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@codefactory.se>
6 * Copyright (C) 2002 James Henstridge <james@daa.com.au>
7 * Copyright (C) 2003 Soeren Sandmann <sandmann@daimi.au.dk>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
26 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
27 * file for a list of people on the GTK+ Team. See the ChangeLog
28 * files for a list of changes. These files are distributed with
29 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
32 #undef GTK_DISABLE_DEPRECATED
35 #include "gtktoolbar.h"
36 #include "gtkradiotoolbutton.h"
37 #include "gtkseparatortoolitem.h"
39 #include "gtkradiobutton.h"
40 #include "gtktoolbar.h"
41 #include "gtkbindings.h"
42 #include <gdk/gdkkeysyms.h>
43 #include "gtkmarshalers.h"
47 #include "gtkprivate.h"
51 #define DEFAULT_IPADDING 0
53 /* note: keep in sync with DEFAULT_SPACE_SIZE and DEFAULT_SPACE_STYLE in gtkseparatortoolitem.c */
54 #define DEFAULT_SPACE_SIZE 4
55 #define DEFAULT_SPACE_STYLE GTK_TOOLBAR_SPACE_LINE
57 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_LARGE_TOOLBAR
58 #define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_BOTH
60 #define MAX_HOMOGENEOUS_N_CHARS 13 /* Items that are wider than this do not participate in
61 * the homogeneous game. In units of
62 * pango_font_get_estimated_char_width().
75 CHILD_PROP_HOMOGENEOUS,
88 static void gtk_toolbar_init (GtkToolbar *toolbar);
89 static void gtk_toolbar_class_init (GtkToolbarClass *klass);
91 static void gtk_toolbar_set_property (GObject *object,
95 static void gtk_toolbar_get_property (GObject *object,
100 static gint gtk_toolbar_expose (GtkWidget *widget,
101 GdkEventExpose *event);
102 static void gtk_toolbar_realize (GtkWidget *widget);
103 static void gtk_toolbar_unrealize (GtkWidget *widget);
104 static void gtk_toolbar_size_request (GtkWidget *widget,
105 GtkRequisition *requisition);
106 static void gtk_toolbar_size_allocate (GtkWidget *widget,
107 GtkAllocation *allocation);
108 static void gtk_toolbar_style_set (GtkWidget *widget,
109 GtkStyle *prev_style);
110 static void gtk_toolbar_direction_changed (GtkWidget *widget,
111 GtkTextDirection previous_direction);
112 static gboolean gtk_toolbar_focus (GtkWidget *widget,
113 GtkDirectionType dir);
114 static void gtk_toolbar_screen_changed (GtkWidget *widget,
115 GdkScreen *previous_screen);
116 static void gtk_toolbar_map (GtkWidget *widget);
117 static void gtk_toolbar_unmap (GtkWidget *widget);
119 static void gtk_toolbar_drag_leave (GtkWidget *widget,
120 GdkDragContext *context,
122 static gboolean gtk_toolbar_drag_motion (GtkWidget *widget,
123 GdkDragContext *context,
127 static void gtk_toolbar_set_child_property (GtkContainer *container,
132 static void gtk_toolbar_get_child_property (GtkContainer *container,
137 static void gtk_toolbar_finalize (GObject *object);
140 static void gtk_toolbar_add (GtkContainer *container,
142 static void gtk_toolbar_remove (GtkContainer *container,
144 static void gtk_toolbar_forall (GtkContainer *container,
145 gboolean include_internals,
146 GtkCallback callback,
147 gpointer callback_data);
148 static GType gtk_toolbar_child_type (GtkContainer *container);
150 static void gtk_toolbar_real_orientation_changed (GtkToolbar *toolbar,
151 GtkOrientation orientation);
152 static void gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
153 GtkToolbarStyle style);
155 static gboolean gtk_toolbar_move_focus (GtkToolbar *toolbar,
156 GtkDirectionType dir);
157 static gboolean gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
158 gboolean focus_home);
160 static gboolean gtk_toolbar_button_press (GtkWidget *toolbar,
161 GdkEventButton *event);
162 static gboolean gtk_toolbar_arrow_button_press (GtkWidget *button,
163 GdkEventButton *event,
164 GtkToolbar *toolbar);
165 static void gtk_toolbar_arrow_button_clicked (GtkWidget *button,
166 GtkToolbar *toolbar);
167 static void gtk_toolbar_update_button_relief (GtkToolbar *toolbar);
168 static GtkReliefStyle get_button_relief (GtkToolbar *toolbar);
169 static gint get_internal_padding (GtkToolbar *toolbar);
170 static GtkShadowType get_shadow_type (GtkToolbar *toolbar);
171 static void gtk_toolbar_remove_tool_item (GtkToolbar *toolbar,
173 static gboolean gtk_toolbar_popup_menu (GtkWidget *toolbar);
175 static GtkWidget *gtk_toolbar_internal_insert_element (GtkToolbar *toolbar,
176 GtkToolbarChildType type,
179 const char *tooltip_text,
180 const char *tooltip_private_text,
182 GtkSignalFunc callback,
194 #define GTK_TOOLBAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_TOOLBAR, GtkToolbarPrivate))
196 struct _GtkToolbarPrivate
201 GtkWidget *arrow_button;
206 GdkWindow *drag_highlight;
209 GdkWindow *event_window;
211 GtkSettings *settings;
214 static GtkContainerClass *parent_class = NULL;
215 static guint toolbar_signals [LAST_SIGNAL] = { 0 };
218 gtk_toolbar_get_type (void)
220 static GtkType type = 0;
224 static const GTypeInfo type_info =
226 sizeof (GtkToolbarClass),
227 (GBaseInitFunc) NULL,
228 (GBaseFinalizeFunc) NULL,
229 (GClassInitFunc) gtk_toolbar_class_init,
230 (GClassFinalizeFunc) NULL,
234 (GInstanceInitFunc) gtk_toolbar_init,
237 type = g_type_register_static (GTK_TYPE_CONTAINER,
246 add_arrow_bindings (GtkBindingSet *binding_set,
248 GtkDirectionType dir)
250 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
252 gtk_binding_entry_add_signal (binding_set, keysym, 0,
254 GTK_TYPE_DIRECTION_TYPE, dir);
255 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
257 GTK_TYPE_DIRECTION_TYPE, dir);
261 add_ctrl_tab_bindings (GtkBindingSet *binding_set,
262 GdkModifierType modifiers,
263 GtkDirectionType direction)
265 gtk_binding_entry_add_signal (binding_set,
266 GDK_Tab, GDK_CONTROL_MASK | modifiers,
268 GTK_TYPE_DIRECTION_TYPE, direction);
269 gtk_binding_entry_add_signal (binding_set,
270 GDK_KP_Tab, GDK_CONTROL_MASK | modifiers,
272 GTK_TYPE_DIRECTION_TYPE, direction);
276 gtk_toolbar_class_init (GtkToolbarClass *klass)
278 GObjectClass *gobject_class;
279 GtkWidgetClass *widget_class;
280 GtkContainerClass *container_class;
281 GtkBindingSet *binding_set;
283 parent_class = g_type_class_peek_parent (klass);
285 gobject_class = (GObjectClass *)klass;
286 widget_class = (GtkWidgetClass *)klass;
287 container_class = (GtkContainerClass *)klass;
289 gobject_class->set_property = gtk_toolbar_set_property;
290 gobject_class->get_property = gtk_toolbar_get_property;
291 gobject_class->finalize = gtk_toolbar_finalize;
293 widget_class->button_press_event = gtk_toolbar_button_press;
294 widget_class->expose_event = gtk_toolbar_expose;
295 widget_class->size_request = gtk_toolbar_size_request;
296 widget_class->size_allocate = gtk_toolbar_size_allocate;
297 widget_class->style_set = gtk_toolbar_style_set;
298 widget_class->direction_changed = gtk_toolbar_direction_changed;
299 widget_class->focus = gtk_toolbar_focus;
300 widget_class->screen_changed = gtk_toolbar_screen_changed;
301 widget_class->realize = gtk_toolbar_realize;
302 widget_class->unrealize = gtk_toolbar_unrealize;
303 widget_class->map = gtk_toolbar_map;
304 widget_class->unmap = gtk_toolbar_unmap;
305 widget_class->popup_menu = gtk_toolbar_popup_menu;
307 widget_class->drag_leave = gtk_toolbar_drag_leave;
308 widget_class->drag_motion = gtk_toolbar_drag_motion;
310 container_class->add = gtk_toolbar_add;
311 container_class->remove = gtk_toolbar_remove;
312 container_class->forall = gtk_toolbar_forall;
313 container_class->child_type = gtk_toolbar_child_type;
314 container_class->get_child_property = gtk_toolbar_get_child_property;
315 container_class->set_child_property = gtk_toolbar_set_child_property;
317 klass->orientation_changed = gtk_toolbar_real_orientation_changed;
318 klass->style_changed = gtk_toolbar_real_style_changed;
321 * GtkToolbar::orientation-changed:
322 * @toolbar: the object which emitted the signal
323 * @orientation: the new #GtkOrientation of the toolbar
325 * Emitted when the orientation of the toolbar changes.
327 toolbar_signals[ORIENTATION_CHANGED] =
328 g_signal_new ("orientation-changed",
329 G_OBJECT_CLASS_TYPE (klass),
331 G_STRUCT_OFFSET (GtkToolbarClass, orientation_changed),
333 g_cclosure_marshal_VOID__ENUM,
335 GTK_TYPE_ORIENTATION);
337 * GtkToolbar::style-changed:
338 * @toolbar: The #GtkToolbar which emitted the signal
339 * @style: the new #GtkToolbarStyle of the toolbar
341 * Emitted when the style of the toolbar changes.
343 toolbar_signals[STYLE_CHANGED] =
344 g_signal_new ("style-changed",
345 G_OBJECT_CLASS_TYPE (klass),
347 G_STRUCT_OFFSET (GtkToolbarClass, style_changed),
349 g_cclosure_marshal_VOID__ENUM,
351 GTK_TYPE_TOOLBAR_STYLE);
353 * GtkToolbar::popup-context-menu:
354 * @toolbar: the #GtkToolbar which emitted the signal
355 * @x: the x coordinate of the point where the menu should appear
356 * @y: the y coordinate of the point where the menu should appear
357 * @button: the mouse button the user pressed, or -1
359 * Emitted when the user right-clicks the toolbar or uses the
360 * keybinding to display a popup menu.
362 * Application developers should handle this signal if they want
363 * to display a context menu on the toolbar. The context-menu should
364 * appear at the coordinates given by @x and @y. The mouse button
365 * number is given by the @button parameter. If the menu was popped
366 * up using the keybaord, @button is -1.
368 * Return value: return %TRUE if the signal was handled, %FALSE if not
370 toolbar_signals[POPUP_CONTEXT_MENU] =
371 g_signal_new ("popup_context_menu",
372 G_OBJECT_CLASS_TYPE (klass),
374 G_STRUCT_OFFSET (GtkToolbarClass, popup_context_menu),
375 _gtk_boolean_handled_accumulator, NULL,
376 _gtk_marshal_BOOLEAN__INT_INT_INT,
378 G_TYPE_INT, G_TYPE_INT,
381 * GtkToolbar::move-focus:
382 * @toolbar: the #GtkToolbar which emitted the signal
383 * @dir: a #GtkDirection
385 * A keybinding signal used internally by GTK+. This signal can't
386 * be used in application code.
388 * Return value: %TRUE if the signal was handled, %FALSE if not
390 toolbar_signals[MOVE_FOCUS] =
391 _gtk_binding_signal_new ("move_focus",
392 G_TYPE_FROM_CLASS (klass),
393 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
394 G_CALLBACK (gtk_toolbar_move_focus),
396 _gtk_marshal_BOOLEAN__ENUM,
398 GTK_TYPE_DIRECTION_TYPE);
400 * GtkToolbar::focus-home-or-end:
401 * @toolbar: the #GtkToolbar which emitted the signal
402 * @focus_home: %TRUE if the first item should be focused
404 * A keybinding signal used internally by GTK+. This signal can't
405 * be used in application code
407 * Return value: %TRUE if the signal was handled, %FALSE if not
409 toolbar_signals[FOCUS_HOME_OR_END] =
410 _gtk_binding_signal_new ("focus_home_or_end",
411 G_OBJECT_CLASS_TYPE (klass),
412 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
413 G_CALLBACK (gtk_toolbar_focus_home_or_end),
415 _gtk_marshal_BOOLEAN__BOOLEAN,
420 g_object_class_install_property (gobject_class,
422 g_param_spec_enum ("orientation",
424 _("The orientation of the toolbar"),
425 GTK_TYPE_ORIENTATION,
426 GTK_ORIENTATION_HORIZONTAL,
429 g_object_class_install_property (gobject_class,
431 g_param_spec_enum ("toolbar_style",
433 _("How to draw the toolbar"),
434 GTK_TYPE_TOOLBAR_STYLE,
437 g_object_class_install_property (gobject_class,
439 g_param_spec_boolean ("show_arrow",
441 _("If an arrow should be shown if the toolbar doesn't fit"),
445 /* child properties */
446 gtk_container_class_install_child_property (container_class,
448 g_param_spec_boolean ("expand",
450 _("Whether the item should receive extra space when the toolbar grows"),
454 gtk_container_class_install_child_property (container_class,
455 CHILD_PROP_HOMOGENEOUS,
456 g_param_spec_boolean ("homogeneous",
458 _("Whether the item should be the same size as other homogeneous items"),
462 gtk_container_class_install_child_property (container_class,
464 g_param_spec_uint ("pack_end",
466 _("Whether the item is positioned at the end of the toolbar"),
470 /* style properties */
471 gtk_widget_class_install_style_property (widget_class,
472 g_param_spec_int ("space_size",
474 _("Size of spacers"),
480 gtk_widget_class_install_style_property (widget_class,
481 g_param_spec_int ("internal_padding",
482 _("Internal padding"),
483 _("Amount of border space between the toolbar shadow and the buttons"),
489 gtk_widget_class_install_style_property (widget_class,
490 g_param_spec_enum ("space_style",
492 _("Whether spacers are vertical lines or just blank"),
493 GTK_TYPE_TOOLBAR_SPACE_STYLE,
497 gtk_widget_class_install_style_property (widget_class,
498 g_param_spec_enum ("button_relief",
500 _("Type of bevel around toolbar buttons"),
501 GTK_TYPE_RELIEF_STYLE,
504 gtk_widget_class_install_style_property (widget_class,
505 g_param_spec_enum ("shadow_type",
507 _("Style of bevel around the toolbar"),
508 GTK_TYPE_SHADOW_TYPE,
512 gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-style",
514 _("Whether default toolbars have text only, text and icons, icons only, etc."),
515 GTK_TYPE_TOOLBAR_STYLE,
516 DEFAULT_TOOLBAR_STYLE,
519 gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-icon-size",
520 _("Toolbar icon size"),
521 _("Size of icons in default toolbars"),
526 binding_set = gtk_binding_set_by_class (klass);
528 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
529 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
530 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
531 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
533 gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
534 "focus_home_or_end", 1,
535 G_TYPE_BOOLEAN, TRUE);
536 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
537 "focus_home_or_end", 1,
538 G_TYPE_BOOLEAN, TRUE);
539 gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
540 "focus_home_or_end", 1,
541 G_TYPE_BOOLEAN, FALSE);
542 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
543 "focus_home_or_end", 1,
544 G_TYPE_BOOLEAN, FALSE);
546 add_ctrl_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
547 add_ctrl_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
549 g_type_class_add_private (gobject_class, sizeof (GtkToolbarPrivate));
553 gtk_toolbar_init (GtkToolbar *toolbar)
555 GtkToolbarPrivate *priv;
557 GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS);
558 GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
560 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
562 toolbar->orientation = GTK_ORIENTATION_HORIZONTAL;
563 toolbar->style = DEFAULT_TOOLBAR_STYLE;
564 toolbar->icon_size = DEFAULT_ICON_SIZE;
565 toolbar->tooltips = gtk_tooltips_new ();
566 g_object_ref (toolbar->tooltips);
567 gtk_object_sink (GTK_OBJECT (toolbar->tooltips));
569 priv->arrow_button = gtk_toggle_button_new ();
570 g_signal_connect (priv->arrow_button, "button_press_event",
571 G_CALLBACK (gtk_toolbar_arrow_button_press), toolbar);
572 g_signal_connect (priv->arrow_button, "clicked",
573 G_CALLBACK (gtk_toolbar_arrow_button_clicked), toolbar);
574 gtk_button_set_relief (GTK_BUTTON (priv->arrow_button),
575 get_button_relief (toolbar));
577 priv->api_mode = DONT_KNOW;
579 gtk_button_set_focus_on_click (GTK_BUTTON (priv->arrow_button), FALSE);
581 priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
582 gtk_widget_set_name (priv->arrow, "gtk-toolbar-arrow");
583 gtk_widget_show (priv->arrow);
584 gtk_container_add (GTK_CONTAINER (priv->arrow_button), priv->arrow);
586 gtk_widget_set_parent (priv->arrow_button, GTK_WIDGET (toolbar));
588 /* which child position a drop will occur at */
589 priv->drop_index = -1;
590 priv->drag_highlight = NULL;
593 priv->show_arrow = TRUE;
594 priv->settings = NULL;
598 toolbar_item_visible (GtkToolbar *toolbar,
601 if (GTK_WIDGET_VISIBLE (item) &&
602 ((toolbar->orientation == GTK_ORIENTATION_HORIZONTAL &&
603 gtk_tool_item_get_visible_horizontal (item)) ||
604 (toolbar->orientation == GTK_ORIENTATION_VERTICAL &&
605 gtk_tool_item_get_visible_vertical (item))))
607 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
609 /* With the old toolbar you could hide a button by calling gtk_widget_hide()
610 * on it. This doesn't work with the new API because the GtkToolItem will not be
613 if (priv->api_mode == OLD_API)
615 GtkWidget *bin_child = GTK_BIN (item)->child;
617 if (bin_child && !GTK_WIDGET_VISIBLE (bin_child))
628 toolbar_item_is_homogeneous (GtkToolbar *toolbar,
632 GtkWidget *widget = GTK_WIDGET (item);
633 GtkRequisition requisition;
634 PangoContext *context;
635 PangoFontMetrics *metrics;
637 gint max_homogeneous_pixels;
639 context = gtk_widget_get_pango_context (widget);
640 metrics = pango_context_get_metrics (context,
641 widget->style->font_desc,
642 pango_context_get_language (context));
643 char_width = pango_font_metrics_get_approximate_char_width (metrics);
644 pango_font_metrics_unref (metrics);
646 max_homogeneous_pixels = PANGO_PIXELS (MAX_HOMOGENEOUS_N_CHARS * char_width);
648 result = gtk_tool_item_get_homogeneous (item) && !GTK_IS_SEPARATOR_TOOL_ITEM (item);
650 gtk_widget_size_request (GTK_WIDGET (item), &requisition);
652 if ((gtk_tool_item_get_is_important (item) &&
653 toolbar->style == GTK_TOOLBAR_BOTH_HORIZ &&
654 toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) ||
655 requisition.width > max_homogeneous_pixels)
664 toolbar_item_set_is_overflow (GtkToolItem *item,
665 gboolean is_overflow)
667 g_object_set_data (G_OBJECT (item), "gtk-toolbar-item-is-overflow", GINT_TO_POINTER (is_overflow));
671 toolbar_item_get_is_overflow (GtkToolItem *item)
675 result = g_object_get_data (G_OBJECT (item), "gtk-toolbar-item-is-overflow");
677 return GPOINTER_TO_INT (result);
681 gtk_toolbar_set_property (GObject *object,
686 GtkToolbar *toolbar = GTK_TOOLBAR (object);
690 case PROP_ORIENTATION:
691 gtk_toolbar_set_orientation (toolbar, g_value_get_enum (value));
693 case PROP_TOOLBAR_STYLE:
694 gtk_toolbar_set_style (toolbar, g_value_get_enum (value));
696 case PROP_SHOW_ARROW:
697 gtk_toolbar_set_show_arrow (toolbar, g_value_get_boolean (value));
700 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
706 gtk_toolbar_get_property (GObject *object,
711 GtkToolbar *toolbar = GTK_TOOLBAR (object);
712 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
716 case PROP_ORIENTATION:
717 g_value_set_enum (value, toolbar->orientation);
719 case PROP_TOOLBAR_STYLE:
720 g_value_set_enum (value, toolbar->style);
722 case PROP_SHOW_ARROW:
723 g_value_set_boolean (value, priv->show_arrow);
726 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
732 gtk_toolbar_map (GtkWidget *widget)
734 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
736 GTK_WIDGET_CLASS (parent_class)->map (widget);
738 if (priv->event_window)
739 gdk_window_show_unraised (priv->event_window);
743 gtk_toolbar_unmap (GtkWidget *widget)
745 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
747 if (priv->event_window)
748 gdk_window_hide (priv->event_window);
750 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
754 gtk_toolbar_realize (GtkWidget *widget)
756 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
757 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
759 GdkWindowAttr attributes;
760 gint attributes_mask;
763 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
765 border_width = GTK_CONTAINER (widget)->border_width;
767 attributes.wclass = GDK_INPUT_ONLY;
768 attributes.window_type = GDK_WINDOW_CHILD;
769 attributes.x = widget->allocation.x + border_width;
770 attributes.y = widget->allocation.y + border_width;
771 attributes.width = widget->allocation.width - border_width * 2;
772 attributes.height = widget->allocation.height - border_width * 2;
773 attributes.event_mask = gtk_widget_get_events (widget);
774 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
775 GDK_BUTTON_RELEASE_MASK |
776 GDK_ENTER_NOTIFY_MASK |
777 GDK_LEAVE_NOTIFY_MASK);
779 attributes_mask = GDK_WA_X | GDK_WA_Y;
781 widget->window = gtk_widget_get_parent_window (widget);
782 g_object_ref (widget->window);
783 widget->style = gtk_style_attach (widget->style, widget->window);
785 priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
786 &attributes, attributes_mask);
787 gdk_window_set_user_data (priv->event_window, toolbar);
791 gtk_toolbar_unrealize (GtkWidget *widget)
793 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
795 if (priv->drag_highlight)
797 gdk_window_set_user_data (priv->drag_highlight, NULL);
798 gdk_window_destroy (priv->drag_highlight);
799 priv->drag_highlight = NULL;
802 if (priv->event_window)
804 gdk_window_set_user_data (priv->event_window, NULL);
805 gdk_window_destroy (priv->event_window);
806 priv->event_window = NULL;
809 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
810 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
814 gtk_toolbar_expose (GtkWidget *widget,
815 GdkEventExpose *event)
817 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
818 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
823 border_width = GTK_CONTAINER (widget)->border_width;
825 if (GTK_WIDGET_DRAWABLE (widget))
827 gtk_paint_box (widget->style,
829 GTK_WIDGET_STATE (widget),
830 get_shadow_type (toolbar),
831 &event->area, widget, "toolbar",
832 border_width + widget->allocation.x,
833 border_width + widget->allocation.y,
834 widget->allocation.width - 2 * border_width,
835 widget->allocation.height - 2 * border_width);
841 GtkToolItem *item = GTK_TOOL_ITEM (items->data);
843 gtk_container_propagate_expose (GTK_CONTAINER (widget),
850 gtk_container_propagate_expose (GTK_CONTAINER (widget),
858 gtk_toolbar_size_request (GtkWidget *widget,
859 GtkRequisition *requisition)
861 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
862 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
864 gint max_child_height;
865 gint max_child_width;
866 gint max_homogeneous_child_width;
867 gint max_homogeneous_child_height;
868 gint homogeneous_size;
871 gint pack_front_size;
873 GtkRequisition arrow_requisition;
875 max_homogeneous_child_width = 0;
876 max_homogeneous_child_height = 0;
878 max_child_height = 0;
879 for (list = priv->items; list != NULL; list = list->next)
881 GtkRequisition requisition;
882 GtkToolItem *item = list->data;
884 if (!toolbar_item_visible (toolbar, item))
887 gtk_widget_size_request (GTK_WIDGET (item), &requisition);
889 max_child_width = MAX (max_child_width, requisition.width);
890 max_child_height = MAX (max_child_height, requisition.height);
892 if (toolbar_item_is_homogeneous (toolbar, item))
894 max_homogeneous_child_width = MAX (max_homogeneous_child_width, requisition.width);
895 max_homogeneous_child_height = MAX (max_homogeneous_child_height, requisition.height);
899 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
900 homogeneous_size = max_homogeneous_child_width;
902 homogeneous_size = max_homogeneous_child_height;
906 for (list = priv->items; list != NULL; list = list->next)
908 GtkToolItem *item = list->data;
911 if (!toolbar_item_visible (toolbar, item))
914 if (toolbar_item_is_homogeneous (toolbar, item))
916 size = homogeneous_size;
920 GtkRequisition requisition;
922 gtk_widget_size_request (GTK_WIDGET (item), &requisition);
924 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
925 size = requisition.width;
927 size = requisition.height;
930 if (gtk_tool_item_get_pack_end (item))
931 pack_end_size += size;
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 + pack_end_size);
952 arrow_requisition.height = 0;
953 arrow_requisition.width = 0;
955 long_req = pack_end_size + 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 fixup_allocation_for_rtl (gint total_size,
987 GtkAllocation *allocation)
989 allocation->x += (total_size - (2 * allocation->x + allocation->width));
993 fixup_allocation_for_vertical (GtkAllocation *allocation)
998 allocation->x = allocation->y;
1001 tmp = allocation->width;
1002 allocation->width = allocation->height;
1003 allocation->height = tmp;
1007 get_item_size (GtkToolbar *toolbar,
1010 GtkRequisition requisition;
1011 GtkToolItem *item = GTK_TOOL_ITEM (child);
1013 gtk_widget_get_child_requisition (child, &requisition);
1015 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1017 if (toolbar_item_is_homogeneous (toolbar, item))
1018 return toolbar->button_maxw;
1020 return requisition.width;
1024 if (toolbar_item_is_homogeneous (toolbar, item))
1025 return toolbar->button_maxh;
1027 return requisition.height;
1032 gtk_toolbar_size_allocate (GtkWidget *widget,
1033 GtkAllocation *allocation)
1035 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1036 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1037 GtkAllocation *allocations;
1038 GtkAllocation arrow_allocation;
1040 gint size, pos, short_size;
1043 gboolean need_arrow;
1044 gint n_expand_items;
1046 gint available_size;
1050 GtkRequisition arrow_requisition;
1052 widget->allocation = *allocation;
1054 border_width = GTK_CONTAINER (toolbar)->border_width;
1056 if (GTK_WIDGET_REALIZED (widget))
1058 gdk_window_move_resize (priv->event_window,
1059 allocation->x + border_width,
1060 allocation->y + border_width,
1061 allocation->width - border_width * 2,
1062 allocation->height - border_width * 2);
1065 border_width += get_internal_padding (toolbar);
1067 gtk_widget_get_child_requisition (GTK_WIDGET (priv->arrow_button),
1068 &arrow_requisition);
1070 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1072 available_size = size = allocation->width - 2 * border_width;
1073 short_size = allocation->height - 2 * border_width;
1074 arrow_size = arrow_requisition.width;
1076 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1078 available_size -= 2 * widget->style->xthickness;
1079 short_size -= 2 * widget->style->ythickness;
1084 available_size = size = allocation->height - 2 * border_width;
1085 short_size = allocation->width - 2 * border_width;
1086 arrow_size = arrow_requisition.height;
1088 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1090 available_size -= 2 * widget->style->ythickness;
1091 short_size -= 2 * widget->style->xthickness;
1095 n_items = g_list_length (priv->items);
1096 allocations = g_new0 (GtkAllocation, n_items);
1099 for (list = priv->items; list != NULL; list = list->next)
1101 GtkToolItem *item = list->data;
1103 if (toolbar_item_visible (toolbar, item))
1104 needed_size += get_item_size (toolbar, GTK_WIDGET (item));
1107 need_arrow = (needed_size > available_size) && priv->show_arrow && priv->api_mode == NEW_API;
1110 size = available_size - arrow_size;
1112 size = available_size;
1114 items = g_list_copy (priv->items);
1116 /* calculate widths of pack end items */
1117 for (list = g_list_last (items), i = 0; list != NULL; list = list->prev, ++i)
1119 GtkToolItem *item = list->data;
1120 GtkAllocation *allocation = &(allocations[n_items - i - 1]);
1123 if (!gtk_tool_item_get_pack_end (item) ||
1124 !toolbar_item_visible (toolbar, item))
1127 item_size = get_item_size (toolbar, GTK_WIDGET (item));
1128 if (item_size <= size)
1131 allocation->width = item_size;
1132 toolbar_item_set_is_overflow (item, FALSE);
1139 if (gtk_tool_item_get_pack_end (item))
1140 toolbar_item_set_is_overflow (item, TRUE);
1148 /* calculate widths of pack front items */
1149 for (list = items, i = 0; list != NULL; list = list->next, ++i)
1151 GtkToolItem *item = list->data;
1154 if (gtk_tool_item_get_pack_end (item) || !toolbar_item_visible (toolbar, item))
1157 item_size = get_item_size (toolbar, GTK_WIDGET (item));
1158 if (item_size <= size)
1161 allocations[i].width = item_size;
1162 toolbar_item_set_is_overflow (item, FALSE);
1169 if (!gtk_tool_item_get_pack_end (item))
1170 toolbar_item_set_is_overflow (item, TRUE);
1179 arrow_allocation.width = arrow_size;
1180 arrow_allocation.height = short_size;
1183 /* expand expandable items */
1185 for (list = priv->items; list != NULL; list = list->next)
1187 GtkToolItem *item = list->data;
1189 if (toolbar_item_visible (toolbar, item) &&
1190 gtk_tool_item_get_expand (item) &&
1191 !toolbar_item_get_is_overflow (item) &&
1192 !GTK_IS_SEPARATOR_TOOL_ITEM (item))
1198 for (list = items, i = 0; list != NULL; list = list->next, ++i)
1200 GtkToolItem *item = list->data;
1202 if (toolbar_item_visible (toolbar, item) && gtk_tool_item_get_expand (item) &&
1203 !toolbar_item_get_is_overflow (item) &&
1204 !GTK_IS_SEPARATOR_TOOL_ITEM (item))
1206 gint extra = size / n_expand_items;
1207 if (size % n_expand_items != 0)
1210 allocations[i].width += extra;
1216 g_assert (n_expand_items == 0);
1218 /* position pack front items */
1220 for (list = items, i = 0; list != NULL; list = list->next, ++i)
1222 GtkToolItem *item = list->data;
1224 if (toolbar_item_visible (toolbar, item) && !toolbar_item_get_is_overflow (item) && !gtk_tool_item_get_pack_end (item))
1226 allocations[i].x = pos;
1227 allocations[i].y = border_width;
1228 allocations[i].height = short_size;
1230 pos += allocations[i].width;
1234 /* position pack end items */
1235 pos = available_size + border_width;
1236 for (list = g_list_last (items), i = 0; list != NULL; list = list->prev, ++i)
1238 GtkToolItem *item = list->data;
1240 if (toolbar_item_visible (toolbar, item) && !toolbar_item_get_is_overflow (item) && gtk_tool_item_get_pack_end (item))
1242 GtkAllocation *allocation = &(allocations[n_items - i - 1]);
1244 allocation->x = pos - allocation->width;
1245 allocation->y = border_width;
1246 allocation->height = short_size;
1248 pos -= allocation->width;
1252 /* position arrow */
1255 arrow_allocation.x = pos - arrow_allocation.width;
1256 arrow_allocation.y = border_width;
1259 /* fix up allocations in the vertical or RTL cases */
1260 if (toolbar->orientation == GTK_ORIENTATION_VERTICAL)
1262 for (i = 0; i < n_items; ++i)
1263 fixup_allocation_for_vertical (&(allocations[i]));
1266 fixup_allocation_for_vertical (&arrow_allocation);
1268 else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1270 for (i = 0; i < n_items; ++i)
1271 fixup_allocation_for_rtl (available_size, &(allocations[i]));
1274 fixup_allocation_for_rtl (available_size, &arrow_allocation);
1277 /* translate the items by allocation->(x,y) */
1278 for (i = 0; i < n_items; ++i)
1280 allocations[i].x += allocation->x;
1281 allocations[i].y += allocation->y;
1283 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1285 allocations[i].x += widget->style->xthickness;
1286 allocations[i].y += widget->style->ythickness;
1292 arrow_allocation.x += allocation->x;
1293 arrow_allocation.y += allocation->y;
1295 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1297 arrow_allocation.x += widget->style->xthickness;
1298 arrow_allocation.y += widget->style->ythickness;
1302 /* finally allocate the items */
1303 for (list = items, i = 0; list != NULL; list = list->next, i++)
1305 GtkToolItem *item = list->data;
1307 if (toolbar_item_visible (toolbar, item) && !toolbar_item_get_is_overflow (item))
1309 gtk_widget_size_allocate (GTK_WIDGET (item), &(allocations[i]));
1310 gtk_widget_set_child_visible (GTK_WIDGET (item), TRUE);
1314 gtk_widget_set_child_visible (GTK_WIDGET (item), FALSE);
1320 gtk_widget_size_allocate (GTK_WIDGET (priv->arrow_button),
1322 gtk_widget_show (GTK_WIDGET (priv->arrow_button));
1326 gtk_widget_hide (GTK_WIDGET (priv->arrow_button));
1329 g_free (allocations);
1330 g_list_free (items);
1334 gtk_toolbar_style_set (GtkWidget *widget,
1335 GtkStyle *prev_style)
1337 if (GTK_WIDGET_REALIZED (widget))
1338 gtk_style_set_background (widget->style, widget->window, widget->state);
1341 gtk_toolbar_update_button_relief (GTK_TOOLBAR (widget));
1345 gtk_toolbar_direction_changed (GtkWidget *widget,
1346 GtkTextDirection previous_dir)
1348 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1349 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1351 if (toolbar->orientation == GTK_ORIENTATION_VERTICAL)
1353 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1354 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
1356 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_LEFT, GTK_SHADOW_NONE);
1359 GTK_WIDGET_CLASS (parent_class)->direction_changed (widget, previous_dir);
1363 gtk_toolbar_list_children_in_focus_order (GtkToolbar *toolbar,
1364 GtkDirectionType dir)
1366 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1367 GList *result = NULL;
1371 /* generate list of children in reverse logical order */
1373 for (list = priv->items; list != NULL; list = list->next)
1375 GtkToolItem *item = list->data;
1376 if (!gtk_tool_item_get_pack_end (item))
1377 result = g_list_prepend (result, item);
1380 result = g_list_prepend (result, priv->arrow_button);
1382 for (list = priv->items; list != NULL; list = list->next)
1384 GtkToolItem *item = list->data;
1386 if (gtk_tool_item_get_pack_end (item))
1387 result = g_list_prepend (result, item);
1390 rtl = (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL);
1392 /* move in logical order when
1394 * - dir is TAB_FORWARD
1396 * - in RTL mode and moving left or up
1398 * - in LTR mode and moving right or down
1400 if (dir == GTK_DIR_TAB_FORWARD ||
1401 (rtl && (dir == GTK_DIR_UP || dir == GTK_DIR_LEFT)) ||
1402 (!rtl && (dir == GTK_DIR_DOWN || dir == GTK_DIR_RIGHT)))
1404 result = g_list_reverse (result);
1411 gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
1412 gboolean focus_home)
1414 GList *children, *list;
1415 GtkDirectionType dir = focus_home? GTK_DIR_RIGHT : GTK_DIR_LEFT;
1417 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1419 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1421 children = g_list_reverse (children);
1423 dir = (dir == GTK_DIR_RIGHT)? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1426 for (list = children; list != NULL; list = list->next)
1428 GtkWidget *child = list->data;
1430 if (GTK_CONTAINER (toolbar)->focus_child == child)
1433 if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1437 g_list_free (children);
1442 /* Keybinding handler. This function is called when the user presses
1443 * Ctrl TAB or an arrow key.
1446 gtk_toolbar_move_focus (GtkToolbar *toolbar,
1447 GtkDirectionType dir)
1450 gboolean try_focus = FALSE;
1452 GtkContainer *container = GTK_CONTAINER (toolbar);
1454 if (container->focus_child &&
1455 gtk_widget_child_focus (container->focus_child, dir))
1460 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1462 for (list = children; list != NULL; list = list->next)
1464 GtkWidget *child = list->data;
1466 if (try_focus && GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1469 if (child == GTK_CONTAINER (toolbar)->focus_child)
1473 g_list_free (children);
1478 /* The focus handler for the toolbar. It called when the user presses
1479 * TAB or otherwise tries to focus the toolbar.
1482 gtk_toolbar_focus (GtkWidget *widget,
1483 GtkDirectionType dir)
1485 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1486 GList *children, *list;
1488 /* if focus is already somewhere inside the toolbar then return FALSE.
1489 * The only way focus can stay inside the toolbar is when the user presses
1490 * arrow keys or Ctrl TAB (both of which are handled by the
1491 * gtk_toolbar_move_focus() keybinding function.
1493 if (GTK_CONTAINER (widget)->focus_child)
1496 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1498 for (list = children; list != NULL; list = list->next)
1500 GtkWidget *child = list->data;
1502 if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1506 g_list_free (children);
1512 style_change_notify (GtkToolbar *toolbar)
1514 if (!toolbar->style_set)
1516 /* pretend it was set, then unset, thus reverting to new default */
1517 toolbar->style_set = TRUE;
1518 gtk_toolbar_unset_style (toolbar);
1523 icon_size_change_notify (GtkToolbar *toolbar)
1525 if (!toolbar->icon_size_set)
1527 /* pretend it was set, then unset, thus reverting to new default */
1528 toolbar->icon_size_set = TRUE;
1529 gtk_toolbar_unset_icon_size (toolbar);
1533 static GtkSettings *
1534 toolbar_get_settings (GtkToolbar *toolbar)
1536 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1537 return priv->settings;
1541 gtk_toolbar_screen_changed (GtkWidget *widget,
1542 GdkScreen *previous_screen)
1544 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
1545 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1546 GtkSettings *old_settings = toolbar_get_settings (toolbar);
1547 GtkSettings *settings;
1549 if (gtk_widget_has_screen (GTK_WIDGET (toolbar)))
1550 settings = gtk_widget_get_settings (GTK_WIDGET (toolbar));
1554 if (settings == old_settings)
1559 g_signal_handler_disconnect (old_settings, toolbar->style_set_connection);
1560 g_signal_handler_disconnect (old_settings, toolbar->icon_size_connection);
1562 g_object_unref (old_settings);
1567 toolbar->style_set_connection =
1568 g_signal_connect_swapped (settings,
1569 "notify::gtk-toolbar-style",
1570 G_CALLBACK (style_change_notify),
1572 toolbar->icon_size_connection =
1573 g_signal_connect_swapped (settings,
1574 "notify::gtk-toolbar-icon-size",
1575 G_CALLBACK (icon_size_change_notify),
1578 g_object_ref (settings);
1579 priv->settings = settings;
1582 priv->settings = NULL;
1584 style_change_notify (toolbar);
1585 icon_size_change_notify (toolbar);
1589 find_drop_pos (GtkToolbar *toolbar,
1595 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1596 GtkOrientation orientation;
1597 GtkTextDirection direction;
1601 gint best_distance, best_pos, best_index, index;
1603 orientation = toolbar->orientation;
1604 direction = gtk_widget_get_direction (GTK_WIDGET (toolbar));
1605 border_width = GTK_CONTAINER (toolbar)->border_width + get_internal_padding (toolbar);
1607 items = priv->items;
1611 if (orientation == GTK_ORIENTATION_HORIZONTAL)
1613 if (direction == GTK_TEXT_DIR_LTR)
1614 *drop_pos = border_width;
1616 *drop_pos = GTK_WIDGET (toolbar)->allocation.width - border_width;
1620 *drop_pos = border_width;
1625 /* initial conditions */
1626 item = GTK_TOOL_ITEM (items->data);
1628 if (orientation == GTK_ORIENTATION_HORIZONTAL)
1630 if (direction == GTK_TEXT_DIR_LTR)
1631 best_pos = GTK_WIDGET (item)->allocation.x;
1633 best_pos = GTK_WIDGET (item)->allocation.x +
1634 GTK_WIDGET (item)->allocation.width;
1635 best_distance = ABS (best_pos - x);
1639 best_pos = GTK_WIDGET (item)->allocation.y;
1640 best_distance = ABS (best_pos - y);
1646 item = GTK_TOOL_ITEM (items->data);
1648 if (GTK_WIDGET_DRAWABLE (item) && !gtk_tool_item_get_pack_end (item))
1652 if (orientation == GTK_ORIENTATION_HORIZONTAL)
1654 if (direction == GTK_TEXT_DIR_LTR)
1655 pos = GTK_WIDGET (item)->allocation.x +
1656 GTK_WIDGET (item)->allocation.width;
1658 pos = GTK_WIDGET (item)->allocation.x;
1659 distance = ABS (pos - x);
1663 pos = GTK_WIDGET (item)->allocation.y +
1664 GTK_WIDGET (item)->allocation.height;
1665 distance = ABS (pos - y);
1667 if (distance < best_distance)
1671 best_distance = distance;
1674 items = items->next;
1676 *drop_index = best_index;
1677 *drop_pos = best_pos;
1681 gtk_toolbar_drag_leave (GtkWidget *widget,
1682 GdkDragContext *context,
1685 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1686 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1688 if (priv->drag_highlight)
1690 gdk_window_set_user_data (priv->drag_highlight, NULL);
1691 gdk_window_destroy (priv->drag_highlight);
1692 priv->drag_highlight = NULL;
1695 priv->drop_index = -1;
1699 gtk_toolbar_drag_motion (GtkWidget *widget,
1700 GdkDragContext *context,
1705 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1706 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1707 gint new_index, new_pos;
1709 find_drop_pos(toolbar, x, y, &new_index, &new_pos);
1711 if (!priv->drag_highlight)
1713 GdkWindowAttr attributes;
1714 guint attributes_mask;
1716 attributes.window_type = GDK_WINDOW_CHILD;
1717 attributes.wclass = GDK_INPUT_OUTPUT;
1718 attributes.visual = gtk_widget_get_visual (widget);
1719 attributes.colormap = gtk_widget_get_colormap (widget);
1720 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
1721 attributes.width = 1;
1722 attributes.height = 1;
1723 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
1724 priv->drag_highlight = gdk_window_new (widget->window,
1725 &attributes, attributes_mask);
1726 gdk_window_set_user_data (priv->drag_highlight, widget);
1727 gdk_window_set_background (priv->drag_highlight,
1728 &widget->style->fg[widget->state]);
1731 if (priv->drop_index < 0 ||
1732 priv->drop_index != new_index)
1734 gint border_width = GTK_CONTAINER (toolbar)->border_width;
1735 priv->drop_index = new_index;
1736 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1738 gdk_window_move_resize (priv->drag_highlight,
1739 widget->allocation.x + new_pos - 1,
1740 widget->allocation.y + border_width,
1741 2, widget->allocation.height-border_width*2);
1745 gdk_window_move_resize (priv->drag_highlight,
1746 widget->allocation.x + border_width,
1747 widget->allocation.y + new_pos - 1,
1748 widget->allocation.width-border_width*2, 2);
1752 gdk_window_show (priv->drag_highlight);
1754 gdk_drag_status (context, context->suggested_action, time_);
1760 gtk_toolbar_get_child_property (GtkContainer *container,
1766 GtkToolItem *item = GTK_TOOL_ITEM (child);
1768 switch (property_id)
1770 case CHILD_PROP_PACK_END:
1771 g_value_set_boolean (value, gtk_tool_item_get_pack_end (item));
1774 case CHILD_PROP_HOMOGENEOUS:
1775 g_value_set_boolean (value, gtk_tool_item_get_homogeneous (item));
1778 case CHILD_PROP_EXPAND:
1779 g_value_set_boolean (value, gtk_tool_item_get_expand (item));
1783 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1789 gtk_toolbar_set_child_property (GtkContainer *container,
1792 const GValue *value,
1795 switch (property_id)
1797 case CHILD_PROP_PACK_END:
1798 gtk_tool_item_set_pack_end (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
1801 case CHILD_PROP_HOMOGENEOUS:
1802 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
1805 case CHILD_PROP_EXPAND:
1806 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
1810 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
1816 gtk_toolbar_add (GtkContainer *container,
1819 GtkToolbar *toolbar;
1821 g_return_if_fail (GTK_IS_TOOLBAR (container));
1822 g_return_if_fail (widget != NULL);
1824 toolbar = GTK_TOOLBAR (container);
1826 if (GTK_IS_TOOL_ITEM (widget))
1827 gtk_toolbar_insert (toolbar, GTK_TOOL_ITEM (widget), 0);
1829 gtk_toolbar_append_widget (toolbar, widget, NULL, NULL);
1833 gtk_toolbar_remove (GtkContainer *container,
1836 GtkToolbar *toolbar;
1837 GtkToolItem *item = NULL;
1839 g_return_if_fail (GTK_IS_TOOLBAR (container));
1840 g_return_if_fail (GTK_IS_WIDGET (widget));
1842 toolbar = GTK_TOOLBAR (container);
1844 if (GTK_IS_TOOL_ITEM (widget))
1846 item = GTK_TOOL_ITEM (widget);
1850 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1853 for (list = priv->items; list != NULL; list = list->next)
1855 if (GTK_BIN (list->data)->child == widget)
1863 g_return_if_fail (item != NULL);
1865 gtk_toolbar_remove_tool_item (GTK_TOOLBAR (container), item);
1869 gtk_toolbar_forall (GtkContainer *container,
1870 gboolean include_internals,
1871 GtkCallback callback,
1872 gpointer callback_data)
1874 GtkToolbar *toolbar = GTK_TOOLBAR (container);
1875 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1878 g_return_if_fail (callback != NULL);
1880 items = priv->items;
1884 GtkToolItem *item = GTK_TOOL_ITEM (items->data);
1886 items = items->next;
1888 (*callback) (GTK_WIDGET (item), callback_data);
1891 if (include_internals)
1892 (* callback) (priv->arrow_button, callback_data);
1896 gtk_toolbar_child_type (GtkContainer *container)
1898 return GTK_TYPE_TOOL_ITEM;
1902 gtk_toolbar_reconfigured (GtkToolbar *toolbar)
1904 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1907 items = priv->items;
1910 GtkToolItem *item = GTK_TOOL_ITEM (items->data);
1912 _gtk_tool_item_toolbar_reconfigured (item);
1914 items = items->next;
1919 gtk_toolbar_real_orientation_changed (GtkToolbar *toolbar,
1920 GtkOrientation orientation)
1922 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1923 if (toolbar->orientation != orientation)
1925 toolbar->orientation = orientation;
1927 if (orientation == GTK_ORIENTATION_HORIZONTAL)
1928 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1929 else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
1930 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
1932 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_LEFT, GTK_SHADOW_NONE);
1934 gtk_toolbar_reconfigured (toolbar);
1936 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1937 g_object_notify (G_OBJECT (toolbar), "orientation");
1942 gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
1943 GtkToolbarStyle style)
1945 if (toolbar->style != style)
1947 toolbar->style = style;
1949 gtk_toolbar_reconfigured (toolbar);
1951 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
1952 g_object_notify (G_OBJECT (toolbar), "toolbar_style");
1957 menu_position_func (GtkMenu *menu,
1963 GtkToolbar *toolbar = GTK_TOOLBAR (user_data);
1964 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1966 GtkRequisition menu_req;
1968 gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y);
1969 gtk_widget_size_request (priv->arrow_button, &req);
1970 gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
1972 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1974 *y += priv->arrow_button->allocation.height;
1975 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
1976 *x += priv->arrow_button->allocation.width - req.width;
1978 *x += req.width - menu_req.width;
1982 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
1983 *x += priv->arrow_button->allocation.width;
1985 *x -= menu_req.width;
1986 *y += priv->arrow_button->allocation.height - req.height;
1993 menu_deactivated (GtkWidget *menu,
1994 GtkToolbar *toolbar)
1996 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1998 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->arrow_button), FALSE);
2002 remove_item (GtkWidget *menu_item,
2005 gtk_container_remove (GTK_CONTAINER (menu_item->parent), menu_item);
2009 show_menu (GtkToolbar *toolbar,
2010 GdkEventButton *event)
2012 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2017 gtk_container_foreach (GTK_CONTAINER (priv->menu), remove_item, NULL);
2018 gtk_widget_destroy (GTK_WIDGET (priv->menu));
2021 priv->menu = GTK_MENU (gtk_menu_new ());
2022 g_signal_connect (priv->menu, "deactivate", G_CALLBACK (menu_deactivated), toolbar);
2024 for (list = priv->items; list != NULL; list = list->next)
2026 GtkToolItem *item = list->data;
2028 if (toolbar_item_visible (toolbar, item) && toolbar_item_get_is_overflow (item))
2030 GtkWidget *menu_item = gtk_tool_item_retrieve_proxy_menu_item (item);
2034 g_assert (GTK_IS_MENU_ITEM (menu_item));
2035 gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_item);
2040 gtk_widget_show_all (GTK_WIDGET (priv->menu));
2042 gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL,
2043 menu_position_func, toolbar,
2044 event? event->button : 0, event? event->time : gtk_get_current_event_time());
2048 gtk_toolbar_arrow_button_clicked (GtkWidget *button,
2049 GtkToolbar *toolbar)
2051 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2053 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->arrow_button)) &&
2054 (!priv->menu || !GTK_WIDGET_VISIBLE (GTK_WIDGET (priv->menu))))
2056 /* We only get here when the button is clicked with the keybaord,
2057 * because mouse button presses result in the menu being shown so
2058 * that priv->menu would be non-NULL and visible.
2060 show_menu (toolbar, NULL);
2061 gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menu), FALSE);
2066 gtk_toolbar_arrow_button_press (GtkWidget *button,
2067 GdkEventButton *event,
2068 GtkToolbar *toolbar)
2070 show_menu (toolbar, event);
2071 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2077 gtk_toolbar_button_press (GtkWidget *toolbar,
2078 GdkEventButton *event)
2080 if (event->button == 3)
2082 gboolean return_value;
2084 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2085 (int)event->x_root, (int)event->y_root, event->button,
2088 return return_value;
2095 gtk_toolbar_popup_menu (GtkWidget *toolbar)
2097 gboolean return_value;
2098 /* This function is the handler for the "popup menu" keybinding,
2099 * ie., it is called when the user presses Shift F10
2101 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2102 -1, -1, -1, &return_value);
2104 return return_value;
2108 gtk_toolbar_update_button_relief (GtkToolbar *toolbar)
2110 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2112 gtk_toolbar_reconfigured (toolbar);
2114 gtk_button_set_relief (GTK_BUTTON (priv->arrow_button), get_button_relief (toolbar));
2117 static GtkReliefStyle
2118 get_button_relief (GtkToolbar *toolbar)
2120 GtkReliefStyle button_relief = GTK_RELIEF_NORMAL;
2122 gtk_widget_ensure_style (GTK_WIDGET (toolbar));
2124 gtk_widget_style_get (GTK_WIDGET (toolbar),
2125 "button_relief", &button_relief,
2128 return button_relief;
2132 get_internal_padding (GtkToolbar *toolbar)
2136 gtk_widget_style_get (GTK_WIDGET (toolbar),
2137 "internal_padding", &ipadding,
2143 static GtkShadowType
2144 get_shadow_type (GtkToolbar *toolbar)
2146 GtkShadowType shadow_type;
2148 gtk_widget_style_get (GTK_WIDGET (toolbar),
2149 "shadow_type", &shadow_type,
2156 gtk_toolbar_check_old_api (GtkToolbar *toolbar)
2158 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2160 if (priv->api_mode == NEW_API)
2162 g_warning ("mixing deprecated and non-deprecated GtkToolbar API is not allowed");
2166 priv->api_mode = OLD_API;
2171 gtk_toolbar_check_new_api (GtkToolbar *toolbar)
2173 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2175 if (priv->api_mode == OLD_API)
2177 g_warning ("mixing deprecated and non-deprecated GtkToolbar API is not allowed");
2181 priv->api_mode = NEW_API;
2186 gtk_toolbar_insert_tool_item (GtkToolbar *toolbar,
2190 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2192 priv->items = g_list_insert (priv->items, item, pos);
2193 toolbar->num_children++;
2195 gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar));
2199 gtk_toolbar_remove_tool_item (GtkToolbar *toolbar,
2202 GtkToolbarPrivate *priv;
2206 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2207 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2208 g_return_if_fail (GTK_IS_TOOL_ITEM (item));
2209 g_return_if_fail (g_list_find (priv->items, item));
2213 for (tmp = priv->items; tmp != NULL; tmp = tmp->next)
2215 if (tmp->data == item)
2221 priv->items = g_list_remove (priv->items, item);
2223 gtk_widget_unparent (GTK_WIDGET (item));
2225 if (priv->api_mode == OLD_API)
2227 GtkToolbarChild *toolbar_child;
2229 toolbar_child = g_list_nth_data (toolbar->children, nth_child);
2230 toolbar->children = g_list_remove (toolbar->children, toolbar_child);
2232 g_free (toolbar_child);
2235 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2241 * Creates a new toolbar.
2243 * Return Value: the newly-created toolbar.
2246 gtk_toolbar_new (void)
2248 GtkToolbar *toolbar;
2250 toolbar = g_object_new (GTK_TYPE_TOOLBAR, NULL);
2252 return GTK_WIDGET (toolbar);
2256 * gtk_toolbar_insert:
2257 * @toolbar: a #GtkToolbar
2258 * @item: a #GtkToolItem
2259 * @pos: the position of the new item
2261 * Insert a #GtkToolItem into the toolbar at position @pos. If @pos is
2262 * 0 the item is prepended to the start of the toolbar. If @pos is
2263 * negative, append the item to the end of the toolbar.
2268 gtk_toolbar_insert (GtkToolbar *toolbar,
2272 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2273 g_return_if_fail (GTK_IS_TOOL_ITEM (item));
2275 if (!gtk_toolbar_check_new_api (toolbar))
2278 gtk_toolbar_insert_tool_item (toolbar, item, pos);
2282 * gtk_toolbar_get_item_index:
2283 * @toolbar: a #GtkToolbar
2284 * @item: a #GtkToolItem that is a child of @toolbar
2286 * Returns the position of @item on the toolbar, starting from 0.
2287 * It is an error if @item is not a child of the toolbar.
2289 * Return value: the position of item on the toolbar.
2294 gtk_toolbar_get_item_index (GtkToolbar *toolbar,
2297 GtkToolbarPrivate *priv;
2299 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2300 g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1);
2302 if (!gtk_toolbar_check_new_api (toolbar))
2305 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2306 g_return_val_if_fail (g_list_find (priv->items, item) != NULL, -1);
2308 return g_list_index (priv->items, item);
2312 * gtk_toolbar_set_orientation:
2313 * @toolbar: a #GtkToolbar.
2314 * @orientation: a new #GtkOrientation.
2316 * Sets whether a toolbar should appear horizontally or vertically.
2319 gtk_toolbar_set_orientation (GtkToolbar *toolbar,
2320 GtkOrientation orientation)
2322 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2324 g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0, orientation);
2328 * gtk_toolbar_get_orientation:
2329 * @toolbar: a #GtkToolbar
2331 * Retrieves the current orientation of the toolbar. See
2332 * gtk_toolbar_set_orientation().
2334 * Return value: the orientation
2337 gtk_toolbar_get_orientation (GtkToolbar *toolbar)
2339 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
2341 return toolbar->orientation;
2345 * gtk_toolbar_set_style:
2346 * @toolbar: a #GtkToolbar.
2347 * @style: the new style for @toolbar.
2349 * Alters the view of @toolbar to display either icons only, text only, or both.
2352 gtk_toolbar_set_style (GtkToolbar *toolbar,
2353 GtkToolbarStyle style)
2355 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2357 toolbar->style_set = TRUE;
2358 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2364 * gtk_toolbar_get_style:
2365 * @toolbar: a #GtkToolbar
2367 * Retrieves whether the toolbar has text, icons, or both . See
2368 * gtk_toolbar_set_style().
2370 * Return value: the current style of @toolbar
2373 gtk_toolbar_get_style (GtkToolbar *toolbar)
2375 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_TOOLBAR_STYLE);
2377 return toolbar->style;
2381 * gtk_toolbar_unset_style:
2382 * @toolbar: a #GtkToolbar
2384 * Unsets a toolbar style set with gtk_toolbar_set_style(), so that
2385 * user preferences will be used to determine the toolbar style.
2388 gtk_toolbar_unset_style (GtkToolbar *toolbar)
2390 GtkToolbarStyle style;
2392 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2394 if (toolbar->style_set)
2396 GtkSettings *settings = toolbar_get_settings (toolbar);
2399 g_object_get (settings,
2400 "gtk-toolbar-style", &style,
2403 style = DEFAULT_TOOLBAR_STYLE;
2405 if (style != toolbar->style)
2406 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2408 toolbar->style_set = FALSE;
2413 * gtk_toolbar_set_tooltips:
2414 * @toolbar: a #GtkToolbar.
2415 * @enable: set to %FALSE to disable the tooltips, or %TRUE to enable them.
2417 * Sets if the tooltips of a toolbar should be active or not.
2420 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
2423 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2426 gtk_tooltips_enable (toolbar->tooltips);
2428 gtk_tooltips_disable (toolbar->tooltips);
2432 * gtk_toolbar_get_tooltips:
2433 * @toolbar: a #GtkToolbar
2435 * Retrieves whether tooltips are enabled. See
2436 * gtk_toolbar_set_tooltips().
2438 * Return value: %TRUE if tooltips are enabled
2441 gtk_toolbar_get_tooltips (GtkToolbar *toolbar)
2443 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2445 return toolbar->tooltips->enabled;
2449 * gtk_toolbar_get_n_items:
2450 * @toolbar: a #GtkToolbar
2452 * Returns the number of items on the toolbar.
2454 * Return value: the number of items on the toolbar
2459 gtk_toolbar_get_n_items (GtkToolbar *toolbar)
2461 GtkToolbarPrivate *priv;
2463 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2465 if (!gtk_toolbar_check_new_api (toolbar))
2468 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2470 return g_list_length (priv->items);
2474 * gtk_toolbar_get_nth_item:
2475 * @toolbar: a #GtkToolbar
2476 * @n: A position on the toolbar
2478 * Returns the @n<!-- -->'s item on @toolbar, or %NULL if the
2479 * toolbar does not contain an @n<!-- -->'th item.
2481 * Return value: The @n<!-- -->'th #GtkToolItem on @toolbar, or %NULL if there
2482 * isn't an @n<!-- -->th item.
2487 gtk_toolbar_get_nth_item (GtkToolbar *toolbar,
2490 GtkToolbarPrivate *priv;
2492 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
2494 if (!gtk_toolbar_check_new_api (toolbar))
2497 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2499 return g_list_nth_data (priv->items, n);
2503 * gtk_toolbar_set_icon_size:
2504 * @toolbar: A #GtkToolbar
2505 * @icon_size: The #GtkIconSize that stock icons in the toolbar shall have.
2507 * This function sets the size of stock icons in the toolbar. You
2508 * can call it both before you add the icons and after they've been
2509 * added. The size you set will override user preferences for the default
2513 gtk_toolbar_set_icon_size (GtkToolbar *toolbar,
2514 GtkIconSize icon_size)
2516 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2518 toolbar->icon_size_set = TRUE;
2520 if (toolbar->icon_size == icon_size)
2523 toolbar->icon_size = icon_size;
2525 gtk_toolbar_reconfigured (toolbar);
2527 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2531 * gtk_toolbar_get_icon_size:
2532 * @toolbar: a #GtkToolbar
2534 * Retrieves the icon size fo the toolbar. See gtk_toolbar_set_icon_size().
2536 * Return value: the current icon size for the icons on the toolbar.
2539 gtk_toolbar_get_icon_size (GtkToolbar *toolbar)
2541 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_ICON_SIZE);
2543 return toolbar->icon_size;
2547 * gtk_toolbar_get_relief_style:
2548 * @toolbar: a #GtkToolbar
2550 * Returns the relief style of buttons on @toolbar. See
2551 * gtk_button_set_relief_style().
2553 * Return value: The relief style of buttons on @toolbar.
2558 gtk_toolbar_get_relief_style (GtkToolbar *toolbar)
2560 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_RELIEF_NONE);
2562 return get_button_relief (toolbar);
2566 * gtk_toolbar_unset_icon_size:
2567 * @toolbar: a #GtkToolbar
2569 * Unsets toolbar icon size set with gtk_toolbar_set_icon_size(), so that
2570 * user preferences will be used to determine the icon size.
2573 gtk_toolbar_unset_icon_size (GtkToolbar *toolbar)
2577 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2579 if (toolbar->icon_size_set)
2581 GtkSettings *settings = toolbar_get_settings (toolbar);
2585 g_object_get (settings,
2586 "gtk-toolbar-icon-size", &size,
2590 size = DEFAULT_ICON_SIZE;
2592 if (size != toolbar->icon_size)
2593 gtk_toolbar_set_icon_size (toolbar, size);
2595 toolbar->icon_size_set = FALSE;
2600 * gtk_toolbar_set_show_arrow:
2601 * @toolbar: a #GtkToolbar
2602 * @show_arrow: Whether to show an overflow menu
2604 * Sets whether to show an overflow menu when
2605 * @toolbar doesn't have room for all items on it. If %TRUE,
2606 * items that there are not room are available through an
2612 gtk_toolbar_set_show_arrow (GtkToolbar *toolbar,
2613 gboolean show_arrow)
2615 GtkToolbarPrivate *priv;
2617 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2619 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2620 show_arrow = show_arrow != FALSE;
2622 if (priv->show_arrow != show_arrow)
2624 priv->show_arrow = show_arrow;
2626 if (!priv->show_arrow)
2627 gtk_widget_hide (priv->arrow_button);
2629 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2630 g_object_notify (G_OBJECT (toolbar), "show_arrow");
2635 * gtk_toolbar_get_show_arrow:
2636 * @toolbar: a #GtkToolbar
2638 * Returns whether the toolbar has an overflow menu.
2639 * See gtk_toolbar_set_show_arrow()
2646 gtk_toolbar_get_show_arrow (GtkToolbar *toolbar)
2648 GtkToolbarPrivate *priv;
2650 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2652 if (!gtk_toolbar_check_new_api (toolbar))
2655 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2657 return priv->show_arrow;
2661 * gtk_toolbar_get_drop_index:
2662 * @toolbar: a #GtkToolbar
2663 * @x: x coordinate of a point on the toolbar
2664 * @y: y coordinate of a point on the toolbar
2666 * Returns the position corresponding to the indicated point on
2667 * @toolbar. This is useful when dragging items to the toolbar:
2668 * this function returns the position a new item should be
2671 * @x and @y are in @toolbar coordinates.
2673 * Return value: The position corresponding to the point (@x, @y) on the toolbar.
2678 gtk_toolbar_get_drop_index (GtkToolbar *toolbar,
2682 gint drop_index, drop_pos;
2684 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2686 if (!gtk_toolbar_check_new_api (toolbar))
2689 find_drop_pos (toolbar, x, y, &drop_index, &drop_pos);
2695 * gtk_toolbar_append_item:
2696 * @toolbar: a #GtkToolbar.
2697 * @text: give your toolbar button a label.
2698 * @tooltip_text: a string that appears when the user holds the mouse over this item.
2699 * @tooltip_private_text: use with #GtkTipsQuery.
2700 * @icon: a #GtkWidget that should be used as the button's icon.
2701 * @callback: the function to be executed when the button is pressed.
2702 * @user_data: a pointer to any data you wish to be passed to the callback.
2704 * Inserts a new item into the toolbar. You must specify the position
2705 * in the toolbar where it will be inserted.
2707 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
2708 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
2710 * Return value: the new toolbar item as a #GtkWidget.
2713 gtk_toolbar_append_item (GtkToolbar *toolbar,
2715 const char *tooltip_text,
2716 const char *tooltip_private_text,
2718 GtkSignalFunc callback,
2721 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
2723 tooltip_text, tooltip_private_text,
2724 icon, callback, user_data,
2725 toolbar->num_children);
2729 * gtk_toolbar_prepend_item:
2730 * @toolbar: a #GtkToolbar.
2731 * @text: give your toolbar button a label.
2732 * @tooltip_text: a string that appears when the user holds the mouse over this item.
2733 * @tooltip_private_text: use with #GtkTipsQuery.
2734 * @icon: a #GtkWidget that should be used as the button's icon.
2735 * @callback: the function to be executed when the button is pressed.
2736 * @user_data: a pointer to any data you wish to be passed to the callback.
2738 * Adds a new button to the beginning (top or left edges) of the given toolbar.
2740 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
2741 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
2743 * Return value: the new toolbar item as a #GtkWidget.
2746 gtk_toolbar_prepend_item (GtkToolbar *toolbar,
2748 const char *tooltip_text,
2749 const char *tooltip_private_text,
2751 GtkSignalFunc callback,
2754 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
2756 tooltip_text, tooltip_private_text,
2757 icon, callback, user_data,
2762 * gtk_toolbar_insert_item:
2763 * @toolbar: a #GtkToolbar.
2764 * @text: give your toolbar button a label.
2765 * @tooltip_text: a string that appears when the user holds the mouse over this item.
2766 * @tooltip_private_text: use with #GtkTipsQuery.
2767 * @icon: a #GtkWidget that should be used as the button's icon.
2768 * @callback: the function to be executed when the button is pressed.
2769 * @user_data: a pointer to any data you wish to be passed to the callback.
2770 * @position: the number of widgets to insert this item after.
2772 * Inserts a new item into the toolbar. You must specify the position in the
2773 * toolbar where it will be inserted.
2775 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
2776 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
2778 * Return value: the new toolbar item as a #GtkWidget.
2781 gtk_toolbar_insert_item (GtkToolbar *toolbar,
2783 const char *tooltip_text,
2784 const char *tooltip_private_text,
2786 GtkSignalFunc callback,
2790 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
2792 tooltip_text, tooltip_private_text,
2793 icon, callback, user_data,
2798 * gtk_toolbar_insert_stock:
2799 * @toolbar: A #GtkToolbar
2800 * @stock_id: The id of the stock item you want to insert
2801 * @tooltip_text: The text in the tooltip of the toolbar button
2802 * @tooltip_private_text: The private text of the tooltip
2803 * @callback: The callback called when the toolbar button is clicked.
2804 * @user_data: user data passed to callback
2805 * @position: The position the button shall be inserted at.
2806 * -1 means at the end.
2808 * Inserts a stock item at the specified position of the toolbar. If
2809 * @stock_id is not a known stock item ID, it's inserted verbatim,
2810 * except that underscores used to mark mnemonics are removed.
2812 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
2813 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
2815 * Returns: the inserted widget
2818 gtk_toolbar_insert_stock (GtkToolbar *toolbar,
2819 const gchar *stock_id,
2820 const char *tooltip_text,
2821 const char *tooltip_private_text,
2822 GtkSignalFunc callback,
2826 return gtk_toolbar_internal_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
2828 tooltip_text, tooltip_private_text,
2829 NULL, callback, user_data,
2834 * gtk_toolbar_append_space:
2835 * @toolbar: a #GtkToolbar.
2837 * Adds a new space to the end of the toolbar.
2840 gtk_toolbar_append_space (GtkToolbar *toolbar)
2842 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
2846 toolbar->num_children);
2850 * gtk_toolbar_prepend_space:
2851 * @toolbar: a #GtkToolbar.
2853 * Adds a new space to the beginning of the toolbar.
2856 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
2858 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
2866 * gtk_toolbar_insert_space:
2867 * @toolbar: a #GtkToolbar
2868 * @position: the number of widgets after which a space should be inserted.
2870 * Inserts a new space in the toolbar at the specified position.
2873 gtk_toolbar_insert_space (GtkToolbar *toolbar,
2876 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
2884 * gtk_toolbar_remove_space:
2885 * @toolbar: a #GtkToolbar.
2886 * @position: the index of the space to remove.
2888 * Removes a space from the specified position.
2891 gtk_toolbar_remove_space (GtkToolbar *toolbar,
2896 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2898 if (!gtk_toolbar_check_old_api (toolbar))
2901 item = g_list_nth_data (toolbar->children, position);
2905 g_warning ("Toolbar position %d doesn't exist", position);
2909 if (!GTK_IS_SEPARATOR_TOOL_ITEM (item))
2911 g_warning ("Toolbar position %d is not a space", position);
2915 gtk_toolbar_remove_tool_item (toolbar, item);
2919 * gtk_toolbar_append_widget:
2920 * @toolbar: a #GtkToolbar.
2921 * @widget: a #GtkWidget to add to the toolbar.
2922 * @tooltip_text: the element's tooltip.
2923 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
2925 * Adds a widget to the end of the given toolbar.
2928 gtk_toolbar_append_widget (GtkToolbar *toolbar,
2930 const gchar *tooltip_text,
2931 const gchar *tooltip_private_text)
2933 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
2935 tooltip_text, tooltip_private_text,
2937 toolbar->num_children);
2941 * gtk_toolbar_prepend_widget:
2942 * @toolbar: a #GtkToolbar.
2943 * @widget: a #GtkWidget to add to the toolbar.
2944 * @tooltip_text: the element's tooltip.
2945 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
2947 * Adds a widget to the beginning of the given toolbar.
2950 gtk_toolbar_prepend_widget (GtkToolbar *toolbar,
2952 const gchar *tooltip_text,
2953 const gchar *tooltip_private_text)
2955 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
2957 tooltip_text, tooltip_private_text,
2963 * gtk_toolbar_insert_widget:
2964 * @toolbar: a #GtkToolbar.
2965 * @widget: a #GtkWidget to add to the toolbar.
2966 * @tooltip_text: the element's tooltip.
2967 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
2968 * @position: the number of widgets to insert this widget after.
2970 * Inserts a widget in the toolbar at the given position.
2973 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
2975 const char *tooltip_text,
2976 const char *tooltip_private_text,
2979 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
2981 tooltip_text, tooltip_private_text,
2987 * gtk_toolbar_append_element:
2988 * @toolbar: a #GtkToolbar.
2989 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
2990 * @widget: a #GtkWidget, or %NULL.
2991 * @text: the element's label.
2992 * @tooltip_text: the element's tooltip.
2993 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
2994 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
2995 * @callback: the function to be executed when the button is pressed.
2996 * @user_data: any data you wish to pass to the callback.
2998 * Adds a new element to the end of a toolbar.
3000 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3001 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3002 * the radio group for the new element. In all other cases, @widget must
3005 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3006 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3008 * Return value: the new toolbar element as a #GtkWidget.
3011 gtk_toolbar_append_element (GtkToolbar *toolbar,
3012 GtkToolbarChildType type,
3015 const char *tooltip_text,
3016 const char *tooltip_private_text,
3018 GtkSignalFunc callback,
3021 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3022 tooltip_text, tooltip_private_text,
3023 icon, callback, user_data,
3024 toolbar->num_children);
3028 * gtk_toolbar_prepend_element:
3029 * @toolbar: a #GtkToolbar.
3030 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
3031 * @widget: a #GtkWidget, or %NULL
3032 * @text: the element's label.
3033 * @tooltip_text: the element's tooltip.
3034 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3035 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3036 * @callback: the function to be executed when the button is pressed.
3037 * @user_data: any data you wish to pass to the callback.
3039 * Adds a new element to the beginning of a toolbar.
3041 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3042 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3043 * the radio group for the new element. In all other cases, @widget must
3046 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3047 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3049 * Return value: the new toolbar element as a #GtkWidget.
3052 gtk_toolbar_prepend_element (GtkToolbar *toolbar,
3053 GtkToolbarChildType type,
3056 const char *tooltip_text,
3057 const char *tooltip_private_text,
3059 GtkSignalFunc callback,
3062 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3063 tooltip_text, tooltip_private_text,
3064 icon, callback, user_data, 0);
3068 * gtk_toolbar_insert_element:
3069 * @toolbar: a #GtkToolbar.
3070 * @type: a value of type #GtkToolbarChildType that determines what @widget
3072 * @widget: a #GtkWidget, or %NULL.
3073 * @text: the element's label.
3074 * @tooltip_text: the element's tooltip.
3075 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3076 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3077 * @callback: the function to be executed when the button is pressed.
3078 * @user_data: any data you wish to pass to the callback.
3079 * @position: the number of widgets to insert this element after.
3081 * Inserts a new element in the toolbar at the given position.
3083 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3084 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3085 * the radio group for the new element. In all other cases, @widget must
3088 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3089 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3091 * Return value: the new toolbar element as a #GtkWidget.
3094 gtk_toolbar_insert_element (GtkToolbar *toolbar,
3095 GtkToolbarChildType type,
3098 const char *tooltip_text,
3099 const char *tooltip_private_text,
3101 GtkSignalFunc callback,
3105 return gtk_toolbar_internal_insert_element (toolbar, type, widget, text,
3106 tooltip_text, tooltip_private_text,
3107 icon, callback, user_data, position, FALSE);
3111 _gtk_toolbar_elide_underscores (const gchar *original)
3115 gboolean last_underscore;
3117 q = result = g_malloc (strlen (original) + 1);
3118 last_underscore = FALSE;
3120 for (p = original; *p; p++)
3122 if (!last_underscore && *p == '_')
3123 last_underscore = TRUE;
3126 last_underscore = FALSE;
3137 gtk_toolbar_internal_insert_element (GtkToolbar *toolbar,
3138 GtkToolbarChildType type,
3141 const char *tooltip_text,
3142 const char *tooltip_private_text,
3144 GtkSignalFunc callback,
3149 GtkToolbarChild *child;
3150 GtkToolItem *item = NULL;
3152 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
3154 if (!gtk_toolbar_check_old_api (toolbar))
3157 if (type == GTK_TOOLBAR_CHILD_WIDGET)
3158 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3159 else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON)
3160 g_return_val_if_fail (widget == NULL, NULL);
3162 child = g_new (GtkToolbarChild, 1);
3166 child->label = NULL;
3170 case GTK_TOOLBAR_CHILD_SPACE:
3171 item = gtk_separator_tool_item_new ();
3172 child->widget = NULL;
3175 case GTK_TOOLBAR_CHILD_WIDGET:
3176 item = gtk_tool_item_new ();
3177 child->widget = widget;
3178 gtk_container_add (GTK_CONTAINER (item), child->widget);
3181 case GTK_TOOLBAR_CHILD_BUTTON:
3182 item = gtk_tool_button_new (NULL, NULL);
3183 child->widget = _gtk_tool_button_get_button (GTK_TOOL_BUTTON (item));
3186 case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
3187 item = gtk_toggle_tool_button_new ();
3188 child->widget = _gtk_tool_button_get_button (GTK_TOOL_BUTTON (item));
3191 case GTK_TOOLBAR_CHILD_RADIOBUTTON:
3192 item = gtk_radio_tool_button_new (widget
3193 ? gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget))
3195 child->widget = _gtk_tool_button_get_button (GTK_TOOL_BUTTON (item));
3199 gtk_widget_show (GTK_WIDGET (item));
3201 if (type == GTK_TOOLBAR_CHILD_BUTTON ||
3202 type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
3203 type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
3209 GtkStockItem stock_item;
3212 gtk_tool_button_set_stock_id (GTK_TOOL_BUTTON (item), text);
3214 gtk_stock_lookup (text, &stock_item);
3215 label_text = _gtk_toolbar_elide_underscores (stock_item.label);
3216 child->label = GTK_WIDGET (gtk_label_new (label_text));
3217 g_free (label_text);
3221 child->label = gtk_label_new (text);
3223 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (item), child->label);
3224 gtk_widget_show (child->label);
3230 gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (item), icon);
3232 /* Applications depend on the toolbar showing the widget for them */
3233 gtk_widget_show (GTK_WIDGET (icon));
3237 * We need to connect to the button's clicked callback because some
3238 * programs may rely on that the widget in the callback is a GtkButton
3241 g_signal_connect (child->widget, "clicked",
3242 callback, user_data);
3245 if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text)
3246 gtk_tool_item_set_tooltip (item, toolbar->tooltips,
3247 tooltip_text, tooltip_private_text);
3249 toolbar->children = g_list_insert (toolbar->children, child, position);
3251 gtk_toolbar_insert_tool_item (toolbar, item, position);
3253 return child->widget;
3257 gtk_toolbar_finalize (GObject *object)
3260 GtkToolbar *toolbar = GTK_TOOLBAR (object);
3262 if (toolbar->tooltips)
3263 g_object_unref (toolbar->tooltips);
3265 for (list = toolbar->children; list != NULL; list = list->next)
3266 g_free (list->data);
3268 g_list_free (toolbar->children);
3270 G_OBJECT_CLASS (parent_class)->finalize (object);