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