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