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
61 * in the homogeneous game. In units of
62 * pango_font_get_estimated_char_width().
75 CHILD_PROP_HOMOGENEOUS
87 static void gtk_toolbar_init (GtkToolbar *toolbar);
88 static void gtk_toolbar_class_init (GtkToolbarClass *klass);
90 static void gtk_toolbar_set_property (GObject *object,
94 static void gtk_toolbar_get_property (GObject *object,
99 static gint gtk_toolbar_expose (GtkWidget *widget,
100 GdkEventExpose *event);
101 static void gtk_toolbar_realize (GtkWidget *widget);
102 static void gtk_toolbar_unrealize (GtkWidget *widget);
103 static void gtk_toolbar_size_request (GtkWidget *widget,
104 GtkRequisition *requisition);
105 static void gtk_toolbar_size_allocate (GtkWidget *widget,
106 GtkAllocation *allocation);
107 static void gtk_toolbar_style_set (GtkWidget *widget,
108 GtkStyle *prev_style);
109 static void gtk_toolbar_direction_changed (GtkWidget *widget,
110 GtkTextDirection previous_direction);
111 static gboolean gtk_toolbar_focus (GtkWidget *widget,
112 GtkDirectionType dir);
113 static void gtk_toolbar_screen_changed (GtkWidget *widget,
114 GdkScreen *previous_screen);
115 static void gtk_toolbar_map (GtkWidget *widget);
116 static void gtk_toolbar_unmap (GtkWidget *widget);
118 static void gtk_toolbar_set_child_property (GtkContainer *container,
123 static void gtk_toolbar_get_child_property (GtkContainer *container,
128 static void gtk_toolbar_finalize (GObject *object);
131 static void gtk_toolbar_add (GtkContainer *container,
133 static void gtk_toolbar_remove (GtkContainer *container,
135 static void gtk_toolbar_forall (GtkContainer *container,
136 gboolean include_internals,
137 GtkCallback callback,
138 gpointer callback_data);
139 static GType gtk_toolbar_child_type (GtkContainer *container);
141 static void gtk_toolbar_real_orientation_changed (GtkToolbar *toolbar,
142 GtkOrientation orientation);
143 static void gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
144 GtkToolbarStyle style);
146 static gboolean gtk_toolbar_move_focus (GtkToolbar *toolbar,
147 GtkDirectionType dir);
148 static gboolean gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
149 gboolean focus_home);
151 static gboolean gtk_toolbar_button_press (GtkWidget *toolbar,
152 GdkEventButton *event);
153 static gboolean gtk_toolbar_arrow_button_press (GtkWidget *button,
154 GdkEventButton *event,
155 GtkToolbar *toolbar);
156 static void gtk_toolbar_arrow_button_clicked (GtkWidget *button,
157 GtkToolbar *toolbar);
158 static void gtk_toolbar_update_button_relief (GtkToolbar *toolbar);
159 static GtkReliefStyle get_button_relief (GtkToolbar *toolbar);
160 static gint get_internal_padding (GtkToolbar *toolbar);
161 static GtkShadowType get_shadow_type (GtkToolbar *toolbar);
162 static void gtk_toolbar_remove_tool_item (GtkToolbar *toolbar,
164 static gboolean gtk_toolbar_popup_menu (GtkWidget *toolbar);
166 static GtkWidget *gtk_toolbar_internal_insert_element (GtkToolbar *toolbar,
167 GtkToolbarChildType type,
170 const char *tooltip_text,
171 const char *tooltip_private_text,
173 GtkSignalFunc callback,
178 typedef struct _ToolbarContent ToolbarContent;
180 static ToolbarContent *gtk_toolbar_insert_tool_item (GtkToolbar *toolbar,
183 gboolean is_placeholder);
185 static gboolean gtk_toolbar_check_new_api (GtkToolbar *toolbar);
193 #define GTK_TOOLBAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_TOOLBAR, GtkToolbarPrivate))
202 struct _ToolbarContent
205 guint is_placeholder : 1;
206 GtkAllocation start_allocation;
207 GtkAllocation goal_allocation;
211 struct _GtkToolbarPrivate
216 GtkWidget *arrow_button;
222 GdkWindow *event_window;
224 GtkSettings *settings;
227 gboolean leaving_dnd;
229 GtkToolItem *highlight_tool_item;
230 gint max_homogeneous_pixels;
236 static GtkContainerClass *parent_class = NULL;
237 static guint toolbar_signals [LAST_SIGNAL] = { 0 };
240 gtk_toolbar_get_type (void)
242 static GtkType type = 0;
246 static const GTypeInfo type_info =
248 sizeof (GtkToolbarClass),
249 (GBaseInitFunc) NULL,
250 (GBaseFinalizeFunc) NULL,
251 (GClassInitFunc) gtk_toolbar_class_init,
252 (GClassFinalizeFunc) NULL,
256 (GInstanceInitFunc) gtk_toolbar_init,
259 type = g_type_register_static (GTK_TYPE_CONTAINER,
268 add_arrow_bindings (GtkBindingSet *binding_set,
270 GtkDirectionType dir)
272 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
274 gtk_binding_entry_add_signal (binding_set, keysym, 0,
276 GTK_TYPE_DIRECTION_TYPE, dir);
277 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
279 GTK_TYPE_DIRECTION_TYPE, dir);
283 add_ctrl_tab_bindings (GtkBindingSet *binding_set,
284 GdkModifierType modifiers,
285 GtkDirectionType direction)
287 gtk_binding_entry_add_signal (binding_set,
288 GDK_Tab, GDK_CONTROL_MASK | modifiers,
290 GTK_TYPE_DIRECTION_TYPE, direction);
291 gtk_binding_entry_add_signal (binding_set,
292 GDK_KP_Tab, GDK_CONTROL_MASK | modifiers,
294 GTK_TYPE_DIRECTION_TYPE, direction);
298 gtk_toolbar_class_init (GtkToolbarClass *klass)
300 GObjectClass *gobject_class;
301 GtkWidgetClass *widget_class;
302 GtkContainerClass *container_class;
303 GtkBindingSet *binding_set;
305 parent_class = g_type_class_peek_parent (klass);
307 gobject_class = (GObjectClass *)klass;
308 widget_class = (GtkWidgetClass *)klass;
309 container_class = (GtkContainerClass *)klass;
311 gobject_class->set_property = gtk_toolbar_set_property;
312 gobject_class->get_property = gtk_toolbar_get_property;
313 gobject_class->finalize = gtk_toolbar_finalize;
315 widget_class->button_press_event = gtk_toolbar_button_press;
316 widget_class->expose_event = gtk_toolbar_expose;
317 widget_class->size_request = gtk_toolbar_size_request;
318 widget_class->size_allocate = gtk_toolbar_size_allocate;
319 widget_class->style_set = gtk_toolbar_style_set;
320 widget_class->direction_changed = gtk_toolbar_direction_changed;
321 widget_class->focus = gtk_toolbar_focus;
322 widget_class->screen_changed = gtk_toolbar_screen_changed;
323 widget_class->realize = gtk_toolbar_realize;
324 widget_class->unrealize = gtk_toolbar_unrealize;
325 widget_class->map = gtk_toolbar_map;
326 widget_class->unmap = gtk_toolbar_unmap;
327 widget_class->popup_menu = gtk_toolbar_popup_menu;
329 container_class->add = gtk_toolbar_add;
330 container_class->remove = gtk_toolbar_remove;
331 container_class->forall = gtk_toolbar_forall;
332 container_class->child_type = gtk_toolbar_child_type;
333 container_class->get_child_property = gtk_toolbar_get_child_property;
334 container_class->set_child_property = gtk_toolbar_set_child_property;
336 klass->orientation_changed = gtk_toolbar_real_orientation_changed;
337 klass->style_changed = gtk_toolbar_real_style_changed;
340 * GtkToolbar::orientation-changed:
341 * @toolbar: the object which emitted the signal
342 * @orientation: the new #GtkOrientation of the toolbar
344 * Emitted when the orientation of the toolbar changes.
346 toolbar_signals[ORIENTATION_CHANGED] =
347 g_signal_new ("orientation-changed",
348 G_OBJECT_CLASS_TYPE (klass),
350 G_STRUCT_OFFSET (GtkToolbarClass, orientation_changed),
352 g_cclosure_marshal_VOID__ENUM,
354 GTK_TYPE_ORIENTATION);
356 * GtkToolbar::style-changed:
357 * @toolbar: The #GtkToolbar which emitted the signal
358 * @style: the new #GtkToolbarStyle of the toolbar
360 * Emitted when the style of the toolbar changes.
362 toolbar_signals[STYLE_CHANGED] =
363 g_signal_new ("style-changed",
364 G_OBJECT_CLASS_TYPE (klass),
366 G_STRUCT_OFFSET (GtkToolbarClass, style_changed),
368 g_cclosure_marshal_VOID__ENUM,
370 GTK_TYPE_TOOLBAR_STYLE);
372 * GtkToolbar::popup-context-menu:
373 * @toolbar: the #GtkToolbar which emitted the signal
374 * @x: the x coordinate of the point where the menu should appear
375 * @y: the y coordinate of the point where the menu should appear
376 * @button: the mouse button the user pressed, or -1
378 * Emitted when the user right-clicks the toolbar or uses the
379 * keybinding to display a popup menu.
381 * Application developers should handle this signal if they want
382 * to display a context menu on the toolbar. The context-menu should
383 * appear at the coordinates given by @x and @y. The mouse button
384 * number is given by the @button parameter. If the menu was popped
385 * up using the keybaord, @button is -1.
387 * Return value: return %TRUE if the signal was handled, %FALSE if not
389 toolbar_signals[POPUP_CONTEXT_MENU] =
390 g_signal_new ("popup_context_menu",
391 G_OBJECT_CLASS_TYPE (klass),
393 G_STRUCT_OFFSET (GtkToolbarClass, popup_context_menu),
394 _gtk_boolean_handled_accumulator, NULL,
395 _gtk_marshal_BOOLEAN__INT_INT_INT,
397 G_TYPE_INT, G_TYPE_INT,
400 * GtkToolbar::move-focus:
401 * @toolbar: the #GtkToolbar which emitted the signal
402 * @dir: a #GtkDirection
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[MOVE_FOCUS] =
410 _gtk_binding_signal_new ("move_focus",
411 G_TYPE_FROM_CLASS (klass),
412 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
413 G_CALLBACK (gtk_toolbar_move_focus),
415 _gtk_marshal_BOOLEAN__ENUM,
417 GTK_TYPE_DIRECTION_TYPE);
419 * GtkToolbar::focus-home-or-end:
420 * @toolbar: the #GtkToolbar which emitted the signal
421 * @focus_home: %TRUE if the first item should be focused
423 * A keybinding signal used internally by GTK+. This signal can't
424 * be used in application code
426 * Return value: %TRUE if the signal was handled, %FALSE if not
428 toolbar_signals[FOCUS_HOME_OR_END] =
429 _gtk_binding_signal_new ("focus_home_or_end",
430 G_OBJECT_CLASS_TYPE (klass),
431 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
432 G_CALLBACK (gtk_toolbar_focus_home_or_end),
434 _gtk_marshal_BOOLEAN__BOOLEAN,
439 g_object_class_install_property (gobject_class,
441 g_param_spec_enum ("orientation",
443 _("The orientation of the toolbar"),
444 GTK_TYPE_ORIENTATION,
445 GTK_ORIENTATION_HORIZONTAL,
448 g_object_class_install_property (gobject_class,
450 g_param_spec_enum ("toolbar_style",
452 _("How to draw the toolbar"),
453 GTK_TYPE_TOOLBAR_STYLE,
456 g_object_class_install_property (gobject_class,
458 g_param_spec_boolean ("show_arrow",
460 _("If an arrow should be shown if the toolbar doesn't fit"),
464 /* child properties */
465 gtk_container_class_install_child_property (container_class,
467 g_param_spec_boolean ("expand",
469 _("Whether the item should receive extra space when the toolbar grows"),
473 gtk_container_class_install_child_property (container_class,
474 CHILD_PROP_HOMOGENEOUS,
475 g_param_spec_boolean ("homogeneous",
477 _("Whether the item should be the same size as other homogeneous items"),
481 /* style properties */
482 gtk_widget_class_install_style_property (widget_class,
483 g_param_spec_int ("space_size",
485 _("Size of spacers"),
491 gtk_widget_class_install_style_property (widget_class,
492 g_param_spec_int ("internal_padding",
493 _("Internal padding"),
494 _("Amount of border space between the toolbar shadow and the buttons"),
500 gtk_widget_class_install_style_property (widget_class,
501 g_param_spec_enum ("space_style",
503 _("Whether spacers are vertical lines or just blank"),
504 GTK_TYPE_TOOLBAR_SPACE_STYLE,
508 gtk_widget_class_install_style_property (widget_class,
509 g_param_spec_enum ("button_relief",
511 _("Type of bevel around toolbar buttons"),
512 GTK_TYPE_RELIEF_STYLE,
515 gtk_widget_class_install_style_property (widget_class,
516 g_param_spec_enum ("shadow_type",
518 _("Style of bevel around the toolbar"),
519 GTK_TYPE_SHADOW_TYPE,
523 gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-style",
525 _("Whether default toolbars have text only, text and icons, icons only, etc."),
526 GTK_TYPE_TOOLBAR_STYLE,
527 DEFAULT_TOOLBAR_STYLE,
530 gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-icon-size",
531 _("Toolbar icon size"),
532 _("Size of icons in default toolbars"),
537 binding_set = gtk_binding_set_by_class (klass);
539 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
540 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
541 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
542 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
544 gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
545 "focus_home_or_end", 1,
546 G_TYPE_BOOLEAN, TRUE);
547 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
548 "focus_home_or_end", 1,
549 G_TYPE_BOOLEAN, TRUE);
550 gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
551 "focus_home_or_end", 1,
552 G_TYPE_BOOLEAN, FALSE);
553 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
554 "focus_home_or_end", 1,
555 G_TYPE_BOOLEAN, FALSE);
557 add_ctrl_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
558 add_ctrl_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
560 g_type_class_add_private (gobject_class, sizeof (GtkToolbarPrivate));
564 gtk_toolbar_init (GtkToolbar *toolbar)
566 GtkToolbarPrivate *priv;
568 GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS);
569 GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
571 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
573 toolbar->orientation = GTK_ORIENTATION_HORIZONTAL;
574 toolbar->style = DEFAULT_TOOLBAR_STYLE;
575 toolbar->icon_size = DEFAULT_ICON_SIZE;
576 toolbar->tooltips = gtk_tooltips_new ();
577 g_object_ref (toolbar->tooltips);
578 gtk_object_sink (GTK_OBJECT (toolbar->tooltips));
580 priv->arrow_button = gtk_toggle_button_new ();
581 g_signal_connect (priv->arrow_button, "button_press_event",
582 G_CALLBACK (gtk_toolbar_arrow_button_press), toolbar);
583 g_signal_connect (priv->arrow_button, "clicked",
584 G_CALLBACK (gtk_toolbar_arrow_button_clicked), toolbar);
585 gtk_button_set_relief (GTK_BUTTON (priv->arrow_button),
586 get_button_relief (toolbar));
588 priv->api_mode = DONT_KNOW;
590 gtk_button_set_focus_on_click (GTK_BUTTON (priv->arrow_button), FALSE);
592 priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
593 gtk_widget_set_name (priv->arrow, "gtk-toolbar-arrow");
594 gtk_widget_show (priv->arrow);
595 gtk_container_add (GTK_CONTAINER (priv->arrow_button), priv->arrow);
597 gtk_widget_set_parent (priv->arrow_button, GTK_WIDGET (toolbar));
599 /* which child position a drop will occur at */
601 priv->show_arrow = TRUE;
602 priv->settings = NULL;
604 priv->max_homogeneous_pixels = -1;
606 priv->timer = g_timer_new ();
610 toolbar_item_visible (GtkToolbar *toolbar,
613 if (GTK_WIDGET_VISIBLE (item) &&
614 ((toolbar->orientation == GTK_ORIENTATION_HORIZONTAL &&
615 gtk_tool_item_get_visible_horizontal (item)) ||
616 (toolbar->orientation == GTK_ORIENTATION_VERTICAL &&
617 gtk_tool_item_get_visible_vertical (item))))
619 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
621 /* With the old toolbar you could hide a button by calling gtk_widget_hide()
622 * on it. This doesn't work with the new API because the GtkToolItem will not be
625 if (priv->api_mode == OLD_API)
627 GtkWidget *bin_child = GTK_BIN (item)->child;
629 if (bin_child && !GTK_WIDGET_VISIBLE (bin_child))
640 calculate_max_homogeneous_pixels (GtkWidget *widget)
642 PangoContext *context;
643 PangoFontMetrics *metrics;
646 context = gtk_widget_get_pango_context (widget);
647 metrics = pango_context_get_metrics (context,
648 widget->style->font_desc,
649 pango_context_get_language (context));
650 char_width = pango_font_metrics_get_approximate_char_width (metrics);
651 pango_font_metrics_unref (metrics);
653 return PANGO_PIXELS (MAX_HOMOGENEOUS_N_CHARS * char_width);
657 toolbar_item_is_homogeneous (GtkToolbar *toolbar,
661 GtkRequisition requisition;
662 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
664 if (priv->max_homogeneous_pixels < 0)
666 priv->max_homogeneous_pixels =
667 calculate_max_homogeneous_pixels (GTK_WIDGET (toolbar));
670 result = gtk_tool_item_get_homogeneous (item) &&
671 !GTK_IS_SEPARATOR_TOOL_ITEM (item);
673 gtk_widget_size_request (GTK_WIDGET (item), &requisition);
675 if ((gtk_tool_item_get_is_important (item) &&
676 toolbar->style == GTK_TOOLBAR_BOTH_HORIZ &&
677 toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) ||
678 requisition.width > priv->max_homogeneous_pixels)
687 gtk_toolbar_set_property (GObject *object,
692 GtkToolbar *toolbar = GTK_TOOLBAR (object);
696 case PROP_ORIENTATION:
697 gtk_toolbar_set_orientation (toolbar, g_value_get_enum (value));
699 case PROP_TOOLBAR_STYLE:
700 gtk_toolbar_set_style (toolbar, g_value_get_enum (value));
702 case PROP_SHOW_ARROW:
703 gtk_toolbar_set_show_arrow (toolbar, g_value_get_boolean (value));
706 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
712 gtk_toolbar_get_property (GObject *object,
717 GtkToolbar *toolbar = GTK_TOOLBAR (object);
718 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
722 case PROP_ORIENTATION:
723 g_value_set_enum (value, toolbar->orientation);
725 case PROP_TOOLBAR_STYLE:
726 g_value_set_enum (value, toolbar->style);
728 case PROP_SHOW_ARROW:
729 g_value_set_boolean (value, priv->show_arrow);
732 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
738 gtk_toolbar_map (GtkWidget *widget)
740 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
742 GTK_WIDGET_CLASS (parent_class)->map (widget);
744 if (priv->event_window)
745 gdk_window_show_unraised (priv->event_window);
749 gtk_toolbar_unmap (GtkWidget *widget)
751 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
753 if (priv->event_window)
754 gdk_window_hide (priv->event_window);
756 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
760 gtk_toolbar_realize (GtkWidget *widget)
762 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
763 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
765 GdkWindowAttr attributes;
766 gint attributes_mask;
769 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
771 border_width = GTK_CONTAINER (widget)->border_width;
773 attributes.wclass = GDK_INPUT_ONLY;
774 attributes.window_type = GDK_WINDOW_CHILD;
775 attributes.x = widget->allocation.x + border_width;
776 attributes.y = widget->allocation.y + border_width;
777 attributes.width = widget->allocation.width - border_width * 2;
778 attributes.height = widget->allocation.height - border_width * 2;
779 attributes.event_mask = gtk_widget_get_events (widget);
780 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
781 GDK_BUTTON_RELEASE_MASK |
782 GDK_ENTER_NOTIFY_MASK |
783 GDK_LEAVE_NOTIFY_MASK);
785 attributes_mask = GDK_WA_X | GDK_WA_Y;
787 widget->window = gtk_widget_get_parent_window (widget);
788 g_object_ref (widget->window);
789 widget->style = gtk_style_attach (widget->style, widget->window);
791 priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
792 &attributes, attributes_mask);
793 gdk_window_set_user_data (priv->event_window, toolbar);
797 gtk_toolbar_unrealize (GtkWidget *widget)
799 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
801 if (priv->event_window)
803 gdk_window_set_user_data (priv->event_window, NULL);
804 gdk_window_destroy (priv->event_window);
805 priv->event_window = NULL;
808 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
809 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
813 gtk_toolbar_expose (GtkWidget *widget,
814 GdkEventExpose *event)
816 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
817 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
822 border_width = GTK_CONTAINER (widget)->border_width;
824 if (GTK_WIDGET_DRAWABLE (widget))
826 gtk_paint_box (widget->style,
828 GTK_WIDGET_STATE (widget),
829 get_shadow_type (toolbar),
830 &event->area, widget, "toolbar",
831 border_width + widget->allocation.x,
832 border_width + widget->allocation.y,
833 widget->allocation.width - 2 * border_width,
834 widget->allocation.height - 2 * border_width);
837 for (list = priv->content; list != NULL; list = list->next)
839 ToolbarContent *content = list->data;
840 GtkToolItem *item = content->item;
842 if (!content->is_placeholder)
843 gtk_container_propagate_expose (GTK_CONTAINER (widget),
848 gtk_container_propagate_expose (GTK_CONTAINER (widget),
856 gtk_toolbar_size_request (GtkWidget *widget,
857 GtkRequisition *requisition)
859 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
860 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
862 gint max_child_height;
863 gint max_child_width;
864 gint max_homogeneous_child_width;
865 gint max_homogeneous_child_height;
866 gint homogeneous_size;
868 gint pack_front_size;
870 GtkRequisition arrow_requisition;
872 max_homogeneous_child_width = 0;
873 max_homogeneous_child_height = 0;
875 max_child_height = 0;
876 for (list = priv->content; list != NULL; list = list->next)
878 GtkRequisition requisition;
879 ToolbarContent *content = list->data;
880 GtkToolItem *item = content->item;
882 if (!toolbar_item_visible (toolbar, item))
885 gtk_widget_size_request (GTK_WIDGET (item), &requisition);
887 max_child_width = MAX (max_child_width, requisition.width);
888 max_child_height = MAX (max_child_height, requisition.height);
890 if (toolbar_item_is_homogeneous (toolbar, item))
892 max_homogeneous_child_width = MAX (max_homogeneous_child_width, requisition.width);
893 max_homogeneous_child_height = MAX (max_homogeneous_child_height, requisition.height);
897 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
898 homogeneous_size = max_homogeneous_child_width;
900 homogeneous_size = max_homogeneous_child_height;
903 for (list = priv->content; list != NULL; list = list->next)
905 ToolbarContent *content = list->data;
906 GtkToolItem *item = content->item;
909 if (!toolbar_item_visible (toolbar, item))
912 if (toolbar_item_is_homogeneous (toolbar, item))
914 size = homogeneous_size;
918 GtkRequisition requisition;
920 gtk_widget_size_request (GTK_WIDGET (item), &requisition);
922 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
923 size = requisition.width;
925 size = requisition.height;
928 pack_front_size += size;
931 if (priv->show_arrow && priv->api_mode == NEW_API)
933 gtk_widget_size_request (priv->arrow_button, &arrow_requisition);
935 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
936 long_req = arrow_requisition.width;
938 long_req = arrow_requisition.height;
940 /* There is no point requesting space for the arrow if that would take
941 * up more space than all the items combined
943 long_req = MIN (long_req, pack_front_size);
947 arrow_requisition.height = 0;
948 arrow_requisition.width = 0;
950 long_req = pack_front_size;
953 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
955 requisition->width = long_req;
956 requisition->height = MAX (max_child_height, arrow_requisition.height);
960 requisition->height = long_req;
961 requisition->width = MAX (max_child_width, arrow_requisition.width);
965 ipadding = get_internal_padding (toolbar);
967 requisition->width += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width);
968 requisition->height += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width);
970 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
972 requisition->width += 2 * widget->style->xthickness;
973 requisition->height += 2 * widget->style->ythickness;
976 toolbar->button_maxw = max_homogeneous_child_width;
977 toolbar->button_maxh = max_homogeneous_child_height;
980 #define SLIDE_SPEED 600 /* pixels per second */
983 position (gint from, gint to, gdouble elapsed)
986 return MIN (from + SLIDE_SPEED * elapsed, to);
988 return MAX (from - SLIDE_SPEED * elapsed, to);
992 compute_intermediate_allocation (GtkToolbar *toolbar,
993 const GtkAllocation *start,
994 const GtkAllocation *goal,
995 GtkAllocation *intermediate)
997 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
998 gdouble elapsed = g_timer_elapsed (priv->timer, NULL);
1000 intermediate->x = position (start->x, goal->x, elapsed);
1001 intermediate->y = position (start->y, goal->y, elapsed);
1002 intermediate->width =
1003 position (start->x + start->width, goal->x + goal->width, elapsed) - intermediate->x;
1004 intermediate->height =
1005 position (start->y + start->height, goal->y + goal->height, elapsed) - intermediate->y;
1009 fixup_allocation_for_rtl (gint total_size,
1010 GtkAllocation *allocation)
1012 allocation->x += (total_size - (2 * allocation->x + allocation->width));
1016 fixup_allocation_for_vertical (GtkAllocation *allocation)
1020 tmp = allocation->x;
1021 allocation->x = allocation->y;
1022 allocation->y = tmp;
1024 tmp = allocation->width;
1025 allocation->width = allocation->height;
1026 allocation->height = tmp;
1030 get_item_size (GtkToolbar *toolbar,
1033 GtkRequisition requisition;
1034 GtkToolItem *item = GTK_TOOL_ITEM (child);
1036 gtk_widget_get_child_requisition (child, &requisition);
1038 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1040 if (toolbar_item_is_homogeneous (toolbar, item))
1041 return toolbar->button_maxw;
1043 return requisition.width;
1047 if (toolbar_item_is_homogeneous (toolbar, item))
1048 return toolbar->button_maxh;
1050 return requisition.height;
1055 slide_idle_handler (gpointer data)
1057 GtkToolbar *toolbar = data;
1058 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1061 if (priv->need_sync)
1064 priv->need_sync = FALSE;
1067 for (list = priv->content; list != NULL; list = list->next)
1069 ToolbarContent *content = list->data;
1070 GtkWidget *widget = GTK_WIDGET (content->item);
1072 if ((content->state == NOT_ALLOCATED) ||
1073 (content->state == NORMAL &&
1074 ((content->goal_allocation.x != widget->allocation.x ||
1075 content->goal_allocation.y != widget->allocation.y ||
1076 content->goal_allocation.width != widget->allocation.width ||
1077 content->goal_allocation.height != widget->allocation.height))))
1079 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1084 priv->is_sliding = FALSE;
1085 if (priv->leaving_dnd)
1087 priv->in_dnd = FALSE;
1088 priv->leaving_dnd = FALSE;
1097 rect_within (GtkAllocation *a1, GtkAllocation *a2)
1099 return (a1->x >= a2->x &&
1100 a1->x + a1->width <= a2->x + a2->width &&
1102 a1->y + a1->height <= a2->y + a2->height);
1106 gtk_toolbar_begin_sliding (GtkToolbar *toolbar)
1108 GtkWidget *widget = GTK_WIDGET (toolbar);
1109 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1117 /* Start the sliding. This function copies the allocation of every
1118 * item into content->start_allocation. For items that haven't
1119 * been allocated yet, we calculate their position and save that
1120 * in start_allocatino along with zero width and zero height.
1122 priv->is_sliding = TRUE;
1125 priv->idle_id = g_idle_add (slide_idle_handler, toolbar);
1127 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1128 vertical = (toolbar->orientation == GTK_ORIENTATION_VERTICAL);
1129 border_width = get_internal_padding (toolbar) + GTK_CONTAINER (toolbar)->border_width;
1133 cur_x = widget->allocation.width - border_width - widget->style->xthickness;
1134 cur_y = widget->allocation.height - border_width - widget->style->ythickness;
1138 cur_x = border_width + widget->style->xthickness;
1139 cur_y = border_width + widget->style->ythickness;
1142 cur_x += widget->allocation.x;
1143 cur_y += widget->allocation.y;
1145 for (list = priv->content; list != NULL; list = list->next)
1147 ToolbarContent *content = list->data;
1148 GtkWidget *item = GTK_WIDGET (content->item);
1149 GtkAllocation *alloc = &(content->start_allocation);
1151 if (content->state == NORMAL && rect_within (&(item->allocation), &(widget->allocation)))
1153 *alloc = item->allocation;
1162 alloc->width = widget->allocation.width -
1163 2 * border_width - 2 * widget->style->xthickness;
1169 alloc->height = widget->allocation.height -
1170 2 * border_width - 2 * widget->style->ythickness;
1175 cur_y = alloc->y + alloc->height;
1179 cur_x = alloc->x + alloc->width;
1182 g_timer_reset (priv->timer);
1186 gtk_toolbar_stop_sliding (GtkToolbar *toolbar)
1188 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1190 if (priv->is_sliding)
1194 priv->is_sliding = FALSE;
1195 priv->in_dnd = FALSE;
1196 priv->leaving_dnd = FALSE;
1200 g_source_remove (priv->idle_id);
1204 list = priv->content;
1207 ToolbarContent *content = list->data;
1210 if (content->is_placeholder)
1211 gtk_toolbar_remove_tool_item (toolbar, content->item);
1214 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1219 gtk_toolbar_size_allocate (GtkWidget *widget,
1220 GtkAllocation *allocation)
1222 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1223 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1224 GtkAllocation *allocations;
1225 ItemState *new_states;
1226 GtkAllocation arrow_allocation;
1228 gint size, pos, short_size;
1231 gboolean need_arrow;
1232 gint n_expand_items;
1234 gint available_size;
1237 GtkRequisition arrow_requisition;
1238 gboolean overflowing;
1239 gboolean size_changed;
1242 size_changed = FALSE;
1243 if (widget->allocation.x != allocation->x ||
1244 widget->allocation.y != allocation->y ||
1245 widget->allocation.width != allocation->width ||
1246 widget->allocation.height != allocation->height)
1248 size_changed = TRUE;
1252 gtk_toolbar_stop_sliding (toolbar);
1254 widget->allocation = *allocation;
1256 border_width = GTK_CONTAINER (toolbar)->border_width;
1258 if (GTK_WIDGET_REALIZED (widget))
1260 gdk_window_move_resize (priv->event_window,
1261 allocation->x + border_width,
1262 allocation->y + border_width,
1263 allocation->width - border_width * 2,
1264 allocation->height - border_width * 2);
1267 border_width += get_internal_padding (toolbar);
1269 gtk_widget_get_child_requisition (GTK_WIDGET (priv->arrow_button),
1270 &arrow_requisition);
1272 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1274 available_size = size = allocation->width - 2 * border_width;
1275 short_size = allocation->height - 2 * border_width;
1276 arrow_size = arrow_requisition.width;
1278 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1280 available_size -= 2 * widget->style->xthickness;
1281 short_size -= 2 * widget->style->ythickness;
1286 available_size = size = allocation->height - 2 * border_width;
1287 short_size = allocation->width - 2 * border_width;
1288 arrow_size = arrow_requisition.height;
1290 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1292 available_size -= 2 * widget->style->ythickness;
1293 short_size -= 2 * widget->style->xthickness;
1297 n_items = g_list_length (priv->content);
1298 allocations = g_new0 (GtkAllocation, n_items);
1299 new_states = g_new0 (ItemState, n_items);
1302 for (list = priv->content; list != NULL; list = list->next)
1304 ToolbarContent *content = list->data;
1305 GtkToolItem *item = content->item;
1307 if (toolbar_item_visible (toolbar, item))
1308 needed_size += get_item_size (toolbar, GTK_WIDGET (item));
1311 need_arrow = (needed_size > available_size) && priv->show_arrow && priv->api_mode == NEW_API;
1314 size = available_size - arrow_size;
1316 size = available_size;
1318 /* calculate widths of items */
1319 overflowing = FALSE;
1320 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1322 ToolbarContent *content = list->data;
1323 GtkToolItem *item = content->item;
1326 if (!toolbar_item_visible (toolbar, item))
1328 new_states[i] = HIDDEN;
1332 item_size = get_item_size (toolbar, GTK_WIDGET (item));
1333 if (item_size <= size && !overflowing)
1336 allocations[i].width = item_size;
1337 new_states[i] = NORMAL;
1342 new_states[i] = OVERFLOWN;
1346 /* calculate width of arrow */
1349 arrow_allocation.width = arrow_size;
1350 arrow_allocation.height = short_size;
1353 /* expand expandable items */
1355 /* We don't expand when there is an overflow menu, because that leads to
1356 * weird jumps when items get moved to the overflow menu and the expanding
1357 * items suddenly get a lot of extra space
1362 for (i = 0, list = priv->content; list != NULL; list = list->next, ++i)
1364 ToolbarContent *content = list->data;
1365 GtkToolItem *item = content->item;
1367 if (gtk_tool_item_get_expand (item) && new_states[i] == NORMAL)
1371 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1373 ToolbarContent *content = list->data;
1374 GtkToolItem *item = content->item;
1376 if (gtk_tool_item_get_expand (item) && new_states[i] == NORMAL)
1378 gint extra = size / n_expand_items;
1379 if (size % n_expand_items != 0)
1382 allocations[i].width += extra;
1388 g_assert (n_expand_items == 0);
1391 /* position items */
1393 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1395 if (new_states[i] == NORMAL)
1397 allocations[i].x = pos;
1398 allocations[i].y = border_width;
1399 allocations[i].height = short_size;
1401 pos += allocations[i].width;
1405 /* position arrow */
1408 arrow_allocation.x = available_size - border_width - arrow_allocation.width;
1409 arrow_allocation.y = border_width;
1412 /* fix up allocations in the vertical or RTL cases */
1413 if (toolbar->orientation == GTK_ORIENTATION_VERTICAL)
1415 for (i = 0; i < n_items; ++i)
1416 fixup_allocation_for_vertical (&(allocations[i]));
1419 fixup_allocation_for_vertical (&arrow_allocation);
1421 else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1423 for (i = 0; i < n_items; ++i)
1424 fixup_allocation_for_rtl (available_size, &(allocations[i]));
1427 fixup_allocation_for_rtl (available_size, &arrow_allocation);
1430 /* translate the items by allocation->(x,y) */
1431 for (i = 0; i < n_items; ++i)
1433 allocations[i].x += allocation->x;
1434 allocations[i].y += allocation->y;
1436 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1438 allocations[i].x += widget->style->xthickness;
1439 allocations[i].y += widget->style->ythickness;
1445 arrow_allocation.x += allocation->x;
1446 arrow_allocation.y += allocation->y;
1448 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1450 arrow_allocation.x += widget->style->xthickness;
1451 arrow_allocation.y += widget->style->ythickness;
1455 /* did anything change? */
1456 for (list = priv->content, i = 0; list != NULL; list = list->next, i++)
1458 ToolbarContent *content = list->data;
1460 if (content->state == NORMAL && new_states[i] != NORMAL)
1462 /* an item disappeared, begin sliding */
1464 gtk_toolbar_begin_sliding (toolbar);
1468 /* finally allocate the items */
1469 for (list = priv->content, i = 0; list != NULL; list = list->next, i++)
1471 ToolbarContent *content = list->data;
1473 content->goal_allocation = allocations[i];
1476 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1478 ToolbarContent *content = list->data;
1479 GtkToolItem *item = content->item;
1481 if (new_states[i] != NORMAL)
1483 gtk_widget_set_child_visible (GTK_WIDGET (item), FALSE);
1487 GtkAllocation alloc;
1488 elapsed = g_timer_elapsed (priv->timer, NULL);
1490 if (priv->is_sliding)
1492 /* FIXME: we should use the same "elapsed" for all items */
1493 compute_intermediate_allocation (toolbar,
1494 &(content->start_allocation),
1495 &(content->goal_allocation),
1497 priv->need_sync = TRUE;
1501 alloc = allocations[i];
1504 if (alloc.width == 0 || alloc.height == 0)
1506 gtk_widget_set_child_visible (GTK_WIDGET (item), FALSE);
1510 gtk_widget_set_child_visible (GTK_WIDGET (item), TRUE);
1511 gtk_widget_size_allocate (GTK_WIDGET (item), &alloc);
1515 content->state = new_states[i];
1520 gtk_widget_size_allocate (GTK_WIDGET (priv->arrow_button),
1522 gtk_widget_show (GTK_WIDGET (priv->arrow_button));
1526 gtk_widget_hide (GTK_WIDGET (priv->arrow_button));
1529 g_free (allocations);
1530 g_free (new_states);
1534 gtk_toolbar_style_set (GtkWidget *widget,
1535 GtkStyle *prev_style)
1537 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
1539 priv->max_homogeneous_pixels = -1;
1541 if (GTK_WIDGET_REALIZED (widget))
1542 gtk_style_set_background (widget->style, widget->window, widget->state);
1545 gtk_toolbar_update_button_relief (GTK_TOOLBAR (widget));
1549 gtk_toolbar_direction_changed (GtkWidget *widget,
1550 GtkTextDirection previous_dir)
1552 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1553 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1555 if (toolbar->orientation == GTK_ORIENTATION_VERTICAL)
1557 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1558 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
1560 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_LEFT, GTK_SHADOW_NONE);
1563 GTK_WIDGET_CLASS (parent_class)->direction_changed (widget, previous_dir);
1567 gtk_toolbar_list_children_in_focus_order (GtkToolbar *toolbar,
1568 GtkDirectionType dir)
1570 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1571 GList *result = NULL;
1575 /* generate list of children in reverse logical order */
1577 for (list = priv->content; list != NULL; list = list->next)
1579 ToolbarContent *content = list->data;
1580 GtkToolItem *item = content->item;
1582 result = g_list_prepend (result, item);
1585 result = g_list_prepend (result, priv->arrow_button);
1587 rtl = (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL);
1589 /* move in logical order when
1591 * - dir is TAB_FORWARD
1593 * - in RTL mode and moving left or up
1595 * - in LTR mode and moving right or down
1597 if (dir == GTK_DIR_TAB_FORWARD ||
1598 (rtl && (dir == GTK_DIR_UP || dir == GTK_DIR_LEFT)) ||
1599 (!rtl && (dir == GTK_DIR_DOWN || dir == GTK_DIR_RIGHT)))
1601 result = g_list_reverse (result);
1608 gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
1609 gboolean focus_home)
1611 GList *children, *list;
1612 GtkDirectionType dir = focus_home? GTK_DIR_RIGHT : GTK_DIR_LEFT;
1614 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1616 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1618 children = g_list_reverse (children);
1620 dir = (dir == GTK_DIR_RIGHT)? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1623 for (list = children; list != NULL; list = list->next)
1625 GtkWidget *child = list->data;
1627 if (GTK_CONTAINER (toolbar)->focus_child == child)
1630 if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1634 g_list_free (children);
1639 /* Keybinding handler. This function is called when the user presses
1640 * Ctrl TAB or an arrow key.
1643 gtk_toolbar_move_focus (GtkToolbar *toolbar,
1644 GtkDirectionType dir)
1647 gboolean try_focus = FALSE;
1649 GtkContainer *container = GTK_CONTAINER (toolbar);
1651 if (container->focus_child &&
1652 gtk_widget_child_focus (container->focus_child, dir))
1657 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1659 for (list = children; list != NULL; list = list->next)
1661 GtkWidget *child = list->data;
1663 if (try_focus && GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1666 if (child == GTK_CONTAINER (toolbar)->focus_child)
1670 g_list_free (children);
1675 /* The focus handler for the toolbar. It called when the user presses
1676 * TAB or otherwise tries to focus the toolbar.
1679 gtk_toolbar_focus (GtkWidget *widget,
1680 GtkDirectionType dir)
1682 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1683 GList *children, *list;
1685 /* if focus is already somewhere inside the toolbar then return FALSE.
1686 * The only way focus can stay inside the toolbar is when the user presses
1687 * arrow keys or Ctrl TAB (both of which are handled by the
1688 * gtk_toolbar_move_focus() keybinding function.
1690 if (GTK_CONTAINER (widget)->focus_child)
1693 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1695 for (list = children; list != NULL; list = list->next)
1697 GtkWidget *child = list->data;
1699 if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1703 g_list_free (children);
1709 style_change_notify (GtkToolbar *toolbar)
1711 if (!toolbar->style_set)
1713 /* pretend it was set, then unset, thus reverting to new default */
1714 toolbar->style_set = TRUE;
1715 gtk_toolbar_unset_style (toolbar);
1720 icon_size_change_notify (GtkToolbar *toolbar)
1722 if (!toolbar->icon_size_set)
1724 /* pretend it was set, then unset, thus reverting to new default */
1725 toolbar->icon_size_set = TRUE;
1726 gtk_toolbar_unset_icon_size (toolbar);
1730 static GtkSettings *
1731 toolbar_get_settings (GtkToolbar *toolbar)
1733 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1734 return priv->settings;
1738 gtk_toolbar_screen_changed (GtkWidget *widget,
1739 GdkScreen *previous_screen)
1741 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
1742 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1743 GtkSettings *old_settings = toolbar_get_settings (toolbar);
1744 GtkSettings *settings;
1746 if (gtk_widget_has_screen (GTK_WIDGET (toolbar)))
1747 settings = gtk_widget_get_settings (GTK_WIDGET (toolbar));
1751 if (settings == old_settings)
1756 g_signal_handler_disconnect (old_settings, toolbar->style_set_connection);
1757 g_signal_handler_disconnect (old_settings, toolbar->icon_size_connection);
1759 g_object_unref (old_settings);
1764 toolbar->style_set_connection =
1765 g_signal_connect_swapped (settings,
1766 "notify::gtk-toolbar-style",
1767 G_CALLBACK (style_change_notify),
1769 toolbar->icon_size_connection =
1770 g_signal_connect_swapped (settings,
1771 "notify::gtk-toolbar-icon-size",
1772 G_CALLBACK (icon_size_change_notify),
1775 g_object_ref (settings);
1776 priv->settings = settings;
1779 priv->settings = NULL;
1781 style_change_notify (toolbar);
1782 icon_size_change_notify (toolbar);
1786 find_drop_index (GtkToolbar *toolbar,
1790 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1791 GList *interesting_content;
1793 GtkOrientation orientation;
1794 GtkTextDirection direction;
1795 gint best_distance = G_MAXINT;
1799 ToolbarContent *best_content;
1801 /* list items we care about wrt. drag and drop */
1802 interesting_content = NULL;
1803 for (list = priv->content; list != NULL; list = list->next)
1805 ToolbarContent *content = list->data;
1807 if (content->state == NORMAL)
1808 interesting_content = g_list_prepend (interesting_content, content);
1810 interesting_content = g_list_reverse (interesting_content);
1812 if (!interesting_content)
1815 orientation = toolbar->orientation;
1816 direction = gtk_widget_get_direction (GTK_WIDGET (toolbar));
1818 /* distance to first interesting item */
1819 best_content = interesting_content->data;
1821 if (orientation == GTK_ORIENTATION_HORIZONTAL)
1825 if (direction == GTK_TEXT_DIR_LTR)
1826 pos = GTK_WIDGET (best_content->item)->allocation.x;
1828 pos = GTK_WIDGET (best_content->item)->allocation.x +
1829 GTK_WIDGET (best_content->item)->allocation.width;
1834 pos = GTK_WIDGET (best_content->item)->allocation.y;
1837 best_content = NULL;
1838 best_distance = ABS (pos - cursor);
1840 /* distance to far end of each item */
1841 for (list = interesting_content; list != NULL; list = list->next)
1843 ToolbarContent *content = list->data;
1844 GtkWidget *widget = GTK_WIDGET (content->item);
1846 if (orientation == GTK_ORIENTATION_HORIZONTAL)
1848 if (direction == GTK_TEXT_DIR_LTR)
1849 pos = widget->allocation.x + widget->allocation.width;
1851 pos = widget->allocation.x;
1855 pos = widget->allocation.y + widget->allocation.height;
1858 distance = ABS (pos - cursor);
1860 if (distance < best_distance)
1862 best_distance = distance;
1863 best_content = content;
1867 g_list_free (interesting_content);
1872 return g_list_index (priv->content, best_content) + 1;
1876 reset_all_placeholders (GtkToolbar *toolbar)
1878 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1881 for (list = priv->content; list != NULL; list = list->next)
1883 ToolbarContent *content = list->data;
1884 if (content->is_placeholder)
1885 gtk_widget_set_size_request (GTK_WIDGET (content->item), 0, 0);
1890 physical_to_logical (GtkToolbar *toolbar, gint physical)
1892 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1896 g_assert (physical >= 0);
1899 for (list = priv->content; list && physical > 0; list = list->next)
1901 ToolbarContent *content = list->data;
1903 if (!content->is_placeholder)
1908 g_assert (physical == 0);
1914 logical_to_physical (GtkToolbar *toolbar, gint logical)
1916 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1920 g_assert (logical >= 0);
1923 for (list = priv->content; list; list = list->next)
1925 ToolbarContent *content = list->data;
1927 if (!content->is_placeholder)
1937 g_assert (logical == 0);
1943 * gtk_toolbar_set_drop_highlight_item:
1944 * @toolbar: a #GtkToolbar
1945 * @item: a #GtkToolItem, or %NULL to turn of highlighting
1946 * @index: a position on @toolbar
1948 * Highlights @toolbar to give an idea of what it would look like
1949 * if @item was added to @toolbar at position indicated by @index. If @item
1950 * is %NULL, highlighting is turned off. In that case @index is ignored.
1952 * The @tool_item passed to this function must not be part of any widget
1953 * hierarchy. When an item is set as drop highlight item it can not
1954 * added to any widget hierarchy or used as highlight item for another
1960 gtk_toolbar_set_drop_highlight_item (GtkToolbar *toolbar,
1961 GtkToolItem *tool_item,
1964 ToolbarContent *content;
1965 GtkToolbarPrivate *priv;
1968 GtkRequisition requisition;
1970 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
1971 g_return_if_fail (tool_item == NULL || GTK_IS_TOOL_ITEM (tool_item));
1973 gtk_toolbar_check_new_api (toolbar);
1975 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1981 priv->leaving_dnd = TRUE;
1982 reset_all_placeholders (toolbar);
1983 gtk_toolbar_begin_sliding (toolbar);
1985 if (priv->highlight_tool_item)
1987 gtk_widget_unparent (GTK_WIDGET (priv->highlight_tool_item));
1988 g_object_unref (priv->highlight_tool_item);
1989 priv->highlight_tool_item = NULL;
1996 if (tool_item != priv->highlight_tool_item)
1998 if (priv->highlight_tool_item)
1999 g_object_unref (priv->highlight_tool_item);
2001 g_object_ref (tool_item);
2002 gtk_object_sink (GTK_OBJECT (tool_item));
2004 priv->highlight_tool_item = tool_item;
2006 gtk_widget_set_parent (GTK_WIDGET (priv->highlight_tool_item),
2007 GTK_WIDGET (toolbar));
2010 priv->in_dnd = TRUE;
2011 priv->leaving_dnd = FALSE;
2013 n_items = gtk_toolbar_get_n_items (toolbar);
2014 if (index < 0 || index > n_items)
2017 index = logical_to_physical (toolbar, index);
2019 content = g_list_nth_data (priv->content, index);
2023 ToolbarContent *prev_content;
2025 prev_content = g_list_nth_data (priv->content, index - 1);
2027 if (prev_content && prev_content->is_placeholder)
2028 content = prev_content;
2031 if (!content || !content->is_placeholder)
2033 GtkWidget *placeholder;
2035 placeholder = GTK_WIDGET (gtk_separator_tool_item_new ());
2036 content = gtk_toolbar_insert_tool_item (toolbar,
2037 GTK_TOOL_ITEM (placeholder),
2039 gtk_widget_show (placeholder);
2043 g_assert (content->is_placeholder);
2045 reset_all_placeholders (toolbar);
2047 gtk_widget_size_request (GTK_WIDGET (priv->highlight_tool_item),
2050 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
2051 requisition.height = -1;
2053 requisition.width = -1;
2055 gtk_widget_set_size_request (GTK_WIDGET (content->item),
2057 requisition.height);
2059 gtk_toolbar_begin_sliding (toolbar);
2063 gtk_toolbar_get_child_property (GtkContainer *container,
2069 GtkToolItem *item = GTK_TOOL_ITEM (child);
2071 switch (property_id)
2073 case CHILD_PROP_HOMOGENEOUS:
2074 g_value_set_boolean (value, gtk_tool_item_get_homogeneous (item));
2077 case CHILD_PROP_EXPAND:
2078 g_value_set_boolean (value, gtk_tool_item_get_expand (item));
2082 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2088 gtk_toolbar_set_child_property (GtkContainer *container,
2091 const GValue *value,
2094 switch (property_id)
2096 case CHILD_PROP_HOMOGENEOUS:
2097 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
2100 case CHILD_PROP_EXPAND:
2101 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
2105 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2111 gtk_toolbar_add (GtkContainer *container,
2114 GtkToolbar *toolbar;
2116 g_return_if_fail (GTK_IS_TOOLBAR (container));
2117 g_return_if_fail (widget != NULL);
2119 toolbar = GTK_TOOLBAR (container);
2121 if (GTK_IS_TOOL_ITEM (widget))
2122 gtk_toolbar_insert (toolbar, GTK_TOOL_ITEM (widget), 0);
2124 gtk_toolbar_append_widget (toolbar, widget, NULL, NULL);
2128 gtk_toolbar_remove (GtkContainer *container,
2131 GtkToolbar *toolbar;
2132 GtkToolItem *item = NULL;
2134 g_return_if_fail (GTK_IS_TOOLBAR (container));
2135 g_return_if_fail (GTK_IS_WIDGET (widget));
2137 toolbar = GTK_TOOLBAR (container);
2139 if (GTK_IS_TOOL_ITEM (widget))
2141 item = GTK_TOOL_ITEM (widget);
2145 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2148 for (list = priv->content; list != NULL; list = list->next)
2150 ToolbarContent *content = list->data;
2152 if (GTK_BIN (content->item)->child == widget)
2154 item = content->item;
2160 g_return_if_fail (item != NULL);
2162 gtk_toolbar_remove_tool_item (GTK_TOOLBAR (container), item);
2166 gtk_toolbar_forall (GtkContainer *container,
2167 gboolean include_internals,
2168 GtkCallback callback,
2169 gpointer callback_data)
2171 GtkToolbar *toolbar = GTK_TOOLBAR (container);
2172 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2175 g_return_if_fail (callback != NULL);
2177 list = priv->content;
2180 ToolbarContent *content = list->data;
2181 GList *next = list->next;
2183 if (!content->is_placeholder || include_internals)
2184 (*callback) (GTK_WIDGET (content->item), callback_data);
2189 if (include_internals)
2190 (* callback) (priv->arrow_button, callback_data);
2194 gtk_toolbar_child_type (GtkContainer *container)
2196 return GTK_TYPE_TOOL_ITEM;
2200 gtk_toolbar_reconfigured (GtkToolbar *toolbar)
2202 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2205 list = priv->content;
2208 ToolbarContent *content = list->data;
2209 GList *next = list->next;
2211 _gtk_tool_item_toolbar_reconfigured (content->item);
2218 gtk_toolbar_real_orientation_changed (GtkToolbar *toolbar,
2219 GtkOrientation orientation)
2221 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2222 if (toolbar->orientation != orientation)
2224 toolbar->orientation = orientation;
2226 if (orientation == GTK_ORIENTATION_HORIZONTAL)
2227 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_DOWN, GTK_SHADOW_NONE);
2228 else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2229 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
2231 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_LEFT, GTK_SHADOW_NONE);
2233 gtk_toolbar_reconfigured (toolbar);
2235 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2236 g_object_notify (G_OBJECT (toolbar), "orientation");
2241 gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
2242 GtkToolbarStyle style)
2244 if (toolbar->style != style)
2246 toolbar->style = style;
2248 gtk_toolbar_reconfigured (toolbar);
2250 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2251 g_object_notify (G_OBJECT (toolbar), "toolbar_style");
2256 menu_position_func (GtkMenu *menu,
2262 GtkToolbar *toolbar = GTK_TOOLBAR (user_data);
2263 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2265 GtkRequisition menu_req;
2267 gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y);
2268 gtk_widget_size_request (priv->arrow_button, &req);
2269 gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
2271 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
2273 *y += priv->arrow_button->allocation.height;
2274 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2275 *x += priv->arrow_button->allocation.width - req.width;
2277 *x += req.width - menu_req.width;
2281 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2282 *x += priv->arrow_button->allocation.width;
2284 *x -= menu_req.width;
2285 *y += priv->arrow_button->allocation.height - req.height;
2292 menu_deactivated (GtkWidget *menu,
2293 GtkToolbar *toolbar)
2295 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2297 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->arrow_button), FALSE);
2301 remove_item (GtkWidget *menu_item,
2304 gtk_container_remove (GTK_CONTAINER (menu_item->parent), menu_item);
2308 show_menu (GtkToolbar *toolbar,
2309 GdkEventButton *event)
2311 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2316 gtk_container_foreach (GTK_CONTAINER (priv->menu), remove_item, NULL);
2317 gtk_widget_destroy (GTK_WIDGET (priv->menu));
2320 priv->menu = GTK_MENU (gtk_menu_new ());
2321 g_signal_connect (priv->menu, "deactivate", G_CALLBACK (menu_deactivated), toolbar);
2323 for (list = priv->content; list != NULL; list = list->next)
2325 ToolbarContent *content = list->data;
2326 GtkToolItem *item = content->item;
2328 if (content->state == OVERFLOWN)
2330 GtkWidget *menu_item = gtk_tool_item_retrieve_proxy_menu_item (item);
2334 g_assert (GTK_IS_MENU_ITEM (menu_item));
2335 gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_item);
2340 gtk_widget_show_all (GTK_WIDGET (priv->menu));
2342 gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL,
2343 menu_position_func, toolbar,
2344 event? event->button : 0, event? event->time : gtk_get_current_event_time());
2348 gtk_toolbar_arrow_button_clicked (GtkWidget *button,
2349 GtkToolbar *toolbar)
2351 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2353 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->arrow_button)) &&
2354 (!priv->menu || !GTK_WIDGET_VISIBLE (GTK_WIDGET (priv->menu))))
2356 /* We only get here when the button is clicked with the keybaord,
2357 * because mouse button presses result in the menu being shown so
2358 * that priv->menu would be non-NULL and visible.
2360 show_menu (toolbar, NULL);
2361 gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menu), FALSE);
2366 gtk_toolbar_arrow_button_press (GtkWidget *button,
2367 GdkEventButton *event,
2368 GtkToolbar *toolbar)
2370 show_menu (toolbar, event);
2371 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2377 gtk_toolbar_button_press (GtkWidget *toolbar,
2378 GdkEventButton *event)
2380 if (event->button == 3)
2382 gboolean return_value;
2384 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2385 (int)event->x_root, (int)event->y_root, event->button,
2388 return return_value;
2395 gtk_toolbar_popup_menu (GtkWidget *toolbar)
2397 gboolean return_value;
2398 /* This function is the handler for the "popup menu" keybinding,
2399 * ie., it is called when the user presses Shift F10
2401 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2402 -1, -1, -1, &return_value);
2404 return return_value;
2408 gtk_toolbar_update_button_relief (GtkToolbar *toolbar)
2410 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2412 gtk_toolbar_reconfigured (toolbar);
2414 gtk_button_set_relief (GTK_BUTTON (priv->arrow_button), get_button_relief (toolbar));
2417 static GtkReliefStyle
2418 get_button_relief (GtkToolbar *toolbar)
2420 GtkReliefStyle button_relief = GTK_RELIEF_NORMAL;
2422 gtk_widget_ensure_style (GTK_WIDGET (toolbar));
2424 gtk_widget_style_get (GTK_WIDGET (toolbar),
2425 "button_relief", &button_relief,
2428 return button_relief;
2432 get_internal_padding (GtkToolbar *toolbar)
2436 gtk_widget_style_get (GTK_WIDGET (toolbar),
2437 "internal_padding", &ipadding,
2443 static GtkShadowType
2444 get_shadow_type (GtkToolbar *toolbar)
2446 GtkShadowType shadow_type;
2448 gtk_widget_style_get (GTK_WIDGET (toolbar),
2449 "shadow_type", &shadow_type,
2456 gtk_toolbar_check_old_api (GtkToolbar *toolbar)
2458 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2460 if (priv->api_mode == NEW_API)
2462 g_warning ("mixing deprecated and non-deprecated GtkToolbar API is not allowed");
2466 priv->api_mode = OLD_API;
2471 gtk_toolbar_check_new_api (GtkToolbar *toolbar)
2473 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2475 if (priv->api_mode == OLD_API)
2477 g_warning ("mixing deprecated and non-deprecated GtkToolbar API is not allowed");
2481 priv->api_mode = NEW_API;
2485 static ToolbarContent *
2486 gtk_toolbar_insert_tool_item (GtkToolbar *toolbar,
2489 gboolean is_placeholder)
2491 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2492 ToolbarContent *content = g_new0 (ToolbarContent, 1);
2494 content->is_placeholder = is_placeholder;
2495 content->item = item;
2496 content->state = NOT_ALLOCATED;
2497 toolbar->num_children++;
2499 priv->content = g_list_insert (priv->content, content, pos);
2501 gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar));
2503 if (!content->is_placeholder)
2504 gtk_toolbar_stop_sliding (toolbar);
2510 gtk_toolbar_remove_tool_item (GtkToolbar *toolbar,
2513 GtkToolbarPrivate *priv;
2516 ToolbarContent *content = NULL;
2518 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2519 g_return_if_fail (GTK_IS_TOOL_ITEM (item));
2521 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2525 for (tmp = priv->content; tmp != NULL; tmp = tmp->next)
2527 content = tmp->data;
2528 if (content->item == item)
2534 g_return_if_fail (content != NULL);
2538 priv->content = g_list_remove (priv->content, content);
2540 gtk_widget_unparent (GTK_WIDGET (item));
2542 if (priv->api_mode == OLD_API)
2544 GtkToolbarChild *toolbar_child;
2546 toolbar_child = g_list_nth_data (toolbar->children, nth_child);
2547 toolbar->children = g_list_remove (toolbar->children, toolbar_child);
2549 g_free (toolbar_child);
2552 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2558 * Creates a new toolbar.
2560 * Return Value: the newly-created toolbar.
2563 gtk_toolbar_new (void)
2565 GtkToolbar *toolbar;
2567 toolbar = g_object_new (GTK_TYPE_TOOLBAR, NULL);
2569 return GTK_WIDGET (toolbar);
2573 * gtk_toolbar_insert:
2574 * @toolbar: a #GtkToolbar
2575 * @item: a #GtkToolItem
2576 * @pos: the position of the new item
2578 * Insert a #GtkToolItem into the toolbar at position @pos. If @pos is
2579 * 0 the item is prepended to the start of the toolbar. If @pos is
2580 * negative, the item is appended to the end of the toolbar.
2585 gtk_toolbar_insert (GtkToolbar *toolbar,
2589 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2590 g_return_if_fail (GTK_IS_TOOL_ITEM (item));
2592 if (!gtk_toolbar_check_new_api (toolbar))
2596 pos = logical_to_physical (toolbar, pos);
2598 gtk_toolbar_insert_tool_item (toolbar, item, pos, FALSE);
2602 * gtk_toolbar_get_item_index:
2603 * @toolbar: a #GtkToolbar
2604 * @item: a #GtkToolItem that is a child of @toolbar
2606 * Returns the position of @item on the toolbar, starting from 0.
2607 * It is an error if @item is not a child of the toolbar.
2609 * Return value: the position of item on the toolbar.
2614 gtk_toolbar_get_item_index (GtkToolbar *toolbar,
2617 GtkToolbarPrivate *priv;
2621 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2622 g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1);
2623 g_return_val_if_fail (GTK_WIDGET (item)->parent == GTK_WIDGET (toolbar), -1);
2625 if (!gtk_toolbar_check_new_api (toolbar))
2628 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2631 for (list = priv->content; list != NULL; list = list->next)
2633 ToolbarContent *content = list->data;
2635 if (content->item == item)
2641 return physical_to_logical (toolbar, n);
2645 * gtk_toolbar_set_orientation:
2646 * @toolbar: a #GtkToolbar.
2647 * @orientation: a new #GtkOrientation.
2649 * Sets whether a toolbar should appear horizontally or vertically.
2652 gtk_toolbar_set_orientation (GtkToolbar *toolbar,
2653 GtkOrientation orientation)
2655 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2657 g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0, orientation);
2661 * gtk_toolbar_get_orientation:
2662 * @toolbar: a #GtkToolbar
2664 * Retrieves the current orientation of the toolbar. See
2665 * gtk_toolbar_set_orientation().
2667 * Return value: the orientation
2670 gtk_toolbar_get_orientation (GtkToolbar *toolbar)
2672 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
2674 return toolbar->orientation;
2678 * gtk_toolbar_set_style:
2679 * @toolbar: a #GtkToolbar.
2680 * @style: the new style for @toolbar.
2682 * Alters the view of @toolbar to display either icons only, text only, or both.
2685 gtk_toolbar_set_style (GtkToolbar *toolbar,
2686 GtkToolbarStyle style)
2688 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2690 toolbar->style_set = TRUE;
2691 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2697 * gtk_toolbar_get_style:
2698 * @toolbar: a #GtkToolbar
2700 * Retrieves whether the toolbar has text, icons, or both . See
2701 * gtk_toolbar_set_style().
2703 * Return value: the current style of @toolbar
2706 gtk_toolbar_get_style (GtkToolbar *toolbar)
2708 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_TOOLBAR_STYLE);
2710 return toolbar->style;
2714 * gtk_toolbar_unset_style:
2715 * @toolbar: a #GtkToolbar
2717 * Unsets a toolbar style set with gtk_toolbar_set_style(), so that
2718 * user preferences will be used to determine the toolbar style.
2721 gtk_toolbar_unset_style (GtkToolbar *toolbar)
2723 GtkToolbarStyle style;
2725 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2727 if (toolbar->style_set)
2729 GtkSettings *settings = toolbar_get_settings (toolbar);
2732 g_object_get (settings,
2733 "gtk-toolbar-style", &style,
2736 style = DEFAULT_TOOLBAR_STYLE;
2738 if (style != toolbar->style)
2739 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2741 toolbar->style_set = FALSE;
2746 * gtk_toolbar_set_tooltips:
2747 * @toolbar: a #GtkToolbar.
2748 * @enable: set to %FALSE to disable the tooltips, or %TRUE to enable them.
2750 * Sets if the tooltips of a toolbar should be active or not.
2753 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
2756 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2759 gtk_tooltips_enable (toolbar->tooltips);
2761 gtk_tooltips_disable (toolbar->tooltips);
2765 * gtk_toolbar_get_tooltips:
2766 * @toolbar: a #GtkToolbar
2768 * Retrieves whether tooltips are enabled. See
2769 * gtk_toolbar_set_tooltips().
2771 * Return value: %TRUE if tooltips are enabled
2774 gtk_toolbar_get_tooltips (GtkToolbar *toolbar)
2776 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2778 return toolbar->tooltips->enabled;
2782 * gtk_toolbar_get_n_items:
2783 * @toolbar: a #GtkToolbar
2785 * Returns the number of items on the toolbar.
2787 * Return value: the number of items on the toolbar
2792 gtk_toolbar_get_n_items (GtkToolbar *toolbar)
2794 GtkToolbarPrivate *priv;
2796 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2798 if (!gtk_toolbar_check_new_api (toolbar))
2801 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2803 return physical_to_logical (toolbar, g_list_length (priv->content));
2807 * gtk_toolbar_get_nth_item:
2808 * @toolbar: a #GtkToolbar
2809 * @n: A position on the toolbar
2811 * Returns the @n<!-- -->'s item on @toolbar, or %NULL if the
2812 * toolbar does not contain an @n<!-- -->'th item.
2814 * Return value: The @n<!-- -->'th #GtkToolItem on @toolbar, or %NULL if there
2815 * isn't an @n<!-- -->th item.
2820 gtk_toolbar_get_nth_item (GtkToolbar *toolbar,
2823 GtkToolbarPrivate *priv;
2824 ToolbarContent *content;
2827 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
2829 if (!gtk_toolbar_check_new_api (toolbar))
2832 n_items = gtk_toolbar_get_n_items (toolbar);
2834 if (n < 0 || n >= n_items)
2837 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2839 content = g_list_nth_data (priv->content, logical_to_physical (toolbar, n));
2842 g_assert (!content->is_placeholder);
2844 return content->item;
2848 * gtk_toolbar_set_icon_size:
2849 * @toolbar: A #GtkToolbar
2850 * @icon_size: The #GtkIconSize that stock icons in the toolbar shall have.
2852 * This function sets the size of stock icons in the toolbar. You
2853 * can call it both before you add the icons and after they've been
2854 * added. The size you set will override user preferences for the default
2858 gtk_toolbar_set_icon_size (GtkToolbar *toolbar,
2859 GtkIconSize icon_size)
2861 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2863 toolbar->icon_size_set = TRUE;
2865 if (toolbar->icon_size == icon_size)
2868 toolbar->icon_size = icon_size;
2870 gtk_toolbar_reconfigured (toolbar);
2872 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2876 * gtk_toolbar_get_icon_size:
2877 * @toolbar: a #GtkToolbar
2879 * Retrieves the icon size fo the toolbar. See gtk_toolbar_set_icon_size().
2881 * Return value: the current icon size for the icons on the toolbar.
2884 gtk_toolbar_get_icon_size (GtkToolbar *toolbar)
2886 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_ICON_SIZE);
2888 return toolbar->icon_size;
2892 * gtk_toolbar_get_relief_style:
2893 * @toolbar: a #GtkToolbar
2895 * Returns the relief style of buttons on @toolbar. See
2896 * gtk_button_set_relief_style().
2898 * Return value: The relief style of buttons on @toolbar.
2903 gtk_toolbar_get_relief_style (GtkToolbar *toolbar)
2905 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_RELIEF_NONE);
2907 return get_button_relief (toolbar);
2911 * gtk_toolbar_unset_icon_size:
2912 * @toolbar: a #GtkToolbar
2914 * Unsets toolbar icon size set with gtk_toolbar_set_icon_size(), so that
2915 * user preferences will be used to determine the icon size.
2918 gtk_toolbar_unset_icon_size (GtkToolbar *toolbar)
2922 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2924 if (toolbar->icon_size_set)
2926 GtkSettings *settings = toolbar_get_settings (toolbar);
2930 g_object_get (settings,
2931 "gtk-toolbar-icon-size", &size,
2935 size = DEFAULT_ICON_SIZE;
2937 if (size != toolbar->icon_size)
2938 gtk_toolbar_set_icon_size (toolbar, size);
2940 toolbar->icon_size_set = FALSE;
2945 * gtk_toolbar_set_show_arrow:
2946 * @toolbar: a #GtkToolbar
2947 * @show_arrow: Whether to show an overflow menu
2949 * Sets whether to show an overflow menu when
2950 * @toolbar doesn't have room for all items on it. If %TRUE,
2951 * items that there are not room are available through an
2957 gtk_toolbar_set_show_arrow (GtkToolbar *toolbar,
2958 gboolean show_arrow)
2960 GtkToolbarPrivate *priv;
2962 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2964 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2965 show_arrow = show_arrow != FALSE;
2967 if (priv->show_arrow != show_arrow)
2969 priv->show_arrow = show_arrow;
2971 if (!priv->show_arrow)
2972 gtk_widget_hide (priv->arrow_button);
2974 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2975 g_object_notify (G_OBJECT (toolbar), "show_arrow");
2980 * gtk_toolbar_get_show_arrow:
2981 * @toolbar: a #GtkToolbar
2983 * Returns whether the toolbar has an overflow menu.
2984 * See gtk_toolbar_set_show_arrow()
2991 gtk_toolbar_get_show_arrow (GtkToolbar *toolbar)
2993 GtkToolbarPrivate *priv;
2995 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2997 if (!gtk_toolbar_check_new_api (toolbar))
3000 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3002 return priv->show_arrow;
3006 * gtk_toolbar_get_drop_index:
3007 * @toolbar: a #GtkToolbar
3008 * @x: x coordinate of a point on the toolbar
3009 * @y: y coordinate of a point on the toolbar
3011 * Returns the position corresponding to the indicated point on
3012 * @toolbar. This is useful when dragging items to the toolbar:
3013 * this function returns the position a new item should be
3016 * @x and @y are in @toolbar coordinates.
3018 * Return value: The position corresponding to the point (@x, @y) on the toolbar.
3023 gtk_toolbar_get_drop_index (GtkToolbar *toolbar,
3027 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
3029 if (!gtk_toolbar_check_new_api (toolbar))
3032 return physical_to_logical (toolbar, find_drop_index (toolbar, x, y));
3036 * gtk_toolbar_append_item:
3037 * @toolbar: a #GtkToolbar.
3038 * @text: give your toolbar button a label.
3039 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3040 * @tooltip_private_text: use with #GtkTipsQuery.
3041 * @icon: a #GtkWidget that should be used as the button's icon.
3042 * @callback: the function to be executed when the button is pressed.
3043 * @user_data: a pointer to any data you wish to be passed to the callback.
3045 * Inserts a new item into the toolbar. You must specify the position
3046 * in the toolbar where it will be inserted.
3048 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3049 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3051 * Return value: the new toolbar item as a #GtkWidget.
3054 gtk_toolbar_append_item (GtkToolbar *toolbar,
3056 const char *tooltip_text,
3057 const char *tooltip_private_text,
3059 GtkSignalFunc callback,
3062 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3064 tooltip_text, tooltip_private_text,
3065 icon, callback, user_data,
3066 toolbar->num_children);
3070 * gtk_toolbar_prepend_item:
3071 * @toolbar: a #GtkToolbar.
3072 * @text: give your toolbar button a label.
3073 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3074 * @tooltip_private_text: use with #GtkTipsQuery.
3075 * @icon: a #GtkWidget that should be used as the button's icon.
3076 * @callback: the function to be executed when the button is pressed.
3077 * @user_data: a pointer to any data you wish to be passed to the callback.
3079 * Adds a new button to the beginning (top or left edges) of the given toolbar.
3081 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3082 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3084 * Return value: the new toolbar item as a #GtkWidget.
3087 gtk_toolbar_prepend_item (GtkToolbar *toolbar,
3089 const char *tooltip_text,
3090 const char *tooltip_private_text,
3092 GtkSignalFunc callback,
3095 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3097 tooltip_text, tooltip_private_text,
3098 icon, callback, user_data,
3103 * gtk_toolbar_insert_item:
3104 * @toolbar: a #GtkToolbar.
3105 * @text: give your toolbar button a label.
3106 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3107 * @tooltip_private_text: use with #GtkTipsQuery.
3108 * @icon: a #GtkWidget that should be used as the button's icon.
3109 * @callback: the function to be executed when the button is pressed.
3110 * @user_data: a pointer to any data you wish to be passed to the callback.
3111 * @position: the number of widgets to insert this item after.
3113 * Inserts a new item into the toolbar. You must specify the position in the
3114 * toolbar where it will be inserted.
3116 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3117 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3119 * Return value: the new toolbar item as a #GtkWidget.
3122 gtk_toolbar_insert_item (GtkToolbar *toolbar,
3124 const char *tooltip_text,
3125 const char *tooltip_private_text,
3127 GtkSignalFunc callback,
3131 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3133 tooltip_text, tooltip_private_text,
3134 icon, callback, user_data,
3139 * gtk_toolbar_insert_stock:
3140 * @toolbar: A #GtkToolbar
3141 * @stock_id: The id of the stock item you want to insert
3142 * @tooltip_text: The text in the tooltip of the toolbar button
3143 * @tooltip_private_text: The private text of the tooltip
3144 * @callback: The callback called when the toolbar button is clicked.
3145 * @user_data: user data passed to callback
3146 * @position: The position the button shall be inserted at.
3147 * -1 means at the end.
3149 * Inserts a stock item at the specified position of the toolbar. If
3150 * @stock_id is not a known stock item ID, it's inserted verbatim,
3151 * except that underscores used to mark mnemonics are removed.
3153 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3154 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3156 * Returns: the inserted widget
3159 gtk_toolbar_insert_stock (GtkToolbar *toolbar,
3160 const gchar *stock_id,
3161 const char *tooltip_text,
3162 const char *tooltip_private_text,
3163 GtkSignalFunc callback,
3167 return gtk_toolbar_internal_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3169 tooltip_text, tooltip_private_text,
3170 NULL, callback, user_data,
3175 * gtk_toolbar_append_space:
3176 * @toolbar: a #GtkToolbar.
3178 * Adds a new space to the end of the toolbar.
3181 gtk_toolbar_append_space (GtkToolbar *toolbar)
3183 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3187 toolbar->num_children);
3191 * gtk_toolbar_prepend_space:
3192 * @toolbar: a #GtkToolbar.
3194 * Adds a new space to the beginning of the toolbar.
3197 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
3199 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3207 * gtk_toolbar_insert_space:
3208 * @toolbar: a #GtkToolbar
3209 * @position: the number of widgets after which a space should be inserted.
3211 * Inserts a new space in the toolbar at the specified position.
3214 gtk_toolbar_insert_space (GtkToolbar *toolbar,
3217 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3225 * gtk_toolbar_remove_space:
3226 * @toolbar: a #GtkToolbar.
3227 * @position: the index of the space to remove.
3229 * Removes a space from the specified position.
3232 gtk_toolbar_remove_space (GtkToolbar *toolbar,
3237 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3239 if (!gtk_toolbar_check_old_api (toolbar))
3242 item = g_list_nth_data (toolbar->children, position);
3246 g_warning ("Toolbar position %d doesn't exist", position);
3250 if (!GTK_IS_SEPARATOR_TOOL_ITEM (item))
3252 g_warning ("Toolbar position %d is not a space", position);
3256 gtk_toolbar_remove_tool_item (toolbar, item);
3260 * gtk_toolbar_append_widget:
3261 * @toolbar: a #GtkToolbar.
3262 * @widget: a #GtkWidget to add to the toolbar.
3263 * @tooltip_text: the element's tooltip.
3264 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3266 * Adds a widget to the end of the given toolbar.
3269 gtk_toolbar_append_widget (GtkToolbar *toolbar,
3271 const gchar *tooltip_text,
3272 const gchar *tooltip_private_text)
3274 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3276 tooltip_text, tooltip_private_text,
3278 toolbar->num_children);
3282 * gtk_toolbar_prepend_widget:
3283 * @toolbar: a #GtkToolbar.
3284 * @widget: a #GtkWidget to add to the toolbar.
3285 * @tooltip_text: the element's tooltip.
3286 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3288 * Adds a widget to the beginning of the given toolbar.
3291 gtk_toolbar_prepend_widget (GtkToolbar *toolbar,
3293 const gchar *tooltip_text,
3294 const gchar *tooltip_private_text)
3296 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3298 tooltip_text, tooltip_private_text,
3304 * gtk_toolbar_insert_widget:
3305 * @toolbar: a #GtkToolbar.
3306 * @widget: a #GtkWidget to add to the toolbar.
3307 * @tooltip_text: the element's tooltip.
3308 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3309 * @position: the number of widgets to insert this widget after.
3311 * Inserts a widget in the toolbar at the given position.
3314 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
3316 const char *tooltip_text,
3317 const char *tooltip_private_text,
3320 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3322 tooltip_text, tooltip_private_text,
3328 * gtk_toolbar_append_element:
3329 * @toolbar: a #GtkToolbar.
3330 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
3331 * @widget: a #GtkWidget, or %NULL.
3332 * @text: the element's label.
3333 * @tooltip_text: the element's tooltip.
3334 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3335 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3336 * @callback: the function to be executed when the button is pressed.
3337 * @user_data: any data you wish to pass to the callback.
3339 * Adds a new element to the end of a toolbar.
3341 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3342 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3343 * the radio group for the new element. In all other cases, @widget must
3346 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3347 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3349 * Return value: the new toolbar element as a #GtkWidget.
3352 gtk_toolbar_append_element (GtkToolbar *toolbar,
3353 GtkToolbarChildType type,
3356 const char *tooltip_text,
3357 const char *tooltip_private_text,
3359 GtkSignalFunc callback,
3362 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3363 tooltip_text, tooltip_private_text,
3364 icon, callback, user_data,
3365 toolbar->num_children);
3369 * gtk_toolbar_prepend_element:
3370 * @toolbar: a #GtkToolbar.
3371 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
3372 * @widget: a #GtkWidget, or %NULL
3373 * @text: the element's label.
3374 * @tooltip_text: the element's tooltip.
3375 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3376 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3377 * @callback: the function to be executed when the button is pressed.
3378 * @user_data: any data you wish to pass to the callback.
3380 * Adds a new element to the beginning of a toolbar.
3382 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3383 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3384 * the radio group for the new element. In all other cases, @widget must
3387 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3388 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3390 * Return value: the new toolbar element as a #GtkWidget.
3393 gtk_toolbar_prepend_element (GtkToolbar *toolbar,
3394 GtkToolbarChildType type,
3397 const char *tooltip_text,
3398 const char *tooltip_private_text,
3400 GtkSignalFunc callback,
3403 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3404 tooltip_text, tooltip_private_text,
3405 icon, callback, user_data, 0);
3409 * gtk_toolbar_insert_element:
3410 * @toolbar: a #GtkToolbar.
3411 * @type: a value of type #GtkToolbarChildType that determines what @widget
3413 * @widget: a #GtkWidget, or %NULL.
3414 * @text: the element's label.
3415 * @tooltip_text: the element's tooltip.
3416 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3417 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3418 * @callback: the function to be executed when the button is pressed.
3419 * @user_data: any data you wish to pass to the callback.
3420 * @position: the number of widgets to insert this element after.
3422 * Inserts a new element in the toolbar at the given position.
3424 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3425 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3426 * the radio group for the new element. In all other cases, @widget must
3429 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3430 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3432 * Return value: the new toolbar element as a #GtkWidget.
3435 gtk_toolbar_insert_element (GtkToolbar *toolbar,
3436 GtkToolbarChildType type,
3439 const char *tooltip_text,
3440 const char *tooltip_private_text,
3442 GtkSignalFunc callback,
3446 return gtk_toolbar_internal_insert_element (toolbar, type, widget, text,
3447 tooltip_text, tooltip_private_text,
3448 icon, callback, user_data, position, FALSE);
3452 _gtk_toolbar_elide_underscores (const gchar *original)
3456 gboolean last_underscore;
3458 q = result = g_malloc (strlen (original) + 1);
3459 last_underscore = FALSE;
3461 for (p = original; *p; p++)
3463 if (!last_underscore && *p == '_')
3464 last_underscore = TRUE;
3467 last_underscore = FALSE;
3478 gtk_toolbar_internal_insert_element (GtkToolbar *toolbar,
3479 GtkToolbarChildType type,
3482 const char *tooltip_text,
3483 const char *tooltip_private_text,
3485 GtkSignalFunc callback,
3490 GtkToolbarChild *child;
3491 GtkToolItem *item = NULL;
3493 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
3495 if (!gtk_toolbar_check_old_api (toolbar))
3498 if (type == GTK_TOOLBAR_CHILD_WIDGET)
3499 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3500 else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON)
3501 g_return_val_if_fail (widget == NULL, NULL);
3503 child = g_new (GtkToolbarChild, 1);
3507 child->label = NULL;
3511 case GTK_TOOLBAR_CHILD_SPACE:
3512 item = gtk_separator_tool_item_new ();
3513 child->widget = NULL;
3516 case GTK_TOOLBAR_CHILD_WIDGET:
3517 item = gtk_tool_item_new ();
3518 child->widget = widget;
3519 gtk_container_add (GTK_CONTAINER (item), child->widget);
3522 case GTK_TOOLBAR_CHILD_BUTTON:
3523 item = gtk_tool_button_new (NULL, NULL);
3524 child->widget = _gtk_tool_button_get_button (GTK_TOOL_BUTTON (item));
3527 case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
3528 item = gtk_toggle_tool_button_new ();
3529 child->widget = _gtk_tool_button_get_button (GTK_TOOL_BUTTON (item));
3532 case GTK_TOOLBAR_CHILD_RADIOBUTTON:
3533 item = gtk_radio_tool_button_new (widget
3534 ? gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget))
3536 child->widget = _gtk_tool_button_get_button (GTK_TOOL_BUTTON (item));
3541 * When we are using the old API, consider all items "is_important". That
3542 * way BOTH_HORIZ will continue to show both icon and label in old API mode
3544 gtk_tool_item_set_is_important (item, TRUE);
3546 gtk_widget_show (GTK_WIDGET (item));
3548 if (type == GTK_TOOLBAR_CHILD_BUTTON ||
3549 type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
3550 type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
3556 GtkStockItem stock_item;
3559 gtk_tool_button_set_stock_id (GTK_TOOL_BUTTON (item), text);
3561 gtk_stock_lookup (text, &stock_item);
3562 label_text = _gtk_toolbar_elide_underscores (stock_item.label);
3563 child->label = GTK_WIDGET (gtk_label_new (label_text));
3564 g_free (label_text);
3568 child->label = gtk_label_new (text);
3570 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (item), child->label);
3571 gtk_widget_show (child->label);
3577 gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (item), icon);
3579 /* Applications depend on the toolbar showing the widget for them */
3580 gtk_widget_show (GTK_WIDGET (icon));
3584 * We need to connect to the button's clicked callback because some
3585 * programs may rely on that the widget in the callback is a GtkButton
3588 g_signal_connect (child->widget, "clicked",
3589 callback, user_data);
3592 if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text)
3593 gtk_tool_item_set_tooltip (item, toolbar->tooltips,
3594 tooltip_text, tooltip_private_text);
3596 toolbar->children = g_list_insert (toolbar->children, child, position);
3598 gtk_toolbar_insert_tool_item (toolbar, item, position, FALSE);
3600 return child->widget;
3604 gtk_toolbar_finalize (GObject *object)
3607 GtkToolbar *toolbar = GTK_TOOLBAR (object);
3608 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3610 if (toolbar->tooltips)
3611 g_object_unref (toolbar->tooltips);
3613 for (list = toolbar->children; list != NULL; list = list->next)
3614 g_free (list->data);
3616 g_list_free (toolbar->children);
3618 for (list = priv->content; list != NULL; list = list->next)
3619 g_free (list->data);
3621 g_list_free (priv->content);
3623 g_timer_destroy (priv->timer);
3626 g_source_remove (priv->idle_id);
3628 G_OBJECT_CLASS (parent_class)->finalize (object);