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