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
36 #include "gtktoolbar.h"
37 #include "gtkradiotoolbutton.h"
38 #include "gtkseparatortoolitem.h"
40 #include "gtkradiobutton.h"
41 #include "gtktoolbar.h"
42 #include "gtkbindings.h"
43 #include <gdk/gdkkeysyms.h>
44 #include "gtkmarshalers.h"
48 #include "gtkprivate.h"
54 #include "gtkseparatormenuitem.h"
58 typedef struct _ToolbarContent ToolbarContent;
60 #define DEFAULT_IPADDING 0
62 #define DEFAULT_SPACE_SIZE 12
63 #define DEFAULT_SPACE_STYLE GTK_TOOLBAR_SPACE_LINE
64 #define SPACE_LINE_DIVISION 10.0
65 #define SPACE_LINE_START 2.0
66 #define SPACE_LINE_END 8.0
68 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_LARGE_TOOLBAR
69 #define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_BOTH
70 #define DEFAULT_ANIMATION_STATE TRUE
72 #define MAX_HOMOGENEOUS_N_CHARS 13 /* Items that are wider than this do not participate
73 * in the homogeneous game. In units of
74 * pango_font_get_estimated_char_width().
76 #define SLIDE_SPEED 600.0 /* How fast the items slide, in pixels per second */
77 #define ACCEL_THRESHOLD 0.18 /* After how much time in seconds will items start speeding up */
79 #define MIXED_API_WARNING \
80 "Mixing deprecated and non-deprecated GtkToolbar API is not allowed"
94 /* Child properties */
98 CHILD_PROP_HOMOGENEOUS
129 struct _GtkToolbarPrivate
134 GtkWidget * arrow_button;
137 GdkWindow * event_window;
139 GtkSettings * settings;
141 GtkToolItem * highlight_tool_item;
142 gint max_homogeneous_pixels;
146 gulong settings_connection;
148 guint show_arrow : 1;
150 guint is_sliding : 1;
151 guint need_rebuild : 1; /* whether the overflow menu should be regenerated */
155 static void gtk_toolbar_set_property (GObject *object,
159 static void gtk_toolbar_get_property (GObject *object,
163 static gint gtk_toolbar_expose (GtkWidget *widget,
164 GdkEventExpose *event);
165 static void gtk_toolbar_realize (GtkWidget *widget);
166 static void gtk_toolbar_unrealize (GtkWidget *widget);
167 static void gtk_toolbar_size_request (GtkWidget *widget,
168 GtkRequisition *requisition);
169 static void gtk_toolbar_size_allocate (GtkWidget *widget,
170 GtkAllocation *allocation);
171 static void gtk_toolbar_style_set (GtkWidget *widget,
172 GtkStyle *prev_style);
173 static gboolean gtk_toolbar_focus (GtkWidget *widget,
174 GtkDirectionType dir);
175 static void gtk_toolbar_move_focus (GtkWidget *widget,
176 GtkDirectionType dir);
177 static void gtk_toolbar_screen_changed (GtkWidget *widget,
178 GdkScreen *previous_screen);
179 static void gtk_toolbar_map (GtkWidget *widget);
180 static void gtk_toolbar_unmap (GtkWidget *widget);
181 static void gtk_toolbar_set_child_property (GtkContainer *container,
186 static void gtk_toolbar_get_child_property (GtkContainer *container,
191 static void gtk_toolbar_finalize (GObject *object);
192 static void gtk_toolbar_show_all (GtkWidget *widget);
193 static void gtk_toolbar_hide_all (GtkWidget *widget);
194 static void gtk_toolbar_add (GtkContainer *container,
196 static void gtk_toolbar_remove (GtkContainer *container,
198 static void gtk_toolbar_forall (GtkContainer *container,
199 gboolean include_internals,
200 GtkCallback callback,
201 gpointer callback_data);
202 static GType gtk_toolbar_child_type (GtkContainer *container);
203 static void gtk_toolbar_orientation_changed (GtkToolbar *toolbar,
204 GtkOrientation orientation);
205 static void gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
206 GtkToolbarStyle style);
207 static gboolean gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
208 gboolean focus_home);
209 static gboolean gtk_toolbar_button_press (GtkWidget *toolbar,
210 GdkEventButton *event);
211 static gboolean gtk_toolbar_arrow_button_press (GtkWidget *button,
212 GdkEventButton *event,
213 GtkToolbar *toolbar);
214 static void gtk_toolbar_arrow_button_clicked (GtkWidget *button,
215 GtkToolbar *toolbar);
216 static void gtk_toolbar_update_button_relief (GtkToolbar *toolbar);
217 static gboolean gtk_toolbar_popup_menu (GtkWidget *toolbar);
218 static GtkWidget *internal_insert_element (GtkToolbar *toolbar,
219 GtkToolbarChildType type,
222 const char *tooltip_text,
223 const char *tooltip_private_text,
225 GtkSignalFunc callback,
229 static void gtk_toolbar_reconfigured (GtkToolbar *toolbar);
230 static gboolean gtk_toolbar_check_new_api (GtkToolbar *toolbar);
231 static gboolean gtk_toolbar_check_old_api (GtkToolbar *toolbar);
233 static GtkReliefStyle get_button_relief (GtkToolbar *toolbar);
234 static gint get_internal_padding (GtkToolbar *toolbar);
235 static gint get_max_child_expand (GtkToolbar *toolbar);
236 static GtkShadowType get_shadow_type (GtkToolbar *toolbar);
237 static gint get_space_size (GtkToolbar *toolbar);
238 static GtkToolbarSpaceStyle get_space_style (GtkToolbar *toolbar);
240 /* methods on ToolbarContent 'class' */
241 static ToolbarContent *toolbar_content_new_tool_item (GtkToolbar *toolbar,
243 gboolean is_placeholder,
245 static ToolbarContent *toolbar_content_new_compatibility (GtkToolbar *toolbar,
246 GtkToolbarChildType type,
251 static void toolbar_content_remove (ToolbarContent *content,
252 GtkToolbar *toolbar);
253 static void toolbar_content_free (ToolbarContent *content);
254 static void toolbar_content_expose (ToolbarContent *content,
255 GtkContainer *container,
256 GdkEventExpose *expose);
257 static gboolean toolbar_content_visible (ToolbarContent *content,
258 GtkToolbar *toolbar);
259 static void toolbar_content_size_request (ToolbarContent *content,
261 GtkRequisition *requisition);
262 static gboolean toolbar_content_is_homogeneous (ToolbarContent *content,
263 GtkToolbar *toolbar);
264 static gboolean toolbar_content_is_placeholder (ToolbarContent *content);
265 static gboolean toolbar_content_disappearing (ToolbarContent *content);
266 static ItemState toolbar_content_get_state (ToolbarContent *content);
267 static gboolean toolbar_content_child_visible (ToolbarContent *content);
268 static void toolbar_content_get_goal_allocation (ToolbarContent *content,
269 GtkAllocation *allocation);
270 static void toolbar_content_get_allocation (ToolbarContent *content,
271 GtkAllocation *allocation);
272 static void toolbar_content_set_start_allocation (ToolbarContent *content,
273 GtkAllocation *new_start_allocation);
274 static void toolbar_content_get_start_allocation (ToolbarContent *content,
275 GtkAllocation *start_allocation);
276 static gboolean toolbar_content_get_expand (ToolbarContent *content);
277 static void toolbar_content_set_goal_allocation (ToolbarContent *content,
278 GtkAllocation *allocation);
279 static void toolbar_content_set_child_visible (ToolbarContent *content,
282 static void toolbar_content_size_allocate (ToolbarContent *content,
283 GtkAllocation *allocation);
284 static void toolbar_content_set_state (ToolbarContent *content,
285 ItemState new_state);
286 static GtkWidget * toolbar_content_get_widget (ToolbarContent *content);
287 static void toolbar_content_set_disappearing (ToolbarContent *content,
288 gboolean disappearing);
289 static void toolbar_content_set_size_request (ToolbarContent *content,
292 static void toolbar_content_toolbar_reconfigured (ToolbarContent *content,
293 GtkToolbar *toolbar);
294 static GtkWidget * toolbar_content_retrieve_menu_item (ToolbarContent *content);
295 static gboolean toolbar_content_has_proxy_menu_item (ToolbarContent *content);
296 static gboolean toolbar_content_is_separator (ToolbarContent *content);
297 static void toolbar_content_show_all (ToolbarContent *content);
298 static void toolbar_content_hide_all (ToolbarContent *content);
299 static void toolbar_content_set_expand (ToolbarContent *content,
302 #define GTK_TOOLBAR_GET_PRIVATE(o) \
303 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_TOOLBAR, GtkToolbarPrivate))
305 static guint toolbar_signals [LAST_SIGNAL] = { 0 };
307 G_DEFINE_TYPE (GtkToolbar, gtk_toolbar, GTK_TYPE_CONTAINER)
310 add_arrow_bindings (GtkBindingSet *binding_set,
312 GtkDirectionType dir)
314 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
316 gtk_binding_entry_add_signal (binding_set, keysym, 0,
318 GTK_TYPE_DIRECTION_TYPE, dir);
319 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
321 GTK_TYPE_DIRECTION_TYPE, dir);
325 add_ctrl_tab_bindings (GtkBindingSet *binding_set,
326 GdkModifierType modifiers,
327 GtkDirectionType direction)
329 gtk_binding_entry_add_signal (binding_set,
330 GDK_Tab, GDK_CONTROL_MASK | modifiers,
332 GTK_TYPE_DIRECTION_TYPE, direction);
333 gtk_binding_entry_add_signal (binding_set,
334 GDK_KP_Tab, GDK_CONTROL_MASK | modifiers,
336 GTK_TYPE_DIRECTION_TYPE, direction);
340 gtk_toolbar_class_init (GtkToolbarClass *klass)
342 GObjectClass *gobject_class;
343 GtkWidgetClass *widget_class;
344 GtkContainerClass *container_class;
345 GtkBindingSet *binding_set;
347 gobject_class = (GObjectClass *)klass;
348 widget_class = (GtkWidgetClass *)klass;
349 container_class = (GtkContainerClass *)klass;
351 gobject_class->set_property = gtk_toolbar_set_property;
352 gobject_class->get_property = gtk_toolbar_get_property;
353 gobject_class->finalize = gtk_toolbar_finalize;
355 widget_class->button_press_event = gtk_toolbar_button_press;
356 widget_class->expose_event = gtk_toolbar_expose;
357 widget_class->size_request = gtk_toolbar_size_request;
358 widget_class->size_allocate = gtk_toolbar_size_allocate;
359 widget_class->style_set = gtk_toolbar_style_set;
360 widget_class->focus = gtk_toolbar_focus;
362 /* need to override the base class function via override_class_closure,
363 * because the signal slot is not available in GtkWidgetClass
365 g_signal_override_class_closure (g_signal_lookup ("move_focus",
368 g_cclosure_new (G_CALLBACK (gtk_toolbar_move_focus),
371 widget_class->screen_changed = gtk_toolbar_screen_changed;
372 widget_class->realize = gtk_toolbar_realize;
373 widget_class->unrealize = gtk_toolbar_unrealize;
374 widget_class->map = gtk_toolbar_map;
375 widget_class->unmap = gtk_toolbar_unmap;
376 widget_class->popup_menu = gtk_toolbar_popup_menu;
377 widget_class->show_all = gtk_toolbar_show_all;
378 widget_class->hide_all = gtk_toolbar_hide_all;
380 container_class->add = gtk_toolbar_add;
381 container_class->remove = gtk_toolbar_remove;
382 container_class->forall = gtk_toolbar_forall;
383 container_class->child_type = gtk_toolbar_child_type;
384 container_class->get_child_property = gtk_toolbar_get_child_property;
385 container_class->set_child_property = gtk_toolbar_set_child_property;
387 klass->orientation_changed = gtk_toolbar_orientation_changed;
388 klass->style_changed = gtk_toolbar_real_style_changed;
391 * GtkToolbar::orientation-changed:
392 * @toolbar: the object which emitted the signal
393 * @orientation: the new #GtkOrientation of the toolbar
395 * Emitted when the orientation of the toolbar changes.
397 toolbar_signals[ORIENTATION_CHANGED] =
398 g_signal_new (I_("orientation-changed"),
399 G_OBJECT_CLASS_TYPE (klass),
401 G_STRUCT_OFFSET (GtkToolbarClass, orientation_changed),
403 g_cclosure_marshal_VOID__ENUM,
405 GTK_TYPE_ORIENTATION);
407 * GtkToolbar::style-changed:
408 * @toolbar: The #GtkToolbar which emitted the signal
409 * @style: the new #GtkToolbarStyle of the toolbar
411 * Emitted when the style of the toolbar changes.
413 toolbar_signals[STYLE_CHANGED] =
414 g_signal_new (I_("style-changed"),
415 G_OBJECT_CLASS_TYPE (klass),
417 G_STRUCT_OFFSET (GtkToolbarClass, style_changed),
419 g_cclosure_marshal_VOID__ENUM,
421 GTK_TYPE_TOOLBAR_STYLE);
423 * GtkToolbar::popup-context-menu:
424 * @toolbar: the #GtkToolbar which emitted the signal
425 * @x: the x coordinate of the point where the menu should appear
426 * @y: the y coordinate of the point where the menu should appear
427 * @button: the mouse button the user pressed, or -1
429 * Emitted when the user right-clicks the toolbar or uses the
430 * keybinding to display a popup menu.
432 * Application developers should handle this signal if they want
433 * to display a context menu on the toolbar. The context-menu should
434 * appear at the coordinates given by @x and @y. The mouse button
435 * number is given by the @button parameter. If the menu was popped
436 * up using the keybaord, @button is -1.
438 * Return value: return %TRUE if the signal was handled, %FALSE if not
440 toolbar_signals[POPUP_CONTEXT_MENU] =
441 g_signal_new (I_("popup_context_menu"),
442 G_OBJECT_CLASS_TYPE (klass),
444 G_STRUCT_OFFSET (GtkToolbarClass, popup_context_menu),
445 _gtk_boolean_handled_accumulator, NULL,
446 _gtk_marshal_BOOLEAN__INT_INT_INT,
448 G_TYPE_INT, G_TYPE_INT,
452 * GtkToolbar::focus-home-or-end:
453 * @toolbar: the #GtkToolbar which emitted the signal
454 * @focus_home: %TRUE if the first item should be focused
456 * A keybinding signal used internally by GTK+. This signal can't
457 * be used in application code
459 * Return value: %TRUE if the signal was handled, %FALSE if not
461 toolbar_signals[FOCUS_HOME_OR_END] =
462 _gtk_binding_signal_new (I_("focus_home_or_end"),
463 G_OBJECT_CLASS_TYPE (klass),
464 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
465 G_CALLBACK (gtk_toolbar_focus_home_or_end),
467 _gtk_marshal_BOOLEAN__BOOLEAN,
472 g_object_class_install_property (gobject_class,
474 g_param_spec_enum ("orientation",
476 P_("The orientation of the toolbar"),
477 GTK_TYPE_ORIENTATION,
478 GTK_ORIENTATION_HORIZONTAL,
479 GTK_PARAM_READWRITE));
481 g_object_class_install_property (gobject_class,
483 g_param_spec_enum ("toolbar-style",
485 P_("How to draw the toolbar"),
486 GTK_TYPE_TOOLBAR_STYLE,
488 GTK_PARAM_READWRITE));
489 g_object_class_install_property (gobject_class,
491 g_param_spec_boolean ("show-arrow",
493 P_("If an arrow should be shown if the toolbar doesn't fit"),
495 GTK_PARAM_READWRITE));
499 * GtkToolbar:tooltips:
501 * If the tooltips of the toolbar should be active or not.
505 g_object_class_install_property (gobject_class,
507 g_param_spec_boolean ("tooltips",
509 P_("If the tooltips of the toolbar should be active or not"),
511 GTK_PARAM_READWRITE));
515 * GtkToolbar:icon-size:
517 * The size of the icons in a toolbar is normally determined by
518 * the toolbar-icon-size setting. When this property is set, it
519 * overrides the setting.
521 * This should only be used for special-purpose toolbars, normal
522 * application toolbars should respect the user preferences for the
527 g_object_class_install_property (gobject_class,
529 g_param_spec_enum ("icon-size",
531 P_("Size of icons in this toolbar"),
534 GTK_PARAM_READWRITE));
537 * GtkToolbar:icon-size-set:
539 * Is %TRUE if the icon-size property has been set.
543 g_object_class_install_property (gobject_class,
545 g_param_spec_boolean ("icon-size-set",
547 P_("Whether the icon-size property has been set"),
549 GTK_PARAM_READWRITE));
551 /* child properties */
552 gtk_container_class_install_child_property (container_class,
554 g_param_spec_boolean ("expand",
556 P_("Whether the item should receive extra space when the toolbar grows"),
558 GTK_PARAM_READWRITE));
560 gtk_container_class_install_child_property (container_class,
561 CHILD_PROP_HOMOGENEOUS,
562 g_param_spec_boolean ("homogeneous",
564 P_("Whether the item should be the same size as other homogeneous items"),
566 GTK_PARAM_READWRITE));
568 /* style properties */
569 gtk_widget_class_install_style_property (widget_class,
570 g_param_spec_int ("space-size",
572 P_("Size of spacers"),
576 GTK_PARAM_READABLE));
578 gtk_widget_class_install_style_property (widget_class,
579 g_param_spec_int ("internal-padding",
580 P_("Internal padding"),
581 P_("Amount of border space between the toolbar shadow and the buttons"),
585 GTK_PARAM_READABLE));
587 gtk_widget_class_install_style_property (widget_class,
588 g_param_spec_int ("max-child-expand",
589 P_("Maximum child expand"),
590 P_("Maximum amount of space an expandable item will be given"),
594 GTK_PARAM_READABLE));
596 gtk_widget_class_install_style_property (widget_class,
597 g_param_spec_enum ("space-style",
599 P_("Whether spacers are vertical lines or just blank"),
600 GTK_TYPE_TOOLBAR_SPACE_STYLE,
602 GTK_PARAM_READABLE));
604 gtk_widget_class_install_style_property (widget_class,
605 g_param_spec_enum ("button-relief",
607 P_("Type of bevel around toolbar buttons"),
608 GTK_TYPE_RELIEF_STYLE,
610 GTK_PARAM_READABLE));
611 gtk_widget_class_install_style_property (widget_class,
612 g_param_spec_enum ("shadow-type",
614 P_("Style of bevel around the toolbar"),
615 GTK_TYPE_SHADOW_TYPE,
617 GTK_PARAM_READABLE));
619 gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-style",
621 P_("Whether default toolbars have text only, text and icons, icons only, etc."),
622 GTK_TYPE_TOOLBAR_STYLE,
623 DEFAULT_TOOLBAR_STYLE,
624 GTK_PARAM_READWRITE));
626 gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-icon-size",
627 P_("Toolbar icon size"),
628 P_("Size of icons in default toolbars"),
631 GTK_PARAM_READWRITE));
633 binding_set = gtk_binding_set_by_class (klass);
635 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
636 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
637 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
638 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
640 gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
641 "focus_home_or_end", 1,
642 G_TYPE_BOOLEAN, TRUE);
643 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
644 "focus_home_or_end", 1,
645 G_TYPE_BOOLEAN, TRUE);
646 gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
647 "focus_home_or_end", 1,
648 G_TYPE_BOOLEAN, FALSE);
649 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
650 "focus_home_or_end", 1,
651 G_TYPE_BOOLEAN, FALSE);
653 add_ctrl_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
654 add_ctrl_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
656 g_type_class_add_private (gobject_class, sizeof (GtkToolbarPrivate));
660 gtk_toolbar_init (GtkToolbar *toolbar)
662 GtkToolbarPrivate *priv;
664 GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS);
665 GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
667 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
669 toolbar->orientation = GTK_ORIENTATION_HORIZONTAL;
670 toolbar->style = DEFAULT_TOOLBAR_STYLE;
671 toolbar->icon_size = DEFAULT_ICON_SIZE;
672 priv->animation = DEFAULT_ANIMATION_STATE;
673 toolbar->tooltips = gtk_tooltips_new ();
674 g_object_ref_sink (toolbar->tooltips);
676 priv->arrow_button = gtk_toggle_button_new ();
677 g_signal_connect (priv->arrow_button, "button_press_event",
678 G_CALLBACK (gtk_toolbar_arrow_button_press), toolbar);
679 g_signal_connect (priv->arrow_button, "clicked",
680 G_CALLBACK (gtk_toolbar_arrow_button_clicked), toolbar);
681 gtk_button_set_relief (GTK_BUTTON (priv->arrow_button),
682 get_button_relief (toolbar));
684 priv->api_mode = DONT_KNOW;
686 gtk_button_set_focus_on_click (GTK_BUTTON (priv->arrow_button), FALSE);
688 priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
689 gtk_widget_set_name (priv->arrow, "gtk-toolbar-arrow");
690 gtk_widget_show (priv->arrow);
691 gtk_container_add (GTK_CONTAINER (priv->arrow_button), priv->arrow);
693 gtk_widget_set_parent (priv->arrow_button, GTK_WIDGET (toolbar));
695 /* which child position a drop will occur at */
697 priv->show_arrow = TRUE;
698 priv->settings = NULL;
700 priv->max_homogeneous_pixels = -1;
702 priv->timer = g_timer_new ();
706 gtk_toolbar_set_property (GObject *object,
711 GtkToolbar *toolbar = GTK_TOOLBAR (object);
715 case PROP_ORIENTATION:
716 gtk_toolbar_set_orientation (toolbar, g_value_get_enum (value));
718 case PROP_TOOLBAR_STYLE:
719 gtk_toolbar_set_style (toolbar, g_value_get_enum (value));
721 case PROP_SHOW_ARROW:
722 gtk_toolbar_set_show_arrow (toolbar, g_value_get_boolean (value));
725 gtk_toolbar_set_tooltips (toolbar, g_value_get_boolean (value));
728 gtk_toolbar_set_icon_size (toolbar, g_value_get_enum (value));
730 case PROP_ICON_SIZE_SET:
731 if (g_value_get_boolean (value))
732 toolbar->icon_size_set = TRUE;
734 gtk_toolbar_unset_icon_size (toolbar);
737 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
743 gtk_toolbar_get_property (GObject *object,
748 GtkToolbar *toolbar = GTK_TOOLBAR (object);
749 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
753 case PROP_ORIENTATION:
754 g_value_set_enum (value, toolbar->orientation);
756 case PROP_TOOLBAR_STYLE:
757 g_value_set_enum (value, toolbar->style);
759 case PROP_SHOW_ARROW:
760 g_value_set_boolean (value, priv->show_arrow);
763 g_value_set_boolean (value, gtk_toolbar_get_tooltips (toolbar));
766 g_value_set_enum (value, gtk_toolbar_get_icon_size (toolbar));
768 case PROP_ICON_SIZE_SET:
769 g_value_set_boolean (value, toolbar->icon_size_set);
772 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
778 gtk_toolbar_map (GtkWidget *widget)
780 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
782 GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->map (widget);
784 if (priv->event_window)
785 gdk_window_show_unraised (priv->event_window);
789 gtk_toolbar_unmap (GtkWidget *widget)
791 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
793 if (priv->event_window)
794 gdk_window_hide (priv->event_window);
796 GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->unmap (widget);
800 gtk_toolbar_realize (GtkWidget *widget)
802 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
803 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
805 GdkWindowAttr attributes;
806 gint attributes_mask;
809 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
811 border_width = GTK_CONTAINER (widget)->border_width;
813 attributes.wclass = GDK_INPUT_ONLY;
814 attributes.window_type = GDK_WINDOW_CHILD;
815 attributes.x = widget->allocation.x + border_width;
816 attributes.y = widget->allocation.y + border_width;
817 attributes.width = widget->allocation.width - border_width * 2;
818 attributes.height = widget->allocation.height - border_width * 2;
819 attributes.event_mask = gtk_widget_get_events (widget);
820 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
821 GDK_BUTTON_RELEASE_MASK |
822 GDK_ENTER_NOTIFY_MASK |
823 GDK_LEAVE_NOTIFY_MASK);
825 attributes_mask = GDK_WA_X | GDK_WA_Y;
827 widget->window = gtk_widget_get_parent_window (widget);
828 g_object_ref (widget->window);
829 widget->style = gtk_style_attach (widget->style, widget->window);
831 priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
832 &attributes, attributes_mask);
833 gdk_window_set_user_data (priv->event_window, toolbar);
837 gtk_toolbar_unrealize (GtkWidget *widget)
839 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
841 if (priv->event_window)
843 gdk_window_set_user_data (priv->event_window, NULL);
844 gdk_window_destroy (priv->event_window);
845 priv->event_window = NULL;
848 if (GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->unrealize)
849 (* GTK_WIDGET_CLASS (gtk_toolbar_parent_class)->unrealize) (widget);
853 gtk_toolbar_expose (GtkWidget *widget,
854 GdkEventExpose *event)
856 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
857 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
862 border_width = GTK_CONTAINER (widget)->border_width;
864 if (GTK_WIDGET_DRAWABLE (widget))
866 gtk_paint_box (widget->style,
868 GTK_WIDGET_STATE (widget),
869 get_shadow_type (toolbar),
870 &event->area, widget, "toolbar",
871 border_width + widget->allocation.x,
872 border_width + widget->allocation.y,
873 widget->allocation.width - 2 * border_width,
874 widget->allocation.height - 2 * border_width);
877 for (list = priv->content; list != NULL; list = list->next)
879 ToolbarContent *content = list->data;
881 toolbar_content_expose (content, GTK_CONTAINER (widget), event);
884 gtk_container_propagate_expose (GTK_CONTAINER (widget),
892 gtk_toolbar_size_request (GtkWidget *widget,
893 GtkRequisition *requisition)
895 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
896 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
898 gint max_child_height;
899 gint max_child_width;
900 gint max_homogeneous_child_width;
901 gint max_homogeneous_child_height;
902 gint homogeneous_size;
904 gint pack_front_size;
906 GtkRequisition arrow_requisition;
908 max_homogeneous_child_width = 0;
909 max_homogeneous_child_height = 0;
911 max_child_height = 0;
912 for (list = priv->content; list != NULL; list = list->next)
914 GtkRequisition requisition;
915 ToolbarContent *content = list->data;
917 if (!toolbar_content_visible (content, toolbar))
920 toolbar_content_size_request (content, toolbar, &requisition);
922 max_child_width = MAX (max_child_width, requisition.width);
923 max_child_height = MAX (max_child_height, requisition.height);
925 if (toolbar_content_is_homogeneous (content, toolbar))
927 max_homogeneous_child_width = MAX (max_homogeneous_child_width, requisition.width);
928 max_homogeneous_child_height = MAX (max_homogeneous_child_height, requisition.height);
932 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
933 homogeneous_size = max_homogeneous_child_width;
935 homogeneous_size = max_homogeneous_child_height;
938 for (list = priv->content; list != NULL; list = list->next)
940 ToolbarContent *content = list->data;
943 if (!toolbar_content_visible (content, toolbar))
946 if (toolbar_content_is_homogeneous (content, toolbar))
948 size = homogeneous_size;
952 GtkRequisition requisition;
954 toolbar_content_size_request (content, toolbar, &requisition);
956 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
957 size = requisition.width;
959 size = requisition.height;
962 pack_front_size += size;
965 if (priv->show_arrow && priv->api_mode == NEW_API)
967 gtk_widget_size_request (priv->arrow_button, &arrow_requisition);
969 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
970 long_req = arrow_requisition.width;
972 long_req = arrow_requisition.height;
974 /* There is no point requesting space for the arrow if that would take
975 * up more space than all the items combined
977 long_req = MIN (long_req, pack_front_size);
981 arrow_requisition.height = 0;
982 arrow_requisition.width = 0;
984 long_req = pack_front_size;
987 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
989 requisition->width = long_req;
990 requisition->height = MAX (max_child_height, arrow_requisition.height);
994 requisition->height = long_req;
995 requisition->width = MAX (max_child_width, arrow_requisition.width);
999 ipadding = get_internal_padding (toolbar);
1001 requisition->width += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width);
1002 requisition->height += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width);
1004 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1006 requisition->width += 2 * widget->style->xthickness;
1007 requisition->height += 2 * widget->style->ythickness;
1010 toolbar->button_maxw = max_homogeneous_child_width;
1011 toolbar->button_maxh = max_homogeneous_child_height;
1015 position (GtkToolbar *toolbar,
1022 if (! GTK_TOOLBAR_GET_PRIVATE (toolbar)->animation)
1025 if (elapsed <= ACCEL_THRESHOLD)
1027 n_pixels = SLIDE_SPEED * elapsed;
1031 /* The formula is a second degree polynomial in
1032 * @elapsed that has the line SLIDE_SPEED * @elapsed
1033 * as tangent for @elapsed == ACCEL_THRESHOLD.
1034 * This makes @n_pixels a smooth function of elapsed time.
1036 n_pixels = (SLIDE_SPEED / ACCEL_THRESHOLD) * elapsed * elapsed -
1037 SLIDE_SPEED * elapsed + SLIDE_SPEED * ACCEL_THRESHOLD;
1041 return MIN (from + n_pixels, to);
1043 return MAX (from - n_pixels, to);
1047 compute_intermediate_allocation (GtkToolbar *toolbar,
1048 const GtkAllocation *start,
1049 const GtkAllocation *goal,
1050 GtkAllocation *intermediate)
1052 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1053 gdouble elapsed = g_timer_elapsed (priv->timer, NULL);
1055 intermediate->x = position (toolbar, start->x, goal->x, elapsed);
1056 intermediate->y = position (toolbar, start->y, goal->y, elapsed);
1057 intermediate->width = position (toolbar, start->x + start->width,
1058 goal->x + goal->width,
1059 elapsed) - intermediate->x;
1060 intermediate->height = position (toolbar, start->y + start->height,
1061 goal->y + goal->height,
1062 elapsed) - intermediate->y;
1066 fixup_allocation_for_rtl (gint total_size,
1067 GtkAllocation *allocation)
1069 allocation->x += (total_size - (2 * allocation->x + allocation->width));
1073 fixup_allocation_for_vertical (GtkAllocation *allocation)
1077 tmp = allocation->x;
1078 allocation->x = allocation->y;
1079 allocation->y = tmp;
1081 tmp = allocation->width;
1082 allocation->width = allocation->height;
1083 allocation->height = tmp;
1087 get_item_size (GtkToolbar *toolbar,
1088 ToolbarContent *content)
1090 GtkRequisition requisition;
1092 toolbar_content_size_request (content, toolbar, &requisition);
1094 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1096 if (toolbar_content_is_homogeneous (content, toolbar))
1097 return toolbar->button_maxw;
1099 return requisition.width;
1103 if (toolbar_content_is_homogeneous (content, toolbar))
1104 return toolbar->button_maxh;
1106 return requisition.height;
1111 slide_idle_handler (gpointer data)
1113 GtkToolbar *toolbar = data;
1114 GtkToolbarPrivate *priv;
1117 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1119 if (priv->need_sync)
1122 priv->need_sync = FALSE;
1125 for (list = priv->content; list != NULL; list = list->next)
1127 ToolbarContent *content = list->data;
1129 GtkAllocation goal_allocation;
1130 GtkAllocation allocation;
1133 state = toolbar_content_get_state (content);
1134 toolbar_content_get_goal_allocation (content, &goal_allocation);
1135 toolbar_content_get_allocation (content, &allocation);
1139 if (state == NOT_ALLOCATED)
1141 /* an unallocated item means that size allocate has to
1142 * called at least once more
1147 /* An invisible item with a goal allocation of
1148 * 0 is already at its goal.
1150 if ((state == NORMAL || state == OVERFLOWN) &&
1151 ((goal_allocation.width != 0 &&
1152 goal_allocation.height != 0) ||
1153 toolbar_content_child_visible (content)))
1155 if ((goal_allocation.x != allocation.x ||
1156 goal_allocation.y != allocation.y ||
1157 goal_allocation.width != allocation.width ||
1158 goal_allocation.height != allocation.height))
1160 /* An item is not in its right position yet. Note
1161 * that OVERFLOWN items do get an allocation in
1162 * gtk_toolbar_size_allocate(). This way you can see
1163 * them slide back in when you drag an item off the
1170 if (toolbar_content_is_placeholder (content) &&
1171 toolbar_content_disappearing (content) &&
1172 toolbar_content_child_visible (content))
1174 /* A disappearing placeholder is still visible.
1182 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1184 GDK_THREADS_LEAVE ();
1189 priv->is_sliding = FALSE;
1196 rect_within (GtkAllocation *a1,
1199 return (a1->x >= a2->x &&
1200 a1->x + a1->width <= a2->x + a2->width &&
1202 a1->y + a1->height <= a2->y + a2->height);
1206 gtk_toolbar_begin_sliding (GtkToolbar *toolbar)
1208 GtkWidget *widget = GTK_WIDGET (toolbar);
1209 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1217 /* Start the sliding. This function copies the allocation of every
1218 * item into content->start_allocation. For items that haven't
1219 * been allocated yet, we calculate their position and save that
1220 * in start_allocatino along with zero width and zero height.
1222 * FIXME: It would be nice if we could share this code with
1223 * the equivalent in gtk_widget_size_allocate().
1225 priv->is_sliding = TRUE;
1228 priv->idle_id = gdk_threads_add_idle (slide_idle_handler, toolbar);
1230 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1231 vertical = (toolbar->orientation == GTK_ORIENTATION_VERTICAL);
1232 border_width = get_internal_padding (toolbar) + GTK_CONTAINER (toolbar)->border_width;
1236 cur_x = widget->allocation.width - border_width - widget->style->xthickness;
1237 cur_y = widget->allocation.height - border_width - widget->style->ythickness;
1241 cur_x = border_width + widget->style->xthickness;
1242 cur_y = border_width + widget->style->ythickness;
1245 cur_x += widget->allocation.x;
1246 cur_y += widget->allocation.y;
1248 for (list = priv->content; list != NULL; list = list->next)
1250 ToolbarContent *content = list->data;
1251 GtkAllocation new_start_allocation;
1252 GtkAllocation item_allocation;
1255 state = toolbar_content_get_state (content);
1256 toolbar_content_get_allocation (content, &item_allocation);
1258 if ((state == NORMAL &&
1259 rect_within (&item_allocation, &(widget->allocation))) ||
1262 new_start_allocation = item_allocation;
1266 new_start_allocation.x = cur_x;
1267 new_start_allocation.y = cur_y;
1271 new_start_allocation.width = widget->allocation.width -
1272 2 * border_width - 2 * widget->style->xthickness;
1273 new_start_allocation.height = 0;
1277 new_start_allocation.width = 0;
1278 new_start_allocation.height = widget->allocation.height -
1279 2 * border_width - 2 * widget->style->ythickness;
1284 cur_y = new_start_allocation.y + new_start_allocation.height;
1286 cur_x = new_start_allocation.x;
1288 cur_x = new_start_allocation.x + new_start_allocation.width;
1290 toolbar_content_set_start_allocation (content, &new_start_allocation);
1293 /* This resize will run before the first idle handler. This
1294 * will make sure that items get the right goal allocation
1295 * so that the idle handler will not immediately return
1298 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1299 g_timer_reset (priv->timer);
1303 gtk_toolbar_stop_sliding (GtkToolbar *toolbar)
1305 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1307 if (priv->is_sliding)
1311 priv->is_sliding = FALSE;
1315 g_source_remove (priv->idle_id);
1319 list = priv->content;
1322 ToolbarContent *content = list->data;
1325 if (toolbar_content_is_placeholder (content))
1327 toolbar_content_remove (content, toolbar);
1328 toolbar_content_free (content);
1332 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1337 remove_item (GtkWidget *menu_item,
1340 gtk_container_remove (GTK_CONTAINER (menu_item->parent), menu_item);
1344 menu_deactivated (GtkWidget *menu,
1345 GtkToolbar *toolbar)
1347 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1348 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->arrow_button), FALSE);
1352 menu_detached (GtkWidget *toolbar,
1355 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1360 rebuild_menu (GtkToolbar *toolbar)
1362 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1363 GList *list, *children;
1367 priv->menu = GTK_MENU (gtk_menu_new());
1368 gtk_menu_attach_to_widget (priv->menu,
1369 GTK_WIDGET (toolbar),
1372 g_signal_connect (priv->menu, "deactivate", G_CALLBACK (menu_deactivated), toolbar);
1375 gtk_container_foreach (GTK_CONTAINER (priv->menu), remove_item, NULL);
1377 for (list = priv->content; list != NULL; list = list->next)
1379 ToolbarContent *content = list->data;
1381 if (toolbar_content_get_state (content) == OVERFLOWN &&
1382 !toolbar_content_is_placeholder (content))
1384 GtkWidget *menu_item = toolbar_content_retrieve_menu_item (content);
1388 g_assert (GTK_IS_MENU_ITEM (menu_item));
1389 gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_item);
1394 /* Remove leading and trailing separator items */
1395 children = gtk_container_get_children (GTK_CONTAINER (priv->menu));
1398 while (list && GTK_IS_SEPARATOR_MENU_ITEM (list->data))
1400 GtkWidget *child = list->data;
1402 gtk_container_remove (GTK_CONTAINER (priv->menu), child);
1405 g_list_free (children);
1407 /* Regenerate the list of children so we don't try to remove items twice */
1408 children = gtk_container_get_children (GTK_CONTAINER (priv->menu));
1410 list = g_list_last (children);
1411 while (list && GTK_IS_SEPARATOR_MENU_ITEM (list->data))
1413 GtkWidget *child = list->data;
1415 gtk_container_remove (GTK_CONTAINER (priv->menu), child);
1418 g_list_free (children);
1420 priv->need_rebuild = FALSE;
1424 gtk_toolbar_size_allocate (GtkWidget *widget,
1425 GtkAllocation *allocation)
1427 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1428 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1429 GtkAllocation *allocations;
1430 ItemState *new_states;
1431 GtkAllocation arrow_allocation;
1433 gint size, pos, short_size;
1436 gboolean need_arrow;
1437 gint n_expand_items;
1439 gint available_size;
1442 GtkRequisition arrow_requisition;
1443 gboolean overflowing;
1444 gboolean size_changed;
1446 GtkAllocation item_area;
1447 GtkShadowType shadow_type;
1449 size_changed = FALSE;
1450 if (widget->allocation.x != allocation->x ||
1451 widget->allocation.y != allocation->y ||
1452 widget->allocation.width != allocation->width ||
1453 widget->allocation.height != allocation->height)
1455 size_changed = TRUE;
1459 gtk_toolbar_stop_sliding (toolbar);
1461 widget->allocation = *allocation;
1463 border_width = GTK_CONTAINER (toolbar)->border_width;
1465 if (GTK_WIDGET_REALIZED (widget))
1467 gdk_window_move_resize (priv->event_window,
1468 allocation->x + border_width,
1469 allocation->y + border_width,
1470 allocation->width - border_width * 2,
1471 allocation->height - border_width * 2);
1474 border_width += get_internal_padding (toolbar);
1476 gtk_widget_get_child_requisition (GTK_WIDGET (priv->arrow_button),
1477 &arrow_requisition);
1479 shadow_type = get_shadow_type (toolbar);
1481 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1483 available_size = size = allocation->width - 2 * border_width;
1484 short_size = allocation->height - 2 * border_width;
1485 arrow_size = arrow_requisition.width;
1487 if (shadow_type != GTK_SHADOW_NONE)
1489 available_size -= 2 * widget->style->xthickness;
1490 short_size -= 2 * widget->style->ythickness;
1495 available_size = size = allocation->height - 2 * border_width;
1496 short_size = allocation->width - 2 * border_width;
1497 arrow_size = arrow_requisition.height;
1499 if (shadow_type != GTK_SHADOW_NONE)
1501 available_size -= 2 * widget->style->ythickness;
1502 short_size -= 2 * widget->style->xthickness;
1506 n_items = g_list_length (priv->content);
1507 allocations = g_new0 (GtkAllocation, n_items);
1508 new_states = g_new0 (ItemState, n_items);
1512 for (list = priv->content; list != NULL; list = list->next)
1514 ToolbarContent *content = list->data;
1516 if (toolbar_content_visible (content, toolbar))
1518 needed_size += get_item_size (toolbar, content);
1520 /* Do we need an arrow?
1522 * Assume we don't, and see if any non-separator item with a
1523 * proxy menu item is then going to overflow.
1525 if (needed_size > available_size &&
1528 priv->api_mode == NEW_API &&
1529 toolbar_content_has_proxy_menu_item (content) &&
1530 !toolbar_content_is_separator (content))
1538 size = available_size - arrow_size;
1540 size = available_size;
1542 /* calculate widths and states of items */
1543 overflowing = FALSE;
1544 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1546 ToolbarContent *content = list->data;
1549 if (!toolbar_content_visible (content, toolbar))
1551 new_states[i] = HIDDEN;
1555 item_size = get_item_size (toolbar, content);
1556 if (item_size <= size && !overflowing)
1559 allocations[i].width = item_size;
1560 new_states[i] = NORMAL;
1565 new_states[i] = OVERFLOWN;
1566 allocations[i].width = item_size;
1570 /* calculate width of arrow */
1573 arrow_allocation.width = arrow_size;
1574 arrow_allocation.height = MAX (short_size, 1);
1577 /* expand expandable items */
1579 /* We don't expand when there is an overflow menu, because that leads to
1580 * weird jumps when items get moved to the overflow menu and the expanding
1581 * items suddenly get a lot of extra space
1585 gint max_child_expand;
1588 for (i = 0, list = priv->content; list != NULL; list = list->next, ++i)
1590 ToolbarContent *content = list->data;
1592 if (toolbar_content_get_expand (content) && new_states[i] == NORMAL)
1596 max_child_expand = get_max_child_expand (toolbar);
1597 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1599 ToolbarContent *content = list->data;
1601 if (toolbar_content_get_expand (content) && new_states[i] == NORMAL)
1603 gint extra = size / n_expand_items;
1604 if (size % n_expand_items != 0)
1607 if (extra > max_child_expand)
1608 extra = max_child_expand;
1610 allocations[i].width += extra;
1616 g_assert (n_expand_items == 0);
1619 /* position items */
1621 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1623 /* both NORMAL and OVERFLOWN items get a position. This ensures
1624 * that sliding will work for OVERFLOWN items too
1626 if (new_states[i] == NORMAL ||
1627 new_states[i] == OVERFLOWN)
1629 allocations[i].x = pos;
1630 allocations[i].y = border_width;
1631 allocations[i].height = short_size;
1633 pos += allocations[i].width;
1637 /* position arrow */
1640 arrow_allocation.x = available_size - border_width - arrow_allocation.width;
1641 arrow_allocation.y = border_width;
1644 item_area.x = border_width;
1645 item_area.y = border_width;
1646 item_area.width = available_size - (need_arrow? arrow_size : 0);
1647 item_area.height = short_size;
1649 /* fix up allocations in the vertical or RTL cases */
1650 if (toolbar->orientation == GTK_ORIENTATION_VERTICAL)
1652 for (i = 0; i < n_items; ++i)
1653 fixup_allocation_for_vertical (&(allocations[i]));
1656 fixup_allocation_for_vertical (&arrow_allocation);
1658 fixup_allocation_for_vertical (&item_area);
1660 else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1662 for (i = 0; i < n_items; ++i)
1663 fixup_allocation_for_rtl (available_size, &(allocations[i]));
1666 fixup_allocation_for_rtl (available_size, &arrow_allocation);
1668 fixup_allocation_for_rtl (available_size, &item_area);
1671 /* translate the items by allocation->(x,y) */
1672 for (i = 0; i < n_items; ++i)
1674 allocations[i].x += allocation->x;
1675 allocations[i].y += allocation->y;
1677 if (shadow_type != GTK_SHADOW_NONE)
1679 allocations[i].x += widget->style->xthickness;
1680 allocations[i].y += widget->style->ythickness;
1686 arrow_allocation.x += allocation->x;
1687 arrow_allocation.y += allocation->y;
1689 if (shadow_type != GTK_SHADOW_NONE)
1691 arrow_allocation.x += widget->style->xthickness;
1692 arrow_allocation.y += widget->style->ythickness;
1696 item_area.x += allocation->x;
1697 item_area.y += allocation->y;
1698 if (shadow_type != GTK_SHADOW_NONE)
1700 item_area.x += widget->style->xthickness;
1701 item_area.y += widget->style->ythickness;
1704 /* did anything change? */
1705 for (list = priv->content, i = 0; list != NULL; list = list->next, i++)
1707 ToolbarContent *content = list->data;
1709 if (toolbar_content_get_state (content) == NORMAL &&
1710 new_states[i] != NORMAL)
1712 /* an item disappeared and we didn't change size, so begin sliding */
1713 if (!size_changed && priv->api_mode == NEW_API)
1714 gtk_toolbar_begin_sliding (toolbar);
1718 /* finally allocate the items */
1719 if (priv->is_sliding)
1721 for (list = priv->content, i = 0; list != NULL; list = list->next, i++)
1723 ToolbarContent *content = list->data;
1725 toolbar_content_set_goal_allocation (content, &(allocations[i]));
1729 elapsed = g_timer_elapsed (priv->timer, NULL);
1730 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1732 ToolbarContent *content = list->data;
1734 if (new_states[i] == OVERFLOWN ||
1735 new_states[i] == NORMAL)
1737 GtkAllocation alloc;
1738 GtkAllocation start_allocation = { 0, };
1739 GtkAllocation goal_allocation;
1741 if (priv->is_sliding)
1743 toolbar_content_get_start_allocation (content, &start_allocation);
1744 toolbar_content_get_goal_allocation (content, &goal_allocation);
1746 compute_intermediate_allocation (toolbar,
1751 priv->need_sync = TRUE;
1755 alloc = allocations[i];
1758 if (alloc.width <= 0 || alloc.height <= 0)
1760 toolbar_content_set_child_visible (content, toolbar, FALSE);
1764 if (!rect_within (&alloc, &item_area))
1766 toolbar_content_set_child_visible (content, toolbar, FALSE);
1767 toolbar_content_size_allocate (content, &alloc);
1771 toolbar_content_set_child_visible (content, toolbar, TRUE);
1772 toolbar_content_size_allocate (content, &alloc);
1778 toolbar_content_set_child_visible (content, toolbar, FALSE);
1781 toolbar_content_set_state (content, new_states[i]);
1784 if (priv->menu && priv->need_rebuild)
1785 rebuild_menu (toolbar);
1789 gtk_widget_size_allocate (GTK_WIDGET (priv->arrow_button),
1791 gtk_widget_show (GTK_WIDGET (priv->arrow_button));
1795 gtk_widget_hide (GTK_WIDGET (priv->arrow_button));
1797 if (priv->menu && GTK_WIDGET_VISIBLE (priv->menu))
1798 gtk_menu_shell_deactivate (GTK_MENU_SHELL (priv->menu));
1801 g_free (allocations);
1802 g_free (new_states);
1806 gtk_toolbar_update_button_relief (GtkToolbar *toolbar)
1808 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1809 GtkReliefStyle relief;
1811 relief = get_button_relief (toolbar);
1813 if (relief != gtk_button_get_relief (GTK_BUTTON (priv->arrow_button)))
1815 gtk_toolbar_reconfigured (toolbar);
1817 gtk_button_set_relief (GTK_BUTTON (priv->arrow_button), relief);
1822 gtk_toolbar_style_set (GtkWidget *widget,
1823 GtkStyle *prev_style)
1825 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
1827 priv->max_homogeneous_pixels = -1;
1829 if (GTK_WIDGET_REALIZED (widget))
1830 gtk_style_set_background (widget->style, widget->window, widget->state);
1833 gtk_toolbar_update_button_relief (GTK_TOOLBAR (widget));
1837 gtk_toolbar_list_children_in_focus_order (GtkToolbar *toolbar,
1838 GtkDirectionType dir)
1840 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1841 GList *result = NULL;
1845 /* generate list of children in reverse logical order */
1847 for (list = priv->content; list != NULL; list = list->next)
1849 ToolbarContent *content = list->data;
1852 widget = toolbar_content_get_widget (content);
1855 result = g_list_prepend (result, widget);
1858 result = g_list_prepend (result, priv->arrow_button);
1860 rtl = (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL);
1862 /* move in logical order when
1864 * - dir is TAB_FORWARD
1866 * - in RTL mode and moving left or up
1868 * - in LTR mode and moving right or down
1870 if (dir == GTK_DIR_TAB_FORWARD ||
1871 (rtl && (dir == GTK_DIR_UP || dir == GTK_DIR_LEFT)) ||
1872 (!rtl && (dir == GTK_DIR_DOWN || dir == GTK_DIR_RIGHT)))
1874 result = g_list_reverse (result);
1881 gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
1882 gboolean focus_home)
1884 GList *children, *list;
1885 GtkDirectionType dir = focus_home? GTK_DIR_RIGHT : GTK_DIR_LEFT;
1887 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1889 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1891 children = g_list_reverse (children);
1893 dir = (dir == GTK_DIR_RIGHT)? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1896 for (list = children; list != NULL; list = list->next)
1898 GtkWidget *child = list->data;
1900 if (GTK_CONTAINER (toolbar)->focus_child == child)
1903 if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1907 g_list_free (children);
1912 /* Keybinding handler. This function is called when the user presses
1913 * Ctrl TAB or an arrow key.
1916 gtk_toolbar_move_focus (GtkWidget *widget,
1917 GtkDirectionType dir)
1919 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1920 GtkContainer *container = GTK_CONTAINER (toolbar);
1922 gboolean try_focus = FALSE;
1925 g_printerr ("%s (dir = %d)\n", G_STRFUNC, dir);
1927 if (container->focus_child &&
1928 gtk_widget_child_focus (container->focus_child, dir))
1933 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1935 for (list = children; list != NULL; list = list->next)
1937 GtkWidget *child = list->data;
1939 if (try_focus && GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1942 if (child == GTK_CONTAINER (toolbar)->focus_child)
1946 g_list_free (children);
1949 /* The focus handler for the toolbar. It called when the user presses
1950 * TAB or otherwise tries to focus the toolbar.
1953 gtk_toolbar_focus (GtkWidget *widget,
1954 GtkDirectionType dir)
1956 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1957 GList *children, *list;
1958 gboolean result = FALSE;
1960 /* if focus is already somewhere inside the toolbar then return FALSE.
1961 * The only way focus can stay inside the toolbar is when the user presses
1962 * arrow keys or Ctrl TAB (both of which are handled by the
1963 * gtk_toolbar_move_focus() keybinding function.
1965 if (GTK_CONTAINER (widget)->focus_child)
1968 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1970 for (list = children; list != NULL; list = list->next)
1972 GtkWidget *child = list->data;
1974 if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1981 g_list_free (children);
1986 static GtkSettings *
1987 toolbar_get_settings (GtkToolbar *toolbar)
1989 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1990 return priv->settings;
1994 style_change_notify (GtkToolbar *toolbar)
1996 if (!toolbar->style_set)
1998 /* pretend it was set, then unset, thus reverting to new default */
1999 toolbar->style_set = TRUE;
2000 gtk_toolbar_unset_style (toolbar);
2005 icon_size_change_notify (GtkToolbar *toolbar)
2007 if (!toolbar->icon_size_set)
2009 /* pretend it was set, then unset, thus reverting to new default */
2010 toolbar->icon_size_set = TRUE;
2011 gtk_toolbar_unset_icon_size (toolbar);
2016 animation_change_notify (GtkToolbar *toolbar)
2018 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2019 GtkSettings *settings = toolbar_get_settings (toolbar);
2023 g_object_get (settings,
2024 "gtk-enable-animations", &animation,
2027 animation = DEFAULT_ANIMATION_STATE;
2029 priv->animation = animation;
2033 settings_change_notify (GtkSettings *settings,
2034 const GParamSpec *pspec,
2035 GtkToolbar *toolbar)
2037 if (! strcmp (pspec->name, "gtk-toolbar-style"))
2038 style_change_notify (toolbar);
2039 else if (! strcmp (pspec->name, "gtk-toolbar-icon-size"))
2040 icon_size_change_notify (toolbar);
2041 else if (! strcmp (pspec->name, "gtk-enable-animations"))
2042 animation_change_notify (toolbar);
2046 gtk_toolbar_screen_changed (GtkWidget *widget,
2047 GdkScreen *previous_screen)
2049 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
2050 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
2051 GtkSettings *old_settings = toolbar_get_settings (toolbar);
2052 GtkSettings *settings;
2054 if (gtk_widget_has_screen (GTK_WIDGET (toolbar)))
2055 settings = gtk_widget_get_settings (GTK_WIDGET (toolbar));
2059 if (settings == old_settings)
2064 g_signal_handler_disconnect (old_settings, priv->settings_connection);
2066 g_object_unref (old_settings);
2071 priv->settings_connection =
2072 g_signal_connect (settings, "notify",
2073 G_CALLBACK (settings_change_notify),
2076 priv->settings = g_object_ref (settings);
2079 priv->settings = NULL;
2081 style_change_notify (toolbar);
2082 icon_size_change_notify (toolbar);
2083 animation_change_notify (toolbar);
2087 find_drop_index (GtkToolbar *toolbar,
2091 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2092 GList *interesting_content;
2094 GtkOrientation orientation;
2095 GtkTextDirection direction;
2096 gint best_distance = G_MAXINT;
2100 ToolbarContent *best_content;
2101 GtkAllocation allocation;
2103 /* list items we care about wrt. drag and drop */
2104 interesting_content = NULL;
2105 for (list = priv->content; list != NULL; list = list->next)
2107 ToolbarContent *content = list->data;
2109 if (toolbar_content_get_state (content) == NORMAL)
2110 interesting_content = g_list_prepend (interesting_content, content);
2112 interesting_content = g_list_reverse (interesting_content);
2114 if (!interesting_content)
2117 orientation = toolbar->orientation;
2118 direction = gtk_widget_get_direction (GTK_WIDGET (toolbar));
2120 /* distance to first interesting item */
2121 best_content = interesting_content->data;
2122 toolbar_content_get_allocation (best_content, &allocation);
2124 if (orientation == GTK_ORIENTATION_HORIZONTAL)
2128 if (direction == GTK_TEXT_DIR_LTR)
2131 pos = allocation.x + allocation.width;
2139 best_content = NULL;
2140 best_distance = ABS (pos - cursor);
2142 /* distance to far end of each item */
2143 for (list = interesting_content; list != NULL; list = list->next)
2145 ToolbarContent *content = list->data;
2147 toolbar_content_get_allocation (content, &allocation);
2149 if (orientation == GTK_ORIENTATION_HORIZONTAL)
2151 if (direction == GTK_TEXT_DIR_LTR)
2152 pos = allocation.x + allocation.width;
2158 pos = allocation.y + allocation.height;
2161 distance = ABS (pos - cursor);
2163 if (distance < best_distance)
2165 best_distance = distance;
2166 best_content = content;
2170 g_list_free (interesting_content);
2175 return g_list_index (priv->content, best_content) + 1;
2179 reset_all_placeholders (GtkToolbar *toolbar)
2181 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2184 for (list = priv->content; list != NULL; list = list->next)
2186 ToolbarContent *content = list->data;
2187 if (toolbar_content_is_placeholder (content))
2188 toolbar_content_set_disappearing (content, TRUE);
2193 physical_to_logical (GtkToolbar *toolbar,
2196 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2200 g_assert (physical >= 0);
2203 for (list = priv->content; list && physical > 0; list = list->next)
2205 ToolbarContent *content = list->data;
2207 if (!toolbar_content_is_placeholder (content))
2212 g_assert (physical == 0);
2218 logical_to_physical (GtkToolbar *toolbar,
2221 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2225 g_assert (logical >= 0);
2228 for (list = priv->content; list; list = list->next)
2230 ToolbarContent *content = list->data;
2232 if (!toolbar_content_is_placeholder (content))
2242 g_assert (logical == 0);
2248 * gtk_toolbar_set_drop_highlight_item:
2249 * @toolbar: a #GtkToolbar
2250 * @tool_item: a #GtkToolItem, or %NULL to turn of highlighting
2251 * @index_: a position on @toolbar
2253 * Highlights @toolbar to give an idea of what it would look like
2254 * if @item was added to @toolbar at the position indicated by @index_.
2255 * If @item is %NULL, highlighting is turned off. In that case @index_
2258 * The @tool_item passed to this function must not be part of any widget
2259 * hierarchy. When an item is set as drop highlight item it can not
2260 * added to any widget hierarchy or used as highlight item for another
2266 gtk_toolbar_set_drop_highlight_item (GtkToolbar *toolbar,
2267 GtkToolItem *tool_item,
2270 ToolbarContent *content;
2271 GtkToolbarPrivate *priv;
2273 GtkRequisition requisition;
2274 GtkRequisition old_requisition;
2275 gboolean restart_sliding;
2277 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2278 g_return_if_fail (tool_item == NULL || GTK_IS_TOOL_ITEM (tool_item));
2280 gtk_toolbar_check_new_api (toolbar);
2282 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2286 if (priv->highlight_tool_item)
2288 gtk_widget_unparent (GTK_WIDGET (priv->highlight_tool_item));
2289 g_object_unref (priv->highlight_tool_item);
2290 priv->highlight_tool_item = NULL;
2293 reset_all_placeholders (toolbar);
2294 gtk_toolbar_begin_sliding (toolbar);
2298 n_items = gtk_toolbar_get_n_items (toolbar);
2299 if (index_ < 0 || index_ > n_items)
2302 if (tool_item != priv->highlight_tool_item)
2304 if (priv->highlight_tool_item)
2305 g_object_unref (priv->highlight_tool_item);
2307 g_object_ref_sink (tool_item);
2309 priv->highlight_tool_item = tool_item;
2311 gtk_widget_set_parent (GTK_WIDGET (priv->highlight_tool_item),
2312 GTK_WIDGET (toolbar));
2315 index_ = logical_to_physical (toolbar, index_);
2317 content = g_list_nth_data (priv->content, index_);
2321 ToolbarContent *prev_content;
2323 prev_content = g_list_nth_data (priv->content, index_ - 1);
2325 if (prev_content && toolbar_content_is_placeholder (prev_content))
2326 content = prev_content;
2329 if (!content || !toolbar_content_is_placeholder (content))
2331 GtkWidget *placeholder;
2333 placeholder = GTK_WIDGET (gtk_separator_tool_item_new ());
2335 content = toolbar_content_new_tool_item (toolbar,
2336 GTK_TOOL_ITEM (placeholder),
2338 gtk_widget_show (placeholder);
2342 g_assert (toolbar_content_is_placeholder (content));
2344 gtk_widget_size_request (GTK_WIDGET (priv->highlight_tool_item),
2347 toolbar_content_set_expand (content, gtk_tool_item_get_expand (tool_item));
2349 restart_sliding = FALSE;
2350 toolbar_content_size_request (content, toolbar, &old_requisition);
2351 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
2353 requisition.height = -1;
2354 if (requisition.width != old_requisition.width)
2355 restart_sliding = TRUE;
2359 requisition.width = -1;
2360 if (requisition.height != old_requisition.height)
2361 restart_sliding = TRUE;
2364 if (toolbar_content_disappearing (content))
2365 restart_sliding = TRUE;
2367 reset_all_placeholders (toolbar);
2368 toolbar_content_set_disappearing (content, FALSE);
2370 toolbar_content_set_size_request (content,
2371 requisition.width, requisition.height);
2373 if (restart_sliding)
2374 gtk_toolbar_begin_sliding (toolbar);
2378 gtk_toolbar_get_child_property (GtkContainer *container,
2384 GtkToolItem *item = GTK_TOOL_ITEM (child);
2386 switch (property_id)
2388 case CHILD_PROP_HOMOGENEOUS:
2389 g_value_set_boolean (value, gtk_tool_item_get_homogeneous (item));
2392 case CHILD_PROP_EXPAND:
2393 g_value_set_boolean (value, gtk_tool_item_get_expand (item));
2397 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2403 gtk_toolbar_set_child_property (GtkContainer *container,
2406 const GValue *value,
2409 switch (property_id)
2411 case CHILD_PROP_HOMOGENEOUS:
2412 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
2415 case CHILD_PROP_EXPAND:
2416 gtk_tool_item_set_expand (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
2420 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2426 gtk_toolbar_show_all (GtkWidget *widget)
2428 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
2431 for (list = priv->content; list != NULL; list = list->next)
2433 ToolbarContent *content = list->data;
2435 toolbar_content_show_all (content);
2438 gtk_widget_show (widget);
2442 gtk_toolbar_hide_all (GtkWidget *widget)
2444 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
2447 for (list = priv->content; list != NULL; list = list->next)
2449 ToolbarContent *content = list->data;
2451 toolbar_content_hide_all (content);
2454 gtk_widget_hide (widget);
2458 gtk_toolbar_add (GtkContainer *container,
2461 GtkToolbar *toolbar;
2463 g_return_if_fail (GTK_IS_TOOLBAR (container));
2464 g_return_if_fail (widget != NULL);
2466 toolbar = GTK_TOOLBAR (container);
2468 if (GTK_IS_TOOL_ITEM (widget))
2469 gtk_toolbar_insert (toolbar, GTK_TOOL_ITEM (widget), -1);
2471 gtk_toolbar_append_widget (toolbar, widget, NULL, NULL);
2475 gtk_toolbar_remove (GtkContainer *container,
2478 GtkToolbar *toolbar;
2479 GtkToolbarPrivate *priv;
2480 ToolbarContent *content_to_remove;
2483 g_return_if_fail (GTK_IS_TOOLBAR (container));
2484 g_return_if_fail (GTK_IS_WIDGET (widget));
2486 toolbar = GTK_TOOLBAR (container);
2487 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2489 content_to_remove = NULL;
2490 for (list = priv->content; list != NULL; list = list->next)
2492 ToolbarContent *content = list->data;
2495 child = toolbar_content_get_widget (content);
2496 if (child && child == widget)
2498 content_to_remove = content;
2503 g_return_if_fail (content_to_remove != NULL);
2505 toolbar_content_remove (content_to_remove, toolbar);
2506 toolbar_content_free (content_to_remove);
2510 gtk_toolbar_forall (GtkContainer *container,
2511 gboolean include_internals,
2512 GtkCallback callback,
2513 gpointer callback_data)
2515 GtkToolbar *toolbar = GTK_TOOLBAR (container);
2516 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2519 g_return_if_fail (callback != NULL);
2521 list = priv->content;
2524 ToolbarContent *content = list->data;
2525 GList *next = list->next;
2527 if (include_internals || !toolbar_content_is_placeholder (content))
2529 GtkWidget *child = toolbar_content_get_widget (content);
2532 (*callback) (child, callback_data);
2538 if (include_internals)
2539 (* callback) (priv->arrow_button, callback_data);
2543 gtk_toolbar_child_type (GtkContainer *container)
2545 return GTK_TYPE_TOOL_ITEM;
2549 gtk_toolbar_reconfigured (GtkToolbar *toolbar)
2551 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2554 list = priv->content;
2557 ToolbarContent *content = list->data;
2558 GList *next = list->next;
2560 toolbar_content_toolbar_reconfigured (content, toolbar);
2567 gtk_toolbar_orientation_changed (GtkToolbar *toolbar,
2568 GtkOrientation orientation)
2570 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2571 if (toolbar->orientation != orientation)
2573 toolbar->orientation = orientation;
2575 if (orientation == GTK_ORIENTATION_HORIZONTAL)
2576 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_DOWN, GTK_SHADOW_NONE);
2578 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
2580 gtk_toolbar_reconfigured (toolbar);
2582 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2583 g_object_notify (G_OBJECT (toolbar), "orientation");
2588 gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
2589 GtkToolbarStyle style)
2591 if (toolbar->style != style)
2593 toolbar->style = style;
2595 gtk_toolbar_reconfigured (toolbar);
2597 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2598 g_object_notify (G_OBJECT (toolbar), "toolbar-style");
2603 menu_position_func (GtkMenu *menu,
2609 GtkToolbar *toolbar = GTK_TOOLBAR (user_data);
2610 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2612 GtkRequisition menu_req;
2613 GdkRectangle monitor;
2617 gtk_widget_size_request (priv->arrow_button, &req);
2618 gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
2620 screen = gtk_widget_get_screen (GTK_WIDGET (menu));
2621 monitor_num = gdk_screen_get_monitor_at_window (screen, priv->arrow_button->window);
2622 if (monitor_num < 0)
2624 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
2626 gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y);
2627 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
2629 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2630 *x += priv->arrow_button->allocation.width - req.width;
2632 *x += req.width - menu_req.width;
2634 if ((*y + priv->arrow_button->allocation.height + menu_req.height) <= monitor.y + monitor.height)
2635 *y += priv->arrow_button->allocation.height;
2636 else if ((*y - menu_req.height) >= monitor.y)
2637 *y -= menu_req.height;
2638 else if (monitor.y + monitor.height - (*y + priv->arrow_button->allocation.height) > *y)
2639 *y += priv->arrow_button->allocation.height;
2641 *y -= menu_req.height;
2645 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2646 *x += priv->arrow_button->allocation.width;
2648 *x -= menu_req.width;
2650 if (*y + menu_req.height > monitor.y + monitor.height &&
2651 *y + priv->arrow_button->allocation.height - monitor.y > monitor.y + monitor.height - *y)
2652 *y += priv->arrow_button->allocation.height - menu_req.height;
2659 show_menu (GtkToolbar *toolbar,
2660 GdkEventButton *event)
2662 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2664 rebuild_menu (toolbar);
2666 gtk_widget_show_all (GTK_WIDGET (priv->menu));
2668 gtk_menu_popup (priv->menu, NULL, NULL,
2669 menu_position_func, toolbar,
2670 event? event->button : 0,
2671 event? event->time : gtk_get_current_event_time());
2675 gtk_toolbar_arrow_button_clicked (GtkWidget *button,
2676 GtkToolbar *toolbar)
2678 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2680 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->arrow_button)) &&
2681 (!priv->menu || !GTK_WIDGET_VISIBLE (priv->menu)))
2683 /* We only get here when the button is clicked with the keyboard,
2684 * because mouse button presses result in the menu being shown so
2685 * that priv->menu would be non-NULL and visible.
2687 show_menu (toolbar, NULL);
2688 gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menu), FALSE);
2693 gtk_toolbar_arrow_button_press (GtkWidget *button,
2694 GdkEventButton *event,
2695 GtkToolbar *toolbar)
2697 show_menu (toolbar, event);
2698 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2704 gtk_toolbar_button_press (GtkWidget *toolbar,
2705 GdkEventButton *event)
2707 if (event->button == 3)
2709 gboolean return_value;
2711 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2712 (int)event->x_root, (int)event->y_root, event->button,
2715 return return_value;
2722 gtk_toolbar_popup_menu (GtkWidget *toolbar)
2724 gboolean return_value;
2725 /* This function is the handler for the "popup menu" keybinding,
2726 * ie., it is called when the user presses Shift F10
2728 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2729 -1, -1, -1, &return_value);
2731 return return_value;
2737 * Creates a new toolbar.
2739 * Return Value: the newly-created toolbar.
2742 gtk_toolbar_new (void)
2744 GtkToolbar *toolbar;
2746 toolbar = g_object_new (GTK_TYPE_TOOLBAR, NULL);
2748 return GTK_WIDGET (toolbar);
2752 * gtk_toolbar_insert:
2753 * @toolbar: a #GtkToolbar
2754 * @item: a #GtkToolItem
2755 * @pos: the position of the new item
2757 * Insert a #GtkToolItem into the toolbar at position @pos. If @pos is
2758 * 0 the item is prepended to the start of the toolbar. If @pos is
2759 * negative, the item is appended to the end of the toolbar.
2764 gtk_toolbar_insert (GtkToolbar *toolbar,
2768 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2769 g_return_if_fail (GTK_IS_TOOL_ITEM (item));
2771 if (!gtk_toolbar_check_new_api (toolbar))
2775 pos = logical_to_physical (toolbar, pos);
2777 toolbar_content_new_tool_item (toolbar, item, FALSE, pos);
2781 * gtk_toolbar_get_item_index:
2782 * @toolbar: a #GtkToolbar
2783 * @item: a #GtkToolItem that is a child of @toolbar
2785 * Returns the position of @item on the toolbar, starting from 0.
2786 * It is an error if @item is not a child of the toolbar.
2788 * Return value: the position of item on the toolbar.
2793 gtk_toolbar_get_item_index (GtkToolbar *toolbar,
2796 GtkToolbarPrivate *priv;
2800 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2801 g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1);
2802 g_return_val_if_fail (GTK_WIDGET (item)->parent == GTK_WIDGET (toolbar), -1);
2804 if (!gtk_toolbar_check_new_api (toolbar))
2807 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2810 for (list = priv->content; list != NULL; list = list->next)
2812 ToolbarContent *content = list->data;
2815 widget = toolbar_content_get_widget (content);
2817 if (item == GTK_TOOL_ITEM (widget))
2823 return physical_to_logical (toolbar, n);
2827 * gtk_toolbar_set_orientation:
2828 * @toolbar: a #GtkToolbar.
2829 * @orientation: a new #GtkOrientation.
2831 * Sets whether a toolbar should appear horizontally or vertically.
2834 gtk_toolbar_set_orientation (GtkToolbar *toolbar,
2835 GtkOrientation orientation)
2837 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2839 g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0, orientation);
2843 * gtk_toolbar_get_orientation:
2844 * @toolbar: a #GtkToolbar
2846 * Retrieves the current orientation of the toolbar. See
2847 * gtk_toolbar_set_orientation().
2849 * Return value: the orientation
2852 gtk_toolbar_get_orientation (GtkToolbar *toolbar)
2854 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
2856 return toolbar->orientation;
2860 * gtk_toolbar_set_style:
2861 * @toolbar: a #GtkToolbar.
2862 * @style: the new style for @toolbar.
2864 * Alters the view of @toolbar to display either icons only, text only, or both.
2867 gtk_toolbar_set_style (GtkToolbar *toolbar,
2868 GtkToolbarStyle style)
2870 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2872 toolbar->style_set = TRUE;
2873 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2877 * gtk_toolbar_get_style:
2878 * @toolbar: a #GtkToolbar
2880 * Retrieves whether the toolbar has text, icons, or both . See
2881 * gtk_toolbar_set_style().
2883 * Return value: the current style of @toolbar
2886 gtk_toolbar_get_style (GtkToolbar *toolbar)
2888 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_TOOLBAR_STYLE);
2890 return toolbar->style;
2894 * gtk_toolbar_unset_style:
2895 * @toolbar: a #GtkToolbar
2897 * Unsets a toolbar style set with gtk_toolbar_set_style(), so that
2898 * user preferences will be used to determine the toolbar style.
2901 gtk_toolbar_unset_style (GtkToolbar *toolbar)
2903 GtkToolbarStyle style;
2905 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2907 if (toolbar->style_set)
2909 GtkSettings *settings = toolbar_get_settings (toolbar);
2912 g_object_get (settings,
2913 "gtk-toolbar-style", &style,
2916 style = DEFAULT_TOOLBAR_STYLE;
2918 if (style != toolbar->style)
2919 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2921 toolbar->style_set = FALSE;
2926 * gtk_toolbar_set_tooltips:
2927 * @toolbar: a #GtkToolbar.
2928 * @enable: set to %FALSE to disable the tooltips, or %TRUE to enable them.
2930 * Sets if the tooltips of a toolbar should be active or not.
2933 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
2936 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2939 gtk_tooltips_enable (toolbar->tooltips);
2941 gtk_tooltips_disable (toolbar->tooltips);
2943 g_object_notify (G_OBJECT (toolbar), "tooltips");
2947 * gtk_toolbar_get_tooltips:
2948 * @toolbar: a #GtkToolbar
2950 * Retrieves whether tooltips are enabled. See
2951 * gtk_toolbar_set_tooltips().
2953 * Return value: %TRUE if tooltips are enabled
2956 gtk_toolbar_get_tooltips (GtkToolbar *toolbar)
2958 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2960 return toolbar->tooltips->enabled;
2964 * gtk_toolbar_get_n_items:
2965 * @toolbar: a #GtkToolbar
2967 * Returns the number of items on the toolbar.
2969 * Return value: the number of items on the toolbar
2974 gtk_toolbar_get_n_items (GtkToolbar *toolbar)
2976 GtkToolbarPrivate *priv;
2978 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2980 if (!gtk_toolbar_check_new_api (toolbar))
2983 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2985 return physical_to_logical (toolbar, g_list_length (priv->content));
2989 * gtk_toolbar_get_nth_item:
2990 * @toolbar: a #GtkToolbar
2991 * @n: A position on the toolbar
2993 * Returns the @n<!-- -->'th item on @toolbar, or %NULL if the
2994 * toolbar does not contain an @n<!-- -->'th item.
2996 * Return value: The @n<!-- -->'th #GtkToolItem on @toolbar, or %NULL if there
2997 * isn't an @n<!-- -->'th item.
3002 gtk_toolbar_get_nth_item (GtkToolbar *toolbar,
3005 GtkToolbarPrivate *priv;
3006 ToolbarContent *content;
3009 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
3011 if (!gtk_toolbar_check_new_api (toolbar))
3014 n_items = gtk_toolbar_get_n_items (toolbar);
3016 if (n < 0 || n >= n_items)
3019 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3021 content = g_list_nth_data (priv->content, logical_to_physical (toolbar, n));
3024 g_assert (!toolbar_content_is_placeholder (content));
3026 return GTK_TOOL_ITEM (toolbar_content_get_widget (content));
3030 * gtk_toolbar_get_icon_size:
3031 * @toolbar: a #GtkToolbar
3033 * Retrieves the icon size for the toolbar. See gtk_toolbar_set_icon_size().
3035 * Return value: the current icon size for the icons on the toolbar.
3038 gtk_toolbar_get_icon_size (GtkToolbar *toolbar)
3040 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_ICON_SIZE);
3042 return toolbar->icon_size;
3046 * gtk_toolbar_get_relief_style:
3047 * @toolbar: a #GtkToolbar
3049 * Returns the relief style of buttons on @toolbar. See
3050 * gtk_button_set_relief().
3052 * Return value: The relief style of buttons on @toolbar.
3057 gtk_toolbar_get_relief_style (GtkToolbar *toolbar)
3059 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_RELIEF_NONE);
3061 return get_button_relief (toolbar);
3065 * gtk_toolbar_set_show_arrow:
3066 * @toolbar: a #GtkToolbar
3067 * @show_arrow: Whether to show an overflow menu
3069 * Sets whether to show an overflow menu when
3070 * @toolbar doesn't have room for all items on it. If %TRUE,
3071 * items that there are not room are available through an
3077 gtk_toolbar_set_show_arrow (GtkToolbar *toolbar,
3078 gboolean show_arrow)
3080 GtkToolbarPrivate *priv;
3082 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3084 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3085 show_arrow = show_arrow != FALSE;
3087 if (priv->show_arrow != show_arrow)
3089 priv->show_arrow = show_arrow;
3091 if (!priv->show_arrow)
3092 gtk_widget_hide (priv->arrow_button);
3094 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3095 g_object_notify (G_OBJECT (toolbar), "show-arrow");
3100 * gtk_toolbar_get_show_arrow:
3101 * @toolbar: a #GtkToolbar
3103 * Returns whether the toolbar has an overflow menu.
3104 * See gtk_toolbar_set_show_arrow().
3106 * Return value: %TRUE if the toolbar has an overflow menu.
3111 gtk_toolbar_get_show_arrow (GtkToolbar *toolbar)
3113 GtkToolbarPrivate *priv;
3115 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
3117 if (!gtk_toolbar_check_new_api (toolbar))
3120 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3122 return priv->show_arrow;
3126 * gtk_toolbar_get_drop_index:
3127 * @toolbar: a #GtkToolbar
3128 * @x: x coordinate of a point on the toolbar
3129 * @y: y coordinate of a point on the toolbar
3131 * Returns the position corresponding to the indicated point on
3132 * @toolbar. This is useful when dragging items to the toolbar:
3133 * this function returns the position a new item should be
3136 * @x and @y are in @toolbar coordinates.
3138 * Return value: The position corresponding to the point (@x, @y) on the toolbar.
3143 gtk_toolbar_get_drop_index (GtkToolbar *toolbar,
3147 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
3149 if (!gtk_toolbar_check_new_api (toolbar))
3152 return physical_to_logical (toolbar, find_drop_index (toolbar, x, y));
3156 gtk_toolbar_finalize (GObject *object)
3159 GtkToolbar *toolbar = GTK_TOOLBAR (object);
3160 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3162 if (toolbar->tooltips)
3163 g_object_unref (toolbar->tooltips);
3165 if (priv->arrow_button)
3166 gtk_widget_unparent (priv->arrow_button);
3168 for (list = priv->content; list != NULL; list = list->next)
3170 ToolbarContent *content = list->data;
3172 toolbar_content_free (content);
3175 g_list_free (priv->content);
3176 g_list_free (toolbar->children);
3178 g_timer_destroy (priv->timer);
3181 gtk_widget_destroy (GTK_WIDGET (priv->menu));
3184 g_source_remove (priv->idle_id);
3186 G_OBJECT_CLASS (gtk_toolbar_parent_class)->finalize (object);
3190 * gtk_toolbar_set_icon_size:
3191 * @toolbar: A #GtkToolbar
3192 * @icon_size: The #GtkIconSize that stock icons in the toolbar shall have.
3194 * This function sets the size of stock icons in the toolbar. You
3195 * can call it both before you add the icons and after they've been
3196 * added. The size you set will override user preferences for the default
3199 * This should only be used for special-purpose toolbars, normal
3200 * application toolbars should respect the user preferences for the
3204 gtk_toolbar_set_icon_size (GtkToolbar *toolbar,
3205 GtkIconSize icon_size)
3207 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3208 g_return_if_fail (icon_size != GTK_ICON_SIZE_INVALID);
3210 if (!toolbar->icon_size_set)
3212 toolbar->icon_size_set = TRUE;
3213 g_object_notify (G_OBJECT (toolbar), "icon-size-set");
3216 if (toolbar->icon_size == icon_size)
3219 toolbar->icon_size = icon_size;
3220 g_object_notify (G_OBJECT (toolbar), "icon-size");
3222 gtk_toolbar_reconfigured (toolbar);
3224 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3228 * gtk_toolbar_unset_icon_size:
3229 * @toolbar: a #GtkToolbar
3231 * Unsets toolbar icon size set with gtk_toolbar_set_icon_size(), so that
3232 * user preferences will be used to determine the icon size.
3235 gtk_toolbar_unset_icon_size (GtkToolbar *toolbar)
3239 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3241 if (toolbar->icon_size_set)
3243 GtkSettings *settings = toolbar_get_settings (toolbar);
3247 g_object_get (settings,
3248 "gtk-toolbar-icon-size", &size,
3252 size = DEFAULT_ICON_SIZE;
3254 if (size != toolbar->icon_size)
3256 gtk_toolbar_set_icon_size (toolbar, size);
3257 g_object_notify (G_OBJECT (toolbar), "icon-size");
3260 toolbar->icon_size_set = FALSE;
3261 g_object_notify (G_OBJECT (toolbar), "icon-size-set");
3270 * gtk_toolbar_append_item:
3271 * @toolbar: a #GtkToolbar.
3272 * @text: give your toolbar button a label.
3273 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3274 * @tooltip_private_text: use with #GtkTipsQuery.
3275 * @icon: a #GtkWidget that should be used as the button's icon.
3276 * @callback: the function to be executed when the button is pressed.
3277 * @user_data: a pointer to any data you wish to be passed to the callback.
3279 * Inserts a new item into the toolbar. You must specify the position
3280 * in the toolbar where it will be inserted.
3282 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3283 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3285 * Return value: the new toolbar item as a #GtkWidget.
3288 gtk_toolbar_append_item (GtkToolbar *toolbar,
3290 const char *tooltip_text,
3291 const char *tooltip_private_text,
3293 GtkSignalFunc callback,
3296 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3298 tooltip_text, tooltip_private_text,
3299 icon, callback, user_data,
3300 toolbar->num_children);
3304 * gtk_toolbar_prepend_item:
3305 * @toolbar: a #GtkToolbar.
3306 * @text: give your toolbar button a label.
3307 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3308 * @tooltip_private_text: use with #GtkTipsQuery.
3309 * @icon: a #GtkWidget that should be used as the button's icon.
3310 * @callback: the function to be executed when the button is pressed.
3311 * @user_data: a pointer to any data you wish to be passed to the callback.
3313 * Adds a new button to the beginning (top or left edges) of the given toolbar.
3315 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3316 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3318 * Return value: the new toolbar item as a #GtkWidget.
3321 gtk_toolbar_prepend_item (GtkToolbar *toolbar,
3323 const char *tooltip_text,
3324 const char *tooltip_private_text,
3326 GtkSignalFunc callback,
3329 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3331 tooltip_text, tooltip_private_text,
3332 icon, callback, user_data,
3337 * gtk_toolbar_insert_item:
3338 * @toolbar: a #GtkToolbar.
3339 * @text: give your toolbar button a label.
3340 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3341 * @tooltip_private_text: use with #GtkTipsQuery.
3342 * @icon: a #GtkWidget that should be used as the button's icon.
3343 * @callback: the function to be executed when the button is pressed.
3344 * @user_data: a pointer to any data you wish to be passed to the callback.
3345 * @position: the number of widgets to insert this item after.
3347 * Inserts a new item into the toolbar. You must specify the position in the
3348 * toolbar where it will be inserted.
3350 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3351 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3353 * Return value: the new toolbar item as a #GtkWidget.
3356 gtk_toolbar_insert_item (GtkToolbar *toolbar,
3358 const char *tooltip_text,
3359 const char *tooltip_private_text,
3361 GtkSignalFunc callback,
3365 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3367 tooltip_text, tooltip_private_text,
3368 icon, callback, user_data,
3373 * gtk_toolbar_insert_stock:
3374 * @toolbar: A #GtkToolbar
3375 * @stock_id: The id of the stock item you want to insert
3376 * @tooltip_text: The text in the tooltip of the toolbar button
3377 * @tooltip_private_text: The private text of the tooltip
3378 * @callback: The callback called when the toolbar button is clicked.
3379 * @user_data: user data passed to callback
3380 * @position: The position the button shall be inserted at.
3381 * -1 means at the end.
3383 * Inserts a stock item at the specified position of the toolbar. If
3384 * @stock_id is not a known stock item ID, it's inserted verbatim,
3385 * except that underscores used to mark mnemonics are removed.
3387 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3388 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3390 * Returns: the inserted widget
3393 gtk_toolbar_insert_stock (GtkToolbar *toolbar,
3394 const gchar *stock_id,
3395 const char *tooltip_text,
3396 const char *tooltip_private_text,
3397 GtkSignalFunc callback,
3401 return internal_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3403 tooltip_text, tooltip_private_text,
3404 NULL, callback, user_data,
3409 * gtk_toolbar_append_space:
3410 * @toolbar: a #GtkToolbar.
3412 * Adds a new space to the end of the toolbar.
3415 gtk_toolbar_append_space (GtkToolbar *toolbar)
3417 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3421 toolbar->num_children);
3425 * gtk_toolbar_prepend_space:
3426 * @toolbar: a #GtkToolbar.
3428 * Adds a new space to the beginning of the toolbar.
3431 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
3433 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3441 * gtk_toolbar_insert_space:
3442 * @toolbar: a #GtkToolbar
3443 * @position: the number of widgets after which a space should be inserted.
3445 * Inserts a new space in the toolbar at the specified position.
3448 gtk_toolbar_insert_space (GtkToolbar *toolbar,
3451 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3459 * gtk_toolbar_remove_space:
3460 * @toolbar: a #GtkToolbar.
3461 * @position: the index of the space to remove.
3463 * Removes a space from the specified position.
3466 gtk_toolbar_remove_space (GtkToolbar *toolbar,
3469 GtkToolbarPrivate *priv;
3470 ToolbarContent *content;
3472 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3474 if (!gtk_toolbar_check_old_api (toolbar))
3477 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3479 content = g_list_nth_data (priv->content, position);
3483 g_warning ("Toolbar position %d doesn't exist", position);
3487 if (!toolbar_content_is_separator (content))
3489 g_warning ("Toolbar position %d is not a space", position);
3493 toolbar_content_remove (content, toolbar);
3494 toolbar_content_free (content);
3498 * gtk_toolbar_append_widget:
3499 * @toolbar: a #GtkToolbar.
3500 * @widget: a #GtkWidget to add to the toolbar.
3501 * @tooltip_text: the element's tooltip.
3502 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3504 * Adds a widget to the end of the given toolbar.
3507 gtk_toolbar_append_widget (GtkToolbar *toolbar,
3509 const gchar *tooltip_text,
3510 const gchar *tooltip_private_text)
3512 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3514 tooltip_text, tooltip_private_text,
3516 toolbar->num_children);
3520 * gtk_toolbar_prepend_widget:
3521 * @toolbar: a #GtkToolbar.
3522 * @widget: a #GtkWidget to add to the toolbar.
3523 * @tooltip_text: the element's tooltip.
3524 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3526 * Adds a widget to the beginning of the given toolbar.
3529 gtk_toolbar_prepend_widget (GtkToolbar *toolbar,
3531 const gchar *tooltip_text,
3532 const gchar *tooltip_private_text)
3534 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3536 tooltip_text, tooltip_private_text,
3542 * gtk_toolbar_insert_widget:
3543 * @toolbar: a #GtkToolbar.
3544 * @widget: a #GtkWidget to add to the toolbar.
3545 * @tooltip_text: the element's tooltip.
3546 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3547 * @position: the number of widgets to insert this widget after.
3549 * Inserts a widget in the toolbar at the given position.
3552 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
3554 const char *tooltip_text,
3555 const char *tooltip_private_text,
3558 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3560 tooltip_text, tooltip_private_text,
3566 * gtk_toolbar_append_element:
3567 * @toolbar: a #GtkToolbar.
3568 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
3569 * @widget: a #GtkWidget, or %NULL.
3570 * @text: the element's label.
3571 * @tooltip_text: the element's tooltip.
3572 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3573 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3574 * @callback: the function to be executed when the button is pressed.
3575 * @user_data: any data you wish to pass to the callback.
3577 * Adds a new element to the end of a toolbar.
3579 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3580 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3581 * the radio group for the new element. In all other cases, @widget must
3584 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3585 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3587 * Return value: the new toolbar element as a #GtkWidget.
3590 gtk_toolbar_append_element (GtkToolbar *toolbar,
3591 GtkToolbarChildType type,
3594 const char *tooltip_text,
3595 const char *tooltip_private_text,
3597 GtkSignalFunc callback,
3600 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3601 tooltip_text, tooltip_private_text,
3602 icon, callback, user_data,
3603 toolbar->num_children);
3607 * gtk_toolbar_prepend_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 beginning 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 the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3628 * Return value: the new toolbar element as a #GtkWidget.
3631 gtk_toolbar_prepend_element (GtkToolbar *toolbar,
3632 GtkToolbarChildType type,
3635 const char *tooltip_text,
3636 const char *tooltip_private_text,
3638 GtkSignalFunc callback,
3641 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3642 tooltip_text, tooltip_private_text,
3643 icon, callback, user_data, 0);
3647 * gtk_toolbar_insert_element:
3648 * @toolbar: a #GtkToolbar.
3649 * @type: a value of type #GtkToolbarChildType that determines what @widget
3651 * @widget: a #GtkWidget, or %NULL.
3652 * @text: the element's label.
3653 * @tooltip_text: the element's tooltip.
3654 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3655 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3656 * @callback: the function to be executed when the button is pressed.
3657 * @user_data: any data you wish to pass to the callback.
3658 * @position: the number of widgets to insert this element after.
3660 * Inserts a new element in the toolbar at the given position.
3662 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3663 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3664 * the radio group for the new element. In all other cases, @widget must
3667 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3668 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3670 * Return value: the new toolbar element as a #GtkWidget.
3673 gtk_toolbar_insert_element (GtkToolbar *toolbar,
3674 GtkToolbarChildType type,
3677 const char *tooltip_text,
3678 const char *tooltip_private_text,
3680 GtkSignalFunc callback,
3684 return internal_insert_element (toolbar, type, widget, text,
3685 tooltip_text, tooltip_private_text,
3686 icon, callback, user_data, position, FALSE);
3690 set_child_packing_and_visibility(GtkToolbar *toolbar,
3691 GtkToolbarChild *child)
3696 box = gtk_bin_get_child (GTK_BIN (child->widget));
3698 g_return_if_fail (GTK_IS_BOX (box));
3702 expand = (toolbar->style != GTK_TOOLBAR_BOTH);
3704 gtk_box_set_child_packing (GTK_BOX (box), child->label,
3705 expand, expand, 0, GTK_PACK_END);
3707 if (toolbar->style != GTK_TOOLBAR_ICONS)
3708 gtk_widget_show (child->label);
3710 gtk_widget_hide (child->label);
3715 expand = (toolbar->style != GTK_TOOLBAR_BOTH_HORIZ);
3717 gtk_box_set_child_packing (GTK_BOX (box), child->icon,
3718 expand, expand, 0, GTK_PACK_END);
3720 if (toolbar->style != GTK_TOOLBAR_TEXT)
3721 gtk_widget_show (child->icon);
3723 gtk_widget_hide (child->icon);
3728 internal_insert_element (GtkToolbar *toolbar,
3729 GtkToolbarChildType type,
3732 const char *tooltip_text,
3733 const char *tooltip_private_text,
3735 GtkSignalFunc callback,
3741 ToolbarContent *content;
3742 char *free_me = NULL;
3744 GtkWidget *child_widget;
3745 GtkWidget *child_label;
3746 GtkWidget *child_icon;
3748 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
3749 if (type == GTK_TOOLBAR_CHILD_WIDGET)
3750 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3751 else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON)
3752 g_return_val_if_fail (widget == NULL, NULL);
3753 if (GTK_IS_TOOL_ITEM (widget))
3754 g_warning (MIXED_API_WARNING);
3756 if (!gtk_toolbar_check_old_api (toolbar))
3759 child_widget = NULL;
3765 case GTK_TOOLBAR_CHILD_SPACE:
3768 case GTK_TOOLBAR_CHILD_WIDGET:
3769 child_widget = widget;
3772 case GTK_TOOLBAR_CHILD_BUTTON:
3773 case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
3774 case GTK_TOOLBAR_CHILD_RADIOBUTTON:
3775 if (type == GTK_TOOLBAR_CHILD_BUTTON)
3777 child_widget = gtk_button_new ();
3779 else if (type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
3781 child_widget = gtk_toggle_button_new ();
3782 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child_widget), FALSE);
3784 else /* type == GTK_TOOLBAR_CHILD_RADIOBUTTON */
3786 GSList *group = NULL;
3789 group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
3791 child_widget = gtk_radio_button_new (group);
3792 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child_widget), FALSE);
3795 gtk_button_set_relief (GTK_BUTTON (child_widget), get_button_relief (toolbar));
3796 gtk_button_set_focus_on_click (GTK_BUTTON (child_widget), FALSE);
3800 g_signal_connect (child_widget, "clicked",
3801 callback, user_data);
3804 if (toolbar->style == GTK_TOOLBAR_BOTH_HORIZ)
3805 box = gtk_hbox_new (FALSE, 0);
3807 box = gtk_vbox_new (FALSE, 0);
3809 gtk_container_add (GTK_CONTAINER (child_widget), box);
3810 gtk_widget_show (box);
3812 if (text && use_stock)
3814 GtkStockItem stock_item;
3815 if (gtk_stock_lookup (text, &stock_item))
3818 icon = gtk_image_new_from_stock (text, toolbar->icon_size);
3820 text = free_me = _gtk_toolbar_elide_underscores (stock_item.label);
3826 child_label = gtk_label_new (text);
3828 gtk_container_add (GTK_CONTAINER (box), child_label);
3833 child_icon = GTK_WIDGET (icon);
3834 gtk_container_add (GTK_CONTAINER (box), child_icon);
3837 gtk_widget_show (child_widget);
3841 g_assert_not_reached ();
3845 if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text)
3847 gtk_tooltips_set_tip (toolbar->tooltips, child_widget,
3848 tooltip_text, tooltip_private_text);
3851 content = toolbar_content_new_compatibility (toolbar, type, child_widget,
3852 child_icon, child_label, position);
3856 return child_widget;
3860 * ToolbarContent methods
3868 struct _ToolbarContent
3878 GtkAllocation start_allocation;
3879 GtkAllocation goal_allocation;
3880 guint is_placeholder : 1;
3881 guint disappearing : 1;
3882 TriState has_menu : 2;
3887 GtkToolbarChild child;
3888 GtkAllocation space_allocation;
3889 guint space_visible : 1;
3894 static ToolbarContent *
3895 toolbar_content_new_tool_item (GtkToolbar *toolbar,
3897 gboolean is_placeholder,
3900 ToolbarContent *content;
3901 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3903 content = g_new0 (ToolbarContent, 1);
3905 content->type = TOOL_ITEM;
3906 content->state = NOT_ALLOCATED;
3907 content->u.tool_item.item = item;
3908 content->u.tool_item.is_placeholder = is_placeholder;
3910 gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar));
3912 priv->content = g_list_insert (priv->content, content, pos);
3914 if (!is_placeholder)
3916 toolbar->num_children++;
3918 gtk_toolbar_stop_sliding (toolbar);
3921 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3922 priv->need_rebuild = TRUE;
3927 static ToolbarContent *
3928 toolbar_content_new_compatibility (GtkToolbar *toolbar,
3929 GtkToolbarChildType type,
3935 ToolbarContent *content;
3936 GtkToolbarChild *child;
3937 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3939 content = g_new0 (ToolbarContent, 1);
3941 child = &(content->u.compatibility.child);
3943 content->type = COMPATIBILITY;
3945 child->widget = widget;
3947 child->label = label;
3949 if (type != GTK_TOOLBAR_CHILD_SPACE)
3951 gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
3955 content->u.compatibility.space_visible = TRUE;
3956 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3959 if (type == GTK_TOOLBAR_CHILD_BUTTON ||
3960 type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
3961 type == GTK_TOOLBAR_CHILD_RADIOBUTTON)
3963 set_child_packing_and_visibility (toolbar, child);
3966 priv->content = g_list_insert (priv->content, content, pos);
3967 toolbar->children = g_list_insert (toolbar->children, child, pos);
3968 priv->need_rebuild = TRUE;
3970 toolbar->num_children++;
3976 toolbar_content_remove (ToolbarContent *content,
3977 GtkToolbar *toolbar)
3979 GtkToolbarChild *child;
3980 GtkToolbarPrivate *priv;
3982 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3984 switch (content->type)
3987 gtk_widget_unparent (GTK_WIDGET (content->u.tool_item.item));
3991 child = &(content->u.compatibility.child);
3993 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
3995 g_object_ref (child->widget);
3996 gtk_widget_unparent (child->widget);
3997 gtk_widget_destroy (child->widget);
3998 g_object_unref (child->widget);
4001 toolbar->children = g_list_remove (toolbar->children, child);
4005 priv->content = g_list_remove (priv->content, content);
4007 if (!toolbar_content_is_placeholder (content))
4008 toolbar->num_children--;
4010 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
4011 priv->need_rebuild = TRUE;
4015 toolbar_content_free (ToolbarContent *content)
4021 calculate_max_homogeneous_pixels (GtkWidget *widget)
4023 PangoContext *context;
4024 PangoFontMetrics *metrics;
4027 context = gtk_widget_get_pango_context (widget);
4028 metrics = pango_context_get_metrics (context,
4029 widget->style->font_desc,
4030 pango_context_get_language (context));
4031 char_width = pango_font_metrics_get_approximate_char_width (metrics);
4032 pango_font_metrics_unref (metrics);
4034 return PANGO_PIXELS (MAX_HOMOGENEOUS_N_CHARS * char_width);
4038 toolbar_content_expose (ToolbarContent *content,
4039 GtkContainer *container,
4040 GdkEventExpose *expose)
4042 GtkToolbar *toolbar = GTK_TOOLBAR (container);
4043 GtkToolbarChild *child;
4044 GtkWidget *widget = NULL; /* quiet gcc */
4046 switch (content->type)
4049 if (!content->u.tool_item.is_placeholder)
4050 widget = GTK_WIDGET (content->u.tool_item.item);
4054 child = &(content->u.compatibility.child);
4056 if (child->type == GTK_TOOLBAR_CHILD_SPACE)
4058 if (content->u.compatibility.space_visible &&
4059 get_space_style (toolbar) == GTK_TOOLBAR_SPACE_LINE)
4060 _gtk_toolbar_paint_space_line (GTK_WIDGET (toolbar), toolbar,
4062 &content->u.compatibility.space_allocation);
4066 widget = child->widget;
4071 gtk_container_propagate_expose (container, widget, expose);
4075 toolbar_content_visible (ToolbarContent *content,
4076 GtkToolbar *toolbar)
4080 switch (content->type)
4083 item = content->u.tool_item.item;
4085 if (!GTK_WIDGET_VISIBLE (item))
4088 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL &&
4089 gtk_tool_item_get_visible_horizontal (item))
4092 if ((toolbar->orientation == GTK_ORIENTATION_VERTICAL &&
4093 gtk_tool_item_get_visible_vertical (item)))
4100 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4101 return GTK_WIDGET_VISIBLE (content->u.compatibility.child.widget);
4107 g_assert_not_reached ();
4112 toolbar_content_size_request (ToolbarContent *content,
4113 GtkToolbar *toolbar,
4114 GtkRequisition *requisition)
4118 switch (content->type)
4121 gtk_widget_size_request (GTK_WIDGET (content->u.tool_item.item),
4123 if (content->u.tool_item.is_placeholder &&
4124 content->u.tool_item.disappearing)
4126 requisition->width = 0;
4127 requisition->height = 0;
4132 space_size = get_space_size (toolbar);
4134 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4136 gtk_widget_size_request (content->u.compatibility.child.widget,
4141 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
4143 requisition->width = space_size;
4144 requisition->height = 0;
4148 requisition->height = space_size;
4149 requisition->width = 0;
4158 toolbar_content_is_homogeneous (ToolbarContent *content,
4159 GtkToolbar *toolbar)
4161 gboolean result = FALSE; /* quiet gcc */
4162 GtkRequisition requisition;
4163 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4165 if (priv->max_homogeneous_pixels < 0)
4167 priv->max_homogeneous_pixels =
4168 calculate_max_homogeneous_pixels (GTK_WIDGET (toolbar));
4171 toolbar_content_size_request (content, toolbar, &requisition);
4173 if (requisition.width > priv->max_homogeneous_pixels)
4176 switch (content->type)
4179 result = gtk_tool_item_get_homogeneous (content->u.tool_item.item) &&
4180 !GTK_IS_SEPARATOR_TOOL_ITEM (content->u.tool_item.item);
4182 if (gtk_tool_item_get_is_important (content->u.tool_item.item) &&
4183 toolbar->style == GTK_TOOLBAR_BOTH_HORIZ &&
4184 toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
4191 if (content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_BUTTON ||
4192 content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4193 content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4208 toolbar_content_is_placeholder (ToolbarContent *content)
4210 if (content->type == TOOL_ITEM && content->u.tool_item.is_placeholder)
4217 toolbar_content_disappearing (ToolbarContent *content)
4219 if (content->type == TOOL_ITEM && content->u.tool_item.disappearing)
4226 toolbar_content_get_state (ToolbarContent *content)
4228 return content->state;
4232 toolbar_content_child_visible (ToolbarContent *content)
4234 switch (content->type)
4237 return GTK_WIDGET_CHILD_VISIBLE (content->u.tool_item.item);
4241 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4243 return GTK_WIDGET_CHILD_VISIBLE (content->u.compatibility.child.widget);
4247 return content->u.compatibility.space_visible;
4252 return FALSE; /* quiet gcc */
4256 toolbar_content_get_goal_allocation (ToolbarContent *content,
4257 GtkAllocation *allocation)
4259 switch (content->type)
4262 *allocation = content->u.tool_item.goal_allocation;
4266 /* Goal allocations are only relevant when we are
4267 * using the new API, so we should never get here
4269 g_assert_not_reached ();
4275 toolbar_content_get_allocation (ToolbarContent *content,
4276 GtkAllocation *allocation)
4278 GtkToolbarChild *child;
4280 switch (content->type)
4283 *allocation = GTK_WIDGET (content->u.tool_item.item)->allocation;
4287 child = &(content->u.compatibility.child);
4289 if (child->type == GTK_TOOLBAR_CHILD_SPACE)
4290 *allocation = content->u.compatibility.space_allocation;
4292 *allocation = child->widget->allocation;
4298 toolbar_content_set_start_allocation (ToolbarContent *content,
4299 GtkAllocation *allocation)
4301 switch (content->type)
4304 content->u.tool_item.start_allocation = *allocation;
4308 /* start_allocation is only relevant when using the new API */
4309 g_assert_not_reached ();
4315 toolbar_content_get_expand (ToolbarContent *content)
4317 if (content->type == TOOL_ITEM &&
4318 gtk_tool_item_get_expand (content->u.tool_item.item) &&
4319 !content->u.tool_item.disappearing)
4328 toolbar_content_set_goal_allocation (ToolbarContent *content,
4329 GtkAllocation *allocation)
4331 switch (content->type)
4334 content->u.tool_item.goal_allocation = *allocation;
4338 /* Only relevant when using new API */
4339 g_assert_not_reached ();
4345 toolbar_content_set_child_visible (ToolbarContent *content,
4346 GtkToolbar *toolbar,
4349 GtkToolbarChild *child;
4351 switch (content->type)
4354 gtk_widget_set_child_visible (GTK_WIDGET (content->u.tool_item.item),
4359 child = &(content->u.compatibility.child);
4361 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
4363 gtk_widget_set_child_visible (child->widget, visible);
4367 if (content->u.compatibility.space_visible != visible)
4369 content->u.compatibility.space_visible = visible;
4370 gtk_widget_queue_draw (GTK_WIDGET (toolbar));
4378 toolbar_content_get_start_allocation (ToolbarContent *content,
4379 GtkAllocation *start_allocation)
4381 switch (content->type)
4384 *start_allocation = content->u.tool_item.start_allocation;
4388 /* Only relevant for new API */
4389 g_assert_not_reached ();
4395 toolbar_content_size_allocate (ToolbarContent *content,
4396 GtkAllocation *allocation)
4398 switch (content->type)
4401 gtk_widget_size_allocate (GTK_WIDGET (content->u.tool_item.item),
4406 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4408 gtk_widget_size_allocate (content->u.compatibility.child.widget,
4413 content->u.compatibility.space_allocation = *allocation;
4420 toolbar_content_set_state (ToolbarContent *content,
4423 content->state = state;
4427 toolbar_content_get_widget (ToolbarContent *content)
4429 GtkToolbarChild *child;
4431 switch (content->type)
4434 return GTK_WIDGET (content->u.tool_item.item);
4438 child = &(content->u.compatibility.child);
4439 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
4440 return child->widget;
4450 toolbar_content_set_disappearing (ToolbarContent *content,
4451 gboolean disappearing)
4453 switch (content->type)
4456 content->u.tool_item.disappearing = disappearing;
4460 /* Only relevant for new API */
4461 g_assert_not_reached ();
4467 toolbar_content_set_size_request (ToolbarContent *content,
4471 switch (content->type)
4474 gtk_widget_set_size_request (GTK_WIDGET (content->u.tool_item.item),
4479 /* Setting size requests only happens with sliding,
4480 * so not relevant here
4482 g_assert_not_reached ();
4488 toolbar_child_reconfigure (GtkToolbar *toolbar,
4489 GtkToolbarChild *child)
4493 GtkToolbarStyle style;
4494 GtkIconSize icon_size;
4495 GtkReliefStyle relief;
4498 style = gtk_toolbar_get_style (toolbar);
4499 icon_size = gtk_toolbar_get_icon_size (toolbar);
4500 relief = gtk_toolbar_get_relief_style (toolbar);
4503 if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4504 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4505 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4507 box = gtk_bin_get_child (GTK_BIN (child->widget));
4509 if (style == GTK_TOOLBAR_BOTH && GTK_IS_HBOX (box))
4513 vbox = gtk_vbox_new (FALSE, 0);
4516 gtk_widget_reparent (child->label, vbox);
4518 gtk_widget_reparent (child->icon, vbox);
4520 gtk_widget_destroy (box);
4521 gtk_container_add (GTK_CONTAINER (child->widget), vbox);
4523 gtk_widget_show (vbox);
4525 else if (style == GTK_TOOLBAR_BOTH_HORIZ && GTK_IS_VBOX (box))
4529 hbox = gtk_hbox_new (FALSE, 0);
4532 gtk_widget_reparent (child->label, hbox);
4534 gtk_widget_reparent (child->icon, hbox);
4536 gtk_widget_destroy (box);
4537 gtk_container_add (GTK_CONTAINER (child->widget), hbox);
4539 gtk_widget_show (hbox);
4542 set_child_packing_and_visibility (toolbar, child);
4547 if ((child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4548 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
4549 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON) &&
4550 GTK_IS_IMAGE (child->icon))
4552 image = GTK_IMAGE (child->icon);
4553 if (gtk_image_get_storage_type (image) == GTK_IMAGE_STOCK)
4555 gtk_image_get_stock (image, &stock_id, NULL);
4556 stock_id = g_strdup (stock_id);
4557 gtk_image_set_from_stock (image,
4565 if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4566 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4567 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4569 gtk_button_set_relief (GTK_BUTTON (child->widget), relief);
4574 toolbar_content_toolbar_reconfigured (ToolbarContent *content,
4575 GtkToolbar *toolbar)
4577 switch (content->type)
4580 _gtk_tool_item_toolbar_reconfigured (content->u.tool_item.item);
4584 toolbar_child_reconfigure (toolbar, &(content->u.compatibility.child));
4590 toolbar_content_retrieve_menu_item (ToolbarContent *content)
4592 if (content->type == TOOL_ITEM)
4593 return gtk_tool_item_retrieve_proxy_menu_item (content->u.tool_item.item);
4595 /* FIXME - we might actually be able to do something meaningful here */
4600 toolbar_content_has_proxy_menu_item (ToolbarContent *content)
4602 if (content->type == TOOL_ITEM)
4604 GtkWidget *menu_item;
4606 if (content->u.tool_item.has_menu == YES)
4608 else if (content->u.tool_item.has_menu == NO)
4611 menu_item = toolbar_content_retrieve_menu_item (content);
4613 content->u.tool_item.has_menu = menu_item? YES : NO;
4615 return menu_item != NULL;
4624 toolbar_content_set_unknown_menu_status (ToolbarContent *content)
4626 if (content->type == TOOL_ITEM)
4627 content->u.tool_item.has_menu = UNKNOWN;
4631 toolbar_content_is_separator (ToolbarContent *content)
4633 GtkToolbarChild *child;
4635 switch (content->type)
4638 return GTK_IS_SEPARATOR_TOOL_ITEM (content->u.tool_item.item);
4642 child = &(content->u.compatibility.child);
4643 return (child->type == GTK_TOOLBAR_CHILD_SPACE);
4651 toolbar_content_set_expand (ToolbarContent *content,
4654 if (content->type == TOOL_ITEM)
4655 gtk_tool_item_set_expand (content->u.tool_item.item, expand);
4659 ignore_show_and_hide_all (ToolbarContent *content)
4661 if (content->type == COMPATIBILITY)
4663 GtkToolbarChildType type = content->u.compatibility.child.type;
4665 if (type == GTK_TOOLBAR_CHILD_BUTTON ||
4666 type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
4667 type == GTK_TOOLBAR_CHILD_RADIOBUTTON)
4677 toolbar_content_show_all (ToolbarContent *content)
4681 if (ignore_show_and_hide_all (content))
4684 widget = toolbar_content_get_widget (content);
4686 gtk_widget_show_all (widget);
4690 toolbar_content_hide_all (ToolbarContent *content)
4694 if (ignore_show_and_hide_all (content))
4697 widget = toolbar_content_get_widget (content);
4699 gtk_widget_hide_all (widget);
4706 get_space_size (GtkToolbar *toolbar)
4708 gint space_size = DEFAULT_SPACE_SIZE;
4712 gtk_widget_style_get (GTK_WIDGET (toolbar),
4713 "space-size", &space_size,
4720 static GtkToolbarSpaceStyle
4721 get_space_style (GtkToolbar *toolbar)
4723 GtkToolbarSpaceStyle space_style = DEFAULT_SPACE_STYLE;
4727 gtk_widget_style_get (GTK_WIDGET (toolbar),
4728 "space-style", &space_style,
4735 static GtkReliefStyle
4736 get_button_relief (GtkToolbar *toolbar)
4738 GtkReliefStyle button_relief = GTK_RELIEF_NORMAL;
4740 gtk_widget_ensure_style (GTK_WIDGET (toolbar));
4742 gtk_widget_style_get (GTK_WIDGET (toolbar),
4743 "button-relief", &button_relief,
4746 return button_relief;
4750 get_internal_padding (GtkToolbar *toolbar)
4754 gtk_widget_style_get (GTK_WIDGET (toolbar),
4755 "internal-padding", &ipadding,
4762 get_max_child_expand (GtkToolbar *toolbar)
4764 gint mexpand = G_MAXINT;
4766 gtk_widget_style_get (GTK_WIDGET (toolbar),
4767 "max-child-expand", &mexpand,
4772 static GtkShadowType
4773 get_shadow_type (GtkToolbar *toolbar)
4775 GtkShadowType shadow_type;
4777 gtk_widget_style_get (GTK_WIDGET (toolbar),
4778 "shadow-type", &shadow_type,
4788 gtk_toolbar_check_old_api (GtkToolbar *toolbar)
4790 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4792 if (priv->api_mode == NEW_API)
4794 g_warning (MIXED_API_WARNING);
4798 priv->api_mode = OLD_API;
4803 gtk_toolbar_check_new_api (GtkToolbar *toolbar)
4805 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4807 if (priv->api_mode == OLD_API)
4809 g_warning (MIXED_API_WARNING);
4813 priv->api_mode = NEW_API;
4817 /* GTK+ internal methods */
4820 _gtk_toolbar_get_default_space_size (void)
4822 return DEFAULT_SPACE_SIZE;
4826 _gtk_toolbar_paint_space_line (GtkWidget *widget,
4827 GtkToolbar *toolbar,
4829 GtkAllocation *allocation)
4831 const double start_fraction = (SPACE_LINE_START / SPACE_LINE_DIVISION);
4832 const double end_fraction = (SPACE_LINE_END / SPACE_LINE_DIVISION);
4834 GtkOrientation orientation;
4836 g_return_if_fail (GTK_IS_WIDGET (widget));
4838 orientation = toolbar? toolbar->orientation : GTK_ORIENTATION_HORIZONTAL;
4840 if (orientation == GTK_ORIENTATION_HORIZONTAL)
4842 gboolean wide_separators;
4843 gint separator_width;
4845 gtk_widget_style_get (widget,
4846 "wide-separators", &wide_separators,
4847 "separator-width", &separator_width,
4850 if (wide_separators)
4851 gtk_paint_box (widget->style, widget->window,
4852 GTK_WIDGET_STATE (widget), GTK_SHADOW_ETCHED_OUT,
4853 area, widget, "vseparator",
4854 allocation->x + (allocation->width - separator_width) / 2,
4855 allocation->y + allocation->height * start_fraction,
4857 allocation->height * (end_fraction - start_fraction));
4859 gtk_paint_vline (widget->style, widget->window,
4860 GTK_WIDGET_STATE (widget), area, widget,
4862 allocation->y + allocation->height * start_fraction,
4863 allocation->y + allocation->height * end_fraction,
4864 allocation->x + (allocation->width - widget->style->xthickness) / 2);
4868 gboolean wide_separators;
4869 gint separator_height;
4871 gtk_widget_style_get (widget,
4872 "wide-separators", &wide_separators,
4873 "separator-height", &separator_height,
4876 if (wide_separators)
4877 gtk_paint_box (widget->style, widget->window,
4878 GTK_WIDGET_STATE (widget), GTK_SHADOW_ETCHED_OUT,
4879 area, widget, "hseparator",
4880 allocation->x + allocation->width * start_fraction,
4881 allocation->y + (allocation->height - separator_height) / 2,
4882 allocation->width * (end_fraction - start_fraction),
4885 gtk_paint_hline (widget->style, widget->window,
4886 GTK_WIDGET_STATE (widget), area, widget,
4888 allocation->x + allocation->width * start_fraction,
4889 allocation->x + allocation->width * end_fraction,
4890 allocation->y + (allocation->height - widget->style->ythickness) / 2);
4895 _gtk_toolbar_elide_underscores (const gchar *original)
4898 const gchar *p, *end;
4900 gboolean last_underscore;
4905 len = strlen (original);
4906 q = result = g_malloc (len + 1);
4907 last_underscore = FALSE;
4909 end = original + len;
4910 for (p = original; p < end; p++)
4912 if (!last_underscore && *p == '_')
4913 last_underscore = TRUE;
4916 last_underscore = FALSE;
4917 if (original + 2 <= p && p + 1 <= end &&
4918 p[-2] == '(' && p[-1] == '_' && p[0] != '_' && p[1] == ')')
4929 if (last_underscore)
4938 _gtk_toolbar_rebuild_menu (GtkToolbar *toolbar)
4940 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4943 priv->need_rebuild = TRUE;
4945 for (list = priv->content; list != NULL; list = list->next)
4947 ToolbarContent *content = list->data;
4949 toolbar_content_set_unknown_menu_status (content);
4952 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
4955 #define __GTK_TOOLBAR_C__
4956 #include "gtkaliasdef.c"