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