1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimpdockwindow.c
5  * Copyright (C) 2001-2005 Michael Natterer <mitch@gimp.org>
6  * Copyright (C)      2009 Martin Nordholts <martinn@src.gnome.org>
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include "config.h"
23 
24 #include <gegl.h>
25 
26 #include <gtk/gtk.h>
27 
28 #include "libgimpwidgets/gimpwidgets.h"
29 
30 #include "widgets-types.h"
31 
32 #include "dialogs/dialogs.h" /* FIXME, we are in the widget layer */
33 
34 #include "config/gimpguiconfig.h"
35 
36 #include "core/gimp.h"
37 #include "core/gimpcontext.h"
38 #include "core/gimpcontainer.h"
39 #include "core/gimpcontainer.h"
40 #include "core/gimplist.h"
41 #include "core/gimpimage.h"
42 
43 #include "gimpcontainercombobox.h"
44 #include "gimpcontainerview.h"
45 #include "gimpdialogfactory.h"
46 #include "gimpdock.h"
47 #include "gimpdockbook.h"
48 #include "gimpdockcolumns.h"
49 #include "gimpdockcontainer.h"
50 #include "gimpdockwindow.h"
51 #include "gimphelp-ids.h"
52 #include "gimpmenufactory.h"
53 #include "gimpsessioninfo-aux.h"
54 #include "gimpsessioninfo.h"
55 #include "gimpsessionmanaged.h"
56 #include "gimptoolbox.h"
57 #include "gimpuimanager.h"
58 #include "gimpwidgets-utils.h"
59 #include "gimpwindow.h"
60 
61 #include "gimp-intl.h"
62 
63 
64 #define DEFAULT_DOCK_HEIGHT          300
65 #define DEFAULT_MENU_VIEW_SIZE       GTK_ICON_SIZE_SMALL_TOOLBAR
66 #define AUX_INFO_SHOW_IMAGE_MENU     "show-image-menu"
67 #define AUX_INFO_FOLLOW_ACTIVE_IMAGE "follow-active-image"
68 
69 
70 enum
71 {
72   PROP_0,
73   PROP_CONTEXT,
74   PROP_DIALOG_FACTORY,
75   PROP_UI_MANAGER_NAME,
76   PROP_IMAGE_CONTAINER,
77   PROP_DISPLAY_CONTAINER,
78   PROP_ALLOW_DOCKBOOK_ABSENCE
79 };
80 
81 
82 struct _GimpDockWindowPrivate
83 {
84   GimpContext       *context;
85 
86   GimpDialogFactory *dialog_factory;
87 
88   gchar             *ui_manager_name;
89   GimpUIManager     *ui_manager;
90   GQuark             image_flush_handler_id;
91 
92   GimpDockColumns   *dock_columns;
93 
94   gboolean           allow_dockbook_absence;
95 
96   guint              update_title_idle_id;
97 
98   gint               ID;
99 
100   GimpContainer     *image_container;
101   GimpContainer     *display_container;
102 
103   gboolean           show_image_menu;
104   gboolean           auto_follow_active;
105 
106   GtkWidget         *image_combo;
107   GtkWidget         *auto_button;
108 };
109 
110 
111 static void            gimp_dock_window_dock_container_iface_init (GimpDockContainerInterface *iface);
112 static void            gimp_dock_window_session_managed_iface_init(GimpSessionManagedInterface*iface);
113 static void            gimp_dock_window_constructed               (GObject                    *object);
114 static void            gimp_dock_window_dispose                   (GObject                    *object);
115 static void            gimp_dock_window_finalize                  (GObject                    *object);
116 static void            gimp_dock_window_set_property              (GObject                    *object,
117                                                                    guint                       property_id,
118                                                                    const GValue               *value,
119                                                                    GParamSpec                 *pspec);
120 static void            gimp_dock_window_get_property              (GObject                    *object,
121                                                                    guint                       property_id,
122                                                                    GValue                     *value,
123                                                                    GParamSpec                 *pspec);
124 static void            gimp_dock_window_style_set                 (GtkWidget                  *widget,
125                                                                    GtkStyle                   *prev_style);
126 static gboolean        gimp_dock_window_delete_event              (GtkWidget                  *widget,
127                                                                    GdkEventAny                *event);
128 static GList         * gimp_dock_window_get_docks                 (GimpDockContainer          *dock_container);
129 static GimpDialogFactory * gimp_dock_window_get_dialog_factory    (GimpDockContainer          *dock_container);
130 static GimpUIManager * gimp_dock_window_get_ui_manager            (GimpDockContainer          *dock_container);
131 static void            gimp_dock_window_add_dock_from_session     (GimpDockContainer          *dock_container,
132                                                                    GimpDock                   *dock,
133                                                                    GimpSessionInfoDock        *dock_info);
134 static GList         * gimp_dock_window_get_aux_info              (GimpSessionManaged         *session_managed);
135 static void            gimp_dock_window_set_aux_info              (GimpSessionManaged         *session_managed,
136                                                                    GList                      *aux_info);
137 static GimpAlignmentType
138                        gimp_dock_window_get_dock_side             (GimpDockContainer          *dock_container,
139                                                                    GimpDock                   *dock);
140 static gboolean        gimp_dock_window_should_add_to_recent      (GimpDockWindow             *dock_window);
141 static void            gimp_dock_window_display_changed           (GimpDockWindow             *dock_window,
142                                                                    GimpObject                 *display,
143                                                                    GimpContext                *context);
144 static void            gimp_dock_window_image_changed             (GimpDockWindow             *dock_window,
145                                                                    GimpImage                  *image,
146                                                                    GimpContext                *context);
147 static void            gimp_dock_window_image_flush               (GimpImage                  *image,
148                                                                    gboolean                    invalidate_preview,
149                                                                    GimpDockWindow             *dock_window);
150 static void            gimp_dock_window_update_title              (GimpDockWindow             *dock_window);
151 static gboolean        gimp_dock_window_update_title_idle         (GimpDockWindow             *dock_window);
152 static gchar         * gimp_dock_window_get_description           (GimpDockWindow             *dock_window,
153                                                                    gboolean                    complete);
154 static void            gimp_dock_window_dock_removed              (GimpDockWindow             *dock_window,
155                                                                    GimpDock                   *dock,
156                                                                    GimpDockColumns            *dock_columns);
157 static void            gimp_dock_window_factory_display_changed   (GimpContext                *context,
158                                                                    GimpObject                 *display,
159                                                                    GimpDock                   *dock);
160 static void            gimp_dock_window_factory_image_changed     (GimpContext                *context,
161                                                                    GimpImage                  *image,
162                                                                    GimpDock                   *dock);
163 static void            gimp_dock_window_auto_clicked              (GtkWidget                  *widget,
164                                                                    GimpDock                   *dock);
165 
166 
G_DEFINE_TYPE_WITH_CODE(GimpDockWindow,gimp_dock_window,GIMP_TYPE_WINDOW,G_ADD_PRIVATE (GimpDockWindow)G_IMPLEMENT_INTERFACE (GIMP_TYPE_DOCK_CONTAINER,gimp_dock_window_dock_container_iface_init)G_IMPLEMENT_INTERFACE (GIMP_TYPE_SESSION_MANAGED,gimp_dock_window_session_managed_iface_init))167 G_DEFINE_TYPE_WITH_CODE (GimpDockWindow, gimp_dock_window, GIMP_TYPE_WINDOW,
168                          G_ADD_PRIVATE (GimpDockWindow)
169                          G_IMPLEMENT_INTERFACE (GIMP_TYPE_DOCK_CONTAINER,
170                                                 gimp_dock_window_dock_container_iface_init)
171                          G_IMPLEMENT_INTERFACE (GIMP_TYPE_SESSION_MANAGED,
172                                                 gimp_dock_window_session_managed_iface_init))
173 
174 #define parent_class gimp_dock_window_parent_class
175 
176 static void
177 gimp_dock_window_class_init (GimpDockWindowClass *klass)
178 {
179   GObjectClass   *object_class = G_OBJECT_CLASS (klass);
180   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
181 
182   object_class->constructed  = gimp_dock_window_constructed;
183   object_class->dispose      = gimp_dock_window_dispose;
184   object_class->finalize     = gimp_dock_window_finalize;
185   object_class->set_property = gimp_dock_window_set_property;
186   object_class->get_property = gimp_dock_window_get_property;
187 
188   widget_class->style_set    = gimp_dock_window_style_set;
189   widget_class->delete_event = gimp_dock_window_delete_event;
190 
191   g_object_class_install_property (object_class, PROP_CONTEXT,
192                                    g_param_spec_object ("context", NULL, NULL,
193                                                         GIMP_TYPE_CONTEXT,
194                                                         GIMP_PARAM_READWRITE |
195                                                         G_PARAM_CONSTRUCT_ONLY));
196 
197   g_object_class_install_property (object_class, PROP_DIALOG_FACTORY,
198                                    g_param_spec_object ("dialog-factory",
199                                                         NULL, NULL,
200                                                         GIMP_TYPE_DIALOG_FACTORY,
201                                                         GIMP_PARAM_READWRITE |
202                                                         G_PARAM_CONSTRUCT_ONLY));
203 
204   g_object_class_install_property (object_class, PROP_UI_MANAGER_NAME,
205                                    g_param_spec_string ("ui-manager-name",
206                                                         NULL, NULL,
207                                                         NULL,
208                                                         GIMP_PARAM_READWRITE |
209                                                         G_PARAM_CONSTRUCT_ONLY));
210 
211   g_object_class_install_property (object_class, PROP_IMAGE_CONTAINER,
212                                    g_param_spec_object ("image-container",
213                                                         NULL, NULL,
214                                                         GIMP_TYPE_CONTAINER,
215                                                         GIMP_PARAM_READWRITE |
216                                                         G_PARAM_CONSTRUCT_ONLY));
217 
218   g_object_class_install_property (object_class, PROP_DISPLAY_CONTAINER,
219                                    g_param_spec_object ("display-container",
220                                                         NULL, NULL,
221                                                         GIMP_TYPE_CONTAINER,
222                                                         GIMP_PARAM_READWRITE |
223                                                         G_PARAM_CONSTRUCT_ONLY));
224 
225   g_object_class_install_property (object_class, PROP_ALLOW_DOCKBOOK_ABSENCE,
226                                    g_param_spec_boolean ("allow-dockbook-absence",
227                                                          NULL, NULL,
228                                                          FALSE,
229                                                          GIMP_PARAM_READWRITE |
230                                                          G_PARAM_CONSTRUCT_ONLY));
231 
232 
233   gtk_widget_class_install_style_property (widget_class,
234                                            g_param_spec_int ("default-height",
235                                                              NULL, NULL,
236                                                              -1, G_MAXINT,
237                                                              DEFAULT_DOCK_HEIGHT,
238                                                              GIMP_PARAM_READABLE));
239 
240   gtk_widget_class_install_style_property (widget_class,
241                                            g_param_spec_enum ("menu-preview-size",
242                                                               NULL, NULL,
243                                                               GTK_TYPE_ICON_SIZE,
244                                                               DEFAULT_MENU_VIEW_SIZE,
245                                                               GIMP_PARAM_READABLE));
246 }
247 
248 static void
gimp_dock_window_init(GimpDockWindow * dock_window)249 gimp_dock_window_init (GimpDockWindow *dock_window)
250 {
251   static gint  dock_window_ID = 1;
252   gchar       *name           = NULL;
253 
254   dock_window->p = gimp_dock_window_get_instance_private (dock_window);
255   dock_window->p->ID                 = dock_window_ID++;
256   dock_window->p->auto_follow_active = TRUE;
257 
258   name = g_strdup_printf ("gimp-dock-%d", dock_window->p->ID);
259   gtk_widget_set_name (GTK_WIDGET (dock_window), name);
260   g_free (name);
261 
262   gtk_window_set_resizable (GTK_WINDOW (dock_window), TRUE);
263   gtk_window_set_focus_on_map (GTK_WINDOW (dock_window), FALSE);
264   gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dock_window), FALSE);
265 }
266 
267 static void
gimp_dock_window_dock_container_iface_init(GimpDockContainerInterface * iface)268 gimp_dock_window_dock_container_iface_init (GimpDockContainerInterface *iface)
269 {
270   iface->get_docks          = gimp_dock_window_get_docks;
271   iface->get_dialog_factory = gimp_dock_window_get_dialog_factory;
272   iface->get_ui_manager     = gimp_dock_window_get_ui_manager;
273   iface->add_dock           = gimp_dock_window_add_dock_from_session;
274   iface->get_dock_side      = gimp_dock_window_get_dock_side;
275 }
276 
277 static void
gimp_dock_window_session_managed_iface_init(GimpSessionManagedInterface * iface)278 gimp_dock_window_session_managed_iface_init (GimpSessionManagedInterface *iface)
279 {
280   iface->get_aux_info = gimp_dock_window_get_aux_info;
281   iface->set_aux_info = gimp_dock_window_set_aux_info;
282 }
283 
284 static void
gimp_dock_window_constructed(GObject * object)285 gimp_dock_window_constructed (GObject *object)
286 {
287   GimpDockWindow  *dock_window = GIMP_DOCK_WINDOW (object);
288   GimpGuiConfig   *config;
289   GimpContext     *factory_context;
290   GimpMenuFactory *menu_factory;
291   GtkAccelGroup   *accel_group;
292   Gimp            *gimp;
293   GtkSettings     *settings;
294   gint             menu_view_width  = -1;
295   gint             menu_view_height = -1;
296 
297   G_OBJECT_CLASS (parent_class)->constructed (object);
298 
299   gimp   = GIMP (dock_window->p->context->gimp);
300   config = GIMP_GUI_CONFIG (gimp->config);
301 
302   /* Create a separate context per dock so that docks can be bound to
303    * a specific image and does not necessarily have to follow the
304    * active image in the user context
305    */
306   g_object_unref (dock_window->p->context);
307   dock_window->p->context           = gimp_context_new (gimp, "Dock Context", NULL);
308   dock_window->p->image_container   = gimp->images;
309   dock_window->p->display_container = gimp->displays;
310 
311   factory_context =
312     gimp_dialog_factory_get_context (dock_window->p->dialog_factory);
313 
314   /* Setup hints */
315   gimp_window_set_hint (GTK_WINDOW (dock_window), config->dock_window_hint);
316 
317   menu_factory =
318     gimp_dialog_factory_get_menu_factory (dock_window->p->dialog_factory);
319 
320   /* Make image window related keyboard shortcuts work also when a
321    * dock window is the focused window
322    */
323   dock_window->p->ui_manager =
324     gimp_menu_factory_manager_new (menu_factory,
325                                    dock_window->p->ui_manager_name,
326                                    dock_window,
327                                    config->tearoff_menus);
328   accel_group = gimp_ui_manager_get_accel_group (dock_window->p->ui_manager);
329   gtk_window_add_accel_group (GTK_WINDOW (dock_window), accel_group);
330 
331   g_signal_connect_object (dock_window->p->context, "display-changed",
332                            G_CALLBACK (gimp_dock_window_display_changed),
333                            dock_window,
334                            G_CONNECT_SWAPPED);
335   g_signal_connect_object (dock_window->p->context, "image-changed",
336                            G_CALLBACK (gimp_dock_window_image_changed),
337                            dock_window,
338                            G_CONNECT_SWAPPED);
339 
340   dock_window->p->image_flush_handler_id =
341     gimp_container_add_handler (gimp->images, "flush",
342                                 G_CALLBACK (gimp_dock_window_image_flush),
343                                 dock_window);
344 
345   gimp_context_define_properties (dock_window->p->context,
346                                   GIMP_CONTEXT_PROP_MASK_ALL &
347                                   ~(GIMP_CONTEXT_PROP_MASK_IMAGE |
348                                     GIMP_CONTEXT_PROP_MASK_DISPLAY),
349                                   FALSE);
350   gimp_context_set_parent (dock_window->p->context,
351                            factory_context);
352 
353   /* Setup widget hierarchy */
354   {
355     GtkWidget *vbox = NULL;
356 
357     /* Top-level GtkVBox */
358     vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
359     gtk_container_add (GTK_CONTAINER (dock_window), vbox);
360     gtk_widget_show (vbox);
361 
362     /* Image selection menu */
363     {
364       GtkWidget *hbox = NULL;
365 
366       /* GtkHBox */
367       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
368       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
369       if (dock_window->p->show_image_menu)
370         gtk_widget_show (hbox);
371 
372       /* Image combo */
373       dock_window->p->image_combo = gimp_container_combo_box_new (NULL, NULL, 16, 1);
374       gtk_box_pack_start (GTK_BOX (hbox), dock_window->p->image_combo, TRUE, TRUE, 0);
375       g_signal_connect (dock_window->p->image_combo, "destroy",
376                         G_CALLBACK (gtk_widget_destroyed),
377                         &dock_window->p->image_combo);
378       gimp_help_set_help_data (dock_window->p->image_combo,
379                                NULL, GIMP_HELP_DOCK_IMAGE_MENU);
380       gtk_widget_show (dock_window->p->image_combo);
381 
382       /* Auto button */
383       dock_window->p->auto_button = gtk_toggle_button_new_with_label (_("Auto"));
384       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dock_window->p->auto_button),
385                                     dock_window->p->auto_follow_active);
386       gtk_box_pack_start (GTK_BOX (hbox), dock_window->p->auto_button, FALSE, FALSE, 0);
387       gtk_widget_show (dock_window->p->auto_button);
388 
389       g_signal_connect (dock_window->p->auto_button, "clicked",
390                         G_CALLBACK (gimp_dock_window_auto_clicked),
391                         dock_window);
392 
393       gimp_help_set_help_data (dock_window->p->auto_button,
394                                _("When enabled, the dialog automatically "
395                                  "follows the image you are working on."),
396                                GIMP_HELP_DOCK_AUTO_BUTTON);
397     }
398 
399     /* GimpDockColumns */
400     /* Let the GimpDockColumns mirror the context so that a GimpDock can
401      * get it when inside a dock window. We do the same thing in the
402      * GimpImageWindow so docks can get the GimpContext there as well
403      */
404     dock_window->p->dock_columns =
405       GIMP_DOCK_COLUMNS (gimp_dock_columns_new (dock_window->p->context,
406                                                 dock_window->p->dialog_factory,
407                                                 dock_window->p->ui_manager));
408     gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (dock_window->p->dock_columns),
409                         TRUE, TRUE, 0);
410     gtk_widget_show (GTK_WIDGET (dock_window->p->dock_columns));
411     g_signal_connect_object (dock_window->p->dock_columns, "dock-removed",
412                              G_CALLBACK (gimp_dock_window_dock_removed),
413                              dock_window,
414                              G_CONNECT_SWAPPED);
415 
416     g_signal_connect_object (dock_window->p->dock_columns, "dock-added",
417                              G_CALLBACK (gimp_dock_window_update_title),
418                              dock_window,
419                              G_CONNECT_SWAPPED);
420     g_signal_connect_object (dock_window->p->dock_columns, "dock-removed",
421                              G_CALLBACK (gimp_dock_window_update_title),
422                              dock_window,
423                              G_CONNECT_SWAPPED);
424   }
425 
426   if (dock_window->p->auto_follow_active)
427     {
428       if (gimp_context_get_display (factory_context))
429         gimp_context_copy_property (factory_context,
430                                     dock_window->p->context,
431                                     GIMP_CONTEXT_PROP_DISPLAY);
432       else
433         gimp_context_copy_property (factory_context,
434                                     dock_window->p->context,
435                                     GIMP_CONTEXT_PROP_IMAGE);
436     }
437 
438   g_signal_connect_object (factory_context, "display-changed",
439                            G_CALLBACK (gimp_dock_window_factory_display_changed),
440                            dock_window,
441                            0);
442   g_signal_connect_object (factory_context, "image-changed",
443                            G_CALLBACK (gimp_dock_window_factory_image_changed),
444                            dock_window,
445                            0);
446 
447   settings = gtk_widget_get_settings (GTK_WIDGET (dock_window));
448   gtk_icon_size_lookup_for_settings (settings,
449                                      DEFAULT_MENU_VIEW_SIZE,
450                                      &menu_view_width,
451                                      &menu_view_height);
452 
453   g_object_set (dock_window->p->image_combo,
454                 "container", dock_window->p->image_container,
455                 "context",   dock_window->p->context,
456                 NULL);
457 
458   gimp_help_connect (GTK_WIDGET (dock_window), gimp_standard_help_func,
459                      GIMP_HELP_DOCK, NULL);
460 
461   if (dock_window->p->auto_follow_active)
462     {
463       if (gimp_context_get_display (factory_context))
464         gimp_context_copy_property (factory_context,
465                                     dock_window->p->context,
466                                     GIMP_CONTEXT_PROP_DISPLAY);
467       else
468         gimp_context_copy_property (factory_context,
469                                     dock_window->p->context,
470                                     GIMP_CONTEXT_PROP_IMAGE);
471     }
472 }
473 
474 static void
gimp_dock_window_dispose(GObject * object)475 gimp_dock_window_dispose (GObject *object)
476 {
477   GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (object);
478 
479   if (dock_window->p->update_title_idle_id)
480     {
481       g_source_remove (dock_window->p->update_title_idle_id);
482       dock_window->p->update_title_idle_id = 0;
483     }
484 
485   if (dock_window->p->image_flush_handler_id)
486     {
487       gimp_container_remove_handler (dock_window->p->context->gimp->images,
488                                      dock_window->p->image_flush_handler_id);
489       dock_window->p->image_flush_handler_id = 0;
490     }
491 
492   g_clear_object (&dock_window->p->ui_manager);
493   g_clear_object (&dock_window->p->dialog_factory);
494   g_clear_object (&dock_window->p->context);
495 
496   G_OBJECT_CLASS (parent_class)->dispose (object);
497 }
498 
499 static void
gimp_dock_window_finalize(GObject * object)500 gimp_dock_window_finalize (GObject *object)
501 {
502   GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (object);
503 
504   g_clear_pointer (&dock_window->p->ui_manager_name, g_free);
505 
506   G_OBJECT_CLASS (parent_class)->finalize (object);
507 }
508 
509 static void
gimp_dock_window_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)510 gimp_dock_window_set_property (GObject      *object,
511                                guint         property_id,
512                                const GValue *value,
513                                GParamSpec   *pspec)
514 {
515   GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (object);
516 
517   switch (property_id)
518     {
519     case PROP_CONTEXT:
520       dock_window->p->context = g_value_dup_object (value);
521       break;
522 
523     case PROP_DIALOG_FACTORY:
524       dock_window->p->dialog_factory = g_value_dup_object (value);
525       break;
526 
527     case PROP_UI_MANAGER_NAME:
528       g_free (dock_window->p->ui_manager_name);
529       dock_window->p->ui_manager_name = g_value_dup_string (value);
530       break;
531 
532     case PROP_IMAGE_CONTAINER:
533       dock_window->p->image_container = g_value_dup_object (value);
534       break;
535 
536     case PROP_DISPLAY_CONTAINER:
537       dock_window->p->display_container = g_value_dup_object (value);
538       break;
539 
540     case PROP_ALLOW_DOCKBOOK_ABSENCE:
541       dock_window->p->allow_dockbook_absence = g_value_get_boolean (value);
542       break;
543 
544     default:
545       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
546       break;
547     }
548 }
549 
550 static void
gimp_dock_window_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)551 gimp_dock_window_get_property (GObject    *object,
552                                guint       property_id,
553                                GValue     *value,
554                                GParamSpec *pspec)
555 {
556   GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (object);
557 
558   switch (property_id)
559     {
560     case PROP_CONTEXT:
561       g_value_set_object (value, dock_window->p->context);
562       break;
563 
564     case PROP_DIALOG_FACTORY:
565       g_value_set_object (value, dock_window->p->dialog_factory);
566       break;
567 
568     case PROP_UI_MANAGER_NAME:
569       g_value_set_string (value, dock_window->p->ui_manager_name);
570       break;
571 
572     case PROP_IMAGE_CONTAINER:
573       g_value_set_object (value, dock_window->p->image_container);
574       break;
575 
576     case PROP_DISPLAY_CONTAINER:
577       g_value_set_object (value, dock_window->p->display_container);
578       break;
579 
580     case PROP_ALLOW_DOCKBOOK_ABSENCE:
581       g_value_set_boolean (value, dock_window->p->allow_dockbook_absence);
582       break;
583 
584     default:
585       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
586       break;
587     }
588 }
589 
590 static void
gimp_dock_window_style_set(GtkWidget * widget,GtkStyle * prev_style)591 gimp_dock_window_style_set (GtkWidget *widget,
592                             GtkStyle  *prev_style)
593 {
594   GimpDockWindow *dock_window      = GIMP_DOCK_WINDOW (widget);
595   GtkStyle       *button_style;
596   GtkIconSize     menu_view_size;
597   GtkSettings    *settings;
598   gint            menu_view_width  = 18;
599   gint            menu_view_height = 18;
600   gint            focus_line_width;
601   gint            focus_padding;
602   gint            ythickness;
603 
604   gint default_height = DEFAULT_DOCK_HEIGHT;
605 
606   GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style);
607 
608   gtk_widget_style_get (widget,
609                         "default-height", &default_height,
610                         "menu-preview-size", &menu_view_size,
611                         NULL);
612 
613   gtk_window_set_default_size (GTK_WINDOW (widget), -1, default_height);
614 
615   settings = gtk_widget_get_settings (dock_window->p->image_combo);
616   gtk_icon_size_lookup_for_settings (settings,
617                                      menu_view_size,
618                                      &menu_view_width,
619                                      &menu_view_height);
620 
621   gtk_widget_style_get (dock_window->p->auto_button,
622                         "focus-line-width", &focus_line_width,
623                         "focus-padding",    &focus_padding,
624                         NULL);
625 
626   button_style = gtk_widget_get_style (widget);
627   ythickness = button_style->ythickness;
628 
629   gimp_container_view_set_view_size (GIMP_CONTAINER_VIEW (dock_window->p->image_combo),
630                                      menu_view_height, 1);
631 
632   gtk_widget_set_size_request (dock_window->p->auto_button, -1,
633                                menu_view_height +
634                                2 * (1 /* CHILD_SPACING */ +
635                                     ythickness            +
636                                     focus_padding         +
637                                     focus_line_width));
638 }
639 
640 /**
641  * gimp_dock_window_delete_event:
642  * @widget:
643  * @event:
644  *
645  * Makes sure that when dock windows are closed they are added to the
646  * list of recently closed docks so that they are easy to bring back.
647  **/
648 static gboolean
gimp_dock_window_delete_event(GtkWidget * widget,GdkEventAny * event)649 gimp_dock_window_delete_event (GtkWidget   *widget,
650                                GdkEventAny *event)
651 {
652   GimpDockWindow         *dock_window = GIMP_DOCK_WINDOW (widget);
653   GimpSessionInfo        *info        = NULL;
654   const gchar            *entry_name  = NULL;
655   GimpDialogFactoryEntry *entry       = NULL;
656   gchar                  *name        = NULL;
657 
658   /* Don't add docks with just a single dockable to the list of
659    * recently closed dock since those can be brought back through the
660    * normal Windows->Dockable Dialogs menu
661    */
662   if (! gimp_dock_window_should_add_to_recent (dock_window))
663     return FALSE;
664 
665   info = gimp_session_info_new ();
666 
667   name = gimp_dock_window_get_description (dock_window, TRUE /*complete*/);
668   gimp_object_set_name (GIMP_OBJECT (info), name);
669   g_free (name);
670 
671   gimp_session_info_get_info_with_widget (info, GTK_WIDGET (dock_window));
672 
673   entry_name = (gimp_dock_window_has_toolbox (dock_window) ?
674                 "gimp-toolbox-window" :
675                 "gimp-dock-window");
676   entry = gimp_dialog_factory_find_entry (dock_window->p->dialog_factory,
677                                           entry_name);
678   gimp_session_info_set_factory_entry (info, entry);
679 
680   gimp_container_add (global_recent_docks, GIMP_OBJECT (info));
681   g_object_unref (info);
682 
683   return FALSE;
684 }
685 
686 static GList *
gimp_dock_window_get_docks(GimpDockContainer * dock_container)687 gimp_dock_window_get_docks (GimpDockContainer *dock_container)
688 {
689   GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (dock_container);
690 
691   return g_list_copy (gimp_dock_columns_get_docks (dock_window->p->dock_columns));
692 }
693 
694 static GimpDialogFactory *
gimp_dock_window_get_dialog_factory(GimpDockContainer * dock_container)695 gimp_dock_window_get_dialog_factory (GimpDockContainer *dock_container)
696 {
697   GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (dock_container);
698 
699   return dock_window->p->dialog_factory;
700 }
701 
702 static GimpUIManager *
gimp_dock_window_get_ui_manager(GimpDockContainer * dock_container)703 gimp_dock_window_get_ui_manager (GimpDockContainer *dock_container)
704 {
705   GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (dock_container);
706 
707   return dock_window->p->ui_manager;
708 }
709 
710 static void
gimp_dock_window_add_dock_from_session(GimpDockContainer * dock_container,GimpDock * dock,GimpSessionInfoDock * dock_info)711 gimp_dock_window_add_dock_from_session (GimpDockContainer   *dock_container,
712                                         GimpDock            *dock,
713                                         GimpSessionInfoDock *dock_info)
714 {
715   GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (dock_container);
716 
717   gimp_dock_window_add_dock (dock_window,
718                              dock,
719                              -1 /*index*/);
720 }
721 
722 static GList *
gimp_dock_window_get_aux_info(GimpSessionManaged * session_managed)723 gimp_dock_window_get_aux_info (GimpSessionManaged *session_managed)
724 {
725   GimpDockWindow     *dock_window = GIMP_DOCK_WINDOW (session_managed);
726   GList              *aux_info    = NULL;
727   GimpSessionInfoAux *aux;
728 
729   if (dock_window->p->allow_dockbook_absence)
730     {
731       /* Assume it is the toolbox; it does not have aux info */
732       return NULL;
733     }
734 
735   g_return_val_if_fail (GIMP_IS_DOCK_WINDOW (dock_window), NULL);
736 
737   aux = gimp_session_info_aux_new (AUX_INFO_SHOW_IMAGE_MENU,
738                                    dock_window->p->show_image_menu ?
739                                    "true" : "false");
740   aux_info = g_list_append (aux_info, aux);
741 
742   aux = gimp_session_info_aux_new (AUX_INFO_FOLLOW_ACTIVE_IMAGE,
743                                    dock_window->p->auto_follow_active ?
744                                    "true" : "false");
745   aux_info = g_list_append (aux_info, aux);
746 
747   return aux_info;
748 }
749 
750 static void
gimp_dock_window_set_aux_info(GimpSessionManaged * session_managed,GList * aux_info)751 gimp_dock_window_set_aux_info (GimpSessionManaged *session_managed,
752                                GList              *aux_info)
753 {
754   GimpDockWindow *dock_window;
755   GList          *list;
756   gboolean        menu_shown;
757   gboolean        auto_follow;
758 
759   g_return_if_fail (GIMP_IS_DOCK_WINDOW (session_managed));
760 
761   dock_window = GIMP_DOCK_WINDOW (session_managed);
762   menu_shown  = dock_window->p->show_image_menu;
763   auto_follow = dock_window->p->auto_follow_active;
764 
765   for (list = aux_info; list; list = g_list_next (list))
766     {
767       GimpSessionInfoAux *aux = list->data;
768 
769       if (! strcmp (aux->name, AUX_INFO_SHOW_IMAGE_MENU))
770         {
771           menu_shown = ! g_ascii_strcasecmp (aux->value, "true");
772         }
773       else if (! strcmp (aux->name, AUX_INFO_FOLLOW_ACTIVE_IMAGE))
774         {
775           auto_follow = ! g_ascii_strcasecmp (aux->value, "true");
776         }
777     }
778 
779   if (menu_shown != dock_window->p->show_image_menu)
780     gimp_dock_window_set_show_image_menu (dock_window, menu_shown);
781 
782   if (auto_follow != dock_window->p->auto_follow_active)
783     gimp_dock_window_set_auto_follow_active (dock_window, auto_follow);
784 }
785 
786 static GimpAlignmentType
gimp_dock_window_get_dock_side(GimpDockContainer * dock_container,GimpDock * dock)787 gimp_dock_window_get_dock_side (GimpDockContainer *dock_container,
788                                 GimpDock          *dock)
789 {
790   g_return_val_if_fail (GIMP_IS_DOCK_WINDOW (dock_container), -1);
791   g_return_val_if_fail (GIMP_IS_DOCK (dock), -1);
792 
793   /* A GimpDockWindow don't have docks on different sides, it's just
794    * one set of columns
795    */
796   return -1;
797 }
798 
799 /**
800  * gimp_dock_window_should_add_to_recent:
801  * @dock_window:
802  *
803  * Returns: %FALSE if the dock window can be recreated with one
804  *          Windows menu item such as Windows->Toolbox or
805  *          Windows->Dockable Dialogs->Layers, %TRUE if not. It should
806  *          then be added to the list of recently closed docks.
807  **/
808 static gboolean
gimp_dock_window_should_add_to_recent(GimpDockWindow * dock_window)809 gimp_dock_window_should_add_to_recent (GimpDockWindow *dock_window)
810 {
811   GList    *docks;
812   gboolean  should_add = TRUE;
813 
814   docks = gimp_dock_container_get_docks (GIMP_DOCK_CONTAINER (dock_window));
815 
816   if (! docks)
817     {
818       should_add = FALSE;
819     }
820   else if (g_list_length (docks) == 1)
821     {
822       GimpDock *dock = GIMP_DOCK (g_list_nth_data (docks, 0));
823 
824       if (GIMP_IS_TOOLBOX (dock) &&
825           gimp_dock_get_n_dockables (dock) == 0)
826         {
827           should_add = FALSE;
828         }
829       else if (! GIMP_IS_TOOLBOX (dock) &&
830                gimp_dock_get_n_dockables (dock) == 1)
831         {
832           should_add = FALSE;
833         }
834     }
835 
836   g_list_free (docks);
837 
838   return should_add;
839 }
840 
841 static void
gimp_dock_window_image_flush(GimpImage * image,gboolean invalidate_preview,GimpDockWindow * dock_window)842 gimp_dock_window_image_flush (GimpImage      *image,
843                               gboolean        invalidate_preview,
844                               GimpDockWindow *dock_window)
845 {
846   if (image == gimp_context_get_image (dock_window->p->context))
847     {
848       GimpObject *display = gimp_context_get_display (dock_window->p->context);
849 
850       if (display)
851         gimp_ui_manager_update (dock_window->p->ui_manager, display);
852     }
853 }
854 
855 static void
gimp_dock_window_update_title(GimpDockWindow * dock_window)856 gimp_dock_window_update_title (GimpDockWindow *dock_window)
857 {
858   if (dock_window->p->update_title_idle_id)
859     g_source_remove (dock_window->p->update_title_idle_id);
860 
861   dock_window->p->update_title_idle_id =
862     g_idle_add ((GSourceFunc) gimp_dock_window_update_title_idle,
863                 dock_window);
864 }
865 
866 static gboolean
gimp_dock_window_update_title_idle(GimpDockWindow * dock_window)867 gimp_dock_window_update_title_idle (GimpDockWindow *dock_window)
868 {
869   gchar *desc = gimp_dock_window_get_description (dock_window,
870                                                   FALSE /*complete*/);
871   if (desc)
872     {
873       gtk_window_set_title (GTK_WINDOW (dock_window), desc);
874       g_free (desc);
875     }
876 
877   dock_window->p->update_title_idle_id = 0;
878 
879   return FALSE;
880 }
881 
882 static gchar *
gimp_dock_window_get_description(GimpDockWindow * dock_window,gboolean complete)883 gimp_dock_window_get_description (GimpDockWindow *dock_window,
884                                   gboolean        complete)
885 {
886   GString *complete_desc = g_string_new (NULL);
887   GList   *docks         = NULL;
888   GList   *iter          = NULL;
889 
890   docks = gimp_dock_container_get_docks (GIMP_DOCK_CONTAINER (dock_window));
891 
892   for (iter = docks;
893        iter;
894        iter = g_list_next (iter))
895     {
896       gchar *desc = gimp_dock_get_description (GIMP_DOCK (iter->data), complete);
897       g_string_append (complete_desc, desc);
898       g_free (desc);
899 
900       if (g_list_next (iter))
901         g_string_append (complete_desc, GIMP_DOCK_COLUMN_SEPARATOR);
902     }
903 
904   g_list_free (docks);
905 
906   return g_string_free (complete_desc, FALSE /*free_segment*/);
907 }
908 
909 static void
gimp_dock_window_dock_removed(GimpDockWindow * dock_window,GimpDock * dock,GimpDockColumns * dock_columns)910 gimp_dock_window_dock_removed (GimpDockWindow  *dock_window,
911                                GimpDock        *dock,
912                                GimpDockColumns *dock_columns)
913 {
914   g_return_if_fail (GIMP_IS_DOCK (dock));
915 
916   if (gimp_dock_columns_get_docks (dock_columns) == NULL &&
917       ! dock_window->p->allow_dockbook_absence)
918     gtk_widget_destroy (GTK_WIDGET (dock_window));
919 }
920 
921 static void
gimp_dock_window_factory_display_changed(GimpContext * context,GimpObject * display,GimpDock * dock)922 gimp_dock_window_factory_display_changed (GimpContext *context,
923                                           GimpObject  *display,
924                                           GimpDock    *dock)
925 {
926   GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (dock);
927 
928   if (display && dock_window->p->auto_follow_active)
929     gimp_context_set_display (dock_window->p->context, display);
930 }
931 
932 static void
gimp_dock_window_factory_image_changed(GimpContext * context,GimpImage * image,GimpDock * dock)933 gimp_dock_window_factory_image_changed (GimpContext *context,
934                                         GimpImage   *image,
935                                         GimpDock    *dock)
936 {
937   GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (dock);
938 
939   /*  won't do anything if we already set the display above  */
940   if (image && dock_window->p->auto_follow_active)
941     gimp_context_set_image (dock_window->p->context, image);
942 }
943 
944 static void
gimp_dock_window_display_changed(GimpDockWindow * dock_window,GimpObject * display,GimpContext * context)945 gimp_dock_window_display_changed (GimpDockWindow *dock_window,
946                                   GimpObject     *display,
947                                   GimpContext    *context)
948 {
949   /*  make sure auto-follow-active works both ways  */
950   if (display && dock_window->p->auto_follow_active)
951     {
952       GimpContext *factory_context =
953         gimp_dialog_factory_get_context (dock_window->p->dialog_factory);
954 
955       gimp_context_set_display (factory_context, display);
956     }
957 
958   gimp_ui_manager_update (dock_window->p->ui_manager,
959                           display);
960 }
961 
962 static void
gimp_dock_window_image_changed(GimpDockWindow * dock_window,GimpImage * image,GimpContext * context)963 gimp_dock_window_image_changed (GimpDockWindow *dock_window,
964                                 GimpImage      *image,
965                                 GimpContext    *context)
966 {
967   GimpContainer *image_container   = dock_window->p->image_container;
968   GimpContainer *display_container = dock_window->p->display_container;
969 
970   /*  make sure auto-follow-active works both ways  */
971   if (image && dock_window->p->auto_follow_active)
972     {
973       GimpContext *factory_context =
974         gimp_dialog_factory_get_context (dock_window->p->dialog_factory);
975 
976       gimp_context_set_image (factory_context, image);
977     }
978 
979   if (image == NULL && ! gimp_container_is_empty (image_container))
980     {
981       image = GIMP_IMAGE (gimp_container_get_first_child (image_container));
982 
983       /*  this invokes this function recursively but we don't enter
984        *  the if() branch the second time
985        */
986       gimp_context_set_image (context, image);
987 
988       /*  stop the emission of the original signal (the emission of
989        *  the recursive signal is finished)
990        */
991       g_signal_stop_emission_by_name (context, "image-changed");
992     }
993   else if (image != NULL && ! gimp_container_is_empty (display_container))
994     {
995       GimpObject *display;
996       GimpImage  *display_image;
997       gboolean    find_display = TRUE;
998 
999       display = gimp_context_get_display (context);
1000 
1001       if (display)
1002         {
1003           g_object_get (display, "image", &display_image, NULL);
1004 
1005           if (display_image)
1006             {
1007               g_object_unref (display_image);
1008 
1009               if (display_image == image)
1010                 find_display = FALSE;
1011             }
1012         }
1013 
1014       if (find_display)
1015         {
1016           GList *list;
1017 
1018           for (list = GIMP_LIST (display_container)->queue->head;
1019                list;
1020                list = g_list_next (list))
1021             {
1022               display = GIMP_OBJECT (list->data);
1023 
1024               g_object_get (display, "image", &display_image, NULL);
1025 
1026               if (display_image)
1027                 {
1028                   g_object_unref (display_image);
1029 
1030                   if (display_image == image)
1031                     {
1032                       /*  this invokes this function recursively but we
1033                        *  don't enter the if(find_display) branch the
1034                        *  second time
1035                        */
1036                       gimp_context_set_display (context, display);
1037 
1038                       /*  don't stop signal emission here because the
1039                        *  context's image was not changed by the
1040                        *  recursive call
1041                        */
1042                       break;
1043                     }
1044                 }
1045             }
1046         }
1047     }
1048 
1049   gimp_ui_manager_update (dock_window->p->ui_manager,
1050                           gimp_context_get_display (context));
1051 }
1052 
1053 static void
gimp_dock_window_auto_clicked(GtkWidget * widget,GimpDock * dock)1054 gimp_dock_window_auto_clicked (GtkWidget *widget,
1055                                GimpDock  *dock)
1056 {
1057   GimpDockWindow *dock_window = GIMP_DOCK_WINDOW (dock);
1058 
1059   gimp_toggle_button_update (widget, &dock_window->p->auto_follow_active);
1060 
1061   if (dock_window->p->auto_follow_active)
1062     {
1063       GimpContext *context;
1064 
1065       context = gimp_dialog_factory_get_context (dock_window->p->dialog_factory);
1066 
1067       gimp_context_copy_properties (context,
1068                                     dock_window->p->context,
1069                                     GIMP_CONTEXT_PROP_MASK_DISPLAY |
1070                                     GIMP_CONTEXT_PROP_MASK_IMAGE);
1071     }
1072 }
1073 
1074 
1075 void
gimp_dock_window_add_dock(GimpDockWindow * dock_window,GimpDock * dock,gint index)1076 gimp_dock_window_add_dock (GimpDockWindow *dock_window,
1077                            GimpDock       *dock,
1078                            gint            index)
1079 {
1080   g_return_if_fail (GIMP_IS_DOCK_WINDOW (dock_window));
1081   g_return_if_fail (GIMP_IS_DOCK (dock));
1082 
1083   gimp_dock_columns_add_dock (dock_window->p->dock_columns,
1084                               GIMP_DOCK (dock),
1085                               index);
1086 
1087   g_signal_connect_object (dock, "description-invalidated",
1088                            G_CALLBACK (gimp_dock_window_update_title),
1089                            dock_window,
1090                            G_CONNECT_SWAPPED);
1091 
1092   /* Some docks like the toolbox dock needs to maintain special hints
1093    * on its container GtkWindow, allow those to do so
1094    */
1095   gimp_dock_set_host_geometry_hints (dock, GTK_WINDOW (dock_window));
1096   g_signal_connect_object (dock, "geometry-invalidated",
1097                            G_CALLBACK (gimp_dock_set_host_geometry_hints),
1098                            dock_window, 0);
1099 }
1100 
1101 void
gimp_dock_window_remove_dock(GimpDockWindow * dock_window,GimpDock * dock)1102 gimp_dock_window_remove_dock (GimpDockWindow *dock_window,
1103                               GimpDock       *dock)
1104 {
1105   gimp_dock_columns_remove_dock (dock_window->p->dock_columns,
1106                                  GIMP_DOCK (dock));
1107 
1108   g_signal_handlers_disconnect_by_func (dock,
1109                                         gimp_dock_window_update_title,
1110                                         dock_window);
1111   g_signal_handlers_disconnect_by_func (dock,
1112                                         gimp_dock_set_host_geometry_hints,
1113                                         dock_window);
1114 }
1115 
1116 GtkWidget *
gimp_dock_window_new(const gchar * role,const gchar * ui_manager_name,gboolean allow_dockbook_absence,GimpDialogFactory * dialog_factory,GimpContext * context)1117 gimp_dock_window_new (const gchar       *role,
1118                       const gchar       *ui_manager_name,
1119                       gboolean           allow_dockbook_absence,
1120                       GimpDialogFactory *dialog_factory,
1121                       GimpContext       *context)
1122 {
1123   g_return_val_if_fail (GIMP_IS_DIALOG_FACTORY (dialog_factory), NULL);
1124   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
1125 
1126   return g_object_new (GIMP_TYPE_DOCK_WINDOW,
1127                        "role",                   role,
1128                        "ui-manager-name",        ui_manager_name,
1129                        "allow-dockbook-absence", allow_dockbook_absence,
1130                        "dialog-factory",         dialog_factory,
1131                        "context",                context,
1132                        NULL);
1133 }
1134 
1135 gint
gimp_dock_window_get_id(GimpDockWindow * dock_window)1136 gimp_dock_window_get_id (GimpDockWindow *dock_window)
1137 {
1138   g_return_val_if_fail (GIMP_IS_DOCK_WINDOW (dock_window), 0);
1139 
1140   return dock_window->p->ID;
1141 }
1142 
1143 GimpContext *
gimp_dock_window_get_context(GimpDockWindow * dock_window)1144 gimp_dock_window_get_context (GimpDockWindow *dock_window)
1145 {
1146   g_return_val_if_fail (GIMP_IS_DOCK_WINDOW (dock_window), NULL);
1147 
1148   return dock_window->p->context;
1149 }
1150 
1151 gboolean
gimp_dock_window_get_auto_follow_active(GimpDockWindow * dock_window)1152 gimp_dock_window_get_auto_follow_active (GimpDockWindow *dock_window)
1153 {
1154   g_return_val_if_fail (GIMP_IS_DOCK_WINDOW (dock_window), FALSE);
1155 
1156   return dock_window->p->auto_follow_active;
1157 }
1158 
1159 void
gimp_dock_window_set_auto_follow_active(GimpDockWindow * dock_window,gboolean auto_follow_active)1160 gimp_dock_window_set_auto_follow_active (GimpDockWindow *dock_window,
1161                                          gboolean        auto_follow_active)
1162 {
1163   g_return_if_fail (GIMP_IS_DOCK_WINDOW (dock_window));
1164 
1165   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dock_window->p->auto_button),
1166                                 auto_follow_active ? TRUE : FALSE);
1167 }
1168 
1169 gboolean
gimp_dock_window_get_show_image_menu(GimpDockWindow * dock_window)1170 gimp_dock_window_get_show_image_menu (GimpDockWindow *dock_window)
1171 {
1172   g_return_val_if_fail (GIMP_IS_DOCK_WINDOW (dock_window), FALSE);
1173 
1174   return dock_window->p->show_image_menu;
1175 }
1176 
1177 void
gimp_dock_window_set_show_image_menu(GimpDockWindow * dock_window,gboolean show)1178 gimp_dock_window_set_show_image_menu (GimpDockWindow *dock_window,
1179                                       gboolean        show)
1180 {
1181   GtkWidget *parent;
1182 
1183   g_return_if_fail (GIMP_IS_DOCK_WINDOW (dock_window));
1184 
1185   parent = gtk_widget_get_parent (dock_window->p->image_combo);
1186 
1187   gtk_widget_set_visible (parent, show);
1188 
1189   dock_window->p->show_image_menu = show ? TRUE : FALSE;
1190 }
1191 
1192 void
gimp_dock_window_setup(GimpDockWindow * dock_window,GimpDockWindow * template)1193 gimp_dock_window_setup (GimpDockWindow *dock_window,
1194                         GimpDockWindow *template)
1195 {
1196   gimp_dock_window_set_auto_follow_active (GIMP_DOCK_WINDOW (dock_window),
1197                                            template->p->auto_follow_active);
1198   gimp_dock_window_set_show_image_menu (GIMP_DOCK_WINDOW (dock_window),
1199                                         template->p->show_image_menu);
1200 }
1201 
1202 /**
1203  * gimp_dock_window_has_toolbox:
1204  * @dock_window:
1205  *
1206  * Returns: %TRUE if the dock window has a GimpToolbox dock, %FALSE
1207  * otherwise.
1208  **/
1209 gboolean
gimp_dock_window_has_toolbox(GimpDockWindow * dock_window)1210 gimp_dock_window_has_toolbox (GimpDockWindow *dock_window)
1211 {
1212   GList *iter = NULL;
1213 
1214   g_return_val_if_fail (GIMP_IS_DOCK_WINDOW (dock_window), FALSE);
1215 
1216   for (iter = gimp_dock_columns_get_docks (dock_window->p->dock_columns);
1217        iter;
1218        iter = g_list_next (iter))
1219     {
1220       if (GIMP_IS_TOOLBOX (iter->data))
1221         return TRUE;
1222     }
1223 
1224   return FALSE;
1225 }
1226 
1227 
1228 /**
1229  * gimp_dock_window_from_dock:
1230  * @dock:
1231  *
1232  * For convenience.
1233  *
1234  * Returns: If the toplevel widget for the dock is a GimpDockWindow,
1235  * return that. Otherwise return %NULL.
1236  **/
1237 GimpDockWindow *
gimp_dock_window_from_dock(GimpDock * dock)1238 gimp_dock_window_from_dock (GimpDock *dock)
1239 {
1240   GtkWidget *toplevel = NULL;
1241 
1242   g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
1243 
1244   toplevel = gtk_widget_get_toplevel (GTK_WIDGET (dock));
1245 
1246   if (GIMP_IS_DOCK_WINDOW (toplevel))
1247     return GIMP_DOCK_WINDOW (toplevel);
1248   else
1249     return NULL;
1250 }
1251