]> Pileus Git - ~andy/gtk/blob - gtk/gtktoolbar.c
remove accidentally committed debugging spew
[~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  * Copyright (C) 2002 Anders Carlsson <andersca@codefactory.se>
6  * Copyright (C) 2002 James Henstridge <james@daa.com.au>
7  * Copyright (C) 2003 Soeren Sandmann <sandmann@daimi.au.dk>
8  * 
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 /*
26  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
27  * file for a list of people on the GTK+ Team.  See the ChangeLog
28  * files for a list of changes.  These files are distributed with
29  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
30  */
31
32 #undef GTK_DISABLE_DEPRECATED
33
34 #include "gtkarrow.h"
35 #include "gtktoolbar.h"
36 #include "gtkradiotoolbutton.h"
37 #include "gtkseparatortoolitem.h"
38 #include "gtkmenu.h"
39 #include "gtkradiobutton.h"
40 #include "gtktoolbar.h"
41 #include "gtkbindings.h"
42 #include <gdk/gdkkeysyms.h>
43 #include "gtkmarshalers.h"
44 #include "gtkmain.h"
45 #include "gtkstock.h"
46 #include "gtklabel.h"
47 #include "gtkprivate.h"
48 #include "gtkintl.h"
49 #include <string.h>
50
51 #define DEFAULT_IPADDING 0
52
53 /* note: keep in sync with DEFAULT_SPACE_SIZE and DEFAULT_SPACE_STYLE in gtkseparatortoolitem.c */
54 #define DEFAULT_SPACE_SIZE  5
55 #define DEFAULT_SPACE_STYLE GTK_TOOLBAR_SPACE_LINE
56
57 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_LARGE_TOOLBAR
58 #define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_BOTH
59
60 enum {
61   PROP_0,
62   PROP_ORIENTATION,
63   PROP_TOOLBAR_STYLE,
64   PROP_SHOW_ARROW
65 };
66
67 enum {
68   CHILD_PROP_0,
69   CHILD_PROP_EXPAND,
70   CHILD_PROP_HOMOGENEOUS,
71   CHILD_PROP_PACK_END,
72 };
73
74 enum {
75   ORIENTATION_CHANGED,
76   STYLE_CHANGED,
77   POPUP_CONTEXT_MENU,
78   MOVE_FOCUS,
79   FOCUS_HOME_OR_END,
80   LAST_SIGNAL
81 };
82
83 static void gtk_toolbar_init       (GtkToolbar      *toolbar);
84 static void gtk_toolbar_class_init (GtkToolbarClass *klass);
85
86 static void gtk_toolbar_set_property (GObject      *object,
87                                       guint         prop_id,
88                                       const GValue *value,
89                                       GParamSpec   *pspec);
90 static void gtk_toolbar_get_property (GObject      *object,
91                                       guint         prop_id,
92                                       GValue       *value,
93                                       GParamSpec   *pspec);
94
95 static gint     gtk_toolbar_expose         (GtkWidget        *widget,
96                                             GdkEventExpose   *event);
97 static void     gtk_toolbar_realize        (GtkWidget        *widget);
98 static void     gtk_toolbar_unrealize      (GtkWidget        *widget);
99 static void     gtk_toolbar_size_request   (GtkWidget        *widget,
100                                             GtkRequisition   *requisition);
101 static void     gtk_toolbar_size_allocate  (GtkWidget        *widget,
102                                             GtkAllocation    *allocation);
103 static void     gtk_toolbar_style_set      (GtkWidget        *widget,
104                                             GtkStyle         *prev_style);
105 static void     gtk_toolbar_direction_changed (GtkWidget        *widget,
106                                                GtkTextDirection  previous_direction);
107 static gboolean gtk_toolbar_focus          (GtkWidget        *widget,
108                                             GtkDirectionType  dir);
109 static void     gtk_toolbar_screen_changed (GtkWidget        *widget,
110                                             GdkScreen        *previous_screen);
111 static void     gtk_toolbar_map            (GtkWidget        *widget);
112 static void     gtk_toolbar_unmap          (GtkWidget        *widget);
113
114 static void     gtk_toolbar_drag_leave  (GtkWidget      *widget,
115                                          GdkDragContext *context,
116                                          guint           time_);
117 static gboolean gtk_toolbar_drag_motion (GtkWidget      *widget,
118                                          GdkDragContext *context,
119                                          gint            x,
120                                          gint            y,
121                                          guint           time_);
122 static void     gtk_toolbar_set_child_property (GtkContainer    *container,
123                                                 GtkWidget       *child,
124                                                 guint            property_id,
125                                                 const GValue    *value,
126                                                 GParamSpec      *pspec);
127 static void    gtk_toolbar_get_child_property (GtkContainer    *container,
128                                                GtkWidget       *child,
129                                                guint            property_id,
130                                                GValue          *value,
131                                                GParamSpec      *pspec);
132 static void gtk_toolbar_finalize (GObject *object);
133
134
135 static void  gtk_toolbar_add        (GtkContainer *container,
136                                      GtkWidget    *widget);
137 static void  gtk_toolbar_remove     (GtkContainer *container,
138                                      GtkWidget    *widget);
139 static void  gtk_toolbar_forall     (GtkContainer *container,
140                                      gboolean      include_internals,
141                                      GtkCallback   callback,
142                                      gpointer      callback_data);
143 static GType gtk_toolbar_child_type (GtkContainer *container);
144
145 static void gtk_toolbar_real_orientation_changed (GtkToolbar      *toolbar,
146                                                   GtkOrientation   orientation);
147 static void gtk_toolbar_real_style_changed       (GtkToolbar      *toolbar,
148                                                   GtkToolbarStyle  style);
149
150 static gboolean gtk_toolbar_move_focus        (GtkToolbar       *toolbar,
151                                                GtkDirectionType  dir);
152 static gboolean gtk_toolbar_focus_home_or_end (GtkToolbar       *toolbar,
153                                                gboolean          focus_home);
154
155 static gboolean             gtk_toolbar_button_press         (GtkWidget      *toolbar,
156                                                               GdkEventButton *event);
157 static gboolean             gtk_toolbar_arrow_button_press (GtkWidget      *button,
158                                                               GdkEventButton *event,
159                                                               GtkToolbar     *toolbar);
160 static void                 gtk_toolbar_arrow_button_clicked (GtkWidget      *button,
161                                                                GtkToolbar     *toolbar);
162 static void                 gtk_toolbar_update_button_relief (GtkToolbar     *toolbar);
163 static GtkReliefStyle       get_button_relief                (GtkToolbar     *toolbar);
164 static gint                 get_space_size                   (GtkToolbar     *toolbar);
165 static gint                 get_internal_padding             (GtkToolbar     *toolbar);
166 static void                 gtk_toolbar_remove_tool_item     (GtkToolbar     *toolbar,
167                                                               GtkToolItem    *item);
168 static gboolean             gtk_toolbar_popup_menu           (GtkWidget      *toolbar);
169
170 static GtkWidget *gtk_toolbar_internal_insert_element (GtkToolbar          *toolbar,
171                                                        GtkToolbarChildType  type,
172                                                        GtkWidget           *widget,
173                                                        const char          *text,
174                                                        const char          *tooltip_text,
175                                                        const char          *tooltip_private_text,
176                                                        GtkWidget           *icon,
177                                                        GtkSignalFunc        callback,
178                                                        gpointer             user_data,
179                                                        gint                 position,
180                                                        gboolean             use_stock);
181
182
183 typedef enum {
184   DONT_KNOW,
185   OLD_API,
186   NEW_API
187 } ApiMode;
188
189 struct _GtkToolbarPrivate
190 {
191   GList     *items;
192   
193   GtkWidget *arrow;
194   GtkWidget *arrow_button;
195   
196   gboolean   show_arrow;
197
198   gint       drop_index;
199   GdkWindow *drag_highlight;
200   GtkMenu   *menu;
201
202   GdkWindow *event_window;
203   ApiMode    api_mode;
204   GtkSettings *settings;
205 };
206
207 static GtkContainerClass *parent_class = NULL;
208 static guint toolbar_signals [LAST_SIGNAL] = { 0 };
209
210 GType
211 gtk_toolbar_get_type (void)
212 {
213   static GtkType type = 0;
214
215   if (!type)
216     {
217       static const GTypeInfo type_info =
218         {
219           sizeof (GtkToolbarClass),
220           (GBaseInitFunc) NULL,
221           (GBaseFinalizeFunc) NULL,
222           (GClassInitFunc) gtk_toolbar_class_init,
223           (GClassFinalizeFunc) NULL,
224           NULL,
225           sizeof (GtkToolbar),
226           0, /* n_preallocs */
227           (GInstanceInitFunc) gtk_toolbar_init,
228         };
229
230       type = g_type_register_static (GTK_TYPE_CONTAINER,
231                                      "GtkToolbar",
232                                      &type_info, 0);
233     }
234   
235   return type;
236 }
237
238 static void
239 add_arrow_bindings (GtkBindingSet   *binding_set,
240                     guint            keysym,
241                     GtkDirectionType dir)
242 {
243   guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
244   
245   gtk_binding_entry_add_signal (binding_set, keysym, 0,
246                                 "move_focus", 1,
247                                 GTK_TYPE_DIRECTION_TYPE, dir);
248   gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
249                                 "move_focus", 1,
250                                 GTK_TYPE_DIRECTION_TYPE, dir);
251 }
252
253 static void
254 add_ctrl_tab_bindings (GtkBindingSet    *binding_set,
255                        GdkModifierType   modifiers,
256                        GtkDirectionType  direction)
257 {
258   gtk_binding_entry_add_signal (binding_set,
259                                 GDK_Tab, GDK_CONTROL_MASK | modifiers,
260                                 "move_focus", 1,
261                                 GTK_TYPE_DIRECTION_TYPE, direction);
262   gtk_binding_entry_add_signal (binding_set,
263                                 GDK_KP_Tab, GDK_CONTROL_MASK | modifiers,
264                                 "move_focus", 1,
265                                 GTK_TYPE_DIRECTION_TYPE, direction);
266 }
267
268 static void
269 gtk_toolbar_class_init (GtkToolbarClass *klass)
270 {
271   GObjectClass *gobject_class;
272   GtkWidgetClass *widget_class;
273   GtkContainerClass *container_class;
274   GtkBindingSet *binding_set;
275
276   parent_class = g_type_class_peek_parent (klass);
277   
278   gobject_class = (GObjectClass *)klass;
279   widget_class = (GtkWidgetClass *)klass;
280   container_class = (GtkContainerClass *)klass;
281   
282   gobject_class->set_property = gtk_toolbar_set_property;
283   gobject_class->get_property = gtk_toolbar_get_property;
284   gobject_class->finalize = gtk_toolbar_finalize;
285
286   widget_class->button_press_event = gtk_toolbar_button_press;
287   widget_class->expose_event = gtk_toolbar_expose;
288   widget_class->size_request = gtk_toolbar_size_request;
289   widget_class->size_allocate = gtk_toolbar_size_allocate;
290   widget_class->style_set = gtk_toolbar_style_set;
291   widget_class->direction_changed = gtk_toolbar_direction_changed;
292   widget_class->focus = gtk_toolbar_focus;
293   widget_class->screen_changed = gtk_toolbar_screen_changed;
294   widget_class->realize = gtk_toolbar_realize;
295   widget_class->unrealize = gtk_toolbar_unrealize;
296   widget_class->map = gtk_toolbar_map;
297   widget_class->unmap = gtk_toolbar_unmap;
298   widget_class->popup_menu = gtk_toolbar_popup_menu;
299   
300   widget_class->drag_leave = gtk_toolbar_drag_leave;
301   widget_class->drag_motion = gtk_toolbar_drag_motion;
302   
303   container_class->add    = gtk_toolbar_add;
304   container_class->remove = gtk_toolbar_remove;
305   container_class->forall = gtk_toolbar_forall;
306   container_class->child_type = gtk_toolbar_child_type;
307   container_class->get_child_property = gtk_toolbar_get_child_property;
308   container_class->set_child_property = gtk_toolbar_set_child_property;
309   
310   klass->orientation_changed = gtk_toolbar_real_orientation_changed;
311   klass->style_changed = gtk_toolbar_real_style_changed;
312   
313   toolbar_signals[ORIENTATION_CHANGED] =
314     g_signal_new ("orientation_changed",
315                   G_OBJECT_CLASS_TYPE (klass),
316                   G_SIGNAL_RUN_FIRST,
317                   G_STRUCT_OFFSET (GtkToolbarClass, orientation_changed),
318                   NULL, NULL,
319                   g_cclosure_marshal_VOID__ENUM,
320                   G_TYPE_NONE, 1,
321                   GTK_TYPE_ORIENTATION);
322   toolbar_signals[STYLE_CHANGED] =
323     g_signal_new ("style_changed",
324                   G_OBJECT_CLASS_TYPE (klass),
325                   G_SIGNAL_RUN_FIRST,
326                   G_STRUCT_OFFSET (GtkToolbarClass, style_changed),
327                   NULL, NULL,
328                   g_cclosure_marshal_VOID__ENUM,
329                   G_TYPE_NONE, 1,
330                   GTK_TYPE_TOOLBAR_STYLE);
331   toolbar_signals[POPUP_CONTEXT_MENU] =
332     g_signal_new ("popup_context_menu",
333                   G_OBJECT_CLASS_TYPE (klass),
334                   G_SIGNAL_RUN_LAST,
335                   G_STRUCT_OFFSET (GtkToolbarClass, popup_context_menu),
336                   _gtk_boolean_handled_accumulator, NULL,
337                   _gtk_marshal_BOOLEAN__INT_INT_INT,
338                   G_TYPE_BOOLEAN, 3,
339                   G_TYPE_INT, G_TYPE_INT,
340                   G_TYPE_INT);
341   toolbar_signals[MOVE_FOCUS] =
342     _gtk_binding_signal_new ("move_focus",
343                              G_TYPE_FROM_CLASS (klass),
344                              G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
345                              G_CALLBACK (gtk_toolbar_move_focus),
346                              NULL, NULL,
347                              _gtk_marshal_BOOLEAN__ENUM,
348                              G_TYPE_BOOLEAN, 1,
349                              GTK_TYPE_DIRECTION_TYPE);
350   toolbar_signals[FOCUS_HOME_OR_END] =
351     _gtk_binding_signal_new ("focus_home_or_end",
352                              G_OBJECT_CLASS_TYPE (klass),
353                              G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
354                              G_CALLBACK (gtk_toolbar_focus_home_or_end),
355                              NULL, NULL,
356                              _gtk_marshal_BOOLEAN__BOOLEAN,
357                              G_TYPE_BOOLEAN, 1,
358                              G_TYPE_BOOLEAN);
359
360   /* properties */
361   g_object_class_install_property (gobject_class,
362                                    PROP_ORIENTATION,
363                                    g_param_spec_enum ("orientation",
364                                                       _("Orientation"),
365                                                       _("The orientation of the toolbar"),
366                                                       GTK_TYPE_ORIENTATION,
367                                                       GTK_ORIENTATION_HORIZONTAL,
368                                                       G_PARAM_READWRITE));
369
370   g_object_class_install_property (gobject_class,
371                                    PROP_TOOLBAR_STYLE,
372                                    g_param_spec_enum ("toolbar_style",
373                                                       _("Toolbar Style"),
374                                                       _("How to draw the toolbar"),
375                                                       GTK_TYPE_TOOLBAR_STYLE,
376                                                       GTK_TOOLBAR_ICONS,
377                                                       G_PARAM_READWRITE));
378   g_object_class_install_property (gobject_class,
379                                    PROP_SHOW_ARROW,
380                                    g_param_spec_boolean ("show_arrow",
381                                                          _("Show Arrow"),
382                                                          _("If an arrow should be shown if the toolbar doesn't fit"),
383                                                          FALSE,
384                                                          G_PARAM_READWRITE));
385
386   /* child properties */
387   gtk_container_class_install_child_property (container_class,
388                                               CHILD_PROP_EXPAND,
389                                               g_param_spec_boolean ("expand", 
390                                                                     _("Expand"), 
391                                                                     _("Whether the item should receive extra space when the toolbar grows"),
392                                                                     TRUE,
393                                                                     G_PARAM_READWRITE));
394
395   gtk_container_class_install_child_property (container_class,
396                                               CHILD_PROP_HOMOGENEOUS,
397                                               g_param_spec_boolean ("homogeneous", 
398                                                                     _("Homogeneous"), 
399                                                                     _("Whether the item should be the same size as other homogeneous items"),
400                                                                     TRUE,
401                                                                     G_PARAM_READWRITE));
402
403   gtk_container_class_install_child_property (container_class,
404                                               CHILD_PROP_PACK_END,
405                                               g_param_spec_uint ("pack_end", 
406                                                                  _("Pack End"), 
407                                                                  _("Whether the item is positioned at the end of the toolbar"),
408                                                                  0, G_MAXINT, 0,
409                                                                  G_PARAM_READWRITE));
410
411   /* style properties */
412   gtk_widget_class_install_style_property (widget_class,
413                                            g_param_spec_int ("space_size",
414                                                              _("Spacer size"),
415                                                              _("Size of spacers"),
416                                                              0,
417                                                              G_MAXINT,
418                                                              DEFAULT_SPACE_SIZE,
419                                                              G_PARAM_READABLE));
420   
421   gtk_widget_class_install_style_property (widget_class,
422                                            g_param_spec_int ("internal_padding",
423                                                              _("Internal padding"),
424                                                              _("Amount of border space between the toolbar shadow and the buttons"),
425                                                              0,
426                                                              G_MAXINT,
427                                                              DEFAULT_IPADDING,
428                                                              G_PARAM_READABLE));
429
430   gtk_widget_class_install_style_property (widget_class,
431                                            g_param_spec_enum ("space_style",
432                                                              _("Space style"),
433                                                              _("Whether spacers are vertical lines or just blank"),
434                                                               GTK_TYPE_TOOLBAR_SPACE_STYLE,
435                                                               DEFAULT_SPACE_STYLE,
436                                                               G_PARAM_READABLE));
437   
438   gtk_widget_class_install_style_property (widget_class,
439                                            g_param_spec_enum ("button_relief",
440                                                               _("Button relief"),
441                                                               _("Type of bevel around toolbar buttons"),
442                                                               GTK_TYPE_RELIEF_STYLE,
443                                                               GTK_RELIEF_NONE,
444                                                               G_PARAM_READABLE));
445   gtk_widget_class_install_style_property (widget_class,
446                                            g_param_spec_enum ("shadow_type",
447                                                               _("Shadow type"),
448                                                               _("Style of bevel around the toolbar"),
449                                                               GTK_TYPE_SHADOW_TYPE,
450                                                               GTK_SHADOW_OUT,
451                                                               G_PARAM_READABLE));
452
453   gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-style",
454                                                     _("Toolbar style"),
455                                                     _("Whether default toolbars have text only, text and icons, icons only, etc."),
456                                                     GTK_TYPE_TOOLBAR_STYLE,
457                                                     DEFAULT_TOOLBAR_STYLE,
458                                                     G_PARAM_READWRITE));
459
460   gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-icon-size",
461                                                     _("Toolbar icon size"),
462                                                     _("Size of icons in default toolbars"),
463                                                     GTK_TYPE_ICON_SIZE,
464                                                     DEFAULT_ICON_SIZE,
465                                                     G_PARAM_READWRITE));  
466
467   binding_set = gtk_binding_set_by_class (klass);
468
469   add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
470   add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
471   add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
472   add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
473
474   gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
475                                 "focus_home_or_end", 1,
476                                 G_TYPE_BOOLEAN, TRUE);
477   gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
478                                 "focus_home_or_end", 1,
479                                 G_TYPE_BOOLEAN, TRUE);
480   gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
481                                 "focus_home_or_end", 1,
482                                 G_TYPE_BOOLEAN, FALSE);
483   gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
484                                 "focus_home_or_end", 1,
485                                 G_TYPE_BOOLEAN, FALSE);
486
487   add_ctrl_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
488   add_ctrl_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
489
490   g_type_class_add_private (gobject_class, sizeof (GtkToolbarPrivate));  
491 }
492
493 static void
494 gtk_toolbar_init (GtkToolbar *toolbar)
495 {
496   GtkToolbarPrivate *priv;
497   
498   GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS);
499   GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
500
501   priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
502   
503   toolbar->orientation = GTK_ORIENTATION_HORIZONTAL;
504   toolbar->style = DEFAULT_TOOLBAR_STYLE;
505   toolbar->icon_size = DEFAULT_ICON_SIZE;
506   toolbar->tooltips = gtk_tooltips_new ();
507   g_object_ref (toolbar->tooltips);
508   gtk_object_sink (GTK_OBJECT (toolbar->tooltips));
509   
510   priv->arrow_button = gtk_toggle_button_new ();
511   g_signal_connect (priv->arrow_button, "button_press_event",
512                     G_CALLBACK (gtk_toolbar_arrow_button_press), toolbar);
513   g_signal_connect (priv->arrow_button, "clicked",
514                     G_CALLBACK (gtk_toolbar_arrow_button_clicked), toolbar);
515   gtk_button_set_relief (GTK_BUTTON (priv->arrow_button),
516                          get_button_relief (toolbar));
517
518   priv->api_mode = DONT_KNOW;
519   
520   gtk_button_set_focus_on_click (GTK_BUTTON (priv->arrow_button), FALSE);
521   
522   priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
523   gtk_widget_show (priv->arrow);
524   gtk_container_add (GTK_CONTAINER (priv->arrow_button), priv->arrow);
525   
526   gtk_widget_set_parent (priv->arrow_button, GTK_WIDGET (toolbar));
527
528   /* which child position a drop will occur at */
529   priv->drop_index = -1;
530   priv->drag_highlight = NULL;
531
532   priv->menu = NULL;
533
534   priv->settings = NULL;
535 }
536
537 static gboolean
538 toolbar_item_visible (GtkToolbar  *toolbar,
539                       GtkToolItem *item)
540 {
541   if (GTK_WIDGET_VISIBLE (item) &&
542       ((toolbar->orientation == GTK_ORIENTATION_HORIZONTAL && item->visible_horizontal) ||
543        (toolbar->orientation == GTK_ORIENTATION_VERTICAL && item->visible_vertical)))
544     {
545       GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
546       
547       /* With the old toolbar you could hide a button by calling gtk_widget_hide()
548        * on it. This doesn't work with the new API because the GtkToolItem will not be
549        * hidden.
550        */
551       if (priv->api_mode == OLD_API)
552         {
553           GtkWidget *bin_child = GTK_BIN (item)->child;
554           
555           if (bin_child && !GTK_WIDGET_VISIBLE (bin_child))
556             return FALSE;
557         }
558       
559       return TRUE;
560     }
561   
562   return FALSE;
563 }
564
565 static void
566 gtk_toolbar_set_property (GObject     *object,
567                           guint        prop_id,
568                           const GValue *value,
569                           GParamSpec   *pspec)
570 {
571   GtkToolbar *toolbar = GTK_TOOLBAR (object);
572
573   switch (prop_id)
574     {
575     case PROP_ORIENTATION:
576       gtk_toolbar_set_orientation (toolbar, g_value_get_enum (value));
577       break;
578     case PROP_TOOLBAR_STYLE:
579       gtk_toolbar_set_style (toolbar, g_value_get_enum (value));
580       break;
581     case PROP_SHOW_ARROW:
582       gtk_toolbar_set_show_arrow (toolbar, g_value_get_boolean (value));
583       break;
584     default:
585       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
586       break;
587     }
588 }
589
590 static void
591 gtk_toolbar_get_property (GObject    *object,
592                           guint       prop_id,
593                           GValue     *value,
594                           GParamSpec *pspec)
595 {
596   GtkToolbar *toolbar = GTK_TOOLBAR (object);
597   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
598   
599   switch (prop_id)
600     {
601     case PROP_ORIENTATION:
602       g_value_set_enum (value, toolbar->orientation);
603       break;
604     case PROP_TOOLBAR_STYLE:
605       g_value_set_enum (value, toolbar->style);
606       break;
607     case PROP_SHOW_ARROW:
608       g_value_set_boolean (value, priv->show_arrow);
609       break;
610     default:
611       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
612       break;
613     }
614 }
615
616 static void
617 gtk_toolbar_map (GtkWidget *widget)
618 {
619   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
620
621   GTK_WIDGET_CLASS (parent_class)->map (widget);
622
623   if (priv->event_window)
624     gdk_window_show_unraised (priv->event_window);
625 }
626
627 static void
628 gtk_toolbar_unmap (GtkWidget *widget)
629 {
630   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
631
632   if (priv->event_window)
633     gdk_window_hide (priv->event_window);
634
635   GTK_WIDGET_CLASS (parent_class)->unmap (widget);
636 }
637
638 static void
639 gtk_toolbar_realize (GtkWidget *widget)
640 {
641   GtkToolbar *toolbar = GTK_TOOLBAR (widget);
642   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
643
644   GdkWindowAttr attributes;
645   gint attributes_mask;
646   gint border_width;
647
648   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
649
650   border_width = GTK_CONTAINER (widget)->border_width;
651
652   attributes.wclass = GDK_INPUT_ONLY;
653   attributes.window_type = GDK_WINDOW_CHILD;
654   attributes.x = widget->allocation.x + border_width;
655   attributes.y = widget->allocation.y + border_width;
656   attributes.width = widget->allocation.width - border_width * 2;
657   attributes.height = widget->allocation.height - border_width * 2;
658   attributes.event_mask = gtk_widget_get_events (widget);
659   /* FIXME: does GDK_EXPOSURE_MASK make sense for an input-only window?
660    * If it doesn't, then it should be removed here and in gtkbutton.c,
661    * gtkmenuitem.c, and maybe other places
662    */
663   attributes.event_mask |= (GDK_EXPOSURE_MASK |
664                             GDK_BUTTON_PRESS_MASK |
665                             GDK_BUTTON_RELEASE_MASK |
666                             GDK_ENTER_NOTIFY_MASK |
667                             GDK_LEAVE_NOTIFY_MASK);
668
669   attributes_mask = GDK_WA_X | GDK_WA_Y;
670
671   widget->window = gtk_widget_get_parent_window (widget);
672   g_object_ref (widget->window);
673   widget->style = gtk_style_attach (widget->style, widget->window);
674   
675   priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
676                                        &attributes, attributes_mask);
677   gdk_window_set_user_data (priv->event_window, toolbar);
678 }
679
680 static void
681 gtk_toolbar_unrealize (GtkWidget *widget)
682 {
683   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
684
685   if (priv->drag_highlight)
686     {
687       gdk_window_set_user_data (priv->drag_highlight, NULL);
688       gdk_window_destroy (priv->drag_highlight);
689       priv->drag_highlight = NULL;
690     }
691
692   if (priv->event_window)
693     {
694       gdk_window_set_user_data (priv->event_window, NULL);
695       gdk_window_destroy (priv->event_window);
696       priv->event_window = NULL;
697     }
698
699   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
700     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
701 }
702
703 static gint
704 gtk_toolbar_expose (GtkWidget      *widget,
705                     GdkEventExpose *event)
706 {
707   GtkToolbar *toolbar = GTK_TOOLBAR (widget);
708   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
709   
710   GList *items;
711   gint border_width;
712   
713   border_width = GTK_CONTAINER (widget)->border_width;
714   
715   if (GTK_WIDGET_DRAWABLE (widget))
716     {
717       GtkShadowType shadow_type;
718
719       gtk_widget_style_get (widget, "shadow_type", &shadow_type, NULL);
720       
721       gtk_paint_box (widget->style,
722                      widget->window,
723                      GTK_WIDGET_STATE (widget),
724                      shadow_type,
725                      &event->area, widget, "toolbar",
726                      border_width + widget->allocation.x,
727                      border_width + widget->allocation.y,
728                      widget->allocation.width - 2 * border_width,
729                      widget->allocation.height - 2 * border_width);
730     }
731
732   items = priv->items;
733   while (items)
734     {
735       GtkToolItem *item = GTK_TOOL_ITEM (items->data);
736
737       gtk_container_propagate_expose (GTK_CONTAINER (widget),
738                                       GTK_WIDGET (item),
739                                       event);
740       
741       items = items->next;
742     }
743
744   gtk_container_propagate_expose (GTK_CONTAINER (widget),
745                                   priv->arrow_button,
746                                   event);
747
748   return FALSE;
749 }
750
751 static void
752 gtk_toolbar_size_request (GtkWidget      *widget,
753                           GtkRequisition *requisition)
754 {
755   GtkToolbar *toolbar = GTK_TOOLBAR (widget);
756   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
757   gint space_size = get_space_size (toolbar);
758   GList *list;
759   gint max_child_height;
760   gint max_child_width;
761   gint max_homogeneous_child_width;
762   gint max_homogeneous_child_height;
763   gint homogeneous_size;
764   gint long_req;
765   gint pack_end_size;
766   gint pack_front_size;
767   gint ipadding;
768   GtkRequisition arrow_requisition;
769
770   max_homogeneous_child_width = 0;
771   max_homogeneous_child_height = 0;
772   max_child_width = 0;
773   max_child_height = 0;
774   for (list = priv->items; list != NULL; list = list->next)
775     {
776       GtkRequisition requisition;
777       GtkToolItem *item = list->data;
778       
779       if (!toolbar_item_visible (toolbar, item))
780         continue;
781
782       gtk_widget_size_request (GTK_WIDGET (item), &requisition);
783       
784       max_child_width = MAX (max_child_width, requisition.width);
785       max_child_height = MAX (max_child_height, requisition.height);
786
787       if (GTK_TOOL_ITEM (item)->homogeneous && GTK_BIN (item)->child)
788         {
789           max_homogeneous_child_width = MAX (max_homogeneous_child_width, requisition.width);
790           max_homogeneous_child_height = MAX (max_homogeneous_child_height, requisition.height);
791         }
792     }
793   
794   if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
795     homogeneous_size = max_homogeneous_child_width;
796   else
797     homogeneous_size = max_homogeneous_child_height;
798   
799   pack_end_size = 0;
800   pack_front_size = 0;
801   for (list = priv->items; list != NULL; list = list->next)
802     {
803       GtkToolItem *item = list->data;
804       guint size;
805       
806       if (!toolbar_item_visible (toolbar, item))
807         continue;
808       
809       if (!GTK_BIN (item)->child)
810         {
811           size = space_size;
812         }
813       else if (item->homogeneous)
814         {
815           size = homogeneous_size;
816         }
817       else
818         {
819           GtkRequisition requisition;
820           
821           gtk_widget_size_request (GTK_WIDGET (item), &requisition);
822
823           if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
824             size = requisition.width;
825           else
826             size = requisition.height;
827         }
828       
829       if (item->pack_end)
830         pack_end_size += size;
831       else
832         pack_front_size += size;
833     }
834   
835   if (priv->show_arrow)
836     {
837       gtk_widget_size_request (priv->arrow_button, &arrow_requisition);
838       
839       if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
840         long_req = arrow_requisition.width;
841       else
842         long_req = arrow_requisition.height;
843
844       /* There is no point requesting space for the arrow if that would take
845        * up more space than all the items combined
846        */
847       long_req = MIN (long_req, pack_front_size + pack_end_size);
848     }
849   else
850     {
851       arrow_requisition.height = 0;
852       arrow_requisition.width = 0;
853       
854       long_req = pack_end_size + pack_front_size;
855     }
856   
857   if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
858     {
859       requisition->width = long_req;
860       requisition->height = MAX (max_child_height, arrow_requisition.height);
861     }
862   else
863     {
864       requisition->height = long_req;
865       requisition->width = MAX (max_child_width, arrow_requisition.width);
866     }
867   
868   /* Extra spacing */
869   ipadding = get_internal_padding (toolbar);
870
871   requisition->width += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width);
872   requisition->height += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width);
873   
874   toolbar->button_maxw = max_homogeneous_child_width;
875   toolbar->button_maxh = max_homogeneous_child_height;
876 }
877
878 static void
879 fixup_allocation_for_rtl (gint           total_size,
880                           GtkAllocation *allocation)
881 {
882   allocation->x += (total_size - (2 * allocation->x + allocation->width));
883 }
884
885 static void
886 fixup_allocation_for_vertical (GtkAllocation *allocation)
887 {
888   gint tmp;
889   
890   tmp = allocation->x;
891   allocation->x = allocation->y;
892   allocation->y = tmp;
893   
894   tmp = allocation->width;
895   allocation->width = allocation->height;
896   allocation->height = tmp;
897 }
898
899 static gint
900 get_item_size (GtkToolbar *toolbar,
901                GtkWidget  *child)
902 {
903   GtkRequisition requisition;
904   GtkToolItem *item = GTK_TOOL_ITEM (child);
905
906   if (!GTK_BIN (item)->child)
907     return get_space_size (toolbar);
908
909   gtk_widget_get_child_requisition (child, &requisition);
910   
911   if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
912     {
913       if (item->homogeneous)
914         return toolbar->button_maxw;
915       else
916         return requisition.width;
917     }
918   else
919     {
920       if (item->homogeneous)
921         return toolbar->button_maxh;
922       else
923         return requisition.height;
924     }
925 }
926
927 static void
928 gtk_toolbar_size_allocate (GtkWidget     *widget,
929                            GtkAllocation *allocation)
930 {
931   GtkToolbar *toolbar = GTK_TOOLBAR (widget);
932   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
933   gint space_size;
934   GtkAllocation *allocations;
935   GtkAllocation arrow_allocation;
936   gint arrow_size;
937   gint size, pos, short_size;
938   GList *list;
939   gint i;
940   gboolean need_arrow;
941   gint n_expand_items;
942   gint border_width;
943   gint available_size;
944   gint n_items;
945   gint needed_size;
946   GList *items;
947   GtkRequisition arrow_requisition;
948
949   widget->allocation = *allocation;
950
951   space_size = get_space_size (toolbar);
952
953   border_width = GTK_CONTAINER (toolbar)->border_width;
954
955   if (GTK_WIDGET_REALIZED (widget))
956     {
957       gdk_window_move_resize (priv->event_window,
958                               allocation->x + border_width,
959                               allocation->y + border_width,
960                               allocation->width - border_width * 2,
961                               allocation->height - border_width * 2);
962     }
963   
964   border_width += get_internal_padding (toolbar);
965   
966   gtk_widget_get_child_requisition (GTK_WIDGET (priv->arrow_button),
967                                     &arrow_requisition);
968   
969   if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
970     {
971       available_size = size = allocation->width - 2 * border_width;
972       short_size = allocation->height - 2 * border_width;
973       arrow_size = arrow_requisition.width;
974     }
975   else
976     {
977       available_size = size = allocation->height - 2 * border_width;
978       short_size = allocation->width - 2 * border_width;
979       arrow_size = arrow_requisition.height;
980     }
981
982   n_items = g_list_length (priv->items);
983   allocations = g_new0 (GtkAllocation, n_items);
984
985   needed_size = 0;
986   for (list = priv->items; list != NULL; list = list->next)
987     {
988       GtkToolItem *item = list->data;
989       
990       if (toolbar_item_visible (toolbar, item))
991         needed_size += get_item_size (toolbar, GTK_WIDGET (item));
992     }
993
994   need_arrow = (needed_size > available_size) && priv->show_arrow;
995
996   if (need_arrow)
997     size = available_size - arrow_size;
998   else
999     size = available_size;
1000
1001   items = g_list_copy (priv->items);
1002
1003   /* calculate widths of pack end items */
1004   for (list = g_list_last (items), i = 0; list != NULL; list = list->prev, ++i)
1005     {
1006       GtkToolItem *item = list->data;
1007       GtkAllocation *allocation = &(allocations[n_items - i - 1]);
1008       gint item_size;
1009       
1010       if (!item->pack_end || !toolbar_item_visible (toolbar, item))
1011         continue;
1012
1013       item_size = get_item_size (toolbar, GTK_WIDGET (item));
1014       if (item_size <= size)
1015         {
1016           size -= item_size;
1017           allocation->width = item_size;
1018           item->overflow_item = FALSE;
1019         }
1020       else
1021         {
1022           while (list)
1023             {
1024               item = list->data;
1025               if (item->pack_end)
1026                 item->overflow_item = TRUE;
1027               
1028               list = list->prev;
1029             }
1030           break;
1031         }
1032     }
1033
1034   /* calculate widths of pack front items */
1035   for (list = items, i = 0; list != NULL; list = list->next, ++i)
1036     {
1037       GtkToolItem *item = list->data;
1038       gint item_size;
1039
1040       if (item->pack_end || !toolbar_item_visible (toolbar, item))
1041         continue;
1042
1043       item_size = get_item_size (toolbar, GTK_WIDGET (item));
1044       if (item_size <= size)
1045         {
1046           size -= item_size;
1047           allocations[i].width = item_size;
1048           item->overflow_item = FALSE;
1049         }
1050       else
1051         {
1052           while (list)
1053             {
1054               item = list->data;
1055               if (!item->pack_end)
1056                 item->overflow_item = TRUE;
1057               list = list->next;
1058             }
1059           break;
1060         }
1061     }
1062
1063   if (need_arrow)
1064     {
1065       arrow_allocation.width = arrow_size;
1066       arrow_allocation.height = short_size;
1067     }
1068   
1069   /* expand expandable items */
1070   n_expand_items = 0;
1071   for (list = priv->items; list != NULL; list = list->next)
1072     {
1073       GtkToolItem *item = list->data;
1074       
1075       if (toolbar_item_visible (toolbar, item) && item->expand &&
1076           !item->overflow_item && GTK_BIN (item)->child)
1077         {
1078           n_expand_items++;
1079         }
1080     }
1081   
1082   for (list = items, i = 0; list != NULL; list = list->next, ++i)
1083     {
1084       GtkToolItem *item = list->data;
1085       
1086       if (toolbar_item_visible (toolbar, item) && item->expand &&
1087           !item->overflow_item && GTK_BIN (item)->child)
1088         {
1089           gint extra = size / n_expand_items;
1090           if (size % n_expand_items != 0)
1091             extra++;
1092
1093           allocations[i].width += extra;
1094           size -= extra;
1095           n_expand_items--;
1096         }
1097     }
1098
1099   g_assert (n_expand_items == 0);
1100   
1101   /* position pack front items */
1102   pos = border_width;
1103   for (list = items, i = 0; list != NULL; list = list->next, ++i)
1104     {
1105       GtkToolItem *item = list->data;
1106       
1107       if (toolbar_item_visible (toolbar, item) && !item->overflow_item && !item->pack_end)
1108         {
1109           allocations[i].x = pos;
1110           allocations[i].y = border_width;
1111           allocations[i].height = short_size;
1112
1113           pos += allocations[i].width;
1114         }
1115     }
1116
1117   /* position pack end items */
1118   pos = available_size + border_width;
1119   for (list = g_list_last (items), i = 0; list != NULL; list = list->prev, ++i)
1120     {
1121       GtkToolItem *item = list->data;
1122       
1123       if (toolbar_item_visible (toolbar, item) && !item->overflow_item && item->pack_end)
1124         {
1125           GtkAllocation *allocation = &(allocations[n_items - i - 1]);
1126
1127           allocation->x = pos - allocation->width;
1128           allocation->y = border_width;
1129           allocation->height = short_size;
1130           
1131           pos -= allocation->width;
1132         }
1133     }
1134
1135   /* position arrow */
1136   if (need_arrow)
1137     {
1138       arrow_allocation.x = pos - arrow_allocation.width;
1139       arrow_allocation.y = border_width;
1140     }
1141   
1142   /* fix up allocations in the vertical or RTL cases */
1143   if (toolbar->orientation == GTK_ORIENTATION_VERTICAL)
1144     {
1145       for (i = 0; i < n_items; ++i)
1146         fixup_allocation_for_vertical (&(allocations[i]));
1147       
1148       if (need_arrow)
1149         fixup_allocation_for_vertical (&arrow_allocation);
1150     }
1151   else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1152     {
1153       for (i = 0; i < n_items; ++i)
1154         fixup_allocation_for_rtl (available_size, &(allocations[i]));
1155
1156       if (need_arrow)
1157         fixup_allocation_for_rtl (available_size, &arrow_allocation);
1158     }
1159   
1160   /* translate the items by allocation->(x,y) */
1161   for (i = 0; i < n_items; ++i)
1162     {
1163       allocations[i].x += allocation->x;
1164       allocations[i].y += allocation->y;
1165     }
1166
1167   if (need_arrow)
1168     {
1169       arrow_allocation.x += allocation->x;
1170       arrow_allocation.y += allocation->y;
1171     }
1172   
1173   /* finally allocate the items */
1174   for (list = items, i = 0; list != NULL; list = list->next, i++)
1175     {
1176       GtkToolItem *item = list->data;
1177       
1178       if (toolbar_item_visible (toolbar, item) && !item->overflow_item)
1179         {
1180           gtk_widget_size_allocate (GTK_WIDGET (item), &(allocations[i]));
1181           gtk_widget_set_child_visible (GTK_WIDGET (item), TRUE);
1182         }
1183       else
1184         {
1185           gtk_widget_set_child_visible (GTK_WIDGET (item), FALSE);
1186         }
1187     }
1188
1189   if (need_arrow)
1190     {
1191       gtk_widget_size_allocate (GTK_WIDGET (priv->arrow_button),
1192                                 &arrow_allocation);
1193       gtk_widget_show (GTK_WIDGET (priv->arrow_button));
1194     }
1195   else
1196     {
1197       gtk_widget_hide (GTK_WIDGET (priv->arrow_button));
1198     }
1199   
1200   g_free (allocations);
1201   g_list_free (items);
1202 }
1203
1204 static void
1205 gtk_toolbar_style_set (GtkWidget *widget,
1206                        GtkStyle  *prev_style)
1207 {
1208   if (GTK_WIDGET_REALIZED (widget))
1209     gtk_style_set_background (widget->style, widget->window, widget->state);
1210
1211   if (prev_style)
1212     gtk_toolbar_update_button_relief (GTK_TOOLBAR (widget));
1213 }
1214
1215 static void 
1216 gtk_toolbar_direction_changed (GtkWidget        *widget,
1217                                GtkTextDirection  previous_dir)
1218 {
1219   GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1220   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1221   
1222   if (toolbar->orientation == GTK_ORIENTATION_VERTICAL)
1223     {
1224       if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1225         gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
1226       else 
1227         gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_LEFT, GTK_SHADOW_NONE);
1228     }
1229
1230   GTK_WIDGET_CLASS (parent_class)->direction_changed (widget, previous_dir);
1231 }
1232
1233 static GList *
1234 gtk_toolbar_list_children_in_focus_order (GtkToolbar       *toolbar,
1235                                           GtkDirectionType  dir)
1236 {
1237   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1238   GList *result = NULL;
1239   GList *list;
1240   gboolean rtl;
1241
1242   /* generate list of children in reverse logical order */
1243   
1244   for (list = priv->items; list != NULL; list = list->next)
1245     {
1246       GtkToolItem *item = list->data;
1247       if (!item->pack_end)
1248         result = g_list_prepend (result, item);
1249     }
1250
1251   for (list = priv->items; list != NULL; list = list->next)
1252     {
1253       GtkToolItem *item = list->data;
1254
1255       if (item->pack_end)
1256         result = g_list_prepend (result, item);
1257     }
1258
1259   result = g_list_prepend (result, priv->arrow_button);
1260
1261   rtl = (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL);
1262   
1263   /* move in logical order when
1264    *
1265    *    - dir is TAB_FORWARD
1266    *
1267    *    - in RTL mode and moving left or up
1268    *
1269    *    - in LTR mode and moving right or down
1270    */
1271   if (dir == GTK_DIR_TAB_FORWARD                                        ||
1272       (rtl  && (dir == GTK_DIR_UP   || dir == GTK_DIR_LEFT))            ||
1273       (!rtl && (dir == GTK_DIR_DOWN || dir == GTK_DIR_RIGHT)))
1274     {
1275       result = g_list_reverse (result);
1276     }
1277
1278   return result;
1279 }
1280
1281 static gboolean
1282 gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
1283                                gboolean    focus_home)
1284 {
1285   GList *children, *list;
1286   GtkDirectionType dir = focus_home? GTK_DIR_RIGHT : GTK_DIR_LEFT;
1287
1288   children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1289
1290   if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1291     {
1292       children = g_list_reverse (children);
1293       
1294       dir = (dir == GTK_DIR_RIGHT)? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1295     }
1296
1297   for (list = children; list != NULL; list = list->next)
1298     {
1299       GtkWidget *child = list->data;
1300       
1301       if (GTK_CONTAINER (toolbar)->focus_child == child)
1302         break;
1303
1304       if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1305         break;
1306     }
1307
1308   g_list_free (children);
1309   
1310   return TRUE;
1311 }   
1312
1313 /* Keybinding handler. This function is called when the user presses
1314  * Ctrl TAB or an arrow key.
1315  */
1316 static gboolean
1317 gtk_toolbar_move_focus (GtkToolbar       *toolbar,
1318                         GtkDirectionType  dir)
1319 {
1320   GList *list;
1321   gboolean try_focus = FALSE;
1322   GList *children;
1323   GtkContainer *container = GTK_CONTAINER (toolbar);
1324
1325   if (container->focus_child &&
1326       gtk_widget_child_focus (container->focus_child, dir))
1327     {
1328       return TRUE;
1329     }
1330   
1331   children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1332
1333   for (list = children; list != NULL; list = list->next)
1334     {
1335       GtkWidget *child = list->data;
1336       
1337       if (try_focus && GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1338         break;
1339
1340       if (child == GTK_CONTAINER (toolbar)->focus_child)
1341         try_focus = TRUE;
1342     }
1343
1344   g_list_free (children);
1345
1346   return TRUE;
1347 }
1348
1349 /* The focus handler for the toolbar. It called when the user presses
1350  * TAB or otherwise tries to focus the toolbar.
1351  */
1352 static gboolean
1353 gtk_toolbar_focus (GtkWidget        *widget,
1354                    GtkDirectionType  dir)
1355 {
1356   GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1357   GList *children, *list;
1358  
1359   /* if focus is already somewhere inside the toolbar then return FALSE.
1360    * The only way focus can stay inside the toolbar is when the user presses
1361    * arrow keys or Ctrl TAB (both of which are handled by the
1362    * gtk_toolbar_move_focus() keybinding function.
1363    */
1364   if (GTK_CONTAINER (widget)->focus_child)
1365     return FALSE;
1366
1367   children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1368
1369   for (list = children; list != NULL; list = list->next)
1370     {
1371       GtkWidget *child = list->data;
1372       
1373       if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1374         return TRUE;
1375     }
1376
1377   g_list_free (children);
1378   
1379   return FALSE;
1380 }
1381
1382 static void
1383 style_change_notify (GtkToolbar *toolbar)
1384 {
1385   if (!toolbar->style_set)
1386     {
1387       /* pretend it was set, then unset, thus reverting to new default */
1388       toolbar->style_set = TRUE; 
1389       gtk_toolbar_unset_style (toolbar);
1390     }
1391 }
1392
1393 static void
1394 icon_size_change_notify (GtkToolbar *toolbar)
1395
1396   if (!toolbar->icon_size_set)
1397     {
1398       /* pretend it was set, then unset, thus reverting to new default */
1399       toolbar->icon_size_set = TRUE; 
1400       gtk_toolbar_unset_icon_size (toolbar);
1401     }
1402 }
1403
1404 static GtkSettings *
1405 toolbar_get_settings (GtkToolbar *toolbar)
1406 {
1407   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1408   return priv->settings;
1409 }
1410
1411 static void
1412 gtk_toolbar_screen_changed (GtkWidget *widget,
1413                             GdkScreen *previous_screen)
1414 {
1415   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
1416   GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1417   GtkSettings *old_settings = toolbar_get_settings (toolbar);
1418   GtkSettings *settings;
1419
1420   if (gtk_widget_has_screen (GTK_WIDGET (toolbar)))
1421     settings = gtk_widget_get_settings (GTK_WIDGET (toolbar));
1422   else
1423     settings = NULL;
1424
1425   if (settings == old_settings)
1426     return;
1427
1428   if (old_settings)
1429     {
1430       g_signal_handler_disconnect (old_settings, toolbar->style_set_connection);
1431       g_signal_handler_disconnect (old_settings, toolbar->icon_size_connection);
1432
1433       g_object_unref (old_settings);
1434     }
1435
1436   if (settings)
1437     {
1438       toolbar->style_set_connection =
1439         g_signal_connect_swapped (settings,
1440                                   "notify::gtk-toolbar-style",
1441                                   G_CALLBACK (style_change_notify),
1442                                   toolbar);
1443       toolbar->icon_size_connection =
1444         g_signal_connect_swapped (settings,
1445                                   "notify::gtk-toolbar-icon-size",
1446                                   G_CALLBACK (icon_size_change_notify),
1447                                   toolbar);
1448
1449       g_object_ref (settings);
1450       priv->settings = settings;
1451     }
1452   else
1453     priv->settings = NULL;
1454
1455   style_change_notify (toolbar);
1456   icon_size_change_notify (toolbar);
1457 }
1458
1459 static void
1460 find_drop_pos (GtkToolbar *toolbar,
1461                gint        x,
1462                gint        y,
1463                gint       *drop_index,
1464                gint       *drop_pos)
1465 {
1466   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1467   GtkOrientation orientation;
1468   GtkTextDirection direction;
1469   GList *items;
1470   GtkToolItem *item;
1471   gint border_width;
1472   gint best_distance, best_pos, best_index, index;
1473
1474   orientation = toolbar->orientation;
1475   direction = gtk_widget_get_direction (GTK_WIDGET (toolbar));
1476   border_width = GTK_CONTAINER (toolbar)->border_width + get_internal_padding (toolbar);
1477
1478   items = priv->items;
1479   if (!items)
1480     {
1481       *drop_index = 0;
1482       if (orientation == GTK_ORIENTATION_HORIZONTAL)
1483         {
1484           if (direction == GTK_TEXT_DIR_LTR) 
1485             *drop_pos = border_width;
1486           else
1487             *drop_pos = GTK_WIDGET (toolbar)->allocation.width - border_width;
1488         }
1489       else
1490         {
1491           *drop_pos = border_width;
1492         }
1493       return;
1494     }
1495
1496   /* initial conditions */
1497   item = GTK_TOOL_ITEM (items->data);
1498   best_index = 0;
1499   if (orientation == GTK_ORIENTATION_HORIZONTAL)
1500     {
1501       if (direction == GTK_TEXT_DIR_LTR)
1502         best_pos = GTK_WIDGET (item)->allocation.x;
1503       else
1504         best_pos = GTK_WIDGET (item)->allocation.x +
1505           GTK_WIDGET (item)->allocation.width;
1506       best_distance = ABS (best_pos - x);
1507     }
1508   else
1509     {
1510       best_pos = GTK_WIDGET (item)->allocation.y;
1511       best_distance = ABS (best_pos - y);
1512     }
1513
1514   index = 0;
1515   while (items)
1516     {
1517       item = GTK_TOOL_ITEM (items->data);
1518       index++;
1519       if (GTK_WIDGET_DRAWABLE (item) && !item->pack_end)
1520         {
1521           gint pos, distance;
1522
1523           if (orientation == GTK_ORIENTATION_HORIZONTAL)
1524             {
1525               if (direction == GTK_TEXT_DIR_LTR)
1526                 pos = GTK_WIDGET (item)->allocation.x +
1527                   GTK_WIDGET (item)->allocation.width;
1528               else
1529                 pos = GTK_WIDGET (item)->allocation.x;
1530               distance = ABS (pos - x);
1531             }
1532           else
1533             {
1534               pos = GTK_WIDGET (item)->allocation.y +
1535                 GTK_WIDGET (item)->allocation.height;
1536               distance = ABS (pos - y);
1537             }
1538           if (distance < best_distance)
1539             {
1540               best_index = index;
1541               best_pos = pos;
1542               best_distance = distance;
1543             }
1544         }
1545       items = items->next;
1546     }
1547   *drop_index = best_index;
1548   *drop_pos = best_pos;
1549 }
1550
1551 static void
1552 gtk_toolbar_drag_leave (GtkWidget      *widget,
1553                         GdkDragContext *context,
1554                         guint           time_)
1555 {
1556   GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1557   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1558
1559   if (priv->drag_highlight)
1560     {
1561       gdk_window_set_user_data (priv->drag_highlight, NULL);
1562       gdk_window_destroy (priv->drag_highlight);
1563       priv->drag_highlight = NULL;
1564     }
1565
1566   priv->drop_index = -1;
1567 }
1568
1569 static gboolean
1570 gtk_toolbar_drag_motion (GtkWidget      *widget,
1571                          GdkDragContext *context,
1572                          gint            x,
1573                          gint            y,
1574                          guint           time_)
1575 {
1576   GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1577   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1578   gint new_index, new_pos;
1579
1580   find_drop_pos(toolbar, x, y, &new_index, &new_pos);
1581
1582   if (!priv->drag_highlight)
1583     {
1584       GdkWindowAttr attributes;
1585       guint attributes_mask;
1586
1587       attributes.window_type = GDK_WINDOW_CHILD;
1588       attributes.wclass = GDK_INPUT_OUTPUT;
1589       attributes.visual = gtk_widget_get_visual (widget);
1590       attributes.colormap = gtk_widget_get_colormap (widget);
1591       attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
1592       attributes.width = 1;
1593       attributes.height = 1;
1594       attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
1595       priv->drag_highlight = gdk_window_new (widget->window,
1596                                              &attributes, attributes_mask);
1597       gdk_window_set_user_data (priv->drag_highlight, widget);
1598       gdk_window_set_background (priv->drag_highlight,
1599                                  &widget->style->fg[widget->state]);
1600     }
1601
1602   if (priv->drop_index < 0 ||
1603       priv->drop_index != new_index)
1604     {
1605       gint border_width = GTK_CONTAINER (toolbar)->border_width;
1606       priv->drop_index = new_index;
1607       if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1608         {
1609           gdk_window_move_resize (priv->drag_highlight,
1610                                   widget->allocation.x + new_pos - 1,
1611                                   widget->allocation.y + border_width,
1612                                   2, widget->allocation.height-border_width*2);
1613         }
1614       else
1615         {
1616           gdk_window_move_resize (priv->drag_highlight,
1617                                   widget->allocation.x + border_width,
1618                                   widget->allocation.y + new_pos - 1,
1619                                   widget->allocation.width-border_width*2, 2);
1620         }
1621     }
1622
1623   gdk_window_show (priv->drag_highlight);
1624
1625   gdk_drag_status (context, context->suggested_action, time_);
1626
1627   return TRUE;
1628 }
1629
1630 static void
1631 gtk_toolbar_get_child_property (GtkContainer *container,
1632                                 GtkWidget    *child,
1633                                 guint         property_id,
1634                                 GValue       *value,
1635                                 GParamSpec   *pspec)
1636 {
1637   GtkToolItem *item = GTK_TOOL_ITEM (child);
1638   
1639   switch (property_id)
1640     {
1641     case CHILD_PROP_PACK_END:
1642       g_value_set_boolean (value, item->pack_end);
1643       break;
1644
1645     case CHILD_PROP_HOMOGENEOUS:
1646       g_value_set_boolean (value, item->homogeneous);
1647       break;
1648
1649     case CHILD_PROP_EXPAND:
1650       g_value_set_boolean (value, item->expand);
1651       break;
1652
1653     default:
1654       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1655       break;
1656     }
1657 }
1658
1659 static void
1660 gtk_toolbar_set_child_property (GtkContainer *container,
1661                                 GtkWidget    *child,
1662                                 guint         property_id,
1663                                 const GValue *value,
1664                                 GParamSpec   *pspec)
1665 {
1666   switch (property_id)
1667     {
1668     case CHILD_PROP_PACK_END:
1669       gtk_tool_item_set_pack_end (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
1670       break;
1671
1672     case CHILD_PROP_HOMOGENEOUS:
1673       gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
1674       break;
1675
1676     case CHILD_PROP_EXPAND:
1677       gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
1678       break;
1679       
1680     default:
1681       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1682       break;
1683     }
1684 }
1685
1686 static void
1687 gtk_toolbar_add (GtkContainer *container,
1688                  GtkWidget    *widget)
1689 {
1690   GtkToolbar *toolbar;
1691   
1692   g_return_if_fail (GTK_IS_TOOLBAR (container));
1693   g_return_if_fail (widget != NULL);
1694
1695   toolbar = GTK_TOOLBAR (container);
1696   
1697   if (GTK_IS_TOOL_ITEM (widget))
1698     gtk_toolbar_insert (toolbar, GTK_TOOL_ITEM (widget), 0);
1699   else
1700     gtk_toolbar_append_widget (toolbar, widget, NULL, NULL);
1701 }
1702
1703 static void
1704 gtk_toolbar_remove (GtkContainer *container,
1705                     GtkWidget    *widget)
1706 {
1707   GtkToolbar *toolbar;
1708   GtkToolItem *item = NULL;
1709   
1710   g_return_if_fail (GTK_IS_TOOLBAR (container));
1711   g_return_if_fail (GTK_IS_WIDGET (widget));
1712
1713   toolbar = GTK_TOOLBAR (container);
1714
1715   if (GTK_IS_TOOL_ITEM (widget))
1716     {
1717       item = GTK_TOOL_ITEM (widget);
1718     }
1719   else
1720     {
1721       GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1722       GList *list;
1723       
1724       for (list = priv->items; list != NULL; list = list->next)
1725         {
1726           if (GTK_BIN (list->data)->child == widget)
1727             {
1728               item = list->data;
1729               break;
1730             }
1731         }
1732     }
1733
1734   g_return_if_fail (item != NULL);
1735
1736   gtk_toolbar_remove_tool_item (GTK_TOOLBAR (container), item);
1737 }
1738
1739 static void
1740 gtk_toolbar_forall (GtkContainer *container,
1741                     gboolean      include_internals,
1742                     GtkCallback   callback,
1743                     gpointer      callback_data)
1744 {
1745   GtkToolbar *toolbar = GTK_TOOLBAR (container);
1746   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1747   GList *items;
1748
1749   g_return_if_fail (callback != NULL);
1750
1751   items = priv->items;
1752       
1753   while (items)
1754     {
1755       GtkToolItem *item = GTK_TOOL_ITEM (items->data);
1756       
1757       items = items->next;
1758       
1759       (*callback) (GTK_WIDGET (item), callback_data);
1760     }
1761   
1762   if (include_internals)
1763     (* callback) (priv->arrow_button, callback_data);
1764 }
1765
1766 static GType
1767 gtk_toolbar_child_type (GtkContainer *container)
1768 {
1769   return GTK_TYPE_TOOL_ITEM;
1770 }
1771
1772 static void
1773 gtk_toolbar_reconfigured (GtkToolbar *toolbar)
1774 {
1775   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1776   GList *items;
1777
1778   items = priv->items;
1779   while (items)
1780     {
1781       GtkToolItem *item = GTK_TOOL_ITEM (items->data);
1782       
1783       gtk_tool_item_toolbar_reconfigured (item);
1784       
1785       items = items->next;
1786     }
1787 }
1788
1789 static void
1790 gtk_toolbar_real_orientation_changed (GtkToolbar    *toolbar,
1791                                       GtkOrientation orientation)
1792 {
1793   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1794   if (toolbar->orientation != orientation)
1795     {
1796       toolbar->orientation = orientation;
1797
1798       if (orientation == GTK_ORIENTATION_HORIZONTAL)
1799         gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1800       else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
1801         gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
1802       else 
1803         gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_LEFT, GTK_SHADOW_NONE);
1804
1805       gtk_toolbar_reconfigured (toolbar);
1806
1807       gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1808       g_object_notify (G_OBJECT (toolbar), "orientation");
1809     }
1810 }
1811
1812 static void
1813 gtk_toolbar_real_style_changed (GtkToolbar     *toolbar,
1814                                 GtkToolbarStyle style)
1815 {
1816   if (toolbar->style != style)
1817     {
1818       toolbar->style = style;
1819
1820       gtk_toolbar_reconfigured (toolbar);
1821
1822       gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1823       g_object_notify (G_OBJECT (toolbar), "toolbar_style");
1824     }
1825 }
1826
1827 static void
1828 menu_position_func (GtkMenu  *menu,
1829                     gint     *x,
1830                     gint     *y,
1831                     gboolean *push_in,
1832                     gpointer  user_data)
1833 {
1834   GtkToolbar *toolbar = GTK_TOOLBAR (user_data);
1835   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1836   GtkRequisition req;
1837   GtkRequisition menu_req;
1838   
1839   gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y);
1840   gtk_widget_size_request (priv->arrow_button, &req);
1841   gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
1842   
1843   if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1844     {
1845       *y += priv->arrow_button->allocation.height;
1846       if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR) 
1847         *x += priv->arrow_button->allocation.width - req.width;
1848       else 
1849         *x += req.width - menu_req.width;
1850     }
1851   else 
1852     {
1853       if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR) 
1854         *x += priv->arrow_button->allocation.width;
1855       else 
1856         *x -= menu_req.width;
1857       *y += priv->arrow_button->allocation.height - req.height;      
1858     }
1859   
1860   *push_in = TRUE;
1861 }
1862
1863 static void
1864 menu_deactivated (GtkWidget  *menu,
1865                   GtkToolbar *toolbar)
1866 {
1867   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1868   
1869   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->arrow_button), FALSE);
1870 }
1871
1872 static void
1873 remove_item (GtkWidget *menu_item,
1874              gpointer   data)
1875 {
1876   gtk_container_remove (GTK_CONTAINER (menu_item->parent), menu_item);
1877 }
1878
1879 static void
1880 show_menu (GtkToolbar     *toolbar,
1881            GdkEventButton *event)
1882 {
1883   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1884   GList *list;
1885   
1886   if (priv->menu)
1887     {
1888       gtk_container_foreach (GTK_CONTAINER (priv->menu), remove_item, NULL);
1889       gtk_widget_destroy (GTK_WIDGET (priv->menu));
1890     }
1891
1892   priv->menu = GTK_MENU (gtk_menu_new ());
1893   g_signal_connect (priv->menu, "deactivate", G_CALLBACK (menu_deactivated), toolbar);
1894
1895   for (list = priv->items; list != NULL; list = list->next)
1896     {
1897       GtkToolItem *item = list->data;
1898
1899       if (toolbar_item_visible (toolbar, item) && item->overflow_item)
1900         {
1901           GtkWidget *menu_item = gtk_tool_item_retrieve_proxy_menu_item (item);
1902
1903           if (menu_item)
1904             {
1905               g_assert (GTK_IS_MENU_ITEM (menu_item));
1906               gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_item);
1907             }
1908         }
1909     }
1910
1911   gtk_widget_show_all (GTK_WIDGET (priv->menu));
1912
1913   gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL,
1914                   menu_position_func, toolbar,
1915                   event? event->button : 0, event? event->time : gtk_get_current_event_time());
1916 }
1917
1918 static void
1919 gtk_toolbar_arrow_button_clicked (GtkWidget  *button,
1920                                   GtkToolbar *toolbar)
1921 {
1922   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);  
1923
1924   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->arrow_button)) &&
1925       (!priv->menu || !GTK_WIDGET_VISIBLE (GTK_WIDGET (priv->menu))))
1926     {
1927       /* We only get here when the button is clicked with the keybaord,
1928        * because mouse button presses result in the menu being shown so
1929        * that priv->menu would be non-NULL and visible.
1930        */
1931       show_menu (toolbar, NULL);
1932       gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menu), FALSE);
1933     }
1934 }
1935
1936 static gboolean
1937 gtk_toolbar_arrow_button_press (GtkWidget      *button,
1938                                 GdkEventButton *event,
1939                                 GtkToolbar     *toolbar)
1940 {
1941   show_menu (toolbar, event);
1942   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
1943  
1944   return TRUE;
1945 }
1946
1947 static gboolean
1948 gtk_toolbar_button_press (GtkWidget      *toolbar,
1949                           GdkEventButton *event)
1950 {
1951   if (event->button == 3)
1952     {
1953       gboolean return_value;
1954     
1955       g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
1956                      (int)event->x_root, (int)event->y_root, event->button,
1957                      &return_value);
1958
1959       return return_value;
1960     }
1961
1962   return FALSE;
1963 }
1964
1965 static gboolean
1966 gtk_toolbar_popup_menu (GtkWidget *toolbar)
1967 {
1968   gboolean return_value;
1969   /* This function is the handler for the "popup menu" keybinding,
1970    * ie., it is called when the user presses Shift F10
1971    */
1972   g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
1973                  -1, -1, -1, &return_value);
1974
1975   return return_value;
1976 }
1977
1978 static void
1979 gtk_toolbar_update_button_relief (GtkToolbar *toolbar)
1980 {
1981   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1982
1983   gtk_toolbar_reconfigured (toolbar);
1984
1985   gtk_button_set_relief (GTK_BUTTON (priv->arrow_button), get_button_relief (toolbar));
1986 }
1987
1988 static GtkReliefStyle
1989 get_button_relief (GtkToolbar *toolbar)
1990 {
1991   GtkReliefStyle button_relief = GTK_RELIEF_NORMAL;
1992
1993   gtk_widget_ensure_style (GTK_WIDGET (toolbar));
1994   
1995   gtk_widget_style_get (GTK_WIDGET (toolbar),
1996                         "button_relief", &button_relief,
1997                         NULL);
1998
1999   return button_relief;
2000 }
2001
2002 static gint
2003 get_space_size (GtkToolbar *toolbar)
2004 {
2005   gint space_size = DEFAULT_SPACE_SIZE;
2006
2007   gtk_widget_style_get (GTK_WIDGET (toolbar),
2008                         "space_size", &space_size,
2009                         NULL);
2010
2011   return space_size;
2012 }
2013
2014 static gint
2015 get_internal_padding (GtkToolbar *toolbar)
2016 {
2017   gint ipadding = 0;
2018
2019   gtk_widget_style_get (GTK_WIDGET (toolbar),
2020                         "internal_padding", &ipadding,
2021                         NULL);
2022
2023   return ipadding;
2024 }
2025
2026 static gboolean
2027 gtk_toolbar_check_old_api (GtkToolbar *toolbar)
2028 {
2029   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2030
2031   if (priv->api_mode == NEW_API)
2032     {
2033       g_warning ("mixing deprecated and non-deprecated GtkToolbar API is not allowed");
2034       return FALSE;
2035     }
2036
2037   priv->api_mode = OLD_API;
2038   return TRUE;
2039 }
2040
2041 static gboolean
2042 gtk_toolbar_check_new_api (GtkToolbar *toolbar)
2043 {
2044   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2045
2046   if (priv->api_mode == OLD_API)
2047     {
2048       g_warning ("mixing deprecated and non-deprecated GtkToolbar API is not allowed");
2049       return FALSE;
2050     }
2051   
2052   priv->api_mode = NEW_API;
2053   return TRUE;
2054 }
2055
2056 static void
2057 gtk_toolbar_insert_tool_item (GtkToolbar  *toolbar,
2058                               GtkToolItem *item,
2059                               gint         pos)
2060 {
2061   GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2062   
2063   priv->items = g_list_insert (priv->items, item, pos);
2064   toolbar->num_children++;
2065
2066   gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar));
2067 }
2068
2069 static void
2070 gtk_toolbar_remove_tool_item (GtkToolbar  *toolbar,
2071                               GtkToolItem *item)
2072 {
2073   GtkToolbarPrivate *priv;
2074   GList *tmp;
2075   gint nth_child;
2076
2077   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2078   priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2079   g_return_if_fail (GTK_IS_TOOL_ITEM (item));
2080   g_return_if_fail (g_list_find (priv->items, item));
2081   
2082   nth_child = 0;
2083
2084   for (tmp = priv->items; tmp != NULL; tmp = tmp->next)
2085     {
2086       if (tmp->data == item)
2087         break;
2088
2089       nth_child++;
2090     }
2091
2092   priv->items = g_list_remove (priv->items, item);
2093
2094   gtk_widget_unparent (GTK_WIDGET (item));
2095
2096   if (priv->api_mode == OLD_API)
2097     {
2098       GtkToolbarChild *toolbar_child;
2099
2100       toolbar_child = g_list_nth_data (toolbar->children, nth_child);
2101       toolbar->children = g_list_remove (toolbar->children, toolbar_child);
2102
2103       g_free (toolbar_child);
2104     }
2105
2106   gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2107 }
2108
2109 GtkWidget *
2110 gtk_toolbar_new (void)
2111 {
2112   GtkToolbar *toolbar;
2113
2114   toolbar = g_object_new (GTK_TYPE_TOOLBAR, NULL);
2115
2116   return GTK_WIDGET (toolbar);
2117 }
2118
2119 void
2120 gtk_toolbar_insert (GtkToolbar  *toolbar,
2121                     GtkToolItem *item,
2122                     gint         pos)
2123 {
2124   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2125   g_return_if_fail (GTK_IS_TOOL_ITEM (item));
2126
2127   if (!gtk_toolbar_check_new_api (toolbar))
2128     return;
2129   
2130   gtk_toolbar_insert_tool_item (toolbar, item, pos);
2131 }
2132
2133 gint
2134 gtk_toolbar_get_item_index (GtkToolbar  *toolbar,
2135                             GtkToolItem *item)
2136 {
2137   GtkToolbarPrivate *priv;
2138
2139   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2140   g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1);
2141
2142   if (!gtk_toolbar_check_new_api (toolbar))
2143     return -1;
2144   
2145   priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2146   g_return_val_if_fail (g_list_find (priv->items, item) != NULL, -1);
2147
2148   return g_list_index (priv->items, item);
2149 }
2150
2151 void
2152 gtk_toolbar_set_orientation (GtkToolbar     *toolbar,
2153                              GtkOrientation  orientation)
2154 {
2155   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2156
2157   g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0, orientation);
2158 }
2159
2160 GtkOrientation
2161 gtk_toolbar_get_orientation (GtkToolbar *toolbar)
2162 {
2163   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
2164
2165   return toolbar->orientation;
2166 }
2167
2168 void
2169 gtk_toolbar_set_style (GtkToolbar      *toolbar,
2170                        GtkToolbarStyle  style)
2171 {
2172   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2173
2174   toolbar->style_set = TRUE;  
2175   g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2176
2177   
2178 }
2179
2180 GtkToolbarStyle
2181 gtk_toolbar_get_style (GtkToolbar *toolbar)
2182 {
2183   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_TOOLBAR_STYLE);
2184
2185   return toolbar->style;
2186 }
2187
2188 void
2189 gtk_toolbar_unset_style (GtkToolbar *toolbar)
2190 {
2191   GtkToolbarStyle style;
2192
2193   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2194
2195   if (toolbar->style_set)
2196     {
2197       GtkSettings *settings = toolbar_get_settings (toolbar);
2198
2199       if (settings)
2200         g_object_get (settings,
2201                       "gtk-toolbar-style", &style,
2202                       NULL);
2203       else
2204         style = DEFAULT_TOOLBAR_STYLE;
2205
2206       if (style != toolbar->style)
2207         g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2208
2209       toolbar->style_set = FALSE;
2210     }
2211 }
2212
2213 void
2214 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
2215                           gboolean    enable)
2216 {
2217   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2218
2219   if (enable)
2220     gtk_tooltips_enable (toolbar->tooltips);
2221   else
2222     gtk_tooltips_disable (toolbar->tooltips);
2223 }
2224
2225 gboolean
2226 gtk_toolbar_get_tooltips (GtkToolbar *toolbar)
2227 {
2228   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2229
2230   return toolbar->tooltips->enabled;
2231 }
2232
2233 gint
2234 gtk_toolbar_get_n_items (GtkToolbar *toolbar)
2235 {
2236   GtkToolbarPrivate *priv;
2237
2238   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2239
2240   if (!gtk_toolbar_check_new_api (toolbar))
2241     return -1;
2242   
2243   priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2244   
2245   return g_list_length (priv->items);
2246 }
2247
2248 /*
2249  * returns NULL if n is out of range
2250  */
2251 GtkToolItem *
2252 gtk_toolbar_get_nth_item (GtkToolbar *toolbar,
2253                           gint        n)
2254 {
2255   GtkToolbarPrivate *priv;
2256
2257   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
2258
2259   if (!gtk_toolbar_check_new_api (toolbar))
2260     return NULL;
2261   
2262   priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2263   
2264   return g_list_nth_data (priv->items, n);
2265 }
2266
2267 void
2268 gtk_toolbar_set_icon_size (GtkToolbar  *toolbar,
2269                            GtkIconSize  icon_size)
2270 {
2271   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2272
2273   toolbar->icon_size_set = TRUE;
2274
2275   if (toolbar->icon_size == icon_size)
2276     return;
2277
2278   toolbar->icon_size = icon_size;
2279
2280   gtk_toolbar_reconfigured (toolbar);
2281
2282   gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2283 }
2284
2285 GtkIconSize
2286 gtk_toolbar_get_icon_size (GtkToolbar *toolbar)
2287 {
2288   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_ICON_SIZE);
2289
2290   return toolbar->icon_size;
2291 }
2292
2293 GtkReliefStyle
2294 gtk_toolbar_get_relief_style (GtkToolbar *toolbar)
2295 {
2296   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_RELIEF_NONE);
2297
2298   return get_button_relief (toolbar);
2299 }
2300
2301 void
2302 gtk_toolbar_unset_icon_size (GtkToolbar *toolbar)
2303 {
2304   GtkIconSize size;
2305
2306   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2307   
2308   if (toolbar->icon_size_set)
2309     {
2310       GtkSettings *settings = toolbar_get_settings (toolbar);
2311
2312       if (settings)
2313         {
2314           g_object_get (settings,
2315                         "gtk-toolbar-icon-size", &size,
2316                         NULL);
2317         }
2318       else
2319         size = DEFAULT_ICON_SIZE;
2320
2321       if (size != toolbar->icon_size)
2322         gtk_toolbar_set_icon_size (toolbar, size);
2323
2324       toolbar->icon_size_set = FALSE;
2325     }
2326 }
2327
2328 void
2329 gtk_toolbar_set_show_arrow (GtkToolbar *toolbar,
2330                             gboolean    show_arrow)
2331 {
2332   GtkToolbarPrivate *priv;
2333   
2334   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2335
2336   priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2337   show_arrow = show_arrow != FALSE;
2338
2339   if (priv->show_arrow != show_arrow)
2340     {
2341       priv->show_arrow = show_arrow;
2342       
2343       if (!priv->show_arrow)
2344         gtk_widget_hide (priv->arrow_button);
2345       
2346       gtk_widget_queue_resize (GTK_WIDGET (toolbar));      
2347       g_object_notify (G_OBJECT (toolbar), "show_arrow");
2348     }
2349 }
2350
2351 gboolean
2352 gtk_toolbar_get_show_arrow (GtkToolbar *toolbar)
2353 {
2354   GtkToolbarPrivate *priv;
2355
2356   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2357
2358   if (!gtk_toolbar_check_new_api (toolbar))
2359     return FALSE;
2360   
2361   priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2362   
2363   return priv->show_arrow;
2364 }
2365
2366 gint
2367 gtk_toolbar_get_drop_index (GtkToolbar *toolbar,
2368                             gint        x,
2369                             gint        y)
2370 {
2371   gint drop_index, drop_pos;
2372
2373   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2374
2375   if (!gtk_toolbar_check_new_api (toolbar))
2376     return -1;
2377   
2378   find_drop_pos (toolbar, x, y, &drop_index, &drop_pos);
2379
2380   return drop_index;
2381 }
2382
2383 GtkWidget *
2384 gtk_toolbar_append_item (GtkToolbar    *toolbar,
2385                          const char    *text,
2386                          const char    *tooltip_text,
2387                          const char    *tooltip_private_text,
2388                          GtkWidget     *icon,
2389                          GtkSignalFunc  callback,
2390                          gpointer       user_data)
2391 {
2392   return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
2393                                      NULL, text,
2394                                      tooltip_text, tooltip_private_text,
2395                                      icon, callback, user_data,
2396                                      toolbar->num_children);
2397 }
2398
2399 GtkWidget *
2400 gtk_toolbar_prepend_item (GtkToolbar    *toolbar,
2401                           const char    *text,
2402                           const char    *tooltip_text,
2403                           const char    *tooltip_private_text,
2404                           GtkWidget     *icon,
2405                           GtkSignalFunc  callback,
2406                           gpointer       user_data)
2407 {
2408   return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
2409                                      NULL, text,
2410                                      tooltip_text, tooltip_private_text,
2411                                      icon, callback, user_data,
2412                                      0);
2413 }
2414
2415 GtkWidget *
2416 gtk_toolbar_insert_item (GtkToolbar    *toolbar,
2417                          const char    *text,
2418                          const char    *tooltip_text,
2419                          const char    *tooltip_private_text,
2420                          GtkWidget     *icon,
2421                          GtkSignalFunc  callback,
2422                          gpointer       user_data,
2423                          gint           position)
2424 {
2425   return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
2426                                      NULL, text,
2427                                      tooltip_text, tooltip_private_text,
2428                                      icon, callback, user_data,
2429                                      position);
2430 }
2431
2432 GtkWidget*
2433 gtk_toolbar_insert_stock (GtkToolbar      *toolbar,
2434                           const gchar     *stock_id,
2435                           const char      *tooltip_text,
2436                           const char      *tooltip_private_text,
2437                           GtkSignalFunc    callback,
2438                           gpointer         user_data,
2439                           gint             position)
2440 {
2441   return gtk_toolbar_internal_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
2442                                               NULL, stock_id,
2443                                               tooltip_text, tooltip_private_text,
2444                                               NULL, callback, user_data,
2445                                               position, TRUE);
2446 }
2447
2448 void
2449 gtk_toolbar_append_space (GtkToolbar *toolbar)
2450 {
2451   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
2452                               NULL, NULL,
2453                               NULL, NULL,
2454                               NULL, NULL, NULL,
2455                               toolbar->num_children);
2456 }
2457
2458 void
2459 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
2460 {
2461   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
2462                               NULL, NULL,
2463                               NULL, NULL,
2464                               NULL, NULL, NULL,
2465                               0);
2466 }
2467
2468 void
2469 gtk_toolbar_insert_space (GtkToolbar *toolbar,
2470                           gint        position)
2471 {
2472   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
2473                               NULL, NULL,
2474                               NULL, NULL,
2475                               NULL, NULL, NULL,
2476                               position);
2477 }
2478
2479 void
2480 gtk_toolbar_remove_space (GtkToolbar *toolbar,
2481                           gint        position)
2482 {
2483   GtkToolItem *item;
2484
2485   g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2486
2487   if (!gtk_toolbar_check_old_api (toolbar))
2488     return;
2489   
2490   item = g_list_nth_data (toolbar->children, position);
2491
2492   if (!item)
2493     {
2494       g_warning ("Toolbar position %d doesn't exist", position);
2495       return;
2496     }
2497
2498   if (GTK_BIN (item)->child)
2499     {
2500       g_warning ("Toolbar position %d is not a space", position);
2501     }
2502
2503   gtk_toolbar_remove_tool_item (toolbar, item);
2504 }
2505
2506 void
2507 gtk_toolbar_append_widget (GtkToolbar  *toolbar,
2508                            GtkWidget   *widget,
2509                            const gchar *tooltip_text,
2510                            const gchar *tooltip_private_text)
2511 {
2512   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
2513                               widget, NULL,
2514                               tooltip_text, tooltip_private_text,
2515                               NULL, NULL, NULL,
2516                               toolbar->num_children);
2517 }
2518
2519 void
2520 gtk_toolbar_prepend_widget (GtkToolbar  *toolbar,
2521                             GtkWidget   *widget,
2522                             const gchar *tooltip_text,
2523                             const gchar *tooltip_private_text)
2524 {
2525   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
2526                               widget, NULL,
2527                               tooltip_text, tooltip_private_text,
2528                               NULL, NULL, NULL,
2529                               0);
2530 }
2531
2532 void
2533 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
2534                            GtkWidget  *widget,
2535                            const char *tooltip_text,
2536                            const char *tooltip_private_text,
2537                            gint        position)
2538 {
2539   gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
2540                               widget, NULL,
2541                               tooltip_text, tooltip_private_text,
2542                               NULL, NULL, NULL,
2543                               position);
2544 }
2545
2546 GtkWidget*
2547 gtk_toolbar_append_element (GtkToolbar          *toolbar,
2548                             GtkToolbarChildType  type,
2549                             GtkWidget           *widget,
2550                             const char          *text,
2551                             const char          *tooltip_text,
2552                             const char          *tooltip_private_text,
2553                             GtkWidget           *icon,
2554                             GtkSignalFunc        callback,
2555                             gpointer             user_data)
2556 {
2557   return gtk_toolbar_insert_element (toolbar, type, widget, text,
2558                                      tooltip_text, tooltip_private_text,
2559                                      icon, callback, user_data,
2560                                      toolbar->num_children);
2561 }
2562
2563 GtkWidget *
2564 gtk_toolbar_prepend_element (GtkToolbar          *toolbar,
2565                              GtkToolbarChildType  type,
2566                              GtkWidget           *widget,
2567                              const char          *text,
2568                              const char          *tooltip_text,
2569                              const char          *tooltip_private_text,
2570                              GtkWidget           *icon,
2571                              GtkSignalFunc        callback,
2572                              gpointer             user_data)
2573 {
2574   return gtk_toolbar_insert_element (toolbar, type, widget, text,
2575                                      tooltip_text, tooltip_private_text,
2576                                      icon, callback, user_data, 0);
2577 }
2578
2579 GtkWidget *
2580 gtk_toolbar_insert_element (GtkToolbar          *toolbar,
2581                             GtkToolbarChildType  type,
2582                             GtkWidget           *widget,
2583                             const char          *text,
2584                             const char          *tooltip_text,
2585                             const char          *tooltip_private_text,
2586                             GtkWidget           *icon,
2587                             GtkSignalFunc        callback,
2588                             gpointer             user_data,
2589                             gint                 position)
2590 {
2591   return gtk_toolbar_internal_insert_element (toolbar, type, widget, text,
2592                                               tooltip_text, tooltip_private_text,
2593                                               icon, callback, user_data, position, FALSE);
2594 }
2595
2596 gchar *
2597 _gtk_toolbar_elide_underscores (const gchar *original)
2598 {
2599   gchar *q, *result;
2600   const gchar *p;
2601   gboolean last_underscore;
2602
2603   q = result = g_malloc (strlen (original) + 1);
2604   last_underscore = FALSE;
2605   
2606   for (p = original; *p; p++)
2607     {
2608       if (!last_underscore && *p == '_')
2609         last_underscore = TRUE;
2610       else
2611         {
2612           last_underscore = FALSE;
2613           *q++ = *p;
2614         }
2615     }
2616   
2617   *q = '\0';
2618   
2619   return result;
2620 }
2621
2622 static GtkWidget *
2623 gtk_toolbar_internal_insert_element (GtkToolbar          *toolbar,
2624                                      GtkToolbarChildType  type,
2625                                      GtkWidget           *widget,
2626                                      const char          *text,
2627                                      const char          *tooltip_text,
2628                                      const char          *tooltip_private_text,
2629                                      GtkWidget           *icon,
2630                                      GtkSignalFunc        callback,
2631                                      gpointer             user_data,
2632                                      gint                 position,
2633                                      gboolean             use_stock)
2634 {
2635   GtkToolbarChild *child;
2636   GtkToolItem *item = NULL;
2637   
2638   g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
2639   
2640   if (!gtk_toolbar_check_old_api (toolbar))
2641     return NULL;
2642   
2643   if (type == GTK_TOOLBAR_CHILD_WIDGET)
2644     g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
2645   else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON)
2646     g_return_val_if_fail (widget == NULL, NULL);
2647
2648   child = g_new (GtkToolbarChild, 1);
2649
2650   child->type = type;
2651   child->icon = NULL;
2652   child->label = NULL;
2653
2654   switch (type)
2655     {
2656     case GTK_TOOLBAR_CHILD_SPACE:
2657       item = gtk_separator_tool_item_new ();
2658       child->widget = NULL;
2659       break;
2660
2661     case GTK_TOOLBAR_CHILD_WIDGET:
2662       item = gtk_tool_item_new ();
2663       child->widget = widget;
2664       gtk_container_add (GTK_CONTAINER (item), child->widget);
2665       break;
2666
2667     case GTK_TOOLBAR_CHILD_BUTTON:
2668       item = gtk_tool_button_new (NULL, NULL);
2669       child->widget = GTK_TOOL_BUTTON (item)->button;
2670       break;
2671       
2672     case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
2673       item = gtk_toggle_tool_button_new ();
2674       child->widget = GTK_TOOL_BUTTON (item)->button;
2675       break;
2676
2677     case GTK_TOOLBAR_CHILD_RADIOBUTTON:
2678       item = gtk_radio_tool_button_new (widget
2679                                         ? gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget))
2680                                         : NULL);
2681       child->widget = GTK_TOOL_BUTTON (item)->button;
2682       break;
2683     }
2684
2685   gtk_widget_show (GTK_WIDGET (item));
2686   
2687   if (type == GTK_TOOLBAR_CHILD_BUTTON ||
2688       type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
2689       type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
2690     {
2691       if (text)
2692         {
2693           if (use_stock)
2694             {
2695               GtkStockItem stock_item;
2696               gchar *label_text;
2697
2698               gtk_tool_button_set_stock_id (GTK_TOOL_BUTTON (item), text);
2699
2700               gtk_stock_lookup (text, &stock_item);
2701               label_text = _gtk_toolbar_elide_underscores (stock_item.label);
2702               child->label = GTK_WIDGET (gtk_label_new (label_text));
2703               g_free (label_text);
2704             }
2705           else
2706             {
2707               child->label = gtk_label_new (text);
2708             }
2709           gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (item), child->label);
2710           gtk_widget_show (child->label);
2711         }
2712
2713       if (icon)
2714         {
2715           child->icon = icon;
2716           gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (item), icon);
2717
2718           /* Applications depend on the toolbar showing the widget for them */
2719           gtk_widget_show (GTK_WIDGET (icon));
2720         }
2721
2722       /*
2723        * We need to connect to the button's clicked callback because some
2724        * programs may rely on that the widget in the callback is a GtkButton
2725        */
2726       if (callback)
2727         g_signal_connect (child->widget, "clicked",
2728                           callback, user_data);
2729     }
2730
2731   if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text)
2732     gtk_tool_item_set_tooltip (item, toolbar->tooltips,
2733                                tooltip_text, tooltip_private_text);
2734   
2735   toolbar->children = g_list_insert (toolbar->children, child, position);
2736
2737   gtk_toolbar_insert_tool_item (toolbar, item, position);
2738
2739   return child->widget;
2740 }
2741
2742 static void
2743 gtk_toolbar_finalize (GObject *object)
2744 {
2745   GList *list;
2746   GtkToolbar *toolbar = GTK_TOOLBAR (object);
2747
2748   if (toolbar->tooltips)
2749     g_object_unref (toolbar->tooltips);
2750
2751   for (list = toolbar->children; list != NULL; list = list->next)
2752     g_free (list->data);
2753
2754   g_list_free (toolbar->children);
2755   
2756   G_OBJECT_CLASS (parent_class)->finalize (object);
2757 }