Code

Dockable dialogs patch applied
[inkscape.git] / src / libgdl / gdl-dock-item-grip.c
1 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 8 -*- */
2 /**
3  * gdl-dock-item-grip.c
4  *
5  * Based on bonobo-dock-item-grip.  Original copyright notice follows.
6  *
7  * Author:
8  *    Michael Meeks
9  *
10  * Copyright (C) 2002 Sun Microsystems, Inc.
11  */
13 #ifdef HAVE_CONFIG_H
14 #include <config.h>
15 #endif
17 #include "gdl-i18n.h"
18 #include <string.h>
19 #include <glib-object.h>
20 #include <gtk/gtkbutton.h>
21 #include <gtk/gtktooltips.h>
22 #include <gtk/gtkimage.h>
23 #include "gdl-dock-item.h"
24 #include "gdl-dock-item-grip.h"
25 #include "gdl-stock.h"
26 #include "gdl-tools.h"
28 #define ALIGN_BORDER 5
30 enum {
31     PROP_0,
32     PROP_ITEM
33 };
34  
35 struct _GdlDockItemGripPrivate {
36     GtkWidget   *close_button;
37     GtkWidget   *iconify_button;
38     GtkTooltips *tooltips;
40     gboolean     icon_pixbuf_valid;
41     GdkPixbuf   *icon_pixbuf;
43     gchar       *title;
44     PangoLayout *title_layout;
45 };
46  
47 GDL_CLASS_BOILERPLATE (GdlDockItemGrip, gdl_dock_item_grip,
48                        GtkContainer, GTK_TYPE_CONTAINER);
50 /* must be called after size_allocate */
51 static void
52 gdl_dock_item_grip_get_title_area (GdlDockItemGrip *grip,
53                                    GdkRectangle    *area)
54 {
55     GtkWidget *widget = GTK_WIDGET (grip);
56     gint       border = GTK_CONTAINER (grip)->border_width;
57     gint       alloc_height;
59     area->width = (widget->allocation.width - 2 * border - ALIGN_BORDER);
60     
61     pango_layout_get_pixel_size (grip->_priv->title_layout, NULL, &alloc_height);
62     
63     alloc_height = MAX (grip->_priv->close_button->allocation.height, alloc_height);
64     alloc_height = MAX (grip->_priv->iconify_button->allocation.height, alloc_height);
65     if (GTK_WIDGET_VISIBLE (grip->_priv->close_button)) {
66         area->width -= grip->_priv->close_button->allocation.width;
67     }
68     if (GTK_WIDGET_VISIBLE (grip->_priv->iconify_button)) {
69         area->width -= grip->_priv->iconify_button->allocation.width;
70     }
72     area->x      = widget->allocation.x + border + ALIGN_BORDER;
73     area->y      = widget->allocation.y + border;
74     area->height = alloc_height;
76     if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
77         area->x += (widget->allocation.width - 2 * border) - area->width;
78 }
80 static void
81 ensure_title_and_icon_pixbuf (GdlDockItemGrip *grip)
82 {
83     gchar *stock_id;
84     GdkPixbuf *pixbuf;
85     
86     g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (grip));
87     
88     /* get long name property from the dock object */
89     if (!grip->_priv->title) {
90         g_object_get (G_OBJECT (grip->item), "long-name", &grip->_priv->title, NULL);
91         if (!grip->_priv->title)
92             grip->_priv->title = g_strdup ("");
93     }
95     /* retrieve stock pixbuf, if any */
96     if (!grip->_priv->icon_pixbuf_valid) {
97         g_object_get (G_OBJECT (grip->item), "stock-id", &stock_id, NULL);
98         
99         if (stock_id) {
100             grip->_priv->icon_pixbuf = gtk_widget_render_icon (GTK_WIDGET (grip),
101                                                                stock_id,
102                                                                GTK_ICON_SIZE_MENU, "");
103             g_free (stock_id);
104             grip->_priv->icon_pixbuf_valid = TRUE;
105         }
106     }
108     /* retrieve pixbuf icon, if any */
109     if (!grip->_priv->icon_pixbuf_valid) {
110         g_object_get (G_OBJECT (grip->item), "pixbuf-icon", &pixbuf, NULL);
111         
112         if (pixbuf) {
113             grip->_priv->icon_pixbuf = pixbuf;
114             grip->_priv->icon_pixbuf_valid = TRUE;
115         }
116     }
118     /* create layout: the actual text is reset at size_allocate */
119     if (!grip->_priv->title_layout) {
120         grip->_priv->title_layout = gtk_widget_create_pango_layout (GTK_WIDGET (grip),
121                                                                     grip->_priv->title);
122         pango_layout_set_single_paragraph_mode (grip->_priv->title_layout, TRUE);
123     }
126 static gint
127 gdl_dock_item_grip_expose (GtkWidget      *widget,
128                            GdkEventExpose *event)
130     GdlDockItemGrip *grip;
131     GdkRectangle     title_area;
132     GdkRectangle     expose_area;
133     gint             layout_width;
134     gint             layout_height;
135     gint             text_x;
136     gint             text_y;
138     grip = GDL_DOCK_ITEM_GRIP (widget);
139     gdl_dock_item_grip_get_title_area (grip, &title_area);
141     if (grip->_priv->icon_pixbuf) {
142         GdkRectangle pixbuf_rect;
143         
144         pixbuf_rect.width = gdk_pixbuf_get_width (grip->_priv->icon_pixbuf);
145         pixbuf_rect.height = gdk_pixbuf_get_height (grip->_priv->icon_pixbuf);
146         if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) {
147             pixbuf_rect.x = title_area.x + title_area.width - pixbuf_rect.width;
148         } else {
149             pixbuf_rect.x = title_area.x;
150             title_area.x += pixbuf_rect.width + 1;
151         }
152         /* shrink title area by the pixbuf width plus a 1px spacing */
153         title_area.width -= pixbuf_rect.width + 1;
154         pixbuf_rect.y = title_area.y + (title_area.height - pixbuf_rect.height) / 2;
156         if (gdk_rectangle_intersect (&event->area, &pixbuf_rect, &expose_area)) {
157             GdkGC *gc;
158             GtkStyle *style;
160             style = gtk_widget_get_style (widget);
161             gc = style->bg_gc[widget->state];
162             gdk_draw_pixbuf (GDK_DRAWABLE (widget->window), gc,
163                              grip->_priv->icon_pixbuf,
164                              0, 0, pixbuf_rect.x, pixbuf_rect.y,
165                              pixbuf_rect.width, pixbuf_rect.height,
166                              GDK_RGB_DITHER_NONE, 0, 0);
167         }
168     }
170     if (gdk_rectangle_intersect (&title_area, &event->area, &expose_area)) {
171         pango_layout_get_pixel_size (grip->_priv->title_layout, &layout_width,
172                                      &layout_height);
174         if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
175             text_x = title_area.x + title_area.width - layout_width;
176         else
177             text_x = title_area.x;
179         text_y = title_area.y + (title_area.height - layout_height) / 2;
181         gtk_paint_layout (widget->style, widget->window, widget->state, TRUE,
182                           &expose_area, widget, NULL, text_x, text_y,
183                           grip->_priv->title_layout);
184     }
186     return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
187 }  
189 static void
190 gdl_dock_item_grip_item_notify (GObject    *master,
191                                 GParamSpec *pspec,
192                                 gpointer    data)
194     GdlDockItemGrip *grip;
195     gboolean cursor;
196     
197     grip = GDL_DOCK_ITEM_GRIP (data);
199     if (strcmp (pspec->name, "stock-id") == 0) {
200         if (grip->_priv->icon_pixbuf) {
201             g_object_unref (grip->_priv->icon_pixbuf);
202             grip->_priv->icon_pixbuf = NULL;
203         }
204         grip->_priv->icon_pixbuf_valid = FALSE;
205         ensure_title_and_icon_pixbuf (grip);
207     } else if (strcmp (pspec->name, "long-name") == 0) {
208         g_free (grip->_priv->title);
209         g_object_unref (grip->_priv->title_layout);
210         grip->_priv->title_layout = NULL;
211         grip->_priv->title = NULL;
212         ensure_title_and_icon_pixbuf (grip);
213         gtk_widget_queue_draw (GTK_WIDGET (grip));
214     } else if (strcmp (pspec->name, "behavior") == 0) {
215         cursor = FALSE;
216         if (grip->_priv->close_button) {
217             if (GDL_DOCK_ITEM_CANT_CLOSE (grip->item)) {
218                 gtk_widget_hide (GTK_WIDGET (grip->_priv->close_button));
219             } else {
220                 gtk_widget_show (GTK_WIDGET (grip->_priv->close_button));
221                 cursor = TRUE;
222             }
223         }
224         if (grip->_priv->iconify_button) {
225             if (GDL_DOCK_ITEM_CANT_ICONIFY (grip->item)) {
226                 gtk_widget_hide (GTK_WIDGET (grip->_priv->iconify_button));
227             } else {
228                 gtk_widget_show (GTK_WIDGET (grip->_priv->iconify_button));
229                 cursor = TRUE;
230             }
231         }
232         if (grip->title_window && !cursor)
233             gdk_window_set_cursor (grip->title_window, NULL);
235     }
238 static void
239 gdl_dock_item_grip_destroy (GtkObject *object)
241     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (object);
242     
243     if (grip->_priv) {
244         GdlDockItemGripPrivate *priv = grip->_priv;
246         if (priv->title_layout) {
247             g_object_unref (priv->title_layout);
248             priv->title_layout = NULL;
249         }
250         g_free (priv->title);
251         priv->title = NULL;
253         if (priv->icon_pixbuf) {
254             g_object_unref (priv->icon_pixbuf);
255             priv->icon_pixbuf = NULL;
256         }
258         if (priv->tooltips) {
259             g_object_unref (priv->tooltips);
260             priv->tooltips = NULL;
261         }
263         if (grip->item)
264             g_signal_handlers_disconnect_by_func (grip->item,
265                                                   gdl_dock_item_grip_item_notify,
266                                                   grip);
267         grip->item = NULL;
269         grip->_priv = NULL;
270         g_free (priv);
271     }
273     GDL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
276 static void
277 gdl_dock_item_grip_set_property (GObject      *object,
278                                  guint         prop_id,
279                                  const GValue *value,
280                                  GParamSpec   *pspec)
282     GdlDockItemGrip *grip;
284     g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (object));
286     grip = GDL_DOCK_ITEM_GRIP (object);
287     
288     switch (prop_id) {
289         case PROP_ITEM:
290             grip->item = g_value_get_object (value);
291             if (grip->item) {
292                 g_signal_connect (grip->item, "notify::long_name",
293                                   G_CALLBACK (gdl_dock_item_grip_item_notify),
294                                   grip);
295                 g_signal_connect (grip->item, "notify::stock_id",
296                                   G_CALLBACK (gdl_dock_item_grip_item_notify),
297                                   grip);
298                 g_signal_connect (grip->item, "notify::behavior",
299                                   G_CALLBACK (gdl_dock_item_grip_item_notify),
300                                   grip);
302                 if (!GDL_DOCK_ITEM_CANT_CLOSE (grip->item) && grip->_priv->close_button)
303                     gtk_widget_show (grip->_priv->close_button);
304                 if (!GDL_DOCK_ITEM_CANT_ICONIFY (grip->item) && grip->_priv->iconify_button)
305                     gtk_widget_show (grip->_priv->iconify_button);
306             }
307             break;
308         default:
309             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
310             break;
311     }
314 static void
315 gdl_dock_item_grip_close_clicked (GtkWidget       *widget,
316                                   GdlDockItemGrip *grip)
318     g_return_if_fail (grip->item != NULL);
320     gdl_dock_item_hide_item (grip->item);
323 static void
324 gdl_dock_item_grip_iconify_clicked (GtkWidget       *widget,
325                                     GdlDockItemGrip *grip)
327     g_return_if_fail (grip->item != NULL);
329     gdl_dock_item_iconify_item (grip->item);
330     
331     /* Workaround to unhighlight the iconify button. */
332     GTK_BUTTON (grip->_priv->iconify_button)->in_button = FALSE;
333     gtk_button_leave (GTK_BUTTON (grip->_priv->iconify_button));
335   
336 static void
337 gdl_dock_item_grip_instance_init (GdlDockItemGrip *grip)
339     GtkWidget *image;
341     GTK_WIDGET_SET_FLAGS (grip, GTK_NO_WINDOW);
342     
343     grip->_priv = g_new0 (GdlDockItemGripPrivate, 1);
344     grip->_priv->icon_pixbuf_valid = FALSE;
345     grip->_priv->icon_pixbuf = NULL;
346     grip->_priv->title_layout = NULL;
348     gtk_widget_push_composite_child ();
349     grip->_priv->close_button = gtk_button_new ();
350     gtk_widget_pop_composite_child ();
351     
352     GTK_WIDGET_UNSET_FLAGS (grip->_priv->close_button, GTK_CAN_FOCUS);
353     gtk_widget_set_parent (grip->_priv->close_button, GTK_WIDGET (grip));
354     gtk_button_set_relief (GTK_BUTTON (grip->_priv->close_button), GTK_RELIEF_NONE);
355     gtk_widget_show (grip->_priv->close_button);
357     image = gtk_image_new_from_stock (GDL_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
358     gtk_container_add (GTK_CONTAINER (grip->_priv->close_button), image);
359     gtk_widget_show (image);
361     g_signal_connect (G_OBJECT (grip->_priv->close_button), "clicked",
362                       G_CALLBACK (gdl_dock_item_grip_close_clicked), grip);
364     gtk_widget_push_composite_child ();
365     grip->_priv->iconify_button = gtk_button_new ();
366     gtk_widget_pop_composite_child ();
367     
368     GTK_WIDGET_UNSET_FLAGS (grip->_priv->iconify_button, GTK_CAN_FOCUS);
369     gtk_widget_set_parent (grip->_priv->iconify_button, GTK_WIDGET (grip));
370     gtk_button_set_relief (GTK_BUTTON (grip->_priv->iconify_button), GTK_RELIEF_NONE);
371     gtk_widget_show (grip->_priv->iconify_button);
373     image = gtk_image_new_from_stock (GDL_STOCK_MENU_LEFT, GTK_ICON_SIZE_MENU);
374     gtk_container_add (GTK_CONTAINER (grip->_priv->iconify_button), image);
375     gtk_widget_show (image);
377     g_signal_connect (G_OBJECT (grip->_priv->iconify_button), "clicked",
378                       G_CALLBACK (gdl_dock_item_grip_iconify_clicked), grip);
380     grip->_priv->tooltips = gtk_tooltips_new ();
381     g_object_ref (grip->_priv->tooltips);
382     gtk_object_sink (GTK_OBJECT (grip->_priv->tooltips));
383     gtk_tooltips_set_tip (grip->_priv->tooltips, grip->_priv->iconify_button,
384                           _("Iconify"), _("Iconify this dock"));
385     gtk_tooltips_set_tip (grip->_priv->tooltips, grip->_priv->close_button,
386                           _("Close"), _("Close this dock"));
389 static void
390 gdl_dock_item_grip_realize (GtkWidget *widget)
392     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (widget);
394     GTK_WIDGET_CLASS (parent_class)->realize (widget);
396     if (!grip->title_window) {
397         GdkWindowAttr  attributes;
398         GdkRectangle   area;
399         GdkCursor     *cursor;
401         ensure_title_and_icon_pixbuf (grip);
402         gdl_dock_item_grip_get_title_area (grip, &area);
404         attributes.x                 = area.x;
405         attributes.y                 = area.y;
406         attributes.width             = area.width;
407         attributes.height            = area.height;
408         attributes.window_type       = GDK_WINDOW_TEMP;
409         attributes.wclass            = GDK_INPUT_ONLY;
410         attributes.override_redirect = TRUE;
411         attributes.event_mask        = (GDK_BUTTON_PRESS_MASK   |
412                                         GDK_BUTTON_RELEASE_MASK |
413                                         GDK_BUTTON_MOTION_MASK  |
414                                         gtk_widget_get_events (widget));
416         grip->title_window = gdk_window_new (gtk_widget_get_parent_window (widget),
417                                              &attributes,
418                                              (GDK_WA_X |
419                                               GDK_WA_Y |
420                                               GDK_WA_NOREDIR));
422         gdk_window_set_user_data (grip->title_window, widget);
423  
424         if (GDL_DOCK_ITEM_CANT_CLOSE (grip->item))
425             cursor = NULL;
426         else if (GDL_DOCK_ITEM_CANT_ICONIFY (grip->item))
427             cursor = NULL;
428         else 
429             cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
430                                              GDK_HAND2);
431         gdk_window_set_cursor (grip->title_window, cursor);
432         if (cursor)
433             gdk_cursor_unref (cursor);
434     }
437 static void
438 gdl_dock_item_grip_unrealize (GtkWidget *widget)
440     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (widget);
442     if (grip->title_window) {
443         gdk_window_set_user_data (grip->title_window, NULL);
444         gdk_window_destroy (grip->title_window);
445         grip->title_window = NULL;
446     }
448     GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
451 static void
452 gdl_dock_item_grip_map (GtkWidget *widget)
454     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (widget);
456     GTK_WIDGET_CLASS (parent_class)->map (widget);
458     if (grip->title_window)
459         gdk_window_show (grip->title_window);
462 static void
463 gdl_dock_item_grip_unmap (GtkWidget *widget)
465     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (widget);
467     if (grip->title_window)
468         gdk_window_hide (grip->title_window);
470     GTK_WIDGET_CLASS (parent_class)->unmap (widget);
473 static void
474 gdl_dock_item_grip_size_request (GtkWidget      *widget,
475                                  GtkRequisition *requisition)
477     GtkRequisition   child_requisition;
478     GtkContainer    *container;
479     GdlDockItemGrip *grip;
480     gint             layout_height;
482     g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (widget));
483     g_return_if_fail (requisition != NULL);
485     container = GTK_CONTAINER (widget);
486     grip = GDL_DOCK_ITEM_GRIP (widget);
487     
488     requisition->width = container->border_width * 2 + ALIGN_BORDER;
489     requisition->height = container->border_width * 2;
491     ensure_title_and_icon_pixbuf (grip);
492     pango_layout_get_pixel_size (grip->_priv->title_layout, NULL, &layout_height);
494     gtk_widget_size_request (grip->_priv->close_button, &child_requisition);
496     requisition->width += child_requisition.width;
497     layout_height = MAX (layout_height, child_requisition.height);
498     
499     gtk_widget_size_request (grip->_priv->iconify_button, &child_requisition);
501     requisition->width += child_requisition.width;
502     layout_height = MAX (layout_height, child_requisition.height);
503     
504     requisition->height += layout_height;
506     if (grip->_priv->icon_pixbuf) {
507         requisition->width += gdk_pixbuf_get_width (grip->_priv->icon_pixbuf) + 1;
508     }
511 #define ELLIPSIS "..."
513 static void
514 ellipsize_layout (PangoLayout *layout, gint width)
516     PangoLayoutLine *line;
517     PangoLayout *ell;
518     gint h, w, ell_w, x;
519     GString *text;
520     
521     if (width <= 0) {
522         pango_layout_set_text (layout, "", -1);
523         return;
524     }
525     
526     pango_layout_get_pixel_size (layout, &w, &h);
527     if (w <= width) return;
528     
529     /* calculate ellipsis width */
530     ell = pango_layout_copy (layout);
531     pango_layout_set_text (ell, ELLIPSIS, -1);
532     pango_layout_get_pixel_size (ell, &ell_w, NULL);
533     g_object_unref (ell);
535     if (width < ell_w) {
536         /* not even ellipsis fits, so hide the text */
537         pango_layout_set_text (layout, "", -1);
538         return;
539     }
541     /* shrink total available width by the width of the ellipsis */
542     width -= ell_w;
543     line = pango_layout_get_line (layout, 0);
544     text = g_string_new (pango_layout_get_text (layout));
545     if (pango_layout_line_x_to_index (line, width * PANGO_SCALE, &x, NULL)) {
546         g_string_set_size (text, x);
547         g_string_append (text, ELLIPSIS);
548         pango_layout_set_text (layout, text->str, -1);
549     }
550     g_string_free (text, TRUE);
553 static void
554 gdl_dock_item_grip_size_allocate (GtkWidget     *widget,
555                                   GtkAllocation *allocation)
557     GdlDockItemGrip *grip;
558     GtkContainer    *container;
559     GtkRequisition   button_requisition = { 0, };
560     GtkAllocation    child_allocation;
562     g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (widget));
563     g_return_if_fail (allocation != NULL);
564   
565     grip = GDL_DOCK_ITEM_GRIP (widget);
566     container = GTK_CONTAINER (widget);
568     GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
570     if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
571         child_allocation.x = allocation->x + container->border_width + ALIGN_BORDER;
572     else
573         child_allocation.x = allocation->x + allocation->width - container->border_width;
574     child_allocation.y = allocation->y + container->border_width;
576     gtk_widget_size_request (grip->_priv->close_button, &button_requisition);
578     if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL)
579         child_allocation.x -= button_requisition.width;
581     child_allocation.width = button_requisition.width;
582     child_allocation.height = button_requisition.height;
584     gtk_widget_size_allocate (grip->_priv->close_button, &child_allocation);
586     if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
587         child_allocation.x += button_requisition.width;
588     
590     gtk_widget_size_request (grip->_priv->iconify_button, &button_requisition);
592     if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL)
593         child_allocation.x -= button_requisition.width;
595     child_allocation.width = button_requisition.width;
596     child_allocation.height = button_requisition.height;
598     gtk_widget_size_allocate (grip->_priv->iconify_button, &child_allocation);
600     if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
601         child_allocation.x += button_requisition.width;
603     
604     if (grip->title_window) {
605         GdkRectangle area;
606         
607         /* set layout text */
608         ensure_title_and_icon_pixbuf (grip);
609         pango_layout_set_text (grip->_priv->title_layout, grip->_priv->title, -1);
611         gdl_dock_item_grip_get_title_area (grip, &area);
613         gdk_window_move_resize (grip->title_window,
614                                 area.x, area.y, area.width, area.height);
616         if (grip->_priv->icon_pixbuf)
617             area.width -= gdk_pixbuf_get_width (grip->_priv->icon_pixbuf) + 1;
618             
619         /* ellipsize title if it doesn't fit the title area */
620         ellipsize_layout (grip->_priv->title_layout, area.width);
621     }
624 static void 
625 gdl_dock_item_grip_add (GtkContainer *container,
626                         GtkWidget    *widget)
628     g_warning ("gtk_container_add not implemented for GdlDockItemGrip");
631 static void  
632 gdl_dock_item_grip_remove (GtkContainer *container,
633                            GtkWidget    *widget)
635     g_warning ("gtk_container_remove not implemented for GdlDockItemGrip");
638 static void
639 gdl_dock_item_grip_forall (GtkContainer *container,
640                            gboolean      include_internals,
641                            GtkCallback   callback,
642                            gpointer      callback_data)
644     GdlDockItemGrip *grip;
645     
646     g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (container));
648     grip = GDL_DOCK_ITEM_GRIP (container);
650     if (include_internals) {
651         (* callback) (grip->_priv->close_button, callback_data);
652         (* callback) (grip->_priv->iconify_button, callback_data);
653     }
656 static GtkType
657 gdl_dock_item_grip_child_type (GtkContainer *container)
659     return G_TYPE_NONE;
662 static void
663 gdl_dock_item_grip_class_init (GdlDockItemGripClass *klass)
665     GObjectClass *gobject_class;
666     GtkObjectClass *gtk_object_class;
667     GtkWidgetClass *widget_class;
668     GtkContainerClass *container_class;
670     parent_class = g_type_class_peek_parent (klass);
671     gobject_class = G_OBJECT_CLASS (klass);
672     gtk_object_class = GTK_OBJECT_CLASS (klass);
673     widget_class = GTK_WIDGET_CLASS (klass);
674     container_class = GTK_CONTAINER_CLASS (klass);
676     gobject_class->set_property = gdl_dock_item_grip_set_property;
678     gtk_object_class->destroy = gdl_dock_item_grip_destroy;
680     widget_class->expose_event = gdl_dock_item_grip_expose;
681     widget_class->realize = gdl_dock_item_grip_realize;
682     widget_class->unrealize = gdl_dock_item_grip_unrealize;
683     widget_class->map = gdl_dock_item_grip_map;
684     widget_class->unmap = gdl_dock_item_grip_unmap;
685     widget_class->size_request = gdl_dock_item_grip_size_request;
686     widget_class->size_allocate = gdl_dock_item_grip_size_allocate;
688     container_class->add = gdl_dock_item_grip_add;
689     container_class->remove = gdl_dock_item_grip_remove;
690     container_class->forall = gdl_dock_item_grip_forall;
691     container_class->child_type = gdl_dock_item_grip_child_type;
693     g_object_class_install_property (
694         gobject_class, PROP_ITEM,
695         g_param_spec_object ("item", _("Controlling dock item"),
696                              _("Dockitem which 'owns' this grip"),
697                              GDL_TYPE_DOCK_ITEM,
698                              G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
700     /* initialize stock images */
701     gdl_stock_init ();
704 GtkWidget *
705 gdl_dock_item_grip_new (GdlDockItem *item)
707     GdlDockItemGrip *grip = g_object_new (GDL_TYPE_DOCK_ITEM_GRIP, "item", item,
708                                           NULL);
710     return GTK_WIDGET (grip);