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;
2542 gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y);
2543 gtk_widget_size_request (priv->arrow_button, &req);
2544 gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
2546 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
2548 *y += priv->arrow_button->allocation.height;
2549 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2550 *x += priv->arrow_button->allocation.width - req.width;
2552 *x += req.width - menu_req.width;
2556 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2557 *x += priv->arrow_button->allocation.width;
2559 *x -= menu_req.width;
2560 *y += priv->arrow_button->allocation.height - req.height;
2567 show_menu (GtkToolbar *toolbar,
2568 GdkEventButton *event)
2570 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2572 rebuild_menu (toolbar);
2574 gtk_widget_show_all (GTK_WIDGET (priv->menu));
2576 gtk_menu_popup (priv->menu, NULL, NULL,
2577 menu_position_func, toolbar,
2578 event? event->button : 0,
2579 event? event->time : gtk_get_current_event_time());
2583 gtk_toolbar_arrow_button_clicked (GtkWidget *button,
2584 GtkToolbar *toolbar)
2586 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2588 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->arrow_button)) &&
2589 (!priv->menu || !GTK_WIDGET_VISIBLE (priv->menu)))
2591 /* We only get here when the button is clicked with the keyboard,
2592 * because mouse button presses result in the menu being shown so
2593 * that priv->menu would be non-NULL and visible.
2595 show_menu (toolbar, NULL);
2596 gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menu), FALSE);
2601 gtk_toolbar_arrow_button_press (GtkWidget *button,
2602 GdkEventButton *event,
2603 GtkToolbar *toolbar)
2605 show_menu (toolbar, event);
2606 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2612 gtk_toolbar_button_press (GtkWidget *toolbar,
2613 GdkEventButton *event)
2615 if (event->button == 3)
2617 gboolean return_value;
2619 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2620 (int)event->x_root, (int)event->y_root, event->button,
2623 return return_value;
2630 gtk_toolbar_popup_menu (GtkWidget *toolbar)
2632 gboolean return_value;
2633 /* This function is the handler for the "popup menu" keybinding,
2634 * ie., it is called when the user presses Shift F10
2636 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2637 -1, -1, -1, &return_value);
2639 return return_value;
2645 * Creates a new toolbar.
2647 * Return Value: the newly-created toolbar.
2650 gtk_toolbar_new (void)
2652 GtkToolbar *toolbar;
2654 toolbar = g_object_new (GTK_TYPE_TOOLBAR, NULL);
2656 return GTK_WIDGET (toolbar);
2660 * gtk_toolbar_insert:
2661 * @toolbar: a #GtkToolbar
2662 * @item: a #GtkToolItem
2663 * @pos: the position of the new item
2665 * Insert a #GtkToolItem into the toolbar at position @pos. If @pos is
2666 * 0 the item is prepended to the start of the toolbar. If @pos is
2667 * negative, the item is appended to the end of the toolbar.
2672 gtk_toolbar_insert (GtkToolbar *toolbar,
2676 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2677 g_return_if_fail (GTK_IS_TOOL_ITEM (item));
2679 if (!gtk_toolbar_check_new_api (toolbar))
2683 pos = logical_to_physical (toolbar, pos);
2685 toolbar_content_new_tool_item (toolbar, item, FALSE, pos);
2689 * gtk_toolbar_get_item_index:
2690 * @toolbar: a #GtkToolbar
2691 * @item: a #GtkToolItem that is a child of @toolbar
2693 * Returns the position of @item on the toolbar, starting from 0.
2694 * It is an error if @item is not a child of the toolbar.
2696 * Return value: the position of item on the toolbar.
2701 gtk_toolbar_get_item_index (GtkToolbar *toolbar,
2704 GtkToolbarPrivate *priv;
2708 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2709 g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1);
2710 g_return_val_if_fail (GTK_WIDGET (item)->parent == GTK_WIDGET (toolbar), -1);
2712 if (!gtk_toolbar_check_new_api (toolbar))
2715 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2718 for (list = priv->content; list != NULL; list = list->next)
2720 ToolbarContent *content = list->data;
2723 widget = toolbar_content_get_widget (content);
2725 if (item == GTK_TOOL_ITEM (widget))
2731 return physical_to_logical (toolbar, n);
2735 * gtk_toolbar_set_orientation:
2736 * @toolbar: a #GtkToolbar.
2737 * @orientation: a new #GtkOrientation.
2739 * Sets whether a toolbar should appear horizontally or vertically.
2742 gtk_toolbar_set_orientation (GtkToolbar *toolbar,
2743 GtkOrientation orientation)
2745 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2747 g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0, orientation);
2751 * gtk_toolbar_get_orientation:
2752 * @toolbar: a #GtkToolbar
2754 * Retrieves the current orientation of the toolbar. See
2755 * gtk_toolbar_set_orientation().
2757 * Return value: the orientation
2760 gtk_toolbar_get_orientation (GtkToolbar *toolbar)
2762 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
2764 return toolbar->orientation;
2768 * gtk_toolbar_set_style:
2769 * @toolbar: a #GtkToolbar.
2770 * @style: the new style for @toolbar.
2772 * Alters the view of @toolbar to display either icons only, text only, or both.
2775 gtk_toolbar_set_style (GtkToolbar *toolbar,
2776 GtkToolbarStyle style)
2778 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2780 toolbar->style_set = TRUE;
2781 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2785 * gtk_toolbar_get_style:
2786 * @toolbar: a #GtkToolbar
2788 * Retrieves whether the toolbar has text, icons, or both . See
2789 * gtk_toolbar_set_style().
2791 * Return value: the current style of @toolbar
2794 gtk_toolbar_get_style (GtkToolbar *toolbar)
2796 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_TOOLBAR_STYLE);
2798 return toolbar->style;
2802 * gtk_toolbar_unset_style:
2803 * @toolbar: a #GtkToolbar
2805 * Unsets a toolbar style set with gtk_toolbar_set_style(), so that
2806 * user preferences will be used to determine the toolbar style.
2809 gtk_toolbar_unset_style (GtkToolbar *toolbar)
2811 GtkToolbarStyle style;
2813 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2815 if (toolbar->style_set)
2817 GtkSettings *settings = toolbar_get_settings (toolbar);
2820 g_object_get (settings,
2821 "gtk-toolbar-style", &style,
2824 style = DEFAULT_TOOLBAR_STYLE;
2826 if (style != toolbar->style)
2827 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2829 toolbar->style_set = FALSE;
2834 * gtk_toolbar_set_tooltips:
2835 * @toolbar: a #GtkToolbar.
2836 * @enable: set to %FALSE to disable the tooltips, or %TRUE to enable them.
2838 * Sets if the tooltips of a toolbar should be active or not.
2841 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
2844 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2847 gtk_tooltips_enable (toolbar->tooltips);
2849 gtk_tooltips_disable (toolbar->tooltips);
2851 g_object_notify (G_OBJECT (toolbar), "tooltips");
2855 * gtk_toolbar_get_tooltips:
2856 * @toolbar: a #GtkToolbar
2858 * Retrieves whether tooltips are enabled. See
2859 * gtk_toolbar_set_tooltips().
2861 * Return value: %TRUE if tooltips are enabled
2864 gtk_toolbar_get_tooltips (GtkToolbar *toolbar)
2866 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2868 return toolbar->tooltips->enabled;
2872 * gtk_toolbar_get_n_items:
2873 * @toolbar: a #GtkToolbar
2875 * Returns the number of items on the toolbar.
2877 * Return value: the number of items on the toolbar
2882 gtk_toolbar_get_n_items (GtkToolbar *toolbar)
2884 GtkToolbarPrivate *priv;
2886 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2888 if (!gtk_toolbar_check_new_api (toolbar))
2891 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2893 return physical_to_logical (toolbar, g_list_length (priv->content));
2897 * gtk_toolbar_get_nth_item:
2898 * @toolbar: a #GtkToolbar
2899 * @n: A position on the toolbar
2901 * Returns the @n<!-- -->'s item on @toolbar, or %NULL if the
2902 * toolbar does not contain an @n<!-- -->'th item.
2904 * Return value: The @n<!-- -->'th #GtkToolItem on @toolbar, or %NULL if there
2905 * isn't an @n<!-- -->th item.
2910 gtk_toolbar_get_nth_item (GtkToolbar *toolbar,
2913 GtkToolbarPrivate *priv;
2914 ToolbarContent *content;
2917 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
2919 if (!gtk_toolbar_check_new_api (toolbar))
2922 n_items = gtk_toolbar_get_n_items (toolbar);
2924 if (n < 0 || n >= n_items)
2927 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2929 content = g_list_nth_data (priv->content, logical_to_physical (toolbar, n));
2932 g_assert (!toolbar_content_is_placeholder (content));
2934 return GTK_TOOL_ITEM (toolbar_content_get_widget (content));
2938 * gtk_toolbar_get_icon_size:
2939 * @toolbar: a #GtkToolbar
2941 * Retrieves the icon size fo the toolbar. See gtk_toolbar_set_icon_size().
2943 * Return value: the current icon size for the icons on the toolbar.
2946 gtk_toolbar_get_icon_size (GtkToolbar *toolbar)
2948 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_ICON_SIZE);
2950 return toolbar->icon_size;
2954 * gtk_toolbar_get_relief_style:
2955 * @toolbar: a #GtkToolbar
2957 * Returns the relief style of buttons on @toolbar. See
2958 * gtk_button_set_relief().
2960 * Return value: The relief style of buttons on @toolbar.
2965 gtk_toolbar_get_relief_style (GtkToolbar *toolbar)
2967 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_RELIEF_NONE);
2969 return get_button_relief (toolbar);
2973 * gtk_toolbar_set_show_arrow:
2974 * @toolbar: a #GtkToolbar
2975 * @show_arrow: Whether to show an overflow menu
2977 * Sets whether to show an overflow menu when
2978 * @toolbar doesn't have room for all items on it. If %TRUE,
2979 * items that there are not room are available through an
2985 gtk_toolbar_set_show_arrow (GtkToolbar *toolbar,
2986 gboolean show_arrow)
2988 GtkToolbarPrivate *priv;
2990 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2992 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2993 show_arrow = show_arrow != FALSE;
2995 if (priv->show_arrow != show_arrow)
2997 priv->show_arrow = show_arrow;
2999 if (!priv->show_arrow)
3000 gtk_widget_hide (priv->arrow_button);
3002 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3003 g_object_notify (G_OBJECT (toolbar), "show-arrow");
3008 * gtk_toolbar_get_show_arrow:
3009 * @toolbar: a #GtkToolbar
3011 * Returns whether the toolbar has an overflow menu.
3012 * See gtk_toolbar_set_show_arrow()
3019 gtk_toolbar_get_show_arrow (GtkToolbar *toolbar)
3021 GtkToolbarPrivate *priv;
3023 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
3025 if (!gtk_toolbar_check_new_api (toolbar))
3028 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3030 return priv->show_arrow;
3034 * gtk_toolbar_get_drop_index:
3035 * @toolbar: a #GtkToolbar
3036 * @x: x coordinate of a point on the toolbar
3037 * @y: y coordinate of a point on the toolbar
3039 * Returns the position corresponding to the indicated point on
3040 * @toolbar. This is useful when dragging items to the toolbar:
3041 * this function returns the position a new item should be
3044 * @x and @y are in @toolbar coordinates.
3046 * Return value: The position corresponding to the point (@x, @y) on the toolbar.
3051 gtk_toolbar_get_drop_index (GtkToolbar *toolbar,
3055 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
3057 if (!gtk_toolbar_check_new_api (toolbar))
3060 return physical_to_logical (toolbar, find_drop_index (toolbar, x, y));
3064 gtk_toolbar_finalize (GObject *object)
3067 GtkToolbar *toolbar = GTK_TOOLBAR (object);
3068 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3070 if (toolbar->tooltips)
3071 g_object_unref (toolbar->tooltips);
3073 if (priv->arrow_button)
3074 gtk_widget_unparent (priv->arrow_button);
3076 for (list = priv->content; list != NULL; list = list->next)
3078 ToolbarContent *content = list->data;
3080 toolbar_content_free (content);
3083 g_list_free (priv->content);
3084 g_list_free (toolbar->children);
3086 g_timer_destroy (priv->timer);
3089 gtk_widget_destroy (GTK_WIDGET (priv->menu));
3092 g_source_remove (priv->idle_id);
3094 G_OBJECT_CLASS (parent_class)->finalize (object);
3102 * gtk_toolbar_set_icon_size:
3103 * @toolbar: A #GtkToolbar
3104 * @icon_size: The #GtkIconSize that stock icons in the toolbar shall have.
3106 * This function sets the size of stock icons in the toolbar. You
3107 * can call it both before you add the icons and after they've been
3108 * added. The size you set will override user preferences for the default
3111 * Deprecated: Applications should respect the user preferences for
3112 * the size of icons in toolbars.
3115 gtk_toolbar_set_icon_size (GtkToolbar *toolbar,
3116 GtkIconSize icon_size)
3118 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3120 toolbar->icon_size_set = TRUE;
3122 if (toolbar->icon_size == icon_size)
3125 toolbar->icon_size = icon_size;
3127 gtk_toolbar_reconfigured (toolbar);
3129 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3133 * gtk_toolbar_unset_icon_size:
3134 * @toolbar: a #GtkToolbar
3136 * Unsets toolbar icon size set with gtk_toolbar_set_icon_size(), so that
3137 * user preferences will be used to determine the icon size.
3140 gtk_toolbar_unset_icon_size (GtkToolbar *toolbar)
3144 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3146 if (toolbar->icon_size_set)
3148 GtkSettings *settings = toolbar_get_settings (toolbar);
3152 g_object_get (settings,
3153 "gtk-toolbar-icon-size", &size,
3157 size = DEFAULT_ICON_SIZE;
3159 if (size != toolbar->icon_size)
3160 gtk_toolbar_set_icon_size (toolbar, size);
3162 toolbar->icon_size_set = FALSE;
3167 * gtk_toolbar_append_item:
3168 * @toolbar: a #GtkToolbar.
3169 * @text: give your toolbar button a label.
3170 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3171 * @tooltip_private_text: use with #GtkTipsQuery.
3172 * @icon: a #GtkWidget that should be used as the button's icon.
3173 * @callback: the function to be executed when the button is pressed.
3174 * @user_data: a pointer to any data you wish to be passed to the callback.
3176 * Inserts a new item into the toolbar. You must specify the position
3177 * in the toolbar where it will be inserted.
3179 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3180 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3182 * Return value: the new toolbar item as a #GtkWidget.
3185 gtk_toolbar_append_item (GtkToolbar *toolbar,
3187 const char *tooltip_text,
3188 const char *tooltip_private_text,
3190 GtkSignalFunc callback,
3193 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3195 tooltip_text, tooltip_private_text,
3196 icon, callback, user_data,
3197 toolbar->num_children);
3201 * gtk_toolbar_prepend_item:
3202 * @toolbar: a #GtkToolbar.
3203 * @text: give your toolbar button a label.
3204 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3205 * @tooltip_private_text: use with #GtkTipsQuery.
3206 * @icon: a #GtkWidget that should be used as the button's icon.
3207 * @callback: the function to be executed when the button is pressed.
3208 * @user_data: a pointer to any data you wish to be passed to the callback.
3210 * Adds a new button to the beginning (top or left edges) of the given toolbar.
3212 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3213 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3215 * Return value: the new toolbar item as a #GtkWidget.
3218 gtk_toolbar_prepend_item (GtkToolbar *toolbar,
3220 const char *tooltip_text,
3221 const char *tooltip_private_text,
3223 GtkSignalFunc callback,
3226 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3228 tooltip_text, tooltip_private_text,
3229 icon, callback, user_data,
3234 * gtk_toolbar_insert_item:
3235 * @toolbar: a #GtkToolbar.
3236 * @text: give your toolbar button a label.
3237 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3238 * @tooltip_private_text: use with #GtkTipsQuery.
3239 * @icon: a #GtkWidget that should be used as the button's icon.
3240 * @callback: the function to be executed when the button is pressed.
3241 * @user_data: a pointer to any data you wish to be passed to the callback.
3242 * @position: the number of widgets to insert this item after.
3244 * Inserts a new item into the toolbar. You must specify the position in the
3245 * toolbar where it will be inserted.
3247 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3248 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3250 * Return value: the new toolbar item as a #GtkWidget.
3253 gtk_toolbar_insert_item (GtkToolbar *toolbar,
3255 const char *tooltip_text,
3256 const char *tooltip_private_text,
3258 GtkSignalFunc callback,
3262 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3264 tooltip_text, tooltip_private_text,
3265 icon, callback, user_data,
3270 * gtk_toolbar_insert_stock:
3271 * @toolbar: A #GtkToolbar
3272 * @stock_id: The id of the stock item you want to insert
3273 * @tooltip_text: The text in the tooltip of the toolbar button
3274 * @tooltip_private_text: The private text of the tooltip
3275 * @callback: The callback called when the toolbar button is clicked.
3276 * @user_data: user data passed to callback
3277 * @position: The position the button shall be inserted at.
3278 * -1 means at the end.
3280 * Inserts a stock item at the specified position of the toolbar. If
3281 * @stock_id is not a known stock item ID, it's inserted verbatim,
3282 * except that underscores used to mark mnemonics are removed.
3284 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3285 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3287 * Returns: the inserted widget
3290 gtk_toolbar_insert_stock (GtkToolbar *toolbar,
3291 const gchar *stock_id,
3292 const char *tooltip_text,
3293 const char *tooltip_private_text,
3294 GtkSignalFunc callback,
3298 return internal_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3300 tooltip_text, tooltip_private_text,
3301 NULL, callback, user_data,
3306 * gtk_toolbar_append_space:
3307 * @toolbar: a #GtkToolbar.
3309 * Adds a new space to the end of the toolbar.
3312 gtk_toolbar_append_space (GtkToolbar *toolbar)
3314 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3318 toolbar->num_children);
3322 * gtk_toolbar_prepend_space:
3323 * @toolbar: a #GtkToolbar.
3325 * Adds a new space to the beginning of the toolbar.
3328 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
3330 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3338 * gtk_toolbar_insert_space:
3339 * @toolbar: a #GtkToolbar
3340 * @position: the number of widgets after which a space should be inserted.
3342 * Inserts a new space in the toolbar at the specified position.
3345 gtk_toolbar_insert_space (GtkToolbar *toolbar,
3348 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3356 * gtk_toolbar_remove_space:
3357 * @toolbar: a #GtkToolbar.
3358 * @position: the index of the space to remove.
3360 * Removes a space from the specified position.
3363 gtk_toolbar_remove_space (GtkToolbar *toolbar,
3366 GtkToolbarPrivate *priv;
3367 ToolbarContent *content;
3369 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3371 if (!gtk_toolbar_check_old_api (toolbar))
3374 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3376 content = g_list_nth_data (priv->content, position);
3380 g_warning ("Toolbar position %d doesn't exist", position);
3384 if (!toolbar_content_is_separator (content))
3386 g_warning ("Toolbar position %d is not a space", position);
3390 toolbar_content_remove (content, toolbar);
3391 toolbar_content_free (content);
3395 * gtk_toolbar_append_widget:
3396 * @toolbar: a #GtkToolbar.
3397 * @widget: a #GtkWidget to add to the toolbar.
3398 * @tooltip_text: the element's tooltip.
3399 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3401 * Adds a widget to the end of the given toolbar.
3404 gtk_toolbar_append_widget (GtkToolbar *toolbar,
3406 const gchar *tooltip_text,
3407 const gchar *tooltip_private_text)
3409 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3411 tooltip_text, tooltip_private_text,
3413 toolbar->num_children);
3417 * gtk_toolbar_prepend_widget:
3418 * @toolbar: a #GtkToolbar.
3419 * @widget: a #GtkWidget to add to the toolbar.
3420 * @tooltip_text: the element's tooltip.
3421 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3423 * Adds a widget to the beginning of the given toolbar.
3426 gtk_toolbar_prepend_widget (GtkToolbar *toolbar,
3428 const gchar *tooltip_text,
3429 const gchar *tooltip_private_text)
3431 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3433 tooltip_text, tooltip_private_text,
3439 * gtk_toolbar_insert_widget:
3440 * @toolbar: a #GtkToolbar.
3441 * @widget: a #GtkWidget to add to the toolbar.
3442 * @tooltip_text: the element's tooltip.
3443 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3444 * @position: the number of widgets to insert this widget after.
3446 * Inserts a widget in the toolbar at the given position.
3449 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
3451 const char *tooltip_text,
3452 const char *tooltip_private_text,
3455 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3457 tooltip_text, tooltip_private_text,
3463 * gtk_toolbar_append_element:
3464 * @toolbar: a #GtkToolbar.
3465 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
3466 * @widget: a #GtkWidget, or %NULL.
3467 * @text: the element's label.
3468 * @tooltip_text: the element's tooltip.
3469 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3470 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3471 * @callback: the function to be executed when the button is pressed.
3472 * @user_data: any data you wish to pass to the callback.
3474 * Adds a new element to the end of a toolbar.
3476 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3477 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3478 * the radio group for the new element. In all other cases, @widget must
3481 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3482 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3484 * Return value: the new toolbar element as a #GtkWidget.
3487 gtk_toolbar_append_element (GtkToolbar *toolbar,
3488 GtkToolbarChildType type,
3491 const char *tooltip_text,
3492 const char *tooltip_private_text,
3494 GtkSignalFunc callback,
3497 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3498 tooltip_text, tooltip_private_text,
3499 icon, callback, user_data,
3500 toolbar->num_children);
3504 * gtk_toolbar_prepend_element:
3505 * @toolbar: a #GtkToolbar.
3506 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
3507 * @widget: a #GtkWidget, or %NULL
3508 * @text: the element's label.
3509 * @tooltip_text: the element's tooltip.
3510 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3511 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3512 * @callback: the function to be executed when the button is pressed.
3513 * @user_data: any data you wish to pass to the callback.
3515 * Adds a new element to the beginning of a toolbar.
3517 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3518 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3519 * the radio group for the new element. In all other cases, @widget must
3522 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3523 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3525 * Return value: the new toolbar element as a #GtkWidget.
3528 gtk_toolbar_prepend_element (GtkToolbar *toolbar,
3529 GtkToolbarChildType type,
3532 const char *tooltip_text,
3533 const char *tooltip_private_text,
3535 GtkSignalFunc callback,
3538 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3539 tooltip_text, tooltip_private_text,
3540 icon, callback, user_data, 0);
3544 * gtk_toolbar_insert_element:
3545 * @toolbar: a #GtkToolbar.
3546 * @type: a value of type #GtkToolbarChildType that determines what @widget
3548 * @widget: a #GtkWidget, or %NULL.
3549 * @text: the element's label.
3550 * @tooltip_text: the element's tooltip.
3551 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3552 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3553 * @callback: the function to be executed when the button is pressed.
3554 * @user_data: any data you wish to pass to the callback.
3555 * @position: the number of widgets to insert this element after.
3557 * Inserts a new element in the toolbar at the given position.
3559 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3560 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3561 * the radio group for the new element. In all other cases, @widget must
3564 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3565 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3567 * Return value: the new toolbar element as a #GtkWidget.
3570 gtk_toolbar_insert_element (GtkToolbar *toolbar,
3571 GtkToolbarChildType type,
3574 const char *tooltip_text,
3575 const char *tooltip_private_text,
3577 GtkSignalFunc callback,
3581 return internal_insert_element (toolbar, type, widget, text,
3582 tooltip_text, tooltip_private_text,
3583 icon, callback, user_data, position, FALSE);
3587 set_child_packing_and_visibility(GtkToolbar *toolbar,
3588 GtkToolbarChild *child)
3593 box = gtk_bin_get_child (GTK_BIN (child->widget));
3595 g_return_if_fail (GTK_IS_BOX (box));
3599 expand = (toolbar->style != GTK_TOOLBAR_BOTH);
3601 gtk_box_set_child_packing (GTK_BOX (box), child->label,
3602 expand, expand, 0, GTK_PACK_END);
3604 if (toolbar->style != GTK_TOOLBAR_ICONS)
3605 gtk_widget_show (child->label);
3607 gtk_widget_hide (child->label);
3612 expand = (toolbar->style != GTK_TOOLBAR_BOTH_HORIZ);
3614 gtk_box_set_child_packing (GTK_BOX (box), child->icon,
3615 expand, expand, 0, GTK_PACK_END);
3617 if (toolbar->style != GTK_TOOLBAR_TEXT)
3618 gtk_widget_show (child->icon);
3620 gtk_widget_hide (child->icon);
3625 internal_insert_element (GtkToolbar *toolbar,
3626 GtkToolbarChildType type,
3629 const char *tooltip_text,
3630 const char *tooltip_private_text,
3632 GtkSignalFunc callback,
3638 ToolbarContent *content;
3639 GtkToolbarPrivate *priv;
3640 char *free_me = NULL;
3641 gboolean is_button = FALSE;
3643 GtkWidget *child_widget;
3644 GtkWidget *child_label;
3645 GtkWidget *child_icon;
3647 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
3648 if (type == GTK_TOOLBAR_CHILD_WIDGET)
3649 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3650 else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON)
3651 g_return_val_if_fail (widget == NULL, NULL);
3652 if (GTK_IS_TOOL_ITEM (widget))
3653 g_warning (MIXED_API_WARNING);
3655 if (!gtk_toolbar_check_old_api (toolbar))
3658 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3660 child_widget = NULL;
3666 case GTK_TOOLBAR_CHILD_SPACE:
3669 case GTK_TOOLBAR_CHILD_WIDGET:
3670 child_widget = widget;
3673 case GTK_TOOLBAR_CHILD_BUTTON:
3674 case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
3675 case GTK_TOOLBAR_CHILD_RADIOBUTTON:
3677 if (type == GTK_TOOLBAR_CHILD_BUTTON)
3679 child_widget = gtk_button_new ();
3681 else if (type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
3683 child_widget = gtk_toggle_button_new ();
3684 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child_widget), FALSE);
3686 else /* type == GTK_TOOLBAR_CHILD_RADIOBUTTON */
3688 GSList *group = NULL;
3691 group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
3693 child_widget = gtk_radio_button_new (group);
3694 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child_widget), FALSE);
3697 gtk_button_set_relief (GTK_BUTTON (child_widget), get_button_relief (toolbar));
3698 gtk_button_set_focus_on_click (GTK_BUTTON (child_widget), FALSE);
3702 g_signal_connect (child_widget, "clicked",
3703 callback, user_data);
3706 if (toolbar->style == GTK_TOOLBAR_BOTH_HORIZ)
3707 box = gtk_hbox_new (FALSE, 0);
3709 box = gtk_vbox_new (FALSE, 0);
3711 gtk_container_add (GTK_CONTAINER (child_widget), box);
3712 gtk_widget_show (box);
3714 if (text && use_stock)
3716 GtkStockItem stock_item;
3717 if (gtk_stock_lookup (text, &stock_item))
3720 icon = gtk_image_new_from_stock (text, toolbar->icon_size);
3722 text = free_me = _gtk_toolbar_elide_underscores (stock_item.label);
3728 child_label = gtk_label_new (text);
3730 gtk_container_add (GTK_CONTAINER (box), child_label);
3735 child_icon = GTK_WIDGET (icon);
3736 gtk_container_add (GTK_CONTAINER (box), child_icon);
3739 gtk_widget_show (child_widget);
3743 g_assert_not_reached ();
3747 if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text)
3749 gtk_tooltips_set_tip (toolbar->tooltips, child_widget,
3750 tooltip_text, tooltip_private_text);
3753 content = toolbar_content_new_compatibility (toolbar, type, child_widget,
3754 child_icon, child_label, position);
3759 return child_widget;
3763 * ToolbarContent methods
3771 struct _ToolbarContent
3781 GtkAllocation start_allocation;
3782 GtkAllocation goal_allocation;
3783 guint is_placeholder : 1;
3784 guint disappearing : 1;
3785 TriState has_menu : 2;
3790 GtkToolbarChild child;
3791 GtkAllocation space_allocation;
3792 guint space_visible : 1;
3797 static ToolbarContent *
3798 toolbar_content_new_tool_item (GtkToolbar *toolbar,
3800 gboolean is_placeholder,
3803 ToolbarContent *content;
3804 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3806 content = g_new0 (ToolbarContent, 1);
3808 content->type = TOOL_ITEM;
3809 content->state = NOT_ALLOCATED;
3810 content->u.tool_item.item = item;
3811 content->u.tool_item.is_placeholder = is_placeholder;
3813 gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar));
3815 priv->content = g_list_insert (priv->content, content, pos);
3817 if (!is_placeholder)
3819 toolbar->num_children++;
3821 gtk_toolbar_stop_sliding (toolbar);
3824 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3825 priv->need_rebuild = TRUE;
3830 static ToolbarContent *
3831 toolbar_content_new_compatibility (GtkToolbar *toolbar,
3832 GtkToolbarChildType type,
3838 ToolbarContent *content;
3839 GtkToolbarChild *child;
3840 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3842 content = g_new0 (ToolbarContent, 1);
3844 child = &(content->u.compatibility.child);
3846 content->type = COMPATIBILITY;
3848 child->widget = widget;
3850 child->label = label;
3852 if (type != GTK_TOOLBAR_CHILD_SPACE)
3854 gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
3858 content->u.compatibility.space_visible = TRUE;
3859 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3862 if (type == GTK_TOOLBAR_CHILD_BUTTON ||
3863 type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
3864 type == GTK_TOOLBAR_CHILD_RADIOBUTTON)
3866 set_child_packing_and_visibility (toolbar, child);
3869 priv->content = g_list_insert (priv->content, content, pos);
3870 toolbar->children = g_list_insert (toolbar->children, child, pos);
3871 priv->need_rebuild = TRUE;
3873 toolbar->num_children++;
3879 toolbar_content_remove (ToolbarContent *content,
3880 GtkToolbar *toolbar)
3882 GtkToolbarChild *child;
3883 GtkToolbarPrivate *priv;
3885 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3887 switch (content->type)
3890 gtk_widget_unparent (GTK_WIDGET (content->u.tool_item.item));
3894 child = &(content->u.compatibility.child);
3896 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
3898 g_object_ref (child->widget);
3899 gtk_widget_unparent (child->widget);
3900 gtk_widget_destroy (child->widget);
3901 g_object_unref (child->widget);
3904 toolbar->children = g_list_remove (toolbar->children, child);
3908 priv->content = g_list_remove (priv->content, content);
3910 if (!toolbar_content_is_placeholder (content))
3911 toolbar->num_children--;
3913 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3914 priv->need_rebuild = TRUE;
3918 toolbar_content_free (ToolbarContent *content)
3924 calculate_max_homogeneous_pixels (GtkWidget *widget)
3926 PangoContext *context;
3927 PangoFontMetrics *metrics;
3930 context = gtk_widget_get_pango_context (widget);
3931 metrics = pango_context_get_metrics (context,
3932 widget->style->font_desc,
3933 pango_context_get_language (context));
3934 char_width = pango_font_metrics_get_approximate_char_width (metrics);
3935 pango_font_metrics_unref (metrics);
3937 return PANGO_PIXELS (MAX_HOMOGENEOUS_N_CHARS * char_width);
3941 toolbar_content_expose (ToolbarContent *content,
3942 GtkContainer *container,
3943 GdkEventExpose *expose)
3945 GtkToolbar *toolbar = GTK_TOOLBAR (container);
3946 GtkToolbarChild *child;
3947 GtkWidget *widget = NULL; /* quiet gcc */
3949 switch (content->type)
3952 if (!content->u.tool_item.is_placeholder)
3953 widget = GTK_WIDGET (content->u.tool_item.item);
3957 child = &(content->u.compatibility.child);
3959 if (child->type == GTK_TOOLBAR_CHILD_SPACE)
3961 if (get_space_style (toolbar) == GTK_TOOLBAR_SPACE_LINE &&
3962 content->u.compatibility.space_visible)
3964 _gtk_toolbar_paint_space_line (GTK_WIDGET (toolbar), toolbar,
3966 &content->u.compatibility.space_allocation);
3971 widget = child->widget;
3976 gtk_container_propagate_expose (container, widget, expose);
3980 toolbar_content_visible (ToolbarContent *content,
3981 GtkToolbar *toolbar)
3985 switch (content->type)
3988 item = content->u.tool_item.item;
3990 if (!GTK_WIDGET_VISIBLE (item))
3993 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL &&
3994 gtk_tool_item_get_visible_horizontal (item))
3999 if ((toolbar->orientation == GTK_ORIENTATION_VERTICAL &&
4000 gtk_tool_item_get_visible_vertical (item)))
4009 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4010 return GTK_WIDGET_VISIBLE (content->u.compatibility.child.widget);
4016 g_assert_not_reached ();
4021 toolbar_content_size_request (ToolbarContent *content,
4022 GtkToolbar *toolbar,
4023 GtkRequisition *requisition)
4027 switch (content->type)
4030 gtk_widget_size_request (GTK_WIDGET (content->u.tool_item.item),
4032 if (content->u.tool_item.is_placeholder &&
4033 content->u.tool_item.disappearing)
4035 requisition->width = 0;
4036 requisition->height = 0;
4041 space_size = get_space_size (toolbar);
4043 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4045 gtk_widget_size_request (content->u.compatibility.child.widget,
4050 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
4052 requisition->width = space_size;
4053 requisition->height = 0;
4057 requisition->height = space_size;
4058 requisition->width = 0;
4067 toolbar_content_is_homogeneous (ToolbarContent *content,
4068 GtkToolbar *toolbar)
4070 gboolean result = FALSE; /* quiet gcc */
4071 GtkRequisition requisition;
4072 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4074 if (priv->max_homogeneous_pixels < 0)
4076 priv->max_homogeneous_pixels =
4077 calculate_max_homogeneous_pixels (GTK_WIDGET (toolbar));
4080 toolbar_content_size_request (content, toolbar, &requisition);
4082 if (requisition.width > priv->max_homogeneous_pixels)
4085 switch (content->type)
4088 result = gtk_tool_item_get_homogeneous (content->u.tool_item.item) &&
4089 !GTK_IS_SEPARATOR_TOOL_ITEM (content->u.tool_item.item);
4091 if (gtk_tool_item_get_is_important (content->u.tool_item.item) &&
4092 toolbar->style == GTK_TOOLBAR_BOTH_HORIZ &&
4093 toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
4100 if (content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_BUTTON ||
4101 content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4102 content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4117 toolbar_content_is_placeholder (ToolbarContent *content)
4119 if (content->type == TOOL_ITEM && content->u.tool_item.is_placeholder)
4126 toolbar_content_disappearing (ToolbarContent *content)
4128 if (content->type == TOOL_ITEM && content->u.tool_item.disappearing)
4135 toolbar_content_get_state (ToolbarContent *content)
4137 return content->state;
4141 toolbar_content_child_visible (ToolbarContent *content)
4143 switch (content->type)
4146 return GTK_WIDGET_CHILD_VISIBLE (content->u.tool_item.item);
4150 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4152 return GTK_WIDGET_CHILD_VISIBLE (content->u.compatibility.child.widget);
4156 return content->u.compatibility.space_visible;
4161 return FALSE; /* quiet gcc */
4165 toolbar_content_get_goal_allocation (ToolbarContent *content,
4166 GtkAllocation *allocation)
4168 switch (content->type)
4171 *allocation = content->u.tool_item.goal_allocation;
4175 /* Goal allocations are only relevant when we are
4176 * using the new API, so we should never get here
4178 g_assert_not_reached ();
4184 toolbar_content_get_allocation (ToolbarContent *content,
4185 GtkAllocation *allocation)
4187 GtkToolbarChild *child;
4189 switch (content->type)
4192 *allocation = GTK_WIDGET (content->u.tool_item.item)->allocation;
4196 child = &(content->u.compatibility.child);
4198 if (child->type == GTK_TOOLBAR_CHILD_SPACE)
4199 *allocation = content->u.compatibility.space_allocation;
4201 *allocation = child->widget->allocation;
4207 toolbar_content_set_start_allocation (ToolbarContent *content,
4208 GtkAllocation *allocation)
4210 switch (content->type)
4213 content->u.tool_item.start_allocation = *allocation;
4217 /* start_allocation is only relevant when using the new API */
4218 g_assert_not_reached ();
4224 toolbar_content_get_expand (ToolbarContent *content)
4226 if (content->type == TOOL_ITEM &&
4227 gtk_tool_item_get_expand (content->u.tool_item.item) &&
4228 !content->u.tool_item.disappearing)
4237 toolbar_content_set_goal_allocation (ToolbarContent *content,
4238 GtkAllocation *allocation)
4240 switch (content->type)
4243 content->u.tool_item.goal_allocation = *allocation;
4247 /* Only relevant when using new API */
4248 g_assert_not_reached ();
4254 toolbar_content_set_child_visible (ToolbarContent *content,
4255 GtkToolbar *toolbar,
4258 GtkToolbarChild *child;
4260 switch (content->type)
4263 gtk_widget_set_child_visible (GTK_WIDGET (content->u.tool_item.item),
4268 child = &(content->u.compatibility.child);
4270 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
4272 gtk_widget_set_child_visible (child->widget, visible);
4276 if (content->u.compatibility.space_visible != visible)
4278 content->u.compatibility.space_visible = visible;
4279 gtk_widget_queue_draw (GTK_WIDGET (toolbar));
4287 toolbar_content_get_start_allocation (ToolbarContent *content,
4288 GtkAllocation *start_allocation)
4290 switch (content->type)
4293 *start_allocation = content->u.tool_item.start_allocation;
4297 /* Only relevant for new API */
4298 g_assert_not_reached ();
4304 toolbar_content_size_allocate (ToolbarContent *content,
4305 GtkAllocation *allocation)
4307 switch (content->type)
4310 gtk_widget_size_allocate (GTK_WIDGET (content->u.tool_item.item),
4315 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4317 gtk_widget_size_allocate (content->u.compatibility.child.widget,
4322 content->u.compatibility.space_allocation = *allocation;
4329 toolbar_content_set_state (ToolbarContent *content,
4332 content->state = state;
4336 toolbar_content_get_widget (ToolbarContent *content)
4338 GtkToolbarChild *child;
4340 switch (content->type)
4343 return GTK_WIDGET (content->u.tool_item.item);
4347 child = &(content->u.compatibility.child);
4348 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
4349 return child->widget;
4359 toolbar_content_set_disappearing (ToolbarContent *content,
4360 gboolean disappearing)
4362 switch (content->type)
4365 content->u.tool_item.disappearing = disappearing;
4369 /* Only relevant for new API */
4370 g_assert_not_reached ();
4376 toolbar_content_set_size_request (ToolbarContent *content,
4380 switch (content->type)
4383 gtk_widget_set_size_request (GTK_WIDGET (content->u.tool_item.item),
4388 /* Setting size requests only happens with sliding,
4389 * so not relevant here
4391 g_assert_not_reached ();
4397 toolbar_child_reconfigure (GtkToolbar *toolbar,
4398 GtkToolbarChild *child)
4402 GtkToolbarStyle style;
4403 GtkIconSize icon_size;
4404 GtkReliefStyle relief;
4407 style = gtk_toolbar_get_style (toolbar);
4408 icon_size = gtk_toolbar_get_icon_size (toolbar);
4409 relief = gtk_toolbar_get_relief_style (toolbar);
4412 if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4413 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4414 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4416 box = gtk_bin_get_child (GTK_BIN (child->widget));
4418 if (style == GTK_TOOLBAR_BOTH && GTK_IS_HBOX (box))
4422 vbox = gtk_vbox_new (FALSE, 0);
4425 gtk_widget_reparent (child->label, vbox);
4427 gtk_widget_reparent (child->icon, vbox);
4429 gtk_widget_destroy (box);
4430 gtk_container_add (GTK_CONTAINER (child->widget), vbox);
4432 gtk_widget_show (vbox);
4434 else if (style == GTK_TOOLBAR_BOTH_HORIZ && GTK_IS_VBOX (box))
4438 hbox = gtk_hbox_new (FALSE, 0);
4441 gtk_widget_reparent (child->label, hbox);
4443 gtk_widget_reparent (child->icon, hbox);
4445 gtk_widget_destroy (box);
4446 gtk_container_add (GTK_CONTAINER (child->widget), hbox);
4448 gtk_widget_show (hbox);
4451 set_child_packing_and_visibility (toolbar, child);
4456 if ((child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4457 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
4458 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON) &&
4459 GTK_IS_IMAGE (child->icon))
4461 image = GTK_IMAGE (child->icon);
4462 if (gtk_image_get_storage_type (image) == GTK_IMAGE_STOCK)
4464 gtk_image_get_stock (image, &stock_id, NULL);
4465 stock_id = g_strdup (stock_id);
4466 gtk_image_set_from_stock (image,
4474 if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4475 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4476 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4478 gtk_button_set_relief (GTK_BUTTON (child->widget), relief);
4483 toolbar_content_toolbar_reconfigured (ToolbarContent *content,
4484 GtkToolbar *toolbar)
4486 switch (content->type)
4489 _gtk_tool_item_toolbar_reconfigured (content->u.tool_item.item);
4493 toolbar_child_reconfigure (toolbar, &(content->u.compatibility.child));
4499 toolbar_content_retrieve_menu_item (ToolbarContent *content)
4501 if (content->type == TOOL_ITEM)
4502 return gtk_tool_item_retrieve_proxy_menu_item (content->u.tool_item.item);
4504 /* FIXME - we might actually be able to do something meaningful here */
4509 toolbar_content_has_proxy_menu_item (ToolbarContent *content)
4511 if (content->type == TOOL_ITEM)
4513 GtkWidget *menu_item;
4515 if (content->u.tool_item.has_menu == YES)
4517 else if (content->u.tool_item.has_menu == NO)
4520 menu_item = toolbar_content_retrieve_menu_item (content);
4522 content->u.tool_item.has_menu = menu_item? YES : NO;
4524 return menu_item != NULL;
4533 toolbar_content_set_unknown_menu_status (ToolbarContent *content)
4535 if (content->type == TOOL_ITEM)
4536 content->u.tool_item.has_menu = UNKNOWN;
4540 toolbar_content_is_separator (ToolbarContent *content)
4542 GtkToolbarChild *child;
4544 switch (content->type)
4547 return GTK_IS_SEPARATOR_TOOL_ITEM (content->u.tool_item.item);
4551 child = &(content->u.compatibility.child);
4552 return (child->type == GTK_TOOLBAR_CHILD_SPACE);
4560 toolbar_content_set_expand (ToolbarContent *content,
4563 if (content->type == TOOL_ITEM)
4564 gtk_tool_item_set_expand (content->u.tool_item.item, expand);
4568 ignore_show_and_hide_all (ToolbarContent *content)
4570 if (content->type == COMPATIBILITY)
4572 GtkToolbarChildType type = content->u.compatibility.child.type;
4574 if (type == GTK_TOOLBAR_CHILD_BUTTON ||
4575 type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
4576 type == GTK_TOOLBAR_CHILD_RADIOBUTTON)
4586 toolbar_content_show_all (ToolbarContent *content)
4590 if (ignore_show_and_hide_all (content))
4593 widget = toolbar_content_get_widget (content);
4595 gtk_widget_show_all (widget);
4599 toolbar_content_hide_all (ToolbarContent *content)
4603 if (ignore_show_and_hide_all (content))
4606 widget = toolbar_content_get_widget (content);
4608 gtk_widget_hide_all (widget);
4615 get_space_size (GtkToolbar *toolbar)
4617 gint space_size = DEFAULT_SPACE_SIZE;
4621 gtk_widget_style_get (GTK_WIDGET (toolbar),
4622 "space-size", &space_size,
4629 static GtkToolbarSpaceStyle
4630 get_space_style (GtkToolbar *toolbar)
4632 GtkToolbarSpaceStyle space_style = DEFAULT_SPACE_STYLE;
4636 gtk_widget_style_get (GTK_WIDGET (toolbar),
4637 "space-style", &space_style,
4644 static GtkReliefStyle
4645 get_button_relief (GtkToolbar *toolbar)
4647 GtkReliefStyle button_relief = GTK_RELIEF_NORMAL;
4649 gtk_widget_ensure_style (GTK_WIDGET (toolbar));
4651 gtk_widget_style_get (GTK_WIDGET (toolbar),
4652 "button-relief", &button_relief,
4655 return button_relief;
4659 get_internal_padding (GtkToolbar *toolbar)
4663 gtk_widget_style_get (GTK_WIDGET (toolbar),
4664 "internal-padding", &ipadding,
4670 static GtkShadowType
4671 get_shadow_type (GtkToolbar *toolbar)
4673 GtkShadowType shadow_type;
4675 gtk_widget_style_get (GTK_WIDGET (toolbar),
4676 "shadow-type", &shadow_type,
4686 gtk_toolbar_check_old_api (GtkToolbar *toolbar)
4688 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4690 if (priv->api_mode == NEW_API)
4692 g_warning (MIXED_API_WARNING);
4696 priv->api_mode = OLD_API;
4701 gtk_toolbar_check_new_api (GtkToolbar *toolbar)
4703 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4705 if (priv->api_mode == OLD_API)
4707 g_warning (MIXED_API_WARNING);
4711 priv->api_mode = NEW_API;
4715 /* GTK+ internal methods */
4718 _gtk_toolbar_get_default_space_size (void)
4720 return DEFAULT_SPACE_SIZE;
4724 _gtk_toolbar_paint_space_line (GtkWidget *widget,
4725 GtkToolbar *toolbar,
4727 GtkAllocation *allocation)
4729 const double start_fraction = (SPACE_LINE_START / SPACE_LINE_DIVISION);
4730 const double end_fraction = (SPACE_LINE_END / SPACE_LINE_DIVISION);
4732 GtkToolbarSpaceStyle space_style;
4733 GtkOrientation orientation;
4735 g_return_if_fail (GTK_IS_WIDGET (widget));
4737 space_style = toolbar? get_space_style (toolbar) : DEFAULT_SPACE_STYLE;
4738 orientation = toolbar? toolbar->orientation : GTK_ORIENTATION_HORIZONTAL;
4740 if (orientation == GTK_ORIENTATION_HORIZONTAL)
4742 gtk_paint_vline (widget->style, widget->window,
4743 GTK_WIDGET_STATE (widget), area, widget,
4745 allocation->y + allocation->height * start_fraction,
4746 allocation->y + allocation->height * end_fraction,
4747 allocation->x + (allocation->width - widget->style->xthickness) / 2);
4751 gtk_paint_hline (widget->style, widget->window,
4752 GTK_WIDGET_STATE (widget), area, widget,
4754 allocation->x + allocation->width * start_fraction,
4755 allocation->x + allocation->width * end_fraction,
4756 allocation->y + (allocation->height - widget->style->ythickness) / 2);
4761 _gtk_toolbar_elide_underscores (const gchar *original)
4765 gboolean last_underscore;
4767 q = result = g_malloc (strlen (original) + 1);
4768 last_underscore = FALSE;
4770 for (p = original; *p; p++)
4772 if (!last_underscore && *p == '_')
4773 last_underscore = TRUE;
4776 last_underscore = FALSE;
4787 _gtk_toolbar_rebuild_menu (GtkToolbar *toolbar)
4789 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4792 priv->need_rebuild = TRUE;
4794 for (list = priv->content; list != NULL; list = list->next)
4796 ToolbarContent *content = list->data;
4798 toolbar_content_set_unknown_menu_status (content);
4801 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
4804 #define __GTK_TOOLBAR_C__
4805 #include "gtkaliasdef.c"