Code

Set merge from trunk
[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     GtkStyle        *bg_style;
134     gint             layout_width;
135     gint             layout_height;
136     gint             text_x;
137     gint             text_y;
138     gboolean         item_or_child_has_focus;
140     grip = GDL_DOCK_ITEM_GRIP (widget);
141     gdl_dock_item_grip_get_title_area (grip, &title_area);
143     /* draw background, highlight it if the dock item or any of its
144      * descendants have focus */
145     bg_style = (gdl_dock_item_or_child_has_focus (grip->item) ?
146                 gtk_widget_get_style (widget)->dark_gc[widget->state] :
147                 gtk_widget_get_style (widget)->mid_gc[widget->state]);
149     gdk_draw_rectangle (GDK_DRAWABLE (widget->window), bg_style, TRUE,
150                         1, 0, widget->allocation.width - 1, widget->allocation.height);
152     if (grip->_priv->icon_pixbuf) {
153         GdkRectangle pixbuf_rect;
154         
155         pixbuf_rect.width = gdk_pixbuf_get_width (grip->_priv->icon_pixbuf);
156         pixbuf_rect.height = gdk_pixbuf_get_height (grip->_priv->icon_pixbuf);
157         if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) {
158             pixbuf_rect.x = title_area.x + title_area.width - pixbuf_rect.width;
159         } else {
160             pixbuf_rect.x = title_area.x;
161             title_area.x += pixbuf_rect.width + 1;
162         }
163         /* shrink title area by the pixbuf width plus a 1px spacing */
164         title_area.width -= pixbuf_rect.width + 1;
165         pixbuf_rect.y = title_area.y + (title_area.height - pixbuf_rect.height) / 2;
167         if (gdk_rectangle_intersect (&event->area, &pixbuf_rect, &expose_area)) {
168             GdkGC *gc;
169             GtkStyle *style;
171             style = gtk_widget_get_style (widget);
172             gc = style->bg_gc[widget->state];
173             gdk_draw_pixbuf (GDK_DRAWABLE (widget->window), gc,
174                              grip->_priv->icon_pixbuf,
175                              0, 0, pixbuf_rect.x, pixbuf_rect.y,
176                              pixbuf_rect.width, pixbuf_rect.height,
177                              GDK_RGB_DITHER_NONE, 0, 0);
178         }
179     }
181     if (gdk_rectangle_intersect (&title_area, &event->area, &expose_area)) {
182         pango_layout_get_pixel_size (grip->_priv->title_layout, &layout_width,
183                                      &layout_height);
185         if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
186             text_x = title_area.x + title_area.width - layout_width;
187         else
188             text_x = title_area.x;
190         text_y = title_area.y + (title_area.height - layout_height) / 2;
192         gtk_paint_layout (widget->style, widget->window, widget->state, TRUE,
193                           &expose_area, widget, NULL, text_x, text_y,
194                           grip->_priv->title_layout);
195     }
197     return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
198 }  
200 static void
201 gdl_dock_item_grip_item_notify (GObject    *master,
202                                 GParamSpec *pspec,
203                                 gpointer    data)
205     GdlDockItemGrip *grip;
206     gboolean cursor;
207     
208     grip = GDL_DOCK_ITEM_GRIP (data);
210     if (strcmp (pspec->name, "stock-id") == 0) {
211         if (grip->_priv->icon_pixbuf) {
212             g_object_unref (grip->_priv->icon_pixbuf);
213             grip->_priv->icon_pixbuf = NULL;
214         }
215         grip->_priv->icon_pixbuf_valid = FALSE;
216         ensure_title_and_icon_pixbuf (grip);
218     } else if (strcmp (pspec->name, "long-name") == 0) {
219         g_free (grip->_priv->title);
220         g_object_unref (grip->_priv->title_layout);
221         grip->_priv->title_layout = NULL;
222         grip->_priv->title = NULL;
223         ensure_title_and_icon_pixbuf (grip);
224         gtk_widget_queue_draw (GTK_WIDGET (grip));
225     } else if (strcmp (pspec->name, "behavior") == 0) {
226         cursor = FALSE;
227         if (grip->_priv->close_button) {
228             if (GDL_DOCK_ITEM_CANT_CLOSE (grip->item)) {
229                 gtk_widget_hide (GTK_WIDGET (grip->_priv->close_button));
230             } else {
231                 gtk_widget_show (GTK_WIDGET (grip->_priv->close_button));
232                 cursor = TRUE;
233             }
234         }
235         if (grip->_priv->iconify_button) {
236             if (GDL_DOCK_ITEM_CANT_ICONIFY (grip->item)) {
237                 gtk_widget_hide (GTK_WIDGET (grip->_priv->iconify_button));
238             } else {
239                 gtk_widget_show (GTK_WIDGET (grip->_priv->iconify_button));
240                 cursor = TRUE;
241             }
242         }
243         if (grip->title_window && !cursor)
244             gdk_window_set_cursor (grip->title_window, NULL);
246     }
249 static void
250 gdl_dock_item_grip_destroy (GtkObject *object)
252     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (object);
253     
254     if (grip->_priv) {
255         GdlDockItemGripPrivate *priv = grip->_priv;
257         if (priv->title_layout) {
258             g_object_unref (priv->title_layout);
259             priv->title_layout = NULL;
260         }
261         g_free (priv->title);
262         priv->title = NULL;
264         if (priv->icon_pixbuf) {
265             g_object_unref (priv->icon_pixbuf);
266             priv->icon_pixbuf = NULL;
267         }
269         if (priv->tooltips) {
270             g_object_unref (priv->tooltips);
271             priv->tooltips = NULL;
272         }
274         if (grip->item)
275             g_signal_handlers_disconnect_by_func (grip->item,
276                                                   gdl_dock_item_grip_item_notify,
277                                                   grip);
278         grip->item = NULL;
280         grip->_priv = NULL;
281         g_free (priv);
282     }
284     GDL_CALL_PARENT (GTK_OBJECT_CLASS, destroy, (object));
287 static void
288 gdl_dock_item_grip_set_property (GObject      *object,
289                                  guint         prop_id,
290                                  const GValue *value,
291                                  GParamSpec   *pspec)
293     GdlDockItemGrip *grip;
295     g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (object));
297     grip = GDL_DOCK_ITEM_GRIP (object);
298     
299     switch (prop_id) {
300         case PROP_ITEM:
301             grip->item = g_value_get_object (value);
302             if (grip->item) {
303                 g_signal_connect (grip->item, "notify::long_name",
304                                   G_CALLBACK (gdl_dock_item_grip_item_notify),
305                                   grip);
306                 g_signal_connect (grip->item, "notify::stock_id",
307                                   G_CALLBACK (gdl_dock_item_grip_item_notify),
308                                   grip);
309                 g_signal_connect (grip->item, "notify::behavior",
310                                   G_CALLBACK (gdl_dock_item_grip_item_notify),
311                                   grip);
313                 if (!GDL_DOCK_ITEM_CANT_CLOSE (grip->item) && grip->_priv->close_button)
314                     gtk_widget_show (grip->_priv->close_button);
315                 if (!GDL_DOCK_ITEM_CANT_ICONIFY (grip->item) && grip->_priv->iconify_button)
316                     gtk_widget_show (grip->_priv->iconify_button);
317             }
318             break;
319         default:
320             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
321             break;
322     }
325 static void
326 gdl_dock_item_grip_close_clicked (GtkWidget       *widget,
327                                   GdlDockItemGrip *grip)
329     g_return_if_fail (grip->item != NULL);
331     gdl_dock_item_hide_item (grip->item);
334 static void
335 gdl_dock_item_grip_iconify_clicked (GtkWidget       *widget,
336                                     GdlDockItemGrip *grip)
338     g_return_if_fail (grip->item != NULL);
340     gdl_dock_item_iconify_item (grip->item);
341     
342     /* Workaround to unhighlight the iconify button. */
343     GTK_BUTTON (grip->_priv->iconify_button)->in_button = FALSE;
344     gtk_button_leave (GTK_BUTTON (grip->_priv->iconify_button));
346   
347 static void
348 gdl_dock_item_grip_instance_init (GdlDockItemGrip *grip)
350     GtkWidget *image;
352     GTK_WIDGET_SET_FLAGS (grip, GTK_NO_WINDOW);
353     
354     grip->_priv = g_new0 (GdlDockItemGripPrivate, 1);
355     grip->_priv->icon_pixbuf_valid = FALSE;
356     grip->_priv->icon_pixbuf = NULL;
357     grip->_priv->title_layout = NULL;
359     gtk_widget_push_composite_child ();
360     grip->_priv->close_button = gtk_button_new ();
361     gtk_widget_pop_composite_child ();
362     
363     GTK_WIDGET_UNSET_FLAGS (grip->_priv->close_button, GTK_CAN_FOCUS);
364     gtk_widget_set_parent (grip->_priv->close_button, GTK_WIDGET (grip));
365     gtk_button_set_relief (GTK_BUTTON (grip->_priv->close_button), GTK_RELIEF_NONE);
366     gtk_widget_show (grip->_priv->close_button);
368     image = gtk_image_new_from_stock (GDL_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
369     gtk_container_add (GTK_CONTAINER (grip->_priv->close_button), image);
370     gtk_widget_show (image);
372     g_signal_connect (G_OBJECT (grip->_priv->close_button), "clicked",
373                       G_CALLBACK (gdl_dock_item_grip_close_clicked), grip);
375     gtk_widget_push_composite_child ();
376     grip->_priv->iconify_button = gtk_button_new ();
377     gtk_widget_pop_composite_child ();
378     
379     GTK_WIDGET_UNSET_FLAGS (grip->_priv->iconify_button, GTK_CAN_FOCUS);
380     gtk_widget_set_parent (grip->_priv->iconify_button, GTK_WIDGET (grip));
381     gtk_button_set_relief (GTK_BUTTON (grip->_priv->iconify_button), GTK_RELIEF_NONE);
382     gtk_widget_show (grip->_priv->iconify_button);
384     image = gtk_image_new_from_stock (GDL_STOCK_MENU_RIGHT, GTK_ICON_SIZE_MENU);
385     gtk_container_add (GTK_CONTAINER (grip->_priv->iconify_button), image);
386     gtk_widget_show (image);
388     g_signal_connect (G_OBJECT (grip->_priv->iconify_button), "clicked",
389                       G_CALLBACK (gdl_dock_item_grip_iconify_clicked), grip);
391     grip->_priv->tooltips = gtk_tooltips_new ();
392     g_object_ref (grip->_priv->tooltips);
393     gtk_object_sink (GTK_OBJECT (grip->_priv->tooltips));
394     gtk_tooltips_set_tip (grip->_priv->tooltips, grip->_priv->iconify_button,
395                           _("Iconify"), _("Iconify this dock"));
396     gtk_tooltips_set_tip (grip->_priv->tooltips, grip->_priv->close_button,
397                           _("Close"), _("Close this dock"));
400 static void
401 gdl_dock_item_grip_realize (GtkWidget *widget)
403     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (widget);
405     GTK_WIDGET_CLASS (parent_class)->realize (widget);
407     if (!grip->title_window) {
408         GdkWindowAttr  attributes;
409         GdkRectangle   area;
410         GdkCursor     *cursor;
412         ensure_title_and_icon_pixbuf (grip);
413         gdl_dock_item_grip_get_title_area (grip, &area);
415         attributes.x                 = area.x;
416         attributes.y                 = area.y;
417         attributes.width             = area.width;
418         attributes.height            = area.height;
419         attributes.window_type       = GDK_WINDOW_TEMP;
420         attributes.wclass            = GDK_INPUT_ONLY;
421         attributes.override_redirect = TRUE;
422         attributes.event_mask        = (GDK_BUTTON_PRESS_MASK   |
423                                         GDK_BUTTON_RELEASE_MASK |
424                                         GDK_BUTTON_MOTION_MASK  |
425                                         gtk_widget_get_events (widget));
427         grip->title_window = gdk_window_new (gtk_widget_get_parent_window (widget),
428                                              &attributes,
429                                              (GDK_WA_X |
430                                               GDK_WA_Y |
431                                               GDK_WA_NOREDIR));
433         gdk_window_set_user_data (grip->title_window, widget);
434  
435         if (GDL_DOCK_ITEM_CANT_CLOSE (grip->item))
436             cursor = NULL;
437         else if (GDL_DOCK_ITEM_CANT_ICONIFY (grip->item))
438             cursor = NULL;
439         else 
440             cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
441                                              GDK_HAND2);
442         gdk_window_set_cursor (grip->title_window, cursor);
443         if (cursor)
444             gdk_cursor_unref (cursor);
445     }
448 static void
449 gdl_dock_item_grip_unrealize (GtkWidget *widget)
451     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (widget);
453     if (grip->title_window) {
454         gdk_window_set_user_data (grip->title_window, NULL);
455         gdk_window_destroy (grip->title_window);
456         grip->title_window = NULL;
457     }
459     GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
462 static void
463 gdl_dock_item_grip_map (GtkWidget *widget)
465     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (widget);
467     GTK_WIDGET_CLASS (parent_class)->map (widget);
469     if (grip->title_window)
470         gdk_window_show (grip->title_window);
473 static void
474 gdl_dock_item_grip_unmap (GtkWidget *widget)
476     GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (widget);
478     if (grip->title_window)
479         gdk_window_hide (grip->title_window);
481     GTK_WIDGET_CLASS (parent_class)->unmap (widget);
484 static void
485 gdl_dock_item_grip_size_request (GtkWidget      *widget,
486                                  GtkRequisition *requisition)
488     GtkRequisition   child_requisition;
489     GtkContainer    *container;
490     GdlDockItemGrip *grip;
491     gint             layout_height;
493     g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (widget));
494     g_return_if_fail (requisition != NULL);
496     container = GTK_CONTAINER (widget);
497     grip = GDL_DOCK_ITEM_GRIP (widget);
498     
499     requisition->width = container->border_width * 2 + ALIGN_BORDER;
500     requisition->height = container->border_width * 2;
502     ensure_title_and_icon_pixbuf (grip);
503     pango_layout_get_pixel_size (grip->_priv->title_layout, NULL, &layout_height);
505     gtk_widget_size_request (grip->_priv->close_button, &child_requisition);
507     requisition->width += child_requisition.width;
508     layout_height = MAX (layout_height, child_requisition.height);
509     
510     gtk_widget_size_request (grip->_priv->iconify_button, &child_requisition);
512     requisition->width += child_requisition.width;
513     layout_height = MAX (layout_height, child_requisition.height);
514     
515     requisition->height += layout_height;
517     if (grip->_priv->icon_pixbuf) {
518         requisition->width += gdk_pixbuf_get_width (grip->_priv->icon_pixbuf) + 1;
519     }
522 #define ELLIPSIS "..."
524 static void
525 ellipsize_layout (PangoLayout *layout, gint width)
527     PangoLayoutLine *line;
528     PangoLayout *ell;
529     gint h, w, ell_w, x;
530     GString *text;
531     
532     if (width <= 0) {
533         pango_layout_set_text (layout, "", -1);
534         return;
535     }
536     
537     pango_layout_get_pixel_size (layout, &w, &h);
538     if (w <= width) return;
539     
540     /* calculate ellipsis width */
541     ell = pango_layout_copy (layout);
542     pango_layout_set_text (ell, ELLIPSIS, -1);
543     pango_layout_get_pixel_size (ell, &ell_w, NULL);
544     g_object_unref (ell);
546     if (width < ell_w) {
547         /* not even ellipsis fits, so hide the text */
548         pango_layout_set_text (layout, "", -1);
549         return;
550     }
552     /* shrink total available width by the width of the ellipsis */
553     width -= ell_w;
554     line = pango_layout_get_line (layout, 0);
555     text = g_string_new (pango_layout_get_text (layout));
556     if (pango_layout_line_x_to_index (line, width * PANGO_SCALE, &x, NULL)) {
557         g_string_set_size (text, x);
558         g_string_append (text, ELLIPSIS);
559         pango_layout_set_text (layout, text->str, -1);
560     }
561     g_string_free (text, TRUE);
564 static void
565 gdl_dock_item_grip_size_allocate (GtkWidget     *widget,
566                                   GtkAllocation *allocation)
568     GdlDockItemGrip *grip;
569     GtkContainer    *container;
570     GtkRequisition   button_requisition = { 0, };
571     GtkAllocation    child_allocation;
573     g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (widget));
574     g_return_if_fail (allocation != NULL);
575   
576     grip = GDL_DOCK_ITEM_GRIP (widget);
577     container = GTK_CONTAINER (widget);
579     GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
581     if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
582         child_allocation.x = allocation->x + container->border_width + ALIGN_BORDER;
583     else
584         child_allocation.x = allocation->x + allocation->width - container->border_width;
585     child_allocation.y = allocation->y + container->border_width;
587     gtk_widget_size_request (grip->_priv->close_button, &button_requisition);
589     if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL)
590         child_allocation.x -= button_requisition.width;
592     child_allocation.width = button_requisition.width;
593     child_allocation.height = button_requisition.height;
595     gtk_widget_size_allocate (grip->_priv->close_button, &child_allocation);
597     if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
598         child_allocation.x += button_requisition.width;
599     
601     gtk_widget_size_request (grip->_priv->iconify_button, &button_requisition);
603     if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL)
604         child_allocation.x -= button_requisition.width;
606     child_allocation.width = button_requisition.width;
607     child_allocation.height = button_requisition.height;
609     gtk_widget_size_allocate (grip->_priv->iconify_button, &child_allocation);
611     if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
612         child_allocation.x += button_requisition.width;
614     
615     if (grip->title_window) {
616         GdkRectangle area;
617         
618         /* set layout text */
619         ensure_title_and_icon_pixbuf (grip);
620         pango_layout_set_text (grip->_priv->title_layout, grip->_priv->title, -1);
622         gdl_dock_item_grip_get_title_area (grip, &area);
624         gdk_window_move_resize (grip->title_window,
625                                 area.x, area.y, area.width, area.height);
627         if (grip->_priv->icon_pixbuf)
628             area.width -= gdk_pixbuf_get_width (grip->_priv->icon_pixbuf) + 1;
629             
630         /* ellipsize title if it doesn't fit the title area */
631         ellipsize_layout (grip->_priv->title_layout, area.width);
632     }
635 static void 
636 gdl_dock_item_grip_add (GtkContainer *container,
637                         GtkWidget    *widget)
639     g_warning ("gtk_container_add not implemented for GdlDockItemGrip");
642 static void  
643 gdl_dock_item_grip_remove (GtkContainer *container,
644                            GtkWidget    *widget)
646     g_warning ("gtk_container_remove not implemented for GdlDockItemGrip");
649 static void
650 gdl_dock_item_grip_forall (GtkContainer *container,
651                            gboolean      include_internals,
652                            GtkCallback   callback,
653                            gpointer      callback_data)
655     GdlDockItemGrip *grip;
656     
657     g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (container));
659     grip = GDL_DOCK_ITEM_GRIP (container);
661     if (include_internals) {
662         (* callback) (grip->_priv->close_button, callback_data);
663         (* callback) (grip->_priv->iconify_button, callback_data);
664     }
667 static GtkType
668 gdl_dock_item_grip_child_type (GtkContainer *container)
670     return G_TYPE_NONE;
673 static void
674 gdl_dock_item_grip_class_init (GdlDockItemGripClass *klass)
676     GObjectClass *gobject_class;
677     GtkObjectClass *gtk_object_class;
678     GtkWidgetClass *widget_class;
679     GtkContainerClass *container_class;
681     parent_class = g_type_class_peek_parent (klass);
682     gobject_class = G_OBJECT_CLASS (klass);
683     gtk_object_class = GTK_OBJECT_CLASS (klass);
684     widget_class = GTK_WIDGET_CLASS (klass);
685     container_class = GTK_CONTAINER_CLASS (klass);
687     gobject_class->set_property = gdl_dock_item_grip_set_property;
689     gtk_object_class->destroy = gdl_dock_item_grip_destroy;
691     widget_class->expose_event = gdl_dock_item_grip_expose;
692     widget_class->realize = gdl_dock_item_grip_realize;
693     widget_class->unrealize = gdl_dock_item_grip_unrealize;
694     widget_class->map = gdl_dock_item_grip_map;
695     widget_class->unmap = gdl_dock_item_grip_unmap;
696     widget_class->size_request = gdl_dock_item_grip_size_request;
697     widget_class->size_allocate = gdl_dock_item_grip_size_allocate;
699     container_class->add = gdl_dock_item_grip_add;
700     container_class->remove = gdl_dock_item_grip_remove;
701     container_class->forall = gdl_dock_item_grip_forall;
702     container_class->child_type = gdl_dock_item_grip_child_type;
704     g_object_class_install_property (
705         gobject_class, PROP_ITEM,
706         g_param_spec_object ("item", _("Controlling dock item"),
707                              _("Dockitem which 'owns' this grip"),
708                              GDL_TYPE_DOCK_ITEM,
709                              G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
711     /* initialize stock images */
712     gdl_stock_init ();
715 GtkWidget *
716 gdl_dock_item_grip_new (GdlDockItem *item)
718     GdlDockItemGrip *grip = g_object_new (GDL_TYPE_DOCK_ITEM_GRIP, "item", item,
719                                           NULL);
721     return GTK_WIDGET (grip);