1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimpdockable.c
5 * Copyright (C) 2001-2003 Michael Natterer <mitch@gimp.org>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <string.h>
24
25 #include <gegl.h>
26 #include <gtk/gtk.h>
27
28 #include "libgimpwidgets/gimpwidgets.h"
29
30 #include "widgets-types.h"
31
32 #include "core/gimpcontext.h"
33
34 #include "gimpdialogfactory.h"
35 #include "gimpdnd.h"
36 #include "gimpdock.h"
37 #include "gimpdockable.h"
38 #include "gimpdockbook.h"
39 #include "gimpdocked.h"
40 #include "gimpdockwindow.h"
41 #include "gimphelp-ids.h"
42 #include "gimppanedbox.h"
43 #include "gimpsessioninfo-aux.h"
44 #include "gimpsessionmanaged.h"
45 #include "gimpuimanager.h"
46 #include "gimpwidgets-utils.h"
47
48 #include "gimp-intl.h"
49
50
51 enum
52 {
53 PROP_0,
54 PROP_LOCKED
55 };
56
57
58 struct _GimpDockablePrivate
59 {
60 gchar *name;
61 gchar *blurb;
62 gchar *icon_name;
63 gchar *help_id;
64 GimpTabStyle tab_style;
65 GimpTabStyle actual_tab_style;
66 gboolean locked;
67
68 GimpDockbook *dockbook;
69
70 GimpContext *context;
71
72 GimpPanedBox *drag_handler;
73
74 /* drag icon hotspot */
75 gint drag_x;
76 gint drag_y;
77 };
78
79
80 static void gimp_dockable_session_managed_iface_init
81 (GimpSessionManagedInterface
82 *iface);
83 static void gimp_dockable_dispose (GObject *object);
84 static void gimp_dockable_set_property (GObject *object,
85 guint property_id,
86 const GValue *value,
87 GParamSpec *pspec);
88 static void gimp_dockable_get_property (GObject *object,
89 guint property_id,
90 GValue *value,
91 GParamSpec *pspec);
92
93 static void gimp_dockable_size_request (GtkWidget *widget,
94 GtkRequisition *requisition);
95 static void gimp_dockable_size_allocate (GtkWidget *widget,
96 GtkAllocation *allocation);
97 static void gimp_dockable_drag_leave (GtkWidget *widget,
98 GdkDragContext *context,
99 guint time);
100 static gboolean gimp_dockable_drag_motion (GtkWidget *widget,
101 GdkDragContext *context,
102 gint x,
103 gint y,
104 guint time);
105 static gboolean gimp_dockable_drag_drop (GtkWidget *widget,
106 GdkDragContext *context,
107 gint x,
108 gint y,
109 guint time);
110
111 static void gimp_dockable_style_set (GtkWidget *widget,
112 GtkStyle *prev_style);
113
114 static void gimp_dockable_add (GtkContainer *container,
115 GtkWidget *widget);
116 static GType gimp_dockable_child_type (GtkContainer *container);
117 static GList * gimp_dockable_get_aux_info (GimpSessionManaged
118 *session_managed);
119 static void gimp_dockable_set_aux_info (GimpSessionManaged
120 *session_managed,
121 GList *aux_info);
122
123 static GimpTabStyle
124 gimp_dockable_convert_tab_style (GimpDockable *dockable,
125 GimpTabStyle tab_style);
126
127
128 G_DEFINE_TYPE_WITH_CODE (GimpDockable, gimp_dockable, GTK_TYPE_BIN,
129 G_ADD_PRIVATE (GimpDockable)
130 G_IMPLEMENT_INTERFACE (GIMP_TYPE_SESSION_MANAGED,
131 gimp_dockable_session_managed_iface_init))
132
133 #define parent_class gimp_dockable_parent_class
134
135 static const GtkTargetEntry dialog_target_table[] = { GIMP_TARGET_DIALOG };
136
137
138 static void
gimp_dockable_class_init(GimpDockableClass * klass)139 gimp_dockable_class_init (GimpDockableClass *klass)
140 {
141 GObjectClass *object_class = G_OBJECT_CLASS (klass);
142 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
143 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
144
145 object_class->dispose = gimp_dockable_dispose;
146 object_class->set_property = gimp_dockable_set_property;
147 object_class->get_property = gimp_dockable_get_property;
148
149 widget_class->size_request = gimp_dockable_size_request;
150 widget_class->size_allocate = gimp_dockable_size_allocate;
151 widget_class->style_set = gimp_dockable_style_set;
152 widget_class->drag_leave = gimp_dockable_drag_leave;
153 widget_class->drag_motion = gimp_dockable_drag_motion;
154 widget_class->drag_drop = gimp_dockable_drag_drop;
155
156 container_class->add = gimp_dockable_add;
157 container_class->child_type = gimp_dockable_child_type;
158
159 g_object_class_install_property (object_class, PROP_LOCKED,
160 g_param_spec_boolean ("locked", NULL, NULL,
161 FALSE,
162 GIMP_PARAM_READWRITE));
163
164 gtk_widget_class_install_style_property (widget_class,
165 g_param_spec_int ("content-border",
166 NULL, NULL,
167 0,
168 G_MAXINT,
169 0,
170 GIMP_PARAM_READABLE));
171 }
172
173 static void
gimp_dockable_init(GimpDockable * dockable)174 gimp_dockable_init (GimpDockable *dockable)
175 {
176 dockable->p = gimp_dockable_get_instance_private (dockable);
177 dockable->p->tab_style = GIMP_TAB_STYLE_AUTOMATIC;
178 dockable->p->actual_tab_style = GIMP_TAB_STYLE_UNDEFINED;
179 dockable->p->drag_x = GIMP_DOCKABLE_DRAG_OFFSET;
180 dockable->p->drag_y = GIMP_DOCKABLE_DRAG_OFFSET;
181
182 gtk_drag_dest_set (GTK_WIDGET (dockable),
183 0,
184 dialog_target_table, G_N_ELEMENTS (dialog_target_table),
185 GDK_ACTION_MOVE);
186 }
187
188 static void
gimp_dockable_session_managed_iface_init(GimpSessionManagedInterface * iface)189 gimp_dockable_session_managed_iface_init (GimpSessionManagedInterface *iface)
190 {
191 iface->get_aux_info = gimp_dockable_get_aux_info;
192 iface->set_aux_info = gimp_dockable_set_aux_info;
193 }
194
195 static void
gimp_dockable_dispose(GObject * object)196 gimp_dockable_dispose (GObject *object)
197 {
198 GimpDockable *dockable = GIMP_DOCKABLE (object);
199
200 if (dockable->p->context)
201 gimp_dockable_set_context (dockable, NULL);
202
203 g_clear_pointer (&dockable->p->blurb, g_free);
204 g_clear_pointer (&dockable->p->name, g_free);
205 g_clear_pointer (&dockable->p->icon_name, g_free);
206 g_clear_pointer (&dockable->p->help_id, g_free);
207
208 G_OBJECT_CLASS (parent_class)->dispose (object);
209 }
210
211 static void
gimp_dockable_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)212 gimp_dockable_set_property (GObject *object,
213 guint property_id,
214 const GValue *value,
215 GParamSpec *pspec)
216 {
217 GimpDockable *dockable = GIMP_DOCKABLE (object);
218
219 switch (property_id)
220 {
221 case PROP_LOCKED:
222 gimp_dockable_set_locked (dockable, g_value_get_boolean (value));
223 break;
224 default:
225 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
226 break;
227 }
228 }
229
230 static void
gimp_dockable_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)231 gimp_dockable_get_property (GObject *object,
232 guint property_id,
233 GValue *value,
234 GParamSpec *pspec)
235 {
236 GimpDockable *dockable = GIMP_DOCKABLE (object);
237
238 switch (property_id)
239 {
240 case PROP_LOCKED:
241 g_value_set_boolean (value, dockable->p->locked);
242 break;
243 default:
244 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
245 break;
246 }
247 }
248
249 static void
gimp_dockable_size_request(GtkWidget * widget,GtkRequisition * requisition)250 gimp_dockable_size_request (GtkWidget *widget,
251 GtkRequisition *requisition)
252 {
253 GtkContainer *container = GTK_CONTAINER (widget);
254 GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
255 GtkRequisition child_requisition;
256 gint border_width;
257
258 border_width = gtk_container_get_border_width (container);
259
260 requisition->width = border_width * 2;
261 requisition->height = border_width * 2;
262
263 if (child && gtk_widget_get_visible (child))
264 {
265 gtk_widget_size_request (child, &child_requisition);
266
267 requisition->width += child_requisition.width;
268 requisition->height += child_requisition.height;
269 }
270 }
271
272 static void
gimp_dockable_size_allocate(GtkWidget * widget,GtkAllocation * allocation)273 gimp_dockable_size_allocate (GtkWidget *widget,
274 GtkAllocation *allocation)
275 {
276 GtkContainer *container = GTK_CONTAINER (widget);
277 GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
278
279 GtkRequisition button_requisition = { 0, };
280 GtkAllocation child_allocation;
281 gint border_width;
282
283
284 gtk_widget_set_allocation (widget, allocation);
285
286 border_width = gtk_container_get_border_width (container);
287
288 if (child && gtk_widget_get_visible (child))
289 {
290 child_allocation.x = allocation->x + border_width;
291 child_allocation.y = allocation->y + border_width;
292 child_allocation.width = MAX (allocation->width -
293 border_width * 2,
294 0);
295 child_allocation.height = MAX (allocation->height -
296 border_width * 2 -
297 button_requisition.height,
298 0);
299
300 child_allocation.y += button_requisition.height;
301
302 gtk_widget_size_allocate (child, &child_allocation);
303 }
304 }
305
306 static void
gimp_dockable_drag_leave(GtkWidget * widget,GdkDragContext * context,guint time)307 gimp_dockable_drag_leave (GtkWidget *widget,
308 GdkDragContext *context,
309 guint time)
310 {
311 gimp_highlight_widget (widget, FALSE);
312 }
313
314 static gboolean
gimp_dockable_drag_motion(GtkWidget * widget,GdkDragContext * context,gint x,gint y,guint time)315 gimp_dockable_drag_motion (GtkWidget *widget,
316 GdkDragContext *context,
317 gint x,
318 gint y,
319 guint time)
320 {
321 GimpDockable *dockable = GIMP_DOCKABLE (widget);
322
323 if (gimp_paned_box_will_handle_drag (dockable->p->drag_handler,
324 widget,
325 context,
326 x, y,
327 time))
328 {
329 gdk_drag_status (context, 0, time);
330 gimp_highlight_widget (widget, FALSE);
331
332 return FALSE;
333 }
334
335 gdk_drag_status (context, GDK_ACTION_MOVE, time);
336 gimp_highlight_widget (widget, TRUE);
337
338 /* Return TRUE so drag_leave() is called */
339 return TRUE;
340 }
341
342 static gboolean
gimp_dockable_drag_drop(GtkWidget * widget,GdkDragContext * context,gint x,gint y,guint time)343 gimp_dockable_drag_drop (GtkWidget *widget,
344 GdkDragContext *context,
345 gint x,
346 gint y,
347 guint time)
348 {
349 GimpDockable *dockable = GIMP_DOCKABLE (widget);
350 gboolean dropped;
351
352 if (gimp_paned_box_will_handle_drag (dockable->p->drag_handler,
353 widget,
354 context,
355 x, y,
356 time))
357 {
358 return FALSE;
359 }
360
361 dropped = gimp_dockbook_drop_dockable (GIMP_DOCKABLE (widget)->p->dockbook,
362 gtk_drag_get_source_widget (context));
363
364 gtk_drag_finish (context, dropped, TRUE, time);
365
366 return TRUE;
367 }
368
369 static void
gimp_dockable_style_set(GtkWidget * widget,GtkStyle * prev_style)370 gimp_dockable_style_set (GtkWidget *widget,
371 GtkStyle *prev_style)
372 {
373 gint content_border;
374
375 GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style);
376
377 gtk_widget_style_get (widget,
378 "content-border", &content_border,
379 NULL);
380
381 gtk_container_set_border_width (GTK_CONTAINER (widget), content_border);
382 }
383
384
385 static void
gimp_dockable_add(GtkContainer * container,GtkWidget * widget)386 gimp_dockable_add (GtkContainer *container,
387 GtkWidget *widget)
388 {
389 GimpDockable *dockable;
390
391 g_return_if_fail (gtk_bin_get_child (GTK_BIN (container)) == NULL);
392
393 GTK_CONTAINER_CLASS (parent_class)->add (container, widget);
394
395 /* not all tab styles are supported by all children */
396 dockable = GIMP_DOCKABLE (container);
397 gimp_dockable_set_tab_style (dockable, dockable->p->tab_style);
398 }
399
400 static GType
gimp_dockable_child_type(GtkContainer * container)401 gimp_dockable_child_type (GtkContainer *container)
402 {
403 if (gtk_bin_get_child (GTK_BIN (container)))
404 return G_TYPE_NONE;
405
406 return GIMP_TYPE_DOCKED;
407 }
408
409 static GtkWidget *
gimp_dockable_new_tab_widget_internal(GimpDockable * dockable,GimpContext * context,GimpTabStyle tab_style,GtkIconSize size,gboolean dnd)410 gimp_dockable_new_tab_widget_internal (GimpDockable *dockable,
411 GimpContext *context,
412 GimpTabStyle tab_style,
413 GtkIconSize size,
414 gboolean dnd)
415 {
416 GtkWidget *tab_widget = NULL;
417 GtkWidget *label = NULL;
418 GtkWidget *icon = NULL;
419
420 switch (tab_style)
421 {
422 case GIMP_TAB_STYLE_NAME:
423 case GIMP_TAB_STYLE_ICON_NAME:
424 case GIMP_TAB_STYLE_PREVIEW_NAME:
425 label = gtk_label_new (dockable->p->name);
426 break;
427
428 case GIMP_TAB_STYLE_BLURB:
429 case GIMP_TAB_STYLE_ICON_BLURB:
430 case GIMP_TAB_STYLE_PREVIEW_BLURB:
431 label = gtk_label_new (dockable->p->blurb);
432 break;
433
434 default:
435 break;
436 }
437
438 switch (tab_style)
439 {
440 case GIMP_TAB_STYLE_ICON:
441 case GIMP_TAB_STYLE_ICON_NAME:
442 case GIMP_TAB_STYLE_ICON_BLURB:
443 icon = gimp_dockable_get_icon (dockable, size);
444 break;
445
446 case GIMP_TAB_STYLE_PREVIEW:
447 case GIMP_TAB_STYLE_PREVIEW_NAME:
448 case GIMP_TAB_STYLE_PREVIEW_BLURB:
449 {
450 GtkWidget *child = gtk_bin_get_child (GTK_BIN (dockable));
451
452 if (child)
453 icon = gimp_docked_get_preview (GIMP_DOCKED (child),
454 context, size);
455
456 if (! icon)
457 icon = gimp_dockable_get_icon (dockable, size);
458 }
459 break;
460
461 default:
462 break;
463 }
464
465 if (label && dnd)
466 gimp_label_set_attributes (GTK_LABEL (label),
467 PANGO_ATTR_WEIGHT, PANGO_WEIGHT_SEMIBOLD,
468 -1);
469
470 switch (tab_style)
471 {
472 case GIMP_TAB_STYLE_ICON:
473 case GIMP_TAB_STYLE_PREVIEW:
474 tab_widget = icon;
475 break;
476
477 case GIMP_TAB_STYLE_NAME:
478 case GIMP_TAB_STYLE_BLURB:
479 tab_widget = label;
480 break;
481
482 case GIMP_TAB_STYLE_ICON_NAME:
483 case GIMP_TAB_STYLE_ICON_BLURB:
484 case GIMP_TAB_STYLE_PREVIEW_NAME:
485 case GIMP_TAB_STYLE_PREVIEW_BLURB:
486 tab_widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, dnd ? 6 : 2);
487
488 gtk_box_pack_start (GTK_BOX (tab_widget), icon, FALSE, FALSE, 0);
489 gtk_widget_show (icon);
490
491 gtk_box_pack_start (GTK_BOX (tab_widget), label, FALSE, FALSE, 0);
492 gtk_widget_show (label);
493 break;
494
495 case GIMP_TAB_STYLE_UNDEFINED:
496 case GIMP_TAB_STYLE_AUTOMATIC:
497 g_warning ("Tab style error, unexpected code path taken, fix!");
498 break;
499 }
500
501 return tab_widget;
502 }
503
504 /* public functions */
505
506 GtkWidget *
gimp_dockable_new(const gchar * name,const gchar * blurb,const gchar * icon_name,const gchar * help_id)507 gimp_dockable_new (const gchar *name,
508 const gchar *blurb,
509 const gchar *icon_name,
510 const gchar *help_id)
511 {
512 GimpDockable *dockable;
513
514 g_return_val_if_fail (name != NULL, NULL);
515 g_return_val_if_fail (icon_name != NULL, NULL);
516 g_return_val_if_fail (help_id != NULL, NULL);
517
518 dockable = g_object_new (GIMP_TYPE_DOCKABLE, NULL);
519
520 dockable->p->name = g_strdup (name);
521 dockable->p->icon_name = g_strdup (icon_name);
522 dockable->p->help_id = g_strdup (help_id);
523
524 if (blurb)
525 dockable->p->blurb = g_strdup (blurb);
526 else
527 dockable->p->blurb = g_strdup (dockable->p->name);
528
529 gimp_help_set_help_data (GTK_WIDGET (dockable), NULL, help_id);
530
531 return GTK_WIDGET (dockable);
532 }
533
534 void
gimp_dockable_set_dockbook(GimpDockable * dockable,GimpDockbook * dockbook)535 gimp_dockable_set_dockbook (GimpDockable *dockable,
536 GimpDockbook *dockbook)
537 {
538 g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
539 g_return_if_fail (dockbook == NULL ||
540 GIMP_IS_DOCKBOOK (dockbook));
541
542 dockable->p->dockbook = dockbook;
543 }
544
545 GimpDockbook *
gimp_dockable_get_dockbook(GimpDockable * dockable)546 gimp_dockable_get_dockbook (GimpDockable *dockable)
547 {
548 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
549
550 return dockable->p->dockbook;
551 }
552
553 GimpTabStyle
gimp_dockable_get_tab_style(GimpDockable * dockable)554 gimp_dockable_get_tab_style (GimpDockable *dockable)
555 {
556 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), -1);
557
558 return dockable->p->tab_style;
559 }
560
561 /**
562 * gimp_dockable_get_actual_tab_style:
563 * @dockable:
564 *
565 * Get actual tab style, i.e. never "automatic". This state should
566 * actually be hold on a per-dockbook basis, but at this point that
567 * feels like over-engineering...
568 **/
569 GimpTabStyle
gimp_dockable_get_actual_tab_style(GimpDockable * dockable)570 gimp_dockable_get_actual_tab_style (GimpDockable *dockable)
571 {
572 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), -1);
573
574 return dockable->p->actual_tab_style;
575 }
576
577 const gchar *
gimp_dockable_get_name(GimpDockable * dockable)578 gimp_dockable_get_name (GimpDockable *dockable)
579 {
580 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
581
582 return dockable->p->name;
583 }
584
585 const gchar *
gimp_dockable_get_blurb(GimpDockable * dockable)586 gimp_dockable_get_blurb (GimpDockable *dockable)
587 {
588 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
589
590 return dockable->p->blurb;
591 }
592
593 const gchar *
gimp_dockable_get_help_id(GimpDockable * dockable)594 gimp_dockable_get_help_id (GimpDockable *dockable)
595 {
596 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
597
598 return dockable->p->help_id;
599 }
600
601 const gchar *
gimp_dockable_get_icon_name(GimpDockable * dockable)602 gimp_dockable_get_icon_name (GimpDockable *dockable)
603 {
604 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
605
606 return dockable->p->icon_name;
607 }
608
609 GtkWidget *
gimp_dockable_get_icon(GimpDockable * dockable,GtkIconSize size)610 gimp_dockable_get_icon (GimpDockable *dockable,
611 GtkIconSize size)
612 {
613 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
614
615 return gtk_image_new_from_icon_name (dockable->p->icon_name, size);
616 }
617
618 gboolean
gimp_dockable_get_locked(GimpDockable * dockable)619 gimp_dockable_get_locked (GimpDockable *dockable)
620 {
621 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), FALSE);
622
623 return dockable->p->locked;
624 }
625
626 void
gimp_dockable_set_drag_pos(GimpDockable * dockable,gint drag_x,gint drag_y)627 gimp_dockable_set_drag_pos (GimpDockable *dockable,
628 gint drag_x,
629 gint drag_y)
630 {
631 g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
632
633 dockable->p->drag_x = drag_x;
634 dockable->p->drag_y = drag_y;
635 }
636
637 void
gimp_dockable_get_drag_pos(GimpDockable * dockable,gint * drag_x,gint * drag_y)638 gimp_dockable_get_drag_pos (GimpDockable *dockable,
639 gint *drag_x,
640 gint *drag_y)
641 {
642 g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
643
644 if (drag_x != NULL)
645 *drag_x = dockable->p->drag_x;
646 if (drag_y != NULL)
647 *drag_y = dockable->p->drag_y;
648 }
649
650 GimpPanedBox *
gimp_dockable_get_drag_handler(GimpDockable * dockable)651 gimp_dockable_get_drag_handler (GimpDockable *dockable)
652 {
653 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
654
655 return dockable->p->drag_handler;
656 }
657
658 void
gimp_dockable_set_locked(GimpDockable * dockable,gboolean lock)659 gimp_dockable_set_locked (GimpDockable *dockable,
660 gboolean lock)
661 {
662 g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
663
664 if (dockable->p->locked != lock)
665 {
666 dockable->p->locked = lock ? TRUE : FALSE;
667
668 g_object_notify (G_OBJECT (dockable), "locked");
669 }
670 }
671
672 gboolean
gimp_dockable_is_locked(GimpDockable * dockable)673 gimp_dockable_is_locked (GimpDockable *dockable)
674 {
675 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), FALSE);
676
677 return dockable->p->locked;
678 }
679
680
681 void
gimp_dockable_set_tab_style(GimpDockable * dockable,GimpTabStyle tab_style)682 gimp_dockable_set_tab_style (GimpDockable *dockable,
683 GimpTabStyle tab_style)
684 {
685 g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
686
687 dockable->p->tab_style = gimp_dockable_convert_tab_style (dockable, tab_style);
688
689 if (tab_style == GIMP_TAB_STYLE_AUTOMATIC)
690 gimp_dockable_set_actual_tab_style (dockable, GIMP_TAB_STYLE_UNDEFINED);
691 else
692 gimp_dockable_set_actual_tab_style (dockable, tab_style);
693
694 if (dockable->p->dockbook)
695 gimp_dockbook_update_auto_tab_style (dockable->p->dockbook);
696 }
697
698 /**
699 * gimp_dockable_set_actual_tab_style:
700 * @dockable:
701 * @tab_style:
702 *
703 * Sets actual tab style, meant for those that decides what
704 * "automatic" tab style means.
705 *
706 * Returns: %TRUE if changed, %FALSE otherwise.
707 **/
708 gboolean
gimp_dockable_set_actual_tab_style(GimpDockable * dockable,GimpTabStyle tab_style)709 gimp_dockable_set_actual_tab_style (GimpDockable *dockable,
710 GimpTabStyle tab_style)
711 {
712 GimpTabStyle new_tab_style = gimp_dockable_convert_tab_style (dockable, tab_style);
713 GimpTabStyle old_tab_style = dockable->p->actual_tab_style;
714
715 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), FALSE);
716 g_return_val_if_fail (tab_style != GIMP_TAB_STYLE_AUTOMATIC, FALSE);
717
718 dockable->p->actual_tab_style = new_tab_style;
719
720 return new_tab_style != old_tab_style;
721 }
722
723 GtkWidget *
gimp_dockable_create_tab_widget(GimpDockable * dockable,GimpContext * context,GimpTabStyle tab_style,GtkIconSize size)724 gimp_dockable_create_tab_widget (GimpDockable *dockable,
725 GimpContext *context,
726 GimpTabStyle tab_style,
727 GtkIconSize size)
728 {
729 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
730 g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
731
732 return gimp_dockable_new_tab_widget_internal (dockable, context,
733 tab_style, size, FALSE);
734 }
735
736 GtkWidget *
gimp_dockable_create_drag_widget(GimpDockable * dockable)737 gimp_dockable_create_drag_widget (GimpDockable *dockable)
738 {
739 GtkWidget *frame;
740 GtkWidget *widget;
741
742 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
743
744 frame = gtk_frame_new (NULL);
745 gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
746
747 widget = gimp_dockable_new_tab_widget_internal (dockable,
748 dockable->p->context,
749 GIMP_TAB_STYLE_ICON_BLURB,
750 GTK_ICON_SIZE_DND,
751 TRUE);
752 gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
753 gtk_container_add (GTK_CONTAINER (frame), widget);
754 gtk_widget_show (widget);
755
756 return frame;
757 }
758
759 void
gimp_dockable_set_context(GimpDockable * dockable,GimpContext * context)760 gimp_dockable_set_context (GimpDockable *dockable,
761 GimpContext *context)
762 {
763 g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
764 g_return_if_fail (context == NULL || GIMP_IS_CONTEXT (context));
765
766 if (context != dockable->p->context)
767 {
768 GtkWidget *child = gtk_bin_get_child (GTK_BIN (dockable));
769
770 if (child)
771 gimp_docked_set_context (GIMP_DOCKED (child), context);
772
773 dockable->p->context = context;
774 }
775 }
776
777 GimpUIManager *
gimp_dockable_get_menu(GimpDockable * dockable,const gchar ** ui_path,gpointer * popup_data)778 gimp_dockable_get_menu (GimpDockable *dockable,
779 const gchar **ui_path,
780 gpointer *popup_data)
781 {
782 GtkWidget *child;
783
784 g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
785 g_return_val_if_fail (ui_path != NULL, NULL);
786 g_return_val_if_fail (popup_data != NULL, NULL);
787
788 child = gtk_bin_get_child (GTK_BIN (dockable));
789
790 if (child)
791 return gimp_docked_get_menu (GIMP_DOCKED (child), ui_path, popup_data);
792
793 return NULL;
794 }
795
796 /**
797 * gimp_dockable_set_drag_handler:
798 * @dockable:
799 * @handler:
800 *
801 * Set a drag handler that will be asked if it will handle drag events
802 * before the dockable handles the event itself.
803 **/
804 void
gimp_dockable_set_drag_handler(GimpDockable * dockable,GimpPanedBox * handler)805 gimp_dockable_set_drag_handler (GimpDockable *dockable,
806 GimpPanedBox *handler)
807 {
808 g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
809
810 dockable->p->drag_handler = handler;
811 }
812
813 void
gimp_dockable_detach(GimpDockable * dockable)814 gimp_dockable_detach (GimpDockable *dockable)
815 {
816 GimpDialogFactory *dialog_factory;
817 GimpMenuFactory *menu_factory;
818 GimpDockWindow *src_dock_window;
819 GimpDock *src_dock;
820 GtkWidget *dock;
821 GimpDockWindow *dock_window;
822 GtkWidget *dockbook;
823
824 g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
825 g_return_if_fail (GIMP_IS_DOCKBOOK (dockable->p->dockbook));
826
827 src_dock = gimp_dockbook_get_dock (dockable->p->dockbook);
828 src_dock_window = gimp_dock_window_from_dock (src_dock);
829
830 dialog_factory = gimp_dock_get_dialog_factory (src_dock);
831 menu_factory = gimp_dialog_factory_get_menu_factory (dialog_factory);
832
833 dock = gimp_dock_with_window_new (dialog_factory,
834 gtk_widget_get_screen (GTK_WIDGET (dockable)),
835 gimp_widget_get_monitor (GTK_WIDGET (dockable)),
836 FALSE /*toolbox*/);
837 dock_window = gimp_dock_window_from_dock (GIMP_DOCK (dock));
838 gtk_window_set_position (GTK_WINDOW (dock_window), GTK_WIN_POS_MOUSE);
839 if (src_dock_window)
840 gimp_dock_window_setup (dock_window, src_dock_window);
841
842 dockbook = gimp_dockbook_new (menu_factory);
843
844 gimp_dock_add_book (GIMP_DOCK (dock), GIMP_DOCKBOOK (dockbook), 0);
845
846 g_object_ref (dockable);
847
848 gimp_dockbook_remove (dockable->p->dockbook, dockable);
849 gimp_dockbook_add (GIMP_DOCKBOOK (dockbook), dockable, 0);
850
851 g_object_unref (dockable);
852
853 gtk_widget_show (GTK_WIDGET (dock_window));
854 gtk_widget_show (dock);
855 }
856
857
858 /* private functions */
859
860 static GList *
gimp_dockable_get_aux_info(GimpSessionManaged * session_managed)861 gimp_dockable_get_aux_info (GimpSessionManaged *session_managed)
862 {
863 GimpDockable *dockable;
864 GtkWidget *child;
865
866 g_return_val_if_fail (GIMP_IS_DOCKABLE (session_managed), NULL);
867
868 dockable = GIMP_DOCKABLE (session_managed);
869
870 child = gtk_bin_get_child (GTK_BIN (dockable));
871
872 if (child)
873 return gimp_docked_get_aux_info (GIMP_DOCKED (child));
874
875 return NULL;
876 }
877
878 static void
gimp_dockable_set_aux_info(GimpSessionManaged * session_managed,GList * aux_info)879 gimp_dockable_set_aux_info (GimpSessionManaged *session_managed,
880 GList *aux_info)
881 {
882 GimpDockable *dockable;
883 GtkWidget *child;
884
885 g_return_if_fail (GIMP_IS_DOCKABLE (session_managed));
886
887 dockable = GIMP_DOCKABLE (session_managed);
888
889 child = gtk_bin_get_child (GTK_BIN (dockable));
890
891 if (child)
892 gimp_docked_set_aux_info (GIMP_DOCKED (child), aux_info);
893 }
894
895 static GimpTabStyle
gimp_dockable_convert_tab_style(GimpDockable * dockable,GimpTabStyle tab_style)896 gimp_dockable_convert_tab_style (GimpDockable *dockable,
897 GimpTabStyle tab_style)
898 {
899 GtkWidget *child = gtk_bin_get_child (GTK_BIN (dockable));
900
901 if (child && ! GIMP_DOCKED_GET_INTERFACE (child)->get_preview)
902 tab_style = gimp_preview_tab_style_to_icon (tab_style);
903
904 return tab_style;
905 }
906