1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 * GtkToolbar copyright (C) Federico Mena
5 * Copyright (C) 2002 Anders Carlsson <andersca@gnome.org>
6 * Copyright (C) 2002 James Henstridge <james@daa.com.au>
7 * Copyright (C) 2003 Soeren Sandmann <sandmann@daimi.au.dk>
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.
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.
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.
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/.
32 #undef GTK_DISABLE_DEPRECATED
35 #include "gtktoolbar.h"
36 #include "gtkradiotoolbutton.h"
37 #include "gtkseparatortoolitem.h"
39 #include "gtkradiobutton.h"
40 #include "gtktoolbar.h"
41 #include "gtkbindings.h"
42 #include <gdk/gdkkeysyms.h>
43 #include "gtkmarshalers.h"
47 #include "gtkprivate.h"
51 #define DEFAULT_IPADDING 0
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
57 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_LARGE_TOOLBAR
58 #define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_BOTH
60 #define MAX_HOMOGENEOUS_N_CHARS 13 /* Items that are wider than this do not participate
61 * in the homogeneous game. In units of
62 * pango_font_get_estimated_char_width().
75 CHILD_PROP_HOMOGENEOUS
87 static void gtk_toolbar_init (GtkToolbar *toolbar);
88 static void gtk_toolbar_class_init (GtkToolbarClass *klass);
90 static void gtk_toolbar_set_property (GObject *object,
94 static void gtk_toolbar_get_property (GObject *object,
99 static gint gtk_toolbar_expose (GtkWidget *widget,
100 GdkEventExpose *event);
101 static void gtk_toolbar_realize (GtkWidget *widget);
102 static void gtk_toolbar_unrealize (GtkWidget *widget);
103 static void gtk_toolbar_size_request (GtkWidget *widget,
104 GtkRequisition *requisition);
105 static void gtk_toolbar_size_allocate (GtkWidget *widget,
106 GtkAllocation *allocation);
107 static void gtk_toolbar_style_set (GtkWidget *widget,
108 GtkStyle *prev_style);
109 static void gtk_toolbar_direction_changed (GtkWidget *widget,
110 GtkTextDirection previous_direction);
111 static gboolean gtk_toolbar_focus (GtkWidget *widget,
112 GtkDirectionType dir);
113 static void gtk_toolbar_screen_changed (GtkWidget *widget,
114 GdkScreen *previous_screen);
115 static void gtk_toolbar_map (GtkWidget *widget);
116 static void gtk_toolbar_unmap (GtkWidget *widget);
118 static void gtk_toolbar_set_child_property (GtkContainer *container,
123 static void gtk_toolbar_get_child_property (GtkContainer *container,
128 static void gtk_toolbar_finalize (GObject *object);
131 static void gtk_toolbar_add (GtkContainer *container,
133 static void gtk_toolbar_remove (GtkContainer *container,
135 static void gtk_toolbar_forall (GtkContainer *container,
136 gboolean include_internals,
137 GtkCallback callback,
138 gpointer callback_data);
139 static GType gtk_toolbar_child_type (GtkContainer *container);
141 static void gtk_toolbar_real_orientation_changed (GtkToolbar *toolbar,
142 GtkOrientation orientation);
143 static void gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
144 GtkToolbarStyle style);
146 static gboolean gtk_toolbar_move_focus (GtkToolbar *toolbar,
147 GtkDirectionType dir);
148 static gboolean gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
149 gboolean focus_home);
151 static gboolean gtk_toolbar_button_press (GtkWidget *toolbar,
152 GdkEventButton *event);
153 static gboolean gtk_toolbar_arrow_button_press (GtkWidget *button,
154 GdkEventButton *event,
155 GtkToolbar *toolbar);
156 static void gtk_toolbar_arrow_button_clicked (GtkWidget *button,
157 GtkToolbar *toolbar);
158 static void gtk_toolbar_update_button_relief (GtkToolbar *toolbar);
159 static GtkReliefStyle get_button_relief (GtkToolbar *toolbar);
160 static gint get_internal_padding (GtkToolbar *toolbar);
161 static GtkShadowType get_shadow_type (GtkToolbar *toolbar);
162 static void gtk_toolbar_remove_tool_item (GtkToolbar *toolbar,
164 static gboolean gtk_toolbar_popup_menu (GtkWidget *toolbar);
166 static GtkWidget *gtk_toolbar_internal_insert_element (GtkToolbar *toolbar,
167 GtkToolbarChildType type,
170 const char *tooltip_text,
171 const char *tooltip_private_text,
173 GtkSignalFunc callback,
178 typedef struct _ToolbarContent ToolbarContent;
180 static ToolbarContent *gtk_toolbar_insert_tool_item (GtkToolbar *toolbar,
183 gboolean is_placeholder);
185 static gboolean gtk_toolbar_check_new_api (GtkToolbar *toolbar);
193 #define GTK_TOOLBAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_TOOLBAR, GtkToolbarPrivate))
202 struct _ToolbarContent
205 guint is_placeholder : 1;
206 guint disappearing : 1;
207 GtkAllocation start_allocation;
208 GtkAllocation goal_allocation;
212 struct _GtkToolbarPrivate
217 GtkWidget * arrow_button;
223 GdkWindow * event_window;
225 GtkSettings * settings;
228 GtkToolItem * highlight_tool_item;
229 gint max_homogeneous_pixels;
235 static GtkContainerClass *parent_class = NULL;
236 static guint toolbar_signals [LAST_SIGNAL] = { 0 };
239 gtk_toolbar_get_type (void)
241 static GtkType type = 0;
245 static const GTypeInfo type_info =
247 sizeof (GtkToolbarClass),
248 (GBaseInitFunc) NULL,
249 (GBaseFinalizeFunc) NULL,
250 (GClassInitFunc) gtk_toolbar_class_init,
251 (GClassFinalizeFunc) NULL,
255 (GInstanceInitFunc) gtk_toolbar_init,
258 type = g_type_register_static (GTK_TYPE_CONTAINER,
267 add_arrow_bindings (GtkBindingSet *binding_set,
269 GtkDirectionType dir)
271 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
273 gtk_binding_entry_add_signal (binding_set, keysym, 0,
275 GTK_TYPE_DIRECTION_TYPE, dir);
276 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
278 GTK_TYPE_DIRECTION_TYPE, dir);
282 add_ctrl_tab_bindings (GtkBindingSet *binding_set,
283 GdkModifierType modifiers,
284 GtkDirectionType direction)
286 gtk_binding_entry_add_signal (binding_set,
287 GDK_Tab, GDK_CONTROL_MASK | modifiers,
289 GTK_TYPE_DIRECTION_TYPE, direction);
290 gtk_binding_entry_add_signal (binding_set,
291 GDK_KP_Tab, GDK_CONTROL_MASK | modifiers,
293 GTK_TYPE_DIRECTION_TYPE, direction);
297 gtk_toolbar_class_init (GtkToolbarClass *klass)
299 GObjectClass *gobject_class;
300 GtkWidgetClass *widget_class;
301 GtkContainerClass *container_class;
302 GtkBindingSet *binding_set;
304 parent_class = g_type_class_peek_parent (klass);
306 gobject_class = (GObjectClass *)klass;
307 widget_class = (GtkWidgetClass *)klass;
308 container_class = (GtkContainerClass *)klass;
310 gobject_class->set_property = gtk_toolbar_set_property;
311 gobject_class->get_property = gtk_toolbar_get_property;
312 gobject_class->finalize = gtk_toolbar_finalize;
314 widget_class->button_press_event = gtk_toolbar_button_press;
315 widget_class->expose_event = gtk_toolbar_expose;
316 widget_class->size_request = gtk_toolbar_size_request;
317 widget_class->size_allocate = gtk_toolbar_size_allocate;
318 widget_class->style_set = gtk_toolbar_style_set;
319 widget_class->direction_changed = gtk_toolbar_direction_changed;
320 widget_class->focus = gtk_toolbar_focus;
321 widget_class->screen_changed = gtk_toolbar_screen_changed;
322 widget_class->realize = gtk_toolbar_realize;
323 widget_class->unrealize = gtk_toolbar_unrealize;
324 widget_class->map = gtk_toolbar_map;
325 widget_class->unmap = gtk_toolbar_unmap;
326 widget_class->popup_menu = gtk_toolbar_popup_menu;
328 container_class->add = gtk_toolbar_add;
329 container_class->remove = gtk_toolbar_remove;
330 container_class->forall = gtk_toolbar_forall;
331 container_class->child_type = gtk_toolbar_child_type;
332 container_class->get_child_property = gtk_toolbar_get_child_property;
333 container_class->set_child_property = gtk_toolbar_set_child_property;
335 klass->orientation_changed = gtk_toolbar_real_orientation_changed;
336 klass->style_changed = gtk_toolbar_real_style_changed;
339 * GtkToolbar::orientation-changed:
340 * @toolbar: the object which emitted the signal
341 * @orientation: the new #GtkOrientation of the toolbar
343 * Emitted when the orientation of the toolbar changes.
345 toolbar_signals[ORIENTATION_CHANGED] =
346 g_signal_new ("orientation-changed",
347 G_OBJECT_CLASS_TYPE (klass),
349 G_STRUCT_OFFSET (GtkToolbarClass, orientation_changed),
351 g_cclosure_marshal_VOID__ENUM,
353 GTK_TYPE_ORIENTATION);
355 * GtkToolbar::style-changed:
356 * @toolbar: The #GtkToolbar which emitted the signal
357 * @style: the new #GtkToolbarStyle of the toolbar
359 * Emitted when the style of the toolbar changes.
361 toolbar_signals[STYLE_CHANGED] =
362 g_signal_new ("style-changed",
363 G_OBJECT_CLASS_TYPE (klass),
365 G_STRUCT_OFFSET (GtkToolbarClass, style_changed),
367 g_cclosure_marshal_VOID__ENUM,
369 GTK_TYPE_TOOLBAR_STYLE);
371 * GtkToolbar::popup-context-menu:
372 * @toolbar: the #GtkToolbar which emitted the signal
373 * @x: the x coordinate of the point where the menu should appear
374 * @y: the y coordinate of the point where the menu should appear
375 * @button: the mouse button the user pressed, or -1
377 * Emitted when the user right-clicks the toolbar or uses the
378 * keybinding to display a popup menu.
380 * Application developers should handle this signal if they want
381 * to display a context menu on the toolbar. The context-menu should
382 * appear at the coordinates given by @x and @y. The mouse button
383 * number is given by the @button parameter. If the menu was popped
384 * up using the keybaord, @button is -1.
386 * Return value: return %TRUE if the signal was handled, %FALSE if not
388 toolbar_signals[POPUP_CONTEXT_MENU] =
389 g_signal_new ("popup_context_menu",
390 G_OBJECT_CLASS_TYPE (klass),
392 G_STRUCT_OFFSET (GtkToolbarClass, popup_context_menu),
393 _gtk_boolean_handled_accumulator, NULL,
394 _gtk_marshal_BOOLEAN__INT_INT_INT,
396 G_TYPE_INT, G_TYPE_INT,
399 * GtkToolbar::move-focus:
400 * @toolbar: the #GtkToolbar which emitted the signal
401 * @dir: a #GtkDirection
403 * A keybinding signal used internally by GTK+. This signal can't
404 * be used in application code.
406 * Return value: %TRUE if the signal was handled, %FALSE if not
408 toolbar_signals[MOVE_FOCUS] =
409 _gtk_binding_signal_new ("move_focus",
410 G_TYPE_FROM_CLASS (klass),
411 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
412 G_CALLBACK (gtk_toolbar_move_focus),
414 _gtk_marshal_BOOLEAN__ENUM,
416 GTK_TYPE_DIRECTION_TYPE);
418 * GtkToolbar::focus-home-or-end:
419 * @toolbar: the #GtkToolbar which emitted the signal
420 * @focus_home: %TRUE if the first item should be focused
422 * A keybinding signal used internally by GTK+. This signal can't
423 * be used in application code
425 * Return value: %TRUE if the signal was handled, %FALSE if not
427 toolbar_signals[FOCUS_HOME_OR_END] =
428 _gtk_binding_signal_new ("focus_home_or_end",
429 G_OBJECT_CLASS_TYPE (klass),
430 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
431 G_CALLBACK (gtk_toolbar_focus_home_or_end),
433 _gtk_marshal_BOOLEAN__BOOLEAN,
438 g_object_class_install_property (gobject_class,
440 g_param_spec_enum ("orientation",
442 _("The orientation of the toolbar"),
443 GTK_TYPE_ORIENTATION,
444 GTK_ORIENTATION_HORIZONTAL,
447 g_object_class_install_property (gobject_class,
449 g_param_spec_enum ("toolbar_style",
451 _("How to draw the toolbar"),
452 GTK_TYPE_TOOLBAR_STYLE,
455 g_object_class_install_property (gobject_class,
457 g_param_spec_boolean ("show_arrow",
459 _("If an arrow should be shown if the toolbar doesn't fit"),
463 /* child properties */
464 gtk_container_class_install_child_property (container_class,
466 g_param_spec_boolean ("expand",
468 _("Whether the item should receive extra space when the toolbar grows"),
472 gtk_container_class_install_child_property (container_class,
473 CHILD_PROP_HOMOGENEOUS,
474 g_param_spec_boolean ("homogeneous",
476 _("Whether the item should be the same size as other homogeneous items"),
480 /* style properties */
481 gtk_widget_class_install_style_property (widget_class,
482 g_param_spec_int ("space_size",
484 _("Size of spacers"),
490 gtk_widget_class_install_style_property (widget_class,
491 g_param_spec_int ("internal_padding",
492 _("Internal padding"),
493 _("Amount of border space between the toolbar shadow and the buttons"),
499 gtk_widget_class_install_style_property (widget_class,
500 g_param_spec_enum ("space_style",
502 _("Whether spacers are vertical lines or just blank"),
503 GTK_TYPE_TOOLBAR_SPACE_STYLE,
507 gtk_widget_class_install_style_property (widget_class,
508 g_param_spec_enum ("button_relief",
510 _("Type of bevel around toolbar buttons"),
511 GTK_TYPE_RELIEF_STYLE,
514 gtk_widget_class_install_style_property (widget_class,
515 g_param_spec_enum ("shadow_type",
517 _("Style of bevel around the toolbar"),
518 GTK_TYPE_SHADOW_TYPE,
522 gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-style",
524 _("Whether default toolbars have text only, text and icons, icons only, etc."),
525 GTK_TYPE_TOOLBAR_STYLE,
526 DEFAULT_TOOLBAR_STYLE,
529 gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-icon-size",
530 _("Toolbar icon size"),
531 _("Size of icons in default toolbars"),
536 binding_set = gtk_binding_set_by_class (klass);
538 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
539 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
540 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
541 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
543 gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
544 "focus_home_or_end", 1,
545 G_TYPE_BOOLEAN, TRUE);
546 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
547 "focus_home_or_end", 1,
548 G_TYPE_BOOLEAN, TRUE);
549 gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
550 "focus_home_or_end", 1,
551 G_TYPE_BOOLEAN, FALSE);
552 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
553 "focus_home_or_end", 1,
554 G_TYPE_BOOLEAN, FALSE);
556 add_ctrl_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
557 add_ctrl_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
559 g_type_class_add_private (gobject_class, sizeof (GtkToolbarPrivate));
563 gtk_toolbar_init (GtkToolbar *toolbar)
565 GtkToolbarPrivate *priv;
567 GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS);
568 GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
570 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
572 toolbar->orientation = GTK_ORIENTATION_HORIZONTAL;
573 toolbar->style = DEFAULT_TOOLBAR_STYLE;
574 toolbar->icon_size = DEFAULT_ICON_SIZE;
575 toolbar->tooltips = gtk_tooltips_new ();
576 g_object_ref (toolbar->tooltips);
577 gtk_object_sink (GTK_OBJECT (toolbar->tooltips));
579 priv->arrow_button = gtk_toggle_button_new ();
580 g_signal_connect (priv->arrow_button, "button_press_event",
581 G_CALLBACK (gtk_toolbar_arrow_button_press), toolbar);
582 g_signal_connect (priv->arrow_button, "clicked",
583 G_CALLBACK (gtk_toolbar_arrow_button_clicked), toolbar);
584 gtk_button_set_relief (GTK_BUTTON (priv->arrow_button),
585 get_button_relief (toolbar));
587 priv->api_mode = DONT_KNOW;
589 gtk_button_set_focus_on_click (GTK_BUTTON (priv->arrow_button), FALSE);
591 priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
592 gtk_widget_set_name (priv->arrow, "gtk-toolbar-arrow");
593 gtk_widget_show (priv->arrow);
594 gtk_container_add (GTK_CONTAINER (priv->arrow_button), priv->arrow);
596 gtk_widget_set_parent (priv->arrow_button, GTK_WIDGET (toolbar));
598 /* which child position a drop will occur at */
600 priv->show_arrow = TRUE;
601 priv->settings = NULL;
603 priv->max_homogeneous_pixels = -1;
605 priv->timer = g_timer_new ();
609 toolbar_item_visible (GtkToolbar *toolbar,
612 if (GTK_WIDGET_VISIBLE (item) &&
613 ((toolbar->orientation == GTK_ORIENTATION_HORIZONTAL &&
614 gtk_tool_item_get_visible_horizontal (item)) ||
615 (toolbar->orientation == GTK_ORIENTATION_VERTICAL &&
616 gtk_tool_item_get_visible_vertical (item))))
618 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
620 /* With the old toolbar you could hide a button by calling gtk_widget_hide()
621 * on it. This doesn't work with the new API because the GtkToolItem will not be
624 if (priv->api_mode == OLD_API)
626 GtkWidget *bin_child = GTK_BIN (item)->child;
628 if (bin_child && !GTK_WIDGET_VISIBLE (bin_child))
639 calculate_max_homogeneous_pixels (GtkWidget *widget)
641 PangoContext *context;
642 PangoFontMetrics *metrics;
645 context = gtk_widget_get_pango_context (widget);
646 metrics = pango_context_get_metrics (context,
647 widget->style->font_desc,
648 pango_context_get_language (context));
649 char_width = pango_font_metrics_get_approximate_char_width (metrics);
650 pango_font_metrics_unref (metrics);
652 return PANGO_PIXELS (MAX_HOMOGENEOUS_N_CHARS * char_width);
656 toolbar_item_is_homogeneous (GtkToolbar *toolbar,
660 GtkRequisition requisition;
661 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
663 if (priv->max_homogeneous_pixels < 0)
665 priv->max_homogeneous_pixels =
666 calculate_max_homogeneous_pixels (GTK_WIDGET (toolbar));
669 result = gtk_tool_item_get_homogeneous (item) &&
670 !GTK_IS_SEPARATOR_TOOL_ITEM (item);
672 gtk_widget_size_request (GTK_WIDGET (item), &requisition);
674 if ((gtk_tool_item_get_is_important (item) &&
675 toolbar->style == GTK_TOOLBAR_BOTH_HORIZ &&
676 toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) ||
677 requisition.width > priv->max_homogeneous_pixels)
686 gtk_toolbar_set_property (GObject *object,
691 GtkToolbar *toolbar = GTK_TOOLBAR (object);
695 case PROP_ORIENTATION:
696 gtk_toolbar_set_orientation (toolbar, g_value_get_enum (value));
698 case PROP_TOOLBAR_STYLE:
699 gtk_toolbar_set_style (toolbar, g_value_get_enum (value));
701 case PROP_SHOW_ARROW:
702 gtk_toolbar_set_show_arrow (toolbar, g_value_get_boolean (value));
705 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
711 gtk_toolbar_get_property (GObject *object,
716 GtkToolbar *toolbar = GTK_TOOLBAR (object);
717 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
721 case PROP_ORIENTATION:
722 g_value_set_enum (value, toolbar->orientation);
724 case PROP_TOOLBAR_STYLE:
725 g_value_set_enum (value, toolbar->style);
727 case PROP_SHOW_ARROW:
728 g_value_set_boolean (value, priv->show_arrow);
731 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
737 gtk_toolbar_map (GtkWidget *widget)
739 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
741 GTK_WIDGET_CLASS (parent_class)->map (widget);
743 if (priv->event_window)
744 gdk_window_show_unraised (priv->event_window);
748 gtk_toolbar_unmap (GtkWidget *widget)
750 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
752 if (priv->event_window)
753 gdk_window_hide (priv->event_window);
755 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
759 gtk_toolbar_realize (GtkWidget *widget)
761 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
762 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
764 GdkWindowAttr attributes;
765 gint attributes_mask;
768 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
770 border_width = GTK_CONTAINER (widget)->border_width;
772 attributes.wclass = GDK_INPUT_ONLY;
773 attributes.window_type = GDK_WINDOW_CHILD;
774 attributes.x = widget->allocation.x + border_width;
775 attributes.y = widget->allocation.y + border_width;
776 attributes.width = widget->allocation.width - border_width * 2;
777 attributes.height = widget->allocation.height - border_width * 2;
778 attributes.event_mask = gtk_widget_get_events (widget);
779 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
780 GDK_BUTTON_RELEASE_MASK |
781 GDK_ENTER_NOTIFY_MASK |
782 GDK_LEAVE_NOTIFY_MASK);
784 attributes_mask = GDK_WA_X | GDK_WA_Y;
786 widget->window = gtk_widget_get_parent_window (widget);
787 g_object_ref (widget->window);
788 widget->style = gtk_style_attach (widget->style, widget->window);
790 priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
791 &attributes, attributes_mask);
792 gdk_window_set_user_data (priv->event_window, toolbar);
796 gtk_toolbar_unrealize (GtkWidget *widget)
798 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
800 if (priv->event_window)
802 gdk_window_set_user_data (priv->event_window, NULL);
803 gdk_window_destroy (priv->event_window);
804 priv->event_window = NULL;
807 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
808 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
812 gtk_toolbar_expose (GtkWidget *widget,
813 GdkEventExpose *event)
815 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
816 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
821 border_width = GTK_CONTAINER (widget)->border_width;
823 if (GTK_WIDGET_DRAWABLE (widget))
825 gtk_paint_box (widget->style,
827 GTK_WIDGET_STATE (widget),
828 get_shadow_type (toolbar),
829 &event->area, widget, "toolbar",
830 border_width + widget->allocation.x,
831 border_width + widget->allocation.y,
832 widget->allocation.width - 2 * border_width,
833 widget->allocation.height - 2 * border_width);
836 for (list = priv->content; list != NULL; list = list->next)
838 ToolbarContent *content = list->data;
839 GtkToolItem *item = content->item;
841 if (!content->is_placeholder)
842 gtk_container_propagate_expose (GTK_CONTAINER (widget),
847 gtk_container_propagate_expose (GTK_CONTAINER (widget),
855 gtk_toolbar_size_request (GtkWidget *widget,
856 GtkRequisition *requisition)
858 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
859 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
861 gint max_child_height;
862 gint max_child_width;
863 gint max_homogeneous_child_width;
864 gint max_homogeneous_child_height;
865 gint homogeneous_size;
867 gint pack_front_size;
869 GtkRequisition arrow_requisition;
871 max_homogeneous_child_width = 0;
872 max_homogeneous_child_height = 0;
874 max_child_height = 0;
875 for (list = priv->content; list != NULL; list = list->next)
877 GtkRequisition requisition;
878 ToolbarContent *content = list->data;
879 GtkToolItem *item = content->item;
881 if (!toolbar_item_visible (toolbar, item))
884 gtk_widget_size_request (GTK_WIDGET (item), &requisition);
886 max_child_width = MAX (max_child_width, requisition.width);
887 max_child_height = MAX (max_child_height, requisition.height);
889 if (toolbar_item_is_homogeneous (toolbar, item))
891 max_homogeneous_child_width = MAX (max_homogeneous_child_width, requisition.width);
892 max_homogeneous_child_height = MAX (max_homogeneous_child_height, requisition.height);
896 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
897 homogeneous_size = max_homogeneous_child_width;
899 homogeneous_size = max_homogeneous_child_height;
902 for (list = priv->content; list != NULL; list = list->next)
904 ToolbarContent *content = list->data;
905 GtkToolItem *item = content->item;
908 if (!toolbar_item_visible (toolbar, item))
911 if (toolbar_item_is_homogeneous (toolbar, item))
913 size = homogeneous_size;
917 GtkRequisition requisition;
919 gtk_widget_size_request (GTK_WIDGET (item), &requisition);
921 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
922 size = requisition.width;
924 size = requisition.height;
927 pack_front_size += size;
930 if (priv->show_arrow && priv->api_mode == NEW_API)
932 gtk_widget_size_request (priv->arrow_button, &arrow_requisition);
934 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
935 long_req = arrow_requisition.width;
937 long_req = arrow_requisition.height;
939 /* There is no point requesting space for the arrow if that would take
940 * up more space than all the items combined
942 long_req = MIN (long_req, pack_front_size);
946 arrow_requisition.height = 0;
947 arrow_requisition.width = 0;
949 long_req = pack_front_size;
952 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
954 requisition->width = long_req;
955 requisition->height = MAX (max_child_height, arrow_requisition.height);
959 requisition->height = long_req;
960 requisition->width = MAX (max_child_width, arrow_requisition.width);
964 ipadding = get_internal_padding (toolbar);
966 requisition->width += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width);
967 requisition->height += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width);
969 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
971 requisition->width += 2 * widget->style->xthickness;
972 requisition->height += 2 * widget->style->ythickness;
975 toolbar->button_maxw = max_homogeneous_child_width;
976 toolbar->button_maxh = max_homogeneous_child_height;
979 #define SLIDE_SPEED 600 /* pixels per second */
982 position (gint from, gint to, gdouble elapsed)
985 return MIN (from + SLIDE_SPEED * elapsed, to);
987 return MAX (from - SLIDE_SPEED * elapsed, to);
991 compute_intermediate_allocation (GtkToolbar *toolbar,
992 const GtkAllocation *start,
993 const GtkAllocation *goal,
994 GtkAllocation *intermediate)
996 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
997 gdouble elapsed = g_timer_elapsed (priv->timer, NULL);
999 intermediate->x = position (start->x, goal->x, elapsed);
1000 intermediate->y = position (start->y, goal->y, elapsed);
1001 intermediate->width =
1002 position (start->x + start->width, goal->x + goal->width, elapsed) - intermediate->x;
1003 intermediate->height =
1004 position (start->y + start->height, goal->y + goal->height, elapsed) - intermediate->y;
1008 fixup_allocation_for_rtl (gint total_size,
1009 GtkAllocation *allocation)
1011 allocation->x += (total_size - (2 * allocation->x + allocation->width));
1015 fixup_allocation_for_vertical (GtkAllocation *allocation)
1019 tmp = allocation->x;
1020 allocation->x = allocation->y;
1021 allocation->y = tmp;
1023 tmp = allocation->width;
1024 allocation->width = allocation->height;
1025 allocation->height = tmp;
1029 get_item_size (GtkToolbar *toolbar,
1030 ToolbarContent *content)
1032 GtkRequisition requisition;
1033 GtkToolItem *item = content->item;
1035 gtk_widget_get_child_requisition (GTK_WIDGET (item), &requisition);
1037 if (content->is_placeholder && content->disappearing)
1041 else if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1043 if (toolbar_item_is_homogeneous (toolbar, item))
1044 return toolbar->button_maxw;
1046 return requisition.width;
1050 if (toolbar_item_is_homogeneous (toolbar, item))
1051 return toolbar->button_maxh;
1053 return requisition.height;
1058 slide_idle_handler (gpointer data)
1060 GtkToolbar *toolbar = data;
1061 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1064 if (priv->need_sync)
1067 priv->need_sync = FALSE;
1070 for (list = priv->content; list != NULL; list = list->next)
1072 ToolbarContent *content = list->data;
1073 GtkWidget *widget = GTK_WIDGET (content->item);
1075 if ((content->state == NOT_ALLOCATED) ||
1076 (content->state == NORMAL &&
1077 GTK_WIDGET_CHILD_VISIBLE (content->item) &&
1078 ((content->goal_allocation.x != widget->allocation.x ||
1079 content->goal_allocation.y != widget->allocation.y ||
1080 content->goal_allocation.width != widget->allocation.width ||
1081 content->goal_allocation.height != widget->allocation.height))) ||
1082 (content->is_placeholder && content->disappearing &&
1083 GTK_WIDGET_CHILD_VISIBLE (content->item)))
1085 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1090 priv->is_sliding = FALSE;
1097 rect_within (GtkAllocation *a1, GtkAllocation *a2)
1099 return (a1->x >= a2->x &&
1100 a1->x + a1->width <= a2->x + a2->width &&
1102 a1->y + a1->height <= a2->y + a2->height);
1106 gtk_toolbar_begin_sliding (GtkToolbar *toolbar)
1108 GtkWidget *widget = GTK_WIDGET (toolbar);
1109 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1117 /* Start the sliding. This function copies the allocation of every
1118 * item into content->start_allocation. For items that haven't
1119 * been allocated yet, we calculate their position and save that
1120 * in start_allocatino along with zero width and zero height.
1122 priv->is_sliding = TRUE;
1125 priv->idle_id = g_idle_add (slide_idle_handler, toolbar);
1127 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1128 vertical = (toolbar->orientation == GTK_ORIENTATION_VERTICAL);
1129 border_width = get_internal_padding (toolbar) + GTK_CONTAINER (toolbar)->border_width;
1133 cur_x = widget->allocation.width - border_width - widget->style->xthickness;
1134 cur_y = widget->allocation.height - border_width - widget->style->ythickness;
1138 cur_x = border_width + widget->style->xthickness;
1139 cur_y = border_width + widget->style->ythickness;
1142 cur_x += widget->allocation.x;
1143 cur_y += widget->allocation.y;
1145 for (list = priv->content; list != NULL; list = list->next)
1147 ToolbarContent *content = list->data;
1148 GtkWidget *item = GTK_WIDGET (content->item);
1149 GtkAllocation *alloc = &(content->start_allocation);
1151 if (content->state == NORMAL && rect_within (&(item->allocation), &(widget->allocation)))
1153 *alloc = item->allocation;
1162 alloc->width = widget->allocation.width -
1163 2 * border_width - 2 * widget->style->xthickness;
1169 alloc->height = widget->allocation.height -
1170 2 * border_width - 2 * widget->style->ythickness;
1175 cur_y = alloc->y + alloc->height;
1179 cur_x = alloc->x + alloc->width;
1182 g_timer_reset (priv->timer);
1186 gtk_toolbar_stop_sliding (GtkToolbar *toolbar)
1188 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1190 if (priv->is_sliding)
1194 priv->is_sliding = FALSE;
1198 g_source_remove (priv->idle_id);
1202 list = priv->content;
1205 ToolbarContent *content = list->data;
1208 if (content->is_placeholder)
1209 gtk_toolbar_remove_tool_item (toolbar, content->item);
1212 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1217 gtk_toolbar_size_allocate (GtkWidget *widget,
1218 GtkAllocation *allocation)
1220 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1221 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1222 GtkAllocation *allocations;
1223 ItemState *new_states;
1224 GtkAllocation arrow_allocation;
1226 gint size, pos, short_size;
1229 gboolean need_arrow;
1230 gint n_expand_items;
1232 gint available_size;
1235 GtkRequisition arrow_requisition;
1236 gboolean overflowing;
1237 gboolean size_changed;
1240 size_changed = FALSE;
1241 if (widget->allocation.x != allocation->x ||
1242 widget->allocation.y != allocation->y ||
1243 widget->allocation.width != allocation->width ||
1244 widget->allocation.height != allocation->height)
1246 size_changed = TRUE;
1250 gtk_toolbar_stop_sliding (toolbar);
1252 widget->allocation = *allocation;
1254 border_width = GTK_CONTAINER (toolbar)->border_width;
1256 if (GTK_WIDGET_REALIZED (widget))
1258 gdk_window_move_resize (priv->event_window,
1259 allocation->x + border_width,
1260 allocation->y + border_width,
1261 allocation->width - border_width * 2,
1262 allocation->height - border_width * 2);
1265 border_width += get_internal_padding (toolbar);
1267 gtk_widget_get_child_requisition (GTK_WIDGET (priv->arrow_button),
1268 &arrow_requisition);
1270 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1272 available_size = size = allocation->width - 2 * border_width;
1273 short_size = allocation->height - 2 * border_width;
1274 arrow_size = arrow_requisition.width;
1276 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1278 available_size -= 2 * widget->style->xthickness;
1279 short_size -= 2 * widget->style->ythickness;
1284 available_size = size = allocation->height - 2 * border_width;
1285 short_size = allocation->width - 2 * border_width;
1286 arrow_size = arrow_requisition.height;
1288 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1290 available_size -= 2 * widget->style->ythickness;
1291 short_size -= 2 * widget->style->xthickness;
1295 n_items = g_list_length (priv->content);
1296 allocations = g_new0 (GtkAllocation, n_items);
1297 new_states = g_new0 (ItemState, n_items);
1300 for (list = priv->content; list != NULL; list = list->next)
1302 ToolbarContent *content = list->data;
1304 if (toolbar_item_visible (toolbar, content->item))
1305 needed_size += get_item_size (toolbar, content);
1308 need_arrow = (needed_size > available_size) && priv->show_arrow && priv->api_mode == NEW_API;
1311 size = available_size - arrow_size;
1313 size = available_size;
1315 /* calculate widths of items */
1316 overflowing = FALSE;
1317 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1319 ToolbarContent *content = list->data;
1320 GtkToolItem *item = content->item;
1323 if (!toolbar_item_visible (toolbar, item))
1325 new_states[i] = HIDDEN;
1329 item_size = get_item_size (toolbar, content);
1330 if (item_size <= size && !overflowing)
1333 allocations[i].width = item_size;
1334 new_states[i] = NORMAL;
1339 new_states[i] = OVERFLOWN;
1343 /* calculate width of arrow */
1346 arrow_allocation.width = arrow_size;
1347 arrow_allocation.height = short_size;
1350 /* expand expandable items */
1352 /* We don't expand when there is an overflow menu, because that leads to
1353 * weird jumps when items get moved to the overflow menu and the expanding
1354 * items suddenly get a lot of extra space
1359 for (i = 0, list = priv->content; list != NULL; list = list->next, ++i)
1361 ToolbarContent *content = list->data;
1362 GtkToolItem *item = content->item;
1364 if (gtk_tool_item_get_expand (item) && new_states[i] == NORMAL)
1368 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1370 ToolbarContent *content = list->data;
1371 GtkToolItem *item = content->item;
1373 if (gtk_tool_item_get_expand (item) && new_states[i] == NORMAL)
1375 gint extra = size / n_expand_items;
1376 if (size % n_expand_items != 0)
1379 allocations[i].width += extra;
1385 g_assert (n_expand_items == 0);
1388 /* position items */
1390 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1392 if (new_states[i] == NORMAL)
1394 allocations[i].x = pos;
1395 allocations[i].y = border_width;
1396 allocations[i].height = short_size;
1398 pos += allocations[i].width;
1402 /* position arrow */
1405 arrow_allocation.x = available_size - border_width - arrow_allocation.width;
1406 arrow_allocation.y = border_width;
1409 /* fix up allocations in the vertical or RTL cases */
1410 if (toolbar->orientation == GTK_ORIENTATION_VERTICAL)
1412 for (i = 0; i < n_items; ++i)
1413 fixup_allocation_for_vertical (&(allocations[i]));
1416 fixup_allocation_for_vertical (&arrow_allocation);
1418 else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1420 for (i = 0; i < n_items; ++i)
1421 fixup_allocation_for_rtl (available_size, &(allocations[i]));
1424 fixup_allocation_for_rtl (available_size, &arrow_allocation);
1427 /* translate the items by allocation->(x,y) */
1428 for (i = 0; i < n_items; ++i)
1430 allocations[i].x += allocation->x;
1431 allocations[i].y += allocation->y;
1433 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1435 allocations[i].x += widget->style->xthickness;
1436 allocations[i].y += widget->style->ythickness;
1442 arrow_allocation.x += allocation->x;
1443 arrow_allocation.y += allocation->y;
1445 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1447 arrow_allocation.x += widget->style->xthickness;
1448 arrow_allocation.y += widget->style->ythickness;
1452 /* did anything change? */
1453 for (list = priv->content, i = 0; list != NULL; list = list->next, i++)
1455 ToolbarContent *content = list->data;
1457 if (content->state == NORMAL && new_states[i] != NORMAL)
1459 /* an item disappeared, begin sliding */
1461 gtk_toolbar_begin_sliding (toolbar);
1465 /* finally allocate the items */
1466 for (list = priv->content, i = 0; list != NULL; list = list->next, i++)
1468 ToolbarContent *content = list->data;
1470 content->goal_allocation = allocations[i];
1473 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1475 ToolbarContent *content = list->data;
1476 GtkToolItem *item = content->item;
1478 if (new_states[i] != NORMAL)
1480 gtk_widget_set_child_visible (GTK_WIDGET (item), FALSE);
1484 GtkAllocation alloc;
1485 elapsed = g_timer_elapsed (priv->timer, NULL);
1487 if (priv->is_sliding)
1489 /* FIXME: we should use the same "elapsed" for all items */
1490 compute_intermediate_allocation (toolbar,
1491 &(content->start_allocation),
1492 &(content->goal_allocation),
1495 priv->need_sync = TRUE;
1499 alloc = allocations[i];
1502 if (alloc.width == 0 || alloc.height == 0)
1504 gtk_widget_set_child_visible (GTK_WIDGET (item), FALSE);
1508 gtk_widget_set_child_visible (GTK_WIDGET (item), TRUE);
1509 gtk_widget_size_allocate (GTK_WIDGET (item), &alloc);
1513 content->state = new_states[i];
1518 gtk_widget_size_allocate (GTK_WIDGET (priv->arrow_button),
1520 gtk_widget_show (GTK_WIDGET (priv->arrow_button));
1524 gtk_widget_hide (GTK_WIDGET (priv->arrow_button));
1527 g_free (allocations);
1528 g_free (new_states);
1532 gtk_toolbar_style_set (GtkWidget *widget,
1533 GtkStyle *prev_style)
1535 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
1537 priv->max_homogeneous_pixels = -1;
1539 if (GTK_WIDGET_REALIZED (widget))
1540 gtk_style_set_background (widget->style, widget->window, widget->state);
1543 gtk_toolbar_update_button_relief (GTK_TOOLBAR (widget));
1547 gtk_toolbar_direction_changed (GtkWidget *widget,
1548 GtkTextDirection previous_dir)
1550 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1551 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1553 if (toolbar->orientation == GTK_ORIENTATION_VERTICAL)
1555 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1556 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
1558 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_LEFT, GTK_SHADOW_NONE);
1561 GTK_WIDGET_CLASS (parent_class)->direction_changed (widget, previous_dir);
1565 gtk_toolbar_list_children_in_focus_order (GtkToolbar *toolbar,
1566 GtkDirectionType dir)
1568 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1569 GList *result = NULL;
1573 /* generate list of children in reverse logical order */
1575 for (list = priv->content; list != NULL; list = list->next)
1577 ToolbarContent *content = list->data;
1578 GtkToolItem *item = content->item;
1580 result = g_list_prepend (result, item);
1583 result = g_list_prepend (result, priv->arrow_button);
1585 rtl = (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL);
1587 /* move in logical order when
1589 * - dir is TAB_FORWARD
1591 * - in RTL mode and moving left or up
1593 * - in LTR mode and moving right or down
1595 if (dir == GTK_DIR_TAB_FORWARD ||
1596 (rtl && (dir == GTK_DIR_UP || dir == GTK_DIR_LEFT)) ||
1597 (!rtl && (dir == GTK_DIR_DOWN || dir == GTK_DIR_RIGHT)))
1599 result = g_list_reverse (result);
1606 gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
1607 gboolean focus_home)
1609 GList *children, *list;
1610 GtkDirectionType dir = focus_home? GTK_DIR_RIGHT : GTK_DIR_LEFT;
1612 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1614 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1616 children = g_list_reverse (children);
1618 dir = (dir == GTK_DIR_RIGHT)? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1621 for (list = children; list != NULL; list = list->next)
1623 GtkWidget *child = list->data;
1625 if (GTK_CONTAINER (toolbar)->focus_child == child)
1628 if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1632 g_list_free (children);
1637 /* Keybinding handler. This function is called when the user presses
1638 * Ctrl TAB or an arrow key.
1641 gtk_toolbar_move_focus (GtkToolbar *toolbar,
1642 GtkDirectionType dir)
1645 gboolean try_focus = FALSE;
1647 GtkContainer *container = GTK_CONTAINER (toolbar);
1649 if (container->focus_child &&
1650 gtk_widget_child_focus (container->focus_child, dir))
1655 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1657 for (list = children; list != NULL; list = list->next)
1659 GtkWidget *child = list->data;
1661 if (try_focus && GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1664 if (child == GTK_CONTAINER (toolbar)->focus_child)
1668 g_list_free (children);
1673 /* The focus handler for the toolbar. It called when the user presses
1674 * TAB or otherwise tries to focus the toolbar.
1677 gtk_toolbar_focus (GtkWidget *widget,
1678 GtkDirectionType dir)
1680 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1681 GList *children, *list;
1683 /* if focus is already somewhere inside the toolbar then return FALSE.
1684 * The only way focus can stay inside the toolbar is when the user presses
1685 * arrow keys or Ctrl TAB (both of which are handled by the
1686 * gtk_toolbar_move_focus() keybinding function.
1688 if (GTK_CONTAINER (widget)->focus_child)
1691 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1693 for (list = children; list != NULL; list = list->next)
1695 GtkWidget *child = list->data;
1697 if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1701 g_list_free (children);
1707 style_change_notify (GtkToolbar *toolbar)
1709 if (!toolbar->style_set)
1711 /* pretend it was set, then unset, thus reverting to new default */
1712 toolbar->style_set = TRUE;
1713 gtk_toolbar_unset_style (toolbar);
1718 icon_size_change_notify (GtkToolbar *toolbar)
1720 if (!toolbar->icon_size_set)
1722 /* pretend it was set, then unset, thus reverting to new default */
1723 toolbar->icon_size_set = TRUE;
1724 gtk_toolbar_unset_icon_size (toolbar);
1728 static GtkSettings *
1729 toolbar_get_settings (GtkToolbar *toolbar)
1731 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1732 return priv->settings;
1736 gtk_toolbar_screen_changed (GtkWidget *widget,
1737 GdkScreen *previous_screen)
1739 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
1740 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1741 GtkSettings *old_settings = toolbar_get_settings (toolbar);
1742 GtkSettings *settings;
1744 if (gtk_widget_has_screen (GTK_WIDGET (toolbar)))
1745 settings = gtk_widget_get_settings (GTK_WIDGET (toolbar));
1749 if (settings == old_settings)
1754 g_signal_handler_disconnect (old_settings, toolbar->style_set_connection);
1755 g_signal_handler_disconnect (old_settings, toolbar->icon_size_connection);
1757 g_object_unref (old_settings);
1762 toolbar->style_set_connection =
1763 g_signal_connect_swapped (settings,
1764 "notify::gtk-toolbar-style",
1765 G_CALLBACK (style_change_notify),
1767 toolbar->icon_size_connection =
1768 g_signal_connect_swapped (settings,
1769 "notify::gtk-toolbar-icon-size",
1770 G_CALLBACK (icon_size_change_notify),
1773 g_object_ref (settings);
1774 priv->settings = settings;
1777 priv->settings = NULL;
1779 style_change_notify (toolbar);
1780 icon_size_change_notify (toolbar);
1784 find_drop_index (GtkToolbar *toolbar,
1788 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1789 GList *interesting_content;
1791 GtkOrientation orientation;
1792 GtkTextDirection direction;
1793 gint best_distance = G_MAXINT;
1797 ToolbarContent *best_content;
1799 /* list items we care about wrt. drag and drop */
1800 interesting_content = NULL;
1801 for (list = priv->content; list != NULL; list = list->next)
1803 ToolbarContent *content = list->data;
1805 if (content->state == NORMAL)
1806 interesting_content = g_list_prepend (interesting_content, content);
1808 interesting_content = g_list_reverse (interesting_content);
1810 if (!interesting_content)
1813 orientation = toolbar->orientation;
1814 direction = gtk_widget_get_direction (GTK_WIDGET (toolbar));
1816 /* distance to first interesting item */
1817 best_content = interesting_content->data;
1819 if (orientation == GTK_ORIENTATION_HORIZONTAL)
1823 if (direction == GTK_TEXT_DIR_LTR)
1824 pos = GTK_WIDGET (best_content->item)->allocation.x;
1826 pos = GTK_WIDGET (best_content->item)->allocation.x +
1827 GTK_WIDGET (best_content->item)->allocation.width;
1832 pos = GTK_WIDGET (best_content->item)->allocation.y;
1835 best_content = NULL;
1836 best_distance = ABS (pos - cursor);
1838 /* distance to far end of each item */
1839 for (list = interesting_content; list != NULL; list = list->next)
1841 ToolbarContent *content = list->data;
1842 GtkWidget *widget = GTK_WIDGET (content->item);
1844 if (orientation == GTK_ORIENTATION_HORIZONTAL)
1846 if (direction == GTK_TEXT_DIR_LTR)
1847 pos = widget->allocation.x + widget->allocation.width;
1849 pos = widget->allocation.x;
1853 pos = widget->allocation.y + widget->allocation.height;
1856 distance = ABS (pos - cursor);
1858 if (distance < best_distance)
1860 best_distance = distance;
1861 best_content = content;
1865 g_list_free (interesting_content);
1870 return g_list_index (priv->content, best_content) + 1;
1874 reset_all_placeholders (GtkToolbar *toolbar)
1876 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1879 for (list = priv->content; list != NULL; list = list->next)
1881 ToolbarContent *content = list->data;
1882 if (content->is_placeholder)
1883 content->disappearing = TRUE;
1888 physical_to_logical (GtkToolbar *toolbar, gint physical)
1890 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1894 g_assert (physical >= 0);
1897 for (list = priv->content; list && physical > 0; list = list->next)
1899 ToolbarContent *content = list->data;
1901 if (!content->is_placeholder)
1906 g_assert (physical == 0);
1912 logical_to_physical (GtkToolbar *toolbar, gint logical)
1914 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1918 g_assert (logical >= 0);
1921 for (list = priv->content; list; list = list->next)
1923 ToolbarContent *content = list->data;
1925 if (!content->is_placeholder)
1935 g_assert (logical == 0);
1941 * gtk_toolbar_set_drop_highlight_item:
1942 * @toolbar: a #GtkToolbar
1943 * @item: a #GtkToolItem, or %NULL to turn of highlighting
1944 * @index: a position on @toolbar
1946 * Highlights @toolbar to give an idea of what it would look like
1947 * if @item was added to @toolbar at position indicated by @index. If @item
1948 * is %NULL, highlighting is turned off. In that case @index is ignored.
1950 * The @tool_item passed to this function must not be part of any widget
1951 * hierarchy. When an item is set as drop highlight item it can not
1952 * added to any widget hierarchy or used as highlight item for another
1958 gtk_toolbar_set_drop_highlight_item (GtkToolbar *toolbar,
1959 GtkToolItem *tool_item,
1962 ToolbarContent *content;
1963 GtkToolbarPrivate *priv;
1965 GtkRequisition requisition;
1967 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1968 g_return_if_fail (tool_item == NULL || GTK_IS_TOOL_ITEM (tool_item));
1970 gtk_toolbar_check_new_api (toolbar);
1972 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1976 if (priv->highlight_tool_item)
1978 gtk_widget_unparent (GTK_WIDGET (priv->highlight_tool_item));
1979 g_object_unref (priv->highlight_tool_item);
1980 priv->highlight_tool_item = NULL;
1983 reset_all_placeholders (toolbar);
1984 gtk_toolbar_begin_sliding (toolbar);
1988 if (tool_item != priv->highlight_tool_item)
1990 if (priv->highlight_tool_item)
1991 g_object_unref (priv->highlight_tool_item);
1993 g_object_ref (tool_item);
1994 gtk_object_sink (GTK_OBJECT (tool_item));
1996 priv->highlight_tool_item = tool_item;
1998 gtk_widget_set_parent (GTK_WIDGET (priv->highlight_tool_item),
1999 GTK_WIDGET (toolbar));
2002 n_items = gtk_toolbar_get_n_items (toolbar);
2003 if (index < 0 || index > n_items)
2006 index = logical_to_physical (toolbar, index);
2008 content = g_list_nth_data (priv->content, index);
2012 ToolbarContent *prev_content;
2014 prev_content = g_list_nth_data (priv->content, index - 1);
2016 if (prev_content && prev_content->is_placeholder)
2017 content = prev_content;
2020 if (!content || !content->is_placeholder)
2022 GtkWidget *placeholder;
2024 placeholder = GTK_WIDGET (gtk_separator_tool_item_new ());
2025 content = gtk_toolbar_insert_tool_item (toolbar,
2026 GTK_TOOL_ITEM (placeholder),
2028 gtk_widget_show (placeholder);
2032 g_assert (content->is_placeholder);
2034 reset_all_placeholders (toolbar);
2036 content->disappearing = FALSE;
2038 gtk_widget_size_request (GTK_WIDGET (priv->highlight_tool_item),
2041 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
2042 requisition.height = -1;
2044 requisition.width = -1;
2046 gtk_widget_set_size_request (GTK_WIDGET (content->item),
2048 requisition.height);
2050 gtk_toolbar_begin_sliding (toolbar);
2054 gtk_toolbar_get_child_property (GtkContainer *container,
2060 GtkToolItem *item = GTK_TOOL_ITEM (child);
2062 switch (property_id)
2064 case CHILD_PROP_HOMOGENEOUS:
2065 g_value_set_boolean (value, gtk_tool_item_get_homogeneous (item));
2068 case CHILD_PROP_EXPAND:
2069 g_value_set_boolean (value, gtk_tool_item_get_expand (item));
2073 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2079 gtk_toolbar_set_child_property (GtkContainer *container,
2082 const GValue *value,
2085 switch (property_id)
2087 case CHILD_PROP_HOMOGENEOUS:
2088 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
2091 case CHILD_PROP_EXPAND:
2092 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
2096 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2102 gtk_toolbar_add (GtkContainer *container,
2105 GtkToolbar *toolbar;
2107 g_return_if_fail (GTK_IS_TOOLBAR (container));
2108 g_return_if_fail (widget != NULL);
2110 toolbar = GTK_TOOLBAR (container);
2112 if (GTK_IS_TOOL_ITEM (widget))
2113 gtk_toolbar_insert (toolbar, GTK_TOOL_ITEM (widget), 0);
2115 gtk_toolbar_append_widget (toolbar, widget, NULL, NULL);
2119 gtk_toolbar_remove (GtkContainer *container,
2122 GtkToolbar *toolbar;
2123 GtkToolItem *item = NULL;
2125 g_return_if_fail (GTK_IS_TOOLBAR (container));
2126 g_return_if_fail (GTK_IS_WIDGET (widget));
2128 toolbar = GTK_TOOLBAR (container);
2130 if (GTK_IS_TOOL_ITEM (widget))
2132 item = GTK_TOOL_ITEM (widget);
2136 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2139 for (list = priv->content; list != NULL; list = list->next)
2141 ToolbarContent *content = list->data;
2143 if (GTK_BIN (content->item)->child == widget)
2145 item = content->item;
2151 g_return_if_fail (item != NULL);
2153 gtk_toolbar_remove_tool_item (GTK_TOOLBAR (container), item);
2157 gtk_toolbar_forall (GtkContainer *container,
2158 gboolean include_internals,
2159 GtkCallback callback,
2160 gpointer callback_data)
2162 GtkToolbar *toolbar = GTK_TOOLBAR (container);
2163 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2166 g_return_if_fail (callback != NULL);
2168 list = priv->content;
2171 ToolbarContent *content = list->data;
2172 GList *next = list->next;
2174 if (!content->is_placeholder || include_internals)
2175 (*callback) (GTK_WIDGET (content->item), callback_data);
2180 if (include_internals)
2181 (* callback) (priv->arrow_button, callback_data);
2185 gtk_toolbar_child_type (GtkContainer *container)
2187 return GTK_TYPE_TOOL_ITEM;
2191 gtk_toolbar_reconfigured (GtkToolbar *toolbar)
2193 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2196 list = priv->content;
2199 ToolbarContent *content = list->data;
2200 GList *next = list->next;
2202 _gtk_tool_item_toolbar_reconfigured (content->item);
2209 gtk_toolbar_real_orientation_changed (GtkToolbar *toolbar,
2210 GtkOrientation orientation)
2212 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2213 if (toolbar->orientation != orientation)
2215 toolbar->orientation = orientation;
2217 if (orientation == GTK_ORIENTATION_HORIZONTAL)
2218 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_DOWN, GTK_SHADOW_NONE);
2219 else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2220 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
2222 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_LEFT, GTK_SHADOW_NONE);
2224 gtk_toolbar_reconfigured (toolbar);
2226 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2227 g_object_notify (G_OBJECT (toolbar), "orientation");
2232 gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
2233 GtkToolbarStyle style)
2235 if (toolbar->style != style)
2237 toolbar->style = style;
2239 gtk_toolbar_reconfigured (toolbar);
2241 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2242 g_object_notify (G_OBJECT (toolbar), "toolbar_style");
2247 menu_position_func (GtkMenu *menu,
2253 GtkToolbar *toolbar = GTK_TOOLBAR (user_data);
2254 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2256 GtkRequisition menu_req;
2258 gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y);
2259 gtk_widget_size_request (priv->arrow_button, &req);
2260 gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
2262 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
2264 *y += priv->arrow_button->allocation.height;
2265 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2266 *x += priv->arrow_button->allocation.width - req.width;
2268 *x += req.width - menu_req.width;
2272 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2273 *x += priv->arrow_button->allocation.width;
2275 *x -= menu_req.width;
2276 *y += priv->arrow_button->allocation.height - req.height;
2283 menu_deactivated (GtkWidget *menu,
2284 GtkToolbar *toolbar)
2286 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2288 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->arrow_button), FALSE);
2292 remove_item (GtkWidget *menu_item,
2295 gtk_container_remove (GTK_CONTAINER (menu_item->parent), menu_item);
2299 show_menu (GtkToolbar *toolbar,
2300 GdkEventButton *event)
2302 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2307 gtk_container_foreach (GTK_CONTAINER (priv->menu), remove_item, NULL);
2308 gtk_widget_destroy (GTK_WIDGET (priv->menu));
2311 priv->menu = GTK_MENU (gtk_menu_new ());
2312 g_signal_connect (priv->menu, "deactivate", G_CALLBACK (menu_deactivated), toolbar);
2314 for (list = priv->content; list != NULL; list = list->next)
2316 ToolbarContent *content = list->data;
2317 GtkToolItem *item = content->item;
2319 if (content->state == OVERFLOWN)
2321 GtkWidget *menu_item = gtk_tool_item_retrieve_proxy_menu_item (item);
2325 g_assert (GTK_IS_MENU_ITEM (menu_item));
2326 gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_item);
2331 gtk_widget_show_all (GTK_WIDGET (priv->menu));
2333 gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL,
2334 menu_position_func, toolbar,
2335 event? event->button : 0, event? event->time : gtk_get_current_event_time());
2339 gtk_toolbar_arrow_button_clicked (GtkWidget *button,
2340 GtkToolbar *toolbar)
2342 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2344 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->arrow_button)) &&
2345 (!priv->menu || !GTK_WIDGET_VISIBLE (GTK_WIDGET (priv->menu))))
2347 /* We only get here when the button is clicked with the keybaord,
2348 * because mouse button presses result in the menu being shown so
2349 * that priv->menu would be non-NULL and visible.
2351 show_menu (toolbar, NULL);
2352 gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menu), FALSE);
2357 gtk_toolbar_arrow_button_press (GtkWidget *button,
2358 GdkEventButton *event,
2359 GtkToolbar *toolbar)
2361 show_menu (toolbar, event);
2362 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2368 gtk_toolbar_button_press (GtkWidget *toolbar,
2369 GdkEventButton *event)
2371 if (event->button == 3)
2373 gboolean return_value;
2375 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2376 (int)event->x_root, (int)event->y_root, event->button,
2379 return return_value;
2386 gtk_toolbar_popup_menu (GtkWidget *toolbar)
2388 gboolean return_value;
2389 /* This function is the handler for the "popup menu" keybinding,
2390 * ie., it is called when the user presses Shift F10
2392 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2393 -1, -1, -1, &return_value);
2395 return return_value;
2399 gtk_toolbar_update_button_relief (GtkToolbar *toolbar)
2401 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2403 gtk_toolbar_reconfigured (toolbar);
2405 gtk_button_set_relief (GTK_BUTTON (priv->arrow_button), get_button_relief (toolbar));
2408 static GtkReliefStyle
2409 get_button_relief (GtkToolbar *toolbar)
2411 GtkReliefStyle button_relief = GTK_RELIEF_NORMAL;
2413 gtk_widget_ensure_style (GTK_WIDGET (toolbar));
2415 gtk_widget_style_get (GTK_WIDGET (toolbar),
2416 "button_relief", &button_relief,
2419 return button_relief;
2423 get_internal_padding (GtkToolbar *toolbar)
2427 gtk_widget_style_get (GTK_WIDGET (toolbar),
2428 "internal_padding", &ipadding,
2434 static GtkShadowType
2435 get_shadow_type (GtkToolbar *toolbar)
2437 GtkShadowType shadow_type;
2439 gtk_widget_style_get (GTK_WIDGET (toolbar),
2440 "shadow_type", &shadow_type,
2447 gtk_toolbar_check_old_api (GtkToolbar *toolbar)
2449 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2451 if (priv->api_mode == NEW_API)
2453 g_warning ("mixing deprecated and non-deprecated GtkToolbar API is not allowed");
2457 priv->api_mode = OLD_API;
2462 gtk_toolbar_check_new_api (GtkToolbar *toolbar)
2464 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2466 if (priv->api_mode == OLD_API)
2468 g_warning ("mixing deprecated and non-deprecated GtkToolbar API is not allowed");
2472 priv->api_mode = NEW_API;
2476 static ToolbarContent *
2477 gtk_toolbar_insert_tool_item (GtkToolbar *toolbar,
2480 gboolean is_placeholder)
2482 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2483 ToolbarContent *content = g_new0 (ToolbarContent, 1);
2485 content->is_placeholder = is_placeholder;
2486 content->item = item;
2487 content->state = NOT_ALLOCATED;
2488 toolbar->num_children++;
2490 priv->content = g_list_insert (priv->content, content, pos);
2492 gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar));
2494 if (!content->is_placeholder)
2495 gtk_toolbar_stop_sliding (toolbar);
2501 gtk_toolbar_remove_tool_item (GtkToolbar *toolbar,
2504 GtkToolbarPrivate *priv;
2507 ToolbarContent *content = NULL;
2509 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2510 g_return_if_fail (GTK_IS_TOOL_ITEM (item));
2512 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2516 for (tmp = priv->content; tmp != NULL; tmp = tmp->next)
2518 content = tmp->data;
2519 if (content->item == item)
2525 g_return_if_fail (content != NULL);
2529 priv->content = g_list_remove (priv->content, content);
2531 gtk_widget_unparent (GTK_WIDGET (item));
2533 if (priv->api_mode == OLD_API)
2535 GtkToolbarChild *toolbar_child;
2537 toolbar_child = g_list_nth_data (toolbar->children, nth_child);
2538 toolbar->children = g_list_remove (toolbar->children, toolbar_child);
2540 g_free (toolbar_child);
2543 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2549 * Creates a new toolbar.
2551 * Return Value: the newly-created toolbar.
2554 gtk_toolbar_new (void)
2556 GtkToolbar *toolbar;
2558 toolbar = g_object_new (GTK_TYPE_TOOLBAR, NULL);
2560 return GTK_WIDGET (toolbar);
2564 * gtk_toolbar_insert:
2565 * @toolbar: a #GtkToolbar
2566 * @item: a #GtkToolItem
2567 * @pos: the position of the new item
2569 * Insert a #GtkToolItem into the toolbar at position @pos. If @pos is
2570 * 0 the item is prepended to the start of the toolbar. If @pos is
2571 * negative, the item is appended to the end of the toolbar.
2576 gtk_toolbar_insert (GtkToolbar *toolbar,
2580 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2581 g_return_if_fail (GTK_IS_TOOL_ITEM (item));
2583 if (!gtk_toolbar_check_new_api (toolbar))
2587 pos = logical_to_physical (toolbar, pos);
2589 gtk_toolbar_insert_tool_item (toolbar, item, pos, FALSE);
2593 * gtk_toolbar_get_item_index:
2594 * @toolbar: a #GtkToolbar
2595 * @item: a #GtkToolItem that is a child of @toolbar
2597 * Returns the position of @item on the toolbar, starting from 0.
2598 * It is an error if @item is not a child of the toolbar.
2600 * Return value: the position of item on the toolbar.
2605 gtk_toolbar_get_item_index (GtkToolbar *toolbar,
2608 GtkToolbarPrivate *priv;
2612 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2613 g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1);
2614 g_return_val_if_fail (GTK_WIDGET (item)->parent == GTK_WIDGET (toolbar), -1);
2616 if (!gtk_toolbar_check_new_api (toolbar))
2619 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2622 for (list = priv->content; list != NULL; list = list->next)
2624 ToolbarContent *content = list->data;
2626 if (content->item == item)
2632 return physical_to_logical (toolbar, n);
2636 * gtk_toolbar_set_orientation:
2637 * @toolbar: a #GtkToolbar.
2638 * @orientation: a new #GtkOrientation.
2640 * Sets whether a toolbar should appear horizontally or vertically.
2643 gtk_toolbar_set_orientation (GtkToolbar *toolbar,
2644 GtkOrientation orientation)
2646 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2648 g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0, orientation);
2652 * gtk_toolbar_get_orientation:
2653 * @toolbar: a #GtkToolbar
2655 * Retrieves the current orientation of the toolbar. See
2656 * gtk_toolbar_set_orientation().
2658 * Return value: the orientation
2661 gtk_toolbar_get_orientation (GtkToolbar *toolbar)
2663 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
2665 return toolbar->orientation;
2669 * gtk_toolbar_set_style:
2670 * @toolbar: a #GtkToolbar.
2671 * @style: the new style for @toolbar.
2673 * Alters the view of @toolbar to display either icons only, text only, or both.
2676 gtk_toolbar_set_style (GtkToolbar *toolbar,
2677 GtkToolbarStyle style)
2679 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2681 toolbar->style_set = TRUE;
2682 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2686 * gtk_toolbar_get_style:
2687 * @toolbar: a #GtkToolbar
2689 * Retrieves whether the toolbar has text, icons, or both . See
2690 * gtk_toolbar_set_style().
2692 * Return value: the current style of @toolbar
2695 gtk_toolbar_get_style (GtkToolbar *toolbar)
2697 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_TOOLBAR_STYLE);
2699 return toolbar->style;
2703 * gtk_toolbar_unset_style:
2704 * @toolbar: a #GtkToolbar
2706 * Unsets a toolbar style set with gtk_toolbar_set_style(), so that
2707 * user preferences will be used to determine the toolbar style.
2710 gtk_toolbar_unset_style (GtkToolbar *toolbar)
2712 GtkToolbarStyle style;
2714 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2716 if (toolbar->style_set)
2718 GtkSettings *settings = toolbar_get_settings (toolbar);
2721 g_object_get (settings,
2722 "gtk-toolbar-style", &style,
2725 style = DEFAULT_TOOLBAR_STYLE;
2727 if (style != toolbar->style)
2728 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2730 toolbar->style_set = FALSE;
2735 * gtk_toolbar_set_tooltips:
2736 * @toolbar: a #GtkToolbar.
2737 * @enable: set to %FALSE to disable the tooltips, or %TRUE to enable them.
2739 * Sets if the tooltips of a toolbar should be active or not.
2742 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
2745 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2748 gtk_tooltips_enable (toolbar->tooltips);
2750 gtk_tooltips_disable (toolbar->tooltips);
2754 * gtk_toolbar_get_tooltips:
2755 * @toolbar: a #GtkToolbar
2757 * Retrieves whether tooltips are enabled. See
2758 * gtk_toolbar_set_tooltips().
2760 * Return value: %TRUE if tooltips are enabled
2763 gtk_toolbar_get_tooltips (GtkToolbar *toolbar)
2765 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2767 return toolbar->tooltips->enabled;
2771 * gtk_toolbar_get_n_items:
2772 * @toolbar: a #GtkToolbar
2774 * Returns the number of items on the toolbar.
2776 * Return value: the number of items on the toolbar
2781 gtk_toolbar_get_n_items (GtkToolbar *toolbar)
2783 GtkToolbarPrivate *priv;
2785 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2787 if (!gtk_toolbar_check_new_api (toolbar))
2790 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2792 return physical_to_logical (toolbar, g_list_length (priv->content));
2796 * gtk_toolbar_get_nth_item:
2797 * @toolbar: a #GtkToolbar
2798 * @n: A position on the toolbar
2800 * Returns the @n<!-- -->'s item on @toolbar, or %NULL if the
2801 * toolbar does not contain an @n<!-- -->'th item.
2803 * Return value: The @n<!-- -->'th #GtkToolItem on @toolbar, or %NULL if there
2804 * isn't an @n<!-- -->th item.
2809 gtk_toolbar_get_nth_item (GtkToolbar *toolbar,
2812 GtkToolbarPrivate *priv;
2813 ToolbarContent *content;
2816 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
2818 if (!gtk_toolbar_check_new_api (toolbar))
2821 n_items = gtk_toolbar_get_n_items (toolbar);
2823 if (n < 0 || n >= n_items)
2826 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2828 content = g_list_nth_data (priv->content, logical_to_physical (toolbar, n));
2831 g_assert (!content->is_placeholder);
2833 return content->item;
2837 * gtk_toolbar_set_icon_size:
2838 * @toolbar: A #GtkToolbar
2839 * @icon_size: The #GtkIconSize that stock icons in the toolbar shall have.
2841 * This function sets the size of stock icons in the toolbar. You
2842 * can call it both before you add the icons and after they've been
2843 * added. The size you set will override user preferences for the default
2847 gtk_toolbar_set_icon_size (GtkToolbar *toolbar,
2848 GtkIconSize icon_size)
2850 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2852 toolbar->icon_size_set = TRUE;
2854 if (toolbar->icon_size == icon_size)
2857 toolbar->icon_size = icon_size;
2859 gtk_toolbar_reconfigured (toolbar);
2861 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2865 * gtk_toolbar_get_icon_size:
2866 * @toolbar: a #GtkToolbar
2868 * Retrieves the icon size fo the toolbar. See gtk_toolbar_set_icon_size().
2870 * Return value: the current icon size for the icons on the toolbar.
2873 gtk_toolbar_get_icon_size (GtkToolbar *toolbar)
2875 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_ICON_SIZE);
2877 return toolbar->icon_size;
2881 * gtk_toolbar_get_relief_style:
2882 * @toolbar: a #GtkToolbar
2884 * Returns the relief style of buttons on @toolbar. See
2885 * gtk_button_set_relief_style().
2887 * Return value: The relief style of buttons on @toolbar.
2892 gtk_toolbar_get_relief_style (GtkToolbar *toolbar)
2894 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_RELIEF_NONE);
2896 return get_button_relief (toolbar);
2900 * gtk_toolbar_unset_icon_size:
2901 * @toolbar: a #GtkToolbar
2903 * Unsets toolbar icon size set with gtk_toolbar_set_icon_size(), so that
2904 * user preferences will be used to determine the icon size.
2907 gtk_toolbar_unset_icon_size (GtkToolbar *toolbar)
2911 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2913 if (toolbar->icon_size_set)
2915 GtkSettings *settings = toolbar_get_settings (toolbar);
2919 g_object_get (settings,
2920 "gtk-toolbar-icon-size", &size,
2924 size = DEFAULT_ICON_SIZE;
2926 if (size != toolbar->icon_size)
2927 gtk_toolbar_set_icon_size (toolbar, size);
2929 toolbar->icon_size_set = FALSE;
2934 * gtk_toolbar_set_show_arrow:
2935 * @toolbar: a #GtkToolbar
2936 * @show_arrow: Whether to show an overflow menu
2938 * Sets whether to show an overflow menu when
2939 * @toolbar doesn't have room for all items on it. If %TRUE,
2940 * items that there are not room are available through an
2946 gtk_toolbar_set_show_arrow (GtkToolbar *toolbar,
2947 gboolean show_arrow)
2949 GtkToolbarPrivate *priv;
2951 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2953 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2954 show_arrow = show_arrow != FALSE;
2956 if (priv->show_arrow != show_arrow)
2958 priv->show_arrow = show_arrow;
2960 if (!priv->show_arrow)
2961 gtk_widget_hide (priv->arrow_button);
2963 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2964 g_object_notify (G_OBJECT (toolbar), "show_arrow");
2969 * gtk_toolbar_get_show_arrow:
2970 * @toolbar: a #GtkToolbar
2972 * Returns whether the toolbar has an overflow menu.
2973 * See gtk_toolbar_set_show_arrow()
2980 gtk_toolbar_get_show_arrow (GtkToolbar *toolbar)
2982 GtkToolbarPrivate *priv;
2984 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2986 if (!gtk_toolbar_check_new_api (toolbar))
2989 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2991 return priv->show_arrow;
2995 * gtk_toolbar_get_drop_index:
2996 * @toolbar: a #GtkToolbar
2997 * @x: x coordinate of a point on the toolbar
2998 * @y: y coordinate of a point on the toolbar
3000 * Returns the position corresponding to the indicated point on
3001 * @toolbar. This is useful when dragging items to the toolbar:
3002 * this function returns the position a new item should be
3005 * @x and @y are in @toolbar coordinates.
3007 * Return value: The position corresponding to the point (@x, @y) on the toolbar.
3012 gtk_toolbar_get_drop_index (GtkToolbar *toolbar,
3016 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
3018 if (!gtk_toolbar_check_new_api (toolbar))
3021 return physical_to_logical (toolbar, find_drop_index (toolbar, x, y));
3025 * gtk_toolbar_append_item:
3026 * @toolbar: a #GtkToolbar.
3027 * @text: give your toolbar button a label.
3028 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3029 * @tooltip_private_text: use with #GtkTipsQuery.
3030 * @icon: a #GtkWidget that should be used as the button's icon.
3031 * @callback: the function to be executed when the button is pressed.
3032 * @user_data: a pointer to any data you wish to be passed to the callback.
3034 * Inserts a new item into the toolbar. You must specify the position
3035 * in the toolbar where it will be inserted.
3037 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3038 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3040 * Return value: the new toolbar item as a #GtkWidget.
3043 gtk_toolbar_append_item (GtkToolbar *toolbar,
3045 const char *tooltip_text,
3046 const char *tooltip_private_text,
3048 GtkSignalFunc callback,
3051 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3053 tooltip_text, tooltip_private_text,
3054 icon, callback, user_data,
3055 toolbar->num_children);
3059 * gtk_toolbar_prepend_item:
3060 * @toolbar: a #GtkToolbar.
3061 * @text: give your toolbar button a label.
3062 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3063 * @tooltip_private_text: use with #GtkTipsQuery.
3064 * @icon: a #GtkWidget that should be used as the button's icon.
3065 * @callback: the function to be executed when the button is pressed.
3066 * @user_data: a pointer to any data you wish to be passed to the callback.
3068 * Adds a new button to the beginning (top or left edges) of the given toolbar.
3070 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3071 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3073 * Return value: the new toolbar item as a #GtkWidget.
3076 gtk_toolbar_prepend_item (GtkToolbar *toolbar,
3078 const char *tooltip_text,
3079 const char *tooltip_private_text,
3081 GtkSignalFunc callback,
3084 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3086 tooltip_text, tooltip_private_text,
3087 icon, callback, user_data,
3092 * gtk_toolbar_insert_item:
3093 * @toolbar: a #GtkToolbar.
3094 * @text: give your toolbar button a label.
3095 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3096 * @tooltip_private_text: use with #GtkTipsQuery.
3097 * @icon: a #GtkWidget that should be used as the button's icon.
3098 * @callback: the function to be executed when the button is pressed.
3099 * @user_data: a pointer to any data you wish to be passed to the callback.
3100 * @position: the number of widgets to insert this item after.
3102 * Inserts a new item into the toolbar. You must specify the position in the
3103 * toolbar where it will be inserted.
3105 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3106 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3108 * Return value: the new toolbar item as a #GtkWidget.
3111 gtk_toolbar_insert_item (GtkToolbar *toolbar,
3113 const char *tooltip_text,
3114 const char *tooltip_private_text,
3116 GtkSignalFunc callback,
3120 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3122 tooltip_text, tooltip_private_text,
3123 icon, callback, user_data,
3128 * gtk_toolbar_insert_stock:
3129 * @toolbar: A #GtkToolbar
3130 * @stock_id: The id of the stock item you want to insert
3131 * @tooltip_text: The text in the tooltip of the toolbar button
3132 * @tooltip_private_text: The private text of the tooltip
3133 * @callback: The callback called when the toolbar button is clicked.
3134 * @user_data: user data passed to callback
3135 * @position: The position the button shall be inserted at.
3136 * -1 means at the end.
3138 * Inserts a stock item at the specified position of the toolbar. If
3139 * @stock_id is not a known stock item ID, it's inserted verbatim,
3140 * except that underscores used to mark mnemonics are removed.
3142 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3143 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3145 * Returns: the inserted widget
3148 gtk_toolbar_insert_stock (GtkToolbar *toolbar,
3149 const gchar *stock_id,
3150 const char *tooltip_text,
3151 const char *tooltip_private_text,
3152 GtkSignalFunc callback,
3156 return gtk_toolbar_internal_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3158 tooltip_text, tooltip_private_text,
3159 NULL, callback, user_data,
3164 * gtk_toolbar_append_space:
3165 * @toolbar: a #GtkToolbar.
3167 * Adds a new space to the end of the toolbar.
3170 gtk_toolbar_append_space (GtkToolbar *toolbar)
3172 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3176 toolbar->num_children);
3180 * gtk_toolbar_prepend_space:
3181 * @toolbar: a #GtkToolbar.
3183 * Adds a new space to the beginning of the toolbar.
3186 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
3188 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3196 * gtk_toolbar_insert_space:
3197 * @toolbar: a #GtkToolbar
3198 * @position: the number of widgets after which a space should be inserted.
3200 * Inserts a new space in the toolbar at the specified position.
3203 gtk_toolbar_insert_space (GtkToolbar *toolbar,
3206 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3214 * gtk_toolbar_remove_space:
3215 * @toolbar: a #GtkToolbar.
3216 * @position: the index of the space to remove.
3218 * Removes a space from the specified position.
3221 gtk_toolbar_remove_space (GtkToolbar *toolbar,
3226 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3228 if (!gtk_toolbar_check_old_api (toolbar))
3231 item = g_list_nth_data (toolbar->children, position);
3235 g_warning ("Toolbar position %d doesn't exist", position);
3239 if (!GTK_IS_SEPARATOR_TOOL_ITEM (item))
3241 g_warning ("Toolbar position %d is not a space", position);
3245 gtk_toolbar_remove_tool_item (toolbar, item);
3249 * gtk_toolbar_append_widget:
3250 * @toolbar: a #GtkToolbar.
3251 * @widget: a #GtkWidget to add to the toolbar.
3252 * @tooltip_text: the element's tooltip.
3253 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3255 * Adds a widget to the end of the given toolbar.
3258 gtk_toolbar_append_widget (GtkToolbar *toolbar,
3260 const gchar *tooltip_text,
3261 const gchar *tooltip_private_text)
3263 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3265 tooltip_text, tooltip_private_text,
3267 toolbar->num_children);
3271 * gtk_toolbar_prepend_widget:
3272 * @toolbar: a #GtkToolbar.
3273 * @widget: a #GtkWidget to add to the toolbar.
3274 * @tooltip_text: the element's tooltip.
3275 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3277 * Adds a widget to the beginning of the given toolbar.
3280 gtk_toolbar_prepend_widget (GtkToolbar *toolbar,
3282 const gchar *tooltip_text,
3283 const gchar *tooltip_private_text)
3285 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3287 tooltip_text, tooltip_private_text,
3293 * gtk_toolbar_insert_widget:
3294 * @toolbar: a #GtkToolbar.
3295 * @widget: a #GtkWidget to add to the toolbar.
3296 * @tooltip_text: the element's tooltip.
3297 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3298 * @position: the number of widgets to insert this widget after.
3300 * Inserts a widget in the toolbar at the given position.
3303 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
3305 const char *tooltip_text,
3306 const char *tooltip_private_text,
3309 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3311 tooltip_text, tooltip_private_text,
3317 * gtk_toolbar_append_element:
3318 * @toolbar: a #GtkToolbar.
3319 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
3320 * @widget: a #GtkWidget, or %NULL.
3321 * @text: the element's label.
3322 * @tooltip_text: the element's tooltip.
3323 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3324 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3325 * @callback: the function to be executed when the button is pressed.
3326 * @user_data: any data you wish to pass to the callback.
3328 * Adds a new element to the end of a toolbar.
3330 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3331 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3332 * the radio group for the new element. In all other cases, @widget must
3335 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3336 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3338 * Return value: the new toolbar element as a #GtkWidget.
3341 gtk_toolbar_append_element (GtkToolbar *toolbar,
3342 GtkToolbarChildType type,
3345 const char *tooltip_text,
3346 const char *tooltip_private_text,
3348 GtkSignalFunc callback,
3351 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3352 tooltip_text, tooltip_private_text,
3353 icon, callback, user_data,
3354 toolbar->num_children);
3358 * gtk_toolbar_prepend_element:
3359 * @toolbar: a #GtkToolbar.
3360 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
3361 * @widget: a #GtkWidget, or %NULL
3362 * @text: the element's label.
3363 * @tooltip_text: the element's tooltip.
3364 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3365 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3366 * @callback: the function to be executed when the button is pressed.
3367 * @user_data: any data you wish to pass to the callback.
3369 * Adds a new element to the beginning of a toolbar.
3371 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3372 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3373 * the radio group for the new element. In all other cases, @widget must
3376 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3377 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3379 * Return value: the new toolbar element as a #GtkWidget.
3382 gtk_toolbar_prepend_element (GtkToolbar *toolbar,
3383 GtkToolbarChildType type,
3386 const char *tooltip_text,
3387 const char *tooltip_private_text,
3389 GtkSignalFunc callback,
3392 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3393 tooltip_text, tooltip_private_text,
3394 icon, callback, user_data, 0);
3398 * gtk_toolbar_insert_element:
3399 * @toolbar: a #GtkToolbar.
3400 * @type: a value of type #GtkToolbarChildType that determines what @widget
3402 * @widget: a #GtkWidget, or %NULL.
3403 * @text: the element's label.
3404 * @tooltip_text: the element's tooltip.
3405 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3406 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3407 * @callback: the function to be executed when the button is pressed.
3408 * @user_data: any data you wish to pass to the callback.
3409 * @position: the number of widgets to insert this element after.
3411 * Inserts a new element in the toolbar at the given position.
3413 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3414 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3415 * the radio group for the new element. In all other cases, @widget must
3418 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3419 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3421 * Return value: the new toolbar element as a #GtkWidget.
3424 gtk_toolbar_insert_element (GtkToolbar *toolbar,
3425 GtkToolbarChildType type,
3428 const char *tooltip_text,
3429 const char *tooltip_private_text,
3431 GtkSignalFunc callback,
3435 return gtk_toolbar_internal_insert_element (toolbar, type, widget, text,
3436 tooltip_text, tooltip_private_text,
3437 icon, callback, user_data, position, FALSE);
3441 _gtk_toolbar_elide_underscores (const gchar *original)
3445 gboolean last_underscore;
3447 q = result = g_malloc (strlen (original) + 1);
3448 last_underscore = FALSE;
3450 for (p = original; *p; p++)
3452 if (!last_underscore && *p == '_')
3453 last_underscore = TRUE;
3456 last_underscore = FALSE;
3467 gtk_toolbar_internal_insert_element (GtkToolbar *toolbar,
3468 GtkToolbarChildType type,
3471 const char *tooltip_text,
3472 const char *tooltip_private_text,
3474 GtkSignalFunc callback,
3479 GtkToolbarChild *child;
3480 GtkToolItem *item = NULL;
3482 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
3484 if (!gtk_toolbar_check_old_api (toolbar))
3487 if (type == GTK_TOOLBAR_CHILD_WIDGET)
3488 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3489 else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON)
3490 g_return_val_if_fail (widget == NULL, NULL);
3492 child = g_new (GtkToolbarChild, 1);
3496 child->label = NULL;
3500 case GTK_TOOLBAR_CHILD_SPACE:
3501 item = gtk_separator_tool_item_new ();
3502 child->widget = NULL;
3505 case GTK_TOOLBAR_CHILD_WIDGET:
3506 item = gtk_tool_item_new ();
3507 child->widget = widget;
3508 gtk_container_add (GTK_CONTAINER (item), child->widget);
3511 case GTK_TOOLBAR_CHILD_BUTTON:
3512 item = gtk_tool_button_new (NULL, NULL);
3513 child->widget = _gtk_tool_button_get_button (GTK_TOOL_BUTTON (item));
3516 case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
3517 item = gtk_toggle_tool_button_new ();
3518 child->widget = _gtk_tool_button_get_button (GTK_TOOL_BUTTON (item));
3521 case GTK_TOOLBAR_CHILD_RADIOBUTTON:
3522 item = gtk_radio_tool_button_new (widget
3523 ? gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget))
3525 child->widget = _gtk_tool_button_get_button (GTK_TOOL_BUTTON (item));
3530 * When we are using the old API, consider all items "is_important". That
3531 * way BOTH_HORIZ will continue to show both icon and label in old API mode
3533 gtk_tool_item_set_is_important (item, TRUE);
3535 gtk_widget_show (GTK_WIDGET (item));
3537 if (type == GTK_TOOLBAR_CHILD_BUTTON ||
3538 type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
3539 type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
3545 GtkStockItem stock_item;
3548 gtk_tool_button_set_stock_id (GTK_TOOL_BUTTON (item), text);
3550 gtk_stock_lookup (text, &stock_item);
3551 label_text = _gtk_toolbar_elide_underscores (stock_item.label);
3552 child->label = GTK_WIDGET (gtk_label_new (label_text));
3553 g_free (label_text);
3557 child->label = gtk_label_new (text);
3559 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (item), child->label);
3560 gtk_widget_show (child->label);
3566 gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (item), icon);
3568 /* Applications depend on the toolbar showing the widget for them */
3569 gtk_widget_show (GTK_WIDGET (icon));
3573 * We need to connect to the button's clicked callback because some
3574 * programs may rely on that the widget in the callback is a GtkButton
3577 g_signal_connect (child->widget, "clicked",
3578 callback, user_data);
3581 if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text)
3582 gtk_tool_item_set_tooltip (item, toolbar->tooltips,
3583 tooltip_text, tooltip_private_text);
3585 toolbar->children = g_list_insert (toolbar->children, child, position);
3587 gtk_toolbar_insert_tool_item (toolbar, item, position, FALSE);
3589 return child->widget;
3593 gtk_toolbar_finalize (GObject *object)
3596 GtkToolbar *toolbar = GTK_TOOLBAR (object);
3597 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3599 if (toolbar->tooltips)
3600 g_object_unref (toolbar->tooltips);
3602 for (list = toolbar->children; list != NULL; list = list->next)
3603 g_free (list->data);
3605 g_list_free (toolbar->children);
3607 for (list = priv->content; list != NULL; list = list->next)
3608 g_free (list->data);
3610 g_list_free (priv->content);
3612 g_timer_destroy (priv->timer);
3615 g_source_remove (priv->idle_id);
3617 G_OBJECT_CLASS (parent_class)->finalize (object);