65 GtkStyleContext *context = gtk_widget_get_style_context(widget);
67 gtk_style_context_get_color(context, GTK_STATE_FLAG_NORMAL, &color);
68 cairo_set_source_rgba(cr, color.red, color.green, color.blue, color.alpha);
69 cairo_set_line_width(cr, 1.2);
72 gtk_widget_get_allocation(widget, &alloc);
73 const double pad = 1.0;
74 const double w =
MAX(0.0, (
double)alloc.width - 2.0 * pad);
75 const double h =
MAX(0.0, (
double)alloc.height - 2.0 * pad);
76 const double size = fmin(w, h);
77 const double x = ((
double)alloc.width -
size) * 0.5;
78 const double y = ((
double)alloc.height -
size) * 0.5;
101 void (*activate_callback)(
GtkWidget *widget, gpointer user_data),
104 GtkWidget *menu_item = gtk_menu_item_new();
106 GtkWidget *icon_widget = gtk_drawing_area_new();
107 GtkWidget *label_widget = gtk_label_new(NULL);
109 gtk_widget_set_size_request(icon_widget, 10, 10);
110 gtk_label_set_markup(GTK_LABEL(label_widget), label);
116 g_signal_connect_data(icon_widget,
"draw", G_CALLBACK(
_menu_icon_draw), data, (GClosureNotify)g_free, 0);
119 gtk_label_set_xalign(GTK_LABEL(label_widget), 0.0f);
120 gtk_box_pack_start(GTK_BOX(box), label_widget,
FALSE,
FALSE, 0);
121 gtk_box_pack_start(GTK_BOX(box), icon_widget,
FALSE,
FALSE, 2);
122 gtk_container_add(GTK_CONTAINER(menu_item), box);
123 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
125 if(activate_callback) g_signal_connect(G_OBJECT(menu_item),
"activate", G_CALLBACK(activate_callback), user_data);
132 void (*activate_callback)(
GtkWidget *widget, gpointer user_data),
135 GtkWidget *menu_item = gtk_menu_item_new();
138 GtkWidget *icon_widget = gtk_drawing_area_new();
139 GtkWidget *label_widget = gtk_label_new(NULL);
140 GtkWidget *shortcut_widget = gtk_label_new(shortcut);
142 gtk_widget_set_size_request(icon_widget, 10, 10);
143 gtk_label_set_markup(GTK_LABEL(label_widget), label);
144 gtk_label_set_xalign(GTK_LABEL(label_widget), 0.0f);
145 gtk_widget_set_halign(label_widget, GTK_ALIGN_START);
146 gtk_widget_set_hexpand(label_widget,
TRUE);
152 g_signal_connect_data(icon_widget,
"draw", G_CALLBACK(
_menu_icon_draw), data, (GClosureNotify)g_free, 0);
155 gtk_label_set_xalign(GTK_LABEL(shortcut_widget), 1.0f);
156 gtk_widget_set_halign(shortcut_widget, GTK_ALIGN_END);
157 gtk_style_context_add_class(gtk_widget_get_style_context(shortcut_widget),
"accelerator");
159 gtk_box_pack_start(GTK_BOX(left_box), label_widget,
TRUE,
TRUE, 0);
160 gtk_box_pack_start(GTK_BOX(left_box), icon_widget,
FALSE,
FALSE, 2);
161 gtk_box_pack_start(GTK_BOX(box), left_box,
TRUE,
TRUE, 0);
162 gtk_box_pack_end(GTK_BOX(box), shortcut_widget,
FALSE,
FALSE, 0);
164 gtk_container_add(GTK_CONTAINER(menu_item), box);
165 gtk_menu_item_set_reserve_indicator(GTK_MENU_ITEM(menu_item),
FALSE);
166 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
168 if(activate_callback) g_signal_connect(G_OBJECT(menu_item),
"activate", G_CALLBACK(activate_callback), user_data);
174 void (*activate_callback)(
GtkWidget *widget, gpointer user_data),
177 GtkWidget *menu_item = gtk_menu_item_new_with_label(
"");
178 GtkWidget *child = gtk_bin_get_child(GTK_BIN(menu_item));
179 gtk_label_set_markup(GTK_LABEL(child), label);
180 gtk_menu_item_set_reserve_indicator(GTK_MENU_ITEM(menu_item),
FALSE);
181 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
183 if(activate_callback) g_signal_connect(G_OBJECT(menu_item),
"activate", G_CALLBACK(activate_callback), user_data);
190 void (*activate_callback)(
GtkWidget *widget, gpointer user_data),
193 GtkWidget *menu_item = gtk_menu_item_new();
195 GtkWidget *label_widget = gtk_label_new(NULL);
196 GtkWidget *shortcut_widget = gtk_label_new(shortcut);
198 gtk_label_set_markup(GTK_LABEL(label_widget), label);
199 gtk_label_set_xalign(GTK_LABEL(label_widget), 0.0f);
200 gtk_widget_set_halign(label_widget, GTK_ALIGN_START);
201 gtk_widget_set_hexpand(label_widget,
TRUE);
203 gtk_label_set_xalign(GTK_LABEL(shortcut_widget), 1.0f);
204 gtk_widget_set_halign(shortcut_widget, GTK_ALIGN_END);
205 gtk_style_context_add_class(gtk_widget_get_style_context(shortcut_widget),
"accelerator");
207 gtk_box_pack_start(GTK_BOX(box), label_widget,
TRUE,
TRUE, 0);
208 gtk_box_pack_end(GTK_BOX(box), shortcut_widget,
FALSE,
FALSE, 0);
209 gtk_container_add(GTK_CONTAINER(menu_item), box);
210 gtk_menu_item_set_reserve_indicator(GTK_MENU_ITEM(menu_item),
FALSE);
211 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
213 if(activate_callback) g_signal_connect(G_OBJECT(menu_item),
"activate", G_CALLBACK(activate_callback), user_data);
220 void (*activate_callback)(
GtkWidget *widget, gpointer user_data),
223 GtkWidget *menu_item = gtk_menu_item_new();
225 GtkWidget *image_widget = icon ? gtk_image_new_from_pixbuf(icon) : gtk_image_new();
226 GtkWidget *label_widget = gtk_label_new(NULL);
228 gtk_label_set_markup(GTK_LABEL(label_widget), label);
229 gtk_label_set_xalign(GTK_LABEL(label_widget), 0.0f);
230 gtk_widget_set_halign(label_widget, GTK_ALIGN_START);
231 gtk_widget_set_hexpand(label_widget,
TRUE);
233 gtk_box_pack_start(GTK_BOX(box), label_widget,
TRUE,
TRUE, 0);
234 gtk_box_pack_end(GTK_BOX(box), image_widget,
FALSE,
FALSE, 0);
235 gtk_container_add(GTK_CONTAINER(menu_item), box);
236 gtk_menu_item_set_reserve_indicator(GTK_MENU_ITEM(menu_item),
FALSE);
237 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
239 if(activate_callback) g_signal_connect(G_OBJECT(menu_item),
"activate", G_CALLBACK(activate_callback), user_data);
246 void (*activate_callback)(
GtkWidget *widget, gpointer user_data),
248 const gboolean checked,
249 const gboolean show_checkbox)
251 GtkWidget *menu_item = gtk_check_menu_item_new();
253 GtkWidget *label_widget = gtk_label_new(NULL);
255 gtk_label_set_markup(GTK_LABEL(label_widget), label);
256 gtk_label_set_xalign(GTK_LABEL(label_widget), 0.0f);
257 gtk_widget_set_halign(label_widget, GTK_ALIGN_START);
258 gtk_widget_set_hexpand(label_widget,
TRUE);
259 gtk_widget_set_hexpand(box,
TRUE);
260 gtk_widget_set_halign(box, GTK_ALIGN_FILL);
262 gtk_box_pack_start(GTK_BOX(box), label_widget,
TRUE,
TRUE, 0);
263 gtk_container_add(GTK_CONTAINER(menu_item), box);
264 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_item), checked);
266 gtk_style_context_add_class(gtk_widget_get_style_context(menu_item),
"dt-masks-inverse-item");
268 gtk_style_context_add_class(gtk_widget_get_style_context(menu_item),
"dt-masks-hide-check");
272 gtk_style_context_add_class(gtk_widget_get_style_context(menu_item),
"dt-masks-checked");
273 gtk_style_context_add_class(gtk_widget_get_style_context(label_widget),
"dt-masks-checked-label");
275 gtk_menu_item_set_reserve_indicator(GTK_MENU_ITEM(menu_item),
FALSE);
276 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
278 if(activate_callback) g_signal_connect(G_OBJECT(menu_item),
"activate", G_CALLBACK(activate_callback), user_data);
285 void (*activate_callback)(
GtkWidget *widget, gpointer user_data),
287 const gboolean checked,
288 const gboolean show_checkbox)
290 GtkWidget *menu_item = gtk_check_menu_item_new();
293 GtkWidget *image_widget = icon ? gtk_image_new_from_pixbuf(icon) : gtk_image_new();
294 GtkWidget *label_widget = gtk_label_new(NULL);
296 gtk_label_set_markup(GTK_LABEL(label_widget), label);
297 gtk_label_set_xalign(GTK_LABEL(label_widget), 0.0f);
298 gtk_widget_set_halign(label_widget, GTK_ALIGN_START);
299 gtk_widget_set_hexpand(label_widget,
TRUE);
300 gtk_widget_set_hexpand(left_box,
TRUE);
301 gtk_widget_set_halign(left_box, GTK_ALIGN_FILL);
302 gtk_widget_set_hexpand(box,
TRUE);
303 gtk_widget_set_halign(box, GTK_ALIGN_FILL);
304 gtk_widget_set_halign(image_widget, GTK_ALIGN_END);
306 gtk_box_pack_start(GTK_BOX(left_box), label_widget,
TRUE,
TRUE, 0);
307 gtk_box_pack_start(GTK_BOX(box), left_box,
TRUE,
TRUE, 0);
308 gtk_box_pack_end(GTK_BOX(box), image_widget,
FALSE,
FALSE, 0);
309 gtk_container_add(GTK_CONTAINER(menu_item), box);
310 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_item), checked);
312 gtk_style_context_add_class(gtk_widget_get_style_context(menu_item),
"dt-masks-inverse-item");
314 gtk_style_context_add_class(gtk_widget_get_style_context(menu_item),
"dt-masks-hide-check");
318 gtk_style_context_add_class(gtk_widget_get_style_context(menu_item),
"dt-masks-checked");
319 gtk_style_context_add_class(gtk_widget_get_style_context(label_widget),
"dt-masks-checked-label");
321 gtk_menu_item_set_reserve_indicator(GTK_MENU_ITEM(menu_item),
FALSE);
322 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
324 if(activate_callback) g_signal_connect(G_OBJECT(menu_item),
"activate", G_CALLBACK(activate_callback), user_data);
334 gboolean (*action_callback)(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data),
335 gboolean (*checked_callback)(
GtkWidget *widget),
336 gboolean (*active_callback)(
GtkWidget *widget),
337 gboolean (*sensitive_callback)(
GtkWidget *widget), guint key_val,
338 GdkModifierType mods, GtkAccelGroup *accel_group)
348 entry->
widget = gtk_check_menu_item_new_with_label(
"");
353 entry->
widget = gtk_menu_item_new_with_label(
"");
359 gtk_label_set_markup(GTK_LABEL(child), label);
363 g_object_set_data(G_OBJECT(entry->
widget),
"custom-data", data);
365 gtk_widget_show_all(GTK_WIDGET(entry->
widget));
367 entry->
menu = menu_index;
384 if(g_strrstr(clean_label,
"/") != NULL)
385 g_strdelimit(clean_label,
"/",
'-');
387 const gchar *parent_path = gtk_menu_get_accel_path(parent);
391 parent_path, clean_label,
392 key_val, mods,
FALSE, _(
"Triggers the action"));
395 gtk_widget_set_accel_path(entry->
widget, path, (!
IS_NULL_PTR(action_callback)) ? accel_group : NULL);
402 gtk_accel_label_set_accel(GTK_ACCEL_LABEL(child), key_val, mods);
409 *items_list = g_list_append(*items_list, entry);
461 gchar *label, GtkAccelGroup *accel_group,
const char *accel_path_prefix)
464 menus[index] = gtk_menu_new();
465 gtk_menu_set_accel_group(GTK_MENU(menus[index]), accel_group);
470 assert(g_strrstr(clean_label,
"/") == NULL);
473 gtk_menu_set_accel_path(GTK_MENU(menus[index]), accel_path);
477 GtkWidget *menu_label = gtk_menu_item_new_with_mnemonic(label);
478 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_label), menus[index]);
479 gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), menu_label);
481 g_signal_connect(G_OBJECT(menu_label),
"activate", G_CALLBACK(
update_menu_entries), lists);
496 gtk_menu_set_accel_group(GTK_MENU(submenu), accel_group);
501 assert(g_strrstr(clean_label,
"/") == NULL);
503 gchar *accel_path =
dt_accels_build_path(gtk_menu_get_accel_path(GTK_MENU(menus[index])), clean_label);
504 gtk_menu_set_accel_path(GTK_MENU(submenu), accel_path);
508 dt_menu_entry_t *entry =
set_menu_entry(menus, lists, label, index, GTK_MENU(menus[index]), NULL, NULL, NULL, NULL, NULL, 0, 0, accel_group);
509 gtk_menu_item_set_submenu(GTK_MENU_ITEM(entry->
widget), submenu);
510 gtk_menu_shell_append(GTK_MENU_SHELL(menus[index]), entry->
widget);
523 gboolean (*action_callback)(GtkAccelGroup *group, GObject *acceleratable,
524 guint keyval, GdkModifierType mods, gpointer user_data),
525 gboolean (*checked_callback)(
GtkWidget *widget),
526 gboolean (*active_callback)(
GtkWidget *widget),
527 gboolean (*sensitive_callback)(
GtkWidget *widget), guint key_val,
528 GdkModifierType mods, GtkAccelGroup *accel_group)
533 action_callback, checked_callback,
534 active_callback, sensitive_callback,
535 key_val, mods, accel_group);
537 gtk_menu_shell_append(GTK_MENU_SHELL(menus[index]), entry->
widget);
538 gtk_menu_item_set_reserve_indicator(GTK_MENU_ITEM(entry->
widget),
TRUE);
543 gboolean (*action_callback)(GtkAccelGroup *group, GObject *acceleratable, guint keyval,
544 GdkModifierType mods, gpointer user_data),
545 gboolean (*checked_callback)(
GtkWidget *widget),
546 gboolean (*active_callback)(
GtkWidget *widget),
547 gboolean (*sensitive_callback)(
GtkWidget *widget), guint key_val, GdkModifierType mods)
555 gboolean (*action_callback)(GtkAccelGroup *group, GObject *acceleratable,
556 guint keyval, GdkModifierType mods, gpointer user_data),
557 gboolean (*checked_callback)(
GtkWidget *widget),
558 gboolean (*active_callback)(
GtkWidget *widget),
559 gboolean (*sensitive_callback)(
GtkWidget *widget), guint key_val,
560 GdkModifierType mods)
563 sensitive_callback, key_val, mods, NULL);
568 gboolean (*action_callback)(GtkAccelGroup *group, GObject *acceleratable,
569 guint keyval, GdkModifierType mods,
571 gboolean (*checked_callback)(
GtkWidget *widget),
572 gboolean (*active_callback)(
GtkWidget *widget),
573 gboolean (*sensitive_callback)(
GtkWidget *widget), guint key_val,
574 GdkModifierType mods, GtkAccelGroup *accel_group)
578 menus, lists, label, index, GTK_MENU(gtk_menu_item_get_submenu(GTK_MENU_ITEM(parent))), data,
579 action_callback, checked_callback, active_callback, sensitive_callback, key_val, mods, accel_group);
581 gtk_menu_shell_append(GTK_MENU_SHELL(gtk_menu_item_get_submenu(GTK_MENU_ITEM(parent))), entry->
widget);
586 gboolean (*action_callback)(GtkAccelGroup *group, GObject *acceleratable, guint keyval,
587 GdkModifierType mods, gpointer user_data),
588 gboolean (*checked_callback)(
GtkWidget *widget),
589 gboolean (*active_callback)(
GtkWidget *widget),
590 gboolean (*sensitive_callback)(
GtkWidget *widget), guint key_val, GdkModifierType mods)
void dt_accels_new_action_shortcut(dt_accels_t *accels, gboolean(*action_callback)(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data), gpointer data, GtkAccelGroup *accel_group, const gchar *action_scope, const gchar *action_name, guint key_val, GdkModifierType accel_mods, const gboolean lock, const char *description)
Register a new shortcut for a generic action, setting up its path, default keys and accel group....
void dt_dev_history_pixelpipe_update(dt_develop_t *dev, gboolean rebuild)
Rebuild or resync pixelpipes after backend history changes.
void dt_dev_history_gui_update(dt_develop_t *dev)
Apply history-loaded params to module GUIs.
gboolean dt_dev_reload_history_items(dt_develop_t *dev, const int32_t imgid)
Reload history from DB and rebuild pipelines/GUI state.