]> Pileus Git - ~andy/gtk/blob - gtk/gtktoolbutton.c
Fix some typos with inline property docs. (#347065, John Finlay)
[~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                gtk_icon_factory_lookup_default (button->priv->stock_id))
410         {
411           icon = gtk_image_new_from_stock (button->priv->stock_id, icon_size);
412           gtk_widget_show (icon);
413         }
414       else if (button->priv->icon_name)
415         {
416           icon = gtk_image_new_from_icon_name (button->priv->icon_name, icon_size);
417           gtk_widget_show (icon);
418         }
419     }
420
421   switch (style)
422     {
423     case GTK_TOOLBAR_ICONS:
424       if (icon)
425         gtk_container_add (GTK_CONTAINER (button->priv->button), icon);
426       break;
427
428     case GTK_TOOLBAR_BOTH:
429       box = gtk_vbox_new (FALSE, icon_spacing);
430       if (icon)
431         gtk_box_pack_start (GTK_BOX (box), icon, TRUE, TRUE, 0);
432       gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 0);
433       gtk_container_add (GTK_CONTAINER (button->priv->button), box);
434       break;
435
436     case GTK_TOOLBAR_BOTH_HORIZ:
437       box = gtk_hbox_new (FALSE, icon_spacing);
438       if (icon)
439         gtk_box_pack_start (GTK_BOX (box), icon, label? FALSE : TRUE, TRUE, 0);
440       if (label)
441         gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
442       gtk_container_add (GTK_CONTAINER (button->priv->button), box);
443       break;
444
445     case GTK_TOOLBAR_TEXT:
446       gtk_container_add (GTK_CONTAINER (button->priv->button), label);
447       break;
448     }
449
450   if (box)
451     gtk_widget_show (box);
452
453   gtk_button_set_relief (GTK_BUTTON (button->priv->button),
454                          gtk_tool_item_get_relief_style (GTK_TOOL_ITEM (button)));
455
456   gtk_tool_item_rebuild_menu (tool_item);
457   
458   gtk_widget_queue_resize (GTK_WIDGET (button));
459 }
460
461 static void
462 gtk_tool_button_set_property (GObject         *object,
463                               guint            prop_id,
464                               const GValue    *value,
465                               GParamSpec      *pspec)
466 {
467   GtkToolButton *button = GTK_TOOL_BUTTON (object);
468   
469   switch (prop_id)
470     {
471     case PROP_LABEL:
472       gtk_tool_button_set_label (button, g_value_get_string (value));
473       break;
474     case PROP_USE_UNDERLINE:
475       gtk_tool_button_set_use_underline (button, g_value_get_boolean (value));
476       break;
477     case PROP_LABEL_WIDGET:
478       gtk_tool_button_set_label_widget (button, g_value_get_object (value));
479       break;
480     case PROP_STOCK_ID:
481       gtk_tool_button_set_stock_id (button, g_value_get_string (value));
482       break;
483     case PROP_ICON_NAME:
484       gtk_tool_button_set_icon_name (button, g_value_get_string (value));
485       break;
486     case PROP_ICON_WIDGET:
487       gtk_tool_button_set_icon_widget (button, g_value_get_object (value));
488       break;
489     default:
490       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
491     }
492 }
493
494 static void
495 gtk_tool_button_property_notify (GObject          *object,
496                                  GParamSpec       *pspec)
497 {
498   if (strcmp (pspec->name, "is-important") == 0)
499     gtk_tool_button_construct_contents (GTK_TOOL_ITEM (object));
500
501   if (parent_class->notify)
502     parent_class->notify (object, pspec);
503 }
504
505 static void
506 gtk_tool_button_get_property (GObject         *object,
507                               guint            prop_id,
508                               GValue          *value,
509                               GParamSpec      *pspec)
510 {
511   GtkToolButton *button = GTK_TOOL_BUTTON (object);
512
513   switch (prop_id)
514     {
515     case PROP_LABEL:
516       g_value_set_string (value, gtk_tool_button_get_label (button));
517       break;
518     case PROP_LABEL_WIDGET:
519       g_value_set_object (value, gtk_tool_button_get_label_widget (button));
520       break;
521     case PROP_USE_UNDERLINE:
522       g_value_set_boolean (value, gtk_tool_button_get_use_underline (button));
523       break;
524     case PROP_STOCK_ID:
525       g_value_set_string (value, button->priv->stock_id);
526       break;
527     case PROP_ICON_NAME:
528       g_value_set_string (value, button->priv->icon_name);
529       break;
530     case PROP_ICON_WIDGET:
531       g_value_set_object (value, button->priv->icon_widget);
532       break;
533     default:
534       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
535     }
536 }
537
538 static void
539 gtk_tool_button_finalize (GObject *object)
540 {
541   GtkToolButton *button = GTK_TOOL_BUTTON (object);
542
543   g_free (button->priv->stock_id);
544   g_free (button->priv->icon_name);
545   g_free (button->priv->label_text);
546
547   if (button->priv->label_widget)
548     g_object_unref (button->priv->label_widget);
549
550   if (button->priv->icon_widget)
551     g_object_unref (button->priv->icon_widget);
552   
553   parent_class->finalize (object);
554 }
555
556 static GtkWidget *
557 clone_image_menu_size (GtkImage *image, GtkSettings *settings)
558 {
559   GtkImageType storage_type = gtk_image_get_storage_type (image);
560
561   if (storage_type == GTK_IMAGE_STOCK)
562     {
563       gchar *stock_id;
564       gtk_image_get_stock (image, &stock_id, NULL);
565       return gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU);
566     }
567   else if (storage_type == GTK_IMAGE_ICON_SET)
568     {
569       GtkIconSet *icon_set;
570       gtk_image_get_icon_set (image, &icon_set, NULL);
571       return gtk_image_new_from_icon_set (icon_set, GTK_ICON_SIZE_MENU);
572     }
573   else if (storage_type == GTK_IMAGE_PIXBUF)
574     {
575       gint width, height;
576       
577       if (settings &&
578           gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
579                                              &width, &height))
580         {
581           GdkPixbuf *src_pixbuf, *dest_pixbuf;
582           GtkWidget *cloned_image;
583
584           src_pixbuf = gtk_image_get_pixbuf (image);
585           dest_pixbuf = gdk_pixbuf_scale_simple (src_pixbuf, width, height,
586                                                  GDK_INTERP_BILINEAR);
587
588           cloned_image = gtk_image_new_from_pixbuf (dest_pixbuf);
589           g_object_unref (dest_pixbuf);
590
591           return cloned_image;
592         }
593     }
594
595   return NULL;
596 }
597       
598 static gboolean
599 gtk_tool_button_create_menu_proxy (GtkToolItem *item)
600 {
601   GtkToolButton *button = GTK_TOOL_BUTTON (item);
602   GtkWidget *menu_item;
603   GtkWidget *menu_image = NULL;
604   GtkStockItem stock_item;
605   gboolean use_mnemonic = TRUE;
606   const char *label;
607
608   if (button->priv->label_widget && GTK_IS_LABEL (button->priv->label_widget))
609     {
610       label = gtk_label_get_label (GTK_LABEL (button->priv->label_widget));
611       use_mnemonic = gtk_label_get_use_underline (GTK_LABEL (button->priv->label_widget));
612     }
613   else if (button->priv->label_text)
614     {
615       label = button->priv->label_text;
616       use_mnemonic = button->priv->use_underline;
617     }
618   else if (button->priv->stock_id && gtk_stock_lookup (button->priv->stock_id, &stock_item))
619     {
620       label = stock_item.label;
621     }
622   else
623     {
624       label = "";
625     }
626   
627   if (use_mnemonic)
628     menu_item = gtk_image_menu_item_new_with_mnemonic (label);
629   else
630     menu_item = gtk_image_menu_item_new_with_label (label);
631
632   if (button->priv->icon_widget && GTK_IS_IMAGE (button->priv->icon_widget))
633     {
634       menu_image = clone_image_menu_size (GTK_IMAGE (button->priv->icon_widget),
635                                           gtk_widget_get_settings (GTK_WIDGET (button)));
636     }
637   else if (button->priv->stock_id)
638     {
639       menu_image = gtk_image_new_from_stock (button->priv->stock_id, GTK_ICON_SIZE_MENU);
640     }
641
642   if (menu_image)
643     gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), menu_image);
644
645   g_signal_connect_closure_by_id (menu_item,
646                                   g_signal_lookup ("activate", G_OBJECT_TYPE (menu_item)), 0,
647                                   g_cclosure_new_object_swap (G_CALLBACK (gtk_button_clicked),
648                                                               G_OBJECT (GTK_TOOL_BUTTON (button)->priv->button)),
649                                   FALSE);
650
651   gtk_tool_item_set_proxy_menu_item (GTK_TOOL_ITEM (button), MENU_ID, menu_item);
652   
653   return TRUE;
654 }
655
656 static void
657 button_clicked (GtkWidget     *widget,
658                 GtkToolButton *button)
659 {
660   g_signal_emit_by_name (button, "clicked");
661 }
662
663 static void
664 gtk_tool_button_toolbar_reconfigured (GtkToolItem *tool_item)
665 {
666   gtk_tool_button_construct_contents (tool_item);
667 }
668
669 static void 
670 gtk_tool_button_update_icon_spacing (GtkToolButton *button)
671 {
672   GtkWidget *box;
673   guint spacing;
674
675   box = GTK_BIN (button->priv->button)->child;
676   if (GTK_IS_BOX (box))
677     {
678       gtk_widget_style_get (GTK_WIDGET (button), 
679                             "icon-spacing", &spacing,
680                             NULL);
681       gtk_box_set_spacing (GTK_BOX (box), spacing);      
682     }
683 }
684
685 static void
686 gtk_tool_button_style_set (GtkWidget *widget,
687                            GtkStyle  *prev_style)
688 {
689   gtk_tool_button_update_icon_spacing (GTK_TOOL_BUTTON (widget));
690 }
691
692 /**
693  * gtk_tool_button_new_from_stock:
694  * @stock_id: the name of the stock item 
695  *
696  * Creates a new #GtkToolButton containing the image and text from a
697  * stock item. Some stock ids have preprocessor macros like #GTK_STOCK_OK
698  * and #GTK_STOCK_APPLY.
699  *
700  * It is an error if @stock_id is not a name of a stock item.
701  * 
702  * Return value: A new #GtkToolButton
703  * 
704  * Since: 2.4
705  **/
706 GtkToolItem *
707 gtk_tool_button_new_from_stock (const gchar *stock_id)
708 {
709   GtkToolButton *button;
710
711   g_return_val_if_fail (stock_id != NULL, NULL);
712     
713   button = g_object_new (GTK_TYPE_TOOL_BUTTON,
714                          "stock-id", stock_id,
715                          NULL);
716
717   return GTK_TOOL_ITEM (button);
718 }
719
720 /**
721  * gtk_tool_button_new:
722  * @label: a string that will be used as label, or %NULL
723  * @icon_widget: a widget that will be used as icon widget, or %NULL
724  * 
725  * Creates a new %GtkToolButton using @icon_widget as icon and @label as
726  * label.
727  * 
728  * Return value: A new #GtkToolButton
729  * 
730  * Since: 2.4
731  **/
732 GtkToolItem *
733 gtk_tool_button_new (GtkWidget   *icon_widget,
734                      const gchar *label)
735 {
736   GtkToolButton *button;
737
738   button = g_object_new (GTK_TYPE_TOOL_BUTTON,
739                          NULL);
740   
741   if (label)
742     gtk_tool_button_set_label (button, label);
743
744   if (icon_widget)
745     gtk_tool_button_set_icon_widget (button, icon_widget);
746
747   return GTK_TOOL_ITEM (button);  
748 }
749
750 /**
751  * gtk_tool_button_set_label:
752  * @button: a #GtkToolButton
753  * @label: a string that will be used as label, or %NULL.
754  * 
755  * Sets @label as the label used for the tool button. The "label" property
756  * only has an effect if not overridden by a non-%NULL "label_widget" property.
757  * If both the "label_widget" and "label" properties are %NULL, the label
758  * is determined by the "stock_id" property. If the "stock_id" property is also
759  * %NULL, @button will not have a label.
760  * 
761  * Since: 2.4
762  **/
763 void
764 gtk_tool_button_set_label (GtkToolButton *button,
765                            const gchar   *label)
766 {
767   gchar *old_label;
768   
769   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
770
771   old_label = button->priv->label_text;
772
773   button->priv->label_text = g_strdup (label);
774   gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
775       
776   g_object_notify (G_OBJECT (button), "label");
777
778   if (old_label)
779     g_free (old_label);
780 }
781
782 /**
783  * gtk_tool_button_get_label:
784  * @button: a #GtkToolButton
785  * 
786  * Returns the label used by the tool button, or %NULL if the tool button
787  * doesn't have a label. or uses a the label from a stock item. The returned
788  * string is owned by GTK+, and must not be modified or freed.
789  * 
790  * Return value: The label, or %NULL
791  * 
792  * Since: 2.4
793  **/
794 G_CONST_RETURN gchar *
795 gtk_tool_button_get_label (GtkToolButton *button)
796 {
797   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
798
799   return button->priv->label_text;
800 }
801
802 /**
803  * gtk_tool_button_set_use_underline:
804  * @button: a #GtkToolButton
805  * @use_underline: whether the button label has the form "_Open"
806  *
807  * If set, an underline in the label property indicates that the next character
808  * should be used for the mnemonic accelerator key in the overflow menu. For
809  * example, if the label property is "_Open" and @use_underline is %TRUE,
810  * the label on the tool button will be "Open" and the item on the overflow
811  * menu will have an underlined 'O'.
812  * 
813  * Labels shown on tool buttons never have mnemonics on them; this property
814  * only affects the menu item on the overflow menu.
815  * 
816  * Since: 2.4
817  **/
818 void
819 gtk_tool_button_set_use_underline (GtkToolButton *button,
820                                    gboolean       use_underline)
821 {
822   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
823
824   use_underline = use_underline != FALSE;
825
826   if (use_underline != button->priv->use_underline)
827     {
828       button->priv->use_underline = use_underline;
829
830       gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
831
832       g_object_notify (G_OBJECT (button), "use-underline");
833     }
834 }
835
836 /**
837  * gtk_tool_button_get_use_underline:
838  * @button: a #GtkToolButton
839  * 
840  * Returns whether underscores in the label property are used as mnemonics
841  * on menu items on the overflow menu. See gtk_tool_button_set_use_underline().
842  * 
843  * Return value: %TRUE if underscores in the label property are used as
844  * mnemonics on menu items on the overflow menu.
845  * 
846  * Since: 2.4
847  **/
848 gboolean
849 gtk_tool_button_get_use_underline (GtkToolButton *button)
850 {
851   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), FALSE);
852
853   return button->priv->use_underline;
854 }
855
856 /**
857  * gtk_tool_button_set_stock_id:
858  * @button: a #GtkToolButton
859  * @stock_id: a name of a stock item, or %NULL
860  * 
861  * Sets the name of the stock item. See gtk_tool_button_new_from_stock().
862  * The stock_id property only has an effect if not
863  * overridden by non-%NULL "label" and "icon_widget" properties.
864  * 
865  * Since: 2.4
866  **/
867 void
868 gtk_tool_button_set_stock_id (GtkToolButton *button,
869                               const gchar   *stock_id)
870 {
871   gchar *old_stock_id;
872   
873   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
874
875   old_stock_id = button->priv->stock_id;
876
877   button->priv->stock_id = g_strdup (stock_id);
878   gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
879   
880   g_object_notify (G_OBJECT (button), "stock-id");
881
882   g_free (old_stock_id);
883 }
884
885 /**
886  * gtk_tool_button_get_stock_id:
887  * @button: a #GtkToolButton
888  * 
889  * Returns the name of the stock item. See gtk_tool_button_set_stock_id().
890  * The returned string is owned by GTK+ and must not be freed or modifed.
891  * 
892  * Return value: the name of the stock item for @button.
893  * 
894  * Since: 2.4
895  **/
896 G_CONST_RETURN gchar *
897 gtk_tool_button_get_stock_id (GtkToolButton *button)
898 {
899   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
900
901   return button->priv->stock_id;
902 }
903
904 /**
905  * gtk_tool_button_set_icon_name
906  * @button: a #GtkToolButton
907  * @icon_name: the name of the themed icon
908  * 
909  * Sets the icon for the tool button from a named themed icon.
910  * See the docs for #GtkIconTheme for more details.
911  * The "icon_name" property only has an effect if not
912  * overridden by non-%NULL "label", "icon_widget" and "stock_id"
913  * properties.
914  * 
915  * Since: 2.8
916  **/
917 void
918 gtk_tool_button_set_icon_name (GtkToolButton *button,
919                                const gchar   *icon_name)
920 {
921   gchar *old_icon_name;
922
923   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
924
925   old_icon_name = button->priv->icon_name;
926
927   button->priv->icon_name = g_strdup (icon_name);
928   gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
929
930   g_object_notify (G_OBJECT (button), "icon-name");
931
932   g_free (old_icon_name);
933 }
934
935 /**
936  * gtk_tool_button_get_icon_name
937  * @button: a #GtkToolButton
938  * 
939  * Returns the name of the themed icon for the tool button,
940  * see gtk_tool_button_set_icon_name().
941  *
942  * Returns: the icon name or %NULL if the tool button has
943  * no themed icon
944  * 
945  * Since: 2.8
946  **/
947 G_CONST_RETURN gchar*
948 gtk_tool_button_get_icon_name (GtkToolButton *button)
949 {
950   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
951
952   return button->priv->icon_name;
953 }
954
955 /**
956  * gtk_tool_button_set_icon_widget:
957  * @button: a #GtkToolButton
958  * @icon_widget: the widget used as icon, or %NULL
959  * 
960  * Sets @icon as the widget used as icon on @button. If @icon_widget is
961  * %NULL the icon is determined by the "stock_id" property. If the
962  * "stock_id" property is also %NULL, @button will not have an icon.
963  * 
964  * Since: 2.4
965  **/
966 void
967 gtk_tool_button_set_icon_widget (GtkToolButton *button,
968                                  GtkWidget     *icon_widget)
969 {
970   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
971   g_return_if_fail (icon_widget == NULL || GTK_IS_WIDGET (icon_widget));
972
973   if (icon_widget != button->priv->icon_widget)
974     {
975       if (button->priv->icon_widget)
976         {
977           if (button->priv->icon_widget->parent)
978             {
979               gtk_container_remove (GTK_CONTAINER (button->priv->icon_widget->parent),
980                                     button->priv->icon_widget);
981             }
982
983           g_object_unref (button->priv->icon_widget);
984         }
985       
986       if (icon_widget)
987         {
988           g_object_ref_sink (icon_widget);
989         }
990
991       button->priv->icon_widget = icon_widget;
992
993       gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
994       
995       g_object_notify (G_OBJECT (button), "icon-widget");
996     }
997 }
998
999 /**
1000  * gtk_tool_button_set_label_widget:
1001  * @button: a #GtkToolButton
1002  * @label_widget: the widget used as label, or %NULL
1003  * 
1004  * Sets @label_widget as the widget that will be used as the label
1005  * for @button. If @label_widget is %NULL the "label" property is used
1006  * as label. If "label" is also %NULL, the label in the stock item
1007  * determined by the "stock_id" property is used as label. If
1008  * "stock_id" is also %NULL, @button does not have a label.
1009  * 
1010  * Since: 2.4
1011  **/
1012 void
1013 gtk_tool_button_set_label_widget (GtkToolButton *button,
1014                                   GtkWidget     *label_widget)
1015 {
1016   g_return_if_fail (GTK_IS_TOOL_BUTTON (button));
1017   g_return_if_fail (label_widget == NULL || GTK_IS_WIDGET (label_widget));
1018
1019   if (label_widget != button->priv->label_widget)
1020     {
1021       if (button->priv->label_widget)
1022         {
1023           if (button->priv->label_widget->parent)
1024             {
1025               gtk_container_remove (GTK_CONTAINER (button->priv->label_widget->parent),
1026                                     button->priv->label_widget);
1027             }
1028           
1029           g_object_unref (button->priv->label_widget);
1030         }
1031       
1032       if (label_widget)
1033         {
1034           g_object_ref_sink (label_widget);
1035         }
1036
1037       button->priv->label_widget = label_widget;
1038
1039       gtk_tool_button_construct_contents (GTK_TOOL_ITEM (button));
1040       
1041       g_object_notify (G_OBJECT (button), "label-widget");
1042     }
1043 }
1044
1045 /**
1046  * gtk_tool_button_get_label_widget:
1047  * @button: a #GtkToolButton
1048  * 
1049  * Returns the widget used as label on @button. See
1050  * gtk_tool_button_set_label_widget().
1051  * 
1052  * Return value: The widget used as label on @button, or %NULL.
1053  * 
1054  * Since: 2.4
1055  **/
1056 GtkWidget *
1057 gtk_tool_button_get_label_widget (GtkToolButton *button)
1058 {
1059   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1060
1061   return button->priv->label_widget;
1062 }
1063
1064 /**
1065  * gtk_tool_button_get_icon_widget:
1066  * @button: a #GtkToolButton
1067  * 
1068  * Return the widget used as icon widget on @button. See
1069  * gtk_tool_button_set_icon_widget().
1070  * 
1071  * Return value: The widget used as icon on @button, or %NULL.
1072  * 
1073  * Since: 2.4
1074  **/
1075 GtkWidget *
1076 gtk_tool_button_get_icon_widget (GtkToolButton *button)
1077 {
1078   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1079
1080   return button->priv->icon_widget;
1081 }
1082
1083 GtkWidget *
1084 _gtk_tool_button_get_button (GtkToolButton *button)
1085 {
1086   g_return_val_if_fail (GTK_IS_TOOL_BUTTON (button), NULL);
1087
1088   return button->priv->button;
1089 }
1090
1091
1092 #define __GTK_TOOL_BUTTON_C__
1093 #include "gtkaliasdef.c"