]> Pileus Git - ~andy/gtk/blob - gtk/gtktoolbar.c
Make this compile without framebuffer enabled
[~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                     GTK_CLASS_TYPE (object_class),
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                     GTK_CLASS_TYPE (object_class),
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   if (toolbar->tooltips)
294     {
295       gtk_object_unref (GTK_OBJECT (toolbar->tooltips));
296       toolbar->tooltips = NULL;
297     }
298
299   for (children = toolbar->children; children; children = children->next)
300     {
301       GtkToolbarChild *child;
302
303       child = children->data;
304
305       if (child->type != GTK_TOOLBAR_CHILD_SPACE)
306         {
307           gtk_widget_ref (child->widget);
308           gtk_widget_unparent (child->widget);
309           gtk_widget_destroy (child->widget);
310           gtk_widget_unref (child->widget);
311         }
312
313       g_free (child);
314     }
315   g_list_free (toolbar->children);
316   toolbar->children = NULL;
317   
318   GTK_OBJECT_CLASS (parent_class)->destroy (object);
319 }
320
321 static void
322 gtk_toolbar_map (GtkWidget *widget)
323 {
324   GtkToolbar *toolbar;
325   GList *children;
326   GtkToolbarChild *child;
327
328   g_return_if_fail (widget != NULL);
329   g_return_if_fail (GTK_IS_TOOLBAR (widget));
330
331   toolbar = GTK_TOOLBAR (widget);
332   GTK_WIDGET_SET_FLAGS (toolbar, GTK_MAPPED);
333
334   for (children = toolbar->children; children; children = children->next)
335     {
336       child = children->data;
337
338       if ((child->type != GTK_TOOLBAR_CHILD_SPACE)
339           && GTK_WIDGET_VISIBLE (child->widget) && !GTK_WIDGET_MAPPED (child->widget))
340         gtk_widget_map (child->widget);
341     }
342 }
343
344 static void
345 gtk_toolbar_unmap (GtkWidget *widget)
346 {
347   GtkToolbar *toolbar;
348   GList *children;
349   GtkToolbarChild *child;
350
351   g_return_if_fail (widget != NULL);
352   g_return_if_fail (GTK_IS_TOOLBAR (widget));
353
354   toolbar = GTK_TOOLBAR (widget);
355   GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_MAPPED);
356
357   for (children = toolbar->children; children; children = children->next)
358     {
359       child = children->data;
360
361       if ((child->type != GTK_TOOLBAR_CHILD_SPACE)
362           && GTK_WIDGET_VISIBLE (child->widget) && GTK_WIDGET_MAPPED (child->widget))
363         gtk_widget_unmap (child->widget);
364     }
365 }
366
367 static void
368 gtk_toolbar_paint_space_line (GtkWidget       *widget,
369                               GdkRectangle    *area,
370                               GtkToolbarChild *child)
371 {
372   GtkToolbar *toolbar;
373   GtkToolbarChildSpace *child_space;
374
375   g_return_if_fail (widget != NULL);
376   g_return_if_fail (GTK_IS_TOOLBAR (widget));
377   g_return_if_fail (child != NULL);
378   g_return_if_fail (child->type == GTK_TOOLBAR_CHILD_SPACE);
379
380   toolbar = GTK_TOOLBAR (widget);
381
382   child_space = (GtkToolbarChildSpace *) child;
383
384   if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
385     gtk_paint_vline (widget->style, widget->window,
386                      GTK_WIDGET_STATE (widget), area, widget,
387                      "toolbar",
388                      child_space->alloc_y + toolbar->button_maxh *
389                      SPACE_LINE_START / SPACE_LINE_DIVISION,
390                      child_space->alloc_y + toolbar->button_maxh *
391                      SPACE_LINE_END / SPACE_LINE_DIVISION,
392                      child_space->alloc_x +
393                      (toolbar->space_size -
394                       widget->style->xthickness) / 2);
395   else
396     gtk_paint_hline (widget->style, widget->window,
397                      GTK_WIDGET_STATE (widget), area, widget,
398                      "toolbar",
399                      child_space->alloc_x + toolbar->button_maxw *
400                      SPACE_LINE_START / SPACE_LINE_DIVISION,
401                      child_space->alloc_x + toolbar->button_maxw *
402                      SPACE_LINE_END / SPACE_LINE_DIVISION,
403                      child_space->alloc_y +
404                      (toolbar->space_size -
405                       widget->style->ythickness) / 2);
406 }
407
408 static void
409 gtk_toolbar_draw (GtkWidget    *widget,
410                   GdkRectangle *area)
411 {
412   GtkToolbar *toolbar;
413   GList *children;
414   GtkToolbarChild *child;
415   GdkRectangle child_area;
416
417   g_return_if_fail (widget != NULL);
418   g_return_if_fail (GTK_IS_TOOLBAR (widget));
419
420   if (GTK_WIDGET_DRAWABLE (widget))
421     {
422       toolbar = GTK_TOOLBAR (widget);
423
424       for (children = toolbar->children; children; children = children->next)
425         {
426           child = children->data;
427
428           if (child->type == GTK_TOOLBAR_CHILD_SPACE)
429             {
430               if (toolbar->space_style == GTK_TOOLBAR_SPACE_LINE)
431                 gtk_toolbar_paint_space_line (widget, area, child);
432             }
433           else if (gtk_widget_intersect (child->widget, area, &child_area))
434             gtk_widget_draw (child->widget, &child_area);
435         }
436     }
437 }
438
439 static gint
440 gtk_toolbar_expose (GtkWidget      *widget,
441                     GdkEventExpose *event)
442 {
443   GtkToolbar *toolbar;
444   GList *children;
445   GtkToolbarChild *child;
446   GdkEventExpose child_event;
447
448   g_return_val_if_fail (widget != NULL, FALSE);
449   g_return_val_if_fail (GTK_IS_TOOLBAR (widget), FALSE);
450   g_return_val_if_fail (event != NULL, FALSE);
451
452   if (GTK_WIDGET_DRAWABLE (widget))
453     {
454       toolbar = GTK_TOOLBAR (widget);
455
456       child_event = *event;
457
458       for (children = toolbar->children; children; children = children->next)
459         {
460           child = children->data;
461
462           if (child->type == GTK_TOOLBAR_CHILD_SPACE)
463             {
464               if (toolbar->space_style == GTK_TOOLBAR_SPACE_LINE)
465                 gtk_toolbar_paint_space_line (widget, &event->area, child);
466             }
467           else if (GTK_WIDGET_NO_WINDOW (child->widget)
468                    && gtk_widget_intersect (child->widget, &event->area, &child_event.area))
469             gtk_widget_event (child->widget, (GdkEvent *) &child_event);
470         }
471     }
472
473   return FALSE;
474 }
475
476 static void
477 gtk_toolbar_size_request (GtkWidget      *widget,
478                           GtkRequisition *requisition)
479 {
480   GtkToolbar *toolbar;
481   GList *children;
482   GtkToolbarChild *child;
483   gint nbuttons;
484   gint button_maxw, button_maxh;
485   gint widget_maxw, widget_maxh;
486   GtkRequisition child_requisition;
487
488   g_return_if_fail (widget != NULL);
489   g_return_if_fail (GTK_IS_TOOLBAR (widget));
490   g_return_if_fail (requisition != NULL);
491
492   toolbar = GTK_TOOLBAR (widget);
493
494   requisition->width = GTK_CONTAINER (toolbar)->border_width * 2;
495   requisition->height = GTK_CONTAINER (toolbar)->border_width * 2;
496   nbuttons = 0;
497   button_maxw = 0;
498   button_maxh = 0;
499   widget_maxw = 0;
500   widget_maxh = 0;
501
502   for (children = toolbar->children; children; children = children->next)
503     {
504       child = children->data;
505
506       switch (child->type)
507         {
508         case GTK_TOOLBAR_CHILD_SPACE:
509           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
510             requisition->width += toolbar->space_size;
511           else
512             requisition->height += toolbar->space_size;
513
514           break;
515
516         case GTK_TOOLBAR_CHILD_BUTTON:
517         case GTK_TOOLBAR_CHILD_RADIOBUTTON:
518         case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
519           if (GTK_WIDGET_VISIBLE (child->widget))
520             {
521               gtk_widget_size_request (child->widget, &child_requisition);
522
523               nbuttons++;
524               button_maxw = MAX (button_maxw, child_requisition.width);
525               button_maxh = MAX (button_maxh, child_requisition.height);
526             }
527
528           break;
529
530         case GTK_TOOLBAR_CHILD_WIDGET:
531           if (GTK_WIDGET_VISIBLE (child->widget))
532             {
533               gtk_widget_size_request (child->widget, &child_requisition);
534
535               widget_maxw = MAX (widget_maxw, child_requisition.width);
536               widget_maxh = MAX (widget_maxh, child_requisition.height);
537
538               if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
539                 requisition->width += child_requisition.width;
540               else
541                 requisition->height += child_requisition.height;
542             }
543
544           break;
545
546         default:
547           g_assert_not_reached ();
548         }
549     }
550
551   if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
552     {
553       requisition->width += nbuttons * button_maxw;
554       requisition->height += MAX (button_maxh, widget_maxh);
555     }
556   else
557     {
558       requisition->width += MAX (button_maxw, widget_maxw);
559       requisition->height += nbuttons * button_maxh;
560     }
561
562   toolbar->button_maxw = button_maxw;
563   toolbar->button_maxh = button_maxh;
564 }
565
566 static void
567 gtk_toolbar_size_allocate (GtkWidget     *widget,
568                            GtkAllocation *allocation)
569 {
570   GtkToolbar *toolbar;
571   GList *children;
572   GtkToolbarChild *child;
573   GtkToolbarChildSpace *child_space;
574   GtkAllocation alloc;
575   GtkRequisition child_requisition;
576   gint border_width;
577
578   g_return_if_fail (widget != NULL);
579   g_return_if_fail (GTK_IS_TOOLBAR (widget));
580   g_return_if_fail (allocation != NULL);
581
582   toolbar = GTK_TOOLBAR (widget);
583   widget->allocation = *allocation;
584
585   border_width = GTK_CONTAINER (toolbar)->border_width;
586
587   if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
588     alloc.x = allocation->x + border_width;
589   else
590     alloc.y = allocation->y + border_width;
591
592   for (children = toolbar->children; children; children = children->next)
593     {
594       child = children->data;
595
596       switch (child->type)
597         {
598         case GTK_TOOLBAR_CHILD_SPACE:
599
600           child_space = (GtkToolbarChildSpace *) child;
601
602           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
603             {
604               child_space->alloc_x = alloc.x;
605               child_space->alloc_y = allocation->y + (allocation->height - toolbar->button_maxh) / 2;
606               alloc.x += toolbar->space_size;
607             }
608           else
609             {
610               child_space->alloc_x = allocation->x + (allocation->width - toolbar->button_maxw) / 2;
611               child_space->alloc_y = alloc.y;
612               alloc.y += toolbar->space_size;
613             }
614
615           break;
616
617         case GTK_TOOLBAR_CHILD_BUTTON:
618         case GTK_TOOLBAR_CHILD_RADIOBUTTON:
619         case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
620           if (!GTK_WIDGET_VISIBLE (child->widget))
621             break;
622
623           alloc.width = toolbar->button_maxw;
624           alloc.height = toolbar->button_maxh;
625
626           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
627             alloc.y = allocation->y + (allocation->height - toolbar->button_maxh) / 2;
628           else
629             alloc.x = allocation->x + (allocation->width - toolbar->button_maxw) / 2;
630
631           gtk_widget_size_allocate (child->widget, &alloc);
632
633           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
634             alloc.x += toolbar->button_maxw;
635           else
636             alloc.y += toolbar->button_maxh;
637
638           break;
639
640         case GTK_TOOLBAR_CHILD_WIDGET:
641           if (!GTK_WIDGET_VISIBLE (child->widget))
642             break;
643
644           gtk_widget_get_child_requisition (child->widget, &child_requisition);
645           
646           alloc.width = child_requisition.width;
647           alloc.height = child_requisition.height;
648
649           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
650             alloc.y = allocation->y + (allocation->height - child_requisition.height) / 2;
651           else
652             alloc.x = allocation->x + (allocation->width - child_requisition.width) / 2;
653
654           gtk_widget_size_allocate (child->widget, &alloc);
655
656           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
657             alloc.x += child_requisition.width;
658           else
659             alloc.y += child_requisition.height;
660
661           break;
662
663         default:
664           g_assert_not_reached ();
665         }
666     }
667 }
668
669 static void
670 gtk_toolbar_add (GtkContainer *container,
671                  GtkWidget    *widget)
672 {
673   g_return_if_fail (container != NULL);
674   g_return_if_fail (GTK_IS_TOOLBAR (container));
675   g_return_if_fail (widget != NULL);
676
677   gtk_toolbar_append_widget (GTK_TOOLBAR (container), widget, NULL, NULL);
678 }
679
680 static void
681 gtk_toolbar_remove (GtkContainer *container,
682                     GtkWidget    *widget)
683 {
684   GtkToolbar *toolbar;
685   GList *children;
686   GtkToolbarChild *child;
687
688   g_return_if_fail (container != NULL);
689   g_return_if_fail (GTK_IS_TOOLBAR (container));
690   g_return_if_fail (widget != NULL);
691
692   toolbar = GTK_TOOLBAR (container);
693
694   for (children = toolbar->children; children; children = children->next)
695     {
696       child = children->data;
697
698       if ((child->type != GTK_TOOLBAR_CHILD_SPACE) && (child->widget == widget))
699         {
700           gboolean was_visible;
701
702           was_visible = GTK_WIDGET_VISIBLE (widget);
703           gtk_widget_unparent (widget);
704
705           toolbar->children = g_list_remove_link (toolbar->children, children);
706           g_free (child);
707           g_list_free (children);
708           toolbar->num_children--;
709
710           if (was_visible && GTK_WIDGET_VISIBLE (container))
711             gtk_widget_queue_resize (GTK_WIDGET (container));
712
713           break;
714         }
715     }
716 }
717
718 static void
719 gtk_toolbar_forall (GtkContainer *container,
720                     gboolean      include_internals,
721                     GtkCallback   callback,
722                     gpointer      callback_data)
723 {
724   GtkToolbar *toolbar;
725   GList *children;
726   GtkToolbarChild *child;
727
728   g_return_if_fail (container != NULL);
729   g_return_if_fail (GTK_IS_TOOLBAR (container));
730   g_return_if_fail (callback != NULL);
731
732   toolbar = GTK_TOOLBAR (container);
733
734   for (children = toolbar->children; children; children = children->next)
735     {
736       child = children->data;
737
738       if (child->type != GTK_TOOLBAR_CHILD_SPACE)
739         (*callback) (child->widget, callback_data);
740     }
741 }
742
743 GtkWidget *
744 gtk_toolbar_append_item (GtkToolbar    *toolbar,
745                          const char    *text,
746                          const char    *tooltip_text,
747                          const char    *tooltip_private_text,
748                          GtkWidget     *icon,
749                          GtkSignalFunc  callback,
750                          gpointer       user_data)
751 {
752   return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
753                                      NULL, text,
754                                      tooltip_text, tooltip_private_text,
755                                      icon, callback, user_data,
756                                      toolbar->num_children);
757 }
758
759 GtkWidget *
760 gtk_toolbar_prepend_item (GtkToolbar    *toolbar,
761                           const char    *text,
762                           const char    *tooltip_text,
763                           const char    *tooltip_private_text,
764                           GtkWidget     *icon,
765                           GtkSignalFunc  callback,
766                           gpointer       user_data)
767 {
768   return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
769                                      NULL, text,
770                                      tooltip_text, tooltip_private_text,
771                                      icon, callback, user_data,
772                                      0);
773 }
774
775 GtkWidget *
776 gtk_toolbar_insert_item (GtkToolbar    *toolbar,
777                          const char    *text,
778                          const char    *tooltip_text,
779                          const char    *tooltip_private_text,
780                          GtkWidget     *icon,
781                          GtkSignalFunc  callback,
782                          gpointer       user_data,
783                          gint           position)
784 {
785   return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
786                                      NULL, text,
787                                      tooltip_text, tooltip_private_text,
788                                      icon, callback, user_data,
789                                      position);
790 }
791
792 void
793 gtk_toolbar_append_space (GtkToolbar *toolbar)
794 {
795   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
796                               NULL, NULL,
797                               NULL, NULL,
798                               NULL, NULL, NULL,
799                               toolbar->num_children);
800 }
801
802 void
803 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
804 {
805   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
806                               NULL, NULL,
807                               NULL, NULL,
808                               NULL, NULL, NULL,
809                               0);
810 }
811
812 void
813 gtk_toolbar_insert_space (GtkToolbar *toolbar,
814                           gint        position)
815 {
816   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
817                               NULL, NULL,
818                               NULL, NULL,
819                               NULL, NULL, NULL,
820                               position);
821 }
822
823 void
824 gtk_toolbar_append_widget (GtkToolbar  *toolbar,
825                            GtkWidget   *widget,
826                            const gchar *tooltip_text,
827                            const gchar *tooltip_private_text)
828 {
829   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
830                               widget, NULL,
831                               tooltip_text, tooltip_private_text,
832                               NULL, NULL, NULL,
833                               toolbar->num_children);
834 }
835
836 void
837 gtk_toolbar_prepend_widget (GtkToolbar  *toolbar,
838                             GtkWidget   *widget,
839                             const gchar *tooltip_text,
840                             const gchar *tooltip_private_text)
841 {
842   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
843                               widget, NULL,
844                               tooltip_text, tooltip_private_text,
845                               NULL, NULL, NULL,
846                               0);
847 }
848
849 void
850 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
851                            GtkWidget  *widget,
852                            const char *tooltip_text,
853                            const char *tooltip_private_text,
854                            gint        position)
855 {
856   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
857                               widget, NULL,
858                               tooltip_text, tooltip_private_text,
859                               NULL, NULL, NULL,
860                               position);
861 }
862
863 GtkWidget*
864 gtk_toolbar_append_element (GtkToolbar          *toolbar,
865                             GtkToolbarChildType  type,
866                             GtkWidget           *widget,
867                             const char          *text,
868                             const char          *tooltip_text,
869                             const char          *tooltip_private_text,
870                             GtkWidget           *icon,
871                             GtkSignalFunc        callback,
872                             gpointer             user_data)
873 {
874   return gtk_toolbar_insert_element (toolbar, type, widget, text,
875                                      tooltip_text, tooltip_private_text,
876                                      icon, callback, user_data,
877                                      toolbar->num_children);
878 }
879
880 GtkWidget *
881 gtk_toolbar_prepend_element (GtkToolbar          *toolbar,
882                              GtkToolbarChildType  type,
883                              GtkWidget           *widget,
884                              const char          *text,
885                              const char          *tooltip_text,
886                              const char          *tooltip_private_text,
887                              GtkWidget           *icon,
888                              GtkSignalFunc        callback,
889                              gpointer             user_data)
890 {
891   return gtk_toolbar_insert_element (toolbar, type, widget, text,
892                                      tooltip_text, tooltip_private_text,
893                                      icon, callback, user_data, 0);
894 }
895
896 GtkWidget *
897 gtk_toolbar_insert_element (GtkToolbar          *toolbar,
898                             GtkToolbarChildType  type,
899                             GtkWidget           *widget,
900                             const char          *text,
901                             const char          *tooltip_text,
902                             const char          *tooltip_private_text,
903                             GtkWidget           *icon,
904                             GtkSignalFunc        callback,
905                             gpointer             user_data,
906                             gint                 position)
907 {
908   GtkToolbarChild *child;
909   GtkWidget *box;
910
911   g_return_val_if_fail (toolbar != NULL, NULL);
912   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
913   if (type == GTK_TOOLBAR_CHILD_WIDGET)
914     {
915       g_return_val_if_fail (widget != NULL, NULL);
916       g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
917     }
918   else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON)
919     g_return_val_if_fail (widget == NULL, NULL);
920
921   if (type == GTK_TOOLBAR_CHILD_SPACE)
922     child = (GtkToolbarChild *) g_new (GtkToolbarChildSpace, 1);
923   else
924     child = g_new (GtkToolbarChild, 1);
925
926   child->type = type;
927   child->icon = NULL;
928   child->label = NULL;
929
930   switch (type)
931     {
932     case GTK_TOOLBAR_CHILD_SPACE:
933       child->widget = NULL;
934       ((GtkToolbarChildSpace *) child)->alloc_x =
935         ((GtkToolbarChildSpace *) child)->alloc_y = 0;
936       break;
937
938     case GTK_TOOLBAR_CHILD_WIDGET:
939       child->widget = widget;
940       break;
941
942     case GTK_TOOLBAR_CHILD_BUTTON:
943     case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
944     case GTK_TOOLBAR_CHILD_RADIOBUTTON:
945       if (type == GTK_TOOLBAR_CHILD_BUTTON)
946         {
947           child->widget = gtk_button_new ();
948           gtk_button_set_relief (GTK_BUTTON (child->widget), toolbar->relief);
949         }
950       else if (type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
951         {
952           child->widget = gtk_toggle_button_new ();
953           gtk_button_set_relief (GTK_BUTTON (child->widget), toolbar->relief);
954           gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child->widget),
955                                       FALSE);
956         }
957       else
958         {
959           child->widget = gtk_radio_button_new (widget
960                                                 ? gtk_radio_button_group (GTK_RADIO_BUTTON (widget))
961                                                 : NULL);
962           gtk_button_set_relief (GTK_BUTTON (child->widget), toolbar->relief);
963           gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child->widget), FALSE);
964         }
965
966       GTK_WIDGET_UNSET_FLAGS (child->widget, GTK_CAN_FOCUS);
967
968       if (callback)
969         gtk_signal_connect (GTK_OBJECT (child->widget), "clicked",
970                             callback, user_data);
971
972       if (toolbar->style == GTK_TOOLBAR_BOTH_HORIZ)
973           box = gtk_hbox_new (FALSE, 0);
974       else
975           box = gtk_vbox_new (FALSE, 0);
976       gtk_container_add (GTK_CONTAINER (child->widget), box);
977       gtk_widget_show (box);
978
979       if (text)
980         {
981           child->label = gtk_label_new (text);
982           gtk_box_pack_end (GTK_BOX (box), child->label, FALSE, FALSE, 0);
983           if (toolbar->style != GTK_TOOLBAR_ICONS)
984             gtk_widget_show (child->label);
985         }
986
987       if (icon)
988         {
989           child->icon = GTK_WIDGET (icon);
990           gtk_box_pack_end (GTK_BOX (box), child->icon, FALSE, FALSE, 0);
991           if (toolbar->style != GTK_TOOLBAR_TEXT)
992             gtk_widget_show (child->icon);
993         }
994
995       gtk_widget_show (child->widget);
996       break;
997
998     default:
999       g_assert_not_reached ();
1000     }
1001
1002   if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text)
1003     gtk_tooltips_set_tip (toolbar->tooltips, child->widget,
1004                           tooltip_text, tooltip_private_text);
1005
1006   toolbar->children = g_list_insert (toolbar->children, child, position);
1007   toolbar->num_children++;
1008
1009   if (type != GTK_TOOLBAR_CHILD_SPACE)
1010     {
1011       gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
1012
1013       if (GTK_WIDGET_REALIZED (child->widget->parent))
1014         gtk_widget_realize (child->widget);
1015
1016       if (GTK_WIDGET_VISIBLE (child->widget->parent) && GTK_WIDGET_VISIBLE (child->widget))
1017         {
1018           if (GTK_WIDGET_MAPPED (child->widget->parent))
1019             gtk_widget_map (child->widget);
1020
1021           gtk_widget_queue_resize (child->widget);
1022         }
1023     }
1024   else
1025     gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1026
1027   return child->widget;
1028 }
1029
1030 void
1031 gtk_toolbar_set_orientation (GtkToolbar     *toolbar,
1032                              GtkOrientation  orientation)
1033 {
1034   g_return_if_fail (toolbar != NULL);
1035   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1036
1037   gtk_signal_emit (GTK_OBJECT (toolbar), toolbar_signals[ORIENTATION_CHANGED], orientation);
1038 }
1039
1040 void
1041 gtk_toolbar_set_style (GtkToolbar      *toolbar,
1042                        GtkToolbarStyle  style)
1043 {
1044   g_return_if_fail (toolbar != NULL);
1045   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1046
1047   gtk_signal_emit (GTK_OBJECT (toolbar), toolbar_signals[STYLE_CHANGED], style);
1048 }
1049
1050 void
1051 gtk_toolbar_set_space_size (GtkToolbar *toolbar,
1052                             gint        space_size)
1053 {
1054   g_return_if_fail (toolbar != NULL);
1055   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1056
1057   if (toolbar->space_size != space_size)
1058     {
1059       toolbar->space_size = space_size;
1060       gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1061     }
1062 }
1063
1064 void
1065 gtk_toolbar_set_space_style (GtkToolbar           *toolbar,
1066                              GtkToolbarSpaceStyle  space_style)
1067 {
1068   g_return_if_fail (toolbar != NULL);
1069   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1070
1071   if (toolbar->space_style != space_style)
1072     {
1073       toolbar->space_style = space_style;
1074       gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1075     }
1076 }
1077
1078 void
1079 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
1080                           gint        enable)
1081 {
1082   g_return_if_fail (toolbar != NULL);
1083   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1084
1085   if (enable)
1086     gtk_tooltips_enable (toolbar->tooltips);
1087   else
1088     gtk_tooltips_disable (toolbar->tooltips);
1089 }
1090
1091 void
1092 gtk_toolbar_set_button_relief (GtkToolbar *toolbar,
1093                                GtkReliefStyle relief)
1094 {
1095   GList *children;
1096   GtkToolbarChild *child;
1097   
1098   g_return_if_fail (toolbar != NULL);
1099   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1100
1101   if (toolbar->relief != relief)
1102     {
1103       toolbar->relief = relief;
1104       
1105       for (children = toolbar->children; children; children = children->next)
1106         {
1107           child = children->data;
1108           if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
1109               child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
1110               child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
1111             gtk_button_set_relief (GTK_BUTTON (child->widget), relief);
1112         }
1113       
1114       gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1115     }
1116 }
1117
1118 GtkReliefStyle
1119 gtk_toolbar_get_button_relief (GtkToolbar *toolbar)
1120 {
1121   g_return_val_if_fail (toolbar != NULL, GTK_RELIEF_NORMAL);
1122   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_RELIEF_NORMAL);
1123
1124   return toolbar->relief;
1125 }
1126
1127 static void
1128 gtk_real_toolbar_orientation_changed (GtkToolbar     *toolbar,
1129                                       GtkOrientation  orientation)
1130 {
1131   g_return_if_fail (toolbar != NULL);
1132   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1133
1134   if (toolbar->orientation != orientation)
1135     {
1136       toolbar->orientation = orientation;
1137       gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1138     }
1139 }
1140
1141 static void
1142 gtk_real_toolbar_style_changed (GtkToolbar      *toolbar,
1143                                 GtkToolbarStyle  style)
1144 {
1145   GList *children;
1146   GtkToolbarChild *child;
1147   GtkWidget* box = NULL;
1148
1149   g_return_if_fail (toolbar != NULL);
1150   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1151
1152   if (toolbar->style != style)
1153     {
1154       toolbar->style = style;
1155
1156       for (children = toolbar->children; children; children = children->next)
1157         {
1158           child = children->data;
1159
1160           if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
1161               child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
1162               child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
1163             switch (style)
1164               {
1165               case GTK_TOOLBAR_ICONS:
1166                 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
1167                   gtk_widget_show (child->icon);
1168
1169                 if (child->label && GTK_WIDGET_VISIBLE (child->label))
1170                   gtk_widget_hide (child->label);
1171
1172                 break;
1173
1174               case GTK_TOOLBAR_TEXT:
1175                 if (child->icon && GTK_WIDGET_VISIBLE (child->icon))
1176                   gtk_widget_hide (child->icon);
1177                 
1178                 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
1179                   gtk_widget_show (child->label);
1180
1181                 break;
1182
1183               case GTK_TOOLBAR_BOTH:
1184                 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
1185                   gtk_widget_show (child->icon);
1186
1187                 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
1188                   gtk_widget_show (child->label);
1189
1190                 box = (GtkWidget*)gtk_container_children (GTK_CONTAINER (child->widget))->data;
1191
1192                 if (GTK_IS_HBOX (box))
1193                 {
1194                     if (child->icon)
1195                     {
1196                         gtk_object_ref (GTK_OBJECT (child->icon));
1197                         gtk_container_remove (GTK_CONTAINER (box),
1198                                               child->icon);
1199                     }
1200                     if (child->label)
1201                     {
1202                         gtk_object_ref (GTK_OBJECT (child->label));
1203                         gtk_container_remove (GTK_CONTAINER (box),
1204                                               child->label);
1205                     }
1206                     gtk_container_remove (GTK_CONTAINER (child->widget),
1207                                           box);
1208                     
1209                     box = gtk_vbox_new (FALSE, 0);
1210                     gtk_widget_show (box);
1211                     
1212                     if (child->label)
1213                     {
1214                         gtk_box_pack_end (GTK_BOX (box), child->label, FALSE, FALSE, 0);
1215                         gtk_object_unref (GTK_OBJECT (child->label));
1216                     }
1217                     if (child->icon)
1218                     {
1219                         gtk_box_pack_end (GTK_BOX (box), child->icon, FALSE, FALSE, 0);
1220                         gtk_object_unref (GTK_OBJECT (child->icon));
1221                     }
1222                     gtk_container_add (GTK_CONTAINER (child->widget),
1223                                        box);
1224                 }
1225                 
1226                 break;
1227                 
1228               case GTK_TOOLBAR_BOTH_HORIZ:
1229                 if (child->icon && !GTK_WIDGET_VISIBLE (child->icon))
1230                   gtk_widget_show (child->icon);
1231                 if (child->label && !GTK_WIDGET_VISIBLE (child->label))
1232                   gtk_widget_show (child->label);
1233
1234                 box = (GtkWidget*)gtk_container_children (GTK_CONTAINER (child->widget))->data;
1235                 
1236                 if (GTK_IS_VBOX (box))
1237                 {
1238                     if (child->icon)
1239                     {
1240                         gtk_object_ref (GTK_OBJECT (child->icon));
1241                         gtk_container_remove (GTK_CONTAINER (box),
1242                                               child->icon);
1243                     }
1244                     if (child->label)
1245                     {
1246                         gtk_object_ref (GTK_OBJECT (child->label));
1247                         gtk_container_remove (GTK_CONTAINER (box),
1248                                               child->label);
1249                     }
1250                     gtk_container_remove (GTK_CONTAINER (child->widget),
1251                                           box);
1252
1253                     box = gtk_hbox_new (FALSE, 0);
1254                     gtk_widget_show (box);
1255                     
1256                     if (child->label)
1257                     {
1258                         gtk_box_pack_end (GTK_BOX (box), child->label, TRUE, TRUE, 0);
1259                         gtk_object_unref (GTK_OBJECT (child->label));
1260                     }
1261                     if (child->icon)
1262                     {
1263                         gtk_box_pack_end (GTK_BOX (box), child->icon, FALSE, FALSE, 0);
1264                         gtk_object_unref (GTK_OBJECT (child->icon));
1265                     }
1266                     gtk_container_add (GTK_CONTAINER (child->widget), box);
1267                     
1268                 }
1269                 
1270                 break;
1271
1272               default:
1273                 g_assert_not_reached ();
1274               }
1275         }
1276                 
1277       gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1278     }
1279 }