3 * Copyright (C) 2002 Anders Carlsson <andersca@codefactory.se>
4 * Copyright (C) 2002 James Henstridge <james@daa.com.au>
5 * Copyright (C) 2003 Soeren Sandmann <sandmann@daimi.au.dk>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 #include "gtktoolbutton.h"
24 #include "gtkbutton.h"
26 #include "gtkiconfactory.h"
28 #include "gtkimagemenuitem.h"
33 #include "gtktoolbar.h"
37 #define MENU_ID "gtk-tool-button-menu-id"
53 static void gtk_tool_button_init (GtkToolButton *button,
54 GtkToolButtonClass *klass);
55 static void gtk_tool_button_class_init (GtkToolButtonClass *klass);
56 static void gtk_tool_button_size_request (GtkWidget *widget,
57 GtkRequisition *requisition);
58 static void gtk_tool_button_size_allocate (GtkWidget *widget,
59 GtkAllocation *allocation);
60 static void gtk_tool_button_set_property (GObject *object,
64 static void gtk_tool_button_get_property (GObject *object,
68 static void gtk_tool_button_finalize (GObject *object);
70 static void gtk_tool_button_toolbar_reconfigured (GtkToolItem *tool_item);
71 static gboolean gtk_tool_button_create_menu_proxy (GtkToolItem *item);
72 static void button_clicked (GtkWidget *widget,
73 GtkToolButton *button);
75 static void gtk_tool_button_construct_contents (GtkToolItem *tool_item);
77 static GObjectClass *parent_class = NULL;
78 static guint toolbutton_signals[LAST_SIGNAL] = { 0 };
81 gtk_tool_button_get_type (void)
83 static GtkType type = 0;
87 static const GTypeInfo type_info =
89 sizeof (GtkToolButtonClass),
91 (GBaseFinalizeFunc) NULL,
92 (GClassInitFunc) gtk_tool_button_class_init,
93 (GClassFinalizeFunc) NULL,
95 sizeof (GtkToolButton),
97 (GInstanceInitFunc) gtk_tool_button_init,
100 type = g_type_register_static (GTK_TYPE_TOOL_ITEM,
108 gtk_tool_button_class_init (GtkToolButtonClass *klass)
110 GObjectClass *object_class;
111 GtkWidgetClass *widget_class;
112 GtkToolItemClass *tool_item_class;
114 parent_class = g_type_class_peek_parent (klass);
116 object_class = (GObjectClass *)klass;
117 widget_class = (GtkWidgetClass *)klass;
118 tool_item_class = (GtkToolItemClass *)klass;
120 object_class->set_property = gtk_tool_button_set_property;
121 object_class->get_property = gtk_tool_button_get_property;
122 object_class->finalize = gtk_tool_button_finalize;
124 widget_class->size_request = gtk_tool_button_size_request;
125 widget_class->size_allocate = gtk_tool_button_size_allocate;
127 tool_item_class->create_menu_proxy = gtk_tool_button_create_menu_proxy;
128 tool_item_class->toolbar_reconfigured = gtk_tool_button_toolbar_reconfigured;
130 klass->button_type = GTK_TYPE_BUTTON;
132 g_object_class_install_property (object_class,
134 g_param_spec_string ("label",
136 _("Text to show in the item."),
139 g_object_class_install_property (object_class,
141 g_param_spec_boolean ("use_underline",
143 _("Interpret underlines in the item label"),
146 g_object_class_install_property (object_class,
148 g_param_spec_object ("label_widget",
150 _("Widget to use as the item label"),
153 g_object_class_install_property (object_class,
155 g_param_spec_string ("stock_id",
157 _("The stock icon displayed on the item"),
160 g_object_class_install_property (object_class,
162 g_param_spec_object ("icon_widget",
164 _("Icon widget to display in the item"),
168 toolbutton_signals[CLICKED] =
169 g_signal_new ("clicked",
170 G_OBJECT_CLASS_TYPE (klass),
172 G_STRUCT_OFFSET (GtkToolButtonClass, clicked),
174 g_cclosure_marshal_VOID__VOID,
179 gtk_tool_button_init (GtkToolButton *button,
180 GtkToolButtonClass *klass)
182 GtkToolItem *toolitem = GTK_TOOL_ITEM (button);
184 toolitem->homogeneous = TRUE;
187 button->button = g_object_new (klass->button_type, NULL);
188 gtk_button_set_focus_on_click (GTK_BUTTON (button->button), FALSE);
189 g_signal_connect_object (button->button, "clicked",
190 G_CALLBACK (button_clicked), button, 0);
192 gtk_container_add (GTK_CONTAINER (button), button->button);
193 gtk_widget_show (button->button);
197 gtk_tool_button_size_request (GtkWidget *widget,
198 GtkRequisition *requisition)
200 GtkWidget *child = GTK_BIN (widget)->child;
202 if (child && GTK_WIDGET_VISIBLE (child))
204 gtk_widget_size_request (child, requisition);
208 requisition->width = 0;
209 requisition->height = 0;
212 requisition->width += GTK_CONTAINER (widget)->border_width * 2;
213 requisition->height += GTK_CONTAINER (widget)->border_width * 2;
217 gtk_tool_button_size_allocate (GtkWidget *widget,
218 GtkAllocation *allocation)
220 GtkToolItem *toolitem = GTK_TOOL_ITEM (widget);
221 GtkAllocation child_allocation;
223 GtkWidget *child = GTK_BIN (widget)->child;
225 widget->allocation = *allocation;
226 border_width = GTK_CONTAINER (widget)->border_width;
228 if (toolitem->drag_window && GTK_WIDGET_REALIZED (widget))
229 gdk_window_move_resize (toolitem->drag_window,
230 widget->allocation.x + border_width,
231 widget->allocation.y + border_width,
232 widget->allocation.width - border_width * 2,
233 widget->allocation.height - border_width * 2);
235 if (child && GTK_WIDGET_VISIBLE (child))
237 child_allocation.x = allocation->x + border_width;
238 child_allocation.y = allocation->y + border_width;
239 child_allocation.width = allocation->width - 2 * border_width;
240 child_allocation.height = allocation->height - 2 * border_width;
242 gtk_widget_size_allocate (child, &child_allocation);
247 gtk_tool_button_construct_contents (GtkToolItem *tool_item)
249 GtkToolButton *button = GTK_TOOL_BUTTON (tool_item);
250 GtkWidget *label = NULL;
251 GtkWidget *icon = NULL;
252 GtkToolbarStyle style;
253 gboolean need_label = FALSE;
254 gboolean need_icon = FALSE;
255 GtkIconSize icon_size;
256 GtkWidget *box = NULL;
258 if (gtk_tool_item_get_proxy_menu_item (tool_item, MENU_ID))
260 /* Remove item, so it will be recreated on the next
261 * create_proxy_menu_item()
263 gtk_tool_item_set_proxy_menu_item (tool_item, MENU_ID, NULL);
266 if (button->icon_widget && button->icon_widget->parent)
268 gtk_container_remove (GTK_CONTAINER (button->icon_widget->parent),
269 button->icon_widget);
272 if (button->label_widget && button->label_widget->parent)
274 gtk_container_remove (GTK_CONTAINER (button->label_widget->parent),
275 button->label_widget);
278 if (GTK_BIN (button->button)->child)
280 gtk_container_remove (GTK_CONTAINER (button->button),
281 GTK_BIN (button->button)->child);
284 style = gtk_tool_item_get_toolbar_style (GTK_TOOL_ITEM (button));
286 if (style != GTK_TOOLBAR_TEXT)
289 if (style != GTK_TOOLBAR_ICONS)
294 if (button->label_widget)
296 label = button->label_widget;
300 GtkStockItem stock_item;
301 gboolean elide = TRUE;
304 if (button->label_text)
306 label_text = button->label_text;
307 elide = button->use_underline;
309 else if (button->stock_id && gtk_stock_lookup (button->stock_id, &stock_item))
310 label_text = stock_item.label;
315 label_text = _gtk_toolbar_elide_underscores (label_text);
317 label_text = g_strdup (label_text);
319 label = gtk_label_new (label_text);
323 gtk_widget_show (label);
327 icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (button));
330 if (button->icon_widget)
332 icon = button->icon_widget;
334 if (GTK_IS_IMAGE (icon))
336 GtkImage *image = GTK_IMAGE (icon);
337 GtkImageType storage_type = gtk_image_get_storage_type (image);
339 if (storage_type == GTK_IMAGE_STOCK)
342 gtk_image_get_stock (image, &stock_id, NULL);
344 icon = gtk_image_new_from_stock (stock_id, icon_size);
345 gtk_widget_show (icon);
347 else if (storage_type == GTK_IMAGE_ICON_SET)
349 GtkIconSet *icon_set;
350 gtk_image_get_icon_set (image, &icon_set, NULL);
352 icon = gtk_image_new_from_icon_set (icon_set, icon_size);
353 gtk_widget_show (icon);
357 else if (button->stock_id)
359 icon = gtk_image_new_from_stock (button->stock_id, icon_size);
360 gtk_widget_show (icon);
366 case GTK_TOOLBAR_ICONS:
368 gtk_container_add (GTK_CONTAINER (button->button), icon);
371 case GTK_TOOLBAR_BOTH:
372 box = gtk_vbox_new (FALSE, 0);
373 gtk_box_pack_start (GTK_BOX (box), icon, TRUE, TRUE, 0);
374 gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 0);
375 gtk_container_add (GTK_CONTAINER (button->button), box);
378 case GTK_TOOLBAR_BOTH_HORIZ:
379 box = gtk_hbox_new (FALSE, 0);
380 gtk_box_pack_start (GTK_BOX (box), icon, FALSE, TRUE, 0);
381 gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
382 gtk_container_add (GTK_CONTAINER (button->button), box);
385 case GTK_TOOLBAR_TEXT:
386 gtk_container_add (GTK_CONTAINER (button->button), label);
391 gtk_widget_show (box);
393 gtk_button_set_relief (GTK_BUTTON (button->button),
394 gtk_tool_item_get_relief_style (GTK_TOOL_ITEM (button)));
396 gtk_widget_queue_resize (GTK_WIDGET (button));
400 gtk_tool_button_set_property (GObject *object,
405 GtkToolButton *button = GTK_TOOL_BUTTON (object);
410 gtk_tool_button_set_label (button, g_value_get_string (value));
412 case PROP_USE_UNDERLINE:
413 gtk_tool_button_set_use_underline (button, g_value_get_boolean (value));
415 case PROP_LABEL_WIDGET:
416 gtk_tool_button_set_label_widget (button, g_value_get_object (value));
419 gtk_tool_button_set_stock_id (button, g_value_get_string (value));
421 case PROP_ICON_WIDGET:
422 gtk_tool_button_set_icon_widget (button, g_value_get_object (value));
425 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
430 gtk_tool_button_get_property (GObject *object,
435 GtkToolButton *button = GTK_TOOL_BUTTON (object);
440 g_value_set_string (value, gtk_tool_button_get_label (button));
442 case PROP_LABEL_WIDGET:
443 g_value_set_object (value, gtk_tool_button_get_label_widget (button));
445 case PROP_USE_UNDERLINE:
446 g_value_set_boolean (value, gtk_tool_button_get_use_underline (button));
449 g_value_set_string (value, button->stock_id);
451 case PROP_ICON_WIDGET:
452 g_value_set_object (value, button->icon_widget);
455 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
460 gtk_tool_button_finalize (GObject *object)
462 GtkToolButton *button = GTK_TOOL_BUTTON (object);
464 g_free (button->stock_id);
465 button->stock_id = NULL;
467 parent_class->finalize (object);
471 gtk_tool_button_create_menu_proxy (GtkToolItem *item)
473 GtkToolButton *button = GTK_TOOL_BUTTON (item);
474 GtkWidget *menu_item;
475 GtkWidget *menu_image = NULL;
476 GtkStockItem stock_item;
477 gboolean use_mnemonic = TRUE;
478 const char *label = "";
480 if (button->label_widget && GTK_IS_LABEL (button->label_widget))
481 label = gtk_label_get_label (GTK_LABEL (button->label_widget));
482 else if (button->label_text)
484 label = button->label_text;
485 use_mnemonic = button->use_underline;
487 else if (button->stock_id && gtk_stock_lookup (button->stock_id, &stock_item))
488 label = stock_item.label;
491 menu_item = gtk_image_menu_item_new_with_mnemonic (label);
493 menu_item = gtk_image_menu_item_new_with_label (label);
495 if (button->icon_widget && GTK_IS_IMAGE (button->icon_widget))
497 GtkImage *image = GTK_IMAGE (button->icon_widget);
498 GtkImageType storage_type = gtk_image_get_storage_type (image);
500 if (storage_type == GTK_IMAGE_STOCK)
503 gtk_image_get_stock (image, &stock_id, NULL);
504 menu_image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU);
506 else if (storage_type == GTK_IMAGE_ICON_SET)
508 GtkIconSet *icon_set;
509 gtk_image_get_icon_set (image, &icon_set, NULL);
510 menu_image = gtk_image_new_from_icon_set (icon_set, GTK_ICON_SIZE_MENU);
513 else if (button->stock_id)
515 menu_image = gtk_image_new_from_stock (button->stock_id, GTK_ICON_SIZE_MENU);
519 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), menu_image);
521 g_signal_connect_closure_by_id (menu_item,
522 g_signal_lookup ("activate", G_OBJECT_TYPE (menu_item)), 0,
523 g_cclosure_new_object_swap (G_CALLBACK (gtk_button_clicked),
524 G_OBJECT (GTK_TOOL_BUTTON (button)->button)),
527 gtk_tool_item_set_proxy_menu_item (GTK_TOOL_ITEM (button), MENU_ID, menu_item);
533 button_clicked (GtkWidget *widget,
534 GtkToolButton *button)
536 g_signal_emit_by_name (button, "clicked");
540 gtk_tool_button_toolbar_reconfigured (GtkToolItem *tool_item)
542 gtk_tool_button_construct_contents (tool_item);
546 gtk_tool_button_new_from_stock (const gchar *stock_id)
548 GtkToolButton *button;
550 g_return_val_if_fail (stock_id != NULL, NULL);
552 button = g_object_new (GTK_TYPE_TOOL_BUTTON,
553 "stock_id", stock_id,
556 return GTK_TOOL_ITEM (button);
560 gtk_tool_button_new (const gchar *label,
561 GtkWidget *icon_widget)
563 GtkToolButton *button;
565 button = g_object_new (GTK_TYPE_TOOL_BUTTON,
569 gtk_tool_button_set_label (button, label);
572 gtk_tool_button_set_icon_widget (button, icon_widget);
574 return GTK_TOOL_ITEM (button);
578 gtk_tool_button_set_label (GtkToolButton *button,
583 g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
585 old_label = button->label_text;
587 button->label_text = g_strdup (label);
588 gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
590 g_object_notify (G_OBJECT (button), "label");
596 G_CONST_RETURN gchar *
597 gtk_tool_button_get_label (GtkToolButton *button)
599 g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
601 return button->label_text;
605 gtk_tool_button_set_use_underline (GtkToolButton *button,
606 gboolean use_underline)
608 g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
610 use_underline = use_underline != FALSE;
612 if (use_underline != button->use_underline)
614 button->use_underline = use_underline;
616 gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
618 g_object_notify (G_OBJECT (button), "use_underline");
623 gtk_tool_button_get_use_underline (GtkToolButton *button)
625 g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), FALSE);
627 return button->use_underline;
631 gtk_tool_button_set_stock_id (GtkToolButton *button,
632 const gchar *stock_id)
636 g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
638 old_stock_id = button->stock_id;
640 button->stock_id = g_strdup (stock_id);
641 gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
643 g_object_notify (G_OBJECT (button), "stock_id");
645 g_free (old_stock_id);
648 G_CONST_RETURN gchar *
649 gtk_tool_button_get_stock_id (GtkToolButton *button)
651 g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
653 return button->stock_id;
657 gtk_tool_button_set_icon_widget (GtkToolButton *button,
660 g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
661 g_return_if_fail (icon == NULL || GTK_IS_WIDGET (icon));
663 if (icon != button->icon_widget)
665 if (button->icon_widget)
666 g_object_unref (G_OBJECT (button->icon_widget));
671 gtk_object_sink (GTK_OBJECT (icon));
674 button->icon_widget = icon;
676 gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
678 g_object_notify (G_OBJECT (button), "icon_widget");
683 gtk_tool_button_set_label_widget (GtkToolButton *button,
684 GtkWidget *label_widget)
686 g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
687 g_return_if_fail (label_widget == NULL || GTK_IS_WIDGET (label_widget));
689 if (label_widget != button->label_widget)
691 if (button->label_widget)
692 g_object_unref (button->label_widget);
696 g_object_ref (label_widget);
697 gtk_object_sink (GTK_OBJECT (label_widget));
700 button->label_widget = label_widget;
702 gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
704 g_object_notify (G_OBJECT (button), "label_widget");
709 gtk_tool_button_get_label_widget (GtkToolButton *button)
711 g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
713 return button->label_widget;
717 gtk_tool_button_get_icon_widget (GtkToolButton *button)
719 g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
721 return button->icon_widget;