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, 2004 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
39 #include <gdk/gdkkeysyms.h>
42 #include "gtkbindings.h"
47 #include "gtkmarshalers.h"
49 #include "gtkorientable.h"
50 #include "gtkradiobutton.h"
51 #include "gtkradiotoolbutton.h"
52 #include "gtkseparatormenuitem.h"
53 #include "gtkseparatortoolitem.h"
55 #include "gtktoolbar.h"
56 #include "gtktoolshell.h"
58 #include "gtkprivate.h"
62 typedef struct _ToolbarContent ToolbarContent;
64 #define DEFAULT_IPADDING 0
66 #define DEFAULT_SPACE_SIZE 12
67 #define DEFAULT_SPACE_STYLE GTK_TOOLBAR_SPACE_LINE
68 #define SPACE_LINE_DIVISION 10.0
69 #define SPACE_LINE_START 2.0
70 #define SPACE_LINE_END 8.0
72 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_LARGE_TOOLBAR
73 #define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_BOTH
74 #define DEFAULT_ANIMATION_STATE TRUE
76 #define MAX_HOMOGENEOUS_N_CHARS 13 /* Items that are wider than this do not participate
77 * in the homogeneous game. In units of
78 * pango_font_get_estimated_char_width().
80 #define SLIDE_SPEED 600.0 /* How fast the items slide, in pixels per second */
81 #define ACCEL_THRESHOLD 0.18 /* After how much time in seconds will items start speeding up */
83 #define MIXED_API_WARNING \
84 "Mixing deprecated and non-deprecated GtkToolbar API is not allowed"
98 /* Child properties */
102 CHILD_PROP_HOMOGENEOUS
133 struct _GtkToolbarPrivate
138 GtkWidget * arrow_button;
141 GdkWindow * event_window;
143 GtkSettings * settings;
145 GtkToolItem * highlight_tool_item;
146 gint max_homogeneous_pixels;
150 gulong settings_connection;
152 guint show_arrow : 1;
154 guint is_sliding : 1;
155 guint need_rebuild : 1; /* whether the overflow menu should be regenerated */
159 static void gtk_toolbar_set_property (GObject *object,
163 static void gtk_toolbar_get_property (GObject *object,
167 static gint gtk_toolbar_expose (GtkWidget *widget,
168 GdkEventExpose *event);
169 static void gtk_toolbar_realize (GtkWidget *widget);
170 static void gtk_toolbar_unrealize (GtkWidget *widget);
171 static void gtk_toolbar_size_request (GtkWidget *widget,
172 GtkRequisition *requisition);
173 static void gtk_toolbar_size_allocate (GtkWidget *widget,
174 GtkAllocation *allocation);
175 static void gtk_toolbar_style_set (GtkWidget *widget,
176 GtkStyle *prev_style);
177 static gboolean gtk_toolbar_focus (GtkWidget *widget,
178 GtkDirectionType dir);
179 static void gtk_toolbar_move_focus (GtkWidget *widget,
180 GtkDirectionType dir);
181 static void gtk_toolbar_screen_changed (GtkWidget *widget,
182 GdkScreen *previous_screen);
183 static void gtk_toolbar_map (GtkWidget *widget);
184 static void gtk_toolbar_unmap (GtkWidget *widget);
185 static void gtk_toolbar_set_child_property (GtkContainer *container,
190 static void gtk_toolbar_get_child_property (GtkContainer *container,
195 static void gtk_toolbar_finalize (GObject *object);
196 static void gtk_toolbar_show_all (GtkWidget *widget);
197 static void gtk_toolbar_hide_all (GtkWidget *widget);
198 static void gtk_toolbar_add (GtkContainer *container,
200 static void gtk_toolbar_remove (GtkContainer *container,
202 static void gtk_toolbar_forall (GtkContainer *container,
203 gboolean include_internals,
204 GtkCallback callback,
205 gpointer callback_data);
206 static GType gtk_toolbar_child_type (GtkContainer *container);
207 static void gtk_toolbar_orientation_changed (GtkToolbar *toolbar,
208 GtkOrientation orientation);
209 static void gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
210 GtkToolbarStyle style);
211 static gboolean gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
212 gboolean focus_home);
213 static gboolean gtk_toolbar_button_press (GtkWidget *toolbar,
214 GdkEventButton *event);
215 static gboolean gtk_toolbar_arrow_button_press (GtkWidget *button,
216 GdkEventButton *event,
217 GtkToolbar *toolbar);
218 static void gtk_toolbar_arrow_button_clicked (GtkWidget *button,
219 GtkToolbar *toolbar);
220 static void gtk_toolbar_update_button_relief (GtkToolbar *toolbar);
221 static gboolean gtk_toolbar_popup_menu (GtkWidget *toolbar);
222 static GtkWidget *internal_insert_element (GtkToolbar *toolbar,
223 GtkToolbarChildType type,
226 const char *tooltip_text,
227 const char *tooltip_private_text,
233 static void gtk_toolbar_reconfigured (GtkToolbar *toolbar);
234 static gboolean gtk_toolbar_check_new_api (GtkToolbar *toolbar);
235 static gboolean gtk_toolbar_check_old_api (GtkToolbar *toolbar);
237 static GtkReliefStyle get_button_relief (GtkToolbar *toolbar);
238 static gint get_internal_padding (GtkToolbar *toolbar);
239 static gint get_max_child_expand (GtkToolbar *toolbar);
240 static GtkShadowType get_shadow_type (GtkToolbar *toolbar);
241 static gint get_space_size (GtkToolbar *toolbar);
242 static GtkToolbarSpaceStyle get_space_style (GtkToolbar *toolbar);
244 /* methods on ToolbarContent 'class' */
245 static ToolbarContent *toolbar_content_new_tool_item (GtkToolbar *toolbar,
247 gboolean is_placeholder,
249 static ToolbarContent *toolbar_content_new_compatibility (GtkToolbar *toolbar,
250 GtkToolbarChildType type,
255 static void toolbar_content_remove (ToolbarContent *content,
256 GtkToolbar *toolbar);
257 static void toolbar_content_free (ToolbarContent *content);
258 static void toolbar_content_expose (ToolbarContent *content,
259 GtkContainer *container,
260 GdkEventExpose *expose);
261 static gboolean toolbar_content_visible (ToolbarContent *content,
262 GtkToolbar *toolbar);
263 static void toolbar_content_size_request (ToolbarContent *content,
265 GtkRequisition *requisition);
266 static gboolean toolbar_content_is_homogeneous (ToolbarContent *content,
267 GtkToolbar *toolbar);
268 static gboolean toolbar_content_is_placeholder (ToolbarContent *content);
269 static gboolean toolbar_content_disappearing (ToolbarContent *content);
270 static ItemState toolbar_content_get_state (ToolbarContent *content);
271 static gboolean toolbar_content_child_visible (ToolbarContent *content);
272 static void toolbar_content_get_goal_allocation (ToolbarContent *content,
273 GtkAllocation *allocation);
274 static void toolbar_content_get_allocation (ToolbarContent *content,
275 GtkAllocation *allocation);
276 static void toolbar_content_set_start_allocation (ToolbarContent *content,
277 GtkAllocation *new_start_allocation);
278 static void toolbar_content_get_start_allocation (ToolbarContent *content,
279 GtkAllocation *start_allocation);
280 static gboolean toolbar_content_get_expand (ToolbarContent *content);
281 static void toolbar_content_set_goal_allocation (ToolbarContent *content,
282 GtkAllocation *allocation);
283 static void toolbar_content_set_child_visible (ToolbarContent *content,
286 static void toolbar_content_size_allocate (ToolbarContent *content,
287 GtkAllocation *allocation);
288 static void toolbar_content_set_state (ToolbarContent *content,
289 ItemState new_state);
290 static GtkWidget * toolbar_content_get_widget (ToolbarContent *content);
291 static void toolbar_content_set_disappearing (ToolbarContent *content,
292 gboolean disappearing);
293 static void toolbar_content_set_size_request (ToolbarContent *content,
296 static void toolbar_content_toolbar_reconfigured (ToolbarContent *content,
297 GtkToolbar *toolbar);
298 static GtkWidget * toolbar_content_retrieve_menu_item (ToolbarContent *content);
299 static gboolean toolbar_content_has_proxy_menu_item (ToolbarContent *content);
300 static gboolean toolbar_content_is_separator (ToolbarContent *content);
301 static void toolbar_content_show_all (ToolbarContent *content);
302 static void toolbar_content_hide_all (ToolbarContent *content);
303 static void toolbar_content_set_expand (ToolbarContent *content,
306 static void toolbar_tool_shell_iface_init (GtkToolShellIface *iface);
307 static GtkIconSize toolbar_get_icon_size (GtkToolShell *shell);
308 static GtkOrientation toolbar_get_orientation (GtkToolShell *shell);
309 static GtkToolbarStyle toolbar_get_style (GtkToolShell *shell);
310 static GtkReliefStyle toolbar_get_relief_style (GtkToolShell *shell);
311 static void toolbar_rebuild_menu (GtkToolShell *shell);
313 #define GTK_TOOLBAR_GET_PRIVATE(o) \
314 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_TOOLBAR, GtkToolbarPrivate))
317 G_DEFINE_TYPE_WITH_CODE (GtkToolbar, gtk_toolbar, GTK_TYPE_CONTAINER,
318 G_IMPLEMENT_INTERFACE (GTK_TYPE_TOOL_SHELL,
319 toolbar_tool_shell_iface_init)
320 G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE,
323 static guint toolbar_signals[LAST_SIGNAL] = { 0 };
327 add_arrow_bindings (GtkBindingSet *binding_set,
329 GtkDirectionType dir)
331 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
333 gtk_binding_entry_add_signal (binding_set, keysym, 0,
335 GTK_TYPE_DIRECTION_TYPE, dir);
336 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
338 GTK_TYPE_DIRECTION_TYPE, dir);
342 add_ctrl_tab_bindings (GtkBindingSet *binding_set,
343 GdkModifierType modifiers,
344 GtkDirectionType direction)
346 gtk_binding_entry_add_signal (binding_set,
347 GDK_Tab, GDK_CONTROL_MASK | modifiers,
349 GTK_TYPE_DIRECTION_TYPE, direction);
350 gtk_binding_entry_add_signal (binding_set,
351 GDK_KP_Tab, GDK_CONTROL_MASK | modifiers,
353 GTK_TYPE_DIRECTION_TYPE, direction);
357 gtk_toolbar_class_init (GtkToolbarClass *klass)
359 GObjectClass *gobject_class;
360 GtkWidgetClass *widget_class;
361 GtkContainerClass *container_class;
362 GtkBindingSet *binding_set;
364 gobject_class = (GObjectClass *)klass;
365 widget_class = (GtkWidgetClass *)klass;
366 container_class = (GtkContainerClass *)klass;
368 gobject_class->set_property = gtk_toolbar_set_property;
369 gobject_class->get_property = gtk_toolbar_get_property;
370 gobject_class->finalize = gtk_toolbar_finalize;
372 widget_class->button_press_event = gtk_toolbar_button_press;
373 widget_class->expose_event = gtk_toolbar_expose;
374 widget_class->size_request = gtk_toolbar_size_request;
375 widget_class->size_allocate = gtk_toolbar_size_allocate;
376 widget_class->style_set = gtk_toolbar_style_set;
377 widget_class->focus = gtk_toolbar_focus;
379 /* need to override the base class function via override_class_handler,
380 * because the signal slot is not available in GtkWidgetClass
382 g_signal_override_class_handler ("move-focus",
384 G_CALLBACK (gtk_toolbar_move_focus));
386 widget_class->screen_changed = gtk_toolbar_screen_changed;
387 widget_class->realize = gtk_toolbar_realize;
388 widget_class->unrealize = gtk_toolbar_unrealize;
389 widget_class->map = gtk_toolbar_map;
390 widget_class->unmap = gtk_toolbar_unmap;
391 widget_class->popup_menu = gtk_toolbar_popup_menu;
392 widget_class->show_all = gtk_toolbar_show_all;
393 widget_class->hide_all = gtk_toolbar_hide_all;
395 container_class->add = gtk_toolbar_add;
396 container_class->remove = gtk_toolbar_remove;
397 container_class->forall = gtk_toolbar_forall;
398 container_class->child_type = gtk_toolbar_child_type;
399 container_class->get_child_property = gtk_toolbar_get_child_property;
400 container_class->set_child_property = gtk_toolbar_set_child_property;
402 klass->orientation_changed = gtk_toolbar_orientation_changed;
403 klass->style_changed = gtk_toolbar_real_style_changed;
406 * GtkToolbar::orientation-changed:
407 * @toolbar: the object which emitted the signal
408 * @orientation: the new #GtkOrientation of the toolbar
410 * Emitted when the orientation of the toolbar changes.
412 toolbar_signals[ORIENTATION_CHANGED] =
413 g_signal_new (I_("orientation-changed"),
414 G_OBJECT_CLASS_TYPE (klass),
416 G_STRUCT_OFFSET (GtkToolbarClass, orientation_changed),
418 g_cclosure_marshal_VOID__ENUM,
420 GTK_TYPE_ORIENTATION);
422 * GtkToolbar::style-changed:
423 * @toolbar: The #GtkToolbar which emitted the signal
424 * @style: the new #GtkToolbarStyle of the toolbar
426 * Emitted when the style of the toolbar changes.
428 toolbar_signals[STYLE_CHANGED] =
429 g_signal_new (I_("style-changed"),
430 G_OBJECT_CLASS_TYPE (klass),
432 G_STRUCT_OFFSET (GtkToolbarClass, style_changed),
434 g_cclosure_marshal_VOID__ENUM,
436 GTK_TYPE_TOOLBAR_STYLE);
438 * GtkToolbar::popup-context-menu:
439 * @toolbar: the #GtkToolbar which emitted the signal
440 * @x: the x coordinate of the point where the menu should appear
441 * @y: the y coordinate of the point where the menu should appear
442 * @button: the mouse button the user pressed, or -1
444 * Emitted when the user right-clicks the toolbar or uses the
445 * keybinding to display a popup menu.
447 * Application developers should handle this signal if they want
448 * to display a context menu on the toolbar. The context-menu should
449 * appear at the coordinates given by @x and @y. The mouse button
450 * number is given by the @button parameter. If the menu was popped
451 * up using the keybaord, @button is -1.
453 * Return value: return %TRUE if the signal was handled, %FALSE if not
455 toolbar_signals[POPUP_CONTEXT_MENU] =
456 g_signal_new (I_("popup-context-menu"),
457 G_OBJECT_CLASS_TYPE (klass),
459 G_STRUCT_OFFSET (GtkToolbarClass, popup_context_menu),
460 _gtk_boolean_handled_accumulator, NULL,
461 _gtk_marshal_BOOLEAN__INT_INT_INT,
463 G_TYPE_INT, G_TYPE_INT,
467 * GtkToolbar::focus-home-or-end:
468 * @toolbar: the #GtkToolbar which emitted the signal
469 * @focus_home: %TRUE if the first item should be focused
471 * A keybinding signal used internally by GTK+. This signal can't
472 * be used in application code
474 * Return value: %TRUE if the signal was handled, %FALSE if not
476 toolbar_signals[FOCUS_HOME_OR_END] =
477 g_signal_new_class_handler (I_("focus-home-or-end"),
478 G_OBJECT_CLASS_TYPE (klass),
479 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
480 G_CALLBACK (gtk_toolbar_focus_home_or_end),
482 _gtk_marshal_BOOLEAN__BOOLEAN,
487 g_object_class_override_property (gobject_class,
491 g_object_class_install_property (gobject_class,
493 g_param_spec_enum ("toolbar-style",
495 P_("How to draw the toolbar"),
496 GTK_TYPE_TOOLBAR_STYLE,
497 DEFAULT_TOOLBAR_STYLE,
498 GTK_PARAM_READWRITE));
499 g_object_class_install_property (gobject_class,
501 g_param_spec_boolean ("show-arrow",
503 P_("If an arrow should be shown if the toolbar doesn't fit"),
505 GTK_PARAM_READWRITE));
509 * GtkToolbar:tooltips:
511 * If the tooltips of the toolbar should be active or not.
515 g_object_class_install_property (gobject_class,
517 g_param_spec_boolean ("tooltips",
519 P_("If the tooltips of the toolbar should be active or not"),
521 GTK_PARAM_READWRITE));
525 * GtkToolbar:icon-size:
527 * The size of the icons in a toolbar is normally determined by
528 * the toolbar-icon-size setting. When this property is set, it
529 * overrides the setting.
531 * This should only be used for special-purpose toolbars, normal
532 * application toolbars should respect the user preferences for the
537 g_object_class_install_property (gobject_class,
539 g_param_spec_int ("icon-size",
541 P_("Size of icons in this toolbar"),
544 GTK_PARAM_READWRITE));
547 * GtkToolbar:icon-size-set:
549 * Is %TRUE if the icon-size property has been set.
553 g_object_class_install_property (gobject_class,
555 g_param_spec_boolean ("icon-size-set",
557 P_("Whether the icon-size property has been set"),
559 GTK_PARAM_READWRITE));
561 /* child properties */
562 gtk_container_class_install_child_property (container_class,
564 g_param_spec_boolean ("expand",
566 P_("Whether the item should receive extra space when the toolbar grows"),
568 GTK_PARAM_READWRITE));
570 gtk_container_class_install_child_property (container_class,
571 CHILD_PROP_HOMOGENEOUS,
572 g_param_spec_boolean ("homogeneous",
574 P_("Whether the item should be the same size as other homogeneous items"),
576 GTK_PARAM_READWRITE));
578 /* style properties */
579 gtk_widget_class_install_style_property (widget_class,
580 g_param_spec_int ("space-size",
582 P_("Size of spacers"),
586 GTK_PARAM_READABLE));
588 gtk_widget_class_install_style_property (widget_class,
589 g_param_spec_int ("internal-padding",
590 P_("Internal padding"),
591 P_("Amount of border space between the toolbar shadow and the buttons"),
595 GTK_PARAM_READABLE));
597 gtk_widget_class_install_style_property (widget_class,
598 g_param_spec_int ("max-child-expand",
599 P_("Maximum child expand"),
600 P_("Maximum amount of space an expandable item will be given"),
604 GTK_PARAM_READABLE));
606 gtk_widget_class_install_style_property (widget_class,
607 g_param_spec_enum ("space-style",
609 P_("Whether spacers are vertical lines or just blank"),
610 GTK_TYPE_TOOLBAR_SPACE_STYLE,
612 GTK_PARAM_READABLE));
614 gtk_widget_class_install_style_property (widget_class,
615 g_param_spec_enum ("button-relief",
617 P_("Type of bevel around toolbar buttons"),
618 GTK_TYPE_RELIEF_STYLE,
620 GTK_PARAM_READABLE));
621 gtk_widget_class_install_style_property (widget_class,
622 g_param_spec_enum ("shadow-type",
624 P_("Style of bevel around the toolbar"),
625 GTK_TYPE_SHADOW_TYPE,
627 GTK_PARAM_READABLE));
629 gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-style",
631 P_("Whether default toolbars have text only, text and icons, icons only, etc."),
632 GTK_TYPE_TOOLBAR_STYLE,
633 DEFAULT_TOOLBAR_STYLE,
634 GTK_PARAM_READWRITE));
636 gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-icon-size",
637 P_("Toolbar icon size"),
638 P_("Size of icons in default toolbars"),
641 GTK_PARAM_READWRITE));
643 binding_set = gtk_binding_set_by_class (klass);
645 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
646 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
647 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
648 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
650 gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
651 "focus-home-or-end", 1,
652 G_TYPE_BOOLEAN, TRUE);
653 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
654 "focus-home-or-end", 1,
655 G_TYPE_BOOLEAN, TRUE);
656 gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
657 "focus-home-or-end", 1,
658 G_TYPE_BOOLEAN, FALSE);
659 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
660 "focus-home-or-end", 1,
661 G_TYPE_BOOLEAN, FALSE);
663 add_ctrl_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
664 add_ctrl_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
666 g_type_class_add_private (gobject_class, sizeof (GtkToolbarPrivate));
670 toolbar_tool_shell_iface_init (GtkToolShellIface *iface)
672 iface->get_icon_size = toolbar_get_icon_size;
673 iface->get_orientation = toolbar_get_orientation;
674 iface->get_style = toolbar_get_style;
675 iface->get_relief_style = toolbar_get_relief_style;
676 iface->rebuild_menu = toolbar_rebuild_menu;
680 gtk_toolbar_init (GtkToolbar *toolbar)
682 GtkToolbarPrivate *priv;
684 GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS);
685 GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
687 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
689 toolbar->orientation = GTK_ORIENTATION_HORIZONTAL;
690 toolbar->style = DEFAULT_TOOLBAR_STYLE;
691 toolbar->icon_size = DEFAULT_ICON_SIZE;
692 priv->animation = DEFAULT_ANIMATION_STATE;
693 toolbar->tooltips = gtk_tooltips_new ();
694 g_object_ref_sink (toolbar->tooltips);
696 priv->arrow_button = gtk_toggle_button_new ();
697 g_signal_connect (priv->arrow_button, "button-press-event",
698 G_CALLBACK (gtk_toolbar_arrow_button_press), toolbar);
699 g_signal_connect (priv->arrow_button, "clicked",
700 G_CALLBACK (gtk_toolbar_arrow_button_clicked), toolbar);
701 gtk_button_set_relief (GTK_BUTTON (priv->arrow_button),
702 get_button_relief (toolbar));
704 priv->api_mode = DONT_KNOW;
706 gtk_button_set_focus_on_click (GTK_BUTTON (priv->arrow_button), FALSE);
708 priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
709 gtk_widget_set_name (priv->arrow, "gtk-toolbar-arrow");
710 gtk_widget_show (priv->arrow);
711 gtk_container_add (GTK_CONTAINER (priv->arrow_button), priv->arrow);
713 gtk_widget_set_parent (priv->arrow_button, GTK_WIDGET (toolbar));
715 /* which child position a drop will occur at */
717 priv->show_arrow = TRUE;
718 priv->settings = NULL;
720 priv->max_homogeneous_pixels = -1;
722 priv->timer = g_timer_new ();
726 gtk_toolbar_set_property (GObject *object,
731 GtkToolbar *toolbar = GTK_TOOLBAR (object);
735 case PROP_ORIENTATION:
736 g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0,
737 g_value_get_enum (value));
739 case PROP_TOOLBAR_STYLE:
740 gtk_toolbar_set_style (toolbar, g_value_get_enum (value));
742 case PROP_SHOW_ARROW:
743 gtk_toolbar_set_show_arrow (toolbar, g_value_get_boolean (value));
746 gtk_toolbar_set_tooltips (toolbar, g_value_get_boolean (value));
749 gtk_toolbar_set_icon_size (toolbar, g_value_get_int (value));
751 case PROP_ICON_SIZE_SET:
752 if (g_value_get_boolean (value))
753 toolbar->icon_size_set = TRUE;
755 gtk_toolbar_unset_icon_size (toolbar);
758 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
764 gtk_toolbar_get_property (GObject *object,
769 GtkToolbar *toolbar = GTK_TOOLBAR (object);
770 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
774 case PROP_ORIENTATION:
775 g_value_set_enum (value, toolbar->orientation);
777 case PROP_TOOLBAR_STYLE:
778 g_value_set_enum (value, toolbar->style);
780 case PROP_SHOW_ARROW:
781 g_value_set_boolean (value, priv->show_arrow);
784 g_value_set_boolean (value, gtk_toolbar_get_tooltips (toolbar));
787 g_value_set_int (value, gtk_toolbar_get_icon_size (toolbar));
789 case PROP_ICON_SIZE_SET:
790 g_value_set_boolean (value, toolbar->icon_size_set);
793 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
799 gtk_toolbar_map (GtkWidget *widget)
801 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
803 GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->map (widget);
805 if (priv->event_window)
806 gdk_window_show_unraised (priv->event_window);
810 gtk_toolbar_unmap (GtkWidget *widget)
812 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
814 if (priv->event_window)
815 gdk_window_hide (priv->event_window);
817 GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->unmap (widget);
821 gtk_toolbar_realize (GtkWidget *widget)
823 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
824 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
826 GdkWindowAttr attributes;
827 gint attributes_mask;
830 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
832 border_width = GTK_CONTAINER (widget)->border_width;
834 attributes.wclass = GDK_INPUT_ONLY;
835 attributes.window_type = GDK_WINDOW_CHILD;
836 attributes.x = widget->allocation.x + border_width;
837 attributes.y = widget->allocation.y + border_width;
838 attributes.width = widget->allocation.width - border_width * 2;
839 attributes.height = widget->allocation.height - border_width * 2;
840 attributes.event_mask = gtk_widget_get_events (widget);
841 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
842 GDK_BUTTON_RELEASE_MASK |
843 GDK_ENTER_NOTIFY_MASK |
844 GDK_LEAVE_NOTIFY_MASK);
846 attributes_mask = GDK_WA_X | GDK_WA_Y;
848 widget->window = gtk_widget_get_parent_window (widget);
849 g_object_ref (widget->window);
850 widget->style = gtk_style_attach (widget->style, widget->window);
852 priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
853 &attributes, attributes_mask);
854 gdk_window_set_user_data (priv->event_window, toolbar);
858 gtk_toolbar_unrealize (GtkWidget *widget)
860 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
862 if (priv->event_window)
864 gdk_window_set_user_data (priv->event_window, NULL);
865 gdk_window_destroy (priv->event_window);
866 priv->event_window = NULL;
869 GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->unrealize (widget);
873 gtk_toolbar_expose (GtkWidget *widget,
874 GdkEventExpose *event)
876 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
877 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
882 border_width = GTK_CONTAINER (widget)->border_width;
884 if (GTK_WIDGET_DRAWABLE (widget))
886 gtk_paint_box (widget->style,
888 GTK_WIDGET_STATE (widget),
889 get_shadow_type (toolbar),
890 &event->area, widget, "toolbar",
891 border_width + widget->allocation.x,
892 border_width + widget->allocation.y,
893 widget->allocation.width - 2 * border_width,
894 widget->allocation.height - 2 * border_width);
897 for (list = priv->content; list != NULL; list = list->next)
899 ToolbarContent *content = list->data;
901 toolbar_content_expose (content, GTK_CONTAINER (widget), event);
904 gtk_container_propagate_expose (GTK_CONTAINER (widget),
912 gtk_toolbar_size_request (GtkWidget *widget,
913 GtkRequisition *requisition)
915 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
916 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
918 gint max_child_height;
919 gint max_child_width;
920 gint max_homogeneous_child_width;
921 gint max_homogeneous_child_height;
922 gint homogeneous_size;
924 gint pack_front_size;
926 GtkRequisition arrow_requisition;
928 max_homogeneous_child_width = 0;
929 max_homogeneous_child_height = 0;
931 max_child_height = 0;
932 for (list = priv->content; list != NULL; list = list->next)
934 GtkRequisition requisition;
935 ToolbarContent *content = list->data;
937 if (!toolbar_content_visible (content, toolbar))
940 toolbar_content_size_request (content, toolbar, &requisition);
942 max_child_width = MAX (max_child_width, requisition.width);
943 max_child_height = MAX (max_child_height, requisition.height);
945 if (toolbar_content_is_homogeneous (content, toolbar))
947 max_homogeneous_child_width = MAX (max_homogeneous_child_width, requisition.width);
948 max_homogeneous_child_height = MAX (max_homogeneous_child_height, requisition.height);
952 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
953 homogeneous_size = max_homogeneous_child_width;
955 homogeneous_size = max_homogeneous_child_height;
958 for (list = priv->content; list != NULL; list = list->next)
960 ToolbarContent *content = list->data;
963 if (!toolbar_content_visible (content, toolbar))
966 if (toolbar_content_is_homogeneous (content, toolbar))
968 size = homogeneous_size;
972 GtkRequisition requisition;
974 toolbar_content_size_request (content, toolbar, &requisition);
976 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
977 size = requisition.width;
979 size = requisition.height;
982 pack_front_size += size;
985 if (priv->show_arrow && priv->api_mode == NEW_API)
987 gtk_widget_size_request (priv->arrow_button, &arrow_requisition);
989 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
990 long_req = arrow_requisition.width;
992 long_req = arrow_requisition.height;
994 /* There is no point requesting space for the arrow if that would take
995 * up more space than all the items combined
997 long_req = MIN (long_req, pack_front_size);
1001 arrow_requisition.height = 0;
1002 arrow_requisition.width = 0;
1004 long_req = pack_front_size;
1007 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1009 requisition->width = long_req;
1010 requisition->height = MAX (max_child_height, arrow_requisition.height);
1014 requisition->height = long_req;
1015 requisition->width = MAX (max_child_width, arrow_requisition.width);
1019 ipadding = get_internal_padding (toolbar);
1021 requisition->width += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width);
1022 requisition->height += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width);
1024 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1026 requisition->width += 2 * widget->style->xthickness;
1027 requisition->height += 2 * widget->style->ythickness;
1030 toolbar->button_maxw = max_homogeneous_child_width;
1031 toolbar->button_maxh = max_homogeneous_child_height;
1035 position (GtkToolbar *toolbar,
1042 if (! GTK_TOOLBAR_GET_PRIVATE (toolbar)->animation)
1045 if (elapsed <= ACCEL_THRESHOLD)
1047 n_pixels = SLIDE_SPEED * elapsed;
1051 /* The formula is a second degree polynomial in
1052 * @elapsed that has the line SLIDE_SPEED * @elapsed
1053 * as tangent for @elapsed == ACCEL_THRESHOLD.
1054 * This makes @n_pixels a smooth function of elapsed time.
1056 n_pixels = (SLIDE_SPEED / ACCEL_THRESHOLD) * elapsed * elapsed -
1057 SLIDE_SPEED * elapsed + SLIDE_SPEED * ACCEL_THRESHOLD;
1061 return MIN (from + n_pixels, to);
1063 return MAX (from - n_pixels, to);
1067 compute_intermediate_allocation (GtkToolbar *toolbar,
1068 const GtkAllocation *start,
1069 const GtkAllocation *goal,
1070 GtkAllocation *intermediate)
1072 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1073 gdouble elapsed = g_timer_elapsed (priv->timer, NULL);
1075 intermediate->x = position (toolbar, start->x, goal->x, elapsed);
1076 intermediate->y = position (toolbar, start->y, goal->y, elapsed);
1077 intermediate->width = position (toolbar, start->x + start->width,
1078 goal->x + goal->width,
1079 elapsed) - intermediate->x;
1080 intermediate->height = position (toolbar, start->y + start->height,
1081 goal->y + goal->height,
1082 elapsed) - intermediate->y;
1086 fixup_allocation_for_rtl (gint total_size,
1087 GtkAllocation *allocation)
1089 allocation->x += (total_size - (2 * allocation->x + allocation->width));
1093 fixup_allocation_for_vertical (GtkAllocation *allocation)
1097 tmp = allocation->x;
1098 allocation->x = allocation->y;
1099 allocation->y = tmp;
1101 tmp = allocation->width;
1102 allocation->width = allocation->height;
1103 allocation->height = tmp;
1107 get_item_size (GtkToolbar *toolbar,
1108 ToolbarContent *content)
1110 GtkRequisition requisition;
1112 toolbar_content_size_request (content, toolbar, &requisition);
1114 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1116 if (toolbar_content_is_homogeneous (content, toolbar))
1117 return toolbar->button_maxw;
1119 return requisition.width;
1123 if (toolbar_content_is_homogeneous (content, toolbar))
1124 return toolbar->button_maxh;
1126 return requisition.height;
1131 slide_idle_handler (gpointer data)
1133 GtkToolbar *toolbar = data;
1134 GtkToolbarPrivate *priv;
1137 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1139 if (priv->need_sync)
1142 priv->need_sync = FALSE;
1145 for (list = priv->content; list != NULL; list = list->next)
1147 ToolbarContent *content = list->data;
1149 GtkAllocation goal_allocation;
1150 GtkAllocation allocation;
1153 state = toolbar_content_get_state (content);
1154 toolbar_content_get_goal_allocation (content, &goal_allocation);
1155 toolbar_content_get_allocation (content, &allocation);
1159 if (state == NOT_ALLOCATED)
1161 /* an unallocated item means that size allocate has to
1162 * called at least once more
1167 /* An invisible item with a goal allocation of
1168 * 0 is already at its goal.
1170 if ((state == NORMAL || state == OVERFLOWN) &&
1171 ((goal_allocation.width != 0 &&
1172 goal_allocation.height != 0) ||
1173 toolbar_content_child_visible (content)))
1175 if ((goal_allocation.x != allocation.x ||
1176 goal_allocation.y != allocation.y ||
1177 goal_allocation.width != allocation.width ||
1178 goal_allocation.height != allocation.height))
1180 /* An item is not in its right position yet. Note
1181 * that OVERFLOWN items do get an allocation in
1182 * gtk_toolbar_size_allocate(). This way you can see
1183 * them slide back in when you drag an item off the
1190 if (toolbar_content_is_placeholder (content) &&
1191 toolbar_content_disappearing (content) &&
1192 toolbar_content_child_visible (content))
1194 /* A disappearing placeholder is still visible.
1202 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1208 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1210 priv->is_sliding = FALSE;
1217 rect_within (GtkAllocation *a1,
1220 return (a1->x >= a2->x &&
1221 a1->x + a1->width <= a2->x + a2->width &&
1223 a1->y + a1->height <= a2->y + a2->height);
1227 gtk_toolbar_begin_sliding (GtkToolbar *toolbar)
1229 GtkWidget *widget = GTK_WIDGET (toolbar);
1230 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1238 /* Start the sliding. This function copies the allocation of every
1239 * item into content->start_allocation. For items that haven't
1240 * been allocated yet, we calculate their position and save that
1241 * in start_allocatino along with zero width and zero height.
1243 * FIXME: It would be nice if we could share this code with
1244 * the equivalent in gtk_widget_size_allocate().
1246 priv->is_sliding = TRUE;
1249 priv->idle_id = gdk_threads_add_idle (slide_idle_handler, toolbar);
1251 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1252 vertical = (toolbar->orientation == GTK_ORIENTATION_VERTICAL);
1253 border_width = get_internal_padding (toolbar) + GTK_CONTAINER (toolbar)->border_width;
1257 cur_x = widget->allocation.width - border_width - widget->style->xthickness;
1258 cur_y = widget->allocation.height - border_width - widget->style->ythickness;
1262 cur_x = border_width + widget->style->xthickness;
1263 cur_y = border_width + widget->style->ythickness;
1266 cur_x += widget->allocation.x;
1267 cur_y += widget->allocation.y;
1269 for (list = priv->content; list != NULL; list = list->next)
1271 ToolbarContent *content = list->data;
1272 GtkAllocation new_start_allocation;
1273 GtkAllocation item_allocation;
1276 state = toolbar_content_get_state (content);
1277 toolbar_content_get_allocation (content, &item_allocation);
1279 if ((state == NORMAL &&
1280 rect_within (&item_allocation, &(widget->allocation))) ||
1283 new_start_allocation = item_allocation;
1287 new_start_allocation.x = cur_x;
1288 new_start_allocation.y = cur_y;
1292 new_start_allocation.width = widget->allocation.width -
1293 2 * border_width - 2 * widget->style->xthickness;
1294 new_start_allocation.height = 0;
1298 new_start_allocation.width = 0;
1299 new_start_allocation.height = widget->allocation.height -
1300 2 * border_width - 2 * widget->style->ythickness;
1305 cur_y = new_start_allocation.y + new_start_allocation.height;
1307 cur_x = new_start_allocation.x;
1309 cur_x = new_start_allocation.x + new_start_allocation.width;
1311 toolbar_content_set_start_allocation (content, &new_start_allocation);
1314 /* This resize will run before the first idle handler. This
1315 * will make sure that items get the right goal allocation
1316 * so that the idle handler will not immediately return
1319 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1320 g_timer_reset (priv->timer);
1324 gtk_toolbar_stop_sliding (GtkToolbar *toolbar)
1326 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1328 if (priv->is_sliding)
1332 priv->is_sliding = FALSE;
1336 g_source_remove (priv->idle_id);
1340 list = priv->content;
1343 ToolbarContent *content = list->data;
1346 if (toolbar_content_is_placeholder (content))
1348 toolbar_content_remove (content, toolbar);
1349 toolbar_content_free (content);
1353 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1358 remove_item (GtkWidget *menu_item,
1361 gtk_container_remove (GTK_CONTAINER (menu_item->parent), menu_item);
1365 menu_deactivated (GtkWidget *menu,
1366 GtkToolbar *toolbar)
1368 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1369 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->arrow_button), FALSE);
1373 menu_detached (GtkWidget *toolbar,
1376 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1381 rebuild_menu (GtkToolbar *toolbar)
1383 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1384 GList *list, *children;
1388 priv->menu = GTK_MENU (gtk_menu_new());
1389 gtk_menu_attach_to_widget (priv->menu,
1390 GTK_WIDGET (toolbar),
1393 g_signal_connect (priv->menu, "deactivate",
1394 G_CALLBACK (menu_deactivated), toolbar);
1397 gtk_container_foreach (GTK_CONTAINER (priv->menu), remove_item, NULL);
1399 for (list = priv->content; list != NULL; list = list->next)
1401 ToolbarContent *content = list->data;
1403 if (toolbar_content_get_state (content) == OVERFLOWN &&
1404 !toolbar_content_is_placeholder (content))
1406 GtkWidget *menu_item = toolbar_content_retrieve_menu_item (content);
1410 g_assert (GTK_IS_MENU_ITEM (menu_item));
1411 gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_item);
1416 /* Remove leading and trailing separator items */
1417 children = gtk_container_get_children (GTK_CONTAINER (priv->menu));
1420 while (list && GTK_IS_SEPARATOR_MENU_ITEM (list->data))
1422 GtkWidget *child = list->data;
1424 gtk_container_remove (GTK_CONTAINER (priv->menu), child);
1427 g_list_free (children);
1429 /* Regenerate the list of children so we don't try to remove items twice */
1430 children = gtk_container_get_children (GTK_CONTAINER (priv->menu));
1432 list = g_list_last (children);
1433 while (list && GTK_IS_SEPARATOR_MENU_ITEM (list->data))
1435 GtkWidget *child = list->data;
1437 gtk_container_remove (GTK_CONTAINER (priv->menu), child);
1440 g_list_free (children);
1442 priv->need_rebuild = FALSE;
1446 gtk_toolbar_size_allocate (GtkWidget *widget,
1447 GtkAllocation *allocation)
1449 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1450 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1451 GtkAllocation *allocations;
1452 ItemState *new_states;
1453 GtkAllocation arrow_allocation;
1455 gint size, pos, short_size;
1458 gboolean need_arrow;
1459 gint n_expand_items;
1461 gint available_size;
1464 GtkRequisition arrow_requisition;
1465 gboolean overflowing;
1466 gboolean size_changed;
1468 GtkAllocation item_area;
1469 GtkShadowType shadow_type;
1471 size_changed = FALSE;
1472 if (widget->allocation.x != allocation->x ||
1473 widget->allocation.y != allocation->y ||
1474 widget->allocation.width != allocation->width ||
1475 widget->allocation.height != allocation->height)
1477 size_changed = TRUE;
1481 gtk_toolbar_stop_sliding (toolbar);
1483 widget->allocation = *allocation;
1485 border_width = GTK_CONTAINER (toolbar)->border_width;
1487 if (GTK_WIDGET_REALIZED (widget))
1489 gdk_window_move_resize (priv->event_window,
1490 allocation->x + border_width,
1491 allocation->y + border_width,
1492 allocation->width - border_width * 2,
1493 allocation->height - border_width * 2);
1496 border_width += get_internal_padding (toolbar);
1498 gtk_widget_get_child_requisition (GTK_WIDGET (priv->arrow_button),
1499 &arrow_requisition);
1501 shadow_type = get_shadow_type (toolbar);
1503 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1505 available_size = size = allocation->width - 2 * border_width;
1506 short_size = allocation->height - 2 * border_width;
1507 arrow_size = arrow_requisition.width;
1509 if (shadow_type != GTK_SHADOW_NONE)
1511 available_size -= 2 * widget->style->xthickness;
1512 short_size -= 2 * widget->style->ythickness;
1517 available_size = size = allocation->height - 2 * border_width;
1518 short_size = allocation->width - 2 * border_width;
1519 arrow_size = arrow_requisition.height;
1521 if (shadow_type != GTK_SHADOW_NONE)
1523 available_size -= 2 * widget->style->ythickness;
1524 short_size -= 2 * widget->style->xthickness;
1528 n_items = g_list_length (priv->content);
1529 allocations = g_new0 (GtkAllocation, n_items);
1530 new_states = g_new0 (ItemState, n_items);
1534 for (list = priv->content; list != NULL; list = list->next)
1536 ToolbarContent *content = list->data;
1538 if (toolbar_content_visible (content, toolbar))
1540 needed_size += get_item_size (toolbar, content);
1542 /* Do we need an arrow?
1544 * Assume we don't, and see if any non-separator item with a
1545 * proxy menu item is then going to overflow.
1547 if (needed_size > available_size &&
1550 priv->api_mode == NEW_API &&
1551 toolbar_content_has_proxy_menu_item (content) &&
1552 !toolbar_content_is_separator (content))
1560 size = available_size - arrow_size;
1562 size = available_size;
1564 /* calculate widths and states of items */
1565 overflowing = FALSE;
1566 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1568 ToolbarContent *content = list->data;
1571 if (!toolbar_content_visible (content, toolbar))
1573 new_states[i] = HIDDEN;
1577 item_size = get_item_size (toolbar, content);
1578 if (item_size <= size && !overflowing)
1581 allocations[i].width = item_size;
1582 new_states[i] = NORMAL;
1587 new_states[i] = OVERFLOWN;
1588 allocations[i].width = item_size;
1592 /* calculate width of arrow */
1595 arrow_allocation.width = arrow_size;
1596 arrow_allocation.height = MAX (short_size, 1);
1599 /* expand expandable items */
1601 /* We don't expand when there is an overflow menu, because that leads to
1602 * weird jumps when items get moved to the overflow menu and the expanding
1603 * items suddenly get a lot of extra space
1607 gint max_child_expand;
1610 for (i = 0, list = priv->content; list != NULL; list = list->next, ++i)
1612 ToolbarContent *content = list->data;
1614 if (toolbar_content_get_expand (content) && new_states[i] == NORMAL)
1618 max_child_expand = get_max_child_expand (toolbar);
1619 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1621 ToolbarContent *content = list->data;
1623 if (toolbar_content_get_expand (content) && new_states[i] == NORMAL)
1625 gint extra = size / n_expand_items;
1626 if (size % n_expand_items != 0)
1629 if (extra > max_child_expand)
1630 extra = max_child_expand;
1632 allocations[i].width += extra;
1638 g_assert (n_expand_items == 0);
1641 /* position items */
1643 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1645 /* both NORMAL and OVERFLOWN items get a position. This ensures
1646 * that sliding will work for OVERFLOWN items too
1648 if (new_states[i] == NORMAL ||
1649 new_states[i] == OVERFLOWN)
1651 allocations[i].x = pos;
1652 allocations[i].y = border_width;
1653 allocations[i].height = short_size;
1655 pos += allocations[i].width;
1659 /* position arrow */
1662 arrow_allocation.x = available_size - border_width - arrow_allocation.width;
1663 arrow_allocation.y = border_width;
1666 item_area.x = border_width;
1667 item_area.y = border_width;
1668 item_area.width = available_size - (need_arrow? arrow_size : 0);
1669 item_area.height = short_size;
1671 /* fix up allocations in the vertical or RTL cases */
1672 if (toolbar->orientation == GTK_ORIENTATION_VERTICAL)
1674 for (i = 0; i < n_items; ++i)
1675 fixup_allocation_for_vertical (&(allocations[i]));
1678 fixup_allocation_for_vertical (&arrow_allocation);
1680 fixup_allocation_for_vertical (&item_area);
1682 else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1684 for (i = 0; i < n_items; ++i)
1685 fixup_allocation_for_rtl (available_size, &(allocations[i]));
1688 fixup_allocation_for_rtl (available_size, &arrow_allocation);
1690 fixup_allocation_for_rtl (available_size, &item_area);
1693 /* translate the items by allocation->(x,y) */
1694 for (i = 0; i < n_items; ++i)
1696 allocations[i].x += allocation->x;
1697 allocations[i].y += allocation->y;
1699 if (shadow_type != GTK_SHADOW_NONE)
1701 allocations[i].x += widget->style->xthickness;
1702 allocations[i].y += widget->style->ythickness;
1708 arrow_allocation.x += allocation->x;
1709 arrow_allocation.y += allocation->y;
1711 if (shadow_type != GTK_SHADOW_NONE)
1713 arrow_allocation.x += widget->style->xthickness;
1714 arrow_allocation.y += widget->style->ythickness;
1718 item_area.x += allocation->x;
1719 item_area.y += allocation->y;
1720 if (shadow_type != GTK_SHADOW_NONE)
1722 item_area.x += widget->style->xthickness;
1723 item_area.y += widget->style->ythickness;
1726 /* did anything change? */
1727 for (list = priv->content, i = 0; list != NULL; list = list->next, i++)
1729 ToolbarContent *content = list->data;
1731 if (toolbar_content_get_state (content) == NORMAL &&
1732 new_states[i] != NORMAL)
1734 /* an item disappeared and we didn't change size, so begin sliding */
1735 if (!size_changed && priv->api_mode == NEW_API)
1736 gtk_toolbar_begin_sliding (toolbar);
1740 /* finally allocate the items */
1741 if (priv->is_sliding)
1743 for (list = priv->content, i = 0; list != NULL; list = list->next, i++)
1745 ToolbarContent *content = list->data;
1747 toolbar_content_set_goal_allocation (content, &(allocations[i]));
1751 elapsed = g_timer_elapsed (priv->timer, NULL);
1752 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1754 ToolbarContent *content = list->data;
1756 if (new_states[i] == OVERFLOWN ||
1757 new_states[i] == NORMAL)
1759 GtkAllocation alloc;
1760 GtkAllocation start_allocation = { 0, };
1761 GtkAllocation goal_allocation;
1763 if (priv->is_sliding)
1765 toolbar_content_get_start_allocation (content, &start_allocation);
1766 toolbar_content_get_goal_allocation (content, &goal_allocation);
1768 compute_intermediate_allocation (toolbar,
1773 priv->need_sync = TRUE;
1777 alloc = allocations[i];
1780 if (alloc.width <= 0 || alloc.height <= 0)
1782 toolbar_content_set_child_visible (content, toolbar, FALSE);
1786 if (!rect_within (&alloc, &item_area))
1788 toolbar_content_set_child_visible (content, toolbar, FALSE);
1789 toolbar_content_size_allocate (content, &alloc);
1793 toolbar_content_set_child_visible (content, toolbar, TRUE);
1794 toolbar_content_size_allocate (content, &alloc);
1800 toolbar_content_set_child_visible (content, toolbar, FALSE);
1803 toolbar_content_set_state (content, new_states[i]);
1806 if (priv->menu && priv->need_rebuild)
1807 rebuild_menu (toolbar);
1811 gtk_widget_size_allocate (GTK_WIDGET (priv->arrow_button),
1813 gtk_widget_show (GTK_WIDGET (priv->arrow_button));
1817 gtk_widget_hide (GTK_WIDGET (priv->arrow_button));
1819 if (priv->menu && GTK_WIDGET_VISIBLE (priv->menu))
1820 gtk_menu_shell_deactivate (GTK_MENU_SHELL (priv->menu));
1823 g_free (allocations);
1824 g_free (new_states);
1828 gtk_toolbar_update_button_relief (GtkToolbar *toolbar)
1830 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1831 GtkReliefStyle relief;
1833 relief = get_button_relief (toolbar);
1835 if (relief != gtk_button_get_relief (GTK_BUTTON (priv->arrow_button)))
1837 gtk_toolbar_reconfigured (toolbar);
1839 gtk_button_set_relief (GTK_BUTTON (priv->arrow_button), relief);
1844 gtk_toolbar_style_set (GtkWidget *widget,
1845 GtkStyle *prev_style)
1847 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
1849 priv->max_homogeneous_pixels = -1;
1851 if (GTK_WIDGET_REALIZED (widget))
1852 gtk_style_set_background (widget->style, widget->window, widget->state);
1855 gtk_toolbar_update_button_relief (GTK_TOOLBAR (widget));
1859 gtk_toolbar_list_children_in_focus_order (GtkToolbar *toolbar,
1860 GtkDirectionType dir)
1862 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1863 GList *result = NULL;
1867 /* generate list of children in reverse logical order */
1869 for (list = priv->content; list != NULL; list = list->next)
1871 ToolbarContent *content = list->data;
1874 widget = toolbar_content_get_widget (content);
1877 result = g_list_prepend (result, widget);
1880 result = g_list_prepend (result, priv->arrow_button);
1882 rtl = (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL);
1884 /* move in logical order when
1886 * - dir is TAB_FORWARD
1888 * - in RTL mode and moving left or up
1890 * - in LTR mode and moving right or down
1892 if (dir == GTK_DIR_TAB_FORWARD ||
1893 (rtl && (dir == GTK_DIR_UP || dir == GTK_DIR_LEFT)) ||
1894 (!rtl && (dir == GTK_DIR_DOWN || dir == GTK_DIR_RIGHT)))
1896 result = g_list_reverse (result);
1903 gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
1904 gboolean focus_home)
1906 GList *children, *list;
1907 GtkDirectionType dir = focus_home? GTK_DIR_RIGHT : GTK_DIR_LEFT;
1909 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1911 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1913 children = g_list_reverse (children);
1915 dir = (dir == GTK_DIR_RIGHT)? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1918 for (list = children; list != NULL; list = list->next)
1920 GtkWidget *child = list->data;
1922 if (GTK_CONTAINER (toolbar)->focus_child == child)
1925 if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1929 g_list_free (children);
1934 /* Keybinding handler. This function is called when the user presses
1935 * Ctrl TAB or an arrow key.
1938 gtk_toolbar_move_focus (GtkWidget *widget,
1939 GtkDirectionType dir)
1941 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1942 GtkContainer *container = GTK_CONTAINER (toolbar);
1944 gboolean try_focus = FALSE;
1947 if (container->focus_child &&
1948 gtk_widget_child_focus (container->focus_child, dir))
1953 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1955 for (list = children; list != NULL; list = list->next)
1957 GtkWidget *child = list->data;
1959 if (try_focus && GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1962 if (child == GTK_CONTAINER (toolbar)->focus_child)
1966 g_list_free (children);
1969 /* The focus handler for the toolbar. It called when the user presses
1970 * TAB or otherwise tries to focus the toolbar.
1973 gtk_toolbar_focus (GtkWidget *widget,
1974 GtkDirectionType dir)
1976 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1977 GList *children, *list;
1978 gboolean result = FALSE;
1980 /* if focus is already somewhere inside the toolbar then return FALSE.
1981 * The only way focus can stay inside the toolbar is when the user presses
1982 * arrow keys or Ctrl TAB (both of which are handled by the
1983 * gtk_toolbar_move_focus() keybinding function.
1985 if (GTK_CONTAINER (widget)->focus_child)
1988 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1990 for (list = children; list != NULL; list = list->next)
1992 GtkWidget *child = list->data;
1994 if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
2001 g_list_free (children);
2006 static GtkSettings *
2007 toolbar_get_settings (GtkToolbar *toolbar)
2009 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2010 return priv->settings;
2014 style_change_notify (GtkToolbar *toolbar)
2016 if (!toolbar->style_set)
2018 /* pretend it was set, then unset, thus reverting to new default */
2019 toolbar->style_set = TRUE;
2020 gtk_toolbar_unset_style (toolbar);
2025 icon_size_change_notify (GtkToolbar *toolbar)
2027 if (!toolbar->icon_size_set)
2029 /* pretend it was set, then unset, thus reverting to new default */
2030 toolbar->icon_size_set = TRUE;
2031 gtk_toolbar_unset_icon_size (toolbar);
2036 animation_change_notify (GtkToolbar *toolbar)
2038 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2039 GtkSettings *settings = toolbar_get_settings (toolbar);
2043 g_object_get (settings,
2044 "gtk-enable-animations", &animation,
2047 animation = DEFAULT_ANIMATION_STATE;
2049 priv->animation = animation;
2053 settings_change_notify (GtkSettings *settings,
2054 const GParamSpec *pspec,
2055 GtkToolbar *toolbar)
2057 if (! strcmp (pspec->name, "gtk-toolbar-style"))
2058 style_change_notify (toolbar);
2059 else if (! strcmp (pspec->name, "gtk-toolbar-icon-size"))
2060 icon_size_change_notify (toolbar);
2061 else if (! strcmp (pspec->name, "gtk-enable-animations"))
2062 animation_change_notify (toolbar);
2066 gtk_toolbar_screen_changed (GtkWidget *widget,
2067 GdkScreen *previous_screen)
2069 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
2070 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
2071 GtkSettings *old_settings = toolbar_get_settings (toolbar);
2072 GtkSettings *settings;
2074 if (gtk_widget_has_screen (GTK_WIDGET (toolbar)))
2075 settings = gtk_widget_get_settings (GTK_WIDGET (toolbar));
2079 if (settings == old_settings)
2084 g_signal_handler_disconnect (old_settings, priv->settings_connection);
2086 g_object_unref (old_settings);
2091 priv->settings_connection =
2092 g_signal_connect (settings, "notify",
2093 G_CALLBACK (settings_change_notify),
2096 priv->settings = g_object_ref (settings);
2099 priv->settings = NULL;
2101 style_change_notify (toolbar);
2102 icon_size_change_notify (toolbar);
2103 animation_change_notify (toolbar);
2107 find_drop_index (GtkToolbar *toolbar,
2111 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2112 GList *interesting_content;
2114 GtkOrientation orientation;
2115 GtkTextDirection direction;
2116 gint best_distance = G_MAXINT;
2120 ToolbarContent *best_content;
2121 GtkAllocation allocation;
2123 /* list items we care about wrt. drag and drop */
2124 interesting_content = NULL;
2125 for (list = priv->content; list != NULL; list = list->next)
2127 ToolbarContent *content = list->data;
2129 if (toolbar_content_get_state (content) == NORMAL)
2130 interesting_content = g_list_prepend (interesting_content, content);
2132 interesting_content = g_list_reverse (interesting_content);
2134 if (!interesting_content)
2137 orientation = toolbar->orientation;
2138 direction = gtk_widget_get_direction (GTK_WIDGET (toolbar));
2140 /* distance to first interesting item */
2141 best_content = interesting_content->data;
2142 toolbar_content_get_allocation (best_content, &allocation);
2144 if (orientation == GTK_ORIENTATION_HORIZONTAL)
2148 if (direction == GTK_TEXT_DIR_LTR)
2151 pos = allocation.x + allocation.width;
2159 best_content = NULL;
2160 best_distance = ABS (pos - cursor);
2162 /* distance to far end of each item */
2163 for (list = interesting_content; list != NULL; list = list->next)
2165 ToolbarContent *content = list->data;
2167 toolbar_content_get_allocation (content, &allocation);
2169 if (orientation == GTK_ORIENTATION_HORIZONTAL)
2171 if (direction == GTK_TEXT_DIR_LTR)
2172 pos = allocation.x + allocation.width;
2178 pos = allocation.y + allocation.height;
2181 distance = ABS (pos - cursor);
2183 if (distance < best_distance)
2185 best_distance = distance;
2186 best_content = content;
2190 g_list_free (interesting_content);
2195 return g_list_index (priv->content, best_content) + 1;
2199 reset_all_placeholders (GtkToolbar *toolbar)
2201 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2204 for (list = priv->content; list != NULL; list = list->next)
2206 ToolbarContent *content = list->data;
2207 if (toolbar_content_is_placeholder (content))
2208 toolbar_content_set_disappearing (content, TRUE);
2213 physical_to_logical (GtkToolbar *toolbar,
2216 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2220 g_assert (physical >= 0);
2223 for (list = priv->content; list && physical > 0; list = list->next)
2225 ToolbarContent *content = list->data;
2227 if (!toolbar_content_is_placeholder (content))
2232 g_assert (physical == 0);
2238 logical_to_physical (GtkToolbar *toolbar,
2241 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2245 g_assert (logical >= 0);
2248 for (list = priv->content; list; list = list->next)
2250 ToolbarContent *content = list->data;
2252 if (!toolbar_content_is_placeholder (content))
2262 g_assert (logical == 0);
2268 * gtk_toolbar_set_drop_highlight_item:
2269 * @toolbar: a #GtkToolbar
2270 * @tool_item: a #GtkToolItem, or %NULL to turn of highlighting
2271 * @index_: a position on @toolbar
2273 * Highlights @toolbar to give an idea of what it would look like
2274 * if @item was added to @toolbar at the position indicated by @index_.
2275 * If @item is %NULL, highlighting is turned off. In that case @index_
2278 * The @tool_item passed to this function must not be part of any widget
2279 * hierarchy. When an item is set as drop highlight item it can not
2280 * added to any widget hierarchy or used as highlight item for another
2286 gtk_toolbar_set_drop_highlight_item (GtkToolbar *toolbar,
2287 GtkToolItem *tool_item,
2290 ToolbarContent *content;
2291 GtkToolbarPrivate *priv;
2293 GtkRequisition requisition;
2294 GtkRequisition old_requisition;
2295 gboolean restart_sliding;
2297 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2298 g_return_if_fail (tool_item == NULL || GTK_IS_TOOL_ITEM (tool_item));
2300 gtk_toolbar_check_new_api (toolbar);
2302 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2306 if (priv->highlight_tool_item)
2308 gtk_widget_unparent (GTK_WIDGET (priv->highlight_tool_item));
2309 g_object_unref (priv->highlight_tool_item);
2310 priv->highlight_tool_item = NULL;
2313 reset_all_placeholders (toolbar);
2314 gtk_toolbar_begin_sliding (toolbar);
2318 n_items = gtk_toolbar_get_n_items (toolbar);
2319 if (index_ < 0 || index_ > n_items)
2322 if (tool_item != priv->highlight_tool_item)
2324 if (priv->highlight_tool_item)
2325 g_object_unref (priv->highlight_tool_item);
2327 g_object_ref_sink (tool_item);
2329 priv->highlight_tool_item = tool_item;
2331 gtk_widget_set_parent (GTK_WIDGET (priv->highlight_tool_item),
2332 GTK_WIDGET (toolbar));
2335 index_ = logical_to_physical (toolbar, index_);
2337 content = g_list_nth_data (priv->content, index_);
2341 ToolbarContent *prev_content;
2343 prev_content = g_list_nth_data (priv->content, index_ - 1);
2345 if (prev_content && toolbar_content_is_placeholder (prev_content))
2346 content = prev_content;
2349 if (!content || !toolbar_content_is_placeholder (content))
2351 GtkWidget *placeholder;
2353 placeholder = GTK_WIDGET (gtk_separator_tool_item_new ());
2355 content = toolbar_content_new_tool_item (toolbar,
2356 GTK_TOOL_ITEM (placeholder),
2358 gtk_widget_show (placeholder);
2362 g_assert (toolbar_content_is_placeholder (content));
2364 gtk_widget_size_request (GTK_WIDGET (priv->highlight_tool_item),
2367 toolbar_content_set_expand (content, gtk_tool_item_get_expand (tool_item));
2369 restart_sliding = FALSE;
2370 toolbar_content_size_request (content, toolbar, &old_requisition);
2371 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
2373 requisition.height = -1;
2374 if (requisition.width != old_requisition.width)
2375 restart_sliding = TRUE;
2379 requisition.width = -1;
2380 if (requisition.height != old_requisition.height)
2381 restart_sliding = TRUE;
2384 if (toolbar_content_disappearing (content))
2385 restart_sliding = TRUE;
2387 reset_all_placeholders (toolbar);
2388 toolbar_content_set_disappearing (content, FALSE);
2390 toolbar_content_set_size_request (content,
2391 requisition.width, requisition.height);
2393 if (restart_sliding)
2394 gtk_toolbar_begin_sliding (toolbar);
2398 gtk_toolbar_get_child_property (GtkContainer *container,
2404 GtkToolItem *item = GTK_TOOL_ITEM (child);
2406 switch (property_id)
2408 case CHILD_PROP_HOMOGENEOUS:
2409 g_value_set_boolean (value, gtk_tool_item_get_homogeneous (item));
2412 case CHILD_PROP_EXPAND:
2413 g_value_set_boolean (value, gtk_tool_item_get_expand (item));
2417 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2423 gtk_toolbar_set_child_property (GtkContainer *container,
2426 const GValue *value,
2429 switch (property_id)
2431 case CHILD_PROP_HOMOGENEOUS:
2432 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
2435 case CHILD_PROP_EXPAND:
2436 gtk_tool_item_set_expand (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
2440 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2446 gtk_toolbar_show_all (GtkWidget *widget)
2448 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
2451 for (list = priv->content; list != NULL; list = list->next)
2453 ToolbarContent *content = list->data;
2455 toolbar_content_show_all (content);
2458 gtk_widget_show (widget);
2462 gtk_toolbar_hide_all (GtkWidget *widget)
2464 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
2467 for (list = priv->content; list != NULL; list = list->next)
2469 ToolbarContent *content = list->data;
2471 toolbar_content_hide_all (content);
2474 gtk_widget_hide (widget);
2478 gtk_toolbar_add (GtkContainer *container,
2481 GtkToolbar *toolbar = GTK_TOOLBAR (container);
2483 if (GTK_IS_TOOL_ITEM (widget))
2484 gtk_toolbar_insert (toolbar, GTK_TOOL_ITEM (widget), -1);
2486 gtk_toolbar_append_widget (toolbar, widget, NULL, NULL);
2490 gtk_toolbar_remove (GtkContainer *container,
2493 GtkToolbar *toolbar = GTK_TOOLBAR (container);
2494 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2495 ToolbarContent *content_to_remove;
2498 content_to_remove = NULL;
2499 for (list = priv->content; list != NULL; list = list->next)
2501 ToolbarContent *content = list->data;
2504 child = toolbar_content_get_widget (content);
2505 if (child && child == widget)
2507 content_to_remove = content;
2512 g_return_if_fail (content_to_remove != NULL);
2514 toolbar_content_remove (content_to_remove, toolbar);
2515 toolbar_content_free (content_to_remove);
2519 gtk_toolbar_forall (GtkContainer *container,
2520 gboolean include_internals,
2521 GtkCallback callback,
2522 gpointer callback_data)
2524 GtkToolbar *toolbar = GTK_TOOLBAR (container);
2525 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2528 g_return_if_fail (callback != NULL);
2530 list = priv->content;
2533 ToolbarContent *content = list->data;
2534 GList *next = list->next;
2536 if (include_internals || !toolbar_content_is_placeholder (content))
2538 GtkWidget *child = toolbar_content_get_widget (content);
2541 callback (child, callback_data);
2547 if (include_internals)
2548 callback (priv->arrow_button, callback_data);
2552 gtk_toolbar_child_type (GtkContainer *container)
2554 return GTK_TYPE_TOOL_ITEM;
2558 gtk_toolbar_reconfigured (GtkToolbar *toolbar)
2560 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2563 list = priv->content;
2566 ToolbarContent *content = list->data;
2567 GList *next = list->next;
2569 toolbar_content_toolbar_reconfigured (content, toolbar);
2576 gtk_toolbar_orientation_changed (GtkToolbar *toolbar,
2577 GtkOrientation orientation)
2579 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2580 if (toolbar->orientation != orientation)
2582 toolbar->orientation = orientation;
2584 if (orientation == GTK_ORIENTATION_HORIZONTAL)
2585 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_DOWN, GTK_SHADOW_NONE);
2587 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
2589 gtk_toolbar_reconfigured (toolbar);
2591 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2592 g_object_notify (G_OBJECT (toolbar), "orientation");
2597 gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
2598 GtkToolbarStyle style)
2600 if (toolbar->style != style)
2602 toolbar->style = style;
2604 gtk_toolbar_reconfigured (toolbar);
2606 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2607 g_object_notify (G_OBJECT (toolbar), "toolbar-style");
2612 menu_position_func (GtkMenu *menu,
2618 GtkToolbar *toolbar = GTK_TOOLBAR (user_data);
2619 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2621 GtkRequisition menu_req;
2622 GdkRectangle monitor;
2626 gtk_widget_size_request (priv->arrow_button, &req);
2627 gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
2629 screen = gtk_widget_get_screen (GTK_WIDGET (menu));
2630 monitor_num = gdk_screen_get_monitor_at_window (screen, priv->arrow_button->window);
2631 if (monitor_num < 0)
2633 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
2635 gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y);
2636 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
2638 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2639 *x += priv->arrow_button->allocation.width - req.width;
2641 *x += req.width - menu_req.width;
2643 if ((*y + priv->arrow_button->allocation.height + menu_req.height) <= monitor.y + monitor.height)
2644 *y += priv->arrow_button->allocation.height;
2645 else if ((*y - menu_req.height) >= monitor.y)
2646 *y -= menu_req.height;
2647 else if (monitor.y + monitor.height - (*y + priv->arrow_button->allocation.height) > *y)
2648 *y += priv->arrow_button->allocation.height;
2650 *y -= menu_req.height;
2654 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2655 *x += priv->arrow_button->allocation.width;
2657 *x -= menu_req.width;
2659 if (*y + menu_req.height > monitor.y + monitor.height &&
2660 *y + priv->arrow_button->allocation.height - monitor.y > monitor.y + monitor.height - *y)
2661 *y += priv->arrow_button->allocation.height - menu_req.height;
2668 show_menu (GtkToolbar *toolbar,
2669 GdkEventButton *event)
2671 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2673 rebuild_menu (toolbar);
2675 gtk_widget_show_all (GTK_WIDGET (priv->menu));
2677 gtk_menu_popup (priv->menu, NULL, NULL,
2678 menu_position_func, toolbar,
2679 event? event->button : 0,
2680 event? event->time : gtk_get_current_event_time());
2684 gtk_toolbar_arrow_button_clicked (GtkWidget *button,
2685 GtkToolbar *toolbar)
2687 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2689 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->arrow_button)) &&
2690 (!priv->menu || !GTK_WIDGET_VISIBLE (priv->menu)))
2692 /* We only get here when the button is clicked with the keyboard,
2693 * because mouse button presses result in the menu being shown so
2694 * that priv->menu would be non-NULL and visible.
2696 show_menu (toolbar, NULL);
2697 gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menu), FALSE);
2702 gtk_toolbar_arrow_button_press (GtkWidget *button,
2703 GdkEventButton *event,
2704 GtkToolbar *toolbar)
2706 show_menu (toolbar, event);
2707 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2713 gtk_toolbar_button_press (GtkWidget *toolbar,
2714 GdkEventButton *event)
2716 if (event->button == 3)
2718 gboolean return_value;
2720 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2721 (int)event->x_root, (int)event->y_root, event->button,
2724 return return_value;
2731 gtk_toolbar_popup_menu (GtkWidget *toolbar)
2733 gboolean return_value;
2734 /* This function is the handler for the "popup menu" keybinding,
2735 * ie., it is called when the user presses Shift F10
2737 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2738 -1, -1, -1, &return_value);
2740 return return_value;
2746 * Creates a new toolbar.
2748 * Return Value: the newly-created toolbar.
2751 gtk_toolbar_new (void)
2753 GtkToolbar *toolbar;
2755 toolbar = g_object_new (GTK_TYPE_TOOLBAR, NULL);
2757 return GTK_WIDGET (toolbar);
2761 * gtk_toolbar_insert:
2762 * @toolbar: a #GtkToolbar
2763 * @item: a #GtkToolItem
2764 * @pos: the position of the new item
2766 * Insert a #GtkToolItem into the toolbar at position @pos. If @pos is
2767 * 0 the item is prepended to the start of the toolbar. If @pos is
2768 * negative, the item is appended to the end of the toolbar.
2773 gtk_toolbar_insert (GtkToolbar *toolbar,
2777 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2778 g_return_if_fail (GTK_IS_TOOL_ITEM (item));
2780 if (!gtk_toolbar_check_new_api (toolbar))
2784 pos = logical_to_physical (toolbar, pos);
2786 toolbar_content_new_tool_item (toolbar, item, FALSE, pos);
2790 * gtk_toolbar_get_item_index:
2791 * @toolbar: a #GtkToolbar
2792 * @item: a #GtkToolItem that is a child of @toolbar
2794 * Returns the position of @item on the toolbar, starting from 0.
2795 * It is an error if @item is not a child of the toolbar.
2797 * Return value: the position of item on the toolbar.
2802 gtk_toolbar_get_item_index (GtkToolbar *toolbar,
2805 GtkToolbarPrivate *priv;
2809 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2810 g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1);
2811 g_return_val_if_fail (GTK_WIDGET (item)->parent == GTK_WIDGET (toolbar), -1);
2813 if (!gtk_toolbar_check_new_api (toolbar))
2816 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2819 for (list = priv->content; list != NULL; list = list->next)
2821 ToolbarContent *content = list->data;
2824 widget = toolbar_content_get_widget (content);
2826 if (item == GTK_TOOL_ITEM (widget))
2832 return physical_to_logical (toolbar, n);
2836 * gtk_toolbar_set_orientation:
2837 * @toolbar: a #GtkToolbar.
2838 * @orientation: a new #GtkOrientation.
2840 * Sets whether a toolbar should appear horizontally or vertically.
2842 * Deprecated: 2.16: Use gtk_orientable_set_orientation() instead.
2845 gtk_toolbar_set_orientation (GtkToolbar *toolbar,
2846 GtkOrientation orientation)
2848 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2850 g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0, orientation);
2854 * gtk_toolbar_get_orientation:
2855 * @toolbar: a #GtkToolbar
2857 * Retrieves the current orientation of the toolbar. See
2858 * gtk_toolbar_set_orientation().
2860 * Return value: the orientation
2862 * Deprecated: 2.16: Use gtk_orientable_get_orientation() instead.
2865 gtk_toolbar_get_orientation (GtkToolbar *toolbar)
2867 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
2869 return toolbar->orientation;
2873 * gtk_toolbar_set_style:
2874 * @toolbar: a #GtkToolbar.
2875 * @style: the new style for @toolbar.
2877 * Alters the view of @toolbar to display either icons only, text only, or both.
2880 gtk_toolbar_set_style (GtkToolbar *toolbar,
2881 GtkToolbarStyle style)
2883 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2885 toolbar->style_set = TRUE;
2886 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2890 * gtk_toolbar_get_style:
2891 * @toolbar: a #GtkToolbar
2893 * Retrieves whether the toolbar has text, icons, or both . See
2894 * gtk_toolbar_set_style().
2896 * Return value: the current style of @toolbar
2899 gtk_toolbar_get_style (GtkToolbar *toolbar)
2901 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_TOOLBAR_STYLE);
2903 return toolbar->style;
2907 * gtk_toolbar_unset_style:
2908 * @toolbar: a #GtkToolbar
2910 * Unsets a toolbar style set with gtk_toolbar_set_style(), so that
2911 * user preferences will be used to determine the toolbar style.
2914 gtk_toolbar_unset_style (GtkToolbar *toolbar)
2916 GtkToolbarStyle style;
2918 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2920 if (toolbar->style_set)
2922 GtkSettings *settings = toolbar_get_settings (toolbar);
2925 g_object_get (settings,
2926 "gtk-toolbar-style", &style,
2929 style = DEFAULT_TOOLBAR_STYLE;
2931 if (style != toolbar->style)
2932 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2934 toolbar->style_set = FALSE;
2939 * gtk_toolbar_set_tooltips:
2940 * @toolbar: a #GtkToolbar.
2941 * @enable: set to %FALSE to disable the tooltips, or %TRUE to enable them.
2943 * Sets if the tooltips of a toolbar should be active or not.
2945 * Deprecated: 2.14: The toolkit-wide #GtkSettings:gtk-enable-tooltips property
2946 * is now used instead.
2949 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
2952 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2955 gtk_tooltips_enable (toolbar->tooltips);
2957 gtk_tooltips_disable (toolbar->tooltips);
2959 g_object_notify (G_OBJECT (toolbar), "tooltips");
2963 * gtk_toolbar_get_tooltips:
2964 * @toolbar: a #GtkToolbar
2966 * Retrieves whether tooltips are enabled. See
2967 * gtk_toolbar_set_tooltips().
2969 * Return value: %TRUE if tooltips are enabled
2971 * Deprecated: 2.14: The toolkit-wide #GtkSettings:gtk-enable-tooltips property
2972 * is now used instead.
2975 gtk_toolbar_get_tooltips (GtkToolbar *toolbar)
2977 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2983 * gtk_toolbar_get_n_items:
2984 * @toolbar: a #GtkToolbar
2986 * Returns the number of items on the toolbar.
2988 * Return value: the number of items on the toolbar
2993 gtk_toolbar_get_n_items (GtkToolbar *toolbar)
2995 GtkToolbarPrivate *priv;
2997 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2999 if (!gtk_toolbar_check_new_api (toolbar))
3002 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3004 return physical_to_logical (toolbar, g_list_length (priv->content));
3008 * gtk_toolbar_get_nth_item:
3009 * @toolbar: a #GtkToolbar
3010 * @n: A position on the toolbar
3012 * Returns the @n<!-- -->'th item on @toolbar, or %NULL if the
3013 * toolbar does not contain an @n<!-- -->'th item.
3015 * Return value: The @n<!-- -->'th #GtkToolItem on @toolbar, or %NULL if there
3016 * isn't an @n<!-- -->'th item.
3021 gtk_toolbar_get_nth_item (GtkToolbar *toolbar,
3024 GtkToolbarPrivate *priv;
3025 ToolbarContent *content;
3028 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
3030 if (!gtk_toolbar_check_new_api (toolbar))
3033 n_items = gtk_toolbar_get_n_items (toolbar);
3035 if (n < 0 || n >= n_items)
3038 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3040 content = g_list_nth_data (priv->content, logical_to_physical (toolbar, n));
3043 g_assert (!toolbar_content_is_placeholder (content));
3045 return GTK_TOOL_ITEM (toolbar_content_get_widget (content));
3049 * gtk_toolbar_get_icon_size:
3050 * @toolbar: a #GtkToolbar
3052 * Retrieves the icon size for the toolbar. See gtk_toolbar_set_icon_size().
3054 * Return value: the current icon size for the icons on the toolbar.
3057 gtk_toolbar_get_icon_size (GtkToolbar *toolbar)
3059 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_ICON_SIZE);
3061 return toolbar->icon_size;
3065 * gtk_toolbar_get_relief_style:
3066 * @toolbar: a #GtkToolbar
3068 * Returns the relief style of buttons on @toolbar. See
3069 * gtk_button_set_relief().
3071 * Return value: The relief style of buttons on @toolbar.
3076 gtk_toolbar_get_relief_style (GtkToolbar *toolbar)
3078 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_RELIEF_NONE);
3080 return get_button_relief (toolbar);
3084 * gtk_toolbar_set_show_arrow:
3085 * @toolbar: a #GtkToolbar
3086 * @show_arrow: Whether to show an overflow menu
3088 * Sets whether to show an overflow menu when
3089 * @toolbar doesn't have room for all items on it. If %TRUE,
3090 * items that there are not room are available through an
3096 gtk_toolbar_set_show_arrow (GtkToolbar *toolbar,
3097 gboolean show_arrow)
3099 GtkToolbarPrivate *priv;
3101 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3103 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3104 show_arrow = show_arrow != FALSE;
3106 if (priv->show_arrow != show_arrow)
3108 priv->show_arrow = show_arrow;
3110 if (!priv->show_arrow)
3111 gtk_widget_hide (priv->arrow_button);
3113 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3114 g_object_notify (G_OBJECT (toolbar), "show-arrow");
3119 * gtk_toolbar_get_show_arrow:
3120 * @toolbar: a #GtkToolbar
3122 * Returns whether the toolbar has an overflow menu.
3123 * See gtk_toolbar_set_show_arrow().
3125 * Return value: %TRUE if the toolbar has an overflow menu.
3130 gtk_toolbar_get_show_arrow (GtkToolbar *toolbar)
3132 GtkToolbarPrivate *priv;
3134 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
3136 if (!gtk_toolbar_check_new_api (toolbar))
3139 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3141 return priv->show_arrow;
3145 * gtk_toolbar_get_drop_index:
3146 * @toolbar: a #GtkToolbar
3147 * @x: x coordinate of a point on the toolbar
3148 * @y: y coordinate of a point on the toolbar
3150 * Returns the position corresponding to the indicated point on
3151 * @toolbar. This is useful when dragging items to the toolbar:
3152 * this function returns the position a new item should be
3155 * @x and @y are in @toolbar coordinates.
3157 * Return value: The position corresponding to the point (@x, @y) on the toolbar.
3162 gtk_toolbar_get_drop_index (GtkToolbar *toolbar,
3166 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
3168 if (!gtk_toolbar_check_new_api (toolbar))
3171 return physical_to_logical (toolbar, find_drop_index (toolbar, x, y));
3175 gtk_toolbar_finalize (GObject *object)
3178 GtkToolbar *toolbar = GTK_TOOLBAR (object);
3179 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3181 if (toolbar->tooltips)
3182 g_object_unref (toolbar->tooltips);
3184 if (priv->arrow_button)
3185 gtk_widget_unparent (priv->arrow_button);
3187 for (list = priv->content; list != NULL; list = list->next)
3189 ToolbarContent *content = list->data;
3191 toolbar_content_free (content);
3194 g_list_free (priv->content);
3195 g_list_free (toolbar->children);
3197 g_timer_destroy (priv->timer);
3200 gtk_widget_destroy (GTK_WIDGET (priv->menu));
3203 g_source_remove (priv->idle_id);
3205 G_OBJECT_CLASS (gtk_toolbar_parent_class)->finalize (object);
3209 * gtk_toolbar_set_icon_size:
3210 * @toolbar: A #GtkToolbar
3211 * @icon_size: The #GtkIconSize that stock icons in the toolbar shall have.
3213 * This function sets the size of stock icons in the toolbar. You
3214 * can call it both before you add the icons and after they've been
3215 * added. The size you set will override user preferences for the default
3218 * This should only be used for special-purpose toolbars, normal
3219 * application toolbars should respect the user preferences for the
3223 gtk_toolbar_set_icon_size (GtkToolbar *toolbar,
3224 GtkIconSize icon_size)
3226 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3227 g_return_if_fail (icon_size != GTK_ICON_SIZE_INVALID);
3229 if (!toolbar->icon_size_set)
3231 toolbar->icon_size_set = TRUE;
3232 g_object_notify (G_OBJECT (toolbar), "icon-size-set");
3235 if (toolbar->icon_size == icon_size)
3238 toolbar->icon_size = icon_size;
3239 g_object_notify (G_OBJECT (toolbar), "icon-size");
3241 gtk_toolbar_reconfigured (toolbar);
3243 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3247 * gtk_toolbar_unset_icon_size:
3248 * @toolbar: a #GtkToolbar
3250 * Unsets toolbar icon size set with gtk_toolbar_set_icon_size(), so that
3251 * user preferences will be used to determine the icon size.
3254 gtk_toolbar_unset_icon_size (GtkToolbar *toolbar)
3258 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3260 if (toolbar->icon_size_set)
3262 GtkSettings *settings = toolbar_get_settings (toolbar);
3266 g_object_get (settings,
3267 "gtk-toolbar-icon-size", &size,
3271 size = DEFAULT_ICON_SIZE;
3273 if (size != toolbar->icon_size)
3275 gtk_toolbar_set_icon_size (toolbar, size);
3276 g_object_notify (G_OBJECT (toolbar), "icon-size");
3279 toolbar->icon_size_set = FALSE;
3280 g_object_notify (G_OBJECT (toolbar), "icon-size-set");
3289 * gtk_toolbar_append_item:
3290 * @toolbar: a #GtkToolbar.
3291 * @text: give your toolbar button a label.
3292 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3293 * @tooltip_private_text: use with #GtkTipsQuery.
3294 * @icon: a #GtkWidget that should be used as the button's icon.
3295 * @callback: the function to be executed when the button is pressed.
3296 * @user_data: a pointer to any data you wish to be passed to the callback.
3298 * Inserts a new item into the toolbar. You must specify the position
3299 * in the toolbar where it will be inserted.
3301 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3302 * arguments. Use G_CALLBACK() to cast the function to #GCallback.
3304 * Return value: the new toolbar item as a #GtkWidget.
3306 * Deprecated: 2.4: Use gtk_toolbar_insert() instead.
3309 gtk_toolbar_append_item (GtkToolbar *toolbar,
3311 const char *tooltip_text,
3312 const char *tooltip_private_text,
3317 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3319 tooltip_text, tooltip_private_text,
3320 icon, callback, user_data,
3321 toolbar->num_children);
3325 * gtk_toolbar_prepend_item:
3326 * @toolbar: a #GtkToolbar.
3327 * @text: give your toolbar button a label.
3328 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3329 * @tooltip_private_text: use with #GtkTipsQuery.
3330 * @icon: a #GtkWidget that should be used as the button's icon.
3331 * @callback: the function to be executed when the button is pressed.
3332 * @user_data: a pointer to any data you wish to be passed to the callback.
3334 * Adds a new button to the beginning (top or left edges) of the given toolbar.
3336 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3337 * arguments. Use G_CALLBACK() to cast the function to #GCallback.
3339 * Return value: the new toolbar item as a #GtkWidget.
3341 * Deprecated: 2.4: Use gtk_toolbar_insert() instead.
3344 gtk_toolbar_prepend_item (GtkToolbar *toolbar,
3346 const char *tooltip_text,
3347 const char *tooltip_private_text,
3352 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3354 tooltip_text, tooltip_private_text,
3355 icon, callback, user_data,
3360 * gtk_toolbar_insert_item:
3361 * @toolbar: a #GtkToolbar.
3362 * @text: give your toolbar button a label.
3363 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3364 * @tooltip_private_text: use with #GtkTipsQuery.
3365 * @icon: a #GtkWidget that should be used as the button's icon.
3366 * @callback: the function to be executed when the button is pressed.
3367 * @user_data: a pointer to any data you wish to be passed to the callback.
3368 * @position: the number of widgets to insert this item after.
3370 * Inserts a new item into the toolbar. You must specify the position in the
3371 * toolbar where it will be inserted.
3373 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3374 * arguments. Use G_CALLBACK() to cast the function to #GCallback.
3376 * Return value: the new toolbar item as a #GtkWidget.
3378 * Deprecated: 2.4: Use gtk_toolbar_insert() instead.
3381 gtk_toolbar_insert_item (GtkToolbar *toolbar,
3383 const char *tooltip_text,
3384 const char *tooltip_private_text,
3390 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3392 tooltip_text, tooltip_private_text,
3393 icon, callback, user_data,
3398 * gtk_toolbar_insert_stock:
3399 * @toolbar: A #GtkToolbar
3400 * @stock_id: The id of the stock item you want to insert
3401 * @tooltip_text: The text in the tooltip of the toolbar button
3402 * @tooltip_private_text: The private text of the tooltip
3403 * @callback: The callback called when the toolbar button is clicked.
3404 * @user_data: user data passed to callback
3405 * @position: The position the button shall be inserted at.
3406 * -1 means at the end.
3408 * Inserts a stock item at the specified position of the toolbar. If
3409 * @stock_id is not a known stock item ID, it's inserted verbatim,
3410 * except that underscores used to mark mnemonics are removed.
3412 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3413 * arguments. Use G_CALLBACK() to cast the function to #GCallback.
3415 * Returns: the inserted widget
3417 * Deprecated: 2.4: Use gtk_toolbar_insert() instead.
3420 gtk_toolbar_insert_stock (GtkToolbar *toolbar,
3421 const gchar *stock_id,
3422 const char *tooltip_text,
3423 const char *tooltip_private_text,
3428 return internal_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3430 tooltip_text, tooltip_private_text,
3431 NULL, callback, user_data,
3436 * gtk_toolbar_append_space:
3437 * @toolbar: a #GtkToolbar.
3439 * Adds a new space to the end of the toolbar.
3441 * Deprecated: 2.4: Use gtk_toolbar_insert() instead.
3444 gtk_toolbar_append_space (GtkToolbar *toolbar)
3446 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3450 toolbar->num_children);
3454 * gtk_toolbar_prepend_space:
3455 * @toolbar: a #GtkToolbar.
3457 * Adds a new space to the beginning of the toolbar.
3459 * Deprecated: 2.4: Use gtk_toolbar_insert() instead.
3462 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
3464 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3472 * gtk_toolbar_insert_space:
3473 * @toolbar: a #GtkToolbar
3474 * @position: the number of widgets after which a space should be inserted.
3476 * Inserts a new space in the toolbar at the specified position.
3478 * Deprecated: 2.4: Use gtk_toolbar_insert() instead.
3481 gtk_toolbar_insert_space (GtkToolbar *toolbar,
3484 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3492 * gtk_toolbar_remove_space:
3493 * @toolbar: a #GtkToolbar.
3494 * @position: the index of the space to remove.
3496 * Removes a space from the specified position.
3498 * Deprecated: 2.4: Use gtk_toolbar_insert() instead.
3501 gtk_toolbar_remove_space (GtkToolbar *toolbar,
3504 GtkToolbarPrivate *priv;
3505 ToolbarContent *content;
3507 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3509 if (!gtk_toolbar_check_old_api (toolbar))
3512 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3514 content = g_list_nth_data (priv->content, position);
3518 g_warning ("Toolbar position %d doesn't exist", position);
3522 if (!toolbar_content_is_separator (content))
3524 g_warning ("Toolbar position %d is not a space", position);
3528 toolbar_content_remove (content, toolbar);
3529 toolbar_content_free (content);
3533 * gtk_toolbar_append_widget:
3534 * @toolbar: a #GtkToolbar.
3535 * @widget: a #GtkWidget to add to the toolbar.
3536 * @tooltip_text: the element's tooltip.
3537 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3539 * Adds a widget to the end of the given toolbar.
3541 * Deprecated: 2.4: Use gtk_toolbar_insert() instead.
3544 gtk_toolbar_append_widget (GtkToolbar *toolbar,
3546 const gchar *tooltip_text,
3547 const gchar *tooltip_private_text)
3549 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3551 tooltip_text, tooltip_private_text,
3553 toolbar->num_children);
3557 * gtk_toolbar_prepend_widget:
3558 * @toolbar: a #GtkToolbar.
3559 * @widget: a #GtkWidget to add to the toolbar.
3560 * @tooltip_text: the element's tooltip.
3561 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3563 * Adds a widget to the beginning of the given toolbar.
3565 * Deprecated: 2.4: Use gtk_toolbar_insert() instead.
3568 gtk_toolbar_prepend_widget (GtkToolbar *toolbar,
3570 const gchar *tooltip_text,
3571 const gchar *tooltip_private_text)
3573 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3575 tooltip_text, tooltip_private_text,
3581 * gtk_toolbar_insert_widget:
3582 * @toolbar: a #GtkToolbar.
3583 * @widget: a #GtkWidget to add to the toolbar.
3584 * @tooltip_text: the element's tooltip.
3585 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3586 * @position: the number of widgets to insert this widget after.
3588 * Inserts a widget in the toolbar at the given position.
3590 * Deprecated: 2.4: Use gtk_toolbar_insert() instead.
3593 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
3595 const char *tooltip_text,
3596 const char *tooltip_private_text,
3599 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3601 tooltip_text, tooltip_private_text,
3607 * gtk_toolbar_append_element:
3608 * @toolbar: a #GtkToolbar.
3609 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
3610 * @widget: a #GtkWidget, or %NULL.
3611 * @text: the element's label.
3612 * @tooltip_text: the element's tooltip.
3613 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3614 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3615 * @callback: the function to be executed when the button is pressed.
3616 * @user_data: any data you wish to pass to the callback.
3618 * Adds a new element to the end of a toolbar.
3620 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3621 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3622 * the radio group for the new element. In all other cases, @widget must
3625 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3626 * arguments. Use G_CALLBACK() to cast the function to #GCallback.
3628 * Return value: the new toolbar element as a #GtkWidget.
3630 * Deprecated: 2.4: Use gtk_toolbar_insert() instead.
3633 gtk_toolbar_append_element (GtkToolbar *toolbar,
3634 GtkToolbarChildType type,
3637 const char *tooltip_text,
3638 const char *tooltip_private_text,
3643 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3644 tooltip_text, tooltip_private_text,
3645 icon, callback, user_data,
3646 toolbar->num_children);
3650 * gtk_toolbar_prepend_element:
3651 * @toolbar: a #GtkToolbar.
3652 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
3653 * @widget: a #GtkWidget, or %NULL
3654 * @text: the element's label.
3655 * @tooltip_text: the element's tooltip.
3656 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3657 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3658 * @callback: the function to be executed when the button is pressed.
3659 * @user_data: any data you wish to pass to the callback.
3661 * Adds a new element to the beginning of a toolbar.
3663 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3664 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3665 * the radio group for the new element. In all other cases, @widget must
3668 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3669 * arguments. Use G_CALLBACK() to cast the function to #GCallback.
3671 * Return value: the new toolbar element as a #GtkWidget.
3673 * Deprecated: 2.4: Use gtk_toolbar_insert() instead.
3676 gtk_toolbar_prepend_element (GtkToolbar *toolbar,
3677 GtkToolbarChildType type,
3680 const char *tooltip_text,
3681 const char *tooltip_private_text,
3686 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3687 tooltip_text, tooltip_private_text,
3688 icon, callback, user_data, 0);
3692 * gtk_toolbar_insert_element:
3693 * @toolbar: a #GtkToolbar.
3694 * @type: a value of type #GtkToolbarChildType that determines what @widget
3696 * @widget: a #GtkWidget, or %NULL.
3697 * @text: the element's label.
3698 * @tooltip_text: the element's tooltip.
3699 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3700 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3701 * @callback: the function to be executed when the button is pressed.
3702 * @user_data: any data you wish to pass to the callback.
3703 * @position: the number of widgets to insert this element after.
3705 * Inserts a new element in the toolbar at the given position.
3707 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3708 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3709 * the radio group for the new element. In all other cases, @widget must
3712 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3713 * arguments. Use G_CALLBACK() to cast the function to #GCallback.
3715 * Return value: the new toolbar element as a #GtkWidget.
3717 * Deprecated: 2.4: Use gtk_toolbar_insert() instead.
3720 gtk_toolbar_insert_element (GtkToolbar *toolbar,
3721 GtkToolbarChildType type,
3724 const char *tooltip_text,
3725 const char *tooltip_private_text,
3731 return internal_insert_element (toolbar, type, widget, text,
3732 tooltip_text, tooltip_private_text,
3733 icon, callback, user_data, position, FALSE);
3737 set_child_packing_and_visibility(GtkToolbar *toolbar,
3738 GtkToolbarChild *child)
3743 box = gtk_bin_get_child (GTK_BIN (child->widget));
3745 g_return_if_fail (GTK_IS_BOX (box));
3749 expand = (toolbar->style != GTK_TOOLBAR_BOTH);
3751 gtk_box_set_child_packing (GTK_BOX (box), child->label,
3752 expand, expand, 0, GTK_PACK_END);
3754 if (toolbar->style != GTK_TOOLBAR_ICONS)
3755 gtk_widget_show (child->label);
3757 gtk_widget_hide (child->label);
3762 expand = (toolbar->style != GTK_TOOLBAR_BOTH_HORIZ);
3764 gtk_box_set_child_packing (GTK_BOX (box), child->icon,
3765 expand, expand, 0, GTK_PACK_END);
3767 if (toolbar->style != GTK_TOOLBAR_TEXT)
3768 gtk_widget_show (child->icon);
3770 gtk_widget_hide (child->icon);
3775 internal_insert_element (GtkToolbar *toolbar,
3776 GtkToolbarChildType type,
3779 const char *tooltip_text,
3780 const char *tooltip_private_text,
3788 ToolbarContent *content;
3789 char *free_me = NULL;
3791 GtkWidget *child_widget;
3792 GtkWidget *child_label;
3793 GtkWidget *child_icon;
3795 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
3796 if (type == GTK_TOOLBAR_CHILD_WIDGET)
3797 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3798 else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON)
3799 g_return_val_if_fail (widget == NULL, NULL);
3800 if (GTK_IS_TOOL_ITEM (widget))
3801 g_warning (MIXED_API_WARNING);
3803 if (!gtk_toolbar_check_old_api (toolbar))
3806 child_widget = NULL;
3812 case GTK_TOOLBAR_CHILD_SPACE:
3815 case GTK_TOOLBAR_CHILD_WIDGET:
3816 child_widget = widget;
3819 case GTK_TOOLBAR_CHILD_BUTTON:
3820 case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
3821 case GTK_TOOLBAR_CHILD_RADIOBUTTON:
3822 if (type == GTK_TOOLBAR_CHILD_BUTTON)
3824 child_widget = gtk_button_new ();
3826 else if (type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
3828 child_widget = gtk_toggle_button_new ();
3829 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child_widget), FALSE);
3831 else /* type == GTK_TOOLBAR_CHILD_RADIOBUTTON */
3833 GSList *group = NULL;
3836 group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
3838 child_widget = gtk_radio_button_new (group);
3839 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child_widget), FALSE);
3842 gtk_button_set_relief (GTK_BUTTON (child_widget), get_button_relief (toolbar));
3843 gtk_button_set_focus_on_click (GTK_BUTTON (child_widget), FALSE);
3847 g_signal_connect (child_widget, "clicked",
3848 callback, user_data);
3851 if (toolbar->style == GTK_TOOLBAR_BOTH_HORIZ)
3852 box = gtk_hbox_new (FALSE, 0);
3854 box = gtk_vbox_new (FALSE, 0);
3856 gtk_container_add (GTK_CONTAINER (child_widget), box);
3857 gtk_widget_show (box);
3859 if (text && use_stock)
3861 GtkStockItem stock_item;
3862 if (gtk_stock_lookup (text, &stock_item))
3865 icon = gtk_image_new_from_stock (text, toolbar->icon_size);
3867 text = free_me = _gtk_toolbar_elide_underscores (stock_item.label);
3873 child_label = gtk_label_new (text);
3875 gtk_container_add (GTK_CONTAINER (box), child_label);
3880 child_icon = GTK_WIDGET (icon);
3881 gtk_container_add (GTK_CONTAINER (box), child_icon);
3884 gtk_widget_show (child_widget);
3888 g_assert_not_reached ();
3892 if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text)
3894 gtk_tooltips_set_tip (toolbar->tooltips, child_widget,
3895 tooltip_text, tooltip_private_text);
3898 content = toolbar_content_new_compatibility (toolbar, type, child_widget,
3899 child_icon, child_label, position);
3903 return child_widget;
3907 * ToolbarContent methods
3915 struct _ToolbarContent
3925 GtkAllocation start_allocation;
3926 GtkAllocation goal_allocation;
3927 guint is_placeholder : 1;
3928 guint disappearing : 1;
3934 GtkToolbarChild child;
3935 GtkAllocation space_allocation;
3936 guint space_visible : 1;
3941 static ToolbarContent *
3942 toolbar_content_new_tool_item (GtkToolbar *toolbar,
3944 gboolean is_placeholder,
3947 ToolbarContent *content;
3948 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3950 content = g_slice_new0 (ToolbarContent);
3952 content->type = TOOL_ITEM;
3953 content->state = NOT_ALLOCATED;
3954 content->u.tool_item.item = item;
3955 content->u.tool_item.is_placeholder = is_placeholder;
3957 gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar));
3959 priv->content = g_list_insert (priv->content, content, pos);
3961 if (!is_placeholder)
3963 toolbar->num_children++;
3965 gtk_toolbar_stop_sliding (toolbar);
3968 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3969 priv->need_rebuild = TRUE;
3974 static ToolbarContent *
3975 toolbar_content_new_compatibility (GtkToolbar *toolbar,
3976 GtkToolbarChildType type,
3982 ToolbarContent *content;
3983 GtkToolbarChild *child;
3984 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3986 content = g_slice_new0 (ToolbarContent);
3988 child = &(content->u.compatibility.child);
3990 content->type = COMPATIBILITY;
3992 child->widget = widget;
3994 child->label = label;
3996 if (type != GTK_TOOLBAR_CHILD_SPACE)
3998 gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
4002 content->u.compatibility.space_visible = TRUE;
4003 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
4006 if (type == GTK_TOOLBAR_CHILD_BUTTON ||
4007 type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
4008 type == GTK_TOOLBAR_CHILD_RADIOBUTTON)
4010 set_child_packing_and_visibility (toolbar, child);
4013 priv->content = g_list_insert (priv->content, content, pos);
4014 toolbar->children = g_list_insert (toolbar->children, child, pos);
4015 priv->need_rebuild = TRUE;
4017 toolbar->num_children++;
4023 toolbar_content_remove (ToolbarContent *content,
4024 GtkToolbar *toolbar)
4026 GtkToolbarChild *child;
4027 GtkToolbarPrivate *priv;
4029 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4031 switch (content->type)
4034 gtk_widget_unparent (GTK_WIDGET (content->u.tool_item.item));
4038 child = &(content->u.compatibility.child);
4040 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
4042 g_object_ref (child->widget);
4043 gtk_widget_unparent (child->widget);
4044 gtk_widget_destroy (child->widget);
4045 g_object_unref (child->widget);
4048 toolbar->children = g_list_remove (toolbar->children, child);
4052 priv->content = g_list_remove (priv->content, content);
4054 if (!toolbar_content_is_placeholder (content))
4055 toolbar->num_children--;
4057 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
4058 priv->need_rebuild = TRUE;
4062 toolbar_content_free (ToolbarContent *content)
4064 g_slice_free (ToolbarContent, content);
4068 calculate_max_homogeneous_pixels (GtkWidget *widget)
4070 PangoContext *context;
4071 PangoFontMetrics *metrics;
4074 context = gtk_widget_get_pango_context (widget);
4075 metrics = pango_context_get_metrics (context,
4076 widget->style->font_desc,
4077 pango_context_get_language (context));
4078 char_width = pango_font_metrics_get_approximate_char_width (metrics);
4079 pango_font_metrics_unref (metrics);
4081 return PANGO_PIXELS (MAX_HOMOGENEOUS_N_CHARS * char_width);
4085 toolbar_content_expose (ToolbarContent *content,
4086 GtkContainer *container,
4087 GdkEventExpose *expose)
4089 GtkToolbar *toolbar = GTK_TOOLBAR (container);
4090 GtkToolbarChild *child;
4091 GtkWidget *widget = NULL; /* quiet gcc */
4093 switch (content->type)
4096 if (!content->u.tool_item.is_placeholder)
4097 widget = GTK_WIDGET (content->u.tool_item.item);
4101 child = &(content->u.compatibility.child);
4103 if (child->type == GTK_TOOLBAR_CHILD_SPACE)
4105 if (content->u.compatibility.space_visible &&
4106 get_space_style (toolbar) == GTK_TOOLBAR_SPACE_LINE)
4107 _gtk_toolbar_paint_space_line (GTK_WIDGET (toolbar), toolbar,
4109 &content->u.compatibility.space_allocation);
4113 widget = child->widget;
4118 gtk_container_propagate_expose (container, widget, expose);
4122 toolbar_content_visible (ToolbarContent *content,
4123 GtkToolbar *toolbar)
4127 switch (content->type)
4130 item = content->u.tool_item.item;
4132 if (!GTK_WIDGET_VISIBLE (item))
4135 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL &&
4136 gtk_tool_item_get_visible_horizontal (item))
4139 if ((toolbar->orientation == GTK_ORIENTATION_VERTICAL &&
4140 gtk_tool_item_get_visible_vertical (item)))
4147 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4148 return GTK_WIDGET_VISIBLE (content->u.compatibility.child.widget);
4154 g_assert_not_reached ();
4159 toolbar_content_size_request (ToolbarContent *content,
4160 GtkToolbar *toolbar,
4161 GtkRequisition *requisition)
4165 switch (content->type)
4168 gtk_widget_size_request (GTK_WIDGET (content->u.tool_item.item),
4170 if (content->u.tool_item.is_placeholder &&
4171 content->u.tool_item.disappearing)
4173 requisition->width = 0;
4174 requisition->height = 0;
4179 space_size = get_space_size (toolbar);
4181 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4183 gtk_widget_size_request (content->u.compatibility.child.widget,
4188 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
4190 requisition->width = space_size;
4191 requisition->height = 0;
4195 requisition->height = space_size;
4196 requisition->width = 0;
4205 toolbar_content_is_homogeneous (ToolbarContent *content,
4206 GtkToolbar *toolbar)
4208 gboolean result = FALSE; /* quiet gcc */
4209 GtkRequisition requisition;
4210 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4212 if (priv->max_homogeneous_pixels < 0)
4214 priv->max_homogeneous_pixels =
4215 calculate_max_homogeneous_pixels (GTK_WIDGET (toolbar));
4218 toolbar_content_size_request (content, toolbar, &requisition);
4220 if (requisition.width > priv->max_homogeneous_pixels)
4223 switch (content->type)
4226 result = gtk_tool_item_get_homogeneous (content->u.tool_item.item) &&
4227 !GTK_IS_SEPARATOR_TOOL_ITEM (content->u.tool_item.item);
4229 if (gtk_tool_item_get_is_important (content->u.tool_item.item) &&
4230 toolbar->style == GTK_TOOLBAR_BOTH_HORIZ &&
4231 toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
4238 if (content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_BUTTON ||
4239 content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4240 content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4255 toolbar_content_is_placeholder (ToolbarContent *content)
4257 if (content->type == TOOL_ITEM && content->u.tool_item.is_placeholder)
4264 toolbar_content_disappearing (ToolbarContent *content)
4266 if (content->type == TOOL_ITEM && content->u.tool_item.disappearing)
4273 toolbar_content_get_state (ToolbarContent *content)
4275 return content->state;
4279 toolbar_content_child_visible (ToolbarContent *content)
4281 switch (content->type)
4284 return GTK_WIDGET_CHILD_VISIBLE (content->u.tool_item.item);
4288 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4290 return GTK_WIDGET_CHILD_VISIBLE (content->u.compatibility.child.widget);
4294 return content->u.compatibility.space_visible;
4299 return FALSE; /* quiet gcc */
4303 toolbar_content_get_goal_allocation (ToolbarContent *content,
4304 GtkAllocation *allocation)
4306 switch (content->type)
4309 *allocation = content->u.tool_item.goal_allocation;
4313 /* Goal allocations are only relevant when we are
4314 * using the new API, so we should never get here
4316 g_assert_not_reached ();
4322 toolbar_content_get_allocation (ToolbarContent *content,
4323 GtkAllocation *allocation)
4325 GtkToolbarChild *child;
4327 switch (content->type)
4330 *allocation = GTK_WIDGET (content->u.tool_item.item)->allocation;
4334 child = &(content->u.compatibility.child);
4336 if (child->type == GTK_TOOLBAR_CHILD_SPACE)
4337 *allocation = content->u.compatibility.space_allocation;
4339 *allocation = child->widget->allocation;
4345 toolbar_content_set_start_allocation (ToolbarContent *content,
4346 GtkAllocation *allocation)
4348 switch (content->type)
4351 content->u.tool_item.start_allocation = *allocation;
4355 /* start_allocation is only relevant when using the new API */
4356 g_assert_not_reached ();
4362 toolbar_content_get_expand (ToolbarContent *content)
4364 if (content->type == TOOL_ITEM &&
4365 gtk_tool_item_get_expand (content->u.tool_item.item) &&
4366 !content->u.tool_item.disappearing)
4375 toolbar_content_set_goal_allocation (ToolbarContent *content,
4376 GtkAllocation *allocation)
4378 switch (content->type)
4381 content->u.tool_item.goal_allocation = *allocation;
4385 /* Only relevant when using new API */
4386 g_assert_not_reached ();
4392 toolbar_content_set_child_visible (ToolbarContent *content,
4393 GtkToolbar *toolbar,
4396 GtkToolbarChild *child;
4398 switch (content->type)
4401 gtk_widget_set_child_visible (GTK_WIDGET (content->u.tool_item.item),
4406 child = &(content->u.compatibility.child);
4408 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
4410 gtk_widget_set_child_visible (child->widget, visible);
4414 if (content->u.compatibility.space_visible != visible)
4416 content->u.compatibility.space_visible = visible;
4417 gtk_widget_queue_draw (GTK_WIDGET (toolbar));
4425 toolbar_content_get_start_allocation (ToolbarContent *content,
4426 GtkAllocation *start_allocation)
4428 switch (content->type)
4431 *start_allocation = content->u.tool_item.start_allocation;
4435 /* Only relevant for new API */
4436 g_assert_not_reached ();
4442 toolbar_content_size_allocate (ToolbarContent *content,
4443 GtkAllocation *allocation)
4445 switch (content->type)
4448 gtk_widget_size_allocate (GTK_WIDGET (content->u.tool_item.item),
4453 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4455 gtk_widget_size_allocate (content->u.compatibility.child.widget,
4460 content->u.compatibility.space_allocation = *allocation;
4467 toolbar_content_set_state (ToolbarContent *content,
4470 content->state = state;
4474 toolbar_content_get_widget (ToolbarContent *content)
4476 GtkToolbarChild *child;
4478 switch (content->type)
4481 return GTK_WIDGET (content->u.tool_item.item);
4485 child = &(content->u.compatibility.child);
4486 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
4487 return child->widget;
4497 toolbar_content_set_disappearing (ToolbarContent *content,
4498 gboolean disappearing)
4500 switch (content->type)
4503 content->u.tool_item.disappearing = disappearing;
4507 /* Only relevant for new API */
4508 g_assert_not_reached ();
4514 toolbar_content_set_size_request (ToolbarContent *content,
4518 switch (content->type)
4521 gtk_widget_set_size_request (GTK_WIDGET (content->u.tool_item.item),
4526 /* Setting size requests only happens with sliding,
4527 * so not relevant here
4529 g_assert_not_reached ();
4535 toolbar_child_reconfigure (GtkToolbar *toolbar,
4536 GtkToolbarChild *child)
4540 GtkToolbarStyle style;
4541 GtkIconSize icon_size;
4542 GtkReliefStyle relief;
4545 style = gtk_toolbar_get_style (toolbar);
4546 icon_size = gtk_toolbar_get_icon_size (toolbar);
4547 relief = gtk_toolbar_get_relief_style (toolbar);
4550 if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4551 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4552 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4554 box = gtk_bin_get_child (GTK_BIN (child->widget));
4556 if (style == GTK_TOOLBAR_BOTH && GTK_IS_HBOX (box))
4560 vbox = gtk_vbox_new (FALSE, 0);
4563 gtk_widget_reparent (child->label, vbox);
4565 gtk_widget_reparent (child->icon, vbox);
4567 gtk_widget_destroy (box);
4568 gtk_container_add (GTK_CONTAINER (child->widget), vbox);
4570 gtk_widget_show (vbox);
4572 else if (style == GTK_TOOLBAR_BOTH_HORIZ && GTK_IS_VBOX (box))
4576 hbox = gtk_hbox_new (FALSE, 0);
4579 gtk_widget_reparent (child->label, hbox);
4581 gtk_widget_reparent (child->icon, hbox);
4583 gtk_widget_destroy (box);
4584 gtk_container_add (GTK_CONTAINER (child->widget), hbox);
4586 gtk_widget_show (hbox);
4589 set_child_packing_and_visibility (toolbar, child);
4594 if ((child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4595 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
4596 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON) &&
4597 GTK_IS_IMAGE (child->icon))
4599 image = GTK_IMAGE (child->icon);
4600 if (gtk_image_get_storage_type (image) == GTK_IMAGE_STOCK)
4602 gtk_image_get_stock (image, &stock_id, NULL);
4603 stock_id = g_strdup (stock_id);
4604 gtk_image_set_from_stock (image,
4612 if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4613 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4614 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4616 gtk_button_set_relief (GTK_BUTTON (child->widget), relief);
4621 toolbar_content_toolbar_reconfigured (ToolbarContent *content,
4622 GtkToolbar *toolbar)
4624 switch (content->type)
4627 gtk_tool_item_toolbar_reconfigured (content->u.tool_item.item);
4631 toolbar_child_reconfigure (toolbar, &(content->u.compatibility.child));
4637 toolbar_content_retrieve_menu_item (ToolbarContent *content)
4639 if (content->type == TOOL_ITEM)
4640 return gtk_tool_item_retrieve_proxy_menu_item (content->u.tool_item.item);
4642 /* FIXME - we might actually be able to do something meaningful here */
4647 toolbar_content_has_proxy_menu_item (ToolbarContent *content)
4649 if (content->type == TOOL_ITEM)
4651 GtkWidget *menu_item;
4653 if (content->u.tool_item.has_menu == YES)
4655 else if (content->u.tool_item.has_menu == NO)
4658 menu_item = toolbar_content_retrieve_menu_item (content);
4660 content->u.tool_item.has_menu = menu_item? YES : NO;
4662 return menu_item != NULL;
4671 toolbar_content_set_unknown_menu_status (ToolbarContent *content)
4673 if (content->type == TOOL_ITEM)
4674 content->u.tool_item.has_menu = UNKNOWN;
4678 toolbar_content_is_separator (ToolbarContent *content)
4680 GtkToolbarChild *child;
4682 switch (content->type)
4685 return GTK_IS_SEPARATOR_TOOL_ITEM (content->u.tool_item.item);
4689 child = &(content->u.compatibility.child);
4690 return (child->type == GTK_TOOLBAR_CHILD_SPACE);
4698 toolbar_content_set_expand (ToolbarContent *content,
4701 if (content->type == TOOL_ITEM)
4702 gtk_tool_item_set_expand (content->u.tool_item.item, expand);
4706 ignore_show_and_hide_all (ToolbarContent *content)
4708 if (content->type == COMPATIBILITY)
4710 GtkToolbarChildType type = content->u.compatibility.child.type;
4712 if (type == GTK_TOOLBAR_CHILD_BUTTON ||
4713 type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
4714 type == GTK_TOOLBAR_CHILD_RADIOBUTTON)
4724 toolbar_content_show_all (ToolbarContent *content)
4728 if (ignore_show_and_hide_all (content))
4731 widget = toolbar_content_get_widget (content);
4733 gtk_widget_show_all (widget);
4737 toolbar_content_hide_all (ToolbarContent *content)
4741 if (ignore_show_and_hide_all (content))
4744 widget = toolbar_content_get_widget (content);
4746 gtk_widget_hide_all (widget);
4753 get_space_size (GtkToolbar *toolbar)
4755 gint space_size = DEFAULT_SPACE_SIZE;
4759 gtk_widget_style_get (GTK_WIDGET (toolbar),
4760 "space-size", &space_size,
4767 static GtkToolbarSpaceStyle
4768 get_space_style (GtkToolbar *toolbar)
4770 GtkToolbarSpaceStyle space_style = DEFAULT_SPACE_STYLE;
4774 gtk_widget_style_get (GTK_WIDGET (toolbar),
4775 "space-style", &space_style,
4782 static GtkReliefStyle
4783 get_button_relief (GtkToolbar *toolbar)
4785 GtkReliefStyle button_relief = GTK_RELIEF_NORMAL;
4787 gtk_widget_ensure_style (GTK_WIDGET (toolbar));
4789 gtk_widget_style_get (GTK_WIDGET (toolbar),
4790 "button-relief", &button_relief,
4793 return button_relief;
4797 get_internal_padding (GtkToolbar *toolbar)
4801 gtk_widget_style_get (GTK_WIDGET (toolbar),
4802 "internal-padding", &ipadding,
4809 get_max_child_expand (GtkToolbar *toolbar)
4811 gint mexpand = G_MAXINT;
4813 gtk_widget_style_get (GTK_WIDGET (toolbar),
4814 "max-child-expand", &mexpand,
4819 static GtkShadowType
4820 get_shadow_type (GtkToolbar *toolbar)
4822 GtkShadowType shadow_type;
4824 gtk_widget_style_get (GTK_WIDGET (toolbar),
4825 "shadow-type", &shadow_type,
4835 gtk_toolbar_check_old_api (GtkToolbar *toolbar)
4837 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4839 if (priv->api_mode == NEW_API)
4841 g_warning (MIXED_API_WARNING);
4845 priv->api_mode = OLD_API;
4850 gtk_toolbar_check_new_api (GtkToolbar *toolbar)
4852 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4854 if (priv->api_mode == OLD_API)
4856 g_warning (MIXED_API_WARNING);
4860 priv->api_mode = NEW_API;
4864 /* GTK+ internal methods */
4867 _gtk_toolbar_get_default_space_size (void)
4869 return DEFAULT_SPACE_SIZE;
4873 _gtk_toolbar_paint_space_line (GtkWidget *widget,
4874 GtkToolbar *toolbar,
4875 const GdkRectangle *area,
4876 const GtkAllocation *allocation)
4878 const double start_fraction = (SPACE_LINE_START / SPACE_LINE_DIVISION);
4879 const double end_fraction = (SPACE_LINE_END / SPACE_LINE_DIVISION);
4881 GtkOrientation orientation;
4883 g_return_if_fail (GTK_IS_WIDGET (widget));
4885 orientation = toolbar? toolbar->orientation : GTK_ORIENTATION_HORIZONTAL;
4887 if (orientation == GTK_ORIENTATION_HORIZONTAL)
4889 gboolean wide_separators;
4890 gint separator_width;
4892 gtk_widget_style_get (widget,
4893 "wide-separators", &wide_separators,
4894 "separator-width", &separator_width,
4897 if (wide_separators)
4898 gtk_paint_box (widget->style, widget->window,
4899 GTK_WIDGET_STATE (widget), GTK_SHADOW_ETCHED_OUT,
4900 area, widget, "vseparator",
4901 allocation->x + (allocation->width - separator_width) / 2,
4902 allocation->y + allocation->height * start_fraction,
4904 allocation->height * (end_fraction - start_fraction));
4906 gtk_paint_vline (widget->style, widget->window,
4907 GTK_WIDGET_STATE (widget), area, widget,
4909 allocation->y + allocation->height * start_fraction,
4910 allocation->y + allocation->height * end_fraction,
4911 allocation->x + (allocation->width - widget->style->xthickness) / 2);
4915 gboolean wide_separators;
4916 gint separator_height;
4918 gtk_widget_style_get (widget,
4919 "wide-separators", &wide_separators,
4920 "separator-height", &separator_height,
4923 if (wide_separators)
4924 gtk_paint_box (widget->style, widget->window,
4925 GTK_WIDGET_STATE (widget), GTK_SHADOW_ETCHED_OUT,
4926 area, widget, "hseparator",
4927 allocation->x + allocation->width * start_fraction,
4928 allocation->y + (allocation->height - separator_height) / 2,
4929 allocation->width * (end_fraction - start_fraction),
4932 gtk_paint_hline (widget->style, widget->window,
4933 GTK_WIDGET_STATE (widget), area, widget,
4935 allocation->x + allocation->width * start_fraction,
4936 allocation->x + allocation->width * end_fraction,
4937 allocation->y + (allocation->height - widget->style->ythickness) / 2);
4942 _gtk_toolbar_elide_underscores (const gchar *original)
4945 const gchar *p, *end;
4947 gboolean last_underscore;
4952 len = strlen (original);
4953 q = result = g_malloc (len + 1);
4954 last_underscore = FALSE;
4956 end = original + len;
4957 for (p = original; p < end; p++)
4959 if (!last_underscore && *p == '_')
4960 last_underscore = TRUE;
4963 last_underscore = FALSE;
4964 if (original + 2 <= p && p + 1 <= end &&
4965 p[-2] == '(' && p[-1] == '_' && p[0] != '_' && p[1] == ')')
4976 if (last_underscore)
4985 toolbar_get_icon_size (GtkToolShell *shell)
4987 return GTK_TOOLBAR (shell)->icon_size;
4990 static GtkOrientation
4991 toolbar_get_orientation (GtkToolShell *shell)
4993 return GTK_TOOLBAR (shell)->orientation;
4996 static GtkToolbarStyle
4997 toolbar_get_style (GtkToolShell *shell)
4999 return GTK_TOOLBAR (shell)->style;
5002 static GtkReliefStyle
5003 toolbar_get_relief_style (GtkToolShell *shell)
5005 return get_button_relief (GTK_TOOLBAR (shell));
5009 toolbar_rebuild_menu (GtkToolShell *shell)
5011 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (shell);
5014 priv->need_rebuild = TRUE;
5016 for (list = priv->content; list != NULL; list = list->next)
5018 ToolbarContent *content = list->data;
5020 toolbar_content_set_unknown_menu_status (content);
5023 gtk_widget_queue_resize (GTK_WIDGET (shell));
5026 #define __GTK_TOOLBAR_C__
5027 #include "gtkaliasdef.c"