Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
togglebutton.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010-2011 Henrik Andersson.
4 Copyright (C) 2010-2011 johannes hanika.
5 Copyright (C) 2011 Antony Dovgal.
6 Copyright (C) 2011-2012, 2014, 2016, 2018 Tobias Ellinghaus.
7 Copyright (C) 2012 José Carlos García Sogo.
8 Copyright (C) 2012 Richard Wonka.
9 Copyright (C) 2013-2016 Roman Lebedev.
10 Copyright (C) 2018 Matthieu Moy.
11 Copyright (C) 2018, 2020-2021 Pascal Obry.
12 Copyright (C) 2019, 2025 Aurélien PIERRE.
13 Copyright (C) 2019 Ulrich Pegelow.
14 Copyright (C) 2020 Hanno Schwalm.
15 Copyright (C) 2020 Marco.
16 Copyright (C) 2020 Mark-64.
17 Copyright (C) 2020 U-DESKTOP-HQME86J\marco.
18 Copyright (C) 2021 Diederik Ter Rahe.
19 Copyright (C) 2021 Hubert Kowalski.
20 Copyright (C) 2022 Aldric Renaudin.
21 Copyright (C) 2022 Martin Bařinka.
22 Copyright (C) 2022 Nicolas Auffray.
23
24 darktable is free software: you can redistribute it and/or modify
25 it under the terms of the GNU General Public License as published by
26 the Free Software Foundation, either version 3 of the License, or
27 (at your option) any later version.
28
29 darktable is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
33
34 You should have received a copy of the GNU General Public License
35 along with darktable. If not, see <http://www.gnu.org/licenses/>.
36*/
37#include "togglebutton.h"
38#include "bauhaus/bauhaus.h"
39#include "button.h"
40#include "gui/gtk.h"
41#include <string.h>
42
45static gboolean _togglebutton_draw(GtkWidget *widget, cairo_t *cr);
46
48{
49 GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
50
51 widget_class->draw = _togglebutton_draw;
52}
53
55{
56}
57
58static gboolean _togglebutton_draw(GtkWidget *widget, cairo_t *cr)
59{
60 g_return_val_if_fail(!IS_NULL_PTR(widget), FALSE);
61 g_return_val_if_fail(DTGTK_IS_TOGGLEBUTTON(widget), FALSE);
62
63 GtkStateFlags state = gtk_widget_get_state_flags(widget);
64
65 GdkRGBA fg_color;
66 GtkStyleContext *context = gtk_widget_get_style_context(widget);
67 gtk_style_context_get_color(context, state, &fg_color);
68
69 /* fetch flags */
70 int flags = DTGTK_TOGGLEBUTTON(widget)->icon_flags;
71
72 /* update active state paint flag */
73 const gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
74 if(active)
76 else
77 flags &= ~CPF_ACTIVE;
78
79 /* update focus state paint flag */
80 const gboolean hasfocus = gtk_widget_has_focus(widget);
81
82 if(hasfocus)
84 else
85 flags &= ~CPF_FOCUS;
86
87 /* prelight */
88 if(state & GTK_STATE_FLAG_PRELIGHT)
90 else
91 flags &= ~CPF_PRELIGHT;
92
93 /* begin cairo drawing */
94 /* get button total allocation */
95 GtkAllocation allocation;
96 gtk_widget_get_allocation(widget, &allocation);
97 const int width = allocation.width;
98 const int height = allocation.height;
99
100 /* get the css geometry properties of the button */
101 GtkBorder margin, border, padding;
102 gtk_style_context_get_margin(context, state, &margin);
103 gtk_style_context_get_border(context, state, &border);
104 gtk_style_context_get_padding(context, state, &padding);
105
106 /* for button frame and background, we remove css margin from allocation */
107 int startx = margin.left;
108 int starty = margin.top;
109 int cwidth = width - margin.left - margin.right;
110 int cheight = height - margin.top - margin.bottom;
111
112 /* draw standard button background and borders */
113 gtk_render_background(context, cr, startx, starty, cwidth, cheight);
114 gtk_render_frame(context, cr, startx, starty, cwidth, cheight);
115
116 gdk_cairo_set_source_rgba(cr, &fg_color);
117
118 /* draw icon */
119 if(DTGTK_TOGGLEBUTTON(widget)->icon)
120 {
121 /* calculate the button content allocation */
122 startx += border.left + padding.left;
123 starty += border.top + padding.top;
124 cwidth -= border.left + border.right + padding.left + padding.right;
125 cheight -= border.top + border.bottom + padding.top + padding.bottom;
126
127 /* The icon margin is read from our drawing-area child only while GTK still owns it.
128 gtk_button_set_label() can replace the child with a label, which destroys the
129 canvas and leaves our stored pointer stale. In that case, we keep drawing the
130 icon with no extra margin instead of dereferencing an invalid child pointer. */
131 GtkBorder cmargin = { 0 };
132 GtkWidget *canvas = gtk_bin_get_child(GTK_BIN(widget));
133 if(!IS_NULL_PTR(canvas) && canvas == DTGTK_TOGGLEBUTTON(widget)->canvas)
134 {
135 GtkStyleContext *ccontext = gtk_widget_get_style_context(canvas);
136 gtk_style_context_get_margin(ccontext, state, &cmargin);
137 }
138
139 startx += round(cmargin.left * cwidth / 100.0f);
140 starty += round(cmargin.top * cheight / 100.0f);
141 cwidth = round((float)cwidth * (1.0 - (cmargin.left + cmargin.right) / 100.0f));
142 cheight = round((float)cheight * (1.0 - (cmargin.top + cmargin.bottom) / 100.0f));
143
144 void *icon_data = DTGTK_TOGGLEBUTTON(widget)->icon_data;
145
146 if(cwidth > 0 && cheight > 0)
147 DTGTK_TOGGLEBUTTON(widget)->icon(cr, startx, starty, cwidth, cheight, flags, icon_data);
148 }
149
150 return FALSE;
151}
152
153// Public functions
154GtkWidget *dtgtk_togglebutton_new(DTGTKCairoPaintIconFunc paint, gint paintflags, void *paintdata)
155{
157 button = g_object_new(dtgtk_togglebutton_get_type(), NULL);
158 button->icon = paint;
159 button->icon_flags = paintflags;
160 button->icon_data = paintdata;
161 button->canvas = gtk_drawing_area_new();
162 gtk_container_add(GTK_CONTAINER(button), button->canvas);
163 dt_gui_add_class(GTK_WIDGET(button), "dt_module_btn");
164 gtk_widget_set_valign(GTK_WIDGET(button), GTK_ALIGN_CENTER);
165 gtk_widget_set_halign(GTK_WIDGET(button), GTK_ALIGN_CENTER);
166 gtk_widget_set_vexpand(GTK_WIDGET(button), FALSE);
167 gtk_widget_set_hexpand(GTK_WIDGET(button), FALSE);
168 return (GtkWidget *)button;
169}
170
172{
173 static GType dtgtk_togglebutton_type = 0;
174 if(!dtgtk_togglebutton_type)
175 {
176 static const GTypeInfo dtgtk_togglebutton_info = {
177 sizeof(GtkDarktableToggleButtonClass), (GBaseInitFunc)NULL, (GBaseFinalizeFunc)NULL,
178 (GClassInitFunc)_togglebutton_class_init, NULL, /* class_finalize */
179 NULL, /* class_data */
180 sizeof(GtkDarktableToggleButton), 0, /* n_preallocs */
181 (GInstanceInitFunc)_togglebutton_init,
182 };
183 dtgtk_togglebutton_type = g_type_register_static(GTK_TYPE_TOGGLE_BUTTON, "GtkDarktableToggleButton",
184 &dtgtk_togglebutton_info, 0);
185 }
186 return dtgtk_togglebutton_type;
187}
188
189
191 gint paintflags, void *paintdata)
192{
193 g_return_if_fail(!IS_NULL_PTR(button));
194 button->icon = paint;
195 button->icon_flags = paintflags;
196 button->icon_data = paintdata;
197}
198
199// clang-format off
200// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
201// vim: shiftwidth=2 expandtab tabstop=2 cindent
202// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
203// clang-format on
#define FALSE
Definition ashift_lsd.c:158
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281
@ CPF_FOCUS
Definition dtgtk/paint.h:69
@ CPF_PRELIGHT
Definition dtgtk/paint.h:68
@ CPF_ACTIVE
Definition dtgtk/paint.h:67
void(* DTGTKCairoPaintIconFunc)(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
Definition dtgtk/paint.h:75
void dt_gui_add_class(GtkWidget *widget, const gchar *class_name)
Definition gtk.c:133
dt_mipmap_buffer_dsc_flags flags
Definition mipmap_cache.c:4
struct _GtkWidget GtkWidget
Definition splash.h:29
const float uint32_t state[4]
DTGTKCairoPaintIconFunc icon
void dtgtk_togglebutton_set_paint(GtkDarktableToggleButton *button, DTGTKCairoPaintIconFunc paint, gint paintflags, void *paintdata)
static void _togglebutton_init(GtkDarktableToggleButton *slider)
GtkWidget * dtgtk_togglebutton_new(DTGTKCairoPaintIconFunc paint, gint paintflags, void *paintdata)
static void _togglebutton_class_init(GtkDarktableToggleButtonClass *klass)
static gboolean _togglebutton_draw(GtkWidget *widget, cairo_t *cr)
GType dtgtk_togglebutton_get_type()
struct _GtkDarktableToggleButtonClass GtkDarktableToggleButtonClass
struct _GtkDarktableToggleButton GtkDarktableToggleButton
#define DTGTK_TOGGLEBUTTON(obj)
#define DTGTK_IS_TOGGLEBUTTON(obj)