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