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