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 };
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 };
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);
61 pango_layout_get_pixel_size (grip->_priv->title_layout, NULL, &alloc_height);
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;
86 g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (grip));
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);
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);
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 }
124 }
126 static gint
127 gdl_dock_item_grip_expose (GtkWidget *widget,
128 GdkEventExpose *event)
129 {
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;
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)
204 {
205 GdlDockItemGrip *grip;
206 gboolean cursor;
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 }
247 }
249 static void
250 gdl_dock_item_grip_destroy (GtkObject *object)
251 {
252 GdlDockItemGrip *grip = GDL_DOCK_ITEM_GRIP (object);
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));
285 }
287 static void
288 gdl_dock_item_grip_set_property (GObject *object,
289 guint prop_id,
290 const GValue *value,
291 GParamSpec *pspec)
292 {
293 GdlDockItemGrip *grip;
295 g_return_if_fail (GDL_IS_DOCK_ITEM_GRIP (object));
297 grip = GDL_DOCK_ITEM_GRIP (object);
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 }
323 }
325 static void
326 gdl_dock_item_grip_close_clicked (GtkWidget *widget,
327 GdlDockItemGrip *grip)
328 {
329 g_return_if_fail (grip->item != NULL);
331 gdl_dock_item_hide_item (grip->item);
332 }
334 static void
335 gdl_dock_item_grip_iconify_clicked (GtkWidget *widget,
336 GdlDockItemGrip *grip)
337 {
338 g_return_if_fail (grip->item != NULL);
340 gdl_dock_item_iconify_item (grip->item);
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));
345 }
347 static void
348 gdl_dock_item_grip_instance_init (GdlDockItemGrip *grip)
349 {
350 GtkWidget *image;
352 GTK_WIDGET_SET_FLAGS (grip, GTK_NO_WINDOW);
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 ();
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 ();
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"));
398 }
400 static void
401 gdl_dock_item_grip_realize (GtkWidget *widget)
402 {
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);
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 }
446 }
448 static void
449 gdl_dock_item_grip_unrealize (GtkWidget *widget)
450 {
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);
460 }
462 static void
463 gdl_dock_item_grip_map (GtkWidget *widget)
464 {
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);
471 }
473 static void
474 gdl_dock_item_grip_unmap (GtkWidget *widget)
475 {
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);
482 }
484 static void
485 gdl_dock_item_grip_size_request (GtkWidget *widget,
486 GtkRequisition *requisition)
487 {
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);
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);
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);
515 requisition->height += layout_height;
517 if (grip->_priv->icon_pixbuf) {
518 requisition->width += gdk_pixbuf_get_width (grip->_priv->icon_pixbuf) + 1;
519 }
520 }
522 #define ELLIPSIS "..."
524 static void
525 ellipsize_layout (PangoLayout *layout, gint width)
526 {
527 PangoLayoutLine *line;
528 PangoLayout *ell;
529 gint h, w, ell_w, x;
530 GString *text;
532 if (width <= 0) {
533 pango_layout_set_text (layout, "", -1);
534 return;
535 }
537 pango_layout_get_pixel_size (layout, &w, &h);
538 if (w <= width) return;
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);
562 }
564 static void
565 gdl_dock_item_grip_size_allocate (GtkWidget *widget,
566 GtkAllocation *allocation)
567 {
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);
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;
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;
615 if (grip->title_window) {
616 GdkRectangle area;
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;
630 /* ellipsize title if it doesn't fit the title area */
631 ellipsize_layout (grip->_priv->title_layout, area.width);
632 }
633 }
635 static void
636 gdl_dock_item_grip_add (GtkContainer *container,
637 GtkWidget *widget)
638 {
639 g_warning ("gtk_container_add not implemented for GdlDockItemGrip");
640 }
642 static void
643 gdl_dock_item_grip_remove (GtkContainer *container,
644 GtkWidget *widget)
645 {
646 g_warning ("gtk_container_remove not implemented for GdlDockItemGrip");
647 }
649 static void
650 gdl_dock_item_grip_forall (GtkContainer *container,
651 gboolean include_internals,
652 GtkCallback callback,
653 gpointer callback_data)
654 {
655 GdlDockItemGrip *grip;
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 }
665 }
667 static GtkType
668 gdl_dock_item_grip_child_type (GtkContainer *container)
669 {
670 return G_TYPE_NONE;
671 }
673 static void
674 gdl_dock_item_grip_class_init (GdlDockItemGripClass *klass)
675 {
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 ();
713 }
715 GtkWidget *
716 gdl_dock_item_grip_new (GdlDockItem *item)
717 {
718 GdlDockItemGrip *grip = g_object_new (GDL_TYPE_DOCK_ITEM_GRIP, "item", item,
719 NULL);
721 return GTK_WIDGET (grip);
722 }