]> Pileus Git - ~andy/gtk/blob - gtk/gtktoolbar.c
fafb94cc511d8632c0e30d34063a6e52be639ea8
[~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 Library 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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library 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-1999.  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
36
37 #define DEFAULT_SPACE_SIZE  5
38 #define DEFAULT_SPACE_STYLE GTK_TOOLBAR_SPACE_EMPTY
39
40 #define SPACE_LINE_DIVISION 10
41 #define SPACE_LINE_START    3
42 #define SPACE_LINE_END      7
43
44 enum {
45   ARG_0,
46   ARG_ORIENTATION,
47   ARG_TOOLBAR_STYLE,
48   ARG_SPACE_SIZE,
49   ARG_SPACE_STYLE,
50   ARG_RELIEF
51 };
52
53 enum {
54   ORIENTATION_CHANGED,
55   STYLE_CHANGED,
56   LAST_SIGNAL
57 };
58
59 typedef struct _GtkToolbarChildSpace GtkToolbarChildSpace;
60 struct _GtkToolbarChildSpace
61 {
62   GtkToolbarChild child;
63
64   gint alloc_x, alloc_y;
65 };
66
67 static void gtk_toolbar_class_init               (GtkToolbarClass *class);
68 static void gtk_toolbar_init                     (GtkToolbar      *toolbar);
69 static void gtk_toolbar_set_arg                  (GtkObject       *object,
70                                                   GtkArg          *arg,
71                                                   guint            arg_id);
72 static void gtk_toolbar_get_arg                  (GtkObject       *object,
73                                                   GtkArg          *arg,
74                                                   guint            arg_id);
75 static void gtk_toolbar_destroy                  (GtkObject       *object);
76 static void gtk_toolbar_map                      (GtkWidget       *widget);
77 static void gtk_toolbar_unmap                    (GtkWidget       *widget);
78 static void gtk_toolbar_draw                     (GtkWidget       *widget,
79                                                   GdkRectangle    *area);
80 static gint gtk_toolbar_expose                   (GtkWidget       *widget,
81                                                   GdkEventExpose  *event);
82 static void gtk_toolbar_size_request             (GtkWidget       *widget,
83                                                   GtkRequisition  *requisition);
84 static void gtk_toolbar_size_allocate            (GtkWidget       *widget,
85                                                   GtkAllocation   *allocation);
86 static void gtk_toolbar_add                      (GtkContainer    *container,
87                                                   GtkWidget       *widget);
88 static void gtk_toolbar_remove                   (GtkContainer    *container,
89                                                   GtkWidget       *widget);
90 static void gtk_toolbar_forall                   (GtkContainer    *container,
91                                                   gboolean         include_internals,
92                                                   GtkCallback      callback,
93                                                   gpointer         callback_data);
94 static void gtk_real_toolbar_orientation_changed (GtkToolbar      *toolbar,
95                                                   GtkOrientation   orientation);
96 static void gtk_real_toolbar_style_changed       (GtkToolbar      *toolbar,
97                                                   GtkToolbarStyle  style);
98
99
100 static GtkContainerClass *parent_class;
101
102 static guint toolbar_signals[LAST_SIGNAL] = { 0 };
103
104
105 GtkType
106 gtk_toolbar_get_type (void)
107 {
108   static GtkType toolbar_type = 0;
109
110   if (!toolbar_type)
111     {
112       static const GtkTypeInfo toolbar_info =
113       {
114         "GtkToolbar",
115         sizeof (GtkToolbar),
116         sizeof (GtkToolbarClass),
117         (GtkClassInitFunc) gtk_toolbar_class_init,
118         (GtkObjectInitFunc) gtk_toolbar_init,
119         /* reserved_1 */ NULL,
120         /* reserved_2 */ NULL,
121         (GtkClassInitFunc) NULL,
122       };
123
124       toolbar_type = gtk_type_unique (gtk_container_get_type (), &toolbar_info);
125     }
126
127   return toolbar_type;
128 }
129
130 static void
131 gtk_toolbar_class_init (GtkToolbarClass *class)
132 {
133   GtkObjectClass *object_class;
134   GtkWidgetClass *widget_class;
135   GtkContainerClass *container_class;
136
137   object_class = (GtkObjectClass *) class;
138   widget_class = (GtkWidgetClass *) class;
139   container_class = (GtkContainerClass *) class;
140
141   parent_class = gtk_type_class (gtk_container_get_type ());
142   
143   toolbar_signals[ORIENTATION_CHANGED] =
144     gtk_signal_new ("orientation_changed",
145                     GTK_RUN_FIRST,
146                     object_class->type,
147                     GTK_SIGNAL_OFFSET (GtkToolbarClass, orientation_changed),
148                     gtk_marshal_NONE__INT,
149                     GTK_TYPE_NONE, 1,
150                     GTK_TYPE_INT);
151   toolbar_signals[STYLE_CHANGED] =
152     gtk_signal_new ("style_changed",
153                     GTK_RUN_FIRST,
154                     object_class->type,
155                     GTK_SIGNAL_OFFSET (GtkToolbarClass, style_changed),
156                     gtk_marshal_NONE__INT,
157                     GTK_TYPE_NONE, 1,
158                     GTK_TYPE_INT);
159
160   gtk_object_class_add_signals (object_class, toolbar_signals, LAST_SIGNAL);
161
162   object_class->destroy = gtk_toolbar_destroy;
163   object_class->set_arg = gtk_toolbar_set_arg;
164   object_class->get_arg = gtk_toolbar_get_arg;
165
166   widget_class->map = gtk_toolbar_map;
167   widget_class->unmap = gtk_toolbar_unmap;
168   widget_class->draw = gtk_toolbar_draw;
169   widget_class->expose_event = gtk_toolbar_expose;
170   widget_class->size_request = gtk_toolbar_size_request;
171   widget_class->size_allocate = gtk_toolbar_size_allocate;
172
173   container_class->add = gtk_toolbar_add;
174   container_class->remove = gtk_toolbar_remove;
175   container_class->forall = gtk_toolbar_forall;
176   container_class->focus = NULL;
177   
178   class->orientation_changed = gtk_real_toolbar_orientation_changed;
179   class->style_changed = gtk_real_toolbar_style_changed;
180   
181   gtk_object_add_arg_type ("GtkToolbar::orientation", GTK_TYPE_ORIENTATION,
182                            GTK_ARG_READWRITE, ARG_ORIENTATION);
183   gtk_object_add_arg_type ("GtkToolbar::toolbar_style", GTK_TYPE_TOOLBAR_STYLE,
184                            GTK_ARG_READWRITE, ARG_TOOLBAR_STYLE);
185   gtk_object_add_arg_type ("GtkToolbar::space_size", GTK_TYPE_UINT,
186                            GTK_ARG_READWRITE, ARG_SPACE_SIZE);
187   gtk_object_add_arg_type ("GtkToolbar::space_style", GTK_TYPE_TOOLBAR_SPACE_STYLE,
188                            GTK_ARG_READWRITE, ARG_SPACE_STYLE);
189   gtk_object_add_arg_type ("GtkToolbar::relief", GTK_TYPE_RELIEF_STYLE,
190                            GTK_ARG_READWRITE, ARG_RELIEF);
191 }
192
193 static void
194 gtk_toolbar_init (GtkToolbar *toolbar)
195 {
196   GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
197   GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS);
198
199   toolbar->num_children = 0;
200   toolbar->children     = NULL;
201   toolbar->orientation  = GTK_ORIENTATION_HORIZONTAL;
202   toolbar->style        = GTK_TOOLBAR_ICONS;
203   toolbar->relief       = GTK_RELIEF_NORMAL;
204   toolbar->space_size   = DEFAULT_SPACE_SIZE;
205   toolbar->space_style  = DEFAULT_SPACE_STYLE;
206   toolbar->tooltips     = gtk_tooltips_new ();
207   toolbar->button_maxw  = 0;
208   toolbar->button_maxh  = 0;
209 }
210
211 static void
212 gtk_toolbar_set_arg (GtkObject *object,
213                      GtkArg    *arg,
214                      guint      arg_id)
215 {
216   GtkToolbar *toolbar = GTK_TOOLBAR (object);
217   
218   switch (arg_id)
219     {
220     case ARG_ORIENTATION:
221       gtk_toolbar_set_orientation (toolbar, GTK_VALUE_ENUM (*arg));
222       break;
223     case ARG_TOOLBAR_STYLE:
224       gtk_toolbar_set_style (toolbar, GTK_VALUE_ENUM (*arg));
225       break;
226     case ARG_SPACE_SIZE:
227       gtk_toolbar_set_space_size (toolbar, GTK_VALUE_UINT (*arg));
228       break;
229     case ARG_SPACE_STYLE:
230       gtk_toolbar_set_space_style (toolbar, GTK_VALUE_ENUM (*arg));
231       break;      
232     case ARG_RELIEF:
233       gtk_toolbar_set_button_relief (toolbar, GTK_VALUE_ENUM (*arg));
234       break;
235     }
236 }
237
238 static void
239 gtk_toolbar_get_arg (GtkObject *object,
240                      GtkArg    *arg,
241                      guint      arg_id)
242 {
243   GtkToolbar *toolbar = GTK_TOOLBAR (object);
244
245   switch (arg_id)
246     {
247     case ARG_ORIENTATION:
248       GTK_VALUE_ENUM (*arg) = toolbar->orientation;
249       break;
250     case ARG_TOOLBAR_STYLE:
251       GTK_VALUE_ENUM (*arg) = toolbar->style;
252       break;
253     case ARG_SPACE_SIZE:
254       GTK_VALUE_UINT (*arg) = toolbar->space_size;
255       break;            
256     case ARG_SPACE_STYLE:
257       GTK_VALUE_ENUM (*arg) = toolbar->space_style;
258       break;
259     case ARG_RELIEF:
260       GTK_VALUE_ENUM (*arg) = toolbar->relief;
261       break;    
262     default:
263       arg->type = GTK_TYPE_INVALID;
264       break;
265     }
266 }
267
268 GtkWidget*
269 gtk_toolbar_new (GtkOrientation  orientation,
270                  GtkToolbarStyle style)
271 {
272   GtkToolbar *toolbar;
273
274   toolbar = gtk_type_new (gtk_toolbar_get_type ());
275
276   toolbar->orientation = orientation;
277   toolbar->style = style;
278
279   return GTK_WIDGET (toolbar);
280 }
281
282 static void
283 gtk_toolbar_destroy (GtkObject *object)
284 {
285   GtkToolbar *toolbar;
286   GList *children;
287
288   g_return_if_fail (object != NULL);
289   g_return_if_fail (GTK_IS_TOOLBAR (object));
290
291   toolbar = GTK_TOOLBAR (object);
292
293   gtk_object_unref (GTK_OBJECT (toolbar->tooltips));
294   toolbar->tooltips = NULL;
295
296   for (children = toolbar->children; children; children = children->next)
297     {
298       GtkToolbarChild *child;
299
300       child = children->data;
301
302       if (child->type != GTK_TOOLBAR_CHILD_SPACE)
303         {
304           gtk_widget_ref (child->widget);
305           gtk_widget_unparent (child->widget);
306           gtk_widget_destroy (child->widget);
307           gtk_widget_unref (child->widget);
308         }
309
310       g_free (child);
311     }
312
313   g_list_free (toolbar->children);
314   toolbar->children = NULL;
315   
316   if (GTK_OBJECT_CLASS (parent_class)->destroy)
317     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
318 }
319
320 static void
321 gtk_toolbar_map (GtkWidget *widget)
322 {
323   GtkToolbar *toolbar;
324   GList *children;
325   GtkToolbarChild *child;
326
327   g_return_if_fail (widget != NULL);
328   g_return_if_fail (GTK_IS_TOOLBAR (widget));
329
330   toolbar = GTK_TOOLBAR (widget);
331   GTK_WIDGET_SET_FLAGS (toolbar, GTK_MAPPED);
332
333   for (children = toolbar->children; children; children = children->next)
334     {
335       child = children->data;
336
337       if ((child->type != GTK_TOOLBAR_CHILD_SPACE)
338           && GTK_WIDGET_VISIBLE (child->widget) && !GTK_WIDGET_MAPPED (child->widget))
339         gtk_widget_map (child->widget);
340     }
341 }
342
343 static void
344 gtk_toolbar_unmap (GtkWidget *widget)
345 {
346   GtkToolbar *toolbar;
347   GList *children;
348   GtkToolbarChild *child;
349
350   g_return_if_fail (widget != NULL);
351   g_return_if_fail (GTK_IS_TOOLBAR (widget));
352
353   toolbar = GTK_TOOLBAR (widget);
354   GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_MAPPED);
355
356   for (children = toolbar->children; children; children = children->next)
357     {
358       child = children->data;
359
360       if ((child->type != GTK_TOOLBAR_CHILD_SPACE)
361           && GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_MAPPED (child->widget))
362         gtk_widget_unmap (child->widget);
363     }
364 }
365
366 static void
367 gtk_toolbar_paint_space_line (GtkWidget       *widget,
368                               GdkRectangle    *area,
369                               GtkToolbarChild *child)
370 {
371   GtkToolbar *toolbar;
372   GtkToolbarChildSpace *child_space;
373
374   g_return_if_fail (widget != NULL);
375   g_return_if_fail (GTK_IS_TOOLBAR (widget));
376   g_return_if_fail (child != NULL);
377   g_return_if_fail (child->type == GTK_TOOLBAR_CHILD_SPACE);
378
379   toolbar = GTK_TOOLBAR (widget);
380
381   child_space = (GtkToolbarChildSpace *) child;
382
383   if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
384     gtk_paint_vline (widget->style, widget->window,
385                      GTK_WIDGET_STATE (widget), area, widget,
386                      "toolbar",
387                      child_space->alloc_y + toolbar->button_maxh *
388                      SPACE_LINE_START / SPACE_LINE_DIVISION,
389                      child_space->alloc_y + toolbar->button_maxh *
390                      SPACE_LINE_END / SPACE_LINE_DIVISION,
391                      child_space->alloc_x +
392                      (toolbar->space_size -
393                       widget->style->klass->xthickness) / 2);
394   else
395     gtk_paint_hline (widget->style, widget->window,
396                      GTK_WIDGET_STATE (widget), area, widget,
397                      "toolbar",
398                      child_space->alloc_x + toolbar->button_maxw *
399                      SPACE_LINE_START / SPACE_LINE_DIVISION,
400                      child_space->alloc_x + toolbar->button_maxw *
401                      SPACE_LINE_END / SPACE_LINE_DIVISION,
402                      child_space->alloc_y +
403                      (toolbar->space_size -
404                       widget->style->klass->ythickness) / 2);
405 }
406
407 static void
408 gtk_toolbar_draw (GtkWidget    *widget,
409                   GdkRectangle *area)
410 {
411   GtkToolbar *toolbar;
412   GList *children;
413   GtkToolbarChild *child;
414   GdkRectangle child_area;
415
416   g_return_if_fail (widget != NULL);
417   g_return_if_fail (GTK_IS_TOOLBAR (widget));
418
419   if (GTK_WIDGET_DRAWABLE (widget))
420     {
421       toolbar = GTK_TOOLBAR (widget);
422
423       for (children = toolbar->children; children; children = children->next)
424         {
425           child = children->data;
426
427           if (child->type == GTK_TOOLBAR_CHILD_SPACE)
428             {
429               if (toolbar->space_style == GTK_TOOLBAR_SPACE_LINE)
430                 gtk_toolbar_paint_space_line (widget, area, child);
431             }
432           else if (gtk_widget_intersect (child->widget, area, &child_area))
433             gtk_widget_draw (child->widget, &child_area);
434         }
435     }
436 }
437
438 static gint
439 gtk_toolbar_expose (GtkWidget      *widget,
440                     GdkEventExpose *event)
441 {
442   GtkToolbar *toolbar;
443   GList *children;
444   GtkToolbarChild *child;
445   GdkEventExpose child_event;
446
447   g_return_val_if_fail (widget != NULL, FALSE);
448   g_return_val_if_fail (GTK_IS_TOOLBAR (widget), FALSE);
449   g_return_val_if_fail (event != NULL, FALSE);
450
451   if (GTK_WIDGET_DRAWABLE (widget))
452     {
453       toolbar = GTK_TOOLBAR (widget);
454
455       child_event = *event;
456
457       for (children = toolbar->children; children; children = children->next)
458         {
459           child = children->data;
460
461           if (child->type == GTK_TOOLBAR_CHILD_SPACE)
462             {
463               if (toolbar->space_style == GTK_TOOLBAR_SPACE_LINE)
464                 gtk_toolbar_paint_space_line (widget, &event->area, child);
465             }
466           else if (GTK_WIDGET_NO_WINDOW (child->widget)
467                    && gtk_widget_intersect (child->widget, &event->area, &child_event.area))
468             gtk_widget_event (child->widget, (GdkEvent *) &child_event);
469         }
470     }
471
472   return FALSE;
473 }
474
475 static void
476 gtk_toolbar_size_request (GtkWidget      *widget,
477                           GtkRequisition *requisition)
478 {
479   GtkToolbar *toolbar;
480   GList *children;
481   GtkToolbarChild *child;
482   gint nbuttons;
483   gint button_maxw, button_maxh;
484   gint widget_maxw, widget_maxh;
485   GtkRequisition child_requisition;
486
487   g_return_if_fail (widget != NULL);
488   g_return_if_fail (GTK_IS_TOOLBAR (widget));
489   g_return_if_fail (requisition != NULL);
490
491   toolbar = GTK_TOOLBAR (widget);
492
493   requisition->width = GTK_CONTAINER (toolbar)->border_width * 2;
494   requisition->height = GTK_CONTAINER (toolbar)->border_width * 2;
495   nbuttons = 0;
496   button_maxw = 0;
497   button_maxh = 0;
498   widget_maxw = 0;
499   widget_maxh = 0;
500
501   for (children = toolbar->children; children; children = children->next)
502     {
503       child = children->data;
504
505       switch (child->type)
506         {
507         case GTK_TOOLBAR_CHILD_SPACE:
508           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
509             requisition->width += toolbar->space_size;
510           else
511             requisition->height += toolbar->space_size;
512
513           break;
514
515         case GTK_TOOLBAR_CHILD_BUTTON:
516         case GTK_TOOLBAR_CHILD_RADIOBUTTON:
517         case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
518           if (GTK_WIDGET_VISIBLE (child->widget))
519             {
520               gtk_widget_size_request (child->widget, &child_requisition);
521
522               nbuttons++;
523               button_maxw = MAX (button_maxw, child_requisition.width);
524               button_maxh = MAX (button_maxh, child_requisition.height);
525             }
526
527           break;
528
529         case GTK_TOOLBAR_CHILD_WIDGET:
530           if (GTK_WIDGET_VISIBLE (child->widget))
531             {
532               gtk_widget_size_request (child->widget, &child_requisition);
533
534               widget_maxw = MAX (widget_maxw, child_requisition.width);
535               widget_maxh = MAX (widget_maxh, child_requisition.height);
536
537               if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
538                 requisition->width += child_requisition.width;
539               else
540                 requisition->height += child_requisition.height;
541             }
542
543           break;
544
545         default:
546           g_assert_not_reached ();
547         }
548     }
549
550   if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
551     {
552       requisition->width += nbuttons * button_maxw;
553       requisition->height += MAX (button_maxh, widget_maxh);
554     }
555   else
556     {
557       requisition->width += MAX (button_maxw, widget_maxw);
558       requisition->height += nbuttons * button_maxh;
559     }
560
561   toolbar->button_maxw = button_maxw;
562   toolbar->button_maxh = button_maxh;
563 }
564
565 static void
566 gtk_toolbar_size_allocate (GtkWidget     *widget,
567                            GtkAllocation *allocation)
568 {
569   GtkToolbar *toolbar;
570   GList *children;
571   GtkToolbarChild *child;
572   GtkToolbarChildSpace *child_space;
573   GtkAllocation alloc;
574   GtkRequisition child_requisition;
575   gint border_width;
576
577   g_return_if_fail (widget != NULL);
578   g_return_if_fail (GTK_IS_TOOLBAR (widget));
579   g_return_if_fail (allocation != NULL);
580
581   toolbar = GTK_TOOLBAR (widget);
582   widget->allocation = *allocation;
583
584   border_width = GTK_CONTAINER (toolbar)->border_width;
585
586   if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
587     alloc.x = allocation->x + border_width;
588   else
589     alloc.y = allocation->y + border_width;
590
591   for (children = toolbar->children; children; children = children->next)
592     {
593       child = children->data;
594
595       switch (child->type)
596         {
597         case GTK_TOOLBAR_CHILD_SPACE:
598
599           child_space = (GtkToolbarChildSpace *) child;
600
601           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
602             {
603               child_space->alloc_x = alloc.x;
604               child_space->alloc_y = allocation->y + (allocation->height - toolbar->button_maxh) / 2;
605               alloc.x += toolbar->space_size;
606             }
607           else
608             {
609               child_space->alloc_x = allocation->x + (allocation->width - toolbar->button_maxw) / 2;
610               child_space->alloc_y = alloc.y;
611               alloc.y += toolbar->space_size;
612             }
613
614           break;
615
616         case GTK_TOOLBAR_CHILD_BUTTON:
617         case GTK_TOOLBAR_CHILD_RADIOBUTTON:
618         case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
619           if (!GTK_WIDGET_VISIBLE (child->widget))
620             break;
621
622           alloc.width = toolbar->button_maxw;
623           alloc.height = toolbar->button_maxh;
624
625           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
626             alloc.y = allocation->y + (allocation->height - toolbar->button_maxh) / 2;
627           else
628             alloc.x = allocation->x + (allocation->width - toolbar->button_maxw) / 2;
629
630           gtk_widget_size_allocate (child->widget, &alloc);
631
632           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
633             alloc.x += toolbar->button_maxw;
634           else
635             alloc.y += toolbar->button_maxh;
636
637           break;
638
639         case GTK_TOOLBAR_CHILD_WIDGET:
640           if (!GTK_WIDGET_VISIBLE (child->widget))
641             break;
642
643           gtk_widget_get_child_requisition (child->widget, &child_requisition);
644           
645           alloc.width = child_requisition.width;
646           alloc.height = child_requisition.height;
647
648           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
649             alloc.y = allocation->y + (allocation->height - child_requisition.height) / 2;
650           else
651             alloc.x = allocation->x + (allocation->width - child_requisition.width) / 2;
652
653           gtk_widget_size_allocate (child->widget, &alloc);
654
655           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
656             alloc.x += child_requisition.width;
657           else
658             alloc.y += child_requisition.height;
659
660           break;
661
662         default:
663           g_assert_not_reached ();
664         }
665     }
666 }
667
668 static void
669 gtk_toolbar_add (GtkContainer *container,
670                  GtkWidget    *widget)
671 {
672   g_return_if_fail (container != NULL);
673   g_return_if_fail (GTK_IS_TOOLBAR (container));
674   g_return_if_fail (widget != NULL);
675
676   gtk_toolbar_append_widget (GTK_TOOLBAR (container), widget, NULL, NULL);
677 }
678
679 static void
680 gtk_toolbar_remove (GtkContainer *container,
681                     GtkWidget    *widget)
682 {
683   GtkToolbar *toolbar;
684   GList *children;
685   GtkToolbarChild *child;
686
687   g_return_if_fail (container != NULL);
688   g_return_if_fail (GTK_IS_TOOLBAR (container));
689   g_return_if_fail (widget != NULL);
690
691   toolbar = GTK_TOOLBAR (container);
692
693   for (children = toolbar->children; children; children = children->next)
694     {
695       child = children->data;
696
697       if ((child->type != GTK_TOOLBAR_CHILD_SPACE) && (child->widget == widget))
698         {
699           gboolean was_visible;
700
701           was_visible = GTK_WIDGET_VISIBLE (widget);
702           gtk_widget_unparent (widget);
703
704           toolbar->children = g_list_remove_link (toolbar->children, children);
705           g_free (child);
706           g_list_free (children);
707           toolbar->num_children--;
708
709           if (was_visible && GTK_WIDGET_VISIBLE (container))
710             gtk_widget_queue_resize (GTK_WIDGET (container));
711
712           break;
713         }
714     }
715 }
716
717 static void
718 gtk_toolbar_forall (GtkContainer *container,
719                     gboolean      include_internals,
720                     GtkCallback   callback,
721                     gpointer      callback_data)
722 {
723   GtkToolbar *toolbar;
724   GList *children;
725   GtkToolbarChild *child;
726
727   g_return_if_fail (container != NULL);
728   g_return_if_fail (GTK_IS_TOOLBAR (container));
729   g_return_if_fail (callback != NULL);
730
731   toolbar = GTK_TOOLBAR (container);
732
733   for (children = toolbar->children; children; children = children->next)
734     {
735       child = children->data;
736
737       if (child->type != GTK_TOOLBAR_CHILD_SPACE)
738         (*callback) (child->widget, callback_data);
739     }
740 }
741
742 GtkWidget *
743 gtk_toolbar_append_item (GtkToolbar    *toolbar,
744                          const char    *text,
745                          const char    *tooltip_text,
746                          const char    *tooltip_private_text,
747                          GtkWidget     *icon,
748                          GtkSignalFunc  callback,
749                          gpointer       user_data)
750 {
751   return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
752                                      NULL, text,
753                                      tooltip_text, tooltip_private_text,
754                                      icon, callback, user_data,
755                                      toolbar->num_children);
756 }
757
758 GtkWidget *
759 gtk_toolbar_prepend_item (GtkToolbar    *toolbar,
760                           const char    *text,
761                           const char    *tooltip_text,
762                           const char    *tooltip_private_text,
763                           GtkWidget     *icon,
764                           GtkSignalFunc  callback,
765                           gpointer       user_data)
766 {
767   return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
768                                      NULL, text,
769                                      tooltip_text, tooltip_private_text,
770                                      icon, callback, user_data,
771                                      0);
772 }
773
774 GtkWidget *
775 gtk_toolbar_insert_item (GtkToolbar    *toolbar,
776                          const char    *text,
777                          const char    *tooltip_text,
778                          const char    *tooltip_private_text,
779                          GtkWidget     *icon,
780                          GtkSignalFunc  callback,
781                          gpointer       user_data,
782                          gint           position)
783 {
784   return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
785                                      NULL, text,
786                                      tooltip_text, tooltip_private_text,
787                                      icon, callback, user_data,
788                                      position);
789 }
790
791 void
792 gtk_toolbar_append_space (GtkToolbar *toolbar)
793 {
794   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
795                               NULL, NULL,
796                               NULL, NULL,
797                               NULL, NULL, NULL,
798                               toolbar->num_children);
799 }
800
801 void
802 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
803 {
804   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
805                               NULL, NULL,
806                               NULL, NULL,
807                               NULL, NULL, NULL,
808                               0);
809 }
810
811 void
812 gtk_toolbar_insert_space (GtkToolbar *toolbar,
813                           gint        position)
814 {
815   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
816                               NULL, NULL,
817                               NULL, NULL,
818                               NULL, NULL, NULL,
819                               position);
820 }
821
822 void
823 gtk_toolbar_append_widget (GtkToolbar  *toolbar,
824                            GtkWidget   *widget,
825                            const gchar *tooltip_text,
826                            const gchar *tooltip_private_text)
827 {
828   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
829                               widget, NULL,
830                               tooltip_text, tooltip_private_text,
831                               NULL, NULL, NULL,
832                               toolbar->num_children);
833 }
834
835 void
836 gtk_toolbar_prepend_widget (GtkToolbar  *toolbar,
837                             GtkWidget   *widget,
838                             const gchar *tooltip_text,
839                             const gchar *tooltip_private_text)
840 {
841   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
842                               widget, NULL,
843                               tooltip_text, tooltip_private_text,
844                               NULL, NULL, NULL,
845                               toolbar->num_children);
846 }
847
848 void
849 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
850                            GtkWidget  *widget,
851                            const char *tooltip_text,
852                            const char *tooltip_private_text,
853                            gint        position)
854 {
855   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
856                               widget, NULL,
857                               tooltip_text, tooltip_private_text,
858                               NULL, NULL, NULL,
859                               position);
860 }
861
862 GtkWidget *
863 gtk_toolbar_append_element (GtkToolbar          *toolbar,
864                             GtkToolbarChildType  type,
865                             GtkWidget           *widget,
866                             const char          *text,
867                             const char          *tooltip_text,
868                             const char          *tooltip_private_text,
869                             GtkWidget           *icon,
870                             GtkSignalFunc        callback,
871                             gpointer             user_data)
872 {
873   return gtk_toolbar_insert_element (toolbar, type, widget, text,
874                                      tooltip_text, tooltip_private_text,
875                                      icon, callback, user_data,
876                                      toolbar->num_children);
877 }
878
879 GtkWidget *
880 gtk_toolbar_prepend_element (GtkToolbar          *toolbar,
881                              GtkToolbarChildType  type,
882                              GtkWidget           *widget,
883                              const char          *text,
884                              const char          *tooltip_text,
885                              const char          *tooltip_private_text,
886                              GtkWidget           *icon,
887                              GtkSignalFunc        callback,
888                              gpointer             user_data)
889 {
890   return gtk_toolbar_insert_element (toolbar, type, widget, text,
891                                      tooltip_text, tooltip_private_text,
892                                      icon, callback, user_data, 0);
893 }
894
895 GtkWidget *
896 gtk_toolbar_insert_element (GtkToolbar          *toolbar,
897                             GtkToolbarChildType  type,
898                             GtkWidget           *widget,
899                             const char          *text,
900                             const char          *tooltip_text,
901                             const char          *tooltip_private_text,
902                             GtkWidget           *icon,
903                             GtkSignalFunc        callback,
904                             gpointer             user_data,
905                             gint                 position)
906 {
907   GtkToolbarChild *child;
908   GtkWidget *box;
909
910   g_return_val_if_fail (toolbar != NULL, NULL);
911   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
912   if (type == GTK_TOOLBAR_CHILD_WIDGET)
913     {
914       g_return_val_if_fail (widget != NULL, NULL);
915       g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
916     }
917   else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON)
918     g_return_val_if_fail (widget == NULL, NULL);
919
920   if (type == GTK_TOOLBAR_CHILD_SPACE)
921     child = (GtkToolbarChild *) g_new (GtkToolbarChildSpace, 1);
922   else
923     child = g_new (GtkToolbarChild, 1);
924
925   child->type = type;
926   child->icon = NULL;
927   child->label = NULL;
928
929   switch (type)
930     {
931     case GTK_TOOLBAR_CHILD_SPACE:
932       child->widget = NULL;
933       ((GtkToolbarChildSpace *) child)->alloc_x =
934         ((GtkToolbarChildSpace *) child)->alloc_y = 0;
935       break;
936
937     case GTK_TOOLBAR_CHILD_WIDGET:
938       child->widget = widget;
939       break;
940
941     case GTK_TOOLBAR_CHILD_BUTTON:
942     case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
943     case GTK_TOOLBAR_CHILD_RADIOBUTTON:
944       if (type == GTK_TOOLBAR_CHILD_BUTTON)
945         {
946           child->widget = gtk_button_new ();
947           gtk_button_set_relief (GTK_BUTTON (child->widget), toolbar->relief);
948         }
949       else if (type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
950         {
951           child->widget = gtk_toggle_button_new ();
952           gtk_button_set_relief (GTK_BUTTON (child->widget), toolbar->relief);
953           gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child->widget),
954                                       FALSE);
955         }
956       else
957         {
958           child->widget = gtk_radio_button_new (widget
959                                                 ? gtk_radio_button_group (GTK_RADIO_BUTTON (widget))
960                                                 : NULL);
961           gtk_button_set_relief (GTK_BUTTON (child->widget), toolbar->relief);
962           gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child->widget), FALSE);
963         }
964
965       GTK_WIDGET_UNSET_FLAGS (child->widget, GTK_CAN_FOCUS);
966
967       if (callback)
968         gtk_signal_connect (GTK_OBJECT (child->widget), "clicked",
969                             callback, user_data);
970
971       if (toolbar->style == GTK_TOOLBAR_BOTH_HORIZ)
972           box = gtk_hbox_new (FALSE, 0);
973       else
974           box = gtk_vbox_new (FALSE, 0);
975       gtk_container_add (GTK_CONTAINER (child->widget), box);
976       gtk_widget_show (box);
977
978       if (text)
979         {
980           child->label = gtk_label_new (text);
981           gtk_box_pack_end (GTK_BOX (box), child->label, FALSE, FALSE, 0);
982           if (toolbar->style != GTK_TOOLBAR_ICONS)
983             gtk_widget_show (child->label);
984         }
985
986       if (icon)
987         {
988           child->icon = GTK_WIDGET (icon);
989           gtk_box_pack_end (GTK_BOX (box), child->icon, FALSE, FALSE, 0);
990           if (toolbar->style != GTK_TOOLBAR_TEXT)
991             gtk_widget_show (child->icon);
992         }
993
994       gtk_widget_show (child->widget);
995       break;
996
997     default:
998       g_assert_not_reached ();
999     }
1000
1001   if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text)
1002     gtk_tooltips_set_tip (toolbar->tooltips, child->widget,
1003                           tooltip_text, tooltip_private_text);
1004
1005   toolbar->children = g_list_insert (toolbar->children, child, position);
1006   toolbar->num_children++;
1007
1008   if (type != GTK_TOOLBAR_CHILD_SPACE)
1009     {
1010       gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
1011
1012       if (GTK_WIDGET_REALIZED (child->widget->parent))
1013         gtk_widget_realize (child->widget);
1014
1015       if (GTK_WIDGET_VISIBLE (child->widget->parent) && GTK_WIDGET_VISIBLE (child->widget))
1016         {
1017           if (GTK_WIDGET_MAPPED (child->widget->parent))
1018             gtk_widget_map (child->widget);
1019
1020           gtk_widget_queue_resize (child->widget);
1021         }
1022     }
1023   else
1024     gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1025
1026   return child->widget;
1027 }
1028
1029 void
1030 gtk_toolbar_set_orientation (GtkToolbar     *toolbar,
1031                              GtkOrientation  orientation)
1032 {
1033   g_return_if_fail (toolbar != NULL);
1034   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1035
1036   gtk_signal_emit (GTK_OBJECT (toolbar), toolbar_signals[ORIENTATION_CHANGED], orientation);
1037 }
1038
1039 void
1040 gtk_toolbar_set_style (GtkToolbar      *toolbar,
1041                        GtkToolbarStyle  style)
1042 {
1043   g_return_if_fail (toolbar != NULL);
1044   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1045
1046   gtk_signal_emit (GTK_OBJECT (toolbar), toolbar_signals[STYLE_CHANGED], style);
1047 }
1048
1049 void
1050 gtk_toolbar_set_space_size (GtkToolbar *toolbar,
1051                             gint        space_size)
1052 {
1053   g_return_if_fail (toolbar != NULL);
1054   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1055
1056   if (toolbar->space_size != space_size)
1057     {
1058       toolbar->space_size = space_size;
1059       gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1060     }
1061 }
1062
1063 void
1064 gtk_toolbar_set_space_style (GtkToolbar           *toolbar,
1065                              GtkToolbarSpaceStyle  space_style)
1066 {
1067   g_return_if_fail (toolbar != NULL);
1068   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1069
1070   if (toolbar->space_style != space_style)
1071     {
1072       toolbar->space_style = space_style;
1073       gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1074     }
1075 }
1076
1077 void
1078 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
1079                           gint        enable)
1080 {
1081   g_return_if_fail (toolbar != NULL);
1082   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1083
1084   if (enable)
1085     gtk_tooltips_enable (toolbar->tooltips);
1086   else
1087     gtk_tooltips_disable (toolbar->tooltips);
1088 }
1089
1090 void
1091 gtk_toolbar_set_button_relief (GtkToolbar *toolbar,
1092                                GtkReliefStyle relief)
1093 {
1094   GList *children;
1095   GtkToolbarChild *child;
1096   
1097   g_return_if_fail (toolbar != NULL);
1098   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1099
1100   if (toolbar->relief != relief)
1101     {
1102       toolbar->relief = relief;
1103       
1104       for (children = toolbar->children; children; children = children->next)
1105         {
1106           child = children->data;
1107           if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
1108               child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
1109               child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
1110             gtk_button_set_relief (GTK_BUTTON (child->widget), relief);
1111         }
1112       
1113       gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1114     }
1115 }
1116
1117 GtkReliefStyle
1118 gtk_toolbar_get_button_relief (GtkToolbar *toolbar)
1119 {
1120   g_return_val_if_fail (toolbar != NULL, GTK_RELIEF_NORMAL);
1121   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_RELIEF_NORMAL);
1122
1123   return toolbar->relief;
1124 }
1125
1126 static void
1127 gtk_real_toolbar_orientation_changed (GtkToolbar     *toolbar,
1128                                       GtkOrientation  orientation)
1129 {
1130   g_return_if_fail (toolbar != NULL);
1131   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1132
1133   if (toolbar->orientation != orientation)
1134     {
1135       toolbar->orientation = orientation;
1136       gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1137     }
1138 }
1139
1140 static void
1141 gtk_real_toolbar_style_changed (GtkToolbar      *toolbar,
1142                                 GtkToolbarStyle  style)
1143 {
1144   GList *children;
1145   GtkToolbarChild *child;
1146   GtkWidget* box = NULL;
1147
1148   g_return_if_fail (toolbar != NULL);
1149   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1150
1151   if (toolbar->style != style)
1152     {
1153       toolbar->style = style;
1154
1155       for (children = toolbar->children; children; children = children->next)
1156         {
1157           child = children->data;
1158
1159           if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
1160               child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
1161               child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
1162             switch (style)
1163               {
1164               case GTK_TOOLBAR_ICONS:
1165                 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
1166                   gtk_widget_show (child->icon);
1167
1168                 if (child->label && GTK_WIDGET_VISIBLE (child->label))
1169                   gtk_widget_hide (child->label);
1170
1171                 break;
1172
1173               case GTK_TOOLBAR_TEXT:
1174                 if (child->icon && GTK_WIDGET_VISIBLE (child->icon))
1175                   gtk_widget_hide (child->icon);
1176                 
1177                 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
1178                   gtk_widget_show (child->label);
1179
1180                 break;
1181
1182               case GTK_TOOLBAR_BOTH:
1183                 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
1184                   gtk_widget_show (child->icon);
1185
1186                 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
1187                   gtk_widget_show (child->label);
1188
1189                 box = (GtkWidget*)gtk_container_children (GTK_CONTAINER (child->widget))->data;
1190
1191                 if (GTK_IS_HBOX (box))
1192                 {
1193                     if (child->icon)
1194                     {
1195                         gtk_object_ref (GTK_OBJECT (child->icon));
1196                         gtk_container_remove (GTK_CONTAINER (box),
1197                                               child->icon);
1198                     }
1199                     if (child->label)
1200                     {
1201                         gtk_object_ref (GTK_OBJECT (child->label));
1202                         gtk_container_remove (GTK_CONTAINER (box),
1203                                               child->label);
1204                     }
1205                     gtk_container_remove (GTK_CONTAINER (child->widget),
1206                                           box);
1207                     
1208                     box = gtk_vbox_new (FALSE, 0);
1209                     gtk_widget_show (box);
1210                     
1211                     if (child->label)
1212                     {
1213                         gtk_box_pack_end (GTK_BOX (box), child->label, FALSE, FALSE, 0);
1214                         gtk_object_unref (GTK_OBJECT (child->label));
1215                     }
1216                     if (child->icon)
1217                     {
1218                         gtk_box_pack_end (GTK_BOX (box), child->icon, FALSE, FALSE, 0);
1219                         gtk_object_unref (GTK_OBJECT (child->icon));
1220                     }
1221                     gtk_container_add (GTK_CONTAINER (child->widget),
1222                                        box);
1223                 }
1224                 
1225                 break;
1226                 
1227               case GTK_TOOLBAR_BOTH_HORIZ:
1228                 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
1229                   gtk_widget_show (child->icon);
1230                 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
1231                   gtk_widget_show (child->label);
1232
1233                 box = (GtkWidget*)gtk_container_children (GTK_CONTAINER (child->widget))->data;
1234                 
1235                 if (GTK_IS_VBOX (box))
1236                 {
1237                     if (child->icon)
1238                     {
1239                         gtk_object_ref (GTK_OBJECT (child->icon));
1240                         gtk_container_remove (GTK_CONTAINER (box),
1241                                               child->icon);
1242                     }
1243                     if (child->label)
1244                     {
1245                         gtk_object_ref (GTK_OBJECT (child->label));
1246                         gtk_container_remove (GTK_CONTAINER (box),
1247                                               child->label);
1248                     }
1249                     gtk_container_remove (GTK_CONTAINER (child->widget),
1250                                           box);
1251
1252                     box = gtk_hbox_new (FALSE, 0);
1253                     gtk_widget_show (box);
1254                     
1255                     if (child->label)
1256                     {
1257                         gtk_box_pack_end (GTK_BOX (box), child->label, TRUE, TRUE, 0);
1258                         gtk_object_unref (GTK_OBJECT (child->label));
1259                     }
1260                     if (child->icon)
1261                     {
1262                         gtk_box_pack_end (GTK_BOX (box), child->icon, FALSE, FALSE, 0);
1263                         gtk_object_unref (GTK_OBJECT (child->icon));
1264                     }
1265                     gtk_container_add (GTK_CONTAINER (child->widget), box);
1266                     
1267                 }
1268                 
1269                 break;
1270
1271               default:
1272                 g_assert_not_reached ();
1273               }
1274         }
1275                 
1276       gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1277     }
1278 }