]> Pileus Git - ~andy/gtk/blob - gtk/gtktoolbutton.c
Insert cast to fix warning. Assign something to old_value to quiet gcc
[~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_size_request  (GtkWidget          *widget,
58                                            GtkRequisition     *requisition);
59 static void gtk_tool_button_size_allocate (GtkWidget          *widget,
60                                            GtkAllocation      *allocation);
61 static void gtk_tool_button_set_property  (GObject            *object,
62                                            guint               prop_id,
63                                            const GValue       *value,
64                                            GParamSpec         *pspec);
65 static void gtk_tool_button_get_property  (GObject            *object,
66                                            guint               prop_id,
67                                            GValue             *value,
68                                            GParamSpec         *pspec);
69 static void gtk_tool_button_finalize      (GObject            *object);
70
71 static void gtk_tool_button_toolbar_reconfigured (GtkToolItem *tool_item);
72 static gboolean   gtk_tool_button_create_menu_proxy (GtkToolItem     *item);
73 static void       button_clicked                    (GtkWidget       *widget,
74                                                      GtkToolButton   *button);
75
76 static void gtk_tool_button_construct_contents (GtkToolItem *tool_item);
77       
78 static GObjectClass *parent_class = NULL;
79 static guint         toolbutton_signals[LAST_SIGNAL] = { 0 };
80
81 GType
82 gtk_tool_button_get_type (void)
83 {
84   static GtkType type = 0;
85
86   if (!type)
87     {
88       static const GTypeInfo type_info =
89         {
90           sizeof (GtkToolButtonClass),
91           (GBaseInitFunc) NULL,
92           (GBaseFinalizeFunc) NULL,
93           (GClassInitFunc) gtk_tool_button_class_init,
94           (GClassFinalizeFunc) NULL,
95           NULL,
96           sizeof (GtkToolButton),
97           0, /* n_preallocs */
98           (GInstanceInitFunc) gtk_tool_button_init,
99         };
100
101       type = g_type_register_static (GTK_TYPE_TOOL_ITEM,
102                                      "GtkToolButton",
103                                      &type_info, 0);
104     }
105   return type;
106 }
107
108 static void
109 gtk_tool_button_class_init (GtkToolButtonClass *klass)
110 {
111   GObjectClass *object_class;
112   GtkWidgetClass *widget_class;
113   GtkToolItemClass *tool_item_class;
114   
115   parent_class = g_type_class_peek_parent (klass);
116   
117   object_class = (GObjectClass *)klass;
118   widget_class = (GtkWidgetClass *)klass;
119   tool_item_class = (GtkToolItemClass *)klass;
120   
121   object_class->set_property = gtk_tool_button_set_property;
122   object_class->get_property = gtk_tool_button_get_property;
123   object_class->finalize = gtk_tool_button_finalize;
124
125   widget_class->size_request = gtk_tool_button_size_request;
126   widget_class->size_allocate = gtk_tool_button_size_allocate;
127
128   tool_item_class->create_menu_proxy = gtk_tool_button_create_menu_proxy;
129   tool_item_class->toolbar_reconfigured = gtk_tool_button_toolbar_reconfigured;
130   
131   klass->button_type = GTK_TYPE_BUTTON;
132
133   /* Properties are interpreted like this:
134    *
135    *          - if the tool button has an icon_widget, then that widget
136    *            will be used as the icon. Otherwise, if the tool button
137    *            has a stock id, the corresponding stock icon will be
138    *            used. Otherwise, the tool button will not have an icon.
139    *
140    *          - if the tool button has a label_widget then that widget
141    *            will be used as the label. Otherwise, if the tool button
142    *            has a label text, that text will be used as label. Otherwise,
143    *            if the toolbutton has a stock id, the corresponding text
144    *            will be used as label. Otherwise, the toolbutton will
145    *            have an empty label.
146    *
147    *          - The use_underline property only has an effect when the label
148    *            on the toolbutton comes from the label property (ie. not from
149    *            label_widget or from stock_id).
150    *
151    *            In that case, if use_underline is set,
152    *
153    *                    - underscores are removed from the label text before
154    *                      the label is shown on the toolbutton unless the
155    *                      underscore is followed by another underscore
156    *
157    *                    - an underscore indicates that the next character when
158    *                      used in the overflow menu should be used as a mnemonic.
159    *
160    *            In short: use_underline = TRUE means that the label text has
161    *            the form "_Open" and the toolbar should take appropriate action.
162    */
163
164   g_object_class_install_property (object_class,
165                                    PROP_LABEL,
166                                    g_param_spec_string ("label",
167                                                         _("Label"),
168                                                         _("Text to show in the item."),
169                                                         NULL,
170                                                         G_PARAM_READWRITE));
171   g_object_class_install_property (object_class,
172                                    PROP_USE_UNDERLINE,
173                                    g_param_spec_boolean ("use_underline",
174                                                          _("Use underline"),
175                                                          _("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"),
176                                                          FALSE,
177                                                          G_PARAM_READWRITE));
178   g_object_class_install_property (object_class,
179                                    PROP_LABEL_WIDGET,
180                                    g_param_spec_object ("label_widget",
181                                                         _("Label widget"),
182                                                         _("Widget to use as the item label"),
183                                                         GTK_TYPE_WIDGET,
184                                                         G_PARAM_READWRITE));
185   g_object_class_install_property (object_class,
186                                    PROP_STOCK_ID,
187                                    g_param_spec_string ("stock_id",
188                                                         _("Stock Id"),
189                                                         _("The stock icon displayed on the item"),
190                                                         NULL,
191                                                         G_PARAM_READWRITE));
192   g_object_class_install_property (object_class,
193                                    PROP_ICON_WIDGET,
194                                    g_param_spec_object ("icon_widget",
195                                                         _("Icon widget"),
196                                                         _("Icon widget to display in the item"),
197                                                         GTK_TYPE_WIDGET,
198                                                         G_PARAM_READWRITE));
199
200   toolbutton_signals[CLICKED] =
201     g_signal_new ("clicked",
202                   G_OBJECT_CLASS_TYPE (klass),
203                   G_SIGNAL_RUN_FIRST,
204                   G_STRUCT_OFFSET (GtkToolButtonClass, clicked),
205                   NULL, NULL,
206                   g_cclosure_marshal_VOID__VOID,
207                   G_TYPE_NONE, 0);
208 }
209
210 static void
211 gtk_tool_button_init (GtkToolButton      *button,
212                       GtkToolButtonClass *klass)
213 {
214   GtkToolItem *toolitem = GTK_TOOL_ITEM (button);
215   
216   toolitem->homogeneous = TRUE;
217
218   /* create button */
219   button->button = g_object_new (klass->button_type, NULL);
220   gtk_button_set_focus_on_click (GTK_BUTTON (button->button), FALSE);
221   g_signal_connect_object (button->button, "clicked",
222                            G_CALLBACK (button_clicked), button, 0);
223
224   gtk_container_add (GTK_CONTAINER (button), button->button);
225   gtk_widget_show (button->button);
226 }
227
228 static void
229 gtk_tool_button_size_request (GtkWidget      *widget,
230                               GtkRequisition *requisition)
231 {
232   GtkWidget *child = GTK_BIN (widget)->child;
233
234   if (child && GTK_WIDGET_VISIBLE (child))
235     {
236       gtk_widget_size_request (child, requisition);
237     }
238   else
239     {
240       requisition->width = 0;
241       requisition->height = 0;
242     }
243   
244   requisition->width += GTK_CONTAINER (widget)->border_width * 2;
245   requisition->height += GTK_CONTAINER (widget)->border_width * 2;  
246 }
247
248 static void
249 gtk_tool_button_size_allocate (GtkWidget     *widget,
250                                GtkAllocation *allocation)
251 {
252   GtkToolItem *toolitem = GTK_TOOL_ITEM (widget);
253   GtkAllocation child_allocation;
254   gint border_width;
255   GtkWidget *child = GTK_BIN (widget)->child;
256
257   widget->allocation = *allocation;
258   border_width = GTK_CONTAINER (widget)->border_width;
259
260   if (toolitem->drag_window && GTK_WIDGET_REALIZED (widget))
261     gdk_window_move_resize (toolitem->drag_window,
262                             widget->allocation.x + border_width,
263                             widget->allocation.y + border_width,
264                             widget->allocation.width - border_width * 2,
265                             widget->allocation.height - border_width * 2);
266   
267   if (child && GTK_WIDGET_VISIBLE (child))
268     {
269       child_allocation.x = allocation->x + border_width;
270       child_allocation.y = allocation->y + border_width;
271       child_allocation.width = allocation->width - 2 * border_width;
272       child_allocation.height = allocation->height - 2 * border_width;
273       
274       gtk_widget_size_allocate (child, &child_allocation);
275     }
276 }
277
278 static void
279 gtk_tool_button_construct_contents (GtkToolItem *tool_item)
280 {
281   GtkToolButton *button = GTK_TOOL_BUTTON (tool_item);
282   GtkWidget *label = NULL;
283   GtkWidget *icon = NULL;
284   GtkToolbarStyle style;
285   gboolean need_label = FALSE;
286   gboolean need_icon = FALSE;
287   GtkIconSize icon_size;
288   GtkWidget *box = NULL;
289
290   if (gtk_tool_item_get_proxy_menu_item (tool_item, MENU_ID))
291     {
292       /* Remove item, so it will be recreated on the next
293        * create_proxy_menu_item()
294        */
295       gtk_tool_item_set_proxy_menu_item (tool_item, MENU_ID, NULL);
296     }
297   
298   if (button->icon_widget && button->icon_widget->parent)
299     {
300       gtk_container_remove (GTK_CONTAINER (button->icon_widget->parent),
301                             button->icon_widget);
302     }
303
304   if (button->label_widget && button->label_widget->parent)
305     {
306       gtk_container_remove (GTK_CONTAINER (button->label_widget->parent),
307                             button->label_widget);
308     }
309
310   if (GTK_BIN (button->button)->child)
311     {
312       /* Note: we are not destroying the label_widget or icon_widget
313        * here because they were removed from their containers above
314        */
315       gtk_widget_destroy (GTK_BIN (button->button)->child);
316     }
317
318   style = gtk_tool_item_get_toolbar_style (GTK_TOOL_ITEM (button));
319   
320   if (style != GTK_TOOLBAR_TEXT)
321     need_icon = TRUE;
322
323   if (style != GTK_TOOLBAR_ICONS)
324     need_label = TRUE;
325
326   if (need_label)
327     {
328       if (button->label_widget)
329         {
330           label = button->label_widget;
331         }
332       else
333         {
334           GtkStockItem stock_item;
335           gboolean elide;
336           gchar *label_text;
337
338           if (button->label_text)
339             {
340               label_text = button->label_text;
341               elide = button->use_underline;
342             }
343           else if (button->stock_id && gtk_stock_lookup (button->stock_id, &stock_item))
344             {
345               label_text = stock_item.label;
346               elide = TRUE;
347             }
348           else
349             {
350               label_text = "";
351               elide = FALSE;
352             }
353
354           if (elide)
355             label_text = _gtk_toolbar_elide_underscores (label_text);
356           else
357             label_text = g_strdup (label_text);
358
359           label = gtk_label_new (label_text);
360
361           g_free (label_text);
362           
363           gtk_widget_show (label);
364         }
365     }
366
367   icon_size = gtk_tool_item_get_icon_size (GTK_TOOL_ITEM (button));
368   if (need_icon)
369     {
370       if (button->icon_widget)
371         {
372           icon = button->icon_widget;
373           
374           if (GTK_IS_IMAGE (icon))
375             {
376               g_object_set (G_OBJECT (button->icon_widget),
377                             "icon-size", icon_size,
378                             NULL);
379             }
380         }
381       else if (button->stock_id)
382         {
383           icon = gtk_image_new_from_stock (button->stock_id, icon_size);
384           gtk_widget_show (icon);
385         }
386     }
387
388   switch (style)
389     {
390     case GTK_TOOLBAR_ICONS:
391       if (icon)
392         gtk_container_add (GTK_CONTAINER (button->button), icon);
393       break;
394
395     case GTK_TOOLBAR_BOTH:
396       box = gtk_vbox_new (FALSE, 0);
397       gtk_box_pack_start (GTK_BOX (box), icon, TRUE, TRUE, 0);
398       gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 0);
399       gtk_container_add (GTK_CONTAINER (button->button), box);
400       break;
401
402     case GTK_TOOLBAR_BOTH_HORIZ:
403       box = gtk_hbox_new (FALSE, 0);
404       gtk_box_pack_start (GTK_BOX (box), icon, FALSE, TRUE, 0);
405       gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
406       gtk_container_add (GTK_CONTAINER (button->button), box);
407       break;
408
409     case GTK_TOOLBAR_TEXT:
410       gtk_container_add (GTK_CONTAINER (button->button), label);
411       break;
412     }
413
414   if (box)
415     gtk_widget_show (box);
416
417   gtk_button_set_relief (GTK_BUTTON (button->button),
418                          gtk_tool_item_get_relief_style (GTK_TOOL_ITEM (button)));
419
420   gtk_widget_queue_resize (GTK_WIDGET (button));
421 }
422
423 static void
424 gtk_tool_button_set_property (GObject         *object,
425                               guint            prop_id,
426                               const GValue    *value,
427                               GParamSpec      *pspec)
428 {
429   GtkToolButton *button = GTK_TOOL_BUTTON (object);
430   
431   switch (prop_id)
432     {
433     case PROP_LABEL:
434       gtk_tool_button_set_label (button, g_value_get_string (value));
435       break;
436     case PROP_USE_UNDERLINE:
437       gtk_tool_button_set_use_underline (button, g_value_get_boolean (value));
438       break;
439     case PROP_LABEL_WIDGET:
440       gtk_tool_button_set_label_widget (button, g_value_get_object (value));
441       break;
442     case PROP_STOCK_ID:
443       gtk_tool_button_set_stock_id (button, g_value_get_string (value));
444       break;
445     case PROP_ICON_WIDGET:
446       gtk_tool_button_set_icon_widget (button, g_value_get_object (value));
447       break;
448     default:
449       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
450     }
451 }
452
453 static void
454 gtk_tool_button_get_property (GObject         *object,
455                               guint            prop_id,
456                               GValue          *value,
457                               GParamSpec      *pspec)
458 {
459   GtkToolButton *button = GTK_TOOL_BUTTON (object);
460
461   switch (prop_id)
462     {
463     case PROP_LABEL:
464       g_value_set_string (value, gtk_tool_button_get_label (button));
465       break;
466     case PROP_LABEL_WIDGET:
467       g_value_set_object (value, gtk_tool_button_get_label_widget (button));
468       break;
469     case PROP_USE_UNDERLINE:
470       g_value_set_boolean (value, gtk_tool_button_get_use_underline (button));
471       break;
472     case PROP_STOCK_ID:
473       g_value_set_string (value, button->stock_id);
474       break;
475     case PROP_ICON_WIDGET:
476       g_value_set_object (value, button->icon_widget);
477       break;
478     default:
479       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
480     }
481 }
482
483 static void
484 gtk_tool_button_finalize (GObject *object)
485 {
486   GtkToolButton *button = GTK_TOOL_BUTTON (object);
487
488   g_free (button->stock_id);
489   button->stock_id = NULL;
490
491   parent_class->finalize (object);
492 }
493
494 static GtkWidget *
495 clone_image_menu_size (GtkImage *image, GtkSettings *settings)
496 {
497   GtkImageType storage_type = gtk_image_get_storage_type (image);
498
499   if (storage_type == GTK_IMAGE_STOCK)
500     {
501       gchar *stock_id;
502       gtk_image_get_stock (image, &stock_id, NULL);
503       return gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU);
504     }
505   else if (storage_type == GTK_IMAGE_ICON_SET)
506     {
507       GtkIconSet *icon_set;
508       gtk_image_get_icon_set (image, &icon_set, NULL);
509       return gtk_image_new_from_icon_set (icon_set, GTK_ICON_SIZE_MENU);
510     }
511   else if (storage_type == GTK_IMAGE_PIXBUF)
512     {
513       gint width, height;
514       
515       if (settings &&
516           gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
517                                              &width, &height))
518         {
519           GdkPixbuf *src_pixbuf, *dest_pixbuf;
520
521           src_pixbuf = gtk_image_get_pixbuf (image);
522           dest_pixbuf = gdk_pixbuf_scale_simple (src_pixbuf, width, height,
523                                                  GDK_INTERP_BILINEAR);
524
525           return gtk_image_new_from_pixbuf (dest_pixbuf);
526         }
527     }
528
529   return NULL;
530 }
531       
532 static gboolean
533 gtk_tool_button_create_menu_proxy (GtkToolItem *item)
534 {
535   GtkToolButton *button = GTK_TOOL_BUTTON (item);
536   GtkWidget *menu_item;
537   GtkWidget *menu_image = NULL;
538   GtkStockItem stock_item;
539   gboolean use_mnemonic = TRUE;
540   const char *label;
541
542   if (button->label_widget && GTK_IS_LABEL (button->label_widget))
543     {
544       label = gtk_label_get_label (GTK_LABEL (button->label_widget));
545       use_mnemonic = gtk_label_get_use_underline (GTK_LABEL (button->label_widget));
546     }
547   else if (button->label_text)
548     {
549       label = button->label_text;
550       use_mnemonic = button->use_underline;
551     }
552   else if (button->stock_id && gtk_stock_lookup (button->stock_id, &stock_item))
553     {
554       label = stock_item.label;
555       use_mnemonic = FALSE;
556     }
557   else
558     {
559       label = "";
560       use_mnemonic = FALSE;
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->icon_widget && GTK_IS_IMAGE (button->icon_widget))
569     {
570       menu_image = clone_image_menu_size (GTK_IMAGE (button->icon_widget),
571                                           gtk_widget_get_settings (GTK_WIDGET (button)));
572     }
573   else if (button->stock_id)
574     {
575       menu_image = gtk_image_new_from_stock (button->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)->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 GtkToolItem *
606 gtk_tool_button_new_from_stock (const gchar *stock_id)
607 {
608   GtkToolButton *button;
609
610   g_return_val_if_fail (stock_id != NULL, NULL);
611     
612   button = g_object_new (GTK_TYPE_TOOL_BUTTON,
613                          "stock_id", stock_id,
614                          NULL);
615
616   return GTK_TOOL_ITEM (button);
617 }
618
619 GtkToolItem *
620 gtk_tool_button_new (const gchar *label,
621                      GtkWidget   *icon_widget)
622 {
623   GtkToolButton *button;
624
625   button = g_object_new (GTK_TYPE_TOOL_BUTTON,
626                          NULL);
627   
628   if (label)
629     gtk_tool_button_set_label (button, label);
630
631   if (icon_widget)
632     gtk_tool_button_set_icon_widget (button, icon_widget);
633
634   return GTK_TOOL_ITEM (button);  
635 }
636
637 void
638 gtk_tool_button_set_label (GtkToolButton *button,
639                            const gchar   *label)
640 {
641   gchar *old_label;
642   
643   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
644
645   old_label = button->label_text;
646
647   button->label_text = g_strdup (label);
648   gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
649       
650   g_object_notify (G_OBJECT (button), "label");
651
652   if (old_label)
653     g_free (old_label);
654 }
655
656 G_CONST_RETURN gchar *
657 gtk_tool_button_get_label (GtkToolButton *button)
658 {
659   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
660
661   return button->label_text;
662 }
663
664 void
665 gtk_tool_button_set_use_underline (GtkToolButton *button,
666                                    gboolean       use_underline)
667 {
668   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
669
670   use_underline = use_underline != FALSE;
671
672   if (use_underline != button->use_underline)
673     {
674       button->use_underline = use_underline;
675
676       gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
677
678       g_object_notify (G_OBJECT (button), "use_underline");
679     }
680 }
681
682 gboolean
683 gtk_tool_button_get_use_underline (GtkToolButton *button)
684 {
685   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), FALSE);
686
687   return button->use_underline;
688 }
689
690 void
691 gtk_tool_button_set_stock_id (GtkToolButton *button,
692                               const gchar   *stock_id)
693 {
694   gchar *old_stock_id;
695   
696   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
697
698   old_stock_id = button->stock_id;
699
700   button->stock_id = g_strdup (stock_id);
701   gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
702   
703   g_object_notify (G_OBJECT (button), "stock_id");
704
705   g_free (old_stock_id);
706 }
707
708 G_CONST_RETURN gchar *
709 gtk_tool_button_get_stock_id (GtkToolButton *button)
710 {
711   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
712
713   return button->stock_id;
714 }
715
716 void
717 gtk_tool_button_set_icon_widget (GtkToolButton *button,
718                                  GtkWidget     *icon)
719 {
720   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
721   g_return_if_fail (icon == NULL || GTK_IS_WIDGET (icon));
722
723   if (icon != button->icon_widget)
724     {
725       if (button->icon_widget)
726         g_object_unref (G_OBJECT (button->icon_widget));
727
728       if (icon)
729         {
730           g_object_ref (icon);
731           gtk_object_sink (GTK_OBJECT (icon));
732         }
733
734       button->icon_widget = icon;
735
736       gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
737       
738       g_object_notify (G_OBJECT (button), "icon_widget");
739     }
740 }
741
742 void
743 gtk_tool_button_set_label_widget (GtkToolButton *button,
744                                   GtkWidget     *label_widget)
745 {
746   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
747   g_return_if_fail (label_widget == NULL || GTK_IS_WIDGET (label_widget));
748
749   if (label_widget != button->label_widget)
750     {
751       if (button->label_widget)
752         g_object_unref (button->label_widget);
753
754       if (label_widget)
755         {
756           g_object_ref (label_widget);
757           gtk_object_sink (GTK_OBJECT (label_widget));
758         }
759
760       button->label_widget = label_widget;
761
762       gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
763       
764       g_object_notify (G_OBJECT (button), "label_widget");
765     }
766 }
767
768 GtkWidget *
769 gtk_tool_button_get_label_widget (GtkToolButton *button)
770 {
771   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
772
773   return button->label_widget;
774 }
775
776 GtkWidget *
777 gtk_tool_button_get_icon_widget (GtkToolButton *button)
778 {
779   g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
780
781   return button->icon_widget;
782 }