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