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