1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimpdock.c
5 * Copyright (C) 2001-2005 Michael Natterer <mitch@gimp.org>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <gegl.h>
24 #include <gtk/gtk.h>
25
26 #include "libgimpwidgets/gimpwidgets.h"
27
28 #include "widgets-types.h"
29
30 #include "core/gimp.h"
31 #include "core/gimpcontext.h"
32 #include "core/gimpmarshal.h"
33
34 #include "gimpdialogfactory.h"
35 #include "gimpdock.h"
36 #include "gimpdockable.h"
37 #include "gimpdockbook.h"
38 #include "gimpdockcolumns.h"
39 #include "gimpdockcontainer.h"
40 #include "gimpdockwindow.h"
41 #include "gimppanedbox.h"
42 #include "gimpuimanager.h"
43 #include "gimpwidgets-utils.h"
44
45 #include "gimp-intl.h"
46
47
48 #define DEFAULT_DOCK_FONT_SCALE PANGO_SCALE_SMALL
49
50
51 enum
52 {
53 BOOK_ADDED,
54 BOOK_REMOVED,
55 DESCRIPTION_INVALIDATED,
56 GEOMETRY_INVALIDATED,
57 LAST_SIGNAL
58 };
59
60
61 struct _GimpDockPrivate
62 {
63 GtkWidget *temp_vbox;
64 GtkWidget *main_vbox;
65 GtkWidget *paned_vbox;
66
67 GList *dockbooks;
68
69 gint ID;
70 };
71
72
73 static void gimp_dock_dispose (GObject *object);
74
75 static void gimp_dock_style_set (GtkWidget *widget,
76 GtkStyle *prev_style);
77 static gchar * gimp_dock_real_get_description (GimpDock *dock,
78 gboolean complete);
79 static void gimp_dock_real_book_added (GimpDock *dock,
80 GimpDockbook *dockbook);
81 static void gimp_dock_real_book_removed (GimpDock *dock,
82 GimpDockbook *dockbook);
83 static void gimp_dock_invalidate_description (GimpDock *dock);
84 static gboolean gimp_dock_dropped_cb (GtkWidget *source,
85 gint insert_index,
86 gpointer data);
87
88
89 G_DEFINE_TYPE_WITH_PRIVATE (GimpDock, gimp_dock, GTK_TYPE_BOX)
90
91 #define parent_class gimp_dock_parent_class
92
93 static guint dock_signals[LAST_SIGNAL] = { 0 };
94
95
96 static void
gimp_dock_class_init(GimpDockClass * klass)97 gimp_dock_class_init (GimpDockClass *klass)
98 {
99 GObjectClass *object_class = G_OBJECT_CLASS (klass);
100 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
101
102 dock_signals[BOOK_ADDED] =
103 g_signal_new ("book-added",
104 G_TYPE_FROM_CLASS (klass),
105 G_SIGNAL_RUN_FIRST,
106 G_STRUCT_OFFSET (GimpDockClass, book_added),
107 NULL, NULL,
108 gimp_marshal_VOID__OBJECT,
109 G_TYPE_NONE, 1,
110 GIMP_TYPE_DOCKBOOK);
111
112 dock_signals[BOOK_REMOVED] =
113 g_signal_new ("book-removed",
114 G_TYPE_FROM_CLASS (klass),
115 G_SIGNAL_RUN_FIRST,
116 G_STRUCT_OFFSET (GimpDockClass, book_removed),
117 NULL, NULL,
118 gimp_marshal_VOID__OBJECT,
119 G_TYPE_NONE, 1,
120 GIMP_TYPE_DOCKBOOK);
121
122 dock_signals[DESCRIPTION_INVALIDATED] =
123 g_signal_new ("description-invalidated",
124 G_TYPE_FROM_CLASS (klass),
125 G_SIGNAL_RUN_FIRST,
126 G_STRUCT_OFFSET (GimpDockClass, description_invalidated),
127 NULL, NULL,
128 gimp_marshal_VOID__VOID,
129 G_TYPE_NONE, 0);
130
131 dock_signals[GEOMETRY_INVALIDATED] =
132 g_signal_new ("geometry-invalidated",
133 G_TYPE_FROM_CLASS (klass),
134 G_SIGNAL_RUN_FIRST,
135 G_STRUCT_OFFSET (GimpDockClass, geometry_invalidated),
136 NULL, NULL,
137 gimp_marshal_VOID__VOID,
138 G_TYPE_NONE, 0);
139
140 object_class->dispose = gimp_dock_dispose;
141
142 widget_class->style_set = gimp_dock_style_set;
143
144 klass->get_description = gimp_dock_real_get_description;
145 klass->set_host_geometry_hints = NULL;
146 klass->book_added = gimp_dock_real_book_added;
147 klass->book_removed = gimp_dock_real_book_removed;
148 klass->description_invalidated = NULL;
149 klass->geometry_invalidated = NULL;
150
151 gtk_widget_class_install_style_property (widget_class,
152 g_param_spec_double ("font-scale",
153 NULL, NULL,
154 0.0,
155 G_MAXDOUBLE,
156 DEFAULT_DOCK_FONT_SCALE,
157 GIMP_PARAM_READABLE));
158 }
159
160 static void
gimp_dock_init(GimpDock * dock)161 gimp_dock_init (GimpDock *dock)
162 {
163 static gint dock_ID = 1;
164 gchar *name = NULL;
165
166 gtk_orientable_set_orientation (GTK_ORIENTABLE (dock),
167 GTK_ORIENTATION_VERTICAL);
168
169 dock->p = gimp_dock_get_instance_private (dock);
170 dock->p->ID = dock_ID++;
171
172 name = g_strdup_printf ("gimp-internal-dock-%d", dock->p->ID);
173 gtk_widget_set_name (GTK_WIDGET (dock), name);
174 g_free (name);
175
176 dock->p->temp_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
177 gtk_box_pack_start (GTK_BOX (dock), dock->p->temp_vbox, FALSE, FALSE, 0);
178 /* Never show it */
179
180 dock->p->main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
181 gtk_box_pack_start (GTK_BOX (dock), dock->p->main_vbox, TRUE, TRUE, 0);
182 gtk_widget_show (dock->p->main_vbox);
183
184 dock->p->paned_vbox = gimp_paned_box_new (FALSE, 0, GTK_ORIENTATION_VERTICAL);
185 gimp_paned_box_set_dropped_cb (GIMP_PANED_BOX (dock->p->paned_vbox),
186 gimp_dock_dropped_cb,
187 dock);
188 gtk_box_pack_start (GTK_BOX (dock->p->main_vbox), dock->p->paned_vbox,
189 TRUE, TRUE, 0);
190 gtk_widget_show (dock->p->paned_vbox);
191 }
192
193 static void
gimp_dock_dispose(GObject * object)194 gimp_dock_dispose (GObject *object)
195 {
196 GimpDock *dock = GIMP_DOCK (object);
197
198 while (dock->p->dockbooks)
199 {
200 GimpDockbook *dockbook = dock->p->dockbooks->data;
201
202 g_object_ref (dockbook);
203 gimp_dock_remove_book (dock, dockbook);
204 gtk_widget_destroy (GTK_WIDGET (dockbook));
205 g_object_unref (dockbook);
206 }
207
208 G_OBJECT_CLASS (parent_class)->dispose (object);
209 }
210
211 static void
gimp_dock_style_set(GtkWidget * widget,GtkStyle * prev_style)212 gimp_dock_style_set (GtkWidget *widget,
213 GtkStyle *prev_style)
214 {
215 GimpDock *dock = GIMP_DOCK (widget);
216 gdouble font_scale = 1.0;
217
218 GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style);
219
220 gtk_widget_style_get (widget,
221 "font-scale", &font_scale,
222 NULL);
223
224 if (font_scale != 1.0)
225 {
226 PangoContext *context;
227 PangoFontDescription *font_desc;
228 gint font_size;
229 gchar *font_str;
230 gchar *rc_string;
231
232 context = gtk_widget_get_pango_context (widget);
233 font_desc = pango_context_get_font_description (context);
234 font_desc = pango_font_description_copy (font_desc);
235
236 font_size = pango_font_description_get_size (font_desc);
237 font_size = font_scale * font_size;
238 pango_font_description_set_size (font_desc, font_size);
239
240 font_str = pango_font_description_to_string (font_desc);
241 pango_font_description_free (font_desc);
242
243 rc_string =
244 g_strdup_printf ("style \"gimp-dock-style\""
245 "{"
246 " font_name = \"%s\""
247 "}"
248 "widget \"*.gimp-internal-dock-%d.*\" style \"gimp-dock-style\"",
249 font_str,
250 dock->p->ID);
251 g_free (font_str);
252
253 gtk_rc_parse_string (rc_string);
254 g_free (rc_string);
255
256 gtk_widget_reset_rc_styles (widget);
257 }
258 }
259
260 static gchar *
gimp_dock_real_get_description(GimpDock * dock,gboolean complete)261 gimp_dock_real_get_description (GimpDock *dock,
262 gboolean complete)
263 {
264 GString *desc;
265 GList *list;
266
267 desc = g_string_new (NULL);
268
269 for (list = gimp_dock_get_dockbooks (dock);
270 list;
271 list = g_list_next (list))
272 {
273 GimpDockbook *dockbook = list->data;
274 GList *children;
275 GList *child;
276
277 if (complete)
278 {
279 /* Include all dockables */
280 children = gtk_container_get_children (GTK_CONTAINER (dockbook));
281 }
282 else
283 {
284 GtkWidget *dockable = NULL;
285 gint page_num = 0;
286
287 page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook));
288 dockable = gtk_notebook_get_nth_page (GTK_NOTEBOOK (dockbook), page_num);
289
290 /* Only include active dockables */
291 children = g_list_append (NULL, dockable);
292 }
293
294 for (child = children; child; child = g_list_next (child))
295 {
296 GimpDockable *dockable = child->data;
297
298 g_string_append (desc, gimp_dockable_get_name (dockable));
299
300 if (g_list_next (child))
301 g_string_append (desc, GIMP_DOCK_DOCKABLE_SEPARATOR);
302 }
303
304 g_list_free (children);
305
306 if (g_list_next (list))
307 g_string_append (desc, GIMP_DOCK_BOOK_SEPARATOR);
308 }
309
310 return g_string_free (desc, FALSE);
311 }
312
313 static void
gimp_dock_real_book_added(GimpDock * dock,GimpDockbook * dockbook)314 gimp_dock_real_book_added (GimpDock *dock,
315 GimpDockbook *dockbook)
316 {
317 g_signal_connect_object (dockbook, "switch-page",
318 G_CALLBACK (gimp_dock_invalidate_description),
319 dock, G_CONNECT_SWAPPED);
320 }
321
322 static void
gimp_dock_real_book_removed(GimpDock * dock,GimpDockbook * dockbook)323 gimp_dock_real_book_removed (GimpDock *dock,
324 GimpDockbook *dockbook)
325 {
326 g_signal_handlers_disconnect_by_func (dockbook,
327 gimp_dock_invalidate_description,
328 dock);
329 }
330
331 static void
gimp_dock_invalidate_description(GimpDock * dock)332 gimp_dock_invalidate_description (GimpDock *dock)
333 {
334 g_return_if_fail (GIMP_IS_DOCK (dock));
335
336 g_signal_emit (dock, dock_signals[DESCRIPTION_INVALIDATED], 0);
337 }
338
339 static gboolean
gimp_dock_dropped_cb(GtkWidget * source,gint insert_index,gpointer data)340 gimp_dock_dropped_cb (GtkWidget *source,
341 gint insert_index,
342 gpointer data)
343 {
344 GimpDock *dock = GIMP_DOCK (data);
345 GimpDockable *dockable = gimp_dockbook_drag_source_to_dockable (source);
346 GimpDialogFactory *factory;
347 GtkWidget *dockbook = NULL;
348
349 if (!dockable )
350 return FALSE;
351
352 /* if dropping to the same dock, take care that we don't try
353 * to reorder the *only* dockable in the dock
354 */
355 if (gimp_dockbook_get_dock (gimp_dockable_get_dockbook (dockable)) == dock)
356 {
357 GList *children;
358 gint n_books;
359 gint n_dockables;
360
361 n_books = g_list_length (gimp_dock_get_dockbooks (dock));
362
363 children = gtk_container_get_children (GTK_CONTAINER (gimp_dockable_get_dockbook (dockable)));
364 n_dockables = g_list_length (children);
365 g_list_free (children);
366
367 if (n_books == 1 && n_dockables == 1)
368 return TRUE; /* successfully do nothing */
369 }
370
371 /* Detach the dockable from the old dockbook */
372 g_object_ref (dockable);
373 gimp_dockbook_remove (gimp_dockable_get_dockbook (dockable), dockable);
374
375 /* Create a new dockbook */
376 factory = gimp_dock_get_dialog_factory (dock);
377 dockbook = gimp_dockbook_new (gimp_dialog_factory_get_menu_factory (factory));
378 gimp_dock_add_book (dock, GIMP_DOCKBOOK (dockbook), insert_index);
379
380 /* Add the dockable to new new dockbook */
381 gimp_dockbook_add (GIMP_DOCKBOOK (dockbook), dockable, -1);
382 g_object_unref (dockable);
383
384 return TRUE;
385 }
386
387
388 /* public functions */
389
390 /**
391 * gimp_dock_get_description:
392 * @dock:
393 * @complete: If %TRUE, only includes the active dockables, i.e. not the
394 * dockables in a non-active GtkNotebook tab
395 *
396 * Returns: A string describing the contents of the dock.
397 **/
398 gchar *
gimp_dock_get_description(GimpDock * dock,gboolean complete)399 gimp_dock_get_description (GimpDock *dock,
400 gboolean complete)
401 {
402 g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
403
404 if (GIMP_DOCK_GET_CLASS (dock)->get_description)
405 return GIMP_DOCK_GET_CLASS (dock)->get_description (dock, complete);
406
407 return NULL;
408 }
409
410 /**
411 * gimp_dock_set_host_geometry_hints:
412 * @dock: The dock
413 * @window: The #GtkWindow to adapt to hosting the dock
414 *
415 * Some docks have some specific needs on the #GtkWindow they are
416 * in. This function allows such docks to perform any such setup on
417 * the #GtkWindow they are in/will be put in.
418 **/
419 void
gimp_dock_set_host_geometry_hints(GimpDock * dock,GtkWindow * window)420 gimp_dock_set_host_geometry_hints (GimpDock *dock,
421 GtkWindow *window)
422 {
423 g_return_if_fail (GIMP_IS_DOCK (dock));
424 g_return_if_fail (GTK_IS_WINDOW (window));
425
426 if (GIMP_DOCK_GET_CLASS (dock)->set_host_geometry_hints)
427 GIMP_DOCK_GET_CLASS (dock)->set_host_geometry_hints (dock, window);
428 }
429
430 /**
431 * gimp_dock_invalidate_geometry:
432 * @dock:
433 *
434 * Call when the dock needs to setup its host #GtkWindow with
435 * GtkDock::set_host_geometry_hints().
436 **/
437 void
gimp_dock_invalidate_geometry(GimpDock * dock)438 gimp_dock_invalidate_geometry (GimpDock *dock)
439 {
440 g_return_if_fail (GIMP_IS_DOCK (dock));
441
442 g_signal_emit (dock, dock_signals[GEOMETRY_INVALIDATED], 0);
443 }
444
445 /**
446 * gimp_dock_update_with_context:
447 * @dock:
448 * @context:
449 *
450 * Set the @context on all dockables in the @dock.
451 **/
452 void
gimp_dock_update_with_context(GimpDock * dock,GimpContext * context)453 gimp_dock_update_with_context (GimpDock *dock,
454 GimpContext *context)
455 {
456 GList *iter = NULL;
457
458 for (iter = gimp_dock_get_dockbooks (dock);
459 iter;
460 iter = g_list_next (iter))
461 {
462 GimpDockbook *dockbook = GIMP_DOCKBOOK (iter->data);
463
464 gimp_dockbook_update_with_context (dockbook, context);
465 }
466 }
467
468 /**
469 * gimp_dock_get_context:
470 * @dock:
471 *
472 * Returns: The #GimpContext for the #GimpDockWindow the @dock is in.
473 **/
474 GimpContext *
gimp_dock_get_context(GimpDock * dock)475 gimp_dock_get_context (GimpDock *dock)
476 {
477 GimpContext *context = NULL;
478
479 g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
480
481 /* First try GimpDockColumns */
482 if (! context)
483 {
484 GimpDockColumns *dock_columns;
485
486 dock_columns =
487 GIMP_DOCK_COLUMNS (gtk_widget_get_ancestor (GTK_WIDGET (dock),
488 GIMP_TYPE_DOCK_COLUMNS));
489
490 if (dock_columns)
491 context = gimp_dock_columns_get_context (dock_columns);
492 }
493
494 /* Then GimpDockWindow */
495 if (! context)
496 {
497 GimpDockWindow *dock_window = gimp_dock_window_from_dock (dock);
498
499 if (dock_window)
500 context = gimp_dock_window_get_context (dock_window);
501 }
502
503 return context;
504 }
505
506 /**
507 * gimp_dock_get_dialog_factory:
508 * @dock:
509 *
510 * Returns: The #GimpDialogFactory for the #GimpDockWindow the @dock
511 * is in.
512 **/
513 GimpDialogFactory *
gimp_dock_get_dialog_factory(GimpDock * dock)514 gimp_dock_get_dialog_factory (GimpDock *dock)
515 {
516 GimpDialogFactory *dialog_factory = NULL;
517
518 g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
519
520 /* First try GimpDockColumns */
521 if (! dialog_factory)
522 {
523 GimpDockColumns *dock_columns;
524
525 dock_columns =
526 GIMP_DOCK_COLUMNS (gtk_widget_get_ancestor (GTK_WIDGET (dock),
527 GIMP_TYPE_DOCK_COLUMNS));
528
529 if (dock_columns)
530 dialog_factory = gimp_dock_columns_get_dialog_factory (dock_columns);
531 }
532
533 /* Then GimpDockWindow */
534 if (! dialog_factory)
535 {
536 GimpDockWindow *dock_window = gimp_dock_window_from_dock (dock);
537
538 if (dock_window)
539 dialog_factory = gimp_dock_container_get_dialog_factory (GIMP_DOCK_CONTAINER (dock_window));
540 }
541
542 return dialog_factory;
543 }
544
545 /**
546 * gimp_dock_get_ui_manager:
547 * @dock:
548 *
549 * Returns: The #GimpUIManager for the #GimpDockWindow the @dock is
550 * in.
551 **/
552 GimpUIManager *
gimp_dock_get_ui_manager(GimpDock * dock)553 gimp_dock_get_ui_manager (GimpDock *dock)
554 {
555 GimpUIManager *ui_manager = NULL;
556
557 g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
558
559 /* First try GimpDockColumns */
560 if (! ui_manager)
561 {
562 GimpDockColumns *dock_columns;
563
564 dock_columns =
565 GIMP_DOCK_COLUMNS (gtk_widget_get_ancestor (GTK_WIDGET (dock),
566 GIMP_TYPE_DOCK_COLUMNS));
567
568 if (dock_columns)
569 ui_manager = gimp_dock_columns_get_ui_manager (dock_columns);
570 }
571
572 /* Then GimpDockContainer */
573 if (! ui_manager)
574 {
575 GimpDockWindow *dock_window = gimp_dock_window_from_dock (dock);
576
577 if (dock_window)
578 {
579 GimpDockContainer *dock_container = GIMP_DOCK_CONTAINER (dock_window);
580
581 ui_manager = gimp_dock_container_get_ui_manager (dock_container);
582 }
583 }
584
585 return ui_manager;
586 }
587
588 GList *
gimp_dock_get_dockbooks(GimpDock * dock)589 gimp_dock_get_dockbooks (GimpDock *dock)
590 {
591 g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
592
593 return dock->p->dockbooks;
594 }
595
596 gint
gimp_dock_get_n_dockables(GimpDock * dock)597 gimp_dock_get_n_dockables (GimpDock *dock)
598 {
599 GList *list = NULL;
600 gint n = 0;
601
602 g_return_val_if_fail (GIMP_IS_DOCK (dock), 0);
603
604 for (list = dock->p->dockbooks; list; list = list->next)
605 n += gtk_notebook_get_n_pages (GTK_NOTEBOOK (list->data));
606
607 return n;
608 }
609
610 GtkWidget *
gimp_dock_get_main_vbox(GimpDock * dock)611 gimp_dock_get_main_vbox (GimpDock *dock)
612 {
613 g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
614
615 return dock->p->main_vbox;
616 }
617
618 GtkWidget *
gimp_dock_get_vbox(GimpDock * dock)619 gimp_dock_get_vbox (GimpDock *dock)
620 {
621 g_return_val_if_fail (GIMP_IS_DOCK (dock), NULL);
622
623 return dock->p->paned_vbox;
624 }
625
626 gint
gimp_dock_get_id(GimpDock * dock)627 gimp_dock_get_id (GimpDock *dock)
628 {
629 g_return_val_if_fail (GIMP_IS_DOCK (dock), 0);
630
631 return dock->p->ID;
632 }
633
634 void
gimp_dock_set_id(GimpDock * dock,gint ID)635 gimp_dock_set_id (GimpDock *dock,
636 gint ID)
637 {
638 g_return_if_fail (GIMP_IS_DOCK (dock));
639
640 dock->p->ID = ID;
641 }
642
643 void
gimp_dock_add(GimpDock * dock,GimpDockable * dockable,gint section,gint position)644 gimp_dock_add (GimpDock *dock,
645 GimpDockable *dockable,
646 gint section,
647 gint position)
648 {
649 GimpDockbook *dockbook;
650
651 g_return_if_fail (GIMP_IS_DOCK (dock));
652 g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
653 g_return_if_fail (gimp_dockable_get_dockbook (dockable) == NULL);
654
655 dockbook = GIMP_DOCKBOOK (dock->p->dockbooks->data);
656
657 gimp_dockbook_add (dockbook, dockable, position);
658 }
659
660 void
gimp_dock_remove(GimpDock * dock,GimpDockable * dockable)661 gimp_dock_remove (GimpDock *dock,
662 GimpDockable *dockable)
663 {
664 g_return_if_fail (GIMP_IS_DOCK (dock));
665 g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
666 g_return_if_fail (gimp_dockable_get_dockbook (dockable) != NULL);
667 g_return_if_fail (gimp_dockbook_get_dock (gimp_dockable_get_dockbook (dockable)) == dock);
668
669 gimp_dockbook_remove (gimp_dockable_get_dockbook (dockable), dockable);
670 }
671
672 void
gimp_dock_add_book(GimpDock * dock,GimpDockbook * dockbook,gint index)673 gimp_dock_add_book (GimpDock *dock,
674 GimpDockbook *dockbook,
675 gint index)
676 {
677 g_return_if_fail (GIMP_IS_DOCK (dock));
678 g_return_if_fail (GIMP_IS_DOCKBOOK (dockbook));
679 g_return_if_fail (gimp_dockbook_get_dock (dockbook) == NULL);
680
681 gimp_dockbook_set_dock (dockbook, dock);
682
683 g_signal_connect_object (dockbook, "dockable-added",
684 G_CALLBACK (gimp_dock_invalidate_description),
685 dock, G_CONNECT_SWAPPED);
686 g_signal_connect_object (dockbook, "dockable-removed",
687 G_CALLBACK (gimp_dock_invalidate_description),
688 dock, G_CONNECT_SWAPPED);
689 g_signal_connect_object (dockbook, "dockable-reordered",
690 G_CALLBACK (gimp_dock_invalidate_description),
691 dock, G_CONNECT_SWAPPED);
692
693 dock->p->dockbooks = g_list_insert (dock->p->dockbooks, dockbook, index);
694 gimp_paned_box_add_widget (GIMP_PANED_BOX (dock->p->paned_vbox),
695 GTK_WIDGET (dockbook),
696 index);
697 gtk_widget_show (GTK_WIDGET (dockbook));
698
699 gimp_dock_invalidate_description (dock);
700
701 g_signal_emit (dock, dock_signals[BOOK_ADDED], 0, dockbook);
702 }
703
704 void
gimp_dock_remove_book(GimpDock * dock,GimpDockbook * dockbook)705 gimp_dock_remove_book (GimpDock *dock,
706 GimpDockbook *dockbook)
707 {
708 g_return_if_fail (GIMP_IS_DOCK (dock));
709 g_return_if_fail (GIMP_IS_DOCKBOOK (dockbook));
710 g_return_if_fail (gimp_dockbook_get_dock (dockbook) == dock);
711
712 gimp_dockbook_set_dock (dockbook, NULL);
713
714 g_signal_handlers_disconnect_by_func (dockbook,
715 gimp_dock_invalidate_description,
716 dock);
717
718 /* Ref the dockbook so we can emit the "book-removed" signal and
719 * pass it as a parameter before it's destroyed
720 */
721 g_object_ref (dockbook);
722
723 dock->p->dockbooks = g_list_remove (dock->p->dockbooks, dockbook);
724 gimp_paned_box_remove_widget (GIMP_PANED_BOX (dock->p->paned_vbox),
725 GTK_WIDGET (dockbook));
726
727 gimp_dock_invalidate_description (dock);
728
729 g_signal_emit (dock, dock_signals[BOOK_REMOVED], 0, dockbook);
730
731 g_object_unref (dockbook);
732 }
733
734 /**
735 * gimp_dock_temp_add:
736 * @dock:
737 * @widget:
738 *
739 * Method to temporarily add a widget to the dock, for example to make
740 * font-scale style property to be applied temporarily to the
741 * child.
742 **/
743 void
gimp_dock_temp_add(GimpDock * dock,GtkWidget * child)744 gimp_dock_temp_add (GimpDock *dock,
745 GtkWidget *child)
746 {
747 g_return_if_fail (GIMP_IS_DOCK (dock));
748 g_return_if_fail (GTK_IS_WIDGET (child));
749
750 gtk_box_pack_start (GTK_BOX (dock->p->temp_vbox), child, FALSE, FALSE, 0);
751 }
752
753 /**
754 * gimp_dock_temp_remove:
755 * @dock:
756 * @child:
757 *
758 * Removes a temporary child added with gimp_dock_temp_add().
759 **/
760 void
gimp_dock_temp_remove(GimpDock * dock,GtkWidget * child)761 gimp_dock_temp_remove (GimpDock *dock,
762 GtkWidget *child)
763 {
764 g_return_if_fail (GIMP_IS_DOCK (dock));
765 g_return_if_fail (GTK_IS_WIDGET (child));
766
767 gtk_container_remove (GTK_CONTAINER (dock->p->temp_vbox), child);
768 }
769