]> Pileus Git - ~andy/gtk/blob - gtk/gtktoolbutton.c
Move documentation to inline comments: GtkToolButton
[~andy/gtk] / gtk / gtktoolbutton.c
1 /* gtktoolbutton.c
2  *
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>
6  *
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.
11  *
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.
16  *
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.
21  */
22
23 #include "config.h"
24 #include "gtktoolbutton.h"
25 #include "gtkbutton.h"
26 #include "gtkhbox.h"
27 #include "gtkiconfactory.h"
28 #include "gtkimage.h"
29 #include "gtkimagemenuitem.h"
30 #include "gtklabel.h"
31 #include "gtkstock.h"
32 #include "gtkvbox.h"
33 #include "gtkintl.h"
34 #include "gtktoolbar.h"
35 #include "gtkactivatable.h"
36 #include "gtkprivate.h"
37
38 #include <string.h>
39
40
41 /**
42  * SECTION:gtktoolbutton
43  * @Short_description: A GtkToolItem subclass that displays buttons
44  * @Title: GtkToolButton
45  * @See_also: #GtkToolbar, #GtkMenuToolButton, #GtkToggleToolButton,
46  *   #GtkRadioToolButton, #GtkSeparatorToolItem
47  *
48  * #GtkToolButton<!-- -->s are #GtkToolItems containing buttons.
49  *
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.
53  *
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.
61  *
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.
68  */
69
70
71 #define MENU_ID "gtk-tool-button-menu-id"
72
73 enum {
74   CLICKED,
75   LAST_SIGNAL
76 };
77
78 enum {
79   PROP_0,
80   PROP_LABEL,
81   PROP_USE_UNDERLINE,
82   PROP_LABEL_WIDGET,
83   PROP_STOCK_ID,
84   PROP_ICON_NAME,
85   PROP_ICON_WIDGET
86 };
87
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,
92                                            guint               prop_id,
93                                            const GValue       *value,
94                                            GParamSpec         *pspec);
95 static void gtk_tool_button_get_property  (GObject            *object,
96                                            guint               prop_id,
97                                            GValue             *value,
98                                            GParamSpec         *pspec);
99 static void gtk_tool_button_property_notify (GObject          *object,
100                                              GParamSpec       *pspec);
101 static void gtk_tool_button_finalize      (GObject            *object);
102
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);
108
109 static void gtk_tool_button_construct_contents (GtkToolItem *tool_item);
110
111 static void gtk_tool_button_activatable_interface_init (GtkActivatableIface  *iface);
112 static void gtk_tool_button_update                     (GtkActivatable       *activatable,
113                                                         GtkAction            *action,
114                                                         const gchar          *property_name);
115 static void gtk_tool_button_sync_action_properties     (GtkActivatable       *activatable,
116                                                         GtkAction            *action);
117
118
119 struct _GtkToolButtonPrivate
120 {
121   GtkWidget *button;
122
123   gchar *stock_id;
124   gchar *icon_name;
125   gchar *label_text;
126   GtkWidget *label_widget;
127   GtkWidget *icon_widget;
128
129   GtkSizeGroup *text_size_group;
130
131   guint use_underline : 1;
132   guint contents_invalid : 1;
133 };
134
135 static GObjectClass        *parent_class = NULL;
136 static GtkActivatableIface *parent_activatable_iface;
137 static guint                toolbutton_signals[LAST_SIGNAL] = { 0 };
138
139
140 GType
141 gtk_tool_button_get_type (void)
142 {
143   static GType type = 0;
144   
145   if (!type)
146     {
147       const GInterfaceInfo activatable_info =
148       {
149         (GInterfaceInitFunc) gtk_tool_button_activatable_interface_init,
150         (GInterfaceFinalizeFunc) NULL,
151         NULL
152       };
153
154       type = g_type_register_static_simple (GTK_TYPE_TOOL_ITEM,
155                                             I_("GtkToolButton"),
156                                             sizeof (GtkToolButtonClass),
157                                             (GClassInitFunc) gtk_tool_button_class_init,
158                                             sizeof (GtkToolButton),
159                                             (GInstanceInitFunc) gtk_tool_button_init,
160                                             0);
161
162       g_type_add_interface_static (type, GTK_TYPE_ACTIVATABLE,
163                                    &activatable_info);
164     }
165   return type;
166 }
167
168 static void
169 gtk_tool_button_class_init (GtkToolButtonClass *klass)
170 {
171   GObjectClass *object_class;
172   GtkWidgetClass *widget_class;
173   GtkToolItemClass *tool_item_class;
174   
175   parent_class = g_type_class_peek_parent (klass);
176   
177   object_class = (GObjectClass *)klass;
178   widget_class = (GtkWidgetClass *)klass;
179   tool_item_class = (GtkToolItemClass *)klass;
180   
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;
185
186   widget_class->style_updated = gtk_tool_button_style_updated;
187
188   tool_item_class->create_menu_proxy = gtk_tool_button_create_menu_proxy;
189   tool_item_class->toolbar_reconfigured = gtk_tool_button_toolbar_reconfigured;
190   
191   klass->button_type = GTK_TYPE_BUTTON;
192
193   /* Properties are interpreted like this:
194    *
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.
201    *
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.
209    *
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).
213    *
214    *            In that case, if use_underline is set,
215    *
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
219    *
220    *                    - an underscore indicates that the next character when
221    *                      used in the overflow menu should be used as a
222    *                      mnemonic.
223    *
224    *            In short: use_underline = TRUE means that the label text has
225    *            the form "_Open" and the toolbar should take appropriate
226    *            action.
227    */
228
229   g_object_class_install_property (object_class,
230                                    PROP_LABEL,
231                                    g_param_spec_string ("label",
232                                                         P_("Label"),
233                                                         P_("Text to show in the item."),
234                                                         NULL,
235                                                         GTK_PARAM_READWRITE));
236   g_object_class_install_property (object_class,
237                                    PROP_USE_UNDERLINE,
238                                    g_param_spec_boolean ("use-underline",
239                                                          P_("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"),
241                                                          FALSE,
242                                                          GTK_PARAM_READWRITE));
243   g_object_class_install_property (object_class,
244                                    PROP_LABEL_WIDGET,
245                                    g_param_spec_object ("label-widget",
246                                                         P_("Label widget"),
247                                                         P_("Widget to use as the item label"),
248                                                         GTK_TYPE_WIDGET,
249                                                         GTK_PARAM_READWRITE));
250   g_object_class_install_property (object_class,
251                                    PROP_STOCK_ID,
252                                    g_param_spec_string ("stock-id",
253                                                         P_("Stock Id"),
254                                                         P_("The stock icon displayed on the item"),
255                                                         NULL,
256                                                         GTK_PARAM_READWRITE));
257
258   /**
259    * GtkToolButton:icon-name:
260    * 
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.
264    *
265    * Since: 2.8 
266    */
267   g_object_class_install_property (object_class,
268                                    PROP_ICON_NAME,
269                                    g_param_spec_string ("icon-name",
270                                                         P_("Icon name"),
271                                                         P_("The name of the themed icon displayed on the item"),
272                                                         NULL,
273                                                         GTK_PARAM_READWRITE));
274   g_object_class_install_property (object_class,
275                                    PROP_ICON_WIDGET,
276                                    g_param_spec_object ("icon-widget",
277                                                         P_("Icon widget"),
278                                                         P_("Icon widget to display in the item"),
279                                                         GTK_TYPE_WIDGET,
280                                                         GTK_PARAM_READWRITE));
281
282   /**
283    * GtkButton:icon-spacing:
284    * 
285    * Spacing in pixels between the icon and label.
286    * 
287    * Since: 2.10
288    */
289   gtk_widget_class_install_style_property (widget_class,
290                                            g_param_spec_int ("icon-spacing",
291                                                              P_("Icon spacing"),
292                                                              P_("Spacing in pixels between the icon and label"),
293                                                              0,
294                                                              G_MAXINT,
295                                                              3,
296                                                              GTK_PARAM_READWRITE));
297
298 /**
299  * GtkToolButton::clicked:
300  * @toolbutton: the object that emitted the signal
301  *
302  * This signal is emitted when the tool button is clicked with the mouse
303  * or activated with the keyboard.
304  **/
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),
310                   NULL, NULL,
311                   g_cclosure_marshal_VOID__VOID,
312                   G_TYPE_NONE, 0);
313   
314   g_type_class_add_private (object_class, sizeof (GtkToolButtonPrivate));
315 }
316
317 static void
318 gtk_tool_button_init (GtkToolButton      *button,
319                       GtkToolButtonClass *klass)
320 {
321   GtkToolItem *toolitem = GTK_TOOL_ITEM (button);
322
323   button->priv = G_TYPE_INSTANCE_GET_PRIVATE (button,
324                                               GTK_TYPE_TOOL_BUTTON,
325                                               GtkToolButtonPrivate);
326
327   button->priv->contents_invalid = TRUE;
328
329   gtk_tool_item_set_homogeneous (toolitem, TRUE);
330
331   /* create button */
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);
336
337   gtk_container_add (GTK_CONTAINER (button), button->priv->button);
338   gtk_widget_show (button->priv->button);
339 }
340
341 static void
342 gtk_tool_button_construct_contents (GtkToolItem *tool_item)
343 {
344   GtkToolButton *button = GTK_TOOL_BUTTON (tool_item);
345   GtkWidget *child;
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;
353   guint icon_spacing;
354   GtkOrientation text_orientation = GTK_ORIENTATION_HORIZONTAL;
355   GtkSizeGroup *size_group = NULL;
356   GtkWidget *parent;
357
358   button->priv->contents_invalid = FALSE;
359
360   gtk_widget_style_get (GTK_WIDGET (tool_item), 
361                         "icon-spacing", &icon_spacing,
362                         NULL);
363
364   if (button->priv->icon_widget)
365     {
366       parent = gtk_widget_get_parent (button->priv->icon_widget);
367       if (parent)
368         {
369           gtk_container_remove (GTK_CONTAINER (parent),
370                                 button->priv->icon_widget);
371         }
372     }
373
374   if (button->priv->label_widget)
375     {
376       parent = gtk_widget_get_parent (button->priv->label_widget);
377       if (parent)
378         {
379           gtk_container_remove (GTK_CONTAINER (parent),
380                                 button->priv->label_widget);
381         }
382     }
383
384   child = gtk_bin_get_child (GTK_BIN (button->priv->button));
385   if (child)
386     {
387       /* Note: we are not destroying the label_widget or icon_widget
388        * here because they were removed from their containers above
389        */
390       gtk_widget_destroy (child);
391     }
392
393   style = gtk_tool_item_get_toolbar_style (GTK_TOOL_ITEM (button));
394   
395   if (style != GTK_TOOLBAR_TEXT)
396     need_icon = TRUE;
397
398   if (style != GTK_TOOLBAR_ICONS && style != GTK_TOOLBAR_BOTH_HORIZ)
399     need_label = TRUE;
400
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))
405     {
406       need_label = TRUE;
407     }
408   
409   if (style == GTK_TOOLBAR_ICONS && button->priv->icon_widget == NULL &&
410       button->priv->stock_id == NULL && button->priv->icon_name == NULL)
411     {
412       need_label = TRUE;
413       need_icon = FALSE;
414       style = GTK_TOOLBAR_TEXT;
415     }
416
417   if (style == GTK_TOOLBAR_TEXT && button->priv->label_widget == NULL &&
418       button->priv->stock_id == NULL && button->priv->label_text == NULL)
419     {
420       need_label = FALSE;
421       need_icon = TRUE;
422       style = GTK_TOOLBAR_ICONS;
423     }
424
425   if (need_label)
426     {
427       if (button->priv->label_widget)
428         {
429           label = button->priv->label_widget;
430         }
431       else
432         {
433           GtkStockItem stock_item;
434           gboolean elide;
435           gchar *label_text;
436
437           if (button->priv->label_text)
438             {
439               label_text = button->priv->label_text;
440               elide = button->priv->use_underline;
441             }
442           else if (button->priv->stock_id && gtk_stock_lookup (button->priv->stock_id, &stock_item))
443             {
444               label_text = stock_item.label;
445               elide = TRUE;
446             }
447           else
448             {
449               label_text = "";
450               elide = FALSE;
451             }
452
453           if (elide)
454             label_text = _gtk_toolbar_elide_underscores (label_text);
455           else
456             label_text = g_strdup (label_text);
457
458           label = gtk_label_new (label_text);
459
460           g_free (label_text);
461           
462           gtk_widget_show (label);
463         }
464
465       if (GTK_IS_LABEL (label))
466         {
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)
471             {
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)),
475                                       0.5);
476             }
477           else
478             {
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);
482               else
483                 gtk_label_set_angle (GTK_LABEL (label), 90);
484               gtk_misc_set_alignment (GTK_MISC (label),
485                                       0.5,
486                                       1 - gtk_tool_item_get_text_alignment (GTK_TOOL_ITEM (button)));
487             }
488         }
489     }
490
491   icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (button));
492   if (need_icon)
493     {
494       if (button->priv->icon_widget)
495         {
496           icon = button->priv->icon_widget;
497           
498           if (GTK_IS_IMAGE (icon))
499             {
500               g_object_set (button->priv->icon_widget,
501                             "icon-size", icon_size,
502                             NULL);
503             }
504         }
505       else if (button->priv->stock_id && 
506                gtk_icon_factory_lookup_default (button->priv->stock_id))
507         {
508           icon = gtk_image_new_from_stock (button->priv->stock_id, icon_size);
509           gtk_widget_show (icon);
510         }
511       else if (button->priv->icon_name)
512         {
513           icon = gtk_image_new_from_icon_name (button->priv->icon_name, icon_size);
514           gtk_widget_show (icon);
515         }
516
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)),
520                                 0.5);
521       else if (GTK_IS_MISC (icon))
522         gtk_misc_set_alignment (GTK_MISC (icon),
523                                 0.5,
524                                 gtk_tool_item_get_text_alignment (GTK_TOOL_ITEM (button)));
525
526       if (icon)
527         {
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);
531         }
532     }
533
534   switch (style)
535     {
536     case GTK_TOOLBAR_ICONS:
537       if (icon)
538         gtk_container_add (GTK_CONTAINER (button->priv->button), icon);
539       break;
540
541     case GTK_TOOLBAR_BOTH:
542       if (text_orientation == GTK_ORIENTATION_HORIZONTAL)
543         box = gtk_box_new (GTK_ORIENTATION_VERTICAL, icon_spacing);
544       else
545         box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, icon_spacing);
546       if (icon)
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);
550       break;
551
552     case GTK_TOOLBAR_BOTH_HORIZ:
553       if (text_orientation == GTK_ORIENTATION_HORIZONTAL)
554         {
555           box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, icon_spacing);
556           if (icon)
557             gtk_box_pack_start (GTK_BOX (box), icon, label? FALSE : TRUE, TRUE, 0);
558           if (label)
559             gtk_box_pack_end (GTK_BOX (box), label, TRUE, TRUE, 0);
560         }
561       else
562         {
563           box = gtk_box_new (GTK_ORIENTATION_VERTICAL, icon_spacing);
564           if (icon)
565             gtk_box_pack_end (GTK_BOX (box), icon, label ? FALSE : TRUE, TRUE, 0);
566           if (label)
567             gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
568         }
569       gtk_container_add (GTK_CONTAINER (button->priv->button), box);
570       break;
571
572     case GTK_TOOLBAR_TEXT:
573       gtk_container_add (GTK_CONTAINER (button->priv->button), label);
574       break;
575     }
576
577   if (box)
578     gtk_widget_show (box);
579
580   gtk_button_set_relief (GTK_BUTTON (button->priv->button),
581                          gtk_tool_item_get_relief_style (GTK_TOOL_ITEM (button)));
582
583   gtk_tool_item_rebuild_menu (tool_item);
584   
585   gtk_widget_queue_resize (GTK_WIDGET (button));
586 }
587
588 static void
589 gtk_tool_button_set_property (GObject         *object,
590                               guint            prop_id,
591                               const GValue    *value,
592                               GParamSpec      *pspec)
593 {
594   GtkToolButton *button = GTK_TOOL_BUTTON (object);
595   
596   switch (prop_id)
597     {
598     case PROP_LABEL:
599       gtk_tool_button_set_label (button, g_value_get_string (value));
600       break;
601     case PROP_USE_UNDERLINE:
602       gtk_tool_button_set_use_underline (button, g_value_get_boolean (value));
603       break;
604     case PROP_LABEL_WIDGET:
605       gtk_tool_button_set_label_widget (button, g_value_get_object (value));
606       break;
607     case PROP_STOCK_ID:
608       gtk_tool_button_set_stock_id (button, g_value_get_string (value));
609       break;
610     case PROP_ICON_NAME:
611       gtk_tool_button_set_icon_name (button, g_value_get_string (value));
612       break;
613     case PROP_ICON_WIDGET:
614       gtk_tool_button_set_icon_widget (button, g_value_get_object (value));
615       break;
616     default:
617       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
618       break;
619     }
620 }
621
622 static void
623 gtk_tool_button_property_notify (GObject          *object,
624                                  GParamSpec       *pspec)
625 {
626   GtkToolButton *button = GTK_TOOL_BUTTON (object);
627
628   if (button->priv->contents_invalid ||
629       strcmp ("is-important", pspec->name) == 0)
630     gtk_tool_button_construct_contents (GTK_TOOL_ITEM (object));
631
632   if (parent_class->notify)
633     parent_class->notify (object, pspec);
634 }
635
636 static void
637 gtk_tool_button_get_property (GObject         *object,
638                               guint            prop_id,
639                               GValue          *value,
640                               GParamSpec      *pspec)
641 {
642   GtkToolButton *button = GTK_TOOL_BUTTON (object);
643
644   switch (prop_id)
645     {
646     case PROP_LABEL:
647       g_value_set_string (value, gtk_tool_button_get_label (button));
648       break;
649     case PROP_LABEL_WIDGET:
650       g_value_set_object (value, gtk_tool_button_get_label_widget (button));
651       break;
652     case PROP_USE_UNDERLINE:
653       g_value_set_boolean (value, gtk_tool_button_get_use_underline (button));
654       break;
655     case PROP_STOCK_ID:
656       g_value_set_string (value, button->priv->stock_id);
657       break;
658     case PROP_ICON_NAME:
659       g_value_set_string (value, button->priv->icon_name);
660       break;
661     case PROP_ICON_WIDGET:
662       g_value_set_object (value, button->priv->icon_widget);
663       break;
664     default:
665       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
666       break;
667     }
668 }
669
670 static void
671 gtk_tool_button_finalize (GObject *object)
672 {
673   GtkToolButton *button = GTK_TOOL_BUTTON (object);
674
675   g_free (button->priv->stock_id);
676   g_free (button->priv->icon_name);
677   g_free (button->priv->label_text);
678
679   if (button->priv->label_widget)
680     g_object_unref (button->priv->label_widget);
681
682   if (button->priv->icon_widget)
683     g_object_unref (button->priv->icon_widget);
684   
685   parent_class->finalize (object);
686 }
687
688 static GtkWidget *
689 clone_image_menu_size (GtkImage *image, GtkSettings *settings)
690 {
691   GtkImageType storage_type = gtk_image_get_storage_type (image);
692
693   if (storage_type == GTK_IMAGE_STOCK)
694     {
695       gchar *stock_id;
696       gtk_image_get_stock (image, &stock_id, NULL);
697       return gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU);
698     }
699   else if (storage_type == GTK_IMAGE_ICON_NAME)
700     {
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);
704     }
705   else if (storage_type == GTK_IMAGE_ICON_SET)
706     {
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);
710     }
711   else if (storage_type == GTK_IMAGE_GICON)
712     {
713       GIcon *icon;
714       gtk_image_get_gicon (image, &icon, NULL);
715       return gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_MENU);
716     }
717   else if (storage_type == GTK_IMAGE_PIXBUF)
718     {
719       gint width, height;
720       
721       if (settings &&
722           gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
723                                              &width, &height))
724         {
725           GdkPixbuf *src_pixbuf, *dest_pixbuf;
726           GtkWidget *cloned_image;
727
728           src_pixbuf = gtk_image_get_pixbuf (image);
729           dest_pixbuf = gdk_pixbuf_scale_simple (src_pixbuf, width, height,
730                                                  GDK_INTERP_BILINEAR);
731
732           cloned_image = gtk_image_new_from_pixbuf (dest_pixbuf);
733           g_object_unref (dest_pixbuf);
734
735           return cloned_image;
736         }
737     }
738
739   return NULL;
740 }
741       
742 static gboolean
743 gtk_tool_button_create_menu_proxy (GtkToolItem *item)
744 {
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;
750   const char *label;
751
752   if (_gtk_tool_item_create_menu_proxy (item))
753     return TRUE;
754  
755   if (GTK_IS_LABEL (button->priv->label_widget))
756     {
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));
759     }
760   else if (button->priv->label_text)
761     {
762       label = button->priv->label_text;
763       use_mnemonic = button->priv->use_underline;
764     }
765   else if (button->priv->stock_id && gtk_stock_lookup (button->priv->stock_id, &stock_item))
766     {
767       label = stock_item.label;
768     }
769   else
770     {
771       label = "";
772     }
773   
774   if (use_mnemonic)
775     menu_item = gtk_image_menu_item_new_with_mnemonic (label);
776   else
777     menu_item = gtk_image_menu_item_new_with_label (label);
778
779   if (GTK_IS_IMAGE (button->priv->icon_widget))
780     {
781       menu_image = clone_image_menu_size (GTK_IMAGE (button->priv->icon_widget),
782                                           gtk_widget_get_settings (GTK_WIDGET (button)));
783     }
784   else if (button->priv->stock_id)
785     {
786       menu_image = gtk_image_new_from_stock (button->priv->stock_id, GTK_ICON_SIZE_MENU);
787     }
788
789   if (menu_image)
790     gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), menu_image);
791
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)),
796                                   FALSE);
797
798   gtk_tool_item_set_proxy_menu_item (GTK_TOOL_ITEM (button), MENU_ID, menu_item);
799   
800   return TRUE;
801 }
802
803 static void
804 button_clicked (GtkWidget     *widget,
805                 GtkToolButton *button)
806 {
807   GtkAction *action;
808
809   action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (button));
810   
811   if (action)
812     gtk_action_activate (action);
813
814   g_signal_emit_by_name (button, "clicked");
815 }
816
817 static void
818 gtk_tool_button_toolbar_reconfigured (GtkToolItem *tool_item)
819 {
820   gtk_tool_button_construct_contents (tool_item);
821 }
822
823 static void 
824 gtk_tool_button_update_icon_spacing (GtkToolButton *button)
825 {
826   GtkWidget *box;
827   guint spacing;
828
829   box = gtk_bin_get_child (GTK_BIN (button->priv->button));
830   if (GTK_IS_BOX (box))
831     {
832       gtk_widget_style_get (GTK_WIDGET (button), 
833                             "icon-spacing", &spacing,
834                             NULL);
835       gtk_box_set_spacing (GTK_BOX (box), spacing);      
836     }
837 }
838
839 static void
840 gtk_tool_button_style_updated (GtkWidget *widget)
841 {
842   GTK_WIDGET_CLASS (parent_class)->style_updated (widget);
843
844   gtk_tool_button_update_icon_spacing (GTK_TOOL_BUTTON (widget));
845 }
846
847 static void 
848 gtk_tool_button_activatable_interface_init (GtkActivatableIface  *iface)
849 {
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;
853 }
854
855 static void
856 gtk_tool_button_update (GtkActivatable *activatable,
857                         GtkAction      *action,
858                         const gchar    *property_name)
859 {
860   GtkToolButton *button;
861   GtkWidget *image;
862
863   parent_activatable_iface->update (activatable, action, property_name);
864
865   if (!gtk_activatable_get_use_action_appearance (activatable))
866     return;
867
868   button = GTK_TOOL_BUTTON (activatable);
869   
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)
875     {
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;
879
880       if ((stock_id && gtk_icon_factory_lookup_default (stock_id)) || !icon)
881         image = NULL;
882       else 
883         {   
884           image = gtk_tool_button_get_icon_widget (button);
885           icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (button));
886
887           if (!image)
888             image = gtk_image_new ();
889         }
890
891       gtk_tool_button_set_icon_widget (button, image);
892       gtk_image_set_from_gicon (GTK_IMAGE (image), icon, icon_size);
893
894     }
895   else if (strcmp (property_name, "icon-name") == 0)
896     gtk_tool_button_set_icon_name (button, gtk_action_get_icon_name (action));
897 }
898
899 static void
900 gtk_tool_button_sync_action_properties (GtkActivatable *activatable,
901                                         GtkAction      *action)
902 {
903   GtkToolButton *button;
904   GIcon         *icon;
905   const gchar   *stock_id;
906
907   parent_activatable_iface->sync_action_properties (activatable, action);
908
909   if (!action)
910     return;
911
912   if (!gtk_activatable_get_use_action_appearance (activatable))
913     return;
914
915   button = GTK_TOOL_BUTTON (activatable);
916   stock_id = gtk_action_get_stock_id (action);
917
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));
922
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)
926     {
927       GtkIconSize icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (button));
928       GtkWidget  *image = gtk_tool_button_get_icon_widget (button);
929       
930       if (!image)
931         {
932           image = gtk_image_new ();
933           gtk_widget_show (image);
934           gtk_tool_button_set_icon_widget (button, image);
935         }
936
937       gtk_image_set_from_gicon (GTK_IMAGE (image), icon, icon_size);
938     }
939   else if (gtk_action_get_icon_name (action))
940     gtk_tool_button_set_icon_name (button, gtk_action_get_icon_name (action));
941   else
942     gtk_tool_button_set_label (button, gtk_action_get_short_label (action));
943 }
944
945 /**
946  * gtk_tool_button_new_from_stock:
947  * @stock_id: the name of the stock item 
948  *
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.
952  *
953  * It is an error if @stock_id is not a name of a stock item.
954  * 
955  * Return value: A new #GtkToolButton
956  * 
957  * Since: 2.4
958  **/
959 GtkToolItem *
960 gtk_tool_button_new_from_stock (const gchar *stock_id)
961 {
962   GtkToolButton *button;
963
964   g_return_val_if_fail (stock_id != NULL, NULL);
965     
966   button = g_object_new (GTK_TYPE_TOOL_BUTTON,
967                          "stock-id", stock_id,
968                          NULL);
969
970   return GTK_TOOL_ITEM (button);
971 }
972
973 /**
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
977  *
978  * Creates a new %GtkToolButton using @icon_widget as icon and @label as
979  * label.
980  *
981  * Return value: A new #GtkToolButton
982  * 
983  * Since: 2.4
984  **/
985 GtkToolItem *
986 gtk_tool_button_new (GtkWidget   *icon_widget,
987                      const gchar *label)
988 {
989   GtkToolButton *button;
990
991   g_return_val_if_fail (icon_widget == NULL || GTK_IS_MISC (icon_widget), NULL);
992
993   button = g_object_new (GTK_TYPE_TOOL_BUTTON,
994                          "label", label,
995                          "icon-widget", icon_widget,
996                          NULL);
997
998   return GTK_TOOL_ITEM (button);  
999 }
1000
1001 /**
1002  * gtk_tool_button_set_label:
1003  * @button: a #GtkToolButton
1004  * @label: (allow-none): a string that will be used as label, or %NULL.
1005  *
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.
1011  * 
1012  * Since: 2.4
1013  **/
1014 void
1015 gtk_tool_button_set_label (GtkToolButton *button,
1016                            const gchar   *label)
1017 {
1018   gchar *old_label;
1019   gchar *elided_label;
1020   AtkObject *accessible;
1021   
1022   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
1023
1024   old_label = button->priv->label_text;
1025
1026   button->priv->label_text = g_strdup (label);
1027   button->priv->contents_invalid = TRUE;     
1028
1029   if (label)
1030     {
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);
1035     }
1036
1037   g_free (old_label);
1038  
1039   g_object_notify (G_OBJECT (button), "label");
1040 }
1041
1042 /**
1043  * gtk_tool_button_get_label:
1044  * @button: a #GtkToolButton
1045  * 
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.
1049  * 
1050  * Return value: The label, or %NULL
1051  * 
1052  * Since: 2.4
1053  **/
1054 G_CONST_RETURN gchar *
1055 gtk_tool_button_get_label (GtkToolButton *button)
1056 {
1057   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1058
1059   return button->priv->label_text;
1060 }
1061
1062 /**
1063  * gtk_tool_button_set_use_underline:
1064  * @button: a #GtkToolButton
1065  * @use_underline: whether the button label has the form "_Open"
1066  *
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'.
1072  * 
1073  * Labels shown on tool buttons never have mnemonics on them; this property
1074  * only affects the menu item on the overflow menu.
1075  * 
1076  * Since: 2.4
1077  **/
1078 void
1079 gtk_tool_button_set_use_underline (GtkToolButton *button,
1080                                    gboolean       use_underline)
1081 {
1082   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
1083
1084   use_underline = use_underline != FALSE;
1085
1086   if (use_underline != button->priv->use_underline)
1087     {
1088       button->priv->use_underline = use_underline;
1089       button->priv->contents_invalid = TRUE;
1090
1091       g_object_notify (G_OBJECT (button), "use-underline");
1092     }
1093 }
1094
1095 /**
1096  * gtk_tool_button_get_use_underline:
1097  * @button: a #GtkToolButton
1098  * 
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().
1101  * 
1102  * Return value: %TRUE if underscores in the label property are used as
1103  * mnemonics on menu items on the overflow menu.
1104  * 
1105  * Since: 2.4
1106  **/
1107 gboolean
1108 gtk_tool_button_get_use_underline (GtkToolButton *button)
1109 {
1110   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), FALSE);
1111
1112   return button->priv->use_underline;
1113 }
1114
1115 /**
1116  * gtk_tool_button_set_stock_id:
1117  * @button: a #GtkToolButton
1118  * @stock_id: (allow-none): a name of a stock item, or %NULL
1119  *
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.
1123  * 
1124  * Since: 2.4
1125  **/
1126 void
1127 gtk_tool_button_set_stock_id (GtkToolButton *button,
1128                               const gchar   *stock_id)
1129 {
1130   gchar *old_stock_id;
1131   
1132   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
1133
1134   old_stock_id = button->priv->stock_id;
1135
1136   button->priv->stock_id = g_strdup (stock_id);
1137   button->priv->contents_invalid = TRUE;
1138
1139   g_free (old_stock_id);
1140   
1141   g_object_notify (G_OBJECT (button), "stock-id");
1142 }
1143
1144 /**
1145  * gtk_tool_button_get_stock_id:
1146  * @button: a #GtkToolButton
1147  * 
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.
1150  * 
1151  * Return value: the name of the stock item for @button.
1152  * 
1153  * Since: 2.4
1154  **/
1155 G_CONST_RETURN gchar *
1156 gtk_tool_button_get_stock_id (GtkToolButton *button)
1157 {
1158   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1159
1160   return button->priv->stock_id;
1161 }
1162
1163 /**
1164  * gtk_tool_button_set_icon_name
1165  * @button: a #GtkToolButton
1166  * @icon_name: (allow-none): the name of the themed icon
1167  *
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"
1172  * properties.
1173  * 
1174  * Since: 2.8
1175  **/
1176 void
1177 gtk_tool_button_set_icon_name (GtkToolButton *button,
1178                                const gchar   *icon_name)
1179 {
1180   gchar *old_icon_name;
1181
1182   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
1183
1184   old_icon_name = button->priv->icon_name;
1185
1186   button->priv->icon_name = g_strdup (icon_name);
1187   button->priv->contents_invalid = TRUE; 
1188
1189   g_free (old_icon_name);
1190
1191   g_object_notify (G_OBJECT (button), "icon-name");
1192 }
1193
1194 /**
1195  * gtk_tool_button_get_icon_name
1196  * @button: a #GtkToolButton
1197  * 
1198  * Returns the name of the themed icon for the tool button,
1199  * see gtk_tool_button_set_icon_name().
1200  *
1201  * Returns: the icon name or %NULL if the tool button has
1202  * no themed icon
1203  * 
1204  * Since: 2.8
1205  **/
1206 G_CONST_RETURN gchar*
1207 gtk_tool_button_get_icon_name (GtkToolButton *button)
1208 {
1209   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1210
1211   return button->priv->icon_name;
1212 }
1213
1214 /**
1215  * gtk_tool_button_set_icon_widget:
1216  * @button: a #GtkToolButton
1217  * @icon_widget: (allow-none): the widget used as icon, or %NULL
1218  *
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.
1222  * 
1223  * Since: 2.4
1224  **/
1225 void
1226 gtk_tool_button_set_icon_widget (GtkToolButton *button,
1227                                  GtkWidget     *icon_widget)
1228 {
1229   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
1230   g_return_if_fail (icon_widget == NULL || GTK_IS_WIDGET (icon_widget));
1231
1232   if (icon_widget != button->priv->icon_widget)
1233     {
1234       if (button->priv->icon_widget)
1235         {
1236           GtkWidget *parent;
1237
1238           parent = gtk_widget_get_parent (button->priv->icon_widget);
1239           if (parent)
1240             gtk_container_remove (GTK_CONTAINER (parent),
1241                                   button->priv->icon_widget);
1242
1243           g_object_unref (button->priv->icon_widget);
1244         }
1245       
1246       if (icon_widget)
1247         g_object_ref_sink (icon_widget);
1248
1249       button->priv->icon_widget = icon_widget;
1250       button->priv->contents_invalid = TRUE;
1251       
1252       g_object_notify (G_OBJECT (button), "icon-widget");
1253     }
1254 }
1255
1256 /**
1257  * gtk_tool_button_set_label_widget:
1258  * @button: a #GtkToolButton
1259  * @label_widget: (allow-none): the widget used as label, or %NULL
1260  *
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.
1266  * 
1267  * Since: 2.4
1268  **/
1269 void
1270 gtk_tool_button_set_label_widget (GtkToolButton *button,
1271                                   GtkWidget     *label_widget)
1272 {
1273   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
1274   g_return_if_fail (label_widget == NULL || GTK_IS_WIDGET (label_widget));
1275
1276   if (label_widget != button->priv->label_widget)
1277     {
1278       if (button->priv->label_widget)
1279         {
1280           GtkWidget *parent;
1281
1282           parent = gtk_widget_get_parent (button->priv->label_widget);
1283           if (parent)
1284             gtk_container_remove (GTK_CONTAINER (parent),
1285                                   button->priv->label_widget);
1286
1287           g_object_unref (button->priv->label_widget);
1288         }
1289       
1290       if (label_widget)
1291         g_object_ref_sink (label_widget);
1292
1293       button->priv->label_widget = label_widget;
1294       button->priv->contents_invalid = TRUE;
1295       
1296       g_object_notify (G_OBJECT (button), "label-widget");
1297     }
1298 }
1299
1300 /**
1301  * gtk_tool_button_get_label_widget:
1302  * @button: a #GtkToolButton
1303  *
1304  * Returns the widget used as label on @button.
1305  * See gtk_tool_button_set_label_widget().
1306  *
1307  * Return value: (transfer none): The widget used as label
1308  *     on @button, or %NULL.
1309  *
1310  * Since: 2.4
1311  **/
1312 GtkWidget *
1313 gtk_tool_button_get_label_widget (GtkToolButton *button)
1314 {
1315   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1316
1317   return button->priv->label_widget;
1318 }
1319
1320 /**
1321  * gtk_tool_button_get_icon_widget:
1322  * @button: a #GtkToolButton
1323  *
1324  * Return the widget used as icon widget on @button.
1325  * See gtk_tool_button_set_icon_widget().
1326  *
1327  * Return value: (transfer none): The widget used as icon
1328  *     on @button, or %NULL.
1329  *
1330  * Since: 2.4
1331  **/
1332 GtkWidget *
1333 gtk_tool_button_get_icon_widget (GtkToolButton *button)
1334 {
1335   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1336
1337   return button->priv->icon_widget;
1338 }
1339
1340 GtkWidget *
1341 _gtk_tool_button_get_button (GtkToolButton *button)
1342 {
1343   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1344
1345   return button->priv->button;
1346 }