]> Pileus Git - ~andy/gtk/blob - gtk/gtktoolbar.c
e58cefd17ea163462ff813352d5702407fd5934d
[~andy/gtk] / gtk / gtktoolbar.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  * GtkToolbar copyright (C) Federico Mena
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include "gtkbutton.h"
29 #include "gtktogglebutton.h"
30 #include "gtkradiobutton.h"
31 #include "gtklabel.h"
32 #include "gtkvbox.h"
33 #include "gtkhbox.h"
34 #include "gtktoolbar.h"
35 #include "gtkstock.h"
36 #include "gtkiconfactory.h"
37 #include "gtkimage.h"
38 #include "gtksettings.h"
39 #include "gtkintl.h"
40 #include "gtkmarshalers.h"
41
42
43 #define DEFAULT_IPADDING 0
44 #define DEFAULT_SPACE_SIZE  5
45 #define DEFAULT_SPACE_STYLE GTK_TOOLBAR_SPACE_LINE
46
47 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_LARGE_TOOLBAR
48 #define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_BOTH
49
50 #define SPACE_LINE_DIVISION 10
51 #define SPACE_LINE_START    3
52 #define SPACE_LINE_END      7
53
54 enum {
55   PROP_0,
56   PROP_ORIENTATION,
57   PROP_TOOLBAR_STYLE
58 };
59
60 enum {
61   ORIENTATION_CHANGED,
62   STYLE_CHANGED,
63   LAST_SIGNAL
64 };
65
66 typedef struct _GtkToolbarChildSpace GtkToolbarChildSpace;
67 struct _GtkToolbarChildSpace
68 {
69   GtkToolbarChild child;
70
71   gint alloc_x, alloc_y;
72 };
73
74 static void gtk_toolbar_class_init               (GtkToolbarClass *class);
75 static void gtk_toolbar_init                     (GtkToolbar      *toolbar);
76 static void gtk_toolbar_set_property             (GObject         *object,
77                                                   guint            prop_id,
78                                                   const GValue    *value,
79                                                   GParamSpec      *pspec);
80 static void gtk_toolbar_get_property             (GObject         *object,
81                                                   guint            prop_id,
82                                                   GValue          *value,
83                                                   GParamSpec      *pspec);
84 static void gtk_toolbar_destroy                  (GtkObject       *object);
85 static gint gtk_toolbar_expose                   (GtkWidget       *widget,
86                                                   GdkEventExpose  *event);
87 static void gtk_toolbar_size_request             (GtkWidget       *widget,
88                                                   GtkRequisition  *requisition);
89 static void gtk_toolbar_size_allocate            (GtkWidget       *widget,
90                                                   GtkAllocation   *allocation);
91 static void gtk_toolbar_style_set                (GtkWidget       *widget,
92                                                   GtkStyle        *prev_style);
93 static gboolean gtk_toolbar_focus                (GtkWidget       *widget,
94                                                   GtkDirectionType dir);
95 static void gtk_toolbar_hierarchy_changed        (GtkWidget       *widget,
96                                                   GtkWidget       *previous_toplevel);
97 static void gtk_toolbar_show_all                 (GtkWidget       *widget);
98 static void gtk_toolbar_add                      (GtkContainer    *container,
99                                                   GtkWidget       *widget);
100 static void gtk_toolbar_remove                   (GtkContainer    *container,
101                                                   GtkWidget       *widget);
102 static void gtk_toolbar_forall                   (GtkContainer    *container,
103                                                   gboolean         include_internals,
104                                                   GtkCallback      callback,
105                                                   gpointer         callback_data);
106
107 static void gtk_real_toolbar_orientation_changed (GtkToolbar      *toolbar,
108                                                   GtkOrientation   orientation);
109 static void gtk_real_toolbar_style_changed       (GtkToolbar      *toolbar,
110                                                   GtkToolbarStyle  style);
111
112 static GtkWidget * gtk_toolbar_internal_insert_element (GtkToolbar          *toolbar,
113                                                         GtkToolbarChildType  type,
114                                                         GtkWidget           *widget,
115                                                         const char          *text,
116                                                         const char          *tooltip_text,
117                                                         const char          *tooltip_private_text,
118                                                         GtkWidget           *icon,
119                                                         GtkSignalFunc        callback,
120                                                         gpointer             user_data,
121                                                         gint                 position,
122                                                         gboolean             has_mnemonic);
123
124 static GtkWidget * gtk_toolbar_internal_insert_item (GtkToolbar    *toolbar,
125                                                      const char    *text,
126                                                      const char    *tooltip_text,
127                                                      const char    *tooltip_private_text,
128                                                      GtkWidget     *icon,
129                                                      GtkSignalFunc  callback,
130                                                      gpointer       user_data,
131                                                      gint           position,
132                                                      gboolean       has_mnemonic);
133
134 static void        gtk_toolbar_update_button_relief (GtkToolbar *toolbar);
135
136 static GtkReliefStyle       get_button_relief (GtkToolbar *toolbar);
137 static gint                 get_space_size    (GtkToolbar *toolbar);
138 static GtkToolbarSpaceStyle get_space_style   (GtkToolbar *toolbar);
139
140
141 static GtkContainerClass *parent_class;
142
143 static guint toolbar_signals[LAST_SIGNAL] = { 0 };
144
145
146 GType
147 gtk_toolbar_get_type (void)
148 {
149   static GType toolbar_type = 0;
150
151   if (!toolbar_type)
152     {
153       static const GTypeInfo toolbar_info =
154       {
155         sizeof (GtkToolbarClass),
156         NULL,           /* base_init */
157         NULL,           /* base_finalize */
158         (GClassInitFunc) gtk_toolbar_class_init,
159         NULL,           /* class_finalize */
160         NULL,           /* class_data */
161         sizeof (GtkToolbar),
162         0,              /* n_preallocs */
163         (GInstanceInitFunc) gtk_toolbar_init,
164       };
165
166       toolbar_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkToolbar",
167                                              &toolbar_info, 0);
168     }
169
170   return toolbar_type;
171 }
172
173 static void
174 gtk_toolbar_class_init (GtkToolbarClass *class)
175 {
176   GObjectClass   *gobject_class;
177   GtkObjectClass *object_class;
178   GtkWidgetClass *widget_class;
179   GtkContainerClass *container_class;
180
181   gobject_class = G_OBJECT_CLASS (class);
182   object_class = (GtkObjectClass *) class;
183   widget_class = (GtkWidgetClass *) class;
184   container_class = (GtkContainerClass *) class;
185
186   parent_class = g_type_class_peek_parent (class);
187
188   object_class->destroy = gtk_toolbar_destroy;
189   gobject_class->set_property = gtk_toolbar_set_property;
190   gobject_class->get_property = gtk_toolbar_get_property;
191
192   widget_class->expose_event = gtk_toolbar_expose;
193   widget_class->size_request = gtk_toolbar_size_request;
194   widget_class->size_allocate = gtk_toolbar_size_allocate;
195   widget_class->style_set = gtk_toolbar_style_set;
196   widget_class->show_all = gtk_toolbar_show_all;
197   widget_class->focus = gtk_toolbar_focus;
198   widget_class->hierarchy_changed = gtk_toolbar_hierarchy_changed;
199   
200   container_class->add = gtk_toolbar_add;
201   container_class->remove = gtk_toolbar_remove;
202   container_class->forall = gtk_toolbar_forall;
203   
204   class->orientation_changed = gtk_real_toolbar_orientation_changed;
205   class->style_changed = gtk_real_toolbar_style_changed;
206
207   toolbar_signals[ORIENTATION_CHANGED] =
208     g_signal_new ("orientation_changed",
209                   G_OBJECT_CLASS_TYPE (gobject_class),
210                   G_SIGNAL_RUN_FIRST,
211                   G_STRUCT_OFFSET (GtkToolbarClass, orientation_changed),
212                   NULL, NULL,
213                   _gtk_marshal_VOID__ENUM,
214                   G_TYPE_NONE, 1,
215                   GTK_TYPE_ORIENTATION);
216   toolbar_signals[STYLE_CHANGED] =
217     g_signal_new ("style_changed",
218                   G_OBJECT_CLASS_TYPE (gobject_class),
219                   G_SIGNAL_RUN_FIRST,
220                   G_STRUCT_OFFSET (GtkToolbarClass, style_changed),
221                   NULL, NULL,
222                   _gtk_marshal_VOID__ENUM,
223                   G_TYPE_NONE, 1,
224                   GTK_TYPE_TOOLBAR_STYLE);
225   
226   g_object_class_install_property (gobject_class,
227                                    PROP_ORIENTATION,
228                                    g_param_spec_enum ("orientation",
229                                                       _("Orientation"),
230                                                       _("The orientation of the toolbar"),
231                                                       GTK_TYPE_ORIENTATION,
232                                                       GTK_ORIENTATION_HORIZONTAL,
233                                                       G_PARAM_READWRITE));
234  
235    g_object_class_install_property (gobject_class,
236                                     PROP_TOOLBAR_STYLE,
237                                     g_param_spec_enum ("toolbar_style",
238                                                       _("Toolbar Style"),
239                                                       _("How to draw the toolbar"),
240                                                       GTK_TYPE_TOOLBAR_STYLE,
241                                                       GTK_TOOLBAR_ICONS,
242                                                       G_PARAM_READWRITE));
243
244
245   gtk_widget_class_install_style_property (widget_class,
246                                            g_param_spec_int ("space_size",
247                                                              _("Spacer size"),
248                                                              _("Size of spacers"),
249                                                              0,
250                                                              G_MAXINT,
251                                                              DEFAULT_SPACE_SIZE,
252                                                              G_PARAM_READABLE));
253
254   gtk_widget_class_install_style_property (widget_class,
255                                            g_param_spec_int ("internal_padding",
256                                                              _("Internal padding"),
257                                                              _("Amount of border space between the toolbar shadow and the buttons"),
258                                                              0,
259                                                              G_MAXINT,
260                                                              DEFAULT_IPADDING,
261                                                              G_PARAM_READABLE));
262   
263   gtk_widget_class_install_style_property (widget_class,
264                                            g_param_spec_enum ("space_style",
265                                                              _("Space style"),
266                                                              _("Whether spacers are vertical lines or just blank"),
267                                                               GTK_TYPE_TOOLBAR_SPACE_STYLE,
268                                                               DEFAULT_SPACE_STYLE,
269                                                               
270                                                               G_PARAM_READABLE));
271
272   gtk_widget_class_install_style_property (widget_class,
273                                            g_param_spec_enum ("button_relief",
274                                                              _("Button relief"),
275                                                              _("Type of bevel around toolbar buttons"),
276                                                               GTK_TYPE_RELIEF_STYLE,
277                                                               GTK_RELIEF_NONE,
278                                                               G_PARAM_READABLE));
279
280   gtk_widget_class_install_style_property (widget_class,
281                                            g_param_spec_enum ("shadow_type",
282                                                               _("Shadow type"),
283                                                               _("Style of bevel around the toolbar"),
284                                                               GTK_TYPE_SHADOW_TYPE,
285                                                               GTK_SHADOW_OUT,
286                                                               G_PARAM_READABLE));
287
288   gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-style",
289                                                     _("Toolbar style"),
290                                                     _("Whether default toolbars have text only, text and icons, icons only, etc."),
291                                                     GTK_TYPE_TOOLBAR_STYLE,
292                                                     DEFAULT_TOOLBAR_STYLE,
293                                                     G_PARAM_READWRITE));
294
295   gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-icon-size",
296                                                     _("Toolbar icon size"),
297                                                     _("Size of icons in default toolbars"),
298                                                     GTK_TYPE_ICON_SIZE,
299                                                     DEFAULT_ICON_SIZE,
300                                                     G_PARAM_READWRITE));  
301 }
302
303 static void
304 style_change_notify (GtkToolbar *toolbar)
305 {
306   if (!toolbar->style_set)
307     {
308       /* pretend it was set, then unset, thus reverting to new default */
309       toolbar->style_set = TRUE; 
310       gtk_toolbar_unset_style (toolbar);
311     }
312 }
313
314 static void
315 icon_size_change_notify (GtkToolbar *toolbar)
316 {
317   if (!toolbar->icon_size_set)
318     {
319       /* pretend it was set, then unset, thus reverting to new default */
320       toolbar->icon_size_set = TRUE; 
321       gtk_toolbar_unset_icon_size (toolbar);
322     }
323 }
324
325 static GtkSettings *
326 toolbar_get_settings (GtkToolbar *toolbar)
327 {
328   return g_object_get_data (G_OBJECT (toolbar), "gtk-toolbar-settings");
329 }
330
331 static void
332 toolbar_screen_changed (GtkToolbar *toolbar)
333 {
334   GtkSettings *old_settings = toolbar_get_settings (toolbar);
335   GtkSettings *settings;
336
337   if (gtk_widget_has_screen (GTK_WIDGET (toolbar)))
338     settings = gtk_widget_get_settings (GTK_WIDGET (toolbar));
339   else
340     settings = NULL;
341
342   if (settings == old_settings)
343     return;
344
345   if (old_settings)
346     {
347       g_signal_handler_disconnect (old_settings, toolbar->style_set_connection);
348       g_signal_handler_disconnect (old_settings, toolbar->icon_size_connection);
349
350       g_object_unref (old_settings);
351     }
352   
353   if (settings)
354     {
355       toolbar->style_set_connection =
356         g_signal_connect_swapped (settings,
357                                   "notify::gtk-toolbar-style",
358                                   G_CALLBACK (style_change_notify),
359                                   toolbar);
360       
361       toolbar->icon_size_connection =
362         g_signal_connect_swapped (settings,
363                                   "notify::gtk-toolbar-icon-size",
364                                    G_CALLBACK (icon_size_change_notify),
365                                    toolbar);
366
367
368       g_object_ref (settings);
369       g_object_set_data (G_OBJECT (toolbar), "gtk-toolbar-settings", settings);
370     }
371   else
372     g_object_set_data (G_OBJECT (toolbar), "gtk-toolbar-settings", NULL);
373
374   style_change_notify (toolbar);
375   icon_size_change_notify (toolbar);
376 }
377
378 static void
379 gtk_toolbar_hierarchy_changed (GtkWidget *widget,
380                                GtkWidget *previous_toplevel)
381 {
382   GtkWidget *toplevel;
383   
384   if (previous_toplevel)
385     g_signal_handlers_disconnect_by_func (previous_toplevel,
386                                           toolbar_screen_changed,
387                                           widget);
388
389   toplevel = gtk_widget_get_toplevel (widget);
390   if (GTK_WIDGET_TOPLEVEL (toplevel))
391     g_signal_connect_swapped (toplevel,
392                               "notify::screen",
393                               G_CALLBACK (toolbar_screen_changed),
394                               widget);
395   
396   toolbar_screen_changed (GTK_TOOLBAR (widget));
397 }
398
399 static void
400 gtk_toolbar_init (GtkToolbar *toolbar)
401 {
402   GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
403   GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS);
404
405   toolbar->num_children = 0;
406   toolbar->children     = NULL;
407   toolbar->orientation  = GTK_ORIENTATION_HORIZONTAL;
408   toolbar->icon_size    = DEFAULT_ICON_SIZE;
409   toolbar->style        = DEFAULT_TOOLBAR_STYLE;
410   toolbar->tooltips     = gtk_tooltips_new ();
411   g_object_ref (toolbar->tooltips);
412   gtk_object_sink (GTK_OBJECT (toolbar->tooltips));
413   
414   toolbar->button_maxw  = 0;
415   toolbar->button_maxh  = 0;
416
417   toolbar->style_set = FALSE;
418   toolbar->icon_size_set = FALSE;
419 }
420
421 static void
422 gtk_toolbar_set_property (GObject      *object,
423                           guint         prop_id,
424                           const GValue *value,
425                           GParamSpec   *pspec)
426 {
427   GtkToolbar *toolbar = GTK_TOOLBAR (object);
428   
429   switch (prop_id)
430     {
431     case PROP_ORIENTATION:
432       gtk_toolbar_set_orientation (toolbar, g_value_get_enum (value));
433       break;
434     case PROP_TOOLBAR_STYLE:
435       gtk_toolbar_set_style (toolbar, g_value_get_enum (value));
436       break;
437     }
438 }
439
440 static void
441 gtk_toolbar_get_property (GObject      *object,
442                           guint         prop_id,
443                           GValue       *value,
444                           GParamSpec   *pspec)
445 {
446   GtkToolbar *toolbar = GTK_TOOLBAR (object);
447
448   switch (prop_id)
449     {
450     case PROP_ORIENTATION:
451       g_value_set_enum (value, toolbar->orientation);
452       break;
453     case PROP_TOOLBAR_STYLE:
454       g_value_set_enum (value, toolbar->style);
455       break;
456     default:
457       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
458       break;
459     }
460 }
461
462 GtkWidget*
463 gtk_toolbar_new (void)
464 {
465   GtkToolbar *toolbar;
466
467   toolbar = g_object_new (GTK_TYPE_TOOLBAR, NULL);
468
469   return GTK_WIDGET (toolbar);
470 }
471
472 static void
473 gtk_toolbar_destroy (GtkObject *object)
474 {
475   GtkToolbar *toolbar;
476   GList *children;
477
478   g_return_if_fail (GTK_IS_TOOLBAR (object));
479
480   toolbar = GTK_TOOLBAR (object);
481
482   if (toolbar->tooltips)
483     {
484       g_object_unref (toolbar->tooltips);
485       toolbar->tooltips = NULL;
486     }
487
488   for (children = toolbar->children; children; children = children->next)
489     {
490       GtkToolbarChild *child;
491
492       child = children->data;
493
494       if (child->type != GTK_TOOLBAR_CHILD_SPACE)
495         {
496           g_object_ref (child->widget);
497           gtk_widget_unparent (child->widget);
498           gtk_widget_destroy (child->widget);
499           g_object_unref (child->widget);
500         }
501
502       g_free (child);
503     }
504   g_list_free (toolbar->children);
505   toolbar->children = NULL;
506   
507   GTK_OBJECT_CLASS (parent_class)->destroy (object);
508 }
509
510 static void
511 gtk_toolbar_paint_space_line (GtkWidget       *widget,
512                               GdkRectangle    *area,
513                               GtkToolbarChild *child)
514 {
515   GtkToolbar *toolbar;
516   GtkToolbarChildSpace *child_space;
517   gint space_size;
518   
519   g_return_if_fail (GTK_IS_TOOLBAR (widget));
520   g_return_if_fail (child != NULL);
521   g_return_if_fail (child->type == GTK_TOOLBAR_CHILD_SPACE);
522
523   toolbar = GTK_TOOLBAR (widget);
524
525   child_space = (GtkToolbarChildSpace *) child;
526   space_size = get_space_size (toolbar);
527   
528   if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
529     gtk_paint_vline (widget->style, widget->window,
530                      GTK_WIDGET_STATE (widget), area, widget,
531                      "toolbar",
532                      child_space->alloc_y + toolbar->button_maxh *
533                      SPACE_LINE_START / SPACE_LINE_DIVISION,
534                      child_space->alloc_y + toolbar->button_maxh *
535                      SPACE_LINE_END / SPACE_LINE_DIVISION,
536                      child_space->alloc_x +
537                      (space_size -
538                       widget->style->xthickness) / 2);
539   else
540     gtk_paint_hline (widget->style, widget->window,
541                      GTK_WIDGET_STATE (widget), area, widget,
542                      "toolbar",
543                      child_space->alloc_x + toolbar->button_maxw *
544                      SPACE_LINE_START / SPACE_LINE_DIVISION,
545                      child_space->alloc_x + toolbar->button_maxw *
546                      SPACE_LINE_END / SPACE_LINE_DIVISION,
547                      child_space->alloc_y +
548                      (space_size -
549                       widget->style->ythickness) / 2);
550 }
551
552 static gint
553 gtk_toolbar_expose (GtkWidget      *widget,
554                     GdkEventExpose *event)
555 {
556   GtkToolbar *toolbar;
557   GList *children;
558   GtkToolbarChild *child;
559   gint border_width;
560   
561   g_return_val_if_fail (GTK_IS_TOOLBAR (widget), FALSE);
562   g_return_val_if_fail (event != NULL, FALSE);
563
564   border_width = GTK_CONTAINER (widget)->border_width;
565   
566   if (GTK_WIDGET_DRAWABLE (widget))
567     {
568       GtkShadowType shadow_type;
569
570       toolbar = GTK_TOOLBAR (widget);
571
572       gtk_widget_style_get (widget, "shadow_type", &shadow_type, NULL);
573       
574       gtk_paint_box (widget->style,
575                      widget->window,
576                      GTK_WIDGET_STATE (widget),
577                      shadow_type,
578                      &event->area, widget, "toolbar",
579                      widget->allocation.x + border_width,
580                      widget->allocation.y + border_width,
581                      widget->allocation.width - border_width,
582                      widget->allocation.height - border_width);
583       
584       for (children = toolbar->children; children; children = children->next)
585         {
586           child = children->data;
587
588           if (child->type == GTK_TOOLBAR_CHILD_SPACE)
589             {
590               if (get_space_style (toolbar) == GTK_TOOLBAR_SPACE_LINE)
591                 gtk_toolbar_paint_space_line (widget, &event->area, child);
592             }
593           else
594             gtk_container_propagate_expose (GTK_CONTAINER (widget),
595                                             child->widget,
596                                             event);
597         }
598     }
599
600   return FALSE;
601 }
602
603 static void
604 gtk_toolbar_size_request (GtkWidget      *widget,
605                           GtkRequisition *requisition)
606 {
607   GtkToolbar *toolbar;
608   GList *children;
609   GtkToolbarChild *child;
610   gint nbuttons;
611   gint button_maxw, button_maxh;
612   gint widget_maxw, widget_maxh;
613   GtkRequisition child_requisition;
614   gint space_size;
615   gint ipadding;
616   
617   g_return_if_fail (GTK_IS_TOOLBAR (widget));
618   g_return_if_fail (requisition != NULL);
619
620   toolbar = GTK_TOOLBAR (widget);
621
622   requisition->width = GTK_CONTAINER (toolbar)->border_width * 2;
623   requisition->height = GTK_CONTAINER (toolbar)->border_width * 2;
624   nbuttons = 0;
625   button_maxw = 0;
626   button_maxh = 0;
627   widget_maxw = 0;
628   widget_maxh = 0;
629
630   space_size = get_space_size (toolbar);
631   
632   for (children = toolbar->children; children; children = children->next)
633     {
634       child = children->data;
635
636       switch (child->type)
637         {
638         case GTK_TOOLBAR_CHILD_SPACE:
639           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
640             requisition->width += space_size;
641           else
642             requisition->height += space_size;
643
644           break;
645
646         case GTK_TOOLBAR_CHILD_BUTTON:
647         case GTK_TOOLBAR_CHILD_RADIOBUTTON:
648         case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
649           if (GTK_WIDGET_VISIBLE (child->widget))
650             {              
651               gtk_widget_size_request (child->widget, &child_requisition);
652
653               nbuttons++;
654               button_maxw = MAX (button_maxw, child_requisition.width);
655               button_maxh = MAX (button_maxh, child_requisition.height);
656             }
657
658           break;
659
660         case GTK_TOOLBAR_CHILD_WIDGET:
661           if (GTK_WIDGET_VISIBLE (child->widget))
662             {
663               gtk_widget_size_request (child->widget, &child_requisition);
664
665               widget_maxw = MAX (widget_maxw, child_requisition.width);
666               widget_maxh = MAX (widget_maxh, child_requisition.height);
667
668               if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
669                 requisition->width += child_requisition.width;
670               else
671                 requisition->height += child_requisition.height;
672             }
673
674           break;
675
676         default:
677           g_assert_not_reached ();
678         }
679     }
680
681   if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
682     {
683       requisition->width += nbuttons * button_maxw;
684       requisition->height += MAX (button_maxh, widget_maxh);
685     }
686   else
687     {
688       requisition->width += MAX (button_maxw, widget_maxw);
689       requisition->height += nbuttons * button_maxh;
690     }
691
692   /* Extra spacing */
693   gtk_widget_style_get (widget, "internal_padding", &ipadding, NULL);
694   
695   requisition->width += 2 * ipadding;
696   requisition->height += 2 * ipadding;
697   
698   toolbar->button_maxw = button_maxw;
699   toolbar->button_maxh = button_maxh;
700 }
701
702 static void
703 gtk_toolbar_size_allocate (GtkWidget     *widget,
704                            GtkAllocation *allocation)
705 {
706   GtkToolbar *toolbar;
707   GList *children;
708   GtkToolbarChild *child;
709   GtkToolbarChildSpace *child_space;
710   GtkAllocation alloc;
711   GtkRequisition child_requisition;
712   gint x_border_width, y_border_width;
713   gint space_size;
714   gint ipadding;
715   
716   g_return_if_fail (GTK_IS_TOOLBAR (widget));
717   g_return_if_fail (allocation != NULL);
718
719   toolbar = GTK_TOOLBAR (widget);
720   widget->allocation = *allocation;
721   
722   x_border_width = GTK_CONTAINER (toolbar)->border_width;
723   y_border_width = GTK_CONTAINER (toolbar)->border_width;
724
725   gtk_widget_style_get (widget, "internal_padding", &ipadding, NULL);
726   
727   x_border_width += ipadding;
728   y_border_width += ipadding;
729   
730   if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
731     alloc.x = allocation->x + x_border_width;
732   else
733     alloc.y = allocation->y + y_border_width;
734
735   space_size = get_space_size (toolbar);
736   
737   for (children = toolbar->children; children; children = children->next)
738     {
739       child = children->data;
740
741       switch (child->type)
742         {
743         case GTK_TOOLBAR_CHILD_SPACE:
744
745           child_space = (GtkToolbarChildSpace *) child;
746
747           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
748             {
749               child_space->alloc_x = alloc.x;
750               child_space->alloc_y = allocation->y + (allocation->height - toolbar->button_maxh) / 2;
751               alloc.x += space_size;
752             }
753           else
754             {
755               child_space->alloc_x = allocation->x + (allocation->width - toolbar->button_maxw) / 2;
756               child_space->alloc_y = alloc.y;
757               alloc.y += space_size;
758             }
759
760           break;
761
762         case GTK_TOOLBAR_CHILD_BUTTON:
763         case GTK_TOOLBAR_CHILD_RADIOBUTTON:
764         case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
765           if (!GTK_WIDGET_VISIBLE (child->widget))
766             break;
767
768           alloc.width = toolbar->button_maxw;
769           alloc.height = toolbar->button_maxh;
770
771           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
772             alloc.y = allocation->y + (allocation->height - toolbar->button_maxh) / 2;
773           else
774             alloc.x = allocation->x + (allocation->width - toolbar->button_maxw) / 2;
775
776           gtk_widget_size_allocate (child->widget, &alloc);
777
778           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
779             alloc.x += toolbar->button_maxw;
780           else
781             alloc.y += toolbar->button_maxh;
782
783           break;
784
785         case GTK_TOOLBAR_CHILD_WIDGET:
786           if (!GTK_WIDGET_VISIBLE (child->widget))
787             break;
788
789           gtk_widget_get_child_requisition (child->widget, &child_requisition);
790           
791           alloc.width = child_requisition.width;
792           alloc.height = child_requisition.height;
793
794           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
795             alloc.y = allocation->y + (allocation->height - child_requisition.height) / 2;
796           else
797             alloc.x = allocation->x + (allocation->width - child_requisition.width) / 2;
798
799           gtk_widget_size_allocate (child->widget, &alloc);
800
801           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
802             alloc.x += child_requisition.width;
803           else
804             alloc.y += child_requisition.height;
805
806           break;
807
808         default:
809           g_assert_not_reached ();
810         }
811     }
812 }
813
814 static void
815 gtk_toolbar_style_set (GtkWidget  *widget,
816                        GtkStyle   *prev_style)
817 {
818   if (prev_style)
819     gtk_toolbar_update_button_relief (GTK_TOOLBAR (widget));
820 }
821
822 static gboolean
823 gtk_toolbar_focus (GtkWidget       *widget,
824                    GtkDirectionType dir)
825 {
826   /* Focus can't go in toolbars */
827   
828   return FALSE;
829 }
830
831 static void
832 child_show_all (GtkWidget *widget)
833 {
834   /* Don't show our own children, since that would
835    * show labels we may intend to hide in icons-only mode
836    */
837   if (!g_object_get_data (G_OBJECT (widget),
838                           "gtk-toolbar-is-child"))
839     gtk_widget_show_all (widget);
840 }
841
842 static void
843 gtk_toolbar_show_all (GtkWidget *widget)
844 {
845   gtk_container_foreach (GTK_CONTAINER (widget),
846                          (GtkCallback) child_show_all,
847                          NULL);
848   gtk_widget_show (widget);
849 }
850
851 static void
852 gtk_toolbar_add (GtkContainer *container,
853                  GtkWidget    *widget)
854 {
855   g_return_if_fail (GTK_IS_TOOLBAR (container));
856   g_return_if_fail (widget != NULL);
857
858   gtk_toolbar_append_widget (GTK_TOOLBAR (container), widget, NULL, NULL);
859 }
860
861 static void
862 gtk_toolbar_remove (GtkContainer *container,
863                     GtkWidget    *widget)
864 {
865   GtkToolbar *toolbar;
866   GList *children;
867   GtkToolbarChild *child;
868
869   g_return_if_fail (GTK_IS_TOOLBAR (container));
870   g_return_if_fail (widget != NULL);
871
872   toolbar = GTK_TOOLBAR (container);
873
874   for (children = toolbar->children; children; children = children->next)
875     {
876       child = children->data;
877
878       if ((child->type != GTK_TOOLBAR_CHILD_SPACE) && (child->widget == widget))
879         {
880           gboolean was_visible;
881
882           was_visible = GTK_WIDGET_VISIBLE (widget);
883           gtk_widget_unparent (widget);
884
885           toolbar->children = g_list_remove_link (toolbar->children, children);
886           g_free (child);
887           g_list_free (children);
888           toolbar->num_children--;
889
890           if (was_visible && GTK_WIDGET_VISIBLE (container))
891             gtk_widget_queue_resize (GTK_WIDGET (container));
892
893           break;
894         }
895     }
896 }
897
898 static void
899 gtk_toolbar_forall (GtkContainer *container,
900                     gboolean      include_internals,
901                     GtkCallback   callback,
902                     gpointer      callback_data)
903 {
904   GtkToolbar *toolbar;
905   GList *children;
906   GtkToolbarChild *child;
907
908   g_return_if_fail (GTK_IS_TOOLBAR (container));
909   g_return_if_fail (callback != NULL);
910
911   toolbar = GTK_TOOLBAR (container);
912
913   for (children = toolbar->children; children; children = children->next)
914     {
915       child = children->data;
916
917       if (child->type != GTK_TOOLBAR_CHILD_SPACE)
918         (*callback) (child->widget, callback_data);
919     }
920 }
921
922 GtkWidget *
923 gtk_toolbar_append_item (GtkToolbar    *toolbar,
924                          const char    *text,
925                          const char    *tooltip_text,
926                          const char    *tooltip_private_text,
927                          GtkWidget     *icon,
928                          GtkSignalFunc  callback,
929                          gpointer       user_data)
930 {
931   return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
932                                      NULL, text,
933                                      tooltip_text, tooltip_private_text,
934                                      icon, callback, user_data,
935                                      toolbar->num_children);
936 }
937
938 GtkWidget *
939 gtk_toolbar_prepend_item (GtkToolbar    *toolbar,
940                           const char    *text,
941                           const char    *tooltip_text,
942                           const char    *tooltip_private_text,
943                           GtkWidget     *icon,
944                           GtkSignalFunc  callback,
945                           gpointer       user_data)
946 {
947   return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
948                                      NULL, text,
949                                      tooltip_text, tooltip_private_text,
950                                      icon, callback, user_data,
951                                      0);
952 }
953
954 static GtkWidget *
955 gtk_toolbar_internal_insert_item (GtkToolbar    *toolbar,
956                                   const char    *text,
957                                   const char    *tooltip_text,
958                                   const char    *tooltip_private_text,
959                                   GtkWidget     *icon,
960                                   GtkSignalFunc  callback,
961                                   gpointer       user_data,
962                                   gint           position,
963                                   gboolean       has_mnemonic)
964 {
965   return gtk_toolbar_internal_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
966                                               NULL, text,
967                                               tooltip_text, tooltip_private_text,
968                                               icon, callback, user_data,
969                                               position, has_mnemonic);
970 }
971      
972 GtkWidget *
973 gtk_toolbar_insert_item (GtkToolbar    *toolbar,
974                          const char    *text,
975                          const char    *tooltip_text,
976                          const char    *tooltip_private_text,
977                          GtkWidget     *icon,
978                          GtkSignalFunc  callback,
979                          gpointer       user_data,
980                          gint           position)
981 {
982   return gtk_toolbar_internal_insert_item (toolbar, 
983                                            text, tooltip_text, tooltip_private_text,
984                                            icon, callback, user_data,
985                                            position, FALSE);
986 }
987
988 /**
989  * gtk_toolbar_set_icon_size:
990  * @toolbar: A #GtkToolbar
991  * @icon_size: The #GtkIconSize that stock icons in the toolbar shall have.
992  *
993  * This function sets the size of stock icons in the toolbar. You
994  * can call it both before you add the icons and after they've been
995  * added. The size you set will override user preferences for the default
996  * icon size.
997  **/
998 void
999 gtk_toolbar_set_icon_size (GtkToolbar  *toolbar,
1000                            GtkIconSize  icon_size)
1001 {
1002   GList *children;
1003   GtkToolbarChild *child;
1004   GtkImage *image;
1005   gchar *stock_id;
1006
1007   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1008
1009   toolbar->icon_size_set = TRUE;
1010   
1011   if (toolbar->icon_size == icon_size)
1012     return;
1013   
1014   toolbar->icon_size = icon_size;
1015
1016   for (children = toolbar->children; children; children = children->next)
1017     {
1018       child = children->data;
1019       if ((child->type == GTK_TOOLBAR_CHILD_BUTTON ||
1020            child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
1021            child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON) &&
1022           GTK_IS_IMAGE (child->icon))
1023         {
1024           image = GTK_IMAGE (child->icon);
1025           if (gtk_image_get_storage_type (image) == GTK_IMAGE_STOCK)
1026             {
1027               gtk_image_get_stock (image, &stock_id, NULL);
1028               stock_id = g_strdup (stock_id);
1029               gtk_image_set_from_stock (image,
1030                                         stock_id,
1031                                         icon_size);
1032               g_free (stock_id);
1033             }
1034         }
1035     }
1036   
1037   gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1038 }
1039
1040 /**
1041  * gtk_toolbar_get_icon_size:
1042  * @toolbar: a #GtkToolbar
1043  *
1044  * Retrieves the icon size fo the toolbar. See gtk_toolbar_set_icon_size().
1045  *
1046  * Return value: the current icon size for the icons on the toolbar.
1047  **/
1048 GtkIconSize
1049 gtk_toolbar_get_icon_size (GtkToolbar *toolbar)
1050 {
1051   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_ICON_SIZE);
1052
1053   return toolbar->icon_size;
1054 }
1055
1056 /**
1057  * gtk_toolbar_unset_icon_size:
1058  * @toolbar: a #GtkToolbar
1059  * 
1060  * Unsets toolbar icon size set with gtk_toolbar_set_icon_size(), so that
1061  * user preferences will be used to determine the icon size.
1062  **/
1063 void
1064 gtk_toolbar_unset_icon_size (GtkToolbar  *toolbar)
1065 {
1066   GtkIconSize size;
1067
1068   if (toolbar->icon_size_set)
1069     {
1070       GtkSettings *settings = toolbar_get_settings (toolbar);
1071
1072       if (settings)
1073         g_object_get (settings,
1074                       "gtk-toolbar-icon-size", &size,
1075                       NULL);
1076       else
1077         size = DEFAULT_ICON_SIZE;
1078
1079       if (size != toolbar->icon_size)
1080         gtk_toolbar_set_icon_size (toolbar, size);
1081
1082       toolbar->icon_size_set = FALSE;
1083     }
1084 }
1085
1086 /**
1087  * gtk_toolbar_insert_stock:
1088  * @toolbar: A #GtkToolbar
1089  * @stock_id: The id of the stock item you want to insert
1090  * @tooltip_text: The text in the tooltip of the toolbar button
1091  * @tooltip_private_text: The private text of the tooltip
1092  * @callback: The callback called when the toolbar button is clicked.
1093  * @user_data: user data passed to callback
1094  * @position: The position the button shall be inserted at.
1095  *            -1 means at the end.
1096  *
1097  * Inserts a stock item at the specified position of the toolbar.  If
1098  * @stock_id is not a known stock item ID, it's inserted verbatim,
1099  * except that underscores are used to mark mnemonics (see
1100  * gtk_label_new_with_mnemonic()).
1101  *
1102  * Returns: the inserted widget
1103  */
1104 GtkWidget*
1105 gtk_toolbar_insert_stock (GtkToolbar      *toolbar,
1106                           const gchar     *stock_id,
1107                           const char      *tooltip_text,
1108                           const char      *tooltip_private_text,
1109                           GtkSignalFunc    callback,
1110                           gpointer         user_data,
1111                           gint             position)
1112 {
1113   GtkStockItem item;
1114   GtkWidget *image;
1115
1116   if (gtk_stock_lookup (stock_id, &item))
1117     {
1118       image = gtk_image_new_from_stock (stock_id, toolbar->icon_size);
1119
1120       return gtk_toolbar_internal_insert_item (toolbar,
1121                                                item.label,
1122                                                tooltip_text,
1123                                                tooltip_private_text,
1124                                                image,
1125                                                callback,
1126                                                user_data,
1127                                                position,
1128                                                TRUE);
1129     }
1130   else
1131     return gtk_toolbar_internal_insert_item (toolbar,
1132                                              stock_id,
1133                                              tooltip_text,
1134                                              tooltip_private_text,
1135                                              NULL,
1136                                              callback,
1137                                              user_data,
1138                                              position,
1139                                              TRUE);
1140 }
1141
1142
1143
1144 void
1145 gtk_toolbar_append_space (GtkToolbar *toolbar)
1146 {
1147   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
1148                               NULL, NULL,
1149                               NULL, NULL,
1150                               NULL, NULL, NULL,
1151                               toolbar->num_children);
1152 }
1153
1154 void
1155 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
1156 {
1157   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
1158                               NULL, NULL,
1159                               NULL, NULL,
1160                               NULL, NULL, NULL,
1161                               0);
1162 }
1163
1164 void
1165 gtk_toolbar_insert_space (GtkToolbar *toolbar,
1166                           gint        position)
1167 {
1168   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
1169                               NULL, NULL,
1170                               NULL, NULL,
1171                               NULL, NULL, NULL,
1172                               position);
1173 }
1174
1175 /**
1176  * gtk_toolbar_remove_space:
1177  * @toolbar: a #GtkToolbar.
1178  * @position: the index of the space to remove.
1179  * 
1180  * Removes a space from the specified position.
1181  **/
1182 void
1183 gtk_toolbar_remove_space (GtkToolbar *toolbar,
1184                           gint        position)
1185 {
1186   GList *children;
1187   GtkToolbarChild *child;
1188   gint i;
1189   
1190   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1191   
1192   i = 0;
1193   for (children = toolbar->children; children; children = children->next)
1194     {
1195       child = children->data;
1196
1197       if (i == position)
1198         {
1199           if (child->type == GTK_TOOLBAR_CHILD_SPACE)
1200             {
1201               toolbar->children = g_list_remove_link (toolbar->children, children);
1202               g_free (child);
1203               g_list_free (children);
1204               toolbar->num_children--;
1205               
1206               gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1207             }
1208           else
1209             {
1210               g_warning ("Toolbar position %d is not a space", position);
1211             }
1212
1213           return;
1214         }
1215
1216       ++i;
1217     }
1218
1219   g_warning ("Toolbar position %d doesn't exist", position);
1220 }
1221
1222 /**
1223  * gtk_toolbar_append_widget:
1224  * @toolbar: a #GtkToolbar.
1225  * @widget: a #GtkWidget to add to the toolbar. 
1226  * @tooltip_text: the element's tooltip.
1227  * @tooltip_private_text: used for context-sensitive help about this toolbar element.
1228  * 
1229  * Adds a widget to the end of the given toolbar.
1230  **/ 
1231 void
1232 gtk_toolbar_append_widget (GtkToolbar  *toolbar,
1233                            GtkWidget   *widget,
1234                            const gchar *tooltip_text,
1235                            const gchar *tooltip_private_text)
1236 {
1237   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
1238                               widget, NULL,
1239                               tooltip_text, tooltip_private_text,
1240                               NULL, NULL, NULL,
1241                               toolbar->num_children);
1242 }
1243
1244 /**
1245  * gtk_toolbar_prepend_widget:
1246  * @toolbar: a #GtkToolbar.
1247  * @widget: a #GtkWidget to add to the toolbar. 
1248  * @tooltip_text: the element's tooltip.
1249  * @tooltip_private_text: used for context-sensitive help about this toolbar element.
1250  * 
1251  * Adds a widget to the beginning of the given toolbar.
1252  **/ 
1253 void
1254 gtk_toolbar_prepend_widget (GtkToolbar  *toolbar,
1255                             GtkWidget   *widget,
1256                             const gchar *tooltip_text,
1257                             const gchar *tooltip_private_text)
1258 {
1259   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
1260                               widget, NULL,
1261                               tooltip_text, tooltip_private_text,
1262                               NULL, NULL, NULL,
1263                               0);
1264 }
1265
1266 /**
1267  * gtk_toolbar_insert_widget:
1268  * @toolbar: a #GtkToolbar.
1269  * @widget: a #GtkWidget to add to the toolbar. 
1270  * @tooltip_text: the element's tooltip.
1271  * @tooltip_private_text: used for context-sensitive help about this toolbar element.
1272  * @position: the number of widgets to insert this widget after.
1273  * 
1274  * Inserts a widget in the toolbar at the given position.
1275  **/ 
1276 void
1277 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
1278                            GtkWidget  *widget,
1279                            const char *tooltip_text,
1280                            const char *tooltip_private_text,
1281                            gint        position)
1282 {
1283   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
1284                               widget, NULL,
1285                               tooltip_text, tooltip_private_text,
1286                               NULL, NULL, NULL,
1287                               position);
1288 }
1289
1290 GtkWidget*
1291 gtk_toolbar_append_element (GtkToolbar          *toolbar,
1292                             GtkToolbarChildType  type,
1293                             GtkWidget           *widget,
1294                             const char          *text,
1295                             const char          *tooltip_text,
1296                             const char          *tooltip_private_text,
1297                             GtkWidget           *icon,
1298                             GtkSignalFunc        callback,
1299                             gpointer             user_data)
1300 {
1301   return gtk_toolbar_insert_element (toolbar, type, widget, text,
1302                                      tooltip_text, tooltip_private_text,
1303                                      icon, callback, user_data,
1304                                      toolbar->num_children);
1305 }
1306
1307 GtkWidget *
1308 gtk_toolbar_prepend_element (GtkToolbar          *toolbar,
1309                              GtkToolbarChildType  type,
1310                              GtkWidget           *widget,
1311                              const char          *text,
1312                              const char          *tooltip_text,
1313                              const char          *tooltip_private_text,
1314                              GtkWidget           *icon,
1315                              GtkSignalFunc        callback,
1316                              gpointer             user_data)
1317 {
1318   return gtk_toolbar_insert_element (toolbar, type, widget, text,
1319                                      tooltip_text, tooltip_private_text,
1320                                      icon, callback, user_data, 0);
1321 }
1322
1323 /**
1324  * gtk_toolbar_insert_element:
1325  * @toolbar: a #GtkToolbar.
1326  * @type: a value of type #GtkToolbarChildType that determines what @widget
1327  *   will be.
1328  * @widget: a #GtkWidget, or %NULL. 
1329  * @text: the element's label.
1330  * @tooltip_text: the element's tooltip.
1331  * @tooltip_private_text: used for context-sensitive help about this toolbar element.
1332  * @icon: a #GtkWidget that provides pictorial representation of the element's function.
1333  * @callback: the function to be executed when the button is pressed.
1334  * @user_data: any data you wish to pass to the callback.
1335  * @position: the number of widgets to insert this element after.
1336  *
1337  * Inserts a new element in the toolbar at the given position. 
1338  *
1339  * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
1340  * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
1341  * the radio group for the new element. In all other cases, @widget must
1342  * be %NULL.
1343  *
1344  * Return value: the new toolbar element as a #GtkWidget.
1345  **/
1346 GtkWidget *
1347 gtk_toolbar_insert_element (GtkToolbar          *toolbar,
1348                             GtkToolbarChildType  type,
1349                             GtkWidget           *widget,
1350                             const char          *text,
1351                             const char          *tooltip_text,
1352                             const char          *tooltip_private_text,
1353                             GtkWidget           *icon,
1354                             GtkSignalFunc        callback,
1355                             gpointer             user_data,
1356                             gint                 position)
1357 {
1358   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
1359   if (type == GTK_TOOLBAR_CHILD_WIDGET)
1360     {
1361       g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
1362     }
1363   else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON)
1364     g_return_val_if_fail (widget == NULL, NULL);
1365   
1366   return gtk_toolbar_internal_insert_element (toolbar, type, widget, text,
1367                                               tooltip_text, tooltip_private_text,
1368                                               icon, callback, user_data,
1369                                               position, FALSE);
1370 }
1371
1372 static GtkWidget *
1373 gtk_toolbar_internal_insert_element (GtkToolbar          *toolbar,
1374                                      GtkToolbarChildType  type,
1375                                      GtkWidget           *widget,
1376                                      const char          *text,
1377                                      const char          *tooltip_text,
1378                                      const char          *tooltip_private_text,
1379                                      GtkWidget           *icon,
1380                                      GtkSignalFunc        callback,
1381                                      gpointer             user_data,
1382                                      gint                 position,
1383                                      gboolean             has_mnemonic)
1384 {
1385   GtkToolbarChild *child;
1386   GtkWidget *box;
1387
1388   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
1389   if (type == GTK_TOOLBAR_CHILD_WIDGET)
1390     {
1391       g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
1392     }
1393   else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON)
1394     g_return_val_if_fail (widget == NULL, NULL);
1395
1396   if (type == GTK_TOOLBAR_CHILD_SPACE)
1397     child = (GtkToolbarChild *) g_new (GtkToolbarChildSpace, 1);
1398   else
1399     child = g_new (GtkToolbarChild, 1);
1400
1401   child->type = type;
1402   child->icon = NULL;
1403   child->label = NULL;
1404
1405   switch (type)
1406     {
1407     case GTK_TOOLBAR_CHILD_SPACE:
1408       child->widget = NULL;
1409       ((GtkToolbarChildSpace *) child)->alloc_x =
1410         ((GtkToolbarChildSpace *) child)->alloc_y = 0;
1411       break;
1412
1413     case GTK_TOOLBAR_CHILD_WIDGET:
1414       child->widget = widget;
1415       break;
1416
1417     case GTK_TOOLBAR_CHILD_BUTTON:
1418     case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
1419     case GTK_TOOLBAR_CHILD_RADIOBUTTON:
1420       if (type == GTK_TOOLBAR_CHILD_BUTTON)
1421         {
1422           child->widget = gtk_button_new ();
1423           gtk_button_set_relief (GTK_BUTTON (child->widget), get_button_relief (toolbar));
1424         }
1425       else if (type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
1426         {
1427           child->widget = gtk_toggle_button_new ();
1428           gtk_button_set_relief (GTK_BUTTON (child->widget), get_button_relief (toolbar));
1429           gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child->widget),
1430                                       FALSE);
1431         }
1432       else
1433         {
1434           child->widget = gtk_radio_button_new (widget
1435                                                 ? gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget))
1436                                                 : NULL);
1437           gtk_button_set_relief (GTK_BUTTON (child->widget), get_button_relief (toolbar));
1438           gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child->widget), FALSE);
1439         }
1440
1441       GTK_WIDGET_UNSET_FLAGS (child->widget, GTK_CAN_FOCUS);
1442
1443       if (callback)
1444         g_signal_connect (child->widget, "clicked",
1445                           callback, user_data);
1446
1447       if (toolbar->style == GTK_TOOLBAR_BOTH_HORIZ)
1448           box = gtk_hbox_new (FALSE, 0);
1449       else
1450           box = gtk_vbox_new (FALSE, 0);
1451       gtk_container_add (GTK_CONTAINER (child->widget), box);
1452       gtk_widget_show (box);
1453
1454       if (text)
1455         {
1456           if (has_mnemonic)
1457             child->label = gtk_label_new_with_mnemonic (text);
1458           else
1459             child->label = gtk_label_new (text);
1460           gtk_box_pack_end (GTK_BOX (box), child->label, FALSE, FALSE, 0);
1461           if (toolbar->style != GTK_TOOLBAR_ICONS)
1462             gtk_widget_show (child->label);
1463         }
1464
1465       if (icon)
1466         {
1467           child->icon = GTK_WIDGET (icon);
1468           gtk_box_pack_end (GTK_BOX (box), child->icon, FALSE, FALSE, 0);
1469           if (toolbar->style != GTK_TOOLBAR_TEXT)
1470             gtk_widget_show (child->icon);
1471         }
1472
1473       if (type != GTK_TOOLBAR_CHILD_WIDGET)
1474         {
1475           /* Mark child as ours */
1476           g_object_set_data (G_OBJECT (child->widget),
1477                              "gtk-toolbar-is-child",
1478                              GINT_TO_POINTER (TRUE));
1479         }
1480       gtk_widget_show (child->widget);
1481       break;
1482
1483     default:
1484       g_assert_not_reached ();
1485     }
1486
1487   if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text)
1488     gtk_tooltips_set_tip (toolbar->tooltips, child->widget,
1489                           tooltip_text, tooltip_private_text);
1490
1491   toolbar->children = g_list_insert (toolbar->children, child, position);
1492   toolbar->num_children++;
1493
1494   if (type != GTK_TOOLBAR_CHILD_SPACE)
1495     gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
1496   else
1497     gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1498
1499   return child->widget;
1500 }
1501
1502 void
1503 gtk_toolbar_set_orientation (GtkToolbar     *toolbar,
1504                              GtkOrientation  orientation)
1505 {
1506   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1507
1508   g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0, orientation);
1509 }
1510
1511 /**
1512  * gtk_toolbar_get_orientation:
1513  * @toolbar: a #GtkToolbar
1514  * 
1515  * Retrieves the current orientation of the toolbar. See
1516  * gtk_toolbar_set_orientation().
1517  *
1518  * Return value: the orientation
1519  **/
1520 GtkOrientation
1521 gtk_toolbar_get_orientation (GtkToolbar *toolbar)
1522 {
1523   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
1524
1525   return toolbar->orientation;
1526 }
1527
1528 void
1529 gtk_toolbar_set_style (GtkToolbar      *toolbar,
1530                        GtkToolbarStyle  style)
1531 {
1532   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1533
1534   toolbar->style_set = TRUE;
1535   g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
1536 }
1537
1538 /**
1539  * gtk_toolbar_get_style:
1540  * @toolbar: a #GtkToolbar
1541  *
1542  * Retrieves whether the toolbar has text, icons, or both . See
1543  * gtk_toolbar_set_style().
1544  
1545  * Return value: the current style of @toolbar
1546  **/
1547 GtkToolbarStyle
1548 gtk_toolbar_get_style (GtkToolbar *toolbar)
1549 {
1550   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_TOOLBAR_STYLE);
1551
1552   return toolbar->style;
1553 }
1554
1555 /**
1556  * gtk_toolbar_unset_style:
1557  * @toolbar: a #GtkToolbar
1558  * 
1559  * Unsets a toolbar style set with gtk_toolbar_set_style(), so that
1560  * user preferences will be used to determine the toolbar style.
1561  **/
1562 void
1563 gtk_toolbar_unset_style (GtkToolbar *toolbar)
1564 {
1565   GtkToolbarStyle style;
1566   
1567   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1568
1569   if (toolbar->style_set)
1570     {
1571       GtkSettings *settings = toolbar_get_settings (toolbar);
1572
1573       if (settings)
1574         g_object_get (settings,
1575                       "gtk-toolbar-style", &style,
1576                       NULL);
1577       else
1578         style = DEFAULT_TOOLBAR_STYLE;
1579
1580       if (style != toolbar->style)
1581         g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
1582       
1583       toolbar->style_set = FALSE;
1584     }
1585 }
1586
1587 void
1588 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
1589                           gboolean    enable)
1590 {
1591   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1592
1593   if (enable)
1594     gtk_tooltips_enable (toolbar->tooltips);
1595   else
1596     gtk_tooltips_disable (toolbar->tooltips);
1597 }
1598
1599 /**
1600  * gtk_toolbar_get_tooltips:
1601  * @toolbar: a #GtkToolbar
1602  *
1603  * Retrieves whether tooltips are enabled. See
1604  * gtk_toolbar_set_tooltips().
1605  *
1606  * Return value: %TRUE if tooltips are enabled
1607  **/
1608 gboolean
1609 gtk_toolbar_get_tooltips (GtkToolbar *toolbar)
1610 {
1611   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
1612
1613   return toolbar->tooltips->enabled;
1614 }
1615
1616 static void
1617 gtk_toolbar_update_button_relief (GtkToolbar *toolbar)
1618 {
1619   GList *children;
1620   GtkToolbarChild *child;
1621   GtkReliefStyle relief;
1622   
1623   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1624
1625   relief = get_button_relief (toolbar);
1626   
1627   for (children = toolbar->children; children; children = children->next)
1628     {
1629       child = children->data;
1630       if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
1631           child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
1632           child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
1633         gtk_button_set_relief (GTK_BUTTON (child->widget), relief);
1634     }
1635 }
1636
1637 static void
1638 gtk_real_toolbar_orientation_changed (GtkToolbar     *toolbar,
1639                                       GtkOrientation  orientation)
1640 {
1641   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1642
1643   if (toolbar->orientation != orientation)
1644     {
1645       toolbar->orientation = orientation;
1646       gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1647       g_object_notify (G_OBJECT (toolbar), "orientation");
1648     }
1649 }
1650
1651 static GtkWidget *
1652 get_first_child (GtkContainer *container)
1653 {
1654   GList *children = gtk_container_get_children (container);
1655   GtkWidget *result = children ? children->data : NULL;
1656   g_list_free (children);
1657   
1658   return result;
1659 }
1660
1661 static void
1662 gtk_real_toolbar_style_changed (GtkToolbar      *toolbar,
1663                                 GtkToolbarStyle  style)
1664 {
1665   GList *children;
1666   GtkToolbarChild *child;
1667   GtkWidget* box = NULL;
1668   
1669   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1670
1671   if (toolbar->style != style)
1672     {
1673       toolbar->style = style;
1674
1675       for (children = toolbar->children; children; children = children->next)
1676         {
1677           child = children->data;
1678
1679           if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
1680               child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
1681               child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
1682             switch (style)
1683               {
1684               case GTK_TOOLBAR_ICONS:
1685                 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
1686                   gtk_widget_show (child->icon);
1687
1688                 if (child->label && GTK_WIDGET_VISIBLE (child->label))
1689                   gtk_widget_hide (child->label);
1690
1691                 break;
1692
1693               case GTK_TOOLBAR_TEXT:
1694                 if (child->icon && GTK_WIDGET_VISIBLE (child->icon))
1695                   gtk_widget_hide (child->icon);
1696                 
1697                 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
1698                   gtk_widget_show (child->label);
1699
1700                 break;
1701
1702               case GTK_TOOLBAR_BOTH:
1703                 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
1704                   gtk_widget_show (child->icon);
1705
1706                 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
1707                   gtk_widget_show (child->label);
1708
1709                 box = get_first_child (GTK_CONTAINER (child->widget));
1710
1711                 if (GTK_IS_HBOX (box))
1712                 {
1713                     if (child->icon)
1714                     {
1715                         g_object_ref (child->icon);
1716                         gtk_container_remove (GTK_CONTAINER (box),
1717                                               child->icon);
1718                     }
1719                     if (child->label)
1720                     {
1721                         g_object_ref (child->label);
1722                         gtk_container_remove (GTK_CONTAINER (box),
1723                                               child->label);
1724                     }
1725                     gtk_container_remove (GTK_CONTAINER (child->widget),
1726                                           box);
1727                     
1728                     box = gtk_vbox_new (FALSE, 0);
1729                     gtk_widget_show (box);
1730                     
1731                     if (child->label)
1732                     {
1733                         gtk_box_pack_end (GTK_BOX (box), child->label, FALSE, FALSE, 0);
1734                         g_object_unref (child->label);
1735                     }
1736                     if (child->icon)
1737                     {
1738                         gtk_box_pack_end (GTK_BOX (box), child->icon, FALSE, FALSE, 0);
1739                         g_object_unref (child->icon);
1740                     }
1741                     gtk_container_add (GTK_CONTAINER (child->widget),
1742                                        box);
1743                 }
1744                 
1745                 break;
1746                 
1747               case GTK_TOOLBAR_BOTH_HORIZ:
1748                 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
1749                   gtk_widget_show (child->icon);
1750                 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
1751                   gtk_widget_show (child->label);
1752
1753                 box = get_first_child (GTK_CONTAINER (child->widget));
1754                 
1755                 if (GTK_IS_VBOX (box))
1756                 {
1757                     if (child->icon)
1758                     {
1759                         g_object_ref (child->icon);
1760                         gtk_container_remove (GTK_CONTAINER (box),
1761                                               child->icon);
1762                     }
1763                     if (child->label)
1764                     {
1765                         g_object_ref (child->label);
1766                         gtk_container_remove (GTK_CONTAINER (box),
1767                                               child->label);
1768                     }
1769                     gtk_container_remove (GTK_CONTAINER (child->widget),
1770                                           box);
1771
1772                     box = gtk_hbox_new (FALSE, 0);
1773                     gtk_widget_show (box);
1774                     
1775                     if (child->label)
1776                     {
1777                         gtk_box_pack_end (GTK_BOX (box), child->label, TRUE, TRUE, 0);
1778                         g_object_unref (child->label);
1779                     }
1780                     if (child->icon)
1781                     {
1782                         gtk_box_pack_end (GTK_BOX (box), child->icon, FALSE, FALSE, 0);
1783                         g_object_unref (child->icon);
1784                     }
1785                     gtk_container_add (GTK_CONTAINER (child->widget), box);
1786                     
1787                 }
1788                 
1789                 break;
1790
1791               default:
1792                 g_assert_not_reached ();
1793               }
1794         }
1795
1796       gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1797       g_object_notify (G_OBJECT (toolbar), "toolbar_style");
1798     }
1799 }
1800
1801
1802 static GtkReliefStyle
1803 get_button_relief (GtkToolbar *toolbar)
1804 {
1805   GtkReliefStyle button_relief = GTK_RELIEF_NORMAL;
1806
1807   gtk_widget_ensure_style (GTK_WIDGET (toolbar));
1808   gtk_widget_style_get (GTK_WIDGET (toolbar),
1809                         "button_relief", &button_relief,
1810                         NULL);
1811
1812   return button_relief;
1813 }
1814
1815 static gint
1816 get_space_size (GtkToolbar *toolbar)
1817 {
1818   gint space_size = DEFAULT_SPACE_SIZE;
1819
1820   gtk_widget_style_get (GTK_WIDGET (toolbar),
1821                         "space_size", &space_size,
1822                         NULL);
1823
1824   return space_size;
1825 }
1826
1827 static GtkToolbarSpaceStyle
1828 get_space_style (GtkToolbar *toolbar)
1829 {
1830   GtkToolbarSpaceStyle space_style = DEFAULT_SPACE_STYLE;
1831
1832   gtk_widget_style_get (GTK_WIDGET (toolbar),
1833                         "space_style", &space_style,
1834                         NULL);
1835
1836
1837   return space_style;  
1838 }