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
71 #define MAX_HOMOGENEOUS_N_CHARS 13 /* Items that are wider than this do not participate
72 * in the homogeneous game. In units of
73 * pango_font_get_estimated_char_width().
75 #define SLIDE_SPEED 600.0 /* How fast the items slide, in pixels per second */
76 #define ACCEL_THRESHOLD 0.18 /* After how much time in seconds will items start speeding up */
78 #define MIXED_API_WARNING \
79 "Mixing deprecated and non-deprecated GtkToolbar API is not allowed"
91 /* Child properties */
95 CHILD_PROP_HOMOGENEOUS
127 struct _GtkToolbarPrivate
132 GtkWidget * arrow_button;
135 GdkWindow * event_window;
137 GtkSettings * settings;
139 GtkToolItem * highlight_tool_item;
140 gint max_homogeneous_pixels;
144 guint show_arrow : 1;
146 guint is_sliding : 1;
147 guint need_rebuild : 1; /* whether the overflow menu should be regenerated */
150 static void gtk_toolbar_init (GtkToolbar *toolbar);
151 static void gtk_toolbar_class_init (GtkToolbarClass *klass);
152 static void gtk_toolbar_set_property (GObject *object,
156 static void gtk_toolbar_get_property (GObject *object,
160 static gint gtk_toolbar_expose (GtkWidget *widget,
161 GdkEventExpose *event);
162 static void gtk_toolbar_realize (GtkWidget *widget);
163 static void gtk_toolbar_unrealize (GtkWidget *widget);
164 static void gtk_toolbar_size_request (GtkWidget *widget,
165 GtkRequisition *requisition);
166 static void gtk_toolbar_size_allocate (GtkWidget *widget,
167 GtkAllocation *allocation);
168 static void gtk_toolbar_style_set (GtkWidget *widget,
169 GtkStyle *prev_style);
170 static gboolean gtk_toolbar_focus (GtkWidget *widget,
171 GtkDirectionType dir);
172 static void gtk_toolbar_screen_changed (GtkWidget *widget,
173 GdkScreen *previous_screen);
174 static void gtk_toolbar_map (GtkWidget *widget);
175 static void gtk_toolbar_unmap (GtkWidget *widget);
176 static void gtk_toolbar_set_child_property (GtkContainer *container,
181 static void gtk_toolbar_get_child_property (GtkContainer *container,
186 static void gtk_toolbar_finalize (GObject *object);
187 static void gtk_toolbar_show_all (GtkWidget *widget);
188 static void gtk_toolbar_hide_all (GtkWidget *widget);
189 static void gtk_toolbar_add (GtkContainer *container,
191 static void gtk_toolbar_remove (GtkContainer *container,
193 static void gtk_toolbar_forall (GtkContainer *container,
194 gboolean include_internals,
195 GtkCallback callback,
196 gpointer callback_data);
197 static GType gtk_toolbar_child_type (GtkContainer *container);
198 static void gtk_toolbar_orientation_changed (GtkToolbar *toolbar,
199 GtkOrientation orientation);
200 static void gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
201 GtkToolbarStyle style);
202 static gboolean gtk_toolbar_move_focus (GtkToolbar *toolbar,
203 GtkDirectionType dir);
204 static gboolean gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
205 gboolean focus_home);
206 static gboolean gtk_toolbar_button_press (GtkWidget *toolbar,
207 GdkEventButton *event);
208 static gboolean gtk_toolbar_arrow_button_press (GtkWidget *button,
209 GdkEventButton *event,
210 GtkToolbar *toolbar);
211 static void gtk_toolbar_arrow_button_clicked (GtkWidget *button,
212 GtkToolbar *toolbar);
213 static void gtk_toolbar_update_button_relief (GtkToolbar *toolbar);
214 static gboolean gtk_toolbar_popup_menu (GtkWidget *toolbar);
215 static GtkWidget *internal_insert_element (GtkToolbar *toolbar,
216 GtkToolbarChildType type,
219 const char *tooltip_text,
220 const char *tooltip_private_text,
222 GtkSignalFunc callback,
226 static void gtk_toolbar_reconfigured (GtkToolbar *toolbar);
227 static gboolean gtk_toolbar_check_new_api (GtkToolbar *toolbar);
228 static gboolean gtk_toolbar_check_old_api (GtkToolbar *toolbar);
230 static GtkReliefStyle get_button_relief (GtkToolbar *toolbar);
231 static gint get_internal_padding (GtkToolbar *toolbar);
232 static GtkShadowType get_shadow_type (GtkToolbar *toolbar);
233 static gint get_space_size (GtkToolbar *toolbar);
234 static GtkToolbarSpaceStyle get_space_style (GtkToolbar *toolbar);
236 /* methods on ToolbarContent 'class' */
237 static ToolbarContent *toolbar_content_new_tool_item (GtkToolbar *toolbar,
239 gboolean is_placeholder,
241 static ToolbarContent *toolbar_content_new_compatibility (GtkToolbar *toolbar,
242 GtkToolbarChildType type,
247 static void toolbar_content_remove (ToolbarContent *content,
248 GtkToolbar *toolbar);
249 static void toolbar_content_free (ToolbarContent *content);
250 static void toolbar_content_expose (ToolbarContent *content,
251 GtkContainer *container,
252 GdkEventExpose *expose);
253 static gboolean toolbar_content_visible (ToolbarContent *content,
254 GtkToolbar *toolbar);
255 static void toolbar_content_size_request (ToolbarContent *content,
257 GtkRequisition *requisition);
258 static gboolean toolbar_content_is_homogeneous (ToolbarContent *content,
259 GtkToolbar *toolbar);
260 static gboolean toolbar_content_is_placeholder (ToolbarContent *content);
261 static gboolean toolbar_content_disappearing (ToolbarContent *content);
262 static ItemState toolbar_content_get_state (ToolbarContent *content);
263 static gboolean toolbar_content_child_visible (ToolbarContent *content);
264 static void toolbar_content_get_goal_allocation (ToolbarContent *content,
265 GtkAllocation *allocation);
266 static void toolbar_content_get_allocation (ToolbarContent *content,
267 GtkAllocation *allocation);
268 static void toolbar_content_set_start_allocation (ToolbarContent *content,
269 GtkAllocation *new_start_allocation);
270 static void toolbar_content_get_start_allocation (ToolbarContent *content,
271 GtkAllocation *start_allocation);
272 static gboolean toolbar_content_get_expand (ToolbarContent *content);
273 static void toolbar_content_set_goal_allocation (ToolbarContent *content,
274 GtkAllocation *allocation);
275 static void toolbar_content_set_child_visible (ToolbarContent *content,
278 static void toolbar_content_size_allocate (ToolbarContent *content,
279 GtkAllocation *allocation);
280 static void toolbar_content_set_state (ToolbarContent *content,
281 ItemState new_state);
282 static GtkWidget * toolbar_content_get_widget (ToolbarContent *content);
283 static void toolbar_content_set_disappearing (ToolbarContent *content,
284 gboolean disappearing);
285 static void toolbar_content_set_size_request (ToolbarContent *content,
288 static void toolbar_content_toolbar_reconfigured (ToolbarContent *content,
289 GtkToolbar *toolbar);
290 static GtkWidget * toolbar_content_retrieve_menu_item (ToolbarContent *content);
291 static gboolean toolbar_content_has_proxy_menu_item (ToolbarContent *content);
292 static gboolean toolbar_content_is_separator (ToolbarContent *content);
293 static void toolbar_content_show_all (ToolbarContent *content);
294 static void toolbar_content_hide_all (ToolbarContent *content);
295 static void toolbar_content_set_expand (ToolbarContent *content,
298 #define GTK_TOOLBAR_GET_PRIVATE(o) \
299 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_TOOLBAR, GtkToolbarPrivate))
301 static GtkContainerClass * parent_class = NULL;
302 static guint toolbar_signals [LAST_SIGNAL] = { 0 };
305 gtk_toolbar_get_type (void)
307 static GtkType type = 0;
311 static const GTypeInfo type_info =
313 sizeof (GtkToolbarClass),
314 (GBaseInitFunc) NULL,
315 (GBaseFinalizeFunc) NULL,
316 (GClassInitFunc) gtk_toolbar_class_init,
317 (GClassFinalizeFunc) NULL,
321 (GInstanceInitFunc) gtk_toolbar_init,
324 type = g_type_register_static (GTK_TYPE_CONTAINER,
333 add_arrow_bindings (GtkBindingSet *binding_set,
335 GtkDirectionType dir)
337 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
339 gtk_binding_entry_add_signal (binding_set, keysym, 0,
341 GTK_TYPE_DIRECTION_TYPE, dir);
342 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
344 GTK_TYPE_DIRECTION_TYPE, dir);
348 add_ctrl_tab_bindings (GtkBindingSet *binding_set,
349 GdkModifierType modifiers,
350 GtkDirectionType direction)
352 gtk_binding_entry_add_signal (binding_set,
353 GDK_Tab, GDK_CONTROL_MASK | modifiers,
355 GTK_TYPE_DIRECTION_TYPE, direction);
356 gtk_binding_entry_add_signal (binding_set,
357 GDK_KP_Tab, GDK_CONTROL_MASK | modifiers,
359 GTK_TYPE_DIRECTION_TYPE, direction);
363 gtk_toolbar_class_init (GtkToolbarClass *klass)
365 GObjectClass *gobject_class;
366 GtkWidgetClass *widget_class;
367 GtkContainerClass *container_class;
368 GtkBindingSet *binding_set;
370 parent_class = g_type_class_peek_parent (klass);
372 gobject_class = (GObjectClass *)klass;
373 widget_class = (GtkWidgetClass *)klass;
374 container_class = (GtkContainerClass *)klass;
376 gobject_class->set_property = gtk_toolbar_set_property;
377 gobject_class->get_property = gtk_toolbar_get_property;
378 gobject_class->finalize = gtk_toolbar_finalize;
380 widget_class->button_press_event = gtk_toolbar_button_press;
381 widget_class->expose_event = gtk_toolbar_expose;
382 widget_class->size_request = gtk_toolbar_size_request;
383 widget_class->size_allocate = gtk_toolbar_size_allocate;
384 widget_class->style_set = gtk_toolbar_style_set;
385 widget_class->focus = gtk_toolbar_focus;
386 widget_class->screen_changed = gtk_toolbar_screen_changed;
387 widget_class->realize = gtk_toolbar_realize;
388 widget_class->unrealize = gtk_toolbar_unrealize;
389 widget_class->map = gtk_toolbar_map;
390 widget_class->unmap = gtk_toolbar_unmap;
391 widget_class->popup_menu = gtk_toolbar_popup_menu;
392 widget_class->show_all = gtk_toolbar_show_all;
393 widget_class->hide_all = gtk_toolbar_hide_all;
395 container_class->add = gtk_toolbar_add;
396 container_class->remove = gtk_toolbar_remove;
397 container_class->forall = gtk_toolbar_forall;
398 container_class->child_type = gtk_toolbar_child_type;
399 container_class->get_child_property = gtk_toolbar_get_child_property;
400 container_class->set_child_property = gtk_toolbar_set_child_property;
402 klass->orientation_changed = gtk_toolbar_orientation_changed;
403 klass->style_changed = gtk_toolbar_real_style_changed;
406 * GtkToolbar::orientation-changed:
407 * @toolbar: the object which emitted the signal
408 * @orientation: the new #GtkOrientation of the toolbar
410 * Emitted when the orientation of the toolbar changes.
412 toolbar_signals[ORIENTATION_CHANGED] =
413 g_signal_new ("orientation-changed",
414 G_OBJECT_CLASS_TYPE (klass),
416 G_STRUCT_OFFSET (GtkToolbarClass, orientation_changed),
418 g_cclosure_marshal_VOID__ENUM,
420 GTK_TYPE_ORIENTATION);
422 * GtkToolbar::style-changed:
423 * @toolbar: The #GtkToolbar which emitted the signal
424 * @style: the new #GtkToolbarStyle of the toolbar
426 * Emitted when the style of the toolbar changes.
428 toolbar_signals[STYLE_CHANGED] =
429 g_signal_new ("style-changed",
430 G_OBJECT_CLASS_TYPE (klass),
432 G_STRUCT_OFFSET (GtkToolbarClass, style_changed),
434 g_cclosure_marshal_VOID__ENUM,
436 GTK_TYPE_TOOLBAR_STYLE);
438 * GtkToolbar::popup-context-menu:
439 * @toolbar: the #GtkToolbar which emitted the signal
440 * @x: the x coordinate of the point where the menu should appear
441 * @y: the y coordinate of the point where the menu should appear
442 * @button: the mouse button the user pressed, or -1
444 * Emitted when the user right-clicks the toolbar or uses the
445 * keybinding to display a popup menu.
447 * Application developers should handle this signal if they want
448 * to display a context menu on the toolbar. The context-menu should
449 * appear at the coordinates given by @x and @y. The mouse button
450 * number is given by the @button parameter. If the menu was popped
451 * up using the keybaord, @button is -1.
453 * Return value: return %TRUE if the signal was handled, %FALSE if not
455 toolbar_signals[POPUP_CONTEXT_MENU] =
456 g_signal_new ("popup_context_menu",
457 G_OBJECT_CLASS_TYPE (klass),
459 G_STRUCT_OFFSET (GtkToolbarClass, popup_context_menu),
460 _gtk_boolean_handled_accumulator, NULL,
461 _gtk_marshal_BOOLEAN__INT_INT_INT,
463 G_TYPE_INT, G_TYPE_INT,
466 * GtkToolbar::move-focus:
467 * @toolbar: the #GtkToolbar which emitted the signal
468 * @dir: a #GtkDirection
470 * A keybinding signal used internally by GTK+. This signal can't
471 * be used in application code.
473 * Return value: %TRUE if the signal was handled, %FALSE if not
475 toolbar_signals[MOVE_FOCUS] =
476 _gtk_binding_signal_new ("move_focus",
477 G_TYPE_FROM_CLASS (klass),
478 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
479 G_CALLBACK (gtk_toolbar_move_focus),
481 _gtk_marshal_BOOLEAN__ENUM,
483 GTK_TYPE_DIRECTION_TYPE);
485 * GtkToolbar::focus-home-or-end:
486 * @toolbar: the #GtkToolbar which emitted the signal
487 * @focus_home: %TRUE if the first item should be focused
489 * A keybinding signal used internally by GTK+. This signal can't
490 * be used in application code
492 * Return value: %TRUE if the signal was handled, %FALSE if not
494 toolbar_signals[FOCUS_HOME_OR_END] =
495 _gtk_binding_signal_new ("focus_home_or_end",
496 G_OBJECT_CLASS_TYPE (klass),
497 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
498 G_CALLBACK (gtk_toolbar_focus_home_or_end),
500 _gtk_marshal_BOOLEAN__BOOLEAN,
505 g_object_class_install_property (gobject_class,
507 g_param_spec_enum ("orientation",
509 P_("The orientation of the toolbar"),
510 GTK_TYPE_ORIENTATION,
511 GTK_ORIENTATION_HORIZONTAL,
512 GTK_PARAM_READWRITE));
514 g_object_class_install_property (gobject_class,
516 g_param_spec_enum ("toolbar-style",
518 P_("How to draw the toolbar"),
519 GTK_TYPE_TOOLBAR_STYLE,
521 GTK_PARAM_READWRITE));
522 g_object_class_install_property (gobject_class,
524 g_param_spec_boolean ("show-arrow",
526 P_("If an arrow should be shown if the toolbar doesn't fit"),
528 GTK_PARAM_READWRITE));
532 * GtkToolbar:tooltips:
534 * If the tooltips of the toolbar should be active or not.
538 g_object_class_install_property (gobject_class,
540 g_param_spec_boolean ("tooltips",
542 P_("If the tooltips of the toolbar should be active or not"),
544 GTK_PARAM_READWRITE));
546 /* child properties */
547 gtk_container_class_install_child_property (container_class,
549 g_param_spec_boolean ("expand",
551 P_("Whether the item should receive extra space when the toolbar grows"),
553 GTK_PARAM_READWRITE));
555 gtk_container_class_install_child_property (container_class,
556 CHILD_PROP_HOMOGENEOUS,
557 g_param_spec_boolean ("homogeneous",
559 P_("Whether the item should be the same size as other homogeneous items"),
561 GTK_PARAM_READWRITE));
563 /* style properties */
564 gtk_widget_class_install_style_property (widget_class,
565 g_param_spec_int ("space-size",
567 P_("Size of spacers"),
571 GTK_PARAM_READABLE));
573 gtk_widget_class_install_style_property (widget_class,
574 g_param_spec_int ("internal-padding",
575 P_("Internal padding"),
576 P_("Amount of border space between the toolbar shadow and the buttons"),
580 GTK_PARAM_READABLE));
582 gtk_widget_class_install_style_property (widget_class,
583 g_param_spec_enum ("space-style",
585 P_("Whether spacers are vertical lines or just blank"),
586 GTK_TYPE_TOOLBAR_SPACE_STYLE,
588 GTK_PARAM_READABLE));
590 gtk_widget_class_install_style_property (widget_class,
591 g_param_spec_enum ("button-relief",
593 P_("Type of bevel around toolbar buttons"),
594 GTK_TYPE_RELIEF_STYLE,
596 GTK_PARAM_READABLE));
597 gtk_widget_class_install_style_property (widget_class,
598 g_param_spec_enum ("shadow-type",
600 P_("Style of bevel around the toolbar"),
601 GTK_TYPE_SHADOW_TYPE,
603 GTK_PARAM_READABLE));
605 gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-style",
607 P_("Whether default toolbars have text only, text and icons, icons only, etc."),
608 GTK_TYPE_TOOLBAR_STYLE,
609 DEFAULT_TOOLBAR_STYLE,
610 GTK_PARAM_READWRITE));
612 gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-icon-size",
613 P_("Toolbar icon size"),
614 P_("Size of icons in default toolbars"),
617 GTK_PARAM_READWRITE));
619 binding_set = gtk_binding_set_by_class (klass);
621 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
622 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
623 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
624 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
626 gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
627 "focus_home_or_end", 1,
628 G_TYPE_BOOLEAN, TRUE);
629 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
630 "focus_home_or_end", 1,
631 G_TYPE_BOOLEAN, TRUE);
632 gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
633 "focus_home_or_end", 1,
634 G_TYPE_BOOLEAN, FALSE);
635 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
636 "focus_home_or_end", 1,
637 G_TYPE_BOOLEAN, FALSE);
639 add_ctrl_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
640 add_ctrl_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
642 g_type_class_add_private (gobject_class, sizeof (GtkToolbarPrivate));
646 gtk_toolbar_init (GtkToolbar *toolbar)
648 GtkToolbarPrivate *priv;
650 GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS);
651 GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
653 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
655 toolbar->orientation = GTK_ORIENTATION_HORIZONTAL;
656 toolbar->style = DEFAULT_TOOLBAR_STYLE;
657 toolbar->icon_size = DEFAULT_ICON_SIZE;
658 toolbar->tooltips = gtk_tooltips_new ();
659 g_object_ref (toolbar->tooltips);
660 gtk_object_sink (GTK_OBJECT (toolbar->tooltips));
662 priv->arrow_button = gtk_toggle_button_new ();
663 g_signal_connect (priv->arrow_button, "button_press_event",
664 G_CALLBACK (gtk_toolbar_arrow_button_press), toolbar);
665 g_signal_connect (priv->arrow_button, "clicked",
666 G_CALLBACK (gtk_toolbar_arrow_button_clicked), toolbar);
667 gtk_button_set_relief (GTK_BUTTON (priv->arrow_button),
668 get_button_relief (toolbar));
670 priv->api_mode = DONT_KNOW;
672 gtk_button_set_focus_on_click (GTK_BUTTON (priv->arrow_button), FALSE);
674 priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
675 gtk_widget_set_name (priv->arrow, "gtk-toolbar-arrow");
676 gtk_widget_show (priv->arrow);
677 gtk_container_add (GTK_CONTAINER (priv->arrow_button), priv->arrow);
679 gtk_widget_set_parent (priv->arrow_button, GTK_WIDGET (toolbar));
681 /* which child position a drop will occur at */
683 priv->show_arrow = TRUE;
684 priv->settings = NULL;
686 priv->max_homogeneous_pixels = -1;
688 priv->timer = g_timer_new ();
692 gtk_toolbar_set_property (GObject *object,
697 GtkToolbar *toolbar = GTK_TOOLBAR (object);
701 case PROP_ORIENTATION:
702 gtk_toolbar_set_orientation (toolbar, g_value_get_enum (value));
704 case PROP_TOOLBAR_STYLE:
705 gtk_toolbar_set_style (toolbar, g_value_get_enum (value));
707 case PROP_SHOW_ARROW:
708 gtk_toolbar_set_show_arrow (toolbar, g_value_get_boolean (value));
711 gtk_toolbar_set_tooltips (toolbar, g_value_get_boolean (value));
714 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
720 gtk_toolbar_get_property (GObject *object,
725 GtkToolbar *toolbar = GTK_TOOLBAR (object);
726 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
730 case PROP_ORIENTATION:
731 g_value_set_enum (value, toolbar->orientation);
733 case PROP_TOOLBAR_STYLE:
734 g_value_set_enum (value, toolbar->style);
736 case PROP_SHOW_ARROW:
737 g_value_set_boolean (value, priv->show_arrow);
740 g_value_set_boolean (value, gtk_toolbar_get_tooltips (toolbar));
743 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
749 gtk_toolbar_map (GtkWidget *widget)
751 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
753 GTK_WIDGET_CLASS (parent_class)->map (widget);
755 if (priv->event_window)
756 gdk_window_show_unraised (priv->event_window);
760 gtk_toolbar_unmap (GtkWidget *widget)
762 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
764 if (priv->event_window)
765 gdk_window_hide (priv->event_window);
767 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
771 gtk_toolbar_realize (GtkWidget *widget)
773 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
774 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
776 GdkWindowAttr attributes;
777 gint attributes_mask;
780 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
782 border_width = GTK_CONTAINER (widget)->border_width;
784 attributes.wclass = GDK_INPUT_ONLY;
785 attributes.window_type = GDK_WINDOW_CHILD;
786 attributes.x = widget->allocation.x + border_width;
787 attributes.y = widget->allocation.y + border_width;
788 attributes.width = widget->allocation.width - border_width * 2;
789 attributes.height = widget->allocation.height - border_width * 2;
790 attributes.event_mask = gtk_widget_get_events (widget);
791 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
792 GDK_BUTTON_RELEASE_MASK |
793 GDK_ENTER_NOTIFY_MASK |
794 GDK_LEAVE_NOTIFY_MASK);
796 attributes_mask = GDK_WA_X | GDK_WA_Y;
798 widget->window = gtk_widget_get_parent_window (widget);
799 g_object_ref (widget->window);
800 widget->style = gtk_style_attach (widget->style, widget->window);
802 priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
803 &attributes, attributes_mask);
804 gdk_window_set_user_data (priv->event_window, toolbar);
808 gtk_toolbar_unrealize (GtkWidget *widget)
810 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
812 if (priv->event_window)
814 gdk_window_set_user_data (priv->event_window, NULL);
815 gdk_window_destroy (priv->event_window);
816 priv->event_window = NULL;
819 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
820 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
824 gtk_toolbar_expose (GtkWidget *widget,
825 GdkEventExpose *event)
827 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
828 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
833 border_width = GTK_CONTAINER (widget)->border_width;
835 if (GTK_WIDGET_DRAWABLE (widget))
837 gtk_paint_box (widget->style,
839 GTK_WIDGET_STATE (widget),
840 get_shadow_type (toolbar),
841 &event->area, widget, "toolbar",
842 border_width + widget->allocation.x,
843 border_width + widget->allocation.y,
844 widget->allocation.width - 2 * border_width,
845 widget->allocation.height - 2 * border_width);
848 for (list = priv->content; list != NULL; list = list->next)
850 ToolbarContent *content = list->data;
852 toolbar_content_expose (content, GTK_CONTAINER (widget), event);
855 gtk_container_propagate_expose (GTK_CONTAINER (widget),
863 gtk_toolbar_size_request (GtkWidget *widget,
864 GtkRequisition *requisition)
866 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
867 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
869 gint max_child_height;
870 gint max_child_width;
871 gint max_homogeneous_child_width;
872 gint max_homogeneous_child_height;
873 gint homogeneous_size;
875 gint pack_front_size;
877 GtkRequisition arrow_requisition;
879 max_homogeneous_child_width = 0;
880 max_homogeneous_child_height = 0;
882 max_child_height = 0;
883 for (list = priv->content; list != NULL; list = list->next)
885 GtkRequisition requisition;
886 ToolbarContent *content = list->data;
888 if (!toolbar_content_visible (content, toolbar))
891 toolbar_content_size_request (content, toolbar, &requisition);
893 max_child_width = MAX (max_child_width, requisition.width);
894 max_child_height = MAX (max_child_height, requisition.height);
896 if (toolbar_content_is_homogeneous (content, toolbar))
898 max_homogeneous_child_width = MAX (max_homogeneous_child_width, requisition.width);
899 max_homogeneous_child_height = MAX (max_homogeneous_child_height, requisition.height);
903 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
904 homogeneous_size = max_homogeneous_child_width;
906 homogeneous_size = max_homogeneous_child_height;
909 for (list = priv->content; list != NULL; list = list->next)
911 ToolbarContent *content = list->data;
914 if (!toolbar_content_visible (content, toolbar))
917 if (toolbar_content_is_homogeneous (content, toolbar))
919 size = homogeneous_size;
923 GtkRequisition requisition;
925 toolbar_content_size_request (content, toolbar, &requisition);
927 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
928 size = requisition.width;
930 size = requisition.height;
933 pack_front_size += size;
936 if (priv->show_arrow && priv->api_mode == NEW_API)
938 gtk_widget_size_request (priv->arrow_button, &arrow_requisition);
940 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
941 long_req = arrow_requisition.width;
943 long_req = arrow_requisition.height;
945 /* There is no point requesting space for the arrow if that would take
946 * up more space than all the items combined
948 long_req = MIN (long_req, pack_front_size);
952 arrow_requisition.height = 0;
953 arrow_requisition.width = 0;
955 long_req = pack_front_size;
958 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
960 requisition->width = long_req;
961 requisition->height = MAX (max_child_height, arrow_requisition.height);
965 requisition->height = long_req;
966 requisition->width = MAX (max_child_width, arrow_requisition.width);
970 ipadding = get_internal_padding (toolbar);
972 requisition->width += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width);
973 requisition->height += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width);
975 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
977 requisition->width += 2 * widget->style->xthickness;
978 requisition->height += 2 * widget->style->ythickness;
981 toolbar->button_maxw = max_homogeneous_child_width;
982 toolbar->button_maxh = max_homogeneous_child_height;
986 position (gint from, gint to, gdouble elapsed)
990 if (elapsed <= ACCEL_THRESHOLD)
992 n_pixels = SLIDE_SPEED * elapsed;
996 /* The formula is a second degree polynomial in
997 * @elapsed that has the line SLIDE_SPEED * @elapsed
998 * as tangent for @elapsed == ACCEL_THRESHOLD.
999 * This makes @n_pixels a smooth function of elapsed time.
1001 n_pixels = (SLIDE_SPEED / ACCEL_THRESHOLD) * elapsed * elapsed -
1002 SLIDE_SPEED * elapsed + SLIDE_SPEED * ACCEL_THRESHOLD;
1006 return MIN (from + n_pixels, to);
1008 return MAX (from - n_pixels, to);
1012 compute_intermediate_allocation (GtkToolbar *toolbar,
1013 const GtkAllocation *start,
1014 const GtkAllocation *goal,
1015 GtkAllocation *intermediate)
1017 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1018 gdouble elapsed = g_timer_elapsed (priv->timer, NULL);
1020 intermediate->x = position (start->x, goal->x, elapsed);
1021 intermediate->y = position (start->y, goal->y, elapsed);
1022 intermediate->width =
1023 position (start->x + start->width, goal->x + goal->width, elapsed) - intermediate->x;
1024 intermediate->height =
1025 position (start->y + start->height, goal->y + goal->height, elapsed) - intermediate->y;
1029 fixup_allocation_for_rtl (gint total_size,
1030 GtkAllocation *allocation)
1032 allocation->x += (total_size - (2 * allocation->x + allocation->width));
1036 fixup_allocation_for_vertical (GtkAllocation *allocation)
1040 tmp = allocation->x;
1041 allocation->x = allocation->y;
1042 allocation->y = tmp;
1044 tmp = allocation->width;
1045 allocation->width = allocation->height;
1046 allocation->height = tmp;
1050 get_item_size (GtkToolbar *toolbar,
1051 ToolbarContent *content)
1053 GtkRequisition requisition;
1055 toolbar_content_size_request (content, toolbar, &requisition);
1057 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1059 if (toolbar_content_is_homogeneous (content, toolbar))
1060 return toolbar->button_maxw;
1062 return requisition.width;
1066 if (toolbar_content_is_homogeneous (content, toolbar))
1067 return toolbar->button_maxh;
1069 return requisition.height;
1074 slide_idle_handler (gpointer data)
1076 GtkToolbar *toolbar = data;
1077 GtkToolbarPrivate *priv;
1080 GDK_THREADS_ENTER ();
1082 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1084 if (priv->need_sync)
1087 priv->need_sync = FALSE;
1090 for (list = priv->content; list != NULL; list = list->next)
1092 ToolbarContent *content = list->data;
1094 GtkAllocation goal_allocation;
1095 GtkAllocation allocation;
1098 state = toolbar_content_get_state (content);
1099 toolbar_content_get_goal_allocation (content, &goal_allocation);
1100 toolbar_content_get_allocation (content, &allocation);
1104 if (state == NOT_ALLOCATED)
1106 /* an unallocated item means that size allocate has to
1107 * called at least once more
1112 /* An invisible item with a goal allocation of
1113 * 0 is already at its goal.
1115 if ((state == NORMAL || state == OVERFLOWN) &&
1116 ((goal_allocation.width != 0 &&
1117 goal_allocation.height != 0) ||
1118 toolbar_content_child_visible (content)))
1120 if ((goal_allocation.x != allocation.x ||
1121 goal_allocation.y != allocation.y ||
1122 goal_allocation.width != allocation.width ||
1123 goal_allocation.height != allocation.height))
1125 /* An item is not in its right position yet. Note
1126 * that OVERFLOWN items do get an allocation in
1127 * gtk_toolbar_size_allocate(). This way you can see
1128 * them slide back in when you drag an item off the
1135 if (toolbar_content_is_placeholder (content) &&
1136 toolbar_content_disappearing (content) &&
1137 toolbar_content_child_visible (content))
1139 /* A disappearing placeholder is still visible.
1147 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1149 GDK_THREADS_LEAVE ();
1154 priv->is_sliding = FALSE;
1157 GDK_THREADS_LEAVE();
1162 rect_within (GtkAllocation *a1,
1165 return (a1->x >= a2->x &&
1166 a1->x + a1->width <= a2->x + a2->width &&
1168 a1->y + a1->height <= a2->y + a2->height);
1172 gtk_toolbar_begin_sliding (GtkToolbar *toolbar)
1174 GtkWidget *widget = GTK_WIDGET (toolbar);
1175 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1183 /* Start the sliding. This function copies the allocation of every
1184 * item into content->start_allocation. For items that haven't
1185 * been allocated yet, we calculate their position and save that
1186 * in start_allocatino along with zero width and zero height.
1188 * FIXME: It would be nice if we could share this code with
1189 * the equivalent in gtk_widget_size_allocate().
1191 priv->is_sliding = TRUE;
1194 priv->idle_id = g_idle_add (slide_idle_handler, toolbar);
1196 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1197 vertical = (toolbar->orientation == GTK_ORIENTATION_VERTICAL);
1198 border_width = get_internal_padding (toolbar) + GTK_CONTAINER (toolbar)->border_width;
1202 cur_x = widget->allocation.width - border_width - widget->style->xthickness;
1203 cur_y = widget->allocation.height - border_width - widget->style->ythickness;
1207 cur_x = border_width + widget->style->xthickness;
1208 cur_y = border_width + widget->style->ythickness;
1211 cur_x += widget->allocation.x;
1212 cur_y += widget->allocation.y;
1214 for (list = priv->content; list != NULL; list = list->next)
1216 ToolbarContent *content = list->data;
1217 GtkAllocation new_start_allocation;
1218 GtkAllocation item_allocation;
1221 state = toolbar_content_get_state (content);
1222 toolbar_content_get_allocation (content, &item_allocation);
1224 if ((state == NORMAL &&
1225 rect_within (&item_allocation, &(widget->allocation))) ||
1228 new_start_allocation = item_allocation;
1232 new_start_allocation.x = cur_x;
1233 new_start_allocation.y = cur_y;
1237 new_start_allocation.width = widget->allocation.width -
1238 2 * border_width - 2 * widget->style->xthickness;
1239 new_start_allocation.height = 0;
1243 new_start_allocation.width = 0;
1244 new_start_allocation.height = widget->allocation.height -
1245 2 * border_width - 2 * widget->style->ythickness;
1250 cur_y = new_start_allocation.y + new_start_allocation.height;
1252 cur_x = new_start_allocation.x;
1254 cur_x = new_start_allocation.x + new_start_allocation.width;
1256 toolbar_content_set_start_allocation (content, &new_start_allocation);
1259 /* This resize will run before the first idle handler. This
1260 * will make sure that items get the right goal allocation
1261 * so that the idle handler will not immediately return
1264 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1265 g_timer_reset (priv->timer);
1269 gtk_toolbar_stop_sliding (GtkToolbar *toolbar)
1271 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1273 if (priv->is_sliding)
1277 priv->is_sliding = FALSE;
1281 g_source_remove (priv->idle_id);
1285 list = priv->content;
1288 ToolbarContent *content = list->data;
1291 if (toolbar_content_is_placeholder (content))
1293 toolbar_content_remove (content, toolbar);
1294 toolbar_content_free (content);
1298 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1303 remove_item (GtkWidget *menu_item,
1306 gtk_container_remove (GTK_CONTAINER (menu_item->parent), menu_item);
1310 menu_deactivated (GtkWidget *menu,
1311 GtkToolbar *toolbar)
1313 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1314 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->arrow_button), FALSE);
1318 menu_detached (GtkWidget *toolbar,
1321 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1326 rebuild_menu (GtkToolbar *toolbar)
1328 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1329 GList *list, *children;
1333 priv->menu = GTK_MENU (gtk_menu_new());
1334 gtk_menu_attach_to_widget (priv->menu,
1335 GTK_WIDGET (toolbar),
1338 g_signal_connect (priv->menu, "deactivate", G_CALLBACK (menu_deactivated), toolbar);
1341 gtk_container_foreach (GTK_CONTAINER (priv->menu), remove_item, NULL);
1343 for (list = priv->content; list != NULL; list = list->next)
1345 ToolbarContent *content = list->data;
1347 if (toolbar_content_get_state (content) == OVERFLOWN &&
1348 !toolbar_content_is_placeholder (content))
1350 GtkWidget *menu_item = toolbar_content_retrieve_menu_item (content);
1354 g_assert (GTK_IS_MENU_ITEM (menu_item));
1355 gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_item);
1360 /* Remove leading and trailing separator items */
1361 children = gtk_container_get_children (GTK_CONTAINER (priv->menu));
1364 while (list && GTK_IS_SEPARATOR_MENU_ITEM (list->data))
1366 GtkWidget *child = list->data;
1368 gtk_container_remove (GTK_CONTAINER (priv->menu), child);
1371 g_list_free (children);
1373 /* Regenerate the list of children so we don't try to remove items twice */
1374 children = gtk_container_get_children (GTK_CONTAINER (priv->menu));
1376 list = g_list_last (children);
1377 while (list && GTK_IS_SEPARATOR_MENU_ITEM (list->data))
1379 GtkWidget *child = list->data;
1381 gtk_container_remove (GTK_CONTAINER (priv->menu), child);
1384 g_list_free (children);
1386 priv->need_rebuild = FALSE;
1390 gtk_toolbar_size_allocate (GtkWidget *widget,
1391 GtkAllocation *allocation)
1393 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1394 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1395 GtkAllocation *allocations;
1396 ItemState *new_states;
1397 GtkAllocation arrow_allocation;
1399 gint size, pos, short_size;
1402 gboolean need_arrow;
1403 gint n_expand_items;
1405 gint available_size;
1408 GtkRequisition arrow_requisition;
1409 gboolean overflowing;
1410 gboolean size_changed;
1412 GtkAllocation item_area;
1414 size_changed = FALSE;
1415 if (widget->allocation.x != allocation->x ||
1416 widget->allocation.y != allocation->y ||
1417 widget->allocation.width != allocation->width ||
1418 widget->allocation.height != allocation->height)
1420 size_changed = TRUE;
1424 gtk_toolbar_stop_sliding (toolbar);
1426 widget->allocation = *allocation;
1428 border_width = GTK_CONTAINER (toolbar)->border_width;
1430 if (GTK_WIDGET_REALIZED (widget))
1432 gdk_window_move_resize (priv->event_window,
1433 allocation->x + border_width,
1434 allocation->y + border_width,
1435 allocation->width - border_width * 2,
1436 allocation->height - border_width * 2);
1439 border_width += get_internal_padding (toolbar);
1441 gtk_widget_get_child_requisition (GTK_WIDGET (priv->arrow_button),
1442 &arrow_requisition);
1444 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1446 available_size = size = allocation->width - 2 * border_width;
1447 short_size = allocation->height - 2 * border_width;
1448 arrow_size = arrow_requisition.width;
1450 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1452 available_size -= 2 * widget->style->xthickness;
1453 short_size -= 2 * widget->style->ythickness;
1458 available_size = size = allocation->height - 2 * border_width;
1459 short_size = allocation->width - 2 * border_width;
1460 arrow_size = arrow_requisition.height;
1462 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1464 available_size -= 2 * widget->style->ythickness;
1465 short_size -= 2 * widget->style->xthickness;
1469 n_items = g_list_length (priv->content);
1470 allocations = g_new0 (GtkAllocation, n_items);
1471 new_states = g_new0 (ItemState, n_items);
1475 for (list = priv->content; list != NULL; list = list->next)
1477 ToolbarContent *content = list->data;
1479 if (toolbar_content_visible (content, toolbar))
1481 needed_size += get_item_size (toolbar, content);
1483 /* Do we need an arrow?
1485 * Assume we don't, and see if any non-separator item with a
1486 * proxy menu item is then going to overflow.
1488 if (needed_size > available_size &&
1491 priv->api_mode == NEW_API &&
1492 toolbar_content_has_proxy_menu_item (content) &&
1493 !toolbar_content_is_separator (content))
1501 size = available_size - arrow_size;
1503 size = available_size;
1505 /* calculate widths and states of items */
1506 overflowing = FALSE;
1507 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1509 ToolbarContent *content = list->data;
1512 if (!toolbar_content_visible (content, toolbar))
1514 new_states[i] = HIDDEN;
1518 item_size = get_item_size (toolbar, content);
1519 if (item_size <= size && !overflowing)
1522 allocations[i].width = item_size;
1523 new_states[i] = NORMAL;
1528 new_states[i] = OVERFLOWN;
1529 allocations[i].width = item_size;
1533 /* calculate width of arrow */
1536 arrow_allocation.width = arrow_size;
1537 arrow_allocation.height = MAX (short_size, 1);
1540 /* expand expandable items */
1542 /* We don't expand when there is an overflow menu, because that leads to
1543 * weird jumps when items get moved to the overflow menu and the expanding
1544 * items suddenly get a lot of extra space
1549 for (i = 0, list = priv->content; list != NULL; list = list->next, ++i)
1551 ToolbarContent *content = list->data;
1553 if (toolbar_content_get_expand (content) && new_states[i] == NORMAL)
1557 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1559 ToolbarContent *content = list->data;
1561 if (toolbar_content_get_expand (content) && new_states[i] == NORMAL)
1563 gint extra = size / n_expand_items;
1564 if (size % n_expand_items != 0)
1567 allocations[i].width += extra;
1573 g_assert (n_expand_items == 0);
1576 /* position items */
1578 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1580 /* both NORMAL and OVERFLOWN items get a position. This ensures
1581 * that sliding will work for OVERFLOWN items too
1583 if (new_states[i] == NORMAL ||
1584 new_states[i] == OVERFLOWN)
1586 allocations[i].x = pos;
1587 allocations[i].y = border_width;
1588 allocations[i].height = short_size;
1590 pos += allocations[i].width;
1594 /* position arrow */
1597 arrow_allocation.x = available_size - border_width - arrow_allocation.width;
1598 arrow_allocation.y = border_width;
1601 item_area.x = border_width;
1602 item_area.y = border_width;
1603 item_area.width = available_size - (need_arrow? arrow_size : 0);
1604 item_area.height = short_size;
1606 /* fix up allocations in the vertical or RTL cases */
1607 if (toolbar->orientation == GTK_ORIENTATION_VERTICAL)
1609 for (i = 0; i < n_items; ++i)
1610 fixup_allocation_for_vertical (&(allocations[i]));
1613 fixup_allocation_for_vertical (&arrow_allocation);
1615 fixup_allocation_for_vertical (&item_area);
1617 else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1619 for (i = 0; i < n_items; ++i)
1620 fixup_allocation_for_rtl (available_size, &(allocations[i]));
1623 fixup_allocation_for_rtl (available_size, &arrow_allocation);
1625 fixup_allocation_for_rtl (available_size, &item_area);
1628 /* translate the items by allocation->(x,y) */
1629 for (i = 0; i < n_items; ++i)
1631 allocations[i].x += allocation->x;
1632 allocations[i].y += allocation->y;
1634 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1636 allocations[i].x += widget->style->xthickness;
1637 allocations[i].y += widget->style->ythickness;
1643 arrow_allocation.x += allocation->x;
1644 arrow_allocation.y += allocation->y;
1646 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1648 arrow_allocation.x += widget->style->xthickness;
1649 arrow_allocation.y += widget->style->ythickness;
1653 item_area.x += allocation->x;
1654 item_area.y += allocation->y;
1655 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1657 item_area.x += widget->style->xthickness;
1658 item_area.y += widget->style->ythickness;
1661 /* did anything change? */
1662 for (list = priv->content, i = 0; list != NULL; list = list->next, i++)
1664 ToolbarContent *content = list->data;
1666 if (toolbar_content_get_state (content) == NORMAL &&
1667 new_states[i] != NORMAL)
1669 /* an item disappeared and we didn't change size, so begin sliding */
1670 if (!size_changed && priv->api_mode == NEW_API)
1671 gtk_toolbar_begin_sliding (toolbar);
1675 /* finally allocate the items */
1676 if (priv->is_sliding)
1678 for (list = priv->content, i = 0; list != NULL; list = list->next, i++)
1680 ToolbarContent *content = list->data;
1682 toolbar_content_set_goal_allocation (content, &(allocations[i]));
1686 elapsed = g_timer_elapsed (priv->timer, NULL);
1687 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1689 ToolbarContent *content = list->data;
1691 if (new_states[i] == OVERFLOWN ||
1692 new_states[i] == NORMAL)
1694 GtkAllocation alloc;
1695 GtkAllocation start_allocation;
1696 GtkAllocation goal_allocation;
1698 if (priv->is_sliding)
1700 toolbar_content_get_start_allocation (content, &start_allocation);
1701 toolbar_content_get_goal_allocation (content, &goal_allocation);
1703 compute_intermediate_allocation (toolbar,
1708 priv->need_sync = TRUE;
1712 alloc = allocations[i];
1715 if (alloc.width <= 0 || alloc.height <= 0)
1717 toolbar_content_set_child_visible (content, toolbar, FALSE);
1721 if (!rect_within (&alloc, &item_area))
1723 toolbar_content_set_child_visible (content, toolbar, FALSE);
1724 toolbar_content_size_allocate (content, &alloc);
1728 toolbar_content_set_child_visible (content, toolbar, TRUE);
1729 toolbar_content_size_allocate (content, &alloc);
1735 toolbar_content_set_child_visible (content, toolbar, FALSE);
1738 toolbar_content_set_state (content, new_states[i]);
1741 if (priv->menu && priv->need_rebuild)
1742 rebuild_menu (toolbar);
1746 gtk_widget_size_allocate (GTK_WIDGET (priv->arrow_button),
1748 gtk_widget_show (GTK_WIDGET (priv->arrow_button));
1752 gtk_widget_hide (GTK_WIDGET (priv->arrow_button));
1754 if (priv->menu && GTK_WIDGET_VISIBLE (priv->menu))
1755 gtk_menu_shell_deactivate (GTK_MENU_SHELL (priv->menu));
1758 g_free (allocations);
1759 g_free (new_states);
1763 gtk_toolbar_update_button_relief (GtkToolbar *toolbar)
1765 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1767 gtk_toolbar_reconfigured (toolbar);
1769 gtk_button_set_relief (GTK_BUTTON (priv->arrow_button), get_button_relief (toolbar));
1773 gtk_toolbar_style_set (GtkWidget *widget,
1774 GtkStyle *prev_style)
1776 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
1778 priv->max_homogeneous_pixels = -1;
1780 if (GTK_WIDGET_REALIZED (widget))
1781 gtk_style_set_background (widget->style, widget->window, widget->state);
1784 gtk_toolbar_update_button_relief (GTK_TOOLBAR (widget));
1788 gtk_toolbar_list_children_in_focus_order (GtkToolbar *toolbar,
1789 GtkDirectionType dir)
1791 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1792 GList *result = NULL;
1796 /* generate list of children in reverse logical order */
1798 for (list = priv->content; list != NULL; list = list->next)
1800 ToolbarContent *content = list->data;
1803 widget = toolbar_content_get_widget (content);
1806 result = g_list_prepend (result, widget);
1809 result = g_list_prepend (result, priv->arrow_button);
1811 rtl = (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL);
1813 /* move in logical order when
1815 * - dir is TAB_FORWARD
1817 * - in RTL mode and moving left or up
1819 * - in LTR mode and moving right or down
1821 if (dir == GTK_DIR_TAB_FORWARD ||
1822 (rtl && (dir == GTK_DIR_UP || dir == GTK_DIR_LEFT)) ||
1823 (!rtl && (dir == GTK_DIR_DOWN || dir == GTK_DIR_RIGHT)))
1825 result = g_list_reverse (result);
1832 gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
1833 gboolean focus_home)
1835 GList *children, *list;
1836 GtkDirectionType dir = focus_home? GTK_DIR_RIGHT : GTK_DIR_LEFT;
1838 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1840 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1842 children = g_list_reverse (children);
1844 dir = (dir == GTK_DIR_RIGHT)? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1847 for (list = children; list != NULL; list = list->next)
1849 GtkWidget *child = list->data;
1851 if (GTK_CONTAINER (toolbar)->focus_child == child)
1854 if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1858 g_list_free (children);
1863 /* Keybinding handler. This function is called when the user presses
1864 * Ctrl TAB or an arrow key.
1867 gtk_toolbar_move_focus (GtkToolbar *toolbar,
1868 GtkDirectionType dir)
1871 gboolean try_focus = FALSE;
1873 GtkContainer *container = GTK_CONTAINER (toolbar);
1875 if (container->focus_child &&
1876 gtk_widget_child_focus (container->focus_child, dir))
1881 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1883 for (list = children; list != NULL; list = list->next)
1885 GtkWidget *child = list->data;
1887 if (try_focus && GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1890 if (child == GTK_CONTAINER (toolbar)->focus_child)
1894 g_list_free (children);
1899 /* The focus handler for the toolbar. It called when the user presses
1900 * TAB or otherwise tries to focus the toolbar.
1903 gtk_toolbar_focus (GtkWidget *widget,
1904 GtkDirectionType dir)
1906 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1907 GList *children, *list;
1908 gboolean result = FALSE;
1910 /* if focus is already somewhere inside the toolbar then return FALSE.
1911 * The only way focus can stay inside the toolbar is when the user presses
1912 * arrow keys or Ctrl TAB (both of which are handled by the
1913 * gtk_toolbar_move_focus() keybinding function.
1915 if (GTK_CONTAINER (widget)->focus_child)
1918 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1920 for (list = children; list != NULL; list = list->next)
1922 GtkWidget *child = list->data;
1924 if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1931 g_list_free (children);
1937 style_change_notify (GtkToolbar *toolbar)
1939 if (!toolbar->style_set)
1941 /* pretend it was set, then unset, thus reverting to new default */
1942 toolbar->style_set = TRUE;
1943 gtk_toolbar_unset_style (toolbar);
1948 icon_size_change_notify (GtkToolbar *toolbar)
1950 if (!toolbar->icon_size_set)
1952 /* pretend it was set, then unset, thus reverting to new default */
1953 toolbar->icon_size_set = TRUE;
1954 gtk_toolbar_unset_icon_size (toolbar);
1958 static GtkSettings *
1959 toolbar_get_settings (GtkToolbar *toolbar)
1961 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1962 return priv->settings;
1966 gtk_toolbar_screen_changed (GtkWidget *widget,
1967 GdkScreen *previous_screen)
1969 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
1970 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1971 GtkSettings *old_settings = toolbar_get_settings (toolbar);
1972 GtkSettings *settings;
1974 if (gtk_widget_has_screen (GTK_WIDGET (toolbar)))
1975 settings = gtk_widget_get_settings (GTK_WIDGET (toolbar));
1979 if (settings == old_settings)
1984 g_signal_handler_disconnect (old_settings, toolbar->style_set_connection);
1985 g_signal_handler_disconnect (old_settings, toolbar->icon_size_connection);
1987 g_object_unref (old_settings);
1992 toolbar->style_set_connection =
1993 g_signal_connect_swapped (settings,
1994 "notify::gtk-toolbar-style",
1995 G_CALLBACK (style_change_notify),
1997 toolbar->icon_size_connection =
1998 g_signal_connect_swapped (settings,
1999 "notify::gtk-toolbar-icon-size",
2000 G_CALLBACK (icon_size_change_notify),
2003 g_object_ref (settings);
2004 priv->settings = settings;
2007 priv->settings = NULL;
2009 style_change_notify (toolbar);
2010 icon_size_change_notify (toolbar);
2014 find_drop_index (GtkToolbar *toolbar,
2018 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2019 GList *interesting_content;
2021 GtkOrientation orientation;
2022 GtkTextDirection direction;
2023 gint best_distance = G_MAXINT;
2027 ToolbarContent *best_content;
2028 GtkAllocation allocation;
2030 /* list items we care about wrt. drag and drop */
2031 interesting_content = NULL;
2032 for (list = priv->content; list != NULL; list = list->next)
2034 ToolbarContent *content = list->data;
2036 if (toolbar_content_get_state (content) == NORMAL)
2037 interesting_content = g_list_prepend (interesting_content, content);
2039 interesting_content = g_list_reverse (interesting_content);
2041 if (!interesting_content)
2044 orientation = toolbar->orientation;
2045 direction = gtk_widget_get_direction (GTK_WIDGET (toolbar));
2047 /* distance to first interesting item */
2048 best_content = interesting_content->data;
2049 toolbar_content_get_allocation (best_content, &allocation);
2051 if (orientation == GTK_ORIENTATION_HORIZONTAL)
2055 if (direction == GTK_TEXT_DIR_LTR)
2058 pos = allocation.x + allocation.width;
2066 best_content = NULL;
2067 best_distance = ABS (pos - cursor);
2069 /* distance to far end of each item */
2070 for (list = interesting_content; list != NULL; list = list->next)
2072 ToolbarContent *content = list->data;
2074 toolbar_content_get_allocation (content, &allocation);
2076 if (orientation == GTK_ORIENTATION_HORIZONTAL)
2078 if (direction == GTK_TEXT_DIR_LTR)
2079 pos = allocation.x + allocation.width;
2085 pos = allocation.y + allocation.height;
2088 distance = ABS (pos - cursor);
2090 if (distance < best_distance)
2092 best_distance = distance;
2093 best_content = content;
2097 g_list_free (interesting_content);
2102 return g_list_index (priv->content, best_content) + 1;
2106 reset_all_placeholders (GtkToolbar *toolbar)
2108 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2111 for (list = priv->content; list != NULL; list = list->next)
2113 ToolbarContent *content = list->data;
2114 if (toolbar_content_is_placeholder (content))
2115 toolbar_content_set_disappearing (content, TRUE);
2120 physical_to_logical (GtkToolbar *toolbar,
2123 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2127 g_assert (physical >= 0);
2130 for (list = priv->content; list && physical > 0; list = list->next)
2132 ToolbarContent *content = list->data;
2134 if (!toolbar_content_is_placeholder (content))
2139 g_assert (physical == 0);
2145 logical_to_physical (GtkToolbar *toolbar,
2148 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2152 g_assert (logical >= 0);
2155 for (list = priv->content; list; list = list->next)
2157 ToolbarContent *content = list->data;
2159 if (!toolbar_content_is_placeholder (content))
2169 g_assert (logical == 0);
2175 * gtk_toolbar_set_drop_highlight_item:
2176 * @toolbar: a #GtkToolbar
2177 * @tool_item: a #GtkToolItem, or %NULL to turn of highlighting
2178 * @index_: a position on @toolbar
2180 * Highlights @toolbar to give an idea of what it would look like
2181 * if @item was added to @toolbar at the position indicated by @index_.
2182 * If @item is %NULL, highlighting is turned off. In that case @index_
2185 * The @tool_item passed to this function must not be part of any widget
2186 * hierarchy. When an item is set as drop highlight item it can not
2187 * added to any widget hierarchy or used as highlight item for another
2193 gtk_toolbar_set_drop_highlight_item (GtkToolbar *toolbar,
2194 GtkToolItem *tool_item,
2197 ToolbarContent *content;
2198 GtkToolbarPrivate *priv;
2200 GtkRequisition requisition;
2201 GtkRequisition old_requisition;
2202 gboolean restart_sliding;
2204 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2205 g_return_if_fail (tool_item == NULL || GTK_IS_TOOL_ITEM (tool_item));
2207 gtk_toolbar_check_new_api (toolbar);
2209 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2213 if (priv->highlight_tool_item)
2215 gtk_widget_unparent (GTK_WIDGET (priv->highlight_tool_item));
2216 g_object_unref (priv->highlight_tool_item);
2217 priv->highlight_tool_item = NULL;
2220 reset_all_placeholders (toolbar);
2221 gtk_toolbar_begin_sliding (toolbar);
2225 n_items = gtk_toolbar_get_n_items (toolbar);
2226 if (index_ < 0 || index_ > n_items)
2229 if (tool_item != priv->highlight_tool_item)
2231 if (priv->highlight_tool_item)
2232 g_object_unref (priv->highlight_tool_item);
2234 g_object_ref (tool_item);
2235 gtk_object_sink (GTK_OBJECT (tool_item));
2237 priv->highlight_tool_item = tool_item;
2239 gtk_widget_set_parent (GTK_WIDGET (priv->highlight_tool_item),
2240 GTK_WIDGET (toolbar));
2243 index_ = logical_to_physical (toolbar, index_);
2245 content = g_list_nth_data (priv->content, index_);
2249 ToolbarContent *prev_content;
2251 prev_content = g_list_nth_data (priv->content, index_ - 1);
2253 if (prev_content && toolbar_content_is_placeholder (prev_content))
2254 content = prev_content;
2257 if (!content || !toolbar_content_is_placeholder (content))
2259 GtkWidget *placeholder;
2261 placeholder = GTK_WIDGET (gtk_separator_tool_item_new ());
2263 content = toolbar_content_new_tool_item (toolbar,
2264 GTK_TOOL_ITEM (placeholder),
2266 gtk_widget_show (placeholder);
2270 g_assert (toolbar_content_is_placeholder (content));
2272 gtk_widget_size_request (GTK_WIDGET (priv->highlight_tool_item),
2275 toolbar_content_set_expand (content, gtk_tool_item_get_expand (tool_item));
2277 restart_sliding = FALSE;
2278 toolbar_content_size_request (content, toolbar, &old_requisition);
2279 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
2281 requisition.height = -1;
2282 if (requisition.width != old_requisition.width)
2283 restart_sliding = TRUE;
2287 requisition.width = -1;
2288 if (requisition.height != old_requisition.height)
2289 restart_sliding = TRUE;
2292 if (toolbar_content_disappearing (content))
2293 restart_sliding = TRUE;
2295 reset_all_placeholders (toolbar);
2296 toolbar_content_set_disappearing (content, FALSE);
2298 toolbar_content_set_size_request (content,
2299 requisition.width, requisition.height);
2301 if (restart_sliding)
2302 gtk_toolbar_begin_sliding (toolbar);
2306 gtk_toolbar_get_child_property (GtkContainer *container,
2312 GtkToolItem *item = GTK_TOOL_ITEM (child);
2314 switch (property_id)
2316 case CHILD_PROP_HOMOGENEOUS:
2317 g_value_set_boolean (value, gtk_tool_item_get_homogeneous (item));
2320 case CHILD_PROP_EXPAND:
2321 g_value_set_boolean (value, gtk_tool_item_get_expand (item));
2325 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2331 gtk_toolbar_set_child_property (GtkContainer *container,
2334 const GValue *value,
2337 switch (property_id)
2339 case CHILD_PROP_HOMOGENEOUS:
2340 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
2343 case CHILD_PROP_EXPAND:
2344 gtk_tool_item_set_expand (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
2348 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2354 gtk_toolbar_show_all (GtkWidget *widget)
2356 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
2359 for (list = priv->content; list != NULL; list = list->next)
2361 ToolbarContent *content = list->data;
2363 toolbar_content_show_all (content);
2366 gtk_widget_show (widget);
2370 gtk_toolbar_hide_all (GtkWidget *widget)
2372 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
2375 for (list = priv->content; list != NULL; list = list->next)
2377 ToolbarContent *content = list->data;
2379 toolbar_content_hide_all (content);
2382 gtk_widget_hide (widget);
2386 gtk_toolbar_add (GtkContainer *container,
2389 GtkToolbar *toolbar;
2391 g_return_if_fail (GTK_IS_TOOLBAR (container));
2392 g_return_if_fail (widget != NULL);
2394 toolbar = GTK_TOOLBAR (container);
2396 if (GTK_IS_TOOL_ITEM (widget))
2397 gtk_toolbar_insert (toolbar, GTK_TOOL_ITEM (widget), -1);
2399 gtk_toolbar_append_widget (toolbar, widget, NULL, NULL);
2403 gtk_toolbar_remove (GtkContainer *container,
2406 GtkToolbar *toolbar;
2407 GtkToolbarPrivate *priv;
2408 ToolbarContent *content_to_remove;
2411 g_return_if_fail (GTK_IS_TOOLBAR (container));
2412 g_return_if_fail (GTK_IS_WIDGET (widget));
2414 toolbar = GTK_TOOLBAR (container);
2415 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2417 content_to_remove = NULL;
2418 for (list = priv->content; list != NULL; list = list->next)
2420 ToolbarContent *content = list->data;
2423 child = toolbar_content_get_widget (content);
2424 if (child && child == widget)
2426 content_to_remove = content;
2431 g_return_if_fail (content_to_remove != NULL);
2433 toolbar_content_remove (content_to_remove, toolbar);
2434 toolbar_content_free (content_to_remove);
2438 gtk_toolbar_forall (GtkContainer *container,
2439 gboolean include_internals,
2440 GtkCallback callback,
2441 gpointer callback_data)
2443 GtkToolbar *toolbar = GTK_TOOLBAR (container);
2444 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2447 g_return_if_fail (callback != NULL);
2449 list = priv->content;
2452 ToolbarContent *content = list->data;
2453 GList *next = list->next;
2455 if (include_internals || !toolbar_content_is_placeholder (content))
2457 GtkWidget *child = toolbar_content_get_widget (content);
2460 (*callback) (child, callback_data);
2466 if (include_internals)
2467 (* callback) (priv->arrow_button, callback_data);
2471 gtk_toolbar_child_type (GtkContainer *container)
2473 return GTK_TYPE_TOOL_ITEM;
2477 gtk_toolbar_reconfigured (GtkToolbar *toolbar)
2479 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2482 list = priv->content;
2485 ToolbarContent *content = list->data;
2486 GList *next = list->next;
2488 toolbar_content_toolbar_reconfigured (content, toolbar);
2495 gtk_toolbar_orientation_changed (GtkToolbar *toolbar,
2496 GtkOrientation orientation)
2498 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2499 if (toolbar->orientation != orientation)
2501 toolbar->orientation = orientation;
2503 if (orientation == GTK_ORIENTATION_HORIZONTAL)
2504 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_DOWN, GTK_SHADOW_NONE);
2506 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
2508 gtk_toolbar_reconfigured (toolbar);
2510 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2511 g_object_notify (G_OBJECT (toolbar), "orientation");
2516 gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
2517 GtkToolbarStyle style)
2519 if (toolbar->style != style)
2521 toolbar->style = style;
2523 gtk_toolbar_reconfigured (toolbar);
2525 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2526 g_object_notify (G_OBJECT (toolbar), "toolbar-style");
2531 menu_position_func (GtkMenu *menu,
2537 GtkToolbar *toolbar = GTK_TOOLBAR (user_data);
2538 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2540 GtkRequisition menu_req;
2541 GdkRectangle monitor;
2545 gtk_widget_size_request (priv->arrow_button, &req);
2546 gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
2548 screen = gtk_widget_get_screen (GTK_WIDGET (menu));
2549 monitor_num = gdk_screen_get_monitor_at_window (screen, priv->arrow_button->window);
2550 if (monitor_num < 0)
2552 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
2554 gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y);
2555 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
2557 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2558 *x += priv->arrow_button->allocation.width - req.width;
2560 *x += req.width - menu_req.width;
2562 if ((*y + priv->arrow_button->allocation.height + menu_req.height) <= monitor.y + monitor.height)
2563 *y += priv->arrow_button->allocation.height;
2564 else if ((*y - menu_req.height) >= monitor.y)
2565 *y -= menu_req.height;
2566 else if (monitor.y + monitor.height - (*y + priv->arrow_button->allocation.height) > *y)
2567 *y += priv->arrow_button->allocation.height;
2569 *y -= menu_req.height;
2573 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2574 *x += priv->arrow_button->allocation.width;
2576 *x -= menu_req.width;
2578 if (*y + menu_req.height > monitor.y + monitor.height &&
2579 *y + priv->arrow_button->allocation.height - monitor.y > monitor.y + monitor.height - *y)
2580 *y += priv->arrow_button->allocation.height - menu_req.height;
2587 show_menu (GtkToolbar *toolbar,
2588 GdkEventButton *event)
2590 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2592 rebuild_menu (toolbar);
2594 gtk_widget_show_all (GTK_WIDGET (priv->menu));
2596 gtk_menu_popup (priv->menu, NULL, NULL,
2597 menu_position_func, toolbar,
2598 event? event->button : 0,
2599 event? event->time : gtk_get_current_event_time());
2603 gtk_toolbar_arrow_button_clicked (GtkWidget *button,
2604 GtkToolbar *toolbar)
2606 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2608 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->arrow_button)) &&
2609 (!priv->menu || !GTK_WIDGET_VISIBLE (priv->menu)))
2611 /* We only get here when the button is clicked with the keyboard,
2612 * because mouse button presses result in the menu being shown so
2613 * that priv->menu would be non-NULL and visible.
2615 show_menu (toolbar, NULL);
2616 gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menu), FALSE);
2621 gtk_toolbar_arrow_button_press (GtkWidget *button,
2622 GdkEventButton *event,
2623 GtkToolbar *toolbar)
2625 show_menu (toolbar, event);
2626 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2632 gtk_toolbar_button_press (GtkWidget *toolbar,
2633 GdkEventButton *event)
2635 if (event->button == 3)
2637 gboolean return_value;
2639 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2640 (int)event->x_root, (int)event->y_root, event->button,
2643 return return_value;
2650 gtk_toolbar_popup_menu (GtkWidget *toolbar)
2652 gboolean return_value;
2653 /* This function is the handler for the "popup menu" keybinding,
2654 * ie., it is called when the user presses Shift F10
2656 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2657 -1, -1, -1, &return_value);
2659 return return_value;
2665 * Creates a new toolbar.
2667 * Return Value: the newly-created toolbar.
2670 gtk_toolbar_new (void)
2672 GtkToolbar *toolbar;
2674 toolbar = g_object_new (GTK_TYPE_TOOLBAR, NULL);
2676 return GTK_WIDGET (toolbar);
2680 * gtk_toolbar_insert:
2681 * @toolbar: a #GtkToolbar
2682 * @item: a #GtkToolItem
2683 * @pos: the position of the new item
2685 * Insert a #GtkToolItem into the toolbar at position @pos. If @pos is
2686 * 0 the item is prepended to the start of the toolbar. If @pos is
2687 * negative, the item is appended to the end of the toolbar.
2692 gtk_toolbar_insert (GtkToolbar *toolbar,
2696 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2697 g_return_if_fail (GTK_IS_TOOL_ITEM (item));
2699 if (!gtk_toolbar_check_new_api (toolbar))
2703 pos = logical_to_physical (toolbar, pos);
2705 toolbar_content_new_tool_item (toolbar, item, FALSE, pos);
2709 * gtk_toolbar_get_item_index:
2710 * @toolbar: a #GtkToolbar
2711 * @item: a #GtkToolItem that is a child of @toolbar
2713 * Returns the position of @item on the toolbar, starting from 0.
2714 * It is an error if @item is not a child of the toolbar.
2716 * Return value: the position of item on the toolbar.
2721 gtk_toolbar_get_item_index (GtkToolbar *toolbar,
2724 GtkToolbarPrivate *priv;
2728 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2729 g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1);
2730 g_return_val_if_fail (GTK_WIDGET (item)->parent == GTK_WIDGET (toolbar), -1);
2732 if (!gtk_toolbar_check_new_api (toolbar))
2735 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2738 for (list = priv->content; list != NULL; list = list->next)
2740 ToolbarContent *content = list->data;
2743 widget = toolbar_content_get_widget (content);
2745 if (item == GTK_TOOL_ITEM (widget))
2751 return physical_to_logical (toolbar, n);
2755 * gtk_toolbar_set_orientation:
2756 * @toolbar: a #GtkToolbar.
2757 * @orientation: a new #GtkOrientation.
2759 * Sets whether a toolbar should appear horizontally or vertically.
2762 gtk_toolbar_set_orientation (GtkToolbar *toolbar,
2763 GtkOrientation orientation)
2765 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2767 g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0, orientation);
2771 * gtk_toolbar_get_orientation:
2772 * @toolbar: a #GtkToolbar
2774 * Retrieves the current orientation of the toolbar. See
2775 * gtk_toolbar_set_orientation().
2777 * Return value: the orientation
2780 gtk_toolbar_get_orientation (GtkToolbar *toolbar)
2782 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
2784 return toolbar->orientation;
2788 * gtk_toolbar_set_style:
2789 * @toolbar: a #GtkToolbar.
2790 * @style: the new style for @toolbar.
2792 * Alters the view of @toolbar to display either icons only, text only, or both.
2795 gtk_toolbar_set_style (GtkToolbar *toolbar,
2796 GtkToolbarStyle style)
2798 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2800 toolbar->style_set = TRUE;
2801 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2805 * gtk_toolbar_get_style:
2806 * @toolbar: a #GtkToolbar
2808 * Retrieves whether the toolbar has text, icons, or both . See
2809 * gtk_toolbar_set_style().
2811 * Return value: the current style of @toolbar
2814 gtk_toolbar_get_style (GtkToolbar *toolbar)
2816 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_TOOLBAR_STYLE);
2818 return toolbar->style;
2822 * gtk_toolbar_unset_style:
2823 * @toolbar: a #GtkToolbar
2825 * Unsets a toolbar style set with gtk_toolbar_set_style(), so that
2826 * user preferences will be used to determine the toolbar style.
2829 gtk_toolbar_unset_style (GtkToolbar *toolbar)
2831 GtkToolbarStyle style;
2833 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2835 if (toolbar->style_set)
2837 GtkSettings *settings = toolbar_get_settings (toolbar);
2840 g_object_get (settings,
2841 "gtk-toolbar-style", &style,
2844 style = DEFAULT_TOOLBAR_STYLE;
2846 if (style != toolbar->style)
2847 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2849 toolbar->style_set = FALSE;
2854 * gtk_toolbar_set_tooltips:
2855 * @toolbar: a #GtkToolbar.
2856 * @enable: set to %FALSE to disable the tooltips, or %TRUE to enable them.
2858 * Sets if the tooltips of a toolbar should be active or not.
2861 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
2864 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2867 gtk_tooltips_enable (toolbar->tooltips);
2869 gtk_tooltips_disable (toolbar->tooltips);
2871 g_object_notify (G_OBJECT (toolbar), "tooltips");
2875 * gtk_toolbar_get_tooltips:
2876 * @toolbar: a #GtkToolbar
2878 * Retrieves whether tooltips are enabled. See
2879 * gtk_toolbar_set_tooltips().
2881 * Return value: %TRUE if tooltips are enabled
2884 gtk_toolbar_get_tooltips (GtkToolbar *toolbar)
2886 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2888 return toolbar->tooltips->enabled;
2892 * gtk_toolbar_get_n_items:
2893 * @toolbar: a #GtkToolbar
2895 * Returns the number of items on the toolbar.
2897 * Return value: the number of items on the toolbar
2902 gtk_toolbar_get_n_items (GtkToolbar *toolbar)
2904 GtkToolbarPrivate *priv;
2906 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2908 if (!gtk_toolbar_check_new_api (toolbar))
2911 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2913 return physical_to_logical (toolbar, g_list_length (priv->content));
2917 * gtk_toolbar_get_nth_item:
2918 * @toolbar: a #GtkToolbar
2919 * @n: A position on the toolbar
2921 * Returns the @n<!-- -->'th item on @toolbar, or %NULL if the
2922 * toolbar does not contain an @n<!-- -->'th item.
2924 * Return value: The @n<!-- -->'th #GtkToolItem on @toolbar, or %NULL if there
2925 * isn't an @n<!-- -->'th item.
2930 gtk_toolbar_get_nth_item (GtkToolbar *toolbar,
2933 GtkToolbarPrivate *priv;
2934 ToolbarContent *content;
2937 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
2939 if (!gtk_toolbar_check_new_api (toolbar))
2942 n_items = gtk_toolbar_get_n_items (toolbar);
2944 if (n < 0 || n >= n_items)
2947 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2949 content = g_list_nth_data (priv->content, logical_to_physical (toolbar, n));
2952 g_assert (!toolbar_content_is_placeholder (content));
2954 return GTK_TOOL_ITEM (toolbar_content_get_widget (content));
2958 * gtk_toolbar_get_icon_size:
2959 * @toolbar: a #GtkToolbar
2961 * Retrieves the icon size fo the toolbar. See gtk_toolbar_set_icon_size().
2963 * Return value: the current icon size for the icons on the toolbar.
2966 gtk_toolbar_get_icon_size (GtkToolbar *toolbar)
2968 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_ICON_SIZE);
2970 return toolbar->icon_size;
2974 * gtk_toolbar_get_relief_style:
2975 * @toolbar: a #GtkToolbar
2977 * Returns the relief style of buttons on @toolbar. See
2978 * gtk_button_set_relief().
2980 * Return value: The relief style of buttons on @toolbar.
2985 gtk_toolbar_get_relief_style (GtkToolbar *toolbar)
2987 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_RELIEF_NONE);
2989 return get_button_relief (toolbar);
2993 * gtk_toolbar_set_show_arrow:
2994 * @toolbar: a #GtkToolbar
2995 * @show_arrow: Whether to show an overflow menu
2997 * Sets whether to show an overflow menu when
2998 * @toolbar doesn't have room for all items on it. If %TRUE,
2999 * items that there are not room are available through an
3005 gtk_toolbar_set_show_arrow (GtkToolbar *toolbar,
3006 gboolean show_arrow)
3008 GtkToolbarPrivate *priv;
3010 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3012 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3013 show_arrow = show_arrow != FALSE;
3015 if (priv->show_arrow != show_arrow)
3017 priv->show_arrow = show_arrow;
3019 if (!priv->show_arrow)
3020 gtk_widget_hide (priv->arrow_button);
3022 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3023 g_object_notify (G_OBJECT (toolbar), "show-arrow");
3028 * gtk_toolbar_get_show_arrow:
3029 * @toolbar: a #GtkToolbar
3031 * Returns whether the toolbar has an overflow menu.
3032 * See gtk_toolbar_set_show_arrow().
3034 * Return value: %TRUE if the toolbar has an overflow menu.
3039 gtk_toolbar_get_show_arrow (GtkToolbar *toolbar)
3041 GtkToolbarPrivate *priv;
3043 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
3045 if (!gtk_toolbar_check_new_api (toolbar))
3048 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3050 return priv->show_arrow;
3054 * gtk_toolbar_get_drop_index:
3055 * @toolbar: a #GtkToolbar
3056 * @x: x coordinate of a point on the toolbar
3057 * @y: y coordinate of a point on the toolbar
3059 * Returns the position corresponding to the indicated point on
3060 * @toolbar. This is useful when dragging items to the toolbar:
3061 * this function returns the position a new item should be
3064 * @x and @y are in @toolbar coordinates.
3066 * Return value: The position corresponding to the point (@x, @y) on the toolbar.
3071 gtk_toolbar_get_drop_index (GtkToolbar *toolbar,
3075 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
3077 if (!gtk_toolbar_check_new_api (toolbar))
3080 return physical_to_logical (toolbar, find_drop_index (toolbar, x, y));
3084 gtk_toolbar_finalize (GObject *object)
3087 GtkToolbar *toolbar = GTK_TOOLBAR (object);
3088 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3090 if (toolbar->tooltips)
3091 g_object_unref (toolbar->tooltips);
3093 if (priv->arrow_button)
3094 gtk_widget_unparent (priv->arrow_button);
3096 for (list = priv->content; list != NULL; list = list->next)
3098 ToolbarContent *content = list->data;
3100 toolbar_content_free (content);
3103 g_list_free (priv->content);
3104 g_list_free (toolbar->children);
3106 g_timer_destroy (priv->timer);
3109 gtk_widget_destroy (GTK_WIDGET (priv->menu));
3112 g_source_remove (priv->idle_id);
3114 G_OBJECT_CLASS (parent_class)->finalize (object);
3122 * gtk_toolbar_set_icon_size:
3123 * @toolbar: A #GtkToolbar
3124 * @icon_size: The #GtkIconSize that stock icons in the toolbar shall have.
3126 * This function sets the size of stock icons in the toolbar. You
3127 * can call it both before you add the icons and after they've been
3128 * added. The size you set will override user preferences for the default
3131 * Deprecated: Applications should respect the user preferences for
3132 * the size of icons in toolbars.
3135 gtk_toolbar_set_icon_size (GtkToolbar *toolbar,
3136 GtkIconSize icon_size)
3138 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3140 toolbar->icon_size_set = TRUE;
3142 if (toolbar->icon_size == icon_size)
3145 toolbar->icon_size = icon_size;
3147 gtk_toolbar_reconfigured (toolbar);
3149 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3153 * gtk_toolbar_unset_icon_size:
3154 * @toolbar: a #GtkToolbar
3156 * Unsets toolbar icon size set with gtk_toolbar_set_icon_size(), so that
3157 * user preferences will be used to determine the icon size.
3160 gtk_toolbar_unset_icon_size (GtkToolbar *toolbar)
3164 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3166 if (toolbar->icon_size_set)
3168 GtkSettings *settings = toolbar_get_settings (toolbar);
3172 g_object_get (settings,
3173 "gtk-toolbar-icon-size", &size,
3177 size = DEFAULT_ICON_SIZE;
3179 if (size != toolbar->icon_size)
3180 gtk_toolbar_set_icon_size (toolbar, size);
3182 toolbar->icon_size_set = FALSE;
3187 * gtk_toolbar_append_item:
3188 * @toolbar: a #GtkToolbar.
3189 * @text: give your toolbar button a label.
3190 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3191 * @tooltip_private_text: use with #GtkTipsQuery.
3192 * @icon: a #GtkWidget that should be used as the button's icon.
3193 * @callback: the function to be executed when the button is pressed.
3194 * @user_data: a pointer to any data you wish to be passed to the callback.
3196 * Inserts a new item into the toolbar. You must specify the position
3197 * in the toolbar where it will be inserted.
3199 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3200 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3202 * Return value: the new toolbar item as a #GtkWidget.
3205 gtk_toolbar_append_item (GtkToolbar *toolbar,
3207 const char *tooltip_text,
3208 const char *tooltip_private_text,
3210 GtkSignalFunc callback,
3213 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3215 tooltip_text, tooltip_private_text,
3216 icon, callback, user_data,
3217 toolbar->num_children);
3221 * gtk_toolbar_prepend_item:
3222 * @toolbar: a #GtkToolbar.
3223 * @text: give your toolbar button a label.
3224 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3225 * @tooltip_private_text: use with #GtkTipsQuery.
3226 * @icon: a #GtkWidget that should be used as the button's icon.
3227 * @callback: the function to be executed when the button is pressed.
3228 * @user_data: a pointer to any data you wish to be passed to the callback.
3230 * Adds a new button to the beginning (top or left edges) of the given toolbar.
3232 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3233 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3235 * Return value: the new toolbar item as a #GtkWidget.
3238 gtk_toolbar_prepend_item (GtkToolbar *toolbar,
3240 const char *tooltip_text,
3241 const char *tooltip_private_text,
3243 GtkSignalFunc callback,
3246 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3248 tooltip_text, tooltip_private_text,
3249 icon, callback, user_data,
3254 * gtk_toolbar_insert_item:
3255 * @toolbar: a #GtkToolbar.
3256 * @text: give your toolbar button a label.
3257 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3258 * @tooltip_private_text: use with #GtkTipsQuery.
3259 * @icon: a #GtkWidget that should be used as the button's icon.
3260 * @callback: the function to be executed when the button is pressed.
3261 * @user_data: a pointer to any data you wish to be passed to the callback.
3262 * @position: the number of widgets to insert this item after.
3264 * Inserts a new item into the toolbar. You must specify the position in the
3265 * toolbar where it will be inserted.
3267 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3268 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3270 * Return value: the new toolbar item as a #GtkWidget.
3273 gtk_toolbar_insert_item (GtkToolbar *toolbar,
3275 const char *tooltip_text,
3276 const char *tooltip_private_text,
3278 GtkSignalFunc callback,
3282 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3284 tooltip_text, tooltip_private_text,
3285 icon, callback, user_data,
3290 * gtk_toolbar_insert_stock:
3291 * @toolbar: A #GtkToolbar
3292 * @stock_id: The id of the stock item you want to insert
3293 * @tooltip_text: The text in the tooltip of the toolbar button
3294 * @tooltip_private_text: The private text of the tooltip
3295 * @callback: The callback called when the toolbar button is clicked.
3296 * @user_data: user data passed to callback
3297 * @position: The position the button shall be inserted at.
3298 * -1 means at the end.
3300 * Inserts a stock item at the specified position of the toolbar. If
3301 * @stock_id is not a known stock item ID, it's inserted verbatim,
3302 * except that underscores used to mark mnemonics are removed.
3304 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3305 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3307 * Returns: the inserted widget
3310 gtk_toolbar_insert_stock (GtkToolbar *toolbar,
3311 const gchar *stock_id,
3312 const char *tooltip_text,
3313 const char *tooltip_private_text,
3314 GtkSignalFunc callback,
3318 return internal_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3320 tooltip_text, tooltip_private_text,
3321 NULL, callback, user_data,
3326 * gtk_toolbar_append_space:
3327 * @toolbar: a #GtkToolbar.
3329 * Adds a new space to the end of the toolbar.
3332 gtk_toolbar_append_space (GtkToolbar *toolbar)
3334 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3338 toolbar->num_children);
3342 * gtk_toolbar_prepend_space:
3343 * @toolbar: a #GtkToolbar.
3345 * Adds a new space to the beginning of the toolbar.
3348 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
3350 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3358 * gtk_toolbar_insert_space:
3359 * @toolbar: a #GtkToolbar
3360 * @position: the number of widgets after which a space should be inserted.
3362 * Inserts a new space in the toolbar at the specified position.
3365 gtk_toolbar_insert_space (GtkToolbar *toolbar,
3368 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3376 * gtk_toolbar_remove_space:
3377 * @toolbar: a #GtkToolbar.
3378 * @position: the index of the space to remove.
3380 * Removes a space from the specified position.
3383 gtk_toolbar_remove_space (GtkToolbar *toolbar,
3386 GtkToolbarPrivate *priv;
3387 ToolbarContent *content;
3389 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3391 if (!gtk_toolbar_check_old_api (toolbar))
3394 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3396 content = g_list_nth_data (priv->content, position);
3400 g_warning ("Toolbar position %d doesn't exist", position);
3404 if (!toolbar_content_is_separator (content))
3406 g_warning ("Toolbar position %d is not a space", position);
3410 toolbar_content_remove (content, toolbar);
3411 toolbar_content_free (content);
3415 * gtk_toolbar_append_widget:
3416 * @toolbar: a #GtkToolbar.
3417 * @widget: a #GtkWidget to add to the toolbar.
3418 * @tooltip_text: the element's tooltip.
3419 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3421 * Adds a widget to the end of the given toolbar.
3424 gtk_toolbar_append_widget (GtkToolbar *toolbar,
3426 const gchar *tooltip_text,
3427 const gchar *tooltip_private_text)
3429 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3431 tooltip_text, tooltip_private_text,
3433 toolbar->num_children);
3437 * gtk_toolbar_prepend_widget:
3438 * @toolbar: a #GtkToolbar.
3439 * @widget: a #GtkWidget to add to the toolbar.
3440 * @tooltip_text: the element's tooltip.
3441 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3443 * Adds a widget to the beginning of the given toolbar.
3446 gtk_toolbar_prepend_widget (GtkToolbar *toolbar,
3448 const gchar *tooltip_text,
3449 const gchar *tooltip_private_text)
3451 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3453 tooltip_text, tooltip_private_text,
3459 * gtk_toolbar_insert_widget:
3460 * @toolbar: a #GtkToolbar.
3461 * @widget: a #GtkWidget to add to the toolbar.
3462 * @tooltip_text: the element's tooltip.
3463 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3464 * @position: the number of widgets to insert this widget after.
3466 * Inserts a widget in the toolbar at the given position.
3469 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
3471 const char *tooltip_text,
3472 const char *tooltip_private_text,
3475 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3477 tooltip_text, tooltip_private_text,
3483 * gtk_toolbar_append_element:
3484 * @toolbar: a #GtkToolbar.
3485 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
3486 * @widget: a #GtkWidget, or %NULL.
3487 * @text: the element's label.
3488 * @tooltip_text: the element's tooltip.
3489 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3490 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3491 * @callback: the function to be executed when the button is pressed.
3492 * @user_data: any data you wish to pass to the callback.
3494 * Adds a new element to the end of a toolbar.
3496 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3497 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3498 * the radio group for the new element. In all other cases, @widget must
3501 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3502 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3504 * Return value: the new toolbar element as a #GtkWidget.
3507 gtk_toolbar_append_element (GtkToolbar *toolbar,
3508 GtkToolbarChildType type,
3511 const char *tooltip_text,
3512 const char *tooltip_private_text,
3514 GtkSignalFunc callback,
3517 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3518 tooltip_text, tooltip_private_text,
3519 icon, callback, user_data,
3520 toolbar->num_children);
3524 * gtk_toolbar_prepend_element:
3525 * @toolbar: a #GtkToolbar.
3526 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
3527 * @widget: a #GtkWidget, or %NULL
3528 * @text: the element's label.
3529 * @tooltip_text: the element's tooltip.
3530 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3531 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3532 * @callback: the function to be executed when the button is pressed.
3533 * @user_data: any data you wish to pass to the callback.
3535 * Adds a new element to the beginning of a toolbar.
3537 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3538 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3539 * the radio group for the new element. In all other cases, @widget must
3542 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3543 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3545 * Return value: the new toolbar element as a #GtkWidget.
3548 gtk_toolbar_prepend_element (GtkToolbar *toolbar,
3549 GtkToolbarChildType type,
3552 const char *tooltip_text,
3553 const char *tooltip_private_text,
3555 GtkSignalFunc callback,
3558 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3559 tooltip_text, tooltip_private_text,
3560 icon, callback, user_data, 0);
3564 * gtk_toolbar_insert_element:
3565 * @toolbar: a #GtkToolbar.
3566 * @type: a value of type #GtkToolbarChildType that determines what @widget
3568 * @widget: a #GtkWidget, or %NULL.
3569 * @text: the element's label.
3570 * @tooltip_text: the element's tooltip.
3571 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3572 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3573 * @callback: the function to be executed when the button is pressed.
3574 * @user_data: any data you wish to pass to the callback.
3575 * @position: the number of widgets to insert this element after.
3577 * Inserts a new element in the toolbar at the given position.
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_insert_element (GtkToolbar *toolbar,
3591 GtkToolbarChildType type,
3594 const char *tooltip_text,
3595 const char *tooltip_private_text,
3597 GtkSignalFunc callback,
3601 return internal_insert_element (toolbar, type, widget, text,
3602 tooltip_text, tooltip_private_text,
3603 icon, callback, user_data, position, FALSE);
3607 set_child_packing_and_visibility(GtkToolbar *toolbar,
3608 GtkToolbarChild *child)
3613 box = gtk_bin_get_child (GTK_BIN (child->widget));
3615 g_return_if_fail (GTK_IS_BOX (box));
3619 expand = (toolbar->style != GTK_TOOLBAR_BOTH);
3621 gtk_box_set_child_packing (GTK_BOX (box), child->label,
3622 expand, expand, 0, GTK_PACK_END);
3624 if (toolbar->style != GTK_TOOLBAR_ICONS)
3625 gtk_widget_show (child->label);
3627 gtk_widget_hide (child->label);
3632 expand = (toolbar->style != GTK_TOOLBAR_BOTH_HORIZ);
3634 gtk_box_set_child_packing (GTK_BOX (box), child->icon,
3635 expand, expand, 0, GTK_PACK_END);
3637 if (toolbar->style != GTK_TOOLBAR_TEXT)
3638 gtk_widget_show (child->icon);
3640 gtk_widget_hide (child->icon);
3645 internal_insert_element (GtkToolbar *toolbar,
3646 GtkToolbarChildType type,
3649 const char *tooltip_text,
3650 const char *tooltip_private_text,
3652 GtkSignalFunc callback,
3658 ToolbarContent *content;
3659 GtkToolbarPrivate *priv;
3660 char *free_me = NULL;
3661 gboolean is_button = FALSE;
3663 GtkWidget *child_widget;
3664 GtkWidget *child_label;
3665 GtkWidget *child_icon;
3667 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
3668 if (type == GTK_TOOLBAR_CHILD_WIDGET)
3669 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3670 else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON)
3671 g_return_val_if_fail (widget == NULL, NULL);
3672 if (GTK_IS_TOOL_ITEM (widget))
3673 g_warning (MIXED_API_WARNING);
3675 if (!gtk_toolbar_check_old_api (toolbar))
3678 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3680 child_widget = NULL;
3686 case GTK_TOOLBAR_CHILD_SPACE:
3689 case GTK_TOOLBAR_CHILD_WIDGET:
3690 child_widget = widget;
3693 case GTK_TOOLBAR_CHILD_BUTTON:
3694 case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
3695 case GTK_TOOLBAR_CHILD_RADIOBUTTON:
3697 if (type == GTK_TOOLBAR_CHILD_BUTTON)
3699 child_widget = gtk_button_new ();
3701 else if (type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
3703 child_widget = gtk_toggle_button_new ();
3704 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child_widget), FALSE);
3706 else /* type == GTK_TOOLBAR_CHILD_RADIOBUTTON */
3708 GSList *group = NULL;
3711 group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
3713 child_widget = gtk_radio_button_new (group);
3714 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child_widget), FALSE);
3717 gtk_button_set_relief (GTK_BUTTON (child_widget), get_button_relief (toolbar));
3718 gtk_button_set_focus_on_click (GTK_BUTTON (child_widget), FALSE);
3722 g_signal_connect (child_widget, "clicked",
3723 callback, user_data);
3726 if (toolbar->style == GTK_TOOLBAR_BOTH_HORIZ)
3727 box = gtk_hbox_new (FALSE, 0);
3729 box = gtk_vbox_new (FALSE, 0);
3731 gtk_container_add (GTK_CONTAINER (child_widget), box);
3732 gtk_widget_show (box);
3734 if (text && use_stock)
3736 GtkStockItem stock_item;
3737 if (gtk_stock_lookup (text, &stock_item))
3740 icon = gtk_image_new_from_stock (text, toolbar->icon_size);
3742 text = free_me = _gtk_toolbar_elide_underscores (stock_item.label);
3748 child_label = gtk_label_new (text);
3750 gtk_container_add (GTK_CONTAINER (box), child_label);
3755 child_icon = GTK_WIDGET (icon);
3756 gtk_container_add (GTK_CONTAINER (box), child_icon);
3759 gtk_widget_show (child_widget);
3763 g_assert_not_reached ();
3767 if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text)
3769 gtk_tooltips_set_tip (toolbar->tooltips, child_widget,
3770 tooltip_text, tooltip_private_text);
3773 content = toolbar_content_new_compatibility (toolbar, type, child_widget,
3774 child_icon, child_label, position);
3779 return child_widget;
3783 * ToolbarContent methods
3791 struct _ToolbarContent
3801 GtkAllocation start_allocation;
3802 GtkAllocation goal_allocation;
3803 guint is_placeholder : 1;
3804 guint disappearing : 1;
3805 TriState has_menu : 2;
3810 GtkToolbarChild child;
3811 GtkAllocation space_allocation;
3812 guint space_visible : 1;
3817 static ToolbarContent *
3818 toolbar_content_new_tool_item (GtkToolbar *toolbar,
3820 gboolean is_placeholder,
3823 ToolbarContent *content;
3824 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3826 content = g_new0 (ToolbarContent, 1);
3828 content->type = TOOL_ITEM;
3829 content->state = NOT_ALLOCATED;
3830 content->u.tool_item.item = item;
3831 content->u.tool_item.is_placeholder = is_placeholder;
3833 gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar));
3835 priv->content = g_list_insert (priv->content, content, pos);
3837 if (!is_placeholder)
3839 toolbar->num_children++;
3841 gtk_toolbar_stop_sliding (toolbar);
3844 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3845 priv->need_rebuild = TRUE;
3850 static ToolbarContent *
3851 toolbar_content_new_compatibility (GtkToolbar *toolbar,
3852 GtkToolbarChildType type,
3858 ToolbarContent *content;
3859 GtkToolbarChild *child;
3860 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3862 content = g_new0 (ToolbarContent, 1);
3864 child = &(content->u.compatibility.child);
3866 content->type = COMPATIBILITY;
3868 child->widget = widget;
3870 child->label = label;
3872 if (type != GTK_TOOLBAR_CHILD_SPACE)
3874 gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
3878 content->u.compatibility.space_visible = TRUE;
3879 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3882 if (type == GTK_TOOLBAR_CHILD_BUTTON ||
3883 type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
3884 type == GTK_TOOLBAR_CHILD_RADIOBUTTON)
3886 set_child_packing_and_visibility (toolbar, child);
3889 priv->content = g_list_insert (priv->content, content, pos);
3890 toolbar->children = g_list_insert (toolbar->children, child, pos);
3891 priv->need_rebuild = TRUE;
3893 toolbar->num_children++;
3899 toolbar_content_remove (ToolbarContent *content,
3900 GtkToolbar *toolbar)
3902 GtkToolbarChild *child;
3903 GtkToolbarPrivate *priv;
3905 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3907 switch (content->type)
3910 gtk_widget_unparent (GTK_WIDGET (content->u.tool_item.item));
3914 child = &(content->u.compatibility.child);
3916 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
3918 g_object_ref (child->widget);
3919 gtk_widget_unparent (child->widget);
3920 gtk_widget_destroy (child->widget);
3921 g_object_unref (child->widget);
3924 toolbar->children = g_list_remove (toolbar->children, child);
3928 priv->content = g_list_remove (priv->content, content);
3930 if (!toolbar_content_is_placeholder (content))
3931 toolbar->num_children--;
3933 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3934 priv->need_rebuild = TRUE;
3938 toolbar_content_free (ToolbarContent *content)
3944 calculate_max_homogeneous_pixels (GtkWidget *widget)
3946 PangoContext *context;
3947 PangoFontMetrics *metrics;
3950 context = gtk_widget_get_pango_context (widget);
3951 metrics = pango_context_get_metrics (context,
3952 widget->style->font_desc,
3953 pango_context_get_language (context));
3954 char_width = pango_font_metrics_get_approximate_char_width (metrics);
3955 pango_font_metrics_unref (metrics);
3957 return PANGO_PIXELS (MAX_HOMOGENEOUS_N_CHARS * char_width);
3961 toolbar_content_expose (ToolbarContent *content,
3962 GtkContainer *container,
3963 GdkEventExpose *expose)
3965 GtkToolbar *toolbar = GTK_TOOLBAR (container);
3966 GtkToolbarChild *child;
3967 GtkWidget *widget = NULL; /* quiet gcc */
3969 switch (content->type)
3972 if (!content->u.tool_item.is_placeholder)
3973 widget = GTK_WIDGET (content->u.tool_item.item);
3977 child = &(content->u.compatibility.child);
3979 if (child->type == GTK_TOOLBAR_CHILD_SPACE)
3981 if (get_space_style (toolbar) == GTK_TOOLBAR_SPACE_LINE &&
3982 content->u.compatibility.space_visible)
3984 _gtk_toolbar_paint_space_line (GTK_WIDGET (toolbar), toolbar,
3986 &content->u.compatibility.space_allocation);
3991 widget = child->widget;
3996 gtk_container_propagate_expose (container, widget, expose);
4000 toolbar_content_visible (ToolbarContent *content,
4001 GtkToolbar *toolbar)
4005 switch (content->type)
4008 item = content->u.tool_item.item;
4010 if (!GTK_WIDGET_VISIBLE (item))
4013 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL &&
4014 gtk_tool_item_get_visible_horizontal (item))
4019 if ((toolbar->orientation == GTK_ORIENTATION_VERTICAL &&
4020 gtk_tool_item_get_visible_vertical (item)))
4029 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4030 return GTK_WIDGET_VISIBLE (content->u.compatibility.child.widget);
4036 g_assert_not_reached ();
4041 toolbar_content_size_request (ToolbarContent *content,
4042 GtkToolbar *toolbar,
4043 GtkRequisition *requisition)
4047 switch (content->type)
4050 gtk_widget_size_request (GTK_WIDGET (content->u.tool_item.item),
4052 if (content->u.tool_item.is_placeholder &&
4053 content->u.tool_item.disappearing)
4055 requisition->width = 0;
4056 requisition->height = 0;
4061 space_size = get_space_size (toolbar);
4063 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4065 gtk_widget_size_request (content->u.compatibility.child.widget,
4070 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
4072 requisition->width = space_size;
4073 requisition->height = 0;
4077 requisition->height = space_size;
4078 requisition->width = 0;
4087 toolbar_content_is_homogeneous (ToolbarContent *content,
4088 GtkToolbar *toolbar)
4090 gboolean result = FALSE; /* quiet gcc */
4091 GtkRequisition requisition;
4092 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4094 if (priv->max_homogeneous_pixels < 0)
4096 priv->max_homogeneous_pixels =
4097 calculate_max_homogeneous_pixels (GTK_WIDGET (toolbar));
4100 toolbar_content_size_request (content, toolbar, &requisition);
4102 if (requisition.width > priv->max_homogeneous_pixels)
4105 switch (content->type)
4108 result = gtk_tool_item_get_homogeneous (content->u.tool_item.item) &&
4109 !GTK_IS_SEPARATOR_TOOL_ITEM (content->u.tool_item.item);
4111 if (gtk_tool_item_get_is_important (content->u.tool_item.item) &&
4112 toolbar->style == GTK_TOOLBAR_BOTH_HORIZ &&
4113 toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
4120 if (content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_BUTTON ||
4121 content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4122 content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4137 toolbar_content_is_placeholder (ToolbarContent *content)
4139 if (content->type == TOOL_ITEM && content->u.tool_item.is_placeholder)
4146 toolbar_content_disappearing (ToolbarContent *content)
4148 if (content->type == TOOL_ITEM && content->u.tool_item.disappearing)
4155 toolbar_content_get_state (ToolbarContent *content)
4157 return content->state;
4161 toolbar_content_child_visible (ToolbarContent *content)
4163 switch (content->type)
4166 return GTK_WIDGET_CHILD_VISIBLE (content->u.tool_item.item);
4170 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4172 return GTK_WIDGET_CHILD_VISIBLE (content->u.compatibility.child.widget);
4176 return content->u.compatibility.space_visible;
4181 return FALSE; /* quiet gcc */
4185 toolbar_content_get_goal_allocation (ToolbarContent *content,
4186 GtkAllocation *allocation)
4188 switch (content->type)
4191 *allocation = content->u.tool_item.goal_allocation;
4195 /* Goal allocations are only relevant when we are
4196 * using the new API, so we should never get here
4198 g_assert_not_reached ();
4204 toolbar_content_get_allocation (ToolbarContent *content,
4205 GtkAllocation *allocation)
4207 GtkToolbarChild *child;
4209 switch (content->type)
4212 *allocation = GTK_WIDGET (content->u.tool_item.item)->allocation;
4216 child = &(content->u.compatibility.child);
4218 if (child->type == GTK_TOOLBAR_CHILD_SPACE)
4219 *allocation = content->u.compatibility.space_allocation;
4221 *allocation = child->widget->allocation;
4227 toolbar_content_set_start_allocation (ToolbarContent *content,
4228 GtkAllocation *allocation)
4230 switch (content->type)
4233 content->u.tool_item.start_allocation = *allocation;
4237 /* start_allocation is only relevant when using the new API */
4238 g_assert_not_reached ();
4244 toolbar_content_get_expand (ToolbarContent *content)
4246 if (content->type == TOOL_ITEM &&
4247 gtk_tool_item_get_expand (content->u.tool_item.item) &&
4248 !content->u.tool_item.disappearing)
4257 toolbar_content_set_goal_allocation (ToolbarContent *content,
4258 GtkAllocation *allocation)
4260 switch (content->type)
4263 content->u.tool_item.goal_allocation = *allocation;
4267 /* Only relevant when using new API */
4268 g_assert_not_reached ();
4274 toolbar_content_set_child_visible (ToolbarContent *content,
4275 GtkToolbar *toolbar,
4278 GtkToolbarChild *child;
4280 switch (content->type)
4283 gtk_widget_set_child_visible (GTK_WIDGET (content->u.tool_item.item),
4288 child = &(content->u.compatibility.child);
4290 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
4292 gtk_widget_set_child_visible (child->widget, visible);
4296 if (content->u.compatibility.space_visible != visible)
4298 content->u.compatibility.space_visible = visible;
4299 gtk_widget_queue_draw (GTK_WIDGET (toolbar));
4307 toolbar_content_get_start_allocation (ToolbarContent *content,
4308 GtkAllocation *start_allocation)
4310 switch (content->type)
4313 *start_allocation = content->u.tool_item.start_allocation;
4317 /* Only relevant for new API */
4318 g_assert_not_reached ();
4324 toolbar_content_size_allocate (ToolbarContent *content,
4325 GtkAllocation *allocation)
4327 switch (content->type)
4330 gtk_widget_size_allocate (GTK_WIDGET (content->u.tool_item.item),
4335 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4337 gtk_widget_size_allocate (content->u.compatibility.child.widget,
4342 content->u.compatibility.space_allocation = *allocation;
4349 toolbar_content_set_state (ToolbarContent *content,
4352 content->state = state;
4356 toolbar_content_get_widget (ToolbarContent *content)
4358 GtkToolbarChild *child;
4360 switch (content->type)
4363 return GTK_WIDGET (content->u.tool_item.item);
4367 child = &(content->u.compatibility.child);
4368 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
4369 return child->widget;
4379 toolbar_content_set_disappearing (ToolbarContent *content,
4380 gboolean disappearing)
4382 switch (content->type)
4385 content->u.tool_item.disappearing = disappearing;
4389 /* Only relevant for new API */
4390 g_assert_not_reached ();
4396 toolbar_content_set_size_request (ToolbarContent *content,
4400 switch (content->type)
4403 gtk_widget_set_size_request (GTK_WIDGET (content->u.tool_item.item),
4408 /* Setting size requests only happens with sliding,
4409 * so not relevant here
4411 g_assert_not_reached ();
4417 toolbar_child_reconfigure (GtkToolbar *toolbar,
4418 GtkToolbarChild *child)
4422 GtkToolbarStyle style;
4423 GtkIconSize icon_size;
4424 GtkReliefStyle relief;
4427 style = gtk_toolbar_get_style (toolbar);
4428 icon_size = gtk_toolbar_get_icon_size (toolbar);
4429 relief = gtk_toolbar_get_relief_style (toolbar);
4432 if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4433 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4434 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4436 box = gtk_bin_get_child (GTK_BIN (child->widget));
4438 if (style == GTK_TOOLBAR_BOTH && GTK_IS_HBOX (box))
4442 vbox = gtk_vbox_new (FALSE, 0);
4445 gtk_widget_reparent (child->label, vbox);
4447 gtk_widget_reparent (child->icon, vbox);
4449 gtk_widget_destroy (box);
4450 gtk_container_add (GTK_CONTAINER (child->widget), vbox);
4452 gtk_widget_show (vbox);
4454 else if (style == GTK_TOOLBAR_BOTH_HORIZ && GTK_IS_VBOX (box))
4458 hbox = gtk_hbox_new (FALSE, 0);
4461 gtk_widget_reparent (child->label, hbox);
4463 gtk_widget_reparent (child->icon, hbox);
4465 gtk_widget_destroy (box);
4466 gtk_container_add (GTK_CONTAINER (child->widget), hbox);
4468 gtk_widget_show (hbox);
4471 set_child_packing_and_visibility (toolbar, child);
4476 if ((child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4477 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
4478 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON) &&
4479 GTK_IS_IMAGE (child->icon))
4481 image = GTK_IMAGE (child->icon);
4482 if (gtk_image_get_storage_type (image) == GTK_IMAGE_STOCK)
4484 gtk_image_get_stock (image, &stock_id, NULL);
4485 stock_id = g_strdup (stock_id);
4486 gtk_image_set_from_stock (image,
4494 if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4495 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4496 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4498 gtk_button_set_relief (GTK_BUTTON (child->widget), relief);
4503 toolbar_content_toolbar_reconfigured (ToolbarContent *content,
4504 GtkToolbar *toolbar)
4506 switch (content->type)
4509 _gtk_tool_item_toolbar_reconfigured (content->u.tool_item.item);
4513 toolbar_child_reconfigure (toolbar, &(content->u.compatibility.child));
4519 toolbar_content_retrieve_menu_item (ToolbarContent *content)
4521 if (content->type == TOOL_ITEM)
4522 return gtk_tool_item_retrieve_proxy_menu_item (content->u.tool_item.item);
4524 /* FIXME - we might actually be able to do something meaningful here */
4529 toolbar_content_has_proxy_menu_item (ToolbarContent *content)
4531 if (content->type == TOOL_ITEM)
4533 GtkWidget *menu_item;
4535 if (content->u.tool_item.has_menu == YES)
4537 else if (content->u.tool_item.has_menu == NO)
4540 menu_item = toolbar_content_retrieve_menu_item (content);
4542 content->u.tool_item.has_menu = menu_item? YES : NO;
4544 return menu_item != NULL;
4553 toolbar_content_set_unknown_menu_status (ToolbarContent *content)
4555 if (content->type == TOOL_ITEM)
4556 content->u.tool_item.has_menu = UNKNOWN;
4560 toolbar_content_is_separator (ToolbarContent *content)
4562 GtkToolbarChild *child;
4564 switch (content->type)
4567 return GTK_IS_SEPARATOR_TOOL_ITEM (content->u.tool_item.item);
4571 child = &(content->u.compatibility.child);
4572 return (child->type == GTK_TOOLBAR_CHILD_SPACE);
4580 toolbar_content_set_expand (ToolbarContent *content,
4583 if (content->type == TOOL_ITEM)
4584 gtk_tool_item_set_expand (content->u.tool_item.item, expand);
4588 ignore_show_and_hide_all (ToolbarContent *content)
4590 if (content->type == COMPATIBILITY)
4592 GtkToolbarChildType type = content->u.compatibility.child.type;
4594 if (type == GTK_TOOLBAR_CHILD_BUTTON ||
4595 type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
4596 type == GTK_TOOLBAR_CHILD_RADIOBUTTON)
4606 toolbar_content_show_all (ToolbarContent *content)
4610 if (ignore_show_and_hide_all (content))
4613 widget = toolbar_content_get_widget (content);
4615 gtk_widget_show_all (widget);
4619 toolbar_content_hide_all (ToolbarContent *content)
4623 if (ignore_show_and_hide_all (content))
4626 widget = toolbar_content_get_widget (content);
4628 gtk_widget_hide_all (widget);
4635 get_space_size (GtkToolbar *toolbar)
4637 gint space_size = DEFAULT_SPACE_SIZE;
4641 gtk_widget_style_get (GTK_WIDGET (toolbar),
4642 "space-size", &space_size,
4649 static GtkToolbarSpaceStyle
4650 get_space_style (GtkToolbar *toolbar)
4652 GtkToolbarSpaceStyle space_style = DEFAULT_SPACE_STYLE;
4656 gtk_widget_style_get (GTK_WIDGET (toolbar),
4657 "space-style", &space_style,
4664 static GtkReliefStyle
4665 get_button_relief (GtkToolbar *toolbar)
4667 GtkReliefStyle button_relief = GTK_RELIEF_NORMAL;
4669 gtk_widget_ensure_style (GTK_WIDGET (toolbar));
4671 gtk_widget_style_get (GTK_WIDGET (toolbar),
4672 "button-relief", &button_relief,
4675 return button_relief;
4679 get_internal_padding (GtkToolbar *toolbar)
4683 gtk_widget_style_get (GTK_WIDGET (toolbar),
4684 "internal-padding", &ipadding,
4690 static GtkShadowType
4691 get_shadow_type (GtkToolbar *toolbar)
4693 GtkShadowType shadow_type;
4695 gtk_widget_style_get (GTK_WIDGET (toolbar),
4696 "shadow-type", &shadow_type,
4706 gtk_toolbar_check_old_api (GtkToolbar *toolbar)
4708 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4710 if (priv->api_mode == NEW_API)
4712 g_warning (MIXED_API_WARNING);
4716 priv->api_mode = OLD_API;
4721 gtk_toolbar_check_new_api (GtkToolbar *toolbar)
4723 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4725 if (priv->api_mode == OLD_API)
4727 g_warning (MIXED_API_WARNING);
4731 priv->api_mode = NEW_API;
4735 /* GTK+ internal methods */
4738 _gtk_toolbar_get_default_space_size (void)
4740 return DEFAULT_SPACE_SIZE;
4744 _gtk_toolbar_paint_space_line (GtkWidget *widget,
4745 GtkToolbar *toolbar,
4747 GtkAllocation *allocation)
4749 const double start_fraction = (SPACE_LINE_START / SPACE_LINE_DIVISION);
4750 const double end_fraction = (SPACE_LINE_END / SPACE_LINE_DIVISION);
4752 GtkToolbarSpaceStyle space_style;
4753 GtkOrientation orientation;
4755 g_return_if_fail (GTK_IS_WIDGET (widget));
4757 space_style = toolbar? get_space_style (toolbar) : DEFAULT_SPACE_STYLE;
4758 orientation = toolbar? toolbar->orientation : GTK_ORIENTATION_HORIZONTAL;
4760 if (orientation == GTK_ORIENTATION_HORIZONTAL)
4762 gtk_paint_vline (widget->style, widget->window,
4763 GTK_WIDGET_STATE (widget), area, widget,
4765 allocation->y + allocation->height * start_fraction,
4766 allocation->y + allocation->height * end_fraction,
4767 allocation->x + (allocation->width - widget->style->xthickness) / 2);
4771 gtk_paint_hline (widget->style, widget->window,
4772 GTK_WIDGET_STATE (widget), area, widget,
4774 allocation->x + allocation->width * start_fraction,
4775 allocation->x + allocation->width * end_fraction,
4776 allocation->y + (allocation->height - widget->style->ythickness) / 2);
4781 _gtk_toolbar_elide_underscores (const gchar *original)
4785 gboolean last_underscore;
4790 q = result = g_malloc (strlen (original) + 1);
4791 last_underscore = FALSE;
4793 for (p = original; *p; p++)
4795 if (!last_underscore && *p == '_')
4796 last_underscore = TRUE;
4799 last_underscore = FALSE;
4810 _gtk_toolbar_rebuild_menu (GtkToolbar *toolbar)
4812 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4815 priv->need_rebuild = TRUE;
4817 for (list = priv->content; list != NULL; list = list->next)
4819 ToolbarContent *content = list->data;
4821 toolbar_content_set_unknown_menu_status (content);
4824 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
4827 #define __GTK_TOOLBAR_C__
4828 #include "gtkaliasdef.c"