Code

make it even darker :)
[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     /* draw darker a background */
142     gdk_draw_rectangle (GDK_DRAWABLE (widget->window),
143                         gtk_widget_get_style (widget)->dark_gc[widget->state],
144                         TRUE,
145                         1, 0,
146                         widget->allocation.width - 1,
147                         widget->allocation.height);
149     if (grip->_priv->icon_pixbuf) {
150         GdkRectangle pixbuf_rect;
151         
152         pixbuf_rect.width = gdk_pixbuf_get_width (grip->_priv->icon_pixbuf);
153         pixbuf_rect.height = gdk_pixbuf_get_height (grip->_priv->icon_pixbuf);
154         if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) {
155             pixbuf_rect.x = title_area.x + title_area.width - pixbuf_rect.width;
156         } else {
157             pixbuf_rect.x = title_area.x;
158             title_area.x += pixbuf_rect.width + 1;
159         }
160         /* shrink title area by the pixbuf width plus a 1px spacing */
161         title_area.width -= pixbuf_rect.width + 1;
162         pixbuf_rect.y = title_area.y + (title_area.height - pixbuf_rect.height) / 2;
164         if (gdk_rectangle_intersect (&event->area, &pixbuf_rect, &expose_area)) {
165             GdkGC *gc;
166             GtkStyle *style;
168             style = gtk_widget_get_style (widget);
169             gc = style->bg_gc[widget->state];
170             gdk_draw_pixbuf (GDK_DRAWABLE (widget->window), gc,
171                              grip->_priv->icon_pixbuf,
172                              0, 0, pixbuf_rect.x, pixbuf_rect.y,
173                              pixbuf_rect.width, pixbuf_rect.height,
174                              GDK_RGB_DITHER_NONE, 0, 0);
175         }
176     }
178     if (gdk_rectangle_intersect (&title_area, &event->area, &expose_area)) {
179         pango_layout_get_pixel_size (grip->_priv->title_layout, &layout_width,
180                                      &layout_height);
182         if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
183             text_x = title_area.x + title_area.width - layout_width;
184         else
185             text_x = title_area.x;
187         text_y = title_area.y + (title_area.height - layout_height) / 2;
189         gtk_paint_layout (widget->style, widget->window, widget->state, TRUE,
190                           &expose_area, widget, NULL, text_x, text_y,
191                           grip->_priv->title_layout);
192     }
194     return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
195 }  
197 static void
198 gdl_dock_item_grip_item_notify (GObject    *master,
199                                 GParamSpec *pspec,
200                                 gpointer    data)
202     GdlDockItemGrip *grip;
203     gboolean cursor;
204     
205     grip = GDL_DOCK_ITEM_GRIP (data);
207     if (strcmp (pspec->name, "stock-id") == 0) {
208         if (grip->_priv->icon_pixbuf) {
209             g_object_unref (grip->_priv->icon_pixbuf);
210             grip->_priv->icon_pixbuf = NULL;
211         }
212         grip->_priv->icon_pixbuf_valid = FALSE;
213         ensure_title_and_icon_pixbuf (grip);
215     } else if (strcmp (pspec->name, "long-name") == 0) {
216         g_free (grip->_priv->title);
217         g_object_unref (grip->_priv->title_layout);
218         grip->_priv->title_layout = NULL;
219         grip->_priv->title = NULL;
220         ensure_title_and_icon_pixbuf (grip);
221         gtk_widget_queue_draw (GTK_WIDGET (grip));
222     } else if (strcmp (pspec->name, "behavior") == 0) {
223         cursor = FALSE;
224         if (grip->_priv->close_button) {
225             if (GDL_DOCK_ITEM_CANT_CLOSE (grip->item)) {
226                 gtk_widget_hide (GTK_WIDGET (grip->_priv->close_button));
227             } else {
228                 gtk_widget_show (GTK_WIDGET (grip->_priv->close_button));
229                 cursor = TRUE;
230             }
231         }
232         if (grip->_priv->iconify_button) {
233             if (GDL_DOCK_ITEM_CANT_ICONIFY (grip->item)) {
234                 gtk_widget_hide (GTK_WIDGET (grip->_priv->iconify_button));
235             } else {
236                 gtk_widget_show (GTK_WIDGET (grip->_priv->iconify_button));
237                 cursor = TRUE;
238             }
239         }
240         if (grip->title_window && !cursor)
241             gdk_window_set_cursor (grip->title_window, NULL);
243     }
246 static void
247 gdl_dock_item_grip_destroy (GtkObject *object)
249     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (object);
250     
251     if (grip->_priv) {
252         GdlDockItemGripPrivate *priv = grip->_priv;
254         if (priv->title_layout) {
255             g_object_unref (priv->title_layout);
256             priv->title_layout = NULL;
257         }
258         g_free (priv->title);
259         priv->title = NULL;
261         if (priv->icon_pixbuf) {
262             g_object_unref (priv->icon_pixbuf);
263             priv->icon_pixbuf = NULL;
264         }
266         if (priv->tooltips) {
267             g_object_unref (priv->tooltips);
268             priv->tooltips = NULL;
269         }
271         if (grip->item)
272             g_signal_handlers_disconnect_by_func (grip->item,
273                                                   gdl_dock_item_grip_item_notify,
274                                                   grip);
275         grip->item = NULL;
277         grip->_priv = NULL;
278         g_free (priv);
279     }
281     GDL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
284 static void
285 gdl_dock_item_grip_set_property (GObject      *object,
286                                  guint         prop_id,
287                                  const GValue *value,
288                                  GParamSpec   *pspec)
290     GdlDockItemGrip *grip;
292     g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (object));
294     grip = GDL_DOCK_ITEM_GRIP (object);
295     
296     switch (prop_id) {
297         case PROP_ITEM:
298             grip->item = g_value_get_object (value);
299             if (grip->item) {
300                 g_signal_connect (grip->item, "notify::long_name",
301                                   G_CALLBACK (gdl_dock_item_grip_item_notify),
302                                   grip);
303                 g_signal_connect (grip->item, "notify::stock_id",
304                                   G_CALLBACK (gdl_dock_item_grip_item_notify),
305                                   grip);
306                 g_signal_connect (grip->item, "notify::behavior",
307                                   G_CALLBACK (gdl_dock_item_grip_item_notify),
308                                   grip);
310                 if (!GDL_DOCK_ITEM_CANT_CLOSE (grip->item) && grip->_priv->close_button)
311                     gtk_widget_show (grip->_priv->close_button);
312                 if (!GDL_DOCK_ITEM_CANT_ICONIFY (grip->item) && grip->_priv->iconify_button)
313                     gtk_widget_show (grip->_priv->iconify_button);
314             }
315             break;
316         default:
317             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
318             break;
319     }
322 static void
323 gdl_dock_item_grip_close_clicked (GtkWidget       *widget,
324                                   GdlDockItemGrip *grip)
326     g_return_if_fail (grip->item != NULL);
328     gdl_dock_item_hide_item (grip->item);
331 static void
332 gdl_dock_item_grip_iconify_clicked (GtkWidget       *widget,
333                                     GdlDockItemGrip *grip)
335     g_return_if_fail (grip->item != NULL);
337     gdl_dock_item_iconify_item (grip->item);
338     
339     /* Workaround to unhighlight the iconify button. */
340     GTK_BUTTON (grip->_priv->iconify_button)->in_button = FALSE;
341     gtk_button_leave (GTK_BUTTON (grip->_priv->iconify_button));
343   
344 static void
345 gdl_dock_item_grip_instance_init (GdlDockItemGrip *grip)
347     GtkWidget *image;
349     GTK_WIDGET_SET_FLAGS (grip, GTK_NO_WINDOW);
350     
351     grip->_priv = g_new0 (GdlDockItemGripPrivate, 1);
352     grip->_priv->icon_pixbuf_valid = FALSE;
353     grip->_priv->icon_pixbuf = NULL;
354     grip->_priv->title_layout = NULL;
356     gtk_widget_push_composite_child ();
357     grip->_priv->close_button = gtk_button_new ();
358     gtk_widget_pop_composite_child ();
359     
360     GTK_WIDGET_UNSET_FLAGS (grip->_priv->close_button, GTK_CAN_FOCUS);
361     gtk_widget_set_parent (grip->_priv->close_button, GTK_WIDGET (grip));
362     gtk_button_set_relief (GTK_BUTTON (grip->_priv->close_button), GTK_RELIEF_NONE);
363     gtk_widget_show (grip->_priv->close_button);
365     image = gtk_image_new_from_stock (GDL_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
366     gtk_container_add (GTK_CONTAINER (grip->_priv->close_button), image);
367     gtk_widget_show (image);
369     g_signal_connect (G_OBJECT (grip->_priv->close_button), "clicked",
370                       G_CALLBACK (gdl_dock_item_grip_close_clicked), grip);
372     gtk_widget_push_composite_child ();
373     grip->_priv->iconify_button = gtk_button_new ();
374     gtk_widget_pop_composite_child ();
375     
376     GTK_WIDGET_UNSET_FLAGS (grip->_priv->iconify_button, GTK_CAN_FOCUS);
377     gtk_widget_set_parent (grip->_priv->iconify_button, GTK_WIDGET (grip));
378     gtk_button_set_relief (GTK_BUTTON (grip->_priv->iconify_button), GTK_RELIEF_NONE);
379     gtk_widget_show (grip->_priv->iconify_button);
381     image = gtk_image_new_from_stock (GDL_STOCK_MENU_RIGHT, GTK_ICON_SIZE_MENU);
382     gtk_container_add (GTK_CONTAINER (grip->_priv->iconify_button), image);
383     gtk_widget_show (image);
385     g_signal_connect (G_OBJECT (grip->_priv->iconify_button), "clicked",
386                       G_CALLBACK (gdl_dock_item_grip_iconify_clicked), grip);
388     grip->_priv->tooltips = gtk_tooltips_new ();
389     g_object_ref (grip->_priv->tooltips);
390     gtk_object_sink (GTK_OBJECT (grip->_priv->tooltips));
391     gtk_tooltips_set_tip (grip->_priv->tooltips, grip->_priv->iconify_button,
392                           _("Iconify"), _("Iconify this dock"));
393     gtk_tooltips_set_tip (grip->_priv->tooltips, grip->_priv->close_button,
394                           _("Close"), _("Close this dock"));
397 static void
398 gdl_dock_item_grip_realize (GtkWidget *widget)
400     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (widget);
402     GTK_WIDGET_CLASS (parent_class)->realize (widget);
404     if (!grip->title_window) {
405         GdkWindowAttr  attributes;
406         GdkRectangle   area;
407         GdkCursor     *cursor;
409         ensure_title_and_icon_pixbuf (grip);
410         gdl_dock_item_grip_get_title_area (grip, &area);
412         attributes.x                 = area.x;
413         attributes.y                 = area.y;
414         attributes.width             = area.width;
415         attributes.height            = area.height;
416         attributes.window_type       = GDK_WINDOW_TEMP;
417         attributes.wclass            = GDK_INPUT_ONLY;
418         attributes.override_redirect = TRUE;
419         attributes.event_mask        = (GDK_BUTTON_PRESS_MASK   |
420                                         GDK_BUTTON_RELEASE_MASK |
421                                         GDK_BUTTON_MOTION_MASK  |
422                                         gtk_widget_get_events (widget));
424         grip->title_window = gdk_window_new (gtk_widget_get_parent_window (widget),
425                                              &attributes,
426                                              (GDK_WA_X |
427                                               GDK_WA_Y |
428                                               GDK_WA_NOREDIR));
430         gdk_window_set_user_data (grip->title_window, widget);
431  
432         if (GDL_DOCK_ITEM_CANT_CLOSE (grip->item))
433             cursor = NULL;
434         else if (GDL_DOCK_ITEM_CANT_ICONIFY (grip->item))
435             cursor = NULL;
436         else 
437             cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
438                                              GDK_HAND2);
439         gdk_window_set_cursor (grip->title_window, cursor);
440         if (cursor)
441             gdk_cursor_unref (cursor);
442     }
445 static void
446 gdl_dock_item_grip_unrealize (GtkWidget *widget)
448     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (widget);
450     if (grip->title_window) {
451         gdk_window_set_user_data (grip->title_window, NULL);
452         gdk_window_destroy (grip->title_window);
453         grip->title_window = NULL;
454     }
456     GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
459 static void
460 gdl_dock_item_grip_map (GtkWidget *widget)
462     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (widget);
464     GTK_WIDGET_CLASS (parent_class)->map (widget);
466     if (grip->title_window)
467         gdk_window_show (grip->title_window);
470 static void
471 gdl_dock_item_grip_unmap (GtkWidget *widget)
473     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (widget);
475     if (grip->title_window)
476         gdk_window_hide (grip->title_window);
478     GTK_WIDGET_CLASS (parent_class)->unmap (widget);
481 static void
482 gdl_dock_item_grip_size_request (GtkWidget      *widget,
483                                  GtkRequisition *requisition)
485     GtkRequisition   child_requisition;
486     GtkContainer    *container;
487     GdlDockItemGrip *grip;
488     gint             layout_height;
490     g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (widget));
491     g_return_if_fail (requisition != NULL);
493     container = GTK_CONTAINER (widget);
494     grip = GDL_DOCK_ITEM_GRIP (widget);
495     
496     requisition->width = container->border_width * 2 + ALIGN_BORDER;
497     requisition->height = container->border_width * 2;
499     ensure_title_and_icon_pixbuf (grip);
500     pango_layout_get_pixel_size (grip->_priv->title_layout, NULL, &layout_height);
502     gtk_widget_size_request (grip->_priv->close_button, &child_requisition);
504     requisition->width += child_requisition.width;
505     layout_height = MAX (layout_height, child_requisition.height);
506     
507     gtk_widget_size_request (grip->_priv->iconify_button, &child_requisition);
509     requisition->width += child_requisition.width;
510     layout_height = MAX (layout_height, child_requisition.height);
511     
512     requisition->height += layout_height;
514     if (grip->_priv->icon_pixbuf) {
515         requisition->width += gdk_pixbuf_get_width (grip->_priv->icon_pixbuf) + 1;
516     }
519 #define ELLIPSIS "..."
521 static void
522 ellipsize_layout (PangoLayout *layout, gint width)
524     PangoLayoutLine *line;
525     PangoLayout *ell;
526     gint h, w, ell_w, x;
527     GString *text;
528     
529     if (width <= 0) {
530         pango_layout_set_text (layout, "", -1);
531         return;
532     }
533     
534     pango_layout_get_pixel_size (layout, &w, &h);
535     if (w <= width) return;
536     
537     /* calculate ellipsis width */
538     ell = pango_layout_copy (layout);
539     pango_layout_set_text (ell, ELLIPSIS, -1);
540     pango_layout_get_pixel_size (ell, &ell_w, NULL);
541     g_object_unref (ell);
543     if (width < ell_w) {
544         /* not even ellipsis fits, so hide the text */
545         pango_layout_set_text (layout, "", -1);
546         return;
547     }
549     /* shrink total available width by the width of the ellipsis */
550     width -= ell_w;
551     line = pango_layout_get_line (layout, 0);
552     text = g_string_new (pango_layout_get_text (layout));
553     if (pango_layout_line_x_to_index (line, width * PANGO_SCALE, &x, NULL)) {
554         g_string_set_size (text, x);
555         g_string_append (text, ELLIPSIS);
556         pango_layout_set_text (layout, text->str, -1);
557     }
558     g_string_free (text, TRUE);
561 static void
562 gdl_dock_item_grip_size_allocate (GtkWidget     *widget,
563                                   GtkAllocation *allocation)
565     GdlDockItemGrip *grip;
566     GtkContainer    *container;
567     GtkRequisition   button_requisition = { 0, };
568     GtkAllocation    child_allocation;
570     g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (widget));
571     g_return_if_fail (allocation != NULL);
572   
573     grip = GDL_DOCK_ITEM_GRIP (widget);
574     container = GTK_CONTAINER (widget);
576     GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
578     if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
579         child_allocation.x = allocation->x + container->border_width + ALIGN_BORDER;
580     else
581         child_allocation.x = allocation->x + allocation->width - container->border_width;
582     child_allocation.y = allocation->y + container->border_width;
584     gtk_widget_size_request (grip->_priv->close_button, &button_requisition);
586     if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL)
587         child_allocation.x -= button_requisition.width;
589     child_allocation.width = button_requisition.width;
590     child_allocation.height = button_requisition.height;
592     gtk_widget_size_allocate (grip->_priv->close_button, &child_allocation);
594     if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
595         child_allocation.x += button_requisition.width;
596     
598     gtk_widget_size_request (grip->_priv->iconify_button, &button_requisition);
600     if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL)
601         child_allocation.x -= button_requisition.width;
603     child_allocation.width = button_requisition.width;
604     child_allocation.height = button_requisition.height;
606     gtk_widget_size_allocate (grip->_priv->iconify_button, &child_allocation);
608     if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
609         child_allocation.x += button_requisition.width;
611     
612     if (grip->title_window) {
613         GdkRectangle area;
614         
615         /* set layout text */
616         ensure_title_and_icon_pixbuf (grip);
617         pango_layout_set_text (grip->_priv->title_layout, grip->_priv->title, -1);
619         gdl_dock_item_grip_get_title_area (grip, &area);
621         gdk_window_move_resize (grip->title_window,
622                                 area.x, area.y, area.width, area.height);
624         if (grip->_priv->icon_pixbuf)
625             area.width -= gdk_pixbuf_get_width (grip->_priv->icon_pixbuf) + 1;
626             
627         /* ellipsize title if it doesn't fit the title area */
628         ellipsize_layout (grip->_priv->title_layout, area.width);
629     }
632 static void 
633 gdl_dock_item_grip_add (GtkContainer *container,
634                         GtkWidget    *widget)
636     g_warning ("gtk_container_add not implemented for GdlDockItemGrip");
639 static void  
640 gdl_dock_item_grip_remove (GtkContainer *container,
641                            GtkWidget    *widget)
643     g_warning ("gtk_container_remove not implemented for GdlDockItemGrip");
646 static void
647 gdl_dock_item_grip_forall (GtkContainer *container,
648                            gboolean      include_internals,
649                            GtkCallback   callback,
650                            gpointer      callback_data)
652     GdlDockItemGrip *grip;
653     
654     g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (container));
656     grip = GDL_DOCK_ITEM_GRIP (container);
658     if (include_internals) {
659         (* callback) (grip->_priv->close_button, callback_data);
660         (* callback) (grip->_priv->iconify_button, callback_data);
661     }
664 static GtkType
665 gdl_dock_item_grip_child_type (GtkContainer *container)
667     return G_TYPE_NONE;
670 static void
671 gdl_dock_item_grip_class_init (GdlDockItemGripClass *klass)
673     GObjectClass *gobject_class;
674     GtkObjectClass *gtk_object_class;
675     GtkWidgetClass *widget_class;
676     GtkContainerClass *container_class;
678     parent_class = g_type_class_peek_parent (klass);
679     gobject_class = G_OBJECT_CLASS (klass);
680     gtk_object_class = GTK_OBJECT_CLASS (klass);
681     widget_class = GTK_WIDGET_CLASS (klass);
682     container_class = GTK_CONTAINER_CLASS (klass);
684     gobject_class->set_property = gdl_dock_item_grip_set_property;
686     gtk_object_class->destroy = gdl_dock_item_grip_destroy;
688     widget_class->expose_event = gdl_dock_item_grip_expose;
689     widget_class->realize = gdl_dock_item_grip_realize;
690     widget_class->unrealize = gdl_dock_item_grip_unrealize;
691     widget_class->map = gdl_dock_item_grip_map;
692     widget_class->unmap = gdl_dock_item_grip_unmap;
693     widget_class->size_request = gdl_dock_item_grip_size_request;
694     widget_class->size_allocate = gdl_dock_item_grip_size_allocate;
696     container_class->add = gdl_dock_item_grip_add;
697     container_class->remove = gdl_dock_item_grip_remove;
698     container_class->forall = gdl_dock_item_grip_forall;
699     container_class->child_type = gdl_dock_item_grip_child_type;
701     g_object_class_install_property (
702         gobject_class, PROP_ITEM,
703         g_param_spec_object ("item", _("Controlling dock item"),
704                              _("Dockitem which 'owns' this grip"),
705                              GDL_TYPE_DOCK_ITEM,
706                              G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
708     /* initialize stock images */
709     gdl_stock_init ();
712 GtkWidget *
713 gdl_dock_item_grip_new (GdlDockItem *item)
715     GdlDockItemGrip *grip = g_object_new (GDL_TYPE_DOCK_ITEM_GRIP, "item", item,
716                                           NULL);
718     return GTK_WIDGET (grip);