]> Pileus Git - ~andy/gtk/blob - gtk/gtktoolbutton.c
5382b7d11d27ae108aa14b59a817bac796489959
[~andy/gtk] / gtk / gtktoolbutton.c
1 /* gtktoolbutton.c
2  *
3  * Copyright (C) 2002 Anders Carlsson <andersca@codefactory.se>
4  * Copyright (C) 2002 James Henstridge <james@daa.com.au>
5  * Copyright (C) 2003 Soeren Sandmann <sandmann@daimi.au.dk>
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 "gtktoolbutton.h"
24 #include "gtkbutton.h"
25 #include "gtkhbox.h"
26 #include "gtkiconfactory.h"
27 #include "gtkimage.h"
28 #include "gtkimagemenuitem.h"
29 #include "gtklabel.h"
30 #include "gtkstock.h"
31 #include "gtkvbox.h"
32 #include "gtkintl.h"
33 #include "gtktoolbar.h"
34 #include "gtkiconfactory.h"
35
36 #include <string.h>
37
38 #define MENU_ID "gtk-tool-button-menu-id"
39
40 enum {
41   CLICKED,
42   LAST_SIGNAL
43 };
44
45 enum {
46   PROP_0,
47   PROP_LABEL,
48   PROP_USE_UNDERLINE,
49   PROP_LABEL_WIDGET,
50   PROP_STOCK_ID,
51   PROP_ICON_WIDGET,
52 };
53
54 static void gtk_tool_button_init          (GtkToolButton      *button,
55                                            GtkToolButtonClass *klass);
56 static void gtk_tool_button_class_init    (GtkToolButtonClass *klass);
57 static void gtk_tool_button_set_property  (GObject            *object,
58                                            guint               prop_id,
59                                            const GValue       *value,
60                                            GParamSpec         *pspec);
61 static void gtk_tool_button_get_property  (GObject            *object,
62                                            guint               prop_id,
63                                            GValue             *value,
64                                            GParamSpec         *pspec);
65 static void gtk_tool_button_property_notify (GObject          *object,
66                                              GParamSpec       *pspec);
67 static void gtk_tool_button_finalize      (GObject            *object);
68
69 static void gtk_tool_button_toolbar_reconfigured (GtkToolItem *tool_item);
70 static gboolean   gtk_tool_button_create_menu_proxy (GtkToolItem     *item);
71 static void       button_clicked                    (GtkWidget       *widget,
72                                                      GtkToolButton   *button);
73
74 static void gtk_tool_button_construct_contents (GtkToolItem *tool_item);
75       
76 static GObjectClass *parent_class = NULL;
77 static guint         toolbutton_signals[LAST_SIGNAL] = { 0 };
78
79 struct _GtkToolButtonPrivate
80 {
81   GtkWidget *button;
82
83   gchar *stock_id;
84   gchar *label_text;
85   GtkWidget *label_widget;
86   GtkWidget *icon_widget;
87   
88   guint use_underline : 1;
89 };
90
91 GType
92 gtk_tool_button_get_type (void)
93 {
94   static GtkType type = 0;
95
96   if (!type)
97     {
98       static const GTypeInfo type_info =
99         {
100           sizeof (GtkToolButtonClass),
101           (GBaseInitFunc) NULL,
102           (GBaseFinalizeFunc) NULL,
103           (GClassInitFunc) gtk_tool_button_class_init,
104           (GClassFinalizeFunc) NULL,
105           NULL,
106           sizeof (GtkToolButton),
107           0, /* n_preallocs */
108           (GInstanceInitFunc) gtk_tool_button_init,
109         };
110
111       type = g_type_register_static (GTK_TYPE_TOOL_ITEM,
112                                      "GtkToolButton",
113                                      &type_info, 0);
114     }
115   return type;
116 }
117
118 static void
119 gtk_tool_button_class_init (GtkToolButtonClass *klass)
120 {
121   GObjectClass *object_class;
122   GtkWidgetClass *widget_class;
123   GtkToolItemClass *tool_item_class;
124   
125   parent_class = g_type_class_peek_parent (klass);
126   
127   object_class = (GObjectClass *)klass;
128   widget_class = (GtkWidgetClass *)klass;
129   tool_item_class = (GtkToolItemClass *)klass;
130   
131   object_class->set_property = gtk_tool_button_set_property;
132   object_class->get_property = gtk_tool_button_get_property;
133   object_class->notify = gtk_tool_button_property_notify;
134   object_class->finalize = gtk_tool_button_finalize;
135
136   tool_item_class->create_menu_proxy = gtk_tool_button_create_menu_proxy;
137   tool_item_class->toolbar_reconfigured = gtk_tool_button_toolbar_reconfigured;
138   
139   klass->button_type = GTK_TYPE_BUTTON;
140
141   /* Properties are interpreted like this:
142    *
143    *          - if the tool button has an icon_widget, then that widget
144    *            will be used as the icon. Otherwise, if the tool button
145    *            has a stock id, the corresponding stock icon will be
146    *            used. Otherwise, the tool button will not have an icon.
147    *
148    *          - if the tool button has a label_widget then that widget
149    *            will be used as the label. Otherwise, if the tool button
150    *            has a label text, that text will be used as label. Otherwise,
151    *            if the toolbutton has a stock id, the corresponding text
152    *            will be used as label. Otherwise, the toolbutton will
153    *            have an empty label.
154    *
155    *          - The use_underline property only has an effect when the label
156    *            on the toolbutton comes from the label property (ie. not from
157    *            label_widget or from stock_id).
158    *
159    *            In that case, if use_underline is set,
160    *
161    *                    - underscores are removed from the label text before
162    *                      the label is shown on the toolbutton unless the
163    *                      underscore is followed by another underscore
164    *
165    *                    - an underscore indicates that the next character when
166    *                      used in the overflow menu should be used as a
167    *                      mnemonic.
168    *
169    *            In short: use_underline = TRUE means that the label text has
170    *            the form "_Open" and the toolbar should take appropriate
171    *            action.
172    */
173
174   g_object_class_install_property (object_class,
175                                    PROP_LABEL,
176                                    g_param_spec_string ("label",
177                                                         _("Label"),
178                                                         _("Text to show in the item."),
179                                                         NULL,
180                                                         G_PARAM_READWRITE));
181   g_object_class_install_property (object_class,
182                                    PROP_USE_UNDERLINE,
183                                    g_param_spec_boolean ("use_underline",
184                                                          _("Use underline"),
185                                                          _("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"),
186                                                          FALSE,
187                                                          G_PARAM_READWRITE));
188   g_object_class_install_property (object_class,
189                                    PROP_LABEL_WIDGET,
190                                    g_param_spec_object ("label_widget",
191                                                         _("Label widget"),
192                                                         _("Widget to use as the item label"),
193                                                         GTK_TYPE_WIDGET,
194                                                         G_PARAM_READWRITE));
195   g_object_class_install_property (object_class,
196                                    PROP_STOCK_ID,
197                                    g_param_spec_string ("stock_id",
198                                                         _("Stock Id"),
199                                                         _("The stock icon displayed on the item"),
200                                                         NULL,
201                                                         G_PARAM_READWRITE));
202   g_object_class_install_property (object_class,
203                                    PROP_ICON_WIDGET,
204                                    g_param_spec_object ("icon_widget",
205                                                         _("Icon widget"),
206                                                         _("Icon widget to display in the item"),
207                                                         GTK_TYPE_WIDGET,
208                                                         G_PARAM_READWRITE));
209
210 /**
211  * GtkToolButton::clicked:
212  * @toolbutton: the object that emitted the signal
213  *
214  * This signal is emitted when the tool button is clicked with the mouse
215  * or activated with the keyboard.
216  **/
217   toolbutton_signals[CLICKED] =
218     g_signal_new ("clicked",
219                   G_OBJECT_CLASS_TYPE (klass),
220                   G_SIGNAL_RUN_FIRST,
221                   G_STRUCT_OFFSET (GtkToolButtonClass, clicked),
222                   NULL, NULL,
223                   g_cclosure_marshal_VOID__VOID,
224                   G_TYPE_NONE, 0);
225   
226   g_type_class_add_private (object_class, sizeof (GtkToolButtonPrivate));
227 }
228
229 static void
230 gtk_tool_button_init (GtkToolButton      *button,
231                       GtkToolButtonClass *klass)
232 {
233   GtkToolItem *toolitem = GTK_TOOL_ITEM (button);
234   
235   button->priv = GTK_TOOL_BUTTON_GET_PRIVATE (button);
236
237   gtk_tool_item_set_homogeneous (toolitem, TRUE);
238
239   /* create button */
240   button->priv->button = g_object_new (klass->button_type, NULL);
241   gtk_button_set_focus_on_click (GTK_BUTTON (button->priv->button), FALSE);
242   g_signal_connect_object (button->priv->button, "clicked",
243                            G_CALLBACK (button_clicked), button, 0);
244
245   gtk_container_add (GTK_CONTAINER (button), button->priv->button);
246   gtk_widget_show (button->priv->button);
247 }
248
249 static void
250 gtk_tool_button_construct_contents (GtkToolItem *tool_item)
251 {
252   GtkToolButton *button = GTK_TOOL_BUTTON (tool_item);
253   GtkWidget *label = NULL;
254   GtkWidget *icon = NULL;
255   GtkToolbarStyle style;
256   gboolean need_label = FALSE;
257   gboolean need_icon = FALSE;
258   GtkIconSize icon_size;
259   GtkWidget *box = NULL;
260
261   if (gtk_tool_item_get_proxy_menu_item (tool_item, MENU_ID))
262     {
263       /* Remove item, so it will be recreated on the next
264        * create_proxy_menu_item()
265        */
266       gtk_tool_item_set_proxy_menu_item (tool_item, MENU_ID, NULL);
267     }
268   
269   if (button->priv->icon_widget && button->priv->icon_widget->parent)
270     {
271       gtk_container_remove (GTK_CONTAINER (button->priv->icon_widget->parent),
272                             button->priv->icon_widget);
273     }
274
275   if (button->priv->label_widget && button->priv->label_widget->parent)
276     {
277       gtk_container_remove (GTK_CONTAINER (button->priv->label_widget->parent),
278                             button->priv->label_widget);
279     }
280
281   if (GTK_BIN (button->priv->button)->child)
282     {
283       /* Note: we are not destroying the label_widget or icon_widget
284        * here because they were removed from their containers above
285        */
286       gtk_widget_destroy (GTK_BIN (button->priv->button)->child);
287     }
288
289   style = gtk_tool_item_get_toolbar_style (GTK_TOOL_ITEM (button));
290   
291   if (style != GTK_TOOLBAR_TEXT)
292     need_icon = TRUE;
293
294   if (style != GTK_TOOLBAR_ICONS && style != GTK_TOOLBAR_BOTH_HORIZ)
295     need_label = TRUE;
296
297   if (style == GTK_TOOLBAR_BOTH_HORIZ &&
298       (gtk_tool_item_get_is_important (GTK_TOOL_ITEM (button)) ||
299        gtk_tool_item_get_orientation (GTK_TOOL_ITEM (button)) == GTK_ORIENTATION_VERTICAL))
300     {
301       need_label = TRUE;
302     }
303   
304   if (style != GTK_TOOLBAR_ICONS &&
305       ((style != GTK_TOOLBAR_BOTH_HORIZ ||
306         gtk_tool_item_get_is_important (GTK_TOOL_ITEM (button)))))
307     need_label = TRUE;
308   
309   if (need_label)
310     {
311       if (button->priv->label_widget)
312         {
313           label = button->priv->label_widget;
314         }
315       else
316         {
317           GtkStockItem stock_item;
318           gboolean elide;
319           gchar *label_text;
320
321           if (button->priv->label_text)
322             {
323               label_text = button->priv->label_text;
324               elide = button->priv->use_underline;
325             }
326           else if (button->priv->stock_id && gtk_stock_lookup (button->priv->stock_id, &stock_item))
327             {
328               label_text = stock_item.label;
329               elide = TRUE;
330             }
331           else
332             {
333               label_text = "";
334               elide = FALSE;
335             }
336
337           if (elide)
338             label_text = _gtk_toolbar_elide_underscores (label_text);
339           else
340             label_text = g_strdup (label_text);
341
342           label = gtk_label_new (label_text);
343
344           g_free (label_text);
345           
346           gtk_widget_show (label);
347         }
348     }
349
350   icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (button));
351   if (need_icon)
352     {
353       if (button->priv->icon_widget)
354         {
355           icon = button->priv->icon_widget;
356           
357           if (GTK_IS_IMAGE (icon))
358             {
359               g_object_set (G_OBJECT (button->priv->icon_widget),
360                             "icon-size", icon_size,
361                             NULL);
362             }
363         }
364       else if (button->priv->stock_id)
365         {
366           icon = gtk_image_new_from_stock (button->priv->stock_id, icon_size);
367           gtk_widget_show (icon);
368         }
369     }
370
371   switch (style)
372     {
373     case GTK_TOOLBAR_ICONS:
374       if (icon)
375         gtk_container_add (GTK_CONTAINER (button->priv->button), icon);
376       break;
377
378     case GTK_TOOLBAR_BOTH:
379       box = gtk_vbox_new (FALSE, 0);
380       if (icon)
381         gtk_box_pack_start (GTK_BOX (box), icon, TRUE, TRUE, 0);
382       gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 0);
383       gtk_container_add (GTK_CONTAINER (button->priv->button), box);
384       break;
385
386     case GTK_TOOLBAR_BOTH_HORIZ:
387       box = gtk_hbox_new (FALSE, 0);
388       gtk_box_pack_start (GTK_BOX (box), icon, label? FALSE : TRUE, TRUE, 0);
389       if (label)
390         gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
391       gtk_container_add (GTK_CONTAINER (button->priv->button), box);
392       break;
393
394     case GTK_TOOLBAR_TEXT:
395       gtk_container_add (GTK_CONTAINER (button->priv->button), label);
396       break;
397     }
398
399   if (box)
400     gtk_widget_show (box);
401
402   gtk_button_set_relief (GTK_BUTTON (button->priv->button),
403                          gtk_tool_item_get_relief_style (GTK_TOOL_ITEM (button)));
404
405   gtk_widget_queue_resize (GTK_WIDGET (button));
406 }
407
408 static void
409 gtk_tool_button_set_property (GObject         *object,
410                               guint            prop_id,
411                               const GValue    *value,
412                               GParamSpec      *pspec)
413 {
414   GtkToolButton *button = GTK_TOOL_BUTTON (object);
415   
416   switch (prop_id)
417     {
418     case PROP_LABEL:
419       gtk_tool_button_set_label (button, g_value_get_string (value));
420       break;
421     case PROP_USE_UNDERLINE:
422       gtk_tool_button_set_use_underline (button, g_value_get_boolean (value));
423       break;
424     case PROP_LABEL_WIDGET:
425       gtk_tool_button_set_label_widget (button, g_value_get_object (value));
426       break;
427     case PROP_STOCK_ID:
428       gtk_tool_button_set_stock_id (button, g_value_get_string (value));
429       break;
430     case PROP_ICON_WIDGET:
431       gtk_tool_button_set_icon_widget (button, g_value_get_object (value));
432       break;
433     default:
434       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
435     }
436 }
437
438 static void
439 gtk_tool_button_property_notify (GObject          *object,
440                                  GParamSpec       *pspec)
441 {
442   if (strcmp (pspec->name, "is_important"))
443     gtk_tool_button_construct_contents (GTK_TOOL_ITEM (object));
444 }
445
446 static void
447 gtk_tool_button_get_property (GObject         *object,
448                               guint            prop_id,
449                               GValue          *value,
450                               GParamSpec      *pspec)
451 {
452   GtkToolButton *button = GTK_TOOL_BUTTON (object);
453
454   switch (prop_id)
455     {
456     case PROP_LABEL:
457       g_value_set_string (value, gtk_tool_button_get_label (button));
458       break;
459     case PROP_LABEL_WIDGET:
460       g_value_set_object (value, gtk_tool_button_get_label_widget (button));
461       break;
462     case PROP_USE_UNDERLINE:
463       g_value_set_boolean (value, gtk_tool_button_get_use_underline (button));
464       break;
465     case PROP_STOCK_ID:
466       g_value_set_string (value, button->priv->stock_id);
467       break;
468     case PROP_ICON_WIDGET:
469       g_value_set_object (value, button->priv->icon_widget);
470       break;
471     default:
472       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
473     }
474 }
475
476 static void
477 gtk_tool_button_finalize (GObject *object)
478 {
479   GtkToolButton *button = GTK_TOOL_BUTTON (object);
480
481   if (button->priv->stock_id)
482     g_free (button->priv->stock_id);
483
484   if (button->priv->label_text)
485     g_free (button->priv->label_text);
486
487   if (button->priv->label_widget)
488     g_object_unref (G_OBJECT (button->priv->label_widget));
489
490   if (button->priv->icon_widget)
491     g_object_unref (G_OBJECT (button->priv->icon_widget));
492   
493   parent_class->finalize (object);
494 }
495
496 static GtkWidget *
497 clone_image_menu_size (GtkImage *image, GtkSettings *settings)
498 {
499   GtkImageType storage_type = gtk_image_get_storage_type (image);
500
501   if (storage_type == GTK_IMAGE_STOCK)
502     {
503       gchar *stock_id;
504       gtk_image_get_stock (image, &stock_id, NULL);
505       return gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU);
506     }
507   else if (storage_type == GTK_IMAGE_ICON_SET)
508     {
509       GtkIconSet *icon_set;
510       gtk_image_get_icon_set (image, &icon_set, NULL);
511       return gtk_image_new_from_icon_set (icon_set, GTK_ICON_SIZE_MENU);
512     }
513   else if (storage_type == GTK_IMAGE_PIXBUF)
514     {
515       gint width, height;
516       
517       if (settings &&
518           gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
519                                              &width, &height))
520         {
521           GdkPixbuf *src_pixbuf, *dest_pixbuf;
522
523           src_pixbuf = gtk_image_get_pixbuf (image);
524           dest_pixbuf = gdk_pixbuf_scale_simple (src_pixbuf, width, height,
525                                                  GDK_INTERP_BILINEAR);
526
527           return gtk_image_new_from_pixbuf (dest_pixbuf);
528         }
529     }
530
531   return NULL;
532 }
533       
534 static gboolean
535 gtk_tool_button_create_menu_proxy (GtkToolItem *item)
536 {
537   GtkToolButton *button = GTK_TOOL_BUTTON (item);
538   GtkWidget *menu_item;
539   GtkWidget *menu_image = NULL;
540   GtkStockItem stock_item;
541   gboolean use_mnemonic = TRUE;
542   const char *label;
543
544   if (button->priv->label_widget && GTK_IS_LABEL (button->priv->label_widget))
545     {
546       label = gtk_label_get_label (GTK_LABEL (button->priv->label_widget));
547       use_mnemonic = gtk_label_get_use_underline (GTK_LABEL (button->priv->label_widget));
548     }
549   else if (button->priv->label_text)
550     {
551       label = button->priv->label_text;
552       use_mnemonic = button->priv->use_underline;
553     }
554   else if (button->priv->stock_id && gtk_stock_lookup (button->priv->stock_id, &stock_item))
555     {
556       label = stock_item.label;
557     }
558   else
559     {
560       label = "";
561     }
562   
563   if (use_mnemonic)
564     menu_item = gtk_image_menu_item_new_with_mnemonic (label);
565   else
566     menu_item = gtk_image_menu_item_new_with_label (label);
567
568   if (button->priv->icon_widget && GTK_IS_IMAGE (button->priv->icon_widget))
569     {
570       menu_image = clone_image_menu_size (GTK_IMAGE (button->priv->icon_widget),
571                                           gtk_widget_get_settings (GTK_WIDGET (button)));
572     }
573   else if (button->priv->stock_id)
574     {
575       menu_image = gtk_image_new_from_stock (button->priv->stock_id, GTK_ICON_SIZE_MENU);
576     }
577
578   if (menu_image)
579     gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), menu_image);
580
581   g_signal_connect_closure_by_id (menu_item,
582                                   g_signal_lookup ("activate", G_OBJECT_TYPE (menu_item)), 0,
583                                   g_cclosure_new_object_swap (G_CALLBACK (gtk_button_clicked),
584                                                               G_OBJECT (GTK_TOOL_BUTTON (button)->priv->button)),
585                                   FALSE);
586
587   gtk_tool_item_set_proxy_menu_item (GTK_TOOL_ITEM (button), MENU_ID, menu_item);
588   
589   return TRUE;
590 }
591
592 static void
593 button_clicked (GtkWidget     *widget,
594                 GtkToolButton *button)
595 {
596   g_signal_emit_by_name (button, "clicked");
597 }
598
599 static void
600 gtk_tool_button_toolbar_reconfigured (GtkToolItem *tool_item)
601 {
602   gtk_tool_button_construct_contents (tool_item);
603 }
604
605 /**
606  * gtk_tool_button_new_from_stock:
607  * @stock_id: the name of the stock item 
608  *
609  * Creates a new #GtkToolButton containing the image and text from a
610  * stock item. Some stock ids have preprocessor macros like #GTK_STOCK_OK
611  * and #GTK_STOCK_APPLY.
612  *
613  * It is an error if @stock_id is not a name of a stock item.
614  * 
615  * Return value: A new #GtkToolButton
616  * 
617  * Since: 2.4
618  **/
619 GtkToolItem *
620 gtk_tool_button_new_from_stock (const gchar *stock_id)
621 {
622   GtkToolButton *button;
623
624   g_return_val_if_fail (stock_id != NULL, NULL);
625     
626   button = g_object_new (GTK_TYPE_TOOL_BUTTON,
627                          "stock_id", stock_id,
628                          NULL);
629
630   return GTK_TOOL_ITEM (button);
631 }
632
633 /**
634  * gtk_tool_button_new:
635  * @label: a string that will be used as label, or %NULL
636  * @icon_widget: a widget that will be used as icon widget, or %NULL
637  * 
638  * Creates a new %GtkToolButton using @icon_widget as icon and @label as
639  * label.
640  * 
641  * Return value: A new #GtkToolButton
642  * 
643  * Since: 2.4
644  **/
645 GtkToolItem *
646 gtk_tool_button_new (GtkWidget   *icon_widget,
647                      const gchar *label)
648 {
649   GtkToolButton *button;
650
651   button = g_object_new (GTK_TYPE_TOOL_BUTTON,
652                          NULL);
653   
654   if (label)
655     gtk_tool_button_set_label (button, label);
656
657   if (icon_widget)
658     gtk_tool_button_set_icon_widget (button, icon_widget);
659
660   return GTK_TOOL_ITEM (button);  
661 }
662
663 /**
664  * gtk_tool_button_set_label:
665  * @button: a #GtkToolButton
666  * @label: a string that will be used as label, or %NULL.
667  * 
668  * Sets @label as the label used for the tool button. The "label" property
669  * only has an effect if not overridden by a non-%NULL "label_widget" property.
670  * If both the "label_widget" and "label" properties are %NULL, the label
671  * is determined by the "stock_id" property. If the "stock_id" property is also
672  * %NULL, @button will not have a label.
673  * 
674  * Since: 2.4
675  **/
676 void
677 gtk_tool_button_set_label (GtkToolButton *button,
678                            const gchar   *label)
679 {
680   gchar *old_label;
681   
682   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
683
684   old_label = button->priv->label_text;
685
686   button->priv->label_text = g_strdup (label);
687   gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
688       
689   g_object_notify (G_OBJECT (button), "label");
690
691   if (old_label)
692     g_free (old_label);
693 }
694
695 /**
696  * gtk_tool_button_get_label:
697  * @button: a #GtkToolButton
698  * 
699  * Returns the label used by the tool button, or %NULL if the tool button
700  * doesn't have a label. or uses a the label from a stock item. The returned
701  * string is owned by GTK+, and must not be modified or freed.
702  * 
703  * Return value: The label, or %NULL
704  * 
705  * Since: 2.4
706  **/
707 G_CONST_RETURN gchar *
708 gtk_tool_button_get_label (GtkToolButton *button)
709 {
710   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
711
712   return button->priv->label_text;
713 }
714
715 /**
716  * gtk_tool_button_set_use_underline:
717  * @button: a #GtkToolButton
718  * @use_underline: whether the button label has the form "_Open"
719  *
720  * If set, an underline in the label property indicates that the next character
721  * should be used for the mnemonic accelerator key in the overflow menu. For
722  * example, if the label property is "_Open" and @use_underline is %TRUE,
723  * the label on the tool button will be "Open" and the item on the overflow
724  * menu will have an underlined 'O'.
725  * 
726  * Labels shown on tool buttons never have mnemonics on them; this property
727  * only affects the menu item on the overflow menu.
728  * 
729  * Since: 2.4
730  **/
731 void
732 gtk_tool_button_set_use_underline (GtkToolButton *button,
733                                    gboolean       use_underline)
734 {
735   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
736
737   use_underline = use_underline != FALSE;
738
739   if (use_underline != button->priv->use_underline)
740     {
741       button->priv->use_underline = use_underline;
742
743       gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
744
745       g_object_notify (G_OBJECT (button), "use_underline");
746     }
747 }
748
749 /**
750  * gtk_tool_button_get_use_underline:
751  * @button: a #GtkToolButton
752  * 
753  * Returns whether underscores in the label property are used as mnemonics
754  * on menu items on the overflow menu. See gtk_tool_button_set_use_underline().
755  * 
756  * Return value: %TRUE if underscores in the label property are used as
757  * mnemonics on menu items on the overflow menu.
758  * 
759  * Since: 2.4
760  **/
761 gboolean
762 gtk_tool_button_get_use_underline (GtkToolButton *button)
763 {
764   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), FALSE);
765
766   return button->priv->use_underline;
767 }
768
769 /**
770  * gtk_tool_button_set_stock_id:
771  * @button: a #GtkToolButton
772  * @stock_id: a name of a stock item, or %NULL
773  * 
774  * Sets the name of the stock item. See gtk_tool_button_new_from_stock().
775  * The stock_id property only has an effect if not
776  * overridden by non-%NULL "label" and "icon_widget" properties.
777  * 
778  * Since: 2.4
779  **/
780 void
781 gtk_tool_button_set_stock_id (GtkToolButton *button,
782                               const gchar   *stock_id)
783 {
784   gchar *old_stock_id;
785   
786   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
787
788   old_stock_id = button->priv->stock_id;
789
790   button->priv->stock_id = g_strdup (stock_id);
791   gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
792   
793   g_object_notify (G_OBJECT (button), "stock_id");
794
795   g_free (old_stock_id);
796 }
797
798 /**
799  * gtk_tool_button_get_stock_id:
800  * @button: a #GtkToolButton
801  * 
802  * Returns the name of the stock item. See gtk_tool_button_set_stock_id().
803  * The returned string is owned by GTK+ and must not be freed or modifed.
804  * 
805  * Return value: the name of the stock item for @button.
806  * 
807  * Since: 2.4
808  **/
809 G_CONST_RETURN gchar *
810 gtk_tool_button_get_stock_id (GtkToolButton *button)
811 {
812   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
813
814   return button->priv->stock_id;
815 }
816
817 /**
818  * gtk_tool_button_set_icon_widget:
819  * @button: a #GtkToolButton
820  * @icon_widget: the widget used as icon, or %NULL
821  * 
822  * Sets @icon as the widget used as icon on @button. If @icon_widget is
823  * %NULL the icon is determined by the "stock_id" property. If the
824  * "stock_id" property is also %NULL, @button will not have an icon.
825  * 
826  * Since: 2.4
827  **/
828 void
829 gtk_tool_button_set_icon_widget (GtkToolButton *button,
830                                  GtkWidget     *icon_widget)
831 {
832   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
833   g_return_if_fail (icon_widget == NULL || GTK_IS_WIDGET (icon_widget));
834
835   if (icon_widget != button->priv->icon_widget)
836     {
837       if (button->priv->icon_widget)
838         g_object_unref (G_OBJECT (button->priv->icon_widget));
839
840       if (icon_widget)
841         {
842           g_object_ref (icon_widget);
843           gtk_object_sink (GTK_OBJECT (icon_widget));
844         }
845
846       button->priv->icon_widget = icon_widget;
847
848       gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
849       
850       g_object_notify (G_OBJECT (button), "icon_widget");
851     }
852 }
853
854 /**
855  * gtk_tool_button_set_label_widget:
856  * @button: a #GtkToolButton
857  * @label_widget: the widget used as label, or %NULL
858  * 
859  * Sets @label_widget as the widget that will be used as the label
860  * for @button. If @label_widget is %NULL the "label" property is used
861  * as label. If "label" is also %NULL, the label in the stock item
862  * determined by the "stock_id" property is used as label. If
863  * "stock_id" is also %NULL, @button does not have a label.
864  * 
865  * Since: 2.4
866  **/
867 void
868 gtk_tool_button_set_label_widget (GtkToolButton *button,
869                                   GtkWidget     *label_widget)
870 {
871   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
872   g_return_if_fail (label_widget == NULL || GTK_IS_WIDGET (label_widget));
873
874   if (label_widget != button->priv->label_widget)
875     {
876       if (button->priv->label_widget)
877         g_object_unref (button->priv->label_widget);
878
879       if (label_widget)
880         {
881           g_object_ref (label_widget);
882           gtk_object_sink (GTK_OBJECT (label_widget));
883         }
884
885       button->priv->label_widget = label_widget;
886
887       gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
888       
889       g_object_notify (G_OBJECT (button), "label_widget");
890     }
891 }
892
893 /**
894  * gtk_tool_button_get_label_widget:
895  * @button: a #GtkToolButton
896  * 
897  * Returns the widget used as label on @button. See
898  * gtk_tool_button_set_label_widget().
899  * 
900  * Return value: The widget used as label on @button, or %NULL.
901  * 
902  * Since: 2.4
903  **/
904 GtkWidget *
905 gtk_tool_button_get_label_widget (GtkToolButton *button)
906 {
907   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
908
909   return button->priv->label_widget;
910 }
911
912 /**
913  * gtk_tool_button_get_icon_widget:
914  * @button: a #GtkToolButton
915  * 
916  * Return the widget used as icon widget on @button. See
917  * gtk_tool_button_set_icon_widget().
918  * 
919  * Return value: The widget used as icon on @button, or %NULL.
920  * 
921  * Since: 2.4
922  **/
923 GtkWidget *
924 gtk_tool_button_get_icon_widget (GtkToolButton *button)
925 {
926   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
927
928   return button->priv->icon_widget;
929 }
930
931 GtkWidget *
932 _gtk_tool_button_get_button (GtkToolButton *button)
933 {
934   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
935
936   return button->priv->button;
937 }
938