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