3 * Copyright (C) 2002 Anders Carlsson <andersca@gnome.org>
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.
24 #include "gtktoolbutton.h"
25 #include "gtkbutton.h"
27 #include "gtkiconfactory.h"
29 #include "gtkimagemenuitem.h"
34 #include "gtktoolbar.h"
35 #include "gtkactivatable.h"
36 #include "gtkprivate.h"
42 * SECTION:gtktoolbutton
43 * @Short_description: A GtkToolItem subclass that displays buttons
44 * @Title: GtkToolButton
45 * @See_also: #GtkToolbar, #GtkMenuToolButton, #GtkToggleToolButton,
46 * #GtkRadioToolButton, #GtkSeparatorToolItem
48 * #GtkToolButton<!-- -->s are #GtkToolItems containing buttons.
50 * Use gtk_tool_button_new() to create a new #GtkToolButton. Use
51 * gtk_tool_button_new_with_stock() to create a #GtkToolButton
52 * containing a stock item.
54 * The label of a #GtkToolButton is determined by the properties
55 * #GtkToolButton:label-widget, #GtkToolButton:label, and
56 * #GtkToolButton:stock-id. If #GtkToolButton:label-widget is
57 * non-%NULL, then that widget is used as the label. Otherwise, if
58 * #GtkToolButton:label is non-%NULL, that string is used as the label.
59 * Otherwise, if #GtkToolButton:stock-id is non-%NULL, the label is
60 * determined by the stock item. Otherwise, the button does not have a label.
62 * The icon of a #GtkToolButton is determined by the properties
63 * #GtkToolButton:icon-widget and #GtkToolButton:stock-id. If
64 * #GtkToolButton:icon-widget is non-%NULL, then
65 * that widget is used as the icon. Otherwise, if #GtkToolButton:stock-id is
66 * non-%NULL, the icon is determined by the stock item. Otherwise,
67 * the button does not have a icon.
71 #define MENU_ID "gtk-tool-button-menu-id"
88 static void gtk_tool_button_init (GtkToolButton *button,
89 GtkToolButtonClass *klass);
90 static void gtk_tool_button_class_init (GtkToolButtonClass *klass);
91 static void gtk_tool_button_set_property (GObject *object,
95 static void gtk_tool_button_get_property (GObject *object,
99 static void gtk_tool_button_property_notify (GObject *object,
101 static void gtk_tool_button_finalize (GObject *object);
103 static void gtk_tool_button_toolbar_reconfigured (GtkToolItem *tool_item);
104 static gboolean gtk_tool_button_create_menu_proxy (GtkToolItem *item);
105 static void button_clicked (GtkWidget *widget,
106 GtkToolButton *button);
107 static void gtk_tool_button_style_updated (GtkWidget *widget);
109 static void gtk_tool_button_construct_contents (GtkToolItem *tool_item);
111 static void gtk_tool_button_activatable_interface_init (GtkActivatableIface *iface);
112 static void gtk_tool_button_update (GtkActivatable *activatable,
114 const gchar *property_name);
115 static void gtk_tool_button_sync_action_properties (GtkActivatable *activatable,
119 struct _GtkToolButtonPrivate
126 GtkWidget *label_widget;
127 GtkWidget *icon_widget;
129 GtkSizeGroup *text_size_group;
131 guint use_underline : 1;
132 guint contents_invalid : 1;
135 static GObjectClass *parent_class = NULL;
136 static GtkActivatableIface *parent_activatable_iface;
137 static guint toolbutton_signals[LAST_SIGNAL] = { 0 };
141 gtk_tool_button_get_type (void)
143 static GType type = 0;
147 const GInterfaceInfo activatable_info =
149 (GInterfaceInitFunc) gtk_tool_button_activatable_interface_init,
150 (GInterfaceFinalizeFunc) NULL,
154 type = g_type_register_static_simple (GTK_TYPE_TOOL_ITEM,
156 sizeof (GtkToolButtonClass),
157 (GClassInitFunc) gtk_tool_button_class_init,
158 sizeof (GtkToolButton),
159 (GInstanceInitFunc) gtk_tool_button_init,
162 g_type_add_interface_static (type, GTK_TYPE_ACTIVATABLE,
169 gtk_tool_button_class_init (GtkToolButtonClass *klass)
171 GObjectClass *object_class;
172 GtkWidgetClass *widget_class;
173 GtkToolItemClass *tool_item_class;
175 parent_class = g_type_class_peek_parent (klass);
177 object_class = (GObjectClass *)klass;
178 widget_class = (GtkWidgetClass *)klass;
179 tool_item_class = (GtkToolItemClass *)klass;
181 object_class->set_property = gtk_tool_button_set_property;
182 object_class->get_property = gtk_tool_button_get_property;
183 object_class->notify = gtk_tool_button_property_notify;
184 object_class->finalize = gtk_tool_button_finalize;
186 widget_class->style_updated = gtk_tool_button_style_updated;
188 tool_item_class->create_menu_proxy = gtk_tool_button_create_menu_proxy;
189 tool_item_class->toolbar_reconfigured = gtk_tool_button_toolbar_reconfigured;
191 klass->button_type = GTK_TYPE_BUTTON;
193 /* Properties are interpreted like this:
195 * - if the tool button has an icon_widget, then that widget
196 * will be used as the icon. Otherwise, if the tool button
197 * has a stock id, the corresponding stock icon will be
198 * used. Otherwise, if the tool button has an icon name,
199 * the corresponding icon from the theme will be used.
200 * Otherwise, the tool button will not have an icon.
202 * - if the tool button has a label_widget then that widget
203 * will be used as the label. Otherwise, if the tool button
204 * has a label text, that text will be used as label. Otherwise,
205 * if the toolbutton has a stock id, the corresponding text
206 * will be used as label. Otherwise, if the tool button has
207 * an icon name, the corresponding icon name from the theme will
208 * be used. Otherwise, the toolbutton will have an empty label.
210 * - The use_underline property only has an effect when the label
211 * on the toolbutton comes from the label property (ie. not from
212 * label_widget or from stock_id).
214 * In that case, if use_underline is set,
216 * - underscores are removed from the label text before
217 * the label is shown on the toolbutton unless the
218 * underscore is followed by another underscore
220 * - an underscore indicates that the next character when
221 * used in the overflow menu should be used as a
224 * In short: use_underline = TRUE means that the label text has
225 * the form "_Open" and the toolbar should take appropriate
229 g_object_class_install_property (object_class,
231 g_param_spec_string ("label",
233 P_("Text to show in the item."),
235 GTK_PARAM_READWRITE));
236 g_object_class_install_property (object_class,
238 g_param_spec_boolean ("use-underline",
240 P_("If set, an underline in the label property indicates that the next character should be used for the mnemonic accelerator key in the overflow menu"),
242 GTK_PARAM_READWRITE));
243 g_object_class_install_property (object_class,
245 g_param_spec_object ("label-widget",
247 P_("Widget to use as the item label"),
249 GTK_PARAM_READWRITE));
250 g_object_class_install_property (object_class,
252 g_param_spec_string ("stock-id",
254 P_("The stock icon displayed on the item"),
256 GTK_PARAM_READWRITE));
259 * GtkToolButton:icon-name:
261 * The name of the themed icon displayed on the item.
262 * This property only has an effect if not overridden by "label",
263 * "icon_widget" or "stock_id" properties.
267 g_object_class_install_property (object_class,
269 g_param_spec_string ("icon-name",
271 P_("The name of the themed icon displayed on the item"),
273 GTK_PARAM_READWRITE));
274 g_object_class_install_property (object_class,
276 g_param_spec_object ("icon-widget",
278 P_("Icon widget to display in the item"),
280 GTK_PARAM_READWRITE));
283 * GtkButton:icon-spacing:
285 * Spacing in pixels between the icon and label.
289 gtk_widget_class_install_style_property (widget_class,
290 g_param_spec_int ("icon-spacing",
292 P_("Spacing in pixels between the icon and label"),
296 GTK_PARAM_READWRITE));
299 * GtkToolButton::clicked:
300 * @toolbutton: the object that emitted the signal
302 * This signal is emitted when the tool button is clicked with the mouse
303 * or activated with the keyboard.
305 toolbutton_signals[CLICKED] =
306 g_signal_new (I_("clicked"),
307 G_OBJECT_CLASS_TYPE (klass),
308 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
309 G_STRUCT_OFFSET (GtkToolButtonClass, clicked),
311 g_cclosure_marshal_VOID__VOID,
314 g_type_class_add_private (object_class, sizeof (GtkToolButtonPrivate));
318 gtk_tool_button_init (GtkToolButton *button,
319 GtkToolButtonClass *klass)
321 GtkToolItem *toolitem = GTK_TOOL_ITEM (button);
323 button->priv = G_TYPE_INSTANCE_GET_PRIVATE (button,
324 GTK_TYPE_TOOL_BUTTON,
325 GtkToolButtonPrivate);
327 button->priv->contents_invalid = TRUE;
329 gtk_tool_item_set_homogeneous (toolitem, TRUE);
332 button->priv->button = g_object_new (klass->button_type, NULL);
333 gtk_button_set_focus_on_click (GTK_BUTTON (button->priv->button), FALSE);
334 g_signal_connect_object (button->priv->button, "clicked",
335 G_CALLBACK (button_clicked), button, 0);
337 gtk_container_add (GTK_CONTAINER (button), button->priv->button);
338 gtk_widget_show (button->priv->button);
342 gtk_tool_button_construct_contents (GtkToolItem *tool_item)
344 GtkToolButton *button = GTK_TOOL_BUTTON (tool_item);
346 GtkWidget *label = NULL;
347 GtkWidget *icon = NULL;
348 GtkToolbarStyle style;
349 gboolean need_label = FALSE;
350 gboolean need_icon = FALSE;
351 GtkIconSize icon_size;
352 GtkWidget *box = NULL;
354 GtkOrientation text_orientation = GTK_ORIENTATION_HORIZONTAL;
355 GtkSizeGroup *size_group = NULL;
358 button->priv->contents_invalid = FALSE;
360 gtk_widget_style_get (GTK_WIDGET (tool_item),
361 "icon-spacing", &icon_spacing,
364 if (button->priv->icon_widget)
366 parent = gtk_widget_get_parent (button->priv->icon_widget);
369 gtk_container_remove (GTK_CONTAINER (parent),
370 button->priv->icon_widget);
374 if (button->priv->label_widget)
376 parent = gtk_widget_get_parent (button->priv->label_widget);
379 gtk_container_remove (GTK_CONTAINER (parent),
380 button->priv->label_widget);
384 child = gtk_bin_get_child (GTK_BIN (button->priv->button));
387 /* Note: we are not destroying the label_widget or icon_widget
388 * here because they were removed from their containers above
390 gtk_widget_destroy (child);
393 style = gtk_tool_item_get_toolbar_style (GTK_TOOL_ITEM (button));
395 if (style != GTK_TOOLBAR_TEXT)
398 if (style != GTK_TOOLBAR_ICONS && style != GTK_TOOLBAR_BOTH_HORIZ)
401 if (style == GTK_TOOLBAR_BOTH_HORIZ &&
402 (gtk_tool_item_get_is_important (GTK_TOOL_ITEM (button)) ||
403 gtk_tool_item_get_orientation (GTK_TOOL_ITEM (button)) == GTK_ORIENTATION_VERTICAL ||
404 gtk_tool_item_get_text_orientation (GTK_TOOL_ITEM (button)) == GTK_ORIENTATION_VERTICAL))
409 if (style == GTK_TOOLBAR_ICONS && button->priv->icon_widget == NULL &&
410 button->priv->stock_id == NULL && button->priv->icon_name == NULL)
414 style = GTK_TOOLBAR_TEXT;
417 if (style == GTK_TOOLBAR_TEXT && button->priv->label_widget == NULL &&
418 button->priv->stock_id == NULL && button->priv->label_text == NULL)
422 style = GTK_TOOLBAR_ICONS;
427 if (button->priv->label_widget)
429 label = button->priv->label_widget;
433 GtkStockItem stock_item;
437 if (button->priv->label_text)
439 label_text = button->priv->label_text;
440 elide = button->priv->use_underline;
442 else if (button->priv->stock_id && gtk_stock_lookup (button->priv->stock_id, &stock_item))
444 label_text = stock_item.label;
454 label_text = _gtk_toolbar_elide_underscores (label_text);
456 label_text = g_strdup (label_text);
458 label = gtk_label_new (label_text);
462 gtk_widget_show (label);
465 if (GTK_IS_LABEL (label))
467 gtk_label_set_ellipsize (GTK_LABEL (label),
468 gtk_tool_item_get_ellipsize_mode (GTK_TOOL_ITEM (button)));
469 text_orientation = gtk_tool_item_get_text_orientation (GTK_TOOL_ITEM (button));
470 if (text_orientation == GTK_ORIENTATION_HORIZONTAL)
472 gtk_label_set_angle (GTK_LABEL (label), 0);
473 gtk_misc_set_alignment (GTK_MISC (label),
474 gtk_tool_item_get_text_alignment (GTK_TOOL_ITEM (button)),
479 gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_NONE);
480 if (gtk_widget_get_direction (GTK_WIDGET (tool_item)) == GTK_TEXT_DIR_RTL)
481 gtk_label_set_angle (GTK_LABEL (label), -90);
483 gtk_label_set_angle (GTK_LABEL (label), 90);
484 gtk_misc_set_alignment (GTK_MISC (label),
486 1 - gtk_tool_item_get_text_alignment (GTK_TOOL_ITEM (button)));
491 icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (button));
494 if (button->priv->icon_widget)
496 icon = button->priv->icon_widget;
498 if (GTK_IS_IMAGE (icon))
500 g_object_set (button->priv->icon_widget,
501 "icon-size", icon_size,
505 else if (button->priv->stock_id &&
506 gtk_icon_factory_lookup_default (button->priv->stock_id))
508 icon = gtk_image_new_from_stock (button->priv->stock_id, icon_size);
509 gtk_widget_show (icon);
511 else if (button->priv->icon_name)
513 icon = gtk_image_new_from_icon_name (button->priv->icon_name, icon_size);
514 gtk_widget_show (icon);
517 if (GTK_IS_MISC (icon) && text_orientation == GTK_ORIENTATION_HORIZONTAL)
518 gtk_misc_set_alignment (GTK_MISC (icon),
519 1.0 - gtk_tool_item_get_text_alignment (GTK_TOOL_ITEM (button)),
521 else if (GTK_IS_MISC (icon))
522 gtk_misc_set_alignment (GTK_MISC (icon),
524 gtk_tool_item_get_text_alignment (GTK_TOOL_ITEM (button)));
528 size_group = gtk_tool_item_get_text_size_group (GTK_TOOL_ITEM (button));
529 if (size_group != NULL)
530 gtk_size_group_add_widget (size_group, icon);
536 case GTK_TOOLBAR_ICONS:
538 gtk_container_add (GTK_CONTAINER (button->priv->button), icon);
541 case GTK_TOOLBAR_BOTH:
542 if (text_orientation == GTK_ORIENTATION_HORIZONTAL)
543 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, icon_spacing);
545 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, icon_spacing);
547 gtk_box_pack_start (GTK_BOX (box), icon, TRUE, TRUE, 0);
548 gtk_box_pack_end (GTK_BOX (box), label, FALSE, TRUE, 0);
549 gtk_container_add (GTK_CONTAINER (button->priv->button), box);
552 case GTK_TOOLBAR_BOTH_HORIZ:
553 if (text_orientation == GTK_ORIENTATION_HORIZONTAL)
555 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, icon_spacing);
557 gtk_box_pack_start (GTK_BOX (box), icon, label? FALSE : TRUE, TRUE, 0);
559 gtk_box_pack_end (GTK_BOX (box), label, TRUE, TRUE, 0);
563 box = gtk_box_new (GTK_ORIENTATION_VERTICAL, icon_spacing);
565 gtk_box_pack_end (GTK_BOX (box), icon, label ? FALSE : TRUE, TRUE, 0);
567 gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
569 gtk_container_add (GTK_CONTAINER (button->priv->button), box);
572 case GTK_TOOLBAR_TEXT:
573 gtk_container_add (GTK_CONTAINER (button->priv->button), label);
578 gtk_widget_show (box);
580 gtk_button_set_relief (GTK_BUTTON (button->priv->button),
581 gtk_tool_item_get_relief_style (GTK_TOOL_ITEM (button)));
583 gtk_tool_item_rebuild_menu (tool_item);
585 gtk_widget_queue_resize (GTK_WIDGET (button));
589 gtk_tool_button_set_property (GObject *object,
594 GtkToolButton *button = GTK_TOOL_BUTTON (object);
599 gtk_tool_button_set_label (button, g_value_get_string (value));
601 case PROP_USE_UNDERLINE:
602 gtk_tool_button_set_use_underline (button, g_value_get_boolean (value));
604 case PROP_LABEL_WIDGET:
605 gtk_tool_button_set_label_widget (button, g_value_get_object (value));
608 gtk_tool_button_set_stock_id (button, g_value_get_string (value));
611 gtk_tool_button_set_icon_name (button, g_value_get_string (value));
613 case PROP_ICON_WIDGET:
614 gtk_tool_button_set_icon_widget (button, g_value_get_object (value));
617 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
623 gtk_tool_button_property_notify (GObject *object,
626 GtkToolButton *button = GTK_TOOL_BUTTON (object);
628 if (button->priv->contents_invalid ||
629 strcmp ("is-important", pspec->name) == 0)
630 gtk_tool_button_construct_contents (GTK_TOOL_ITEM (object));
632 if (parent_class->notify)
633 parent_class->notify (object, pspec);
637 gtk_tool_button_get_property (GObject *object,
642 GtkToolButton *button = GTK_TOOL_BUTTON (object);
647 g_value_set_string (value, gtk_tool_button_get_label (button));
649 case PROP_LABEL_WIDGET:
650 g_value_set_object (value, gtk_tool_button_get_label_widget (button));
652 case PROP_USE_UNDERLINE:
653 g_value_set_boolean (value, gtk_tool_button_get_use_underline (button));
656 g_value_set_string (value, button->priv->stock_id);
659 g_value_set_string (value, button->priv->icon_name);
661 case PROP_ICON_WIDGET:
662 g_value_set_object (value, button->priv->icon_widget);
665 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
671 gtk_tool_button_finalize (GObject *object)
673 GtkToolButton *button = GTK_TOOL_BUTTON (object);
675 g_free (button->priv->stock_id);
676 g_free (button->priv->icon_name);
677 g_free (button->priv->label_text);
679 if (button->priv->label_widget)
680 g_object_unref (button->priv->label_widget);
682 if (button->priv->icon_widget)
683 g_object_unref (button->priv->icon_widget);
685 parent_class->finalize (object);
689 clone_image_menu_size (GtkImage *image, GtkSettings *settings)
691 GtkImageType storage_type = gtk_image_get_storage_type (image);
693 if (storage_type == GTK_IMAGE_STOCK)
696 gtk_image_get_stock (image, &stock_id, NULL);
697 return gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU);
699 else if (storage_type == GTK_IMAGE_ICON_NAME)
701 const gchar *icon_name;
702 gtk_image_get_icon_name (image, &icon_name, NULL);
703 return gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
705 else if (storage_type == GTK_IMAGE_ICON_SET)
707 GtkIconSet *icon_set;
708 gtk_image_get_icon_set (image, &icon_set, NULL);
709 return gtk_image_new_from_icon_set (icon_set, GTK_ICON_SIZE_MENU);
711 else if (storage_type == GTK_IMAGE_GICON)
714 gtk_image_get_gicon (image, &icon, NULL);
715 return gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_MENU);
717 else if (storage_type == GTK_IMAGE_PIXBUF)
722 gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
725 GdkPixbuf *src_pixbuf, *dest_pixbuf;
726 GtkWidget *cloned_image;
728 src_pixbuf = gtk_image_get_pixbuf (image);
729 dest_pixbuf = gdk_pixbuf_scale_simple (src_pixbuf, width, height,
730 GDK_INTERP_BILINEAR);
732 cloned_image = gtk_image_new_from_pixbuf (dest_pixbuf);
733 g_object_unref (dest_pixbuf);
743 gtk_tool_button_create_menu_proxy (GtkToolItem *item)
745 GtkToolButton *button = GTK_TOOL_BUTTON (item);
746 GtkWidget *menu_item;
747 GtkWidget *menu_image = NULL;
748 GtkStockItem stock_item;
749 gboolean use_mnemonic = TRUE;
752 if (_gtk_tool_item_create_menu_proxy (item))
755 if (GTK_IS_LABEL (button->priv->label_widget))
757 label = gtk_label_get_label (GTK_LABEL (button->priv->label_widget));
758 use_mnemonic = gtk_label_get_use_underline (GTK_LABEL (button->priv->label_widget));
760 else if (button->priv->label_text)
762 label = button->priv->label_text;
763 use_mnemonic = button->priv->use_underline;
765 else if (button->priv->stock_id && gtk_stock_lookup (button->priv->stock_id, &stock_item))
767 label = stock_item.label;
775 menu_item = gtk_image_menu_item_new_with_mnemonic (label);
777 menu_item = gtk_image_menu_item_new_with_label (label);
779 if (GTK_IS_IMAGE (button->priv->icon_widget))
781 menu_image = clone_image_menu_size (GTK_IMAGE (button->priv->icon_widget),
782 gtk_widget_get_settings (GTK_WIDGET (button)));
784 else if (button->priv->stock_id)
786 menu_image = gtk_image_new_from_stock (button->priv->stock_id, GTK_ICON_SIZE_MENU);
790 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), menu_image);
792 g_signal_connect_closure_by_id (menu_item,
793 g_signal_lookup ("activate", G_OBJECT_TYPE (menu_item)), 0,
794 g_cclosure_new_object_swap (G_CALLBACK (gtk_button_clicked),
795 G_OBJECT (GTK_TOOL_BUTTON (button)->priv->button)),
798 gtk_tool_item_set_proxy_menu_item (GTK_TOOL_ITEM (button), MENU_ID, menu_item);
804 button_clicked (GtkWidget *widget,
805 GtkToolButton *button)
809 action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (button));
812 gtk_action_activate (action);
814 g_signal_emit_by_name (button, "clicked");
818 gtk_tool_button_toolbar_reconfigured (GtkToolItem *tool_item)
820 gtk_tool_button_construct_contents (tool_item);
824 gtk_tool_button_update_icon_spacing (GtkToolButton *button)
829 box = gtk_bin_get_child (GTK_BIN (button->priv->button));
830 if (GTK_IS_BOX (box))
832 gtk_widget_style_get (GTK_WIDGET (button),
833 "icon-spacing", &spacing,
835 gtk_box_set_spacing (GTK_BOX (box), spacing);
840 gtk_tool_button_style_updated (GtkWidget *widget)
842 GTK_WIDGET_CLASS (parent_class)->style_updated (widget);
844 gtk_tool_button_update_icon_spacing (GTK_TOOL_BUTTON (widget));
848 gtk_tool_button_activatable_interface_init (GtkActivatableIface *iface)
850 parent_activatable_iface = g_type_interface_peek_parent (iface);
851 iface->update = gtk_tool_button_update;
852 iface->sync_action_properties = gtk_tool_button_sync_action_properties;
856 gtk_tool_button_update (GtkActivatable *activatable,
858 const gchar *property_name)
860 GtkToolButton *button;
863 parent_activatable_iface->update (activatable, action, property_name);
865 if (!gtk_activatable_get_use_action_appearance (activatable))
868 button = GTK_TOOL_BUTTON (activatable);
870 if (strcmp (property_name, "short-label") == 0)
871 gtk_tool_button_set_label (button, gtk_action_get_short_label (action));
872 else if (strcmp (property_name, "stock-id") == 0)
873 gtk_tool_button_set_stock_id (button, gtk_action_get_stock_id (action));
874 else if (strcmp (property_name, "gicon") == 0)
876 const gchar *stock_id = gtk_action_get_stock_id (action);
877 GIcon *icon = gtk_action_get_gicon (action);
878 GtkIconSize icon_size = GTK_ICON_SIZE_BUTTON;
880 if ((stock_id && gtk_icon_factory_lookup_default (stock_id)) || !icon)
884 image = gtk_tool_button_get_icon_widget (button);
885 icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (button));
888 image = gtk_image_new ();
891 gtk_tool_button_set_icon_widget (button, image);
892 gtk_image_set_from_gicon (GTK_IMAGE (image), icon, icon_size);
895 else if (strcmp (property_name, "icon-name") == 0)
896 gtk_tool_button_set_icon_name (button, gtk_action_get_icon_name (action));
900 gtk_tool_button_sync_action_properties (GtkActivatable *activatable,
903 GtkToolButton *button;
905 const gchar *stock_id;
907 parent_activatable_iface->sync_action_properties (activatable, action);
912 if (!gtk_activatable_get_use_action_appearance (activatable))
915 button = GTK_TOOL_BUTTON (activatable);
916 stock_id = gtk_action_get_stock_id (action);
918 gtk_tool_button_set_label (button, gtk_action_get_short_label (action));
919 gtk_tool_button_set_use_underline (button, TRUE);
920 gtk_tool_button_set_stock_id (button, stock_id);
921 gtk_tool_button_set_icon_name (button, gtk_action_get_icon_name (action));
923 if (stock_id && gtk_icon_factory_lookup_default (stock_id))
924 gtk_tool_button_set_icon_widget (button, NULL);
925 else if ((icon = gtk_action_get_gicon (action)) != NULL)
927 GtkIconSize icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (button));
928 GtkWidget *image = gtk_tool_button_get_icon_widget (button);
932 image = gtk_image_new ();
933 gtk_widget_show (image);
934 gtk_tool_button_set_icon_widget (button, image);
937 gtk_image_set_from_gicon (GTK_IMAGE (image), icon, icon_size);
939 else if (gtk_action_get_icon_name (action))
940 gtk_tool_button_set_icon_name (button, gtk_action_get_icon_name (action));
942 gtk_tool_button_set_label (button, gtk_action_get_short_label (action));
946 * gtk_tool_button_new_from_stock:
947 * @stock_id: the name of the stock item
949 * Creates a new #GtkToolButton containing the image and text from a
950 * stock item. Some stock ids have preprocessor macros like #GTK_STOCK_OK
951 * and #GTK_STOCK_APPLY.
953 * It is an error if @stock_id is not a name of a stock item.
955 * Return value: A new #GtkToolButton
960 gtk_tool_button_new_from_stock (const gchar *stock_id)
962 GtkToolButton *button;
964 g_return_val_if_fail (stock_id != NULL, NULL);
966 button = g_object_new (GTK_TYPE_TOOL_BUTTON,
967 "stock-id", stock_id,
970 return GTK_TOOL_ITEM (button);
974 * gtk_tool_button_new:
975 * @label: (allow-none): a string that will be used as label, or %NULL
976 * @icon_widget: (allow-none): a #GtkMisc widget that will be used as icon widget, or %NULL
978 * Creates a new %GtkToolButton using @icon_widget as icon and @label as
981 * Return value: A new #GtkToolButton
986 gtk_tool_button_new (GtkWidget *icon_widget,
989 GtkToolButton *button;
991 g_return_val_if_fail (icon_widget == NULL || GTK_IS_MISC (icon_widget), NULL);
993 button = g_object_new (GTK_TYPE_TOOL_BUTTON,
995 "icon-widget", icon_widget,
998 return GTK_TOOL_ITEM (button);
1002 * gtk_tool_button_set_label:
1003 * @button: a #GtkToolButton
1004 * @label: (allow-none): a string that will be used as label, or %NULL.
1006 * Sets @label as the label used for the tool button. The "label" property
1007 * only has an effect if not overridden by a non-%NULL "label_widget" property.
1008 * If both the "label_widget" and "label" properties are %NULL, the label
1009 * is determined by the "stock_id" property. If the "stock_id" property is also
1010 * %NULL, @button will not have a label.
1015 gtk_tool_button_set_label (GtkToolButton *button,
1019 gchar *elided_label;
1020 AtkObject *accessible;
1022 g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
1024 old_label = button->priv->label_text;
1026 button->priv->label_text = g_strdup (label);
1027 button->priv->contents_invalid = TRUE;
1031 elided_label = _gtk_toolbar_elide_underscores (label);
1032 accessible = gtk_widget_get_accessible (GTK_WIDGET (button->priv->button));
1033 atk_object_set_name (accessible, elided_label);
1034 g_free (elided_label);
1039 g_object_notify (G_OBJECT (button), "label");
1043 * gtk_tool_button_get_label:
1044 * @button: a #GtkToolButton
1046 * Returns the label used by the tool button, or %NULL if the tool button
1047 * doesn't have a label. or uses a the label from a stock item. The returned
1048 * string is owned by GTK+, and must not be modified or freed.
1050 * Return value: The label, or %NULL
1055 gtk_tool_button_get_label (GtkToolButton *button)
1057 g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1059 return button->priv->label_text;
1063 * gtk_tool_button_set_use_underline:
1064 * @button: a #GtkToolButton
1065 * @use_underline: whether the button label has the form "_Open"
1067 * If set, an underline in the label property indicates that the next character
1068 * should be used for the mnemonic accelerator key in the overflow menu. For
1069 * example, if the label property is "_Open" and @use_underline is %TRUE,
1070 * the label on the tool button will be "Open" and the item on the overflow
1071 * menu will have an underlined 'O'.
1073 * Labels shown on tool buttons never have mnemonics on them; this property
1074 * only affects the menu item on the overflow menu.
1079 gtk_tool_button_set_use_underline (GtkToolButton *button,
1080 gboolean use_underline)
1082 g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
1084 use_underline = use_underline != FALSE;
1086 if (use_underline != button->priv->use_underline)
1088 button->priv->use_underline = use_underline;
1089 button->priv->contents_invalid = TRUE;
1091 g_object_notify (G_OBJECT (button), "use-underline");
1096 * gtk_tool_button_get_use_underline:
1097 * @button: a #GtkToolButton
1099 * Returns whether underscores in the label property are used as mnemonics
1100 * on menu items on the overflow menu. See gtk_tool_button_set_use_underline().
1102 * Return value: %TRUE if underscores in the label property are used as
1103 * mnemonics on menu items on the overflow menu.
1108 gtk_tool_button_get_use_underline (GtkToolButton *button)
1110 g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), FALSE);
1112 return button->priv->use_underline;
1116 * gtk_tool_button_set_stock_id:
1117 * @button: a #GtkToolButton
1118 * @stock_id: (allow-none): a name of a stock item, or %NULL
1120 * Sets the name of the stock item. See gtk_tool_button_new_from_stock().
1121 * The stock_id property only has an effect if not
1122 * overridden by non-%NULL "label" and "icon_widget" properties.
1127 gtk_tool_button_set_stock_id (GtkToolButton *button,
1128 const gchar *stock_id)
1130 gchar *old_stock_id;
1132 g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
1134 old_stock_id = button->priv->stock_id;
1136 button->priv->stock_id = g_strdup (stock_id);
1137 button->priv->contents_invalid = TRUE;
1139 g_free (old_stock_id);
1141 g_object_notify (G_OBJECT (button), "stock-id");
1145 * gtk_tool_button_get_stock_id:
1146 * @button: a #GtkToolButton
1148 * Returns the name of the stock item. See gtk_tool_button_set_stock_id().
1149 * The returned string is owned by GTK+ and must not be freed or modifed.
1151 * Return value: the name of the stock item for @button.
1156 gtk_tool_button_get_stock_id (GtkToolButton *button)
1158 g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1160 return button->priv->stock_id;
1164 * gtk_tool_button_set_icon_name
1165 * @button: a #GtkToolButton
1166 * @icon_name: (allow-none): the name of the themed icon
1168 * Sets the icon for the tool button from a named themed icon.
1169 * See the docs for #GtkIconTheme for more details.
1170 * The "icon_name" property only has an effect if not
1171 * overridden by non-%NULL "label", "icon_widget" and "stock_id"
1177 gtk_tool_button_set_icon_name (GtkToolButton *button,
1178 const gchar *icon_name)
1180 gchar *old_icon_name;
1182 g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
1184 old_icon_name = button->priv->icon_name;
1186 button->priv->icon_name = g_strdup (icon_name);
1187 button->priv->contents_invalid = TRUE;
1189 g_free (old_icon_name);
1191 g_object_notify (G_OBJECT (button), "icon-name");
1195 * gtk_tool_button_get_icon_name
1196 * @button: a #GtkToolButton
1198 * Returns the name of the themed icon for the tool button,
1199 * see gtk_tool_button_set_icon_name().
1201 * Returns: the icon name or %NULL if the tool button has
1207 gtk_tool_button_get_icon_name (GtkToolButton *button)
1209 g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1211 return button->priv->icon_name;
1215 * gtk_tool_button_set_icon_widget:
1216 * @button: a #GtkToolButton
1217 * @icon_widget: (allow-none): the widget used as icon, or %NULL
1219 * Sets @icon as the widget used as icon on @button. If @icon_widget is
1220 * %NULL the icon is determined by the "stock_id" property. If the
1221 * "stock_id" property is also %NULL, @button will not have an icon.
1226 gtk_tool_button_set_icon_widget (GtkToolButton *button,
1227 GtkWidget *icon_widget)
1229 g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
1230 g_return_if_fail (icon_widget == NULL || GTK_IS_WIDGET (icon_widget));
1232 if (icon_widget != button->priv->icon_widget)
1234 if (button->priv->icon_widget)
1238 parent = gtk_widget_get_parent (button->priv->icon_widget);
1240 gtk_container_remove (GTK_CONTAINER (parent),
1241 button->priv->icon_widget);
1243 g_object_unref (button->priv->icon_widget);
1247 g_object_ref_sink (icon_widget);
1249 button->priv->icon_widget = icon_widget;
1250 button->priv->contents_invalid = TRUE;
1252 g_object_notify (G_OBJECT (button), "icon-widget");
1257 * gtk_tool_button_set_label_widget:
1258 * @button: a #GtkToolButton
1259 * @label_widget: (allow-none): the widget used as label, or %NULL
1261 * Sets @label_widget as the widget that will be used as the label
1262 * for @button. If @label_widget is %NULL the "label" property is used
1263 * as label. If "label" is also %NULL, the label in the stock item
1264 * determined by the "stock_id" property is used as label. If
1265 * "stock_id" is also %NULL, @button does not have a label.
1270 gtk_tool_button_set_label_widget (GtkToolButton *button,
1271 GtkWidget *label_widget)
1273 g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
1274 g_return_if_fail (label_widget == NULL || GTK_IS_WIDGET (label_widget));
1276 if (label_widget != button->priv->label_widget)
1278 if (button->priv->label_widget)
1282 parent = gtk_widget_get_parent (button->priv->label_widget);
1284 gtk_container_remove (GTK_CONTAINER (parent),
1285 button->priv->label_widget);
1287 g_object_unref (button->priv->label_widget);
1291 g_object_ref_sink (label_widget);
1293 button->priv->label_widget = label_widget;
1294 button->priv->contents_invalid = TRUE;
1296 g_object_notify (G_OBJECT (button), "label-widget");
1301 * gtk_tool_button_get_label_widget:
1302 * @button: a #GtkToolButton
1304 * Returns the widget used as label on @button.
1305 * See gtk_tool_button_set_label_widget().
1307 * Return value: (transfer none): The widget used as label
1308 * on @button, or %NULL.
1313 gtk_tool_button_get_label_widget (GtkToolButton *button)
1315 g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1317 return button->priv->label_widget;
1321 * gtk_tool_button_get_icon_widget:
1322 * @button: a #GtkToolButton
1324 * Return the widget used as icon widget on @button.
1325 * See gtk_tool_button_set_icon_widget().
1327 * Return value: (transfer none): The widget used as icon
1328 * on @button, or %NULL.
1333 gtk_tool_button_get_icon_widget (GtkToolButton *button)
1335 g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1337 return button->priv->icon_widget;
1341 _gtk_tool_button_get_button (GtkToolButton *button)
1343 g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1345 return button->priv->button;