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