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