1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimpeditor.c
5 * Copyright (C) 2001-2004 Michael Natterer <mitch@gimp.org>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <gegl.h>
24 #include <gtk/gtk.h>
25
26 #include "libgimpwidgets/gimpwidgets.h"
27
28 #include "widgets-types.h"
29
30 #include "config/gimpguiconfig.h"
31
32 #include "core/gimp.h"
33
34 #include "gimpaction.h"
35 #include "gimpactiongroup.h"
36 #include "gimpdocked.h"
37 #include "gimpeditor.h"
38 #include "gimpdnd.h"
39 #include "gimphighlightablebutton.h"
40 #include "gimpmenufactory.h"
41 #include "gimptoggleaction.h"
42 #include "gimpuimanager.h"
43 #include "gimpwidgets-utils.h"
44
45 #include "gimp-intl.h"
46
47
48 #define DEFAULT_CONTENT_SPACING 2
49 #define DEFAULT_BUTTON_SPACING 2
50 #define DEFAULT_BUTTON_ICON_SIZE GTK_ICON_SIZE_MENU
51 #define DEFAULT_BUTTON_RELIEF GTK_RELIEF_NONE
52
53
54 enum
55 {
56 PROP_0,
57 PROP_MENU_FACTORY,
58 PROP_MENU_IDENTIFIER,
59 PROP_UI_PATH,
60 PROP_POPUP_DATA,
61 PROP_SHOW_NAME,
62 PROP_NAME
63 };
64
65
66 struct _GimpEditorPrivate
67 {
68 GimpMenuFactory *menu_factory;
69 gchar *menu_identifier;
70 GimpUIManager *ui_manager;
71 gchar *ui_path;
72 gpointer popup_data;
73
74 gboolean show_button_bar;
75 GtkWidget *name_label;
76 GtkWidget *button_box;
77 };
78
79
80 static void gimp_editor_docked_iface_init (GimpDockedInterface *iface);
81
82 static void gimp_editor_constructed (GObject *object);
83 static void gimp_editor_dispose (GObject *object);
84 static void gimp_editor_set_property (GObject *object,
85 guint property_id,
86 const GValue *value,
87 GParamSpec *pspec);
88 static void gimp_editor_get_property (GObject *object,
89 guint property_id,
90 GValue *value,
91 GParamSpec *pspec);
92
93 static void gimp_editor_style_set (GtkWidget *widget,
94 GtkStyle *prev_style);
95
96 static GimpUIManager * gimp_editor_get_menu (GimpDocked *docked,
97 const gchar **ui_path,
98 gpointer *popup_data);
99 static gboolean gimp_editor_has_button_bar (GimpDocked *docked);
100 static void gimp_editor_set_show_button_bar (GimpDocked *docked,
101 gboolean show);
102 static gboolean gimp_editor_get_show_button_bar (GimpDocked *docked);
103
104 static GtkIconSize gimp_editor_ensure_button_box (GimpEditor *editor,
105 GtkReliefStyle *button_relief);
106
107 static void gimp_editor_get_styling (GimpEditor *editor,
108 GimpGuiConfig *config,
109 gint *content_spacing,
110 GtkIconSize *button_icon_size,
111 gint *button_spacing,
112 GtkReliefStyle *button_relief);
113 static void gimp_editor_config_size_changed (GimpGuiConfig *config,
114 GimpEditor *editor);
115
116
G_DEFINE_TYPE_WITH_CODE(GimpEditor,gimp_editor,GTK_TYPE_BOX,G_ADD_PRIVATE (GimpEditor)G_IMPLEMENT_INTERFACE (GIMP_TYPE_DOCKED,gimp_editor_docked_iface_init))117 G_DEFINE_TYPE_WITH_CODE (GimpEditor, gimp_editor, GTK_TYPE_BOX,
118 G_ADD_PRIVATE (GimpEditor)
119 G_IMPLEMENT_INTERFACE (GIMP_TYPE_DOCKED,
120 gimp_editor_docked_iface_init))
121
122 #define parent_class gimp_editor_parent_class
123
124
125 static void
126 gimp_editor_class_init (GimpEditorClass *klass)
127 {
128 GObjectClass *object_class = G_OBJECT_CLASS (klass);
129 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
130
131 object_class->constructed = gimp_editor_constructed;
132 object_class->dispose = gimp_editor_dispose;
133 object_class->set_property = gimp_editor_set_property;
134 object_class->get_property = gimp_editor_get_property;
135
136 widget_class->style_set = gimp_editor_style_set;
137
138 g_object_class_install_property (object_class, PROP_MENU_FACTORY,
139 g_param_spec_object ("menu-factory",
140 NULL, NULL,
141 GIMP_TYPE_MENU_FACTORY,
142 GIMP_PARAM_READWRITE |
143 G_PARAM_CONSTRUCT_ONLY));
144
145 g_object_class_install_property (object_class, PROP_MENU_IDENTIFIER,
146 g_param_spec_string ("menu-identifier",
147 NULL, NULL,
148 NULL,
149 GIMP_PARAM_READWRITE |
150 G_PARAM_CONSTRUCT_ONLY));
151
152 g_object_class_install_property (object_class, PROP_UI_PATH,
153 g_param_spec_string ("ui-path",
154 NULL, NULL,
155 NULL,
156 GIMP_PARAM_READWRITE |
157 G_PARAM_CONSTRUCT_ONLY));
158
159 g_object_class_install_property (object_class, PROP_POPUP_DATA,
160 g_param_spec_pointer ("popup-data",
161 NULL, NULL,
162 GIMP_PARAM_READWRITE |
163 G_PARAM_CONSTRUCT_ONLY));
164
165 g_object_class_install_property (object_class, PROP_SHOW_NAME,
166 g_param_spec_boolean ("show-name",
167 NULL, NULL,
168 FALSE,
169 GIMP_PARAM_READWRITE));
170
171 g_object_class_install_property (object_class, PROP_NAME,
172 g_param_spec_string ("name",
173 NULL, NULL,
174 NULL,
175 GIMP_PARAM_WRITABLE |
176 G_PARAM_CONSTRUCT));
177
178 gtk_widget_class_install_style_property (widget_class,
179 g_param_spec_int ("content-spacing",
180 NULL, NULL,
181 0,
182 G_MAXINT,
183 DEFAULT_CONTENT_SPACING,
184 GIMP_PARAM_READABLE));
185
186 gtk_widget_class_install_style_property (widget_class,
187 g_param_spec_int ("button-spacing",
188 NULL, NULL,
189 0,
190 G_MAXINT,
191 DEFAULT_BUTTON_SPACING,
192 GIMP_PARAM_READABLE));
193
194 gtk_widget_class_install_style_property (widget_class,
195 g_param_spec_enum ("button-icon-size",
196 NULL, NULL,
197 GTK_TYPE_ICON_SIZE,
198 DEFAULT_BUTTON_ICON_SIZE,
199 GIMP_PARAM_READABLE));
200
201 gtk_widget_class_install_style_property (widget_class,
202 g_param_spec_enum ("button-relief",
203 NULL, NULL,
204 GTK_TYPE_RELIEF_STYLE,
205 DEFAULT_BUTTON_RELIEF,
206 GIMP_PARAM_READABLE));
207 }
208
209 static void
gimp_editor_docked_iface_init(GimpDockedInterface * iface)210 gimp_editor_docked_iface_init (GimpDockedInterface *iface)
211 {
212 iface->get_menu = gimp_editor_get_menu;
213 iface->has_button_bar = gimp_editor_has_button_bar;
214 iface->set_show_button_bar = gimp_editor_set_show_button_bar;
215 iface->get_show_button_bar = gimp_editor_get_show_button_bar;
216 }
217
218 static void
gimp_editor_init(GimpEditor * editor)219 gimp_editor_init (GimpEditor *editor)
220 {
221 gtk_orientable_set_orientation (GTK_ORIENTABLE (editor),
222 GTK_ORIENTATION_VERTICAL);
223
224 editor->priv = gimp_editor_get_instance_private (editor);
225 editor->priv->popup_data = editor;
226 editor->priv->show_button_bar = TRUE;
227
228 editor->priv->name_label = g_object_new (GTK_TYPE_LABEL,
229 "xalign", 0.0,
230 "yalign", 0.5,
231 "ellipsize", PANGO_ELLIPSIZE_END,
232 NULL);
233 gimp_label_set_attributes (GTK_LABEL (editor->priv->name_label),
234 PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
235 -1);
236 gtk_box_pack_start (GTK_BOX (editor), editor->priv->name_label,
237 FALSE, FALSE, 0);
238 }
239
240 static void
gimp_editor_constructed(GObject * object)241 gimp_editor_constructed (GObject *object)
242 {
243 GimpEditor *editor = GIMP_EDITOR (object);
244
245 G_OBJECT_CLASS (parent_class)->constructed (object);
246
247 if (! editor->priv->popup_data)
248 editor->priv->popup_data = editor;
249
250 if (editor->priv->menu_factory && editor->priv->menu_identifier)
251 {
252 editor->priv->ui_manager =
253 gimp_menu_factory_manager_new (editor->priv->menu_factory,
254 editor->priv->menu_identifier,
255 editor->priv->popup_data,
256 FALSE);
257 g_signal_connect (editor->priv->ui_manager->gimp->config,
258 "size-changed",
259 G_CALLBACK (gimp_editor_config_size_changed),
260 editor);
261 }
262 }
263
264 static void
gimp_editor_dispose(GObject * object)265 gimp_editor_dispose (GObject *object)
266 {
267 GimpEditor *editor = GIMP_EDITOR (object);
268
269 g_clear_object (&editor->priv->menu_factory);
270
271 g_clear_pointer (&editor->priv->menu_identifier, g_free);
272
273 if (editor->priv->ui_manager)
274 {
275 g_signal_handlers_disconnect_by_func (editor->priv->ui_manager->gimp->config,
276 G_CALLBACK (gimp_editor_config_size_changed),
277 editor);
278 g_clear_object (&editor->priv->ui_manager);
279 }
280
281 g_clear_pointer (&editor->priv->ui_path, g_free);
282
283 G_OBJECT_CLASS (parent_class)->dispose (object);
284 }
285
286 static void
gimp_editor_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)287 gimp_editor_set_property (GObject *object,
288 guint property_id,
289 const GValue *value,
290 GParamSpec *pspec)
291 {
292 GimpEditor *editor = GIMP_EDITOR (object);
293
294 switch (property_id)
295 {
296 case PROP_MENU_FACTORY:
297 editor->priv->menu_factory = g_value_dup_object (value);
298 break;
299
300 case PROP_MENU_IDENTIFIER:
301 editor->priv->menu_identifier = g_value_dup_string (value);
302 break;
303
304 case PROP_UI_PATH:
305 editor->priv->ui_path = g_value_dup_string (value);
306 break;
307
308 case PROP_POPUP_DATA:
309 editor->priv->popup_data = g_value_get_pointer (value);
310 break;
311
312 case PROP_SHOW_NAME:
313 g_object_set_property (G_OBJECT (editor->priv->name_label),
314 "visible", value);
315 break;
316
317 case PROP_NAME:
318 gimp_editor_set_name (editor, g_value_get_string (value));
319 break;
320
321 default:
322 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
323 break;
324 }
325 }
326
327 static void
gimp_editor_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)328 gimp_editor_get_property (GObject *object,
329 guint property_id,
330 GValue *value,
331 GParamSpec *pspec)
332 {
333 GimpEditor *editor = GIMP_EDITOR (object);
334
335 switch (property_id)
336 {
337 case PROP_MENU_FACTORY:
338 g_value_set_object (value, editor->priv->menu_factory);
339 break;
340
341 case PROP_MENU_IDENTIFIER:
342 g_value_set_string (value, editor->priv->menu_identifier);
343 break;
344
345 case PROP_UI_PATH:
346 g_value_set_string (value, editor->priv->ui_path);
347 break;
348
349 case PROP_POPUP_DATA:
350 g_value_set_pointer (value, editor->priv->popup_data);
351 break;
352
353 case PROP_SHOW_NAME:
354 g_object_get_property (G_OBJECT (editor->priv->name_label),
355 "visible", value);
356 break;
357
358 default:
359 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
360 break;
361 }
362 }
363
364 static void
gimp_editor_style_set(GtkWidget * widget,GtkStyle * prev_style)365 gimp_editor_style_set (GtkWidget *widget,
366 GtkStyle *prev_style)
367 {
368 GimpEditor *editor = GIMP_EDITOR (widget);
369 GimpGuiConfig *config = NULL;
370
371 GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style);
372
373 if (editor->priv->ui_manager)
374 config = GIMP_GUI_CONFIG (editor->priv->ui_manager->gimp->config);
375 gimp_editor_config_size_changed (config, editor);
376 }
377
378 static GimpUIManager *
gimp_editor_get_menu(GimpDocked * docked,const gchar ** ui_path,gpointer * popup_data)379 gimp_editor_get_menu (GimpDocked *docked,
380 const gchar **ui_path,
381 gpointer *popup_data)
382 {
383 GimpEditor *editor = GIMP_EDITOR (docked);
384
385 *ui_path = editor->priv->ui_path;
386 *popup_data = editor->priv->popup_data;
387
388 return editor->priv->ui_manager;
389 }
390
391
392 static gboolean
gimp_editor_has_button_bar(GimpDocked * docked)393 gimp_editor_has_button_bar (GimpDocked *docked)
394 {
395 GimpEditor *editor = GIMP_EDITOR (docked);
396
397 return editor->priv->button_box != NULL;
398 }
399
400 static void
gimp_editor_set_show_button_bar(GimpDocked * docked,gboolean show)401 gimp_editor_set_show_button_bar (GimpDocked *docked,
402 gboolean show)
403 {
404 GimpEditor *editor = GIMP_EDITOR (docked);
405
406 if (show != editor->priv->show_button_bar)
407 {
408 editor->priv->show_button_bar = show;
409
410 if (editor->priv->button_box)
411 gtk_widget_set_visible (editor->priv->button_box, show);
412 }
413 }
414
415 static gboolean
gimp_editor_get_show_button_bar(GimpDocked * docked)416 gimp_editor_get_show_button_bar (GimpDocked *docked)
417 {
418 GimpEditor *editor = GIMP_EDITOR (docked);
419
420 return editor->priv->show_button_bar;
421 }
422
423 GtkWidget *
gimp_editor_new(void)424 gimp_editor_new (void)
425 {
426 return g_object_new (GIMP_TYPE_EDITOR, NULL);
427 }
428
429 void
gimp_editor_create_menu(GimpEditor * editor,GimpMenuFactory * menu_factory,const gchar * menu_identifier,const gchar * ui_path,gpointer popup_data)430 gimp_editor_create_menu (GimpEditor *editor,
431 GimpMenuFactory *menu_factory,
432 const gchar *menu_identifier,
433 const gchar *ui_path,
434 gpointer popup_data)
435 {
436 g_return_if_fail (GIMP_IS_EDITOR (editor));
437 g_return_if_fail (GIMP_IS_MENU_FACTORY (menu_factory));
438 g_return_if_fail (menu_identifier != NULL);
439 g_return_if_fail (ui_path != NULL);
440
441 if (editor->priv->menu_factory)
442 g_object_unref (editor->priv->menu_factory);
443
444 editor->priv->menu_factory = g_object_ref (menu_factory);
445
446 if (editor->priv->ui_manager)
447 {
448 g_signal_handlers_disconnect_by_func (editor->priv->ui_manager->gimp->config,
449 G_CALLBACK (gimp_editor_config_size_changed),
450 editor);
451 g_object_unref (editor->priv->ui_manager);
452 }
453
454 editor->priv->ui_manager = gimp_menu_factory_manager_new (menu_factory,
455 menu_identifier,
456 popup_data,
457 FALSE);
458 g_signal_connect (editor->priv->ui_manager->gimp->config,
459 "size-changed",
460 G_CALLBACK (gimp_editor_config_size_changed),
461 editor);
462
463 if (editor->priv->ui_path)
464 g_free (editor->priv->ui_path);
465
466 editor->priv->ui_path = g_strdup (ui_path);
467
468 editor->priv->popup_data = popup_data;
469 }
470
471 gboolean
gimp_editor_popup_menu(GimpEditor * editor,GimpMenuPositionFunc position_func,gpointer position_data)472 gimp_editor_popup_menu (GimpEditor *editor,
473 GimpMenuPositionFunc position_func,
474 gpointer position_data)
475 {
476 g_return_val_if_fail (GIMP_IS_EDITOR (editor), FALSE);
477
478 if (editor->priv->ui_manager && editor->priv->ui_path)
479 {
480 gimp_ui_manager_update (editor->priv->ui_manager, editor->priv->popup_data);
481 gimp_ui_manager_ui_popup (editor->priv->ui_manager, editor->priv->ui_path,
482 GTK_WIDGET (editor),
483 position_func, position_data,
484 NULL, NULL);
485 return TRUE;
486 }
487
488 return FALSE;
489 }
490
491 GtkWidget *
gimp_editor_add_button(GimpEditor * editor,const gchar * icon_name,const gchar * tooltip,const gchar * help_id,GCallback callback,GCallback extended_callback,gpointer callback_data)492 gimp_editor_add_button (GimpEditor *editor,
493 const gchar *icon_name,
494 const gchar *tooltip,
495 const gchar *help_id,
496 GCallback callback,
497 GCallback extended_callback,
498 gpointer callback_data)
499 {
500 GtkWidget *button;
501 GtkWidget *image;
502 GtkIconSize button_icon_size;
503 GtkReliefStyle button_relief;
504
505 g_return_val_if_fail (GIMP_IS_EDITOR (editor), NULL);
506 g_return_val_if_fail (icon_name != NULL, NULL);
507
508 button_icon_size = gimp_editor_ensure_button_box (editor, &button_relief);
509
510 button = gimp_highlightable_button_new ();
511 gtk_button_set_relief (GTK_BUTTON (button), button_relief);
512 gtk_box_pack_start (GTK_BOX (editor->priv->button_box), button, TRUE, TRUE, 0);
513 gtk_widget_show (button);
514
515 if (tooltip || help_id)
516 gimp_help_set_help_data (button, tooltip, help_id);
517
518 if (callback)
519 g_signal_connect (button, "clicked",
520 callback,
521 callback_data);
522
523 if (extended_callback)
524 g_signal_connect (button, "extended-clicked",
525 extended_callback,
526 callback_data);
527
528 image = gtk_image_new_from_icon_name (icon_name, button_icon_size);
529 gtk_container_add (GTK_CONTAINER (button), image);
530 gtk_widget_show (image);
531
532 return button;
533 }
534
535 GtkWidget *
gimp_editor_add_icon_box(GimpEditor * editor,GType enum_type,const gchar * icon_prefix,GCallback callback,gpointer callback_data)536 gimp_editor_add_icon_box (GimpEditor *editor,
537 GType enum_type,
538 const gchar *icon_prefix,
539 GCallback callback,
540 gpointer callback_data)
541 {
542 GtkWidget *hbox;
543 GtkWidget *first_button;
544 GtkIconSize button_icon_size;
545 GtkReliefStyle button_relief;
546 GList *children;
547 GList *list;
548
549 g_return_val_if_fail (GIMP_IS_EDITOR (editor), NULL);
550 g_return_val_if_fail (g_type_is_a (enum_type, G_TYPE_ENUM), NULL);
551 g_return_val_if_fail (icon_prefix != NULL, NULL);
552
553 button_icon_size = gimp_editor_ensure_button_box (editor, &button_relief);
554
555 hbox = gimp_enum_icon_box_new (enum_type, icon_prefix, button_icon_size,
556 callback, callback_data,
557 &first_button);
558
559 children = gtk_container_get_children (GTK_CONTAINER (hbox));
560
561 for (list = children; list; list = g_list_next (list))
562 {
563 GtkWidget *button = list->data;
564
565 g_object_ref (button);
566
567 gtk_button_set_relief (GTK_BUTTON (button), button_relief);
568
569 gtk_container_remove (GTK_CONTAINER (hbox), button);
570 gtk_box_pack_start (GTK_BOX (editor->priv->button_box), button,
571 TRUE, TRUE, 0);
572
573 g_object_unref (button);
574 }
575
576 g_list_free (children);
577
578 g_object_ref_sink (hbox);
579 g_object_unref (hbox);
580
581 return first_button;
582 }
583
584
585 typedef struct
586 {
587 GdkModifierType mod_mask;
588 GimpAction *action;
589 } ExtendedAction;
590
591 static void
gimp_editor_button_extended_actions_free(GList * actions)592 gimp_editor_button_extended_actions_free (GList *actions)
593 {
594 GList *list;
595
596 for (list = actions; list; list = list->next)
597 g_slice_free (ExtendedAction, list->data);
598
599 g_list_free (actions);
600 }
601
602 static void
gimp_editor_button_extended_clicked(GtkWidget * button,GdkModifierType mask,gpointer data)603 gimp_editor_button_extended_clicked (GtkWidget *button,
604 GdkModifierType mask,
605 gpointer data)
606 {
607 GList *extended = g_object_get_data (G_OBJECT (button), "extended-actions");
608 GList *list;
609
610 for (list = extended; list; list = g_list_next (list))
611 {
612 ExtendedAction *ext = list->data;
613
614 if ((ext->mod_mask & mask) == ext->mod_mask &&
615 gimp_action_get_sensitive (ext->action))
616 {
617 gimp_action_activate (ext->action);
618 break;
619 }
620 }
621 }
622
623 GtkWidget *
gimp_editor_add_action_button(GimpEditor * editor,const gchar * group_name,const gchar * action_name,...)624 gimp_editor_add_action_button (GimpEditor *editor,
625 const gchar *group_name,
626 const gchar *action_name,
627 ...)
628 {
629 GimpActionGroup *group;
630 GimpAction *action;
631 GtkWidget *button;
632 GtkWidget *old_child;
633 GtkWidget *image;
634 GtkIconSize button_icon_size;
635 GtkReliefStyle button_relief;
636 const gchar *icon_name;
637 gchar *tooltip;
638 const gchar *help_id;
639 GList *extended = NULL;
640 va_list args;
641
642 g_return_val_if_fail (GIMP_IS_EDITOR (editor), NULL);
643 g_return_val_if_fail (action_name != NULL, NULL);
644 g_return_val_if_fail (editor->priv->ui_manager != NULL, NULL);
645
646 group = gimp_ui_manager_get_action_group (editor->priv->ui_manager,
647 group_name);
648
649 g_return_val_if_fail (group != NULL, NULL);
650
651 action = gimp_action_group_get_action (group, action_name);
652
653 g_return_val_if_fail (action != NULL, NULL);
654
655 button_icon_size = gimp_editor_ensure_button_box (editor, &button_relief);
656
657 if (GIMP_IS_TOGGLE_ACTION (action))
658 button = gtk_toggle_button_new ();
659 else
660 button = gimp_highlightable_button_new ();
661
662 gtk_button_set_relief (GTK_BUTTON (button), button_relief);
663
664 icon_name = gimp_action_get_icon_name (action);
665 tooltip = g_strdup (gimp_action_get_tooltip (action));
666 help_id = g_object_get_qdata (G_OBJECT (action), GIMP_HELP_ID);
667
668 old_child = gtk_bin_get_child (GTK_BIN (button));
669
670 if (old_child)
671 gtk_widget_destroy (old_child);
672
673 image = gtk_image_new_from_icon_name (icon_name, button_icon_size);
674 gtk_container_add (GTK_CONTAINER (button), image);
675 gtk_widget_show (image);
676
677 gtk_activatable_set_related_action ((GtkActivatable *) button,
678 (GtkAction *) action);
679 gtk_box_pack_start (GTK_BOX (editor->priv->button_box), button,
680 TRUE, TRUE, 0);
681 gtk_widget_show (button);
682
683 va_start (args, action_name);
684
685 action_name = va_arg (args, const gchar *);
686
687 while (action_name)
688 {
689 GdkModifierType mod_mask;
690
691 mod_mask = va_arg (args, GdkModifierType);
692
693 action = gimp_action_group_get_action (group, action_name);
694
695 if (action && mod_mask)
696 {
697 ExtendedAction *ext = g_slice_new (ExtendedAction);
698
699 ext->mod_mask = mod_mask;
700 ext->action = action;
701
702 extended = g_list_prepend (extended, ext);
703
704 if (tooltip)
705 {
706 const gchar *ext_tooltip = gimp_action_get_tooltip (action);
707
708 if (ext_tooltip)
709 {
710 gchar *tmp = g_strconcat (tooltip, "\n<b>",
711 gimp_get_mod_string (ext->mod_mask),
712 "</b> ", ext_tooltip, NULL);
713 g_free (tooltip);
714 tooltip = tmp;
715 }
716 }
717 }
718
719 action_name = va_arg (args, const gchar *);
720 }
721
722 va_end (args);
723
724 if (extended)
725 {
726 g_object_set_data_full (G_OBJECT (button), "extended-actions", extended,
727 (GDestroyNotify) gimp_editor_button_extended_actions_free);
728
729 g_signal_connect (button, "extended-clicked",
730 G_CALLBACK (gimp_editor_button_extended_clicked),
731 NULL);
732 }
733
734 if (tooltip || help_id)
735 gimp_help_set_help_data_with_markup (button, tooltip, help_id);
736
737 g_free (tooltip);
738
739 return button;
740 }
741
742 void
gimp_editor_set_show_name(GimpEditor * editor,gboolean show)743 gimp_editor_set_show_name (GimpEditor *editor,
744 gboolean show)
745 {
746 g_return_if_fail (GIMP_IS_EDITOR (editor));
747
748 g_object_set (editor, "show-name", show, NULL);
749 }
750
751 void
gimp_editor_set_name(GimpEditor * editor,const gchar * name)752 gimp_editor_set_name (GimpEditor *editor,
753 const gchar *name)
754 {
755 g_return_if_fail (GIMP_IS_EDITOR (editor));
756
757 gtk_label_set_text (GTK_LABEL (editor->priv->name_label),
758 name ? name : _("(None)"));
759 }
760
761 void
gimp_editor_set_box_style(GimpEditor * editor,GtkBox * box)762 gimp_editor_set_box_style (GimpEditor *editor,
763 GtkBox *box)
764 {
765 GimpGuiConfig *config = NULL;
766 GList *children;
767 GList *list;
768 gint content_spacing;
769 GtkIconSize button_icon_size;
770 gint button_spacing;
771 GtkReliefStyle button_relief;
772
773 g_return_if_fail (GIMP_IS_EDITOR (editor));
774 g_return_if_fail (GTK_IS_BOX (box));
775
776 if (editor->priv->ui_manager)
777 config = GIMP_GUI_CONFIG (editor->priv->ui_manager->gimp->config);
778
779 gimp_editor_get_styling (editor, config,
780 &content_spacing,
781 &button_icon_size,
782 &button_spacing,
783 &button_relief);
784
785 gtk_box_set_spacing (box, button_spacing);
786
787 children = gtk_container_get_children (GTK_CONTAINER (box));
788 for (list = children; list; list = g_list_next (list))
789 {
790 if (GTK_IS_BUTTON (list->data))
791 {
792 GtkWidget *child;
793
794 gtk_button_set_relief (GTK_BUTTON (list->data), button_relief);
795
796 child = gtk_bin_get_child (GTK_BIN (list->data));
797
798 if (GTK_IS_IMAGE (child))
799 {
800 GtkIconSize old_size;
801 const gchar *icon_name;
802
803 gtk_image_get_icon_name (GTK_IMAGE (child), &icon_name, &old_size);
804
805 if (button_icon_size != old_size)
806 gtk_image_set_from_icon_name (GTK_IMAGE (child),
807 icon_name, button_icon_size);
808 }
809 }
810 }
811
812 g_list_free (children);
813 }
814
815 GimpUIManager *
gimp_editor_get_ui_manager(GimpEditor * editor)816 gimp_editor_get_ui_manager (GimpEditor *editor)
817 {
818 g_return_val_if_fail (GIMP_IS_EDITOR (editor), NULL);
819
820 return editor->priv->ui_manager;
821 }
822
823 GtkBox *
gimp_editor_get_button_box(GimpEditor * editor)824 gimp_editor_get_button_box (GimpEditor *editor)
825 {
826 g_return_val_if_fail (GIMP_IS_EDITOR (editor), NULL);
827
828 return GTK_BOX (editor->priv->button_box);
829 }
830
831 GimpMenuFactory *
832
gimp_editor_get_menu_factory(GimpEditor * editor)833 gimp_editor_get_menu_factory (GimpEditor *editor)
834 {
835 g_return_val_if_fail (GIMP_IS_EDITOR (editor), NULL);
836
837 return editor->priv->menu_factory;
838 }
839
840 gpointer *
gimp_editor_get_popup_data(GimpEditor * editor)841 gimp_editor_get_popup_data (GimpEditor *editor)
842 {
843 g_return_val_if_fail (GIMP_IS_EDITOR (editor), NULL);
844
845 return editor->priv->popup_data;
846 }
847
848 gchar *
gimp_editor_get_ui_path(GimpEditor * editor)849 gimp_editor_get_ui_path (GimpEditor *editor)
850 {
851 g_return_val_if_fail (GIMP_IS_EDITOR (editor), NULL);
852
853 return editor->priv->ui_path;
854 }
855
856
857 /* private functions */
858
859 static GtkIconSize
gimp_editor_ensure_button_box(GimpEditor * editor,GtkReliefStyle * button_relief)860 gimp_editor_ensure_button_box (GimpEditor *editor,
861 GtkReliefStyle *button_relief)
862 {
863 GimpGuiConfig *config = NULL;
864 GtkIconSize button_icon_size;
865 gint button_spacing;
866 gint content_spacing;
867
868 if (editor->priv->ui_manager)
869 {
870 Gimp *gimp;
871
872 gimp = editor->priv->ui_manager->gimp;
873 config = GIMP_GUI_CONFIG (gimp->config);
874 }
875 gimp_editor_get_styling (editor, config,
876 &content_spacing,
877 &button_icon_size,
878 &button_spacing,
879 button_relief);
880
881 if (! editor->priv->button_box)
882 {
883 editor->priv->button_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL,
884 button_spacing);
885 gtk_box_set_homogeneous (GTK_BOX (editor->priv->button_box), TRUE);
886 gtk_box_pack_end (GTK_BOX (editor), editor->priv->button_box, FALSE, FALSE, 0);
887 gtk_box_reorder_child (GTK_BOX (editor), editor->priv->button_box, 0);
888
889 if (editor->priv->show_button_bar)
890 gtk_widget_show (editor->priv->button_box);
891 }
892
893 return button_icon_size;
894 }
895
896 static void
gimp_editor_get_styling(GimpEditor * editor,GimpGuiConfig * config,gint * content_spacing,GtkIconSize * button_icon_size,gint * button_spacing,GtkReliefStyle * button_relief)897 gimp_editor_get_styling (GimpEditor *editor,
898 GimpGuiConfig *config,
899 gint *content_spacing,
900 GtkIconSize *button_icon_size,
901 gint *button_spacing,
902 GtkReliefStyle *button_relief)
903 {
904 GimpIconSize size;
905
906 /* Get the theme styling. */
907 gtk_widget_style_get (GTK_WIDGET (editor),
908 "content-spacing", content_spacing,
909 "button-icon-size", button_icon_size,
910 "button-spacing", button_spacing,
911 "button-relief", button_relief,
912 NULL);
913
914 /* Check if we should override theme styling. */
915 if (config)
916 {
917 size = gimp_gui_config_detect_icon_size (config);
918 switch (size)
919 {
920 case GIMP_ICON_SIZE_SMALL:
921 *button_spacing = MIN (*button_spacing / 2, 1);
922 *content_spacing = MIN (*content_spacing / 2, 1);
923 case GIMP_ICON_SIZE_MEDIUM:
924 *button_icon_size = GTK_ICON_SIZE_MENU;
925 break;
926 case GIMP_ICON_SIZE_LARGE:
927 *button_icon_size = GTK_ICON_SIZE_LARGE_TOOLBAR;
928 *button_spacing *= 2;
929 *content_spacing *= 2;
930 break;
931 case GIMP_ICON_SIZE_HUGE:
932 *button_icon_size = GTK_ICON_SIZE_DND;
933 *button_spacing *= 3;
934 *content_spacing *= 3;
935 break;
936 default:
937 /* GIMP_ICON_SIZE_DEFAULT:
938 * let's use the sizes set by the theme. */
939 break;
940 }
941 }
942 }
943
944 static void
gimp_editor_config_size_changed(GimpGuiConfig * config,GimpEditor * editor)945 gimp_editor_config_size_changed (GimpGuiConfig *config,
946 GimpEditor *editor)
947 {
948 gint content_spacing;
949 GtkIconSize button_icon_size;
950 gint button_spacing;
951 GtkReliefStyle button_relief;
952
953 gimp_editor_get_styling (editor, config,
954 &content_spacing,
955 &button_icon_size,
956 &button_spacing,
957 &button_relief);
958
959 /* Editor styling. */
960 gtk_box_set_spacing (GTK_BOX (editor), content_spacing);
961
962 /* Button box styling. */
963 if (editor->priv->button_box)
964 gimp_editor_set_box_style (editor,
965 GTK_BOX (editor->priv->button_box));
966 }
967