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