1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 * GtkToolbar copyright (C) Federico Mena
5 * Copyright (C) 2002 Anders Carlsson <andersca@gnome.org>
6 * Copyright (C) 2002 James Henstridge <james@daa.com.au>
7 * Copyright (C) 2003, 2004 Soeren Sandmann <sandmann@daimi.au.dk>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
26 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
27 * file for a list of people on the GTK+ Team. See the ChangeLog
28 * files for a list of changes. These files are distributed with
29 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
32 #undef GTK_DISABLE_DEPRECATED
37 #include "gtktoolbar.h"
38 #include "gtkradiotoolbutton.h"
39 #include "gtkseparatortoolitem.h"
41 #include "gtkradiobutton.h"
42 #include "gtktoolbar.h"
43 #include "gtkbindings.h"
44 #include <gdk/gdkkeysyms.h>
45 #include "gtkmarshalers.h"
49 #include "gtkprivate.h"
55 #include "gtkseparatormenuitem.h"
58 typedef struct _ToolbarContent ToolbarContent;
60 #define DEFAULT_IPADDING 0
62 #define DEFAULT_SPACE_SIZE 12
63 #define DEFAULT_SPACE_STYLE GTK_TOOLBAR_SPACE_LINE
64 #define SPACE_LINE_DIVISION 10.0
65 #define SPACE_LINE_START 2.0
66 #define SPACE_LINE_END 8.0
68 #define DEFAULT_ICON_SIZE GTK_ICON_SIZE_LARGE_TOOLBAR
69 #define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_BOTH
71 #define MAX_HOMOGENEOUS_N_CHARS 13 /* Items that are wider than this do not participate
72 * in the homogeneous game. In units of
73 * pango_font_get_estimated_char_width().
75 #define SLIDE_SPEED 600.0 /* How fast the items slide, in pixels per second */
76 #define ACCEL_THRESHOLD 0.18 /* After how much time in seconds will items start speeding up */
78 #define MIXED_API_WARNING \
79 "Mixing deprecated and non-deprecated GtkToolbar API is not allowed"
90 /* Child properties */
94 CHILD_PROP_HOMOGENEOUS
126 struct _GtkToolbarPrivate
131 GtkWidget * arrow_button;
134 GdkWindow * event_window;
136 GtkSettings * settings;
138 GtkToolItem * highlight_tool_item;
139 gint max_homogeneous_pixels;
143 guint show_arrow : 1;
145 guint is_sliding : 1;
146 guint need_rebuild : 1; /* whether the overflow menu should be regenerated */
149 static void gtk_toolbar_init (GtkToolbar *toolbar);
150 static void gtk_toolbar_class_init (GtkToolbarClass *klass);
151 static void gtk_toolbar_set_property (GObject *object,
155 static void gtk_toolbar_get_property (GObject *object,
159 static gint gtk_toolbar_expose (GtkWidget *widget,
160 GdkEventExpose *event);
161 static void gtk_toolbar_realize (GtkWidget *widget);
162 static void gtk_toolbar_unrealize (GtkWidget *widget);
163 static void gtk_toolbar_size_request (GtkWidget *widget,
164 GtkRequisition *requisition);
165 static void gtk_toolbar_size_allocate (GtkWidget *widget,
166 GtkAllocation *allocation);
167 static void gtk_toolbar_style_set (GtkWidget *widget,
168 GtkStyle *prev_style);
169 static gboolean gtk_toolbar_focus (GtkWidget *widget,
170 GtkDirectionType dir);
171 static void gtk_toolbar_screen_changed (GtkWidget *widget,
172 GdkScreen *previous_screen);
173 static void gtk_toolbar_map (GtkWidget *widget);
174 static void gtk_toolbar_unmap (GtkWidget *widget);
175 static void gtk_toolbar_set_child_property (GtkContainer *container,
180 static void gtk_toolbar_get_child_property (GtkContainer *container,
185 static void gtk_toolbar_finalize (GObject *object);
186 static void gtk_toolbar_show_all (GtkWidget *widget);
187 static void gtk_toolbar_hide_all (GtkWidget *widget);
188 static void gtk_toolbar_add (GtkContainer *container,
190 static void gtk_toolbar_remove (GtkContainer *container,
192 static void gtk_toolbar_forall (GtkContainer *container,
193 gboolean include_internals,
194 GtkCallback callback,
195 gpointer callback_data);
196 static GType gtk_toolbar_child_type (GtkContainer *container);
197 static void gtk_toolbar_orientation_changed (GtkToolbar *toolbar,
198 GtkOrientation orientation);
199 static void gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
200 GtkToolbarStyle style);
201 static gboolean gtk_toolbar_move_focus (GtkToolbar *toolbar,
202 GtkDirectionType dir);
203 static gboolean gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
204 gboolean focus_home);
205 static gboolean gtk_toolbar_button_press (GtkWidget *toolbar,
206 GdkEventButton *event);
207 static gboolean gtk_toolbar_arrow_button_press (GtkWidget *button,
208 GdkEventButton *event,
209 GtkToolbar *toolbar);
210 static void gtk_toolbar_arrow_button_clicked (GtkWidget *button,
211 GtkToolbar *toolbar);
212 static void gtk_toolbar_update_button_relief (GtkToolbar *toolbar);
213 static gboolean gtk_toolbar_popup_menu (GtkWidget *toolbar);
214 static GtkWidget *internal_insert_element (GtkToolbar *toolbar,
215 GtkToolbarChildType type,
218 const char *tooltip_text,
219 const char *tooltip_private_text,
221 GtkSignalFunc callback,
225 static void gtk_toolbar_reconfigured (GtkToolbar *toolbar);
226 static gboolean gtk_toolbar_check_new_api (GtkToolbar *toolbar);
227 static gboolean gtk_toolbar_check_old_api (GtkToolbar *toolbar);
229 static GtkReliefStyle get_button_relief (GtkToolbar *toolbar);
230 static gint get_internal_padding (GtkToolbar *toolbar);
231 static GtkShadowType get_shadow_type (GtkToolbar *toolbar);
232 static gint get_space_size (GtkToolbar *toolbar);
233 static GtkToolbarSpaceStyle get_space_style (GtkToolbar *toolbar);
235 /* methods on ToolbarContent 'class' */
236 static ToolbarContent *toolbar_content_new_tool_item (GtkToolbar *toolbar,
238 gboolean is_placeholder,
240 static ToolbarContent *toolbar_content_new_compatibility (GtkToolbar *toolbar,
241 GtkToolbarChildType type,
246 static void toolbar_content_remove (ToolbarContent *content,
247 GtkToolbar *toolbar);
248 static void toolbar_content_free (ToolbarContent *content);
249 static void toolbar_content_expose (ToolbarContent *content,
250 GtkContainer *container,
251 GdkEventExpose *expose);
252 static gboolean toolbar_content_visible (ToolbarContent *content,
253 GtkToolbar *toolbar);
254 static void toolbar_content_size_request (ToolbarContent *content,
256 GtkRequisition *requisition);
257 static gboolean toolbar_content_is_homogeneous (ToolbarContent *content,
258 GtkToolbar *toolbar);
259 static gboolean toolbar_content_is_placeholder (ToolbarContent *content);
260 static gboolean toolbar_content_disappearing (ToolbarContent *content);
261 static ItemState toolbar_content_get_state (ToolbarContent *content);
262 static gboolean toolbar_content_child_visible (ToolbarContent *content);
263 static void toolbar_content_get_goal_allocation (ToolbarContent *content,
264 GtkAllocation *allocation);
265 static void toolbar_content_get_allocation (ToolbarContent *content,
266 GtkAllocation *allocation);
267 static void toolbar_content_set_start_allocation (ToolbarContent *content,
268 GtkAllocation *new_start_allocation);
269 static void toolbar_content_get_start_allocation (ToolbarContent *content,
270 GtkAllocation *start_allocation);
271 static gboolean toolbar_content_get_expand (ToolbarContent *content);
272 static void toolbar_content_set_goal_allocation (ToolbarContent *content,
273 GtkAllocation *allocation);
274 static void toolbar_content_set_child_visible (ToolbarContent *content,
277 static void toolbar_content_size_allocate (ToolbarContent *content,
278 GtkAllocation *allocation);
279 static void toolbar_content_set_state (ToolbarContent *content,
280 ItemState new_state);
281 static GtkWidget * toolbar_content_get_widget (ToolbarContent *content);
282 static void toolbar_content_set_disappearing (ToolbarContent *content,
283 gboolean disappearing);
284 static void toolbar_content_set_size_request (ToolbarContent *content,
287 static void toolbar_content_toolbar_reconfigured (ToolbarContent *content,
288 GtkToolbar *toolbar);
289 static GtkWidget * toolbar_content_retrieve_menu_item (ToolbarContent *content);
290 static gboolean toolbar_content_has_proxy_menu_item (ToolbarContent *content);
291 static gboolean toolbar_content_is_separator (ToolbarContent *content);
292 static void toolbar_content_show_all (ToolbarContent *content);
293 static void toolbar_content_hide_all (ToolbarContent *content);
294 static void toolbar_content_set_expand (ToolbarContent *content,
297 #define GTK_TOOLBAR_GET_PRIVATE(o) \
298 (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_TOOLBAR, GtkToolbarPrivate))
300 static GtkContainerClass * parent_class = NULL;
301 static guint toolbar_signals [LAST_SIGNAL] = { 0 };
304 gtk_toolbar_get_type (void)
306 static GtkType type = 0;
310 static const GTypeInfo type_info =
312 sizeof (GtkToolbarClass),
313 (GBaseInitFunc) NULL,
314 (GBaseFinalizeFunc) NULL,
315 (GClassInitFunc) gtk_toolbar_class_init,
316 (GClassFinalizeFunc) NULL,
320 (GInstanceInitFunc) gtk_toolbar_init,
323 type = g_type_register_static (GTK_TYPE_CONTAINER,
332 add_arrow_bindings (GtkBindingSet *binding_set,
334 GtkDirectionType dir)
336 guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
338 gtk_binding_entry_add_signal (binding_set, keysym, 0,
340 GTK_TYPE_DIRECTION_TYPE, dir);
341 gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
343 GTK_TYPE_DIRECTION_TYPE, dir);
347 add_ctrl_tab_bindings (GtkBindingSet *binding_set,
348 GdkModifierType modifiers,
349 GtkDirectionType direction)
351 gtk_binding_entry_add_signal (binding_set,
352 GDK_Tab, GDK_CONTROL_MASK | modifiers,
354 GTK_TYPE_DIRECTION_TYPE, direction);
355 gtk_binding_entry_add_signal (binding_set,
356 GDK_KP_Tab, GDK_CONTROL_MASK | modifiers,
358 GTK_TYPE_DIRECTION_TYPE, direction);
362 gtk_toolbar_class_init (GtkToolbarClass *klass)
364 GObjectClass *gobject_class;
365 GtkWidgetClass *widget_class;
366 GtkContainerClass *container_class;
367 GtkBindingSet *binding_set;
369 parent_class = g_type_class_peek_parent (klass);
371 gobject_class = (GObjectClass *)klass;
372 widget_class = (GtkWidgetClass *)klass;
373 container_class = (GtkContainerClass *)klass;
375 gobject_class->set_property = gtk_toolbar_set_property;
376 gobject_class->get_property = gtk_toolbar_get_property;
377 gobject_class->finalize = gtk_toolbar_finalize;
379 widget_class->button_press_event = gtk_toolbar_button_press;
380 widget_class->expose_event = gtk_toolbar_expose;
381 widget_class->size_request = gtk_toolbar_size_request;
382 widget_class->size_allocate = gtk_toolbar_size_allocate;
383 widget_class->style_set = gtk_toolbar_style_set;
384 widget_class->focus = gtk_toolbar_focus;
385 widget_class->screen_changed = gtk_toolbar_screen_changed;
386 widget_class->realize = gtk_toolbar_realize;
387 widget_class->unrealize = gtk_toolbar_unrealize;
388 widget_class->map = gtk_toolbar_map;
389 widget_class->unmap = gtk_toolbar_unmap;
390 widget_class->popup_menu = gtk_toolbar_popup_menu;
391 widget_class->show_all = gtk_toolbar_show_all;
392 widget_class->hide_all = gtk_toolbar_hide_all;
394 container_class->add = gtk_toolbar_add;
395 container_class->remove = gtk_toolbar_remove;
396 container_class->forall = gtk_toolbar_forall;
397 container_class->child_type = gtk_toolbar_child_type;
398 container_class->get_child_property = gtk_toolbar_get_child_property;
399 container_class->set_child_property = gtk_toolbar_set_child_property;
401 klass->orientation_changed = gtk_toolbar_orientation_changed;
402 klass->style_changed = gtk_toolbar_real_style_changed;
405 * GtkToolbar::orientation-changed:
406 * @toolbar: the object which emitted the signal
407 * @orientation: the new #GtkOrientation of the toolbar
409 * Emitted when the orientation of the toolbar changes.
411 toolbar_signals[ORIENTATION_CHANGED] =
412 g_signal_new ("orientation-changed",
413 G_OBJECT_CLASS_TYPE (klass),
415 G_STRUCT_OFFSET (GtkToolbarClass, orientation_changed),
417 g_cclosure_marshal_VOID__ENUM,
419 GTK_TYPE_ORIENTATION);
421 * GtkToolbar::style-changed:
422 * @toolbar: The #GtkToolbar which emitted the signal
423 * @style: the new #GtkToolbarStyle of the toolbar
425 * Emitted when the style of the toolbar changes.
427 toolbar_signals[STYLE_CHANGED] =
428 g_signal_new ("style-changed",
429 G_OBJECT_CLASS_TYPE (klass),
431 G_STRUCT_OFFSET (GtkToolbarClass, style_changed),
433 g_cclosure_marshal_VOID__ENUM,
435 GTK_TYPE_TOOLBAR_STYLE);
437 * GtkToolbar::popup-context-menu:
438 * @toolbar: the #GtkToolbar which emitted the signal
439 * @x: the x coordinate of the point where the menu should appear
440 * @y: the y coordinate of the point where the menu should appear
441 * @button: the mouse button the user pressed, or -1
443 * Emitted when the user right-clicks the toolbar or uses the
444 * keybinding to display a popup menu.
446 * Application developers should handle this signal if they want
447 * to display a context menu on the toolbar. The context-menu should
448 * appear at the coordinates given by @x and @y. The mouse button
449 * number is given by the @button parameter. If the menu was popped
450 * up using the keybaord, @button is -1.
452 * Return value: return %TRUE if the signal was handled, %FALSE if not
454 toolbar_signals[POPUP_CONTEXT_MENU] =
455 g_signal_new ("popup_context_menu",
456 G_OBJECT_CLASS_TYPE (klass),
458 G_STRUCT_OFFSET (GtkToolbarClass, popup_context_menu),
459 _gtk_boolean_handled_accumulator, NULL,
460 _gtk_marshal_BOOLEAN__INT_INT_INT,
462 G_TYPE_INT, G_TYPE_INT,
465 * GtkToolbar::move-focus:
466 * @toolbar: the #GtkToolbar which emitted the signal
467 * @dir: a #GtkDirection
469 * A keybinding signal used internally by GTK+. This signal can't
470 * be used in application code.
472 * Return value: %TRUE if the signal was handled, %FALSE if not
474 toolbar_signals[MOVE_FOCUS] =
475 _gtk_binding_signal_new ("move_focus",
476 G_TYPE_FROM_CLASS (klass),
477 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
478 G_CALLBACK (gtk_toolbar_move_focus),
480 _gtk_marshal_BOOLEAN__ENUM,
482 GTK_TYPE_DIRECTION_TYPE);
484 * GtkToolbar::focus-home-or-end:
485 * @toolbar: the #GtkToolbar which emitted the signal
486 * @focus_home: %TRUE if the first item should be focused
488 * A keybinding signal used internally by GTK+. This signal can't
489 * be used in application code
491 * Return value: %TRUE if the signal was handled, %FALSE if not
493 toolbar_signals[FOCUS_HOME_OR_END] =
494 _gtk_binding_signal_new ("focus_home_or_end",
495 G_OBJECT_CLASS_TYPE (klass),
496 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
497 G_CALLBACK (gtk_toolbar_focus_home_or_end),
499 _gtk_marshal_BOOLEAN__BOOLEAN,
504 g_object_class_install_property (gobject_class,
506 g_param_spec_enum ("orientation",
508 P_("The orientation of the toolbar"),
509 GTK_TYPE_ORIENTATION,
510 GTK_ORIENTATION_HORIZONTAL,
513 g_object_class_install_property (gobject_class,
515 g_param_spec_enum ("toolbar_style",
517 P_("How to draw the toolbar"),
518 GTK_TYPE_TOOLBAR_STYLE,
521 g_object_class_install_property (gobject_class,
523 g_param_spec_boolean ("show_arrow",
525 P_("If an arrow should be shown if the toolbar doesn't fit"),
529 /* child properties */
530 gtk_container_class_install_child_property (container_class,
532 g_param_spec_boolean ("expand",
534 P_("Whether the item should receive extra space when the toolbar grows"),
538 gtk_container_class_install_child_property (container_class,
539 CHILD_PROP_HOMOGENEOUS,
540 g_param_spec_boolean ("homogeneous",
542 P_("Whether the item should be the same size as other homogeneous items"),
546 /* style properties */
547 gtk_widget_class_install_style_property (widget_class,
548 g_param_spec_int ("space_size",
550 P_("Size of spacers"),
556 gtk_widget_class_install_style_property (widget_class,
557 g_param_spec_int ("internal_padding",
558 P_("Internal padding"),
559 P_("Amount of border space between the toolbar shadow and the buttons"),
565 gtk_widget_class_install_style_property (widget_class,
566 g_param_spec_enum ("space_style",
568 P_("Whether spacers are vertical lines or just blank"),
569 GTK_TYPE_TOOLBAR_SPACE_STYLE,
573 gtk_widget_class_install_style_property (widget_class,
574 g_param_spec_enum ("button_relief",
576 P_("Type of bevel around toolbar buttons"),
577 GTK_TYPE_RELIEF_STYLE,
580 gtk_widget_class_install_style_property (widget_class,
581 g_param_spec_enum ("shadow_type",
583 P_("Style of bevel around the toolbar"),
584 GTK_TYPE_SHADOW_TYPE,
588 gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-style",
590 P_("Whether default toolbars have text only, text and icons, icons only, etc."),
591 GTK_TYPE_TOOLBAR_STYLE,
592 DEFAULT_TOOLBAR_STYLE,
595 gtk_settings_install_property (g_param_spec_enum ("gtk-toolbar-icon-size",
596 P_("Toolbar icon size"),
597 P_("Size of icons in default toolbars"),
602 binding_set = gtk_binding_set_by_class (klass);
604 add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
605 add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT);
606 add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
607 add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
609 gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
610 "focus_home_or_end", 1,
611 G_TYPE_BOOLEAN, TRUE);
612 gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
613 "focus_home_or_end", 1,
614 G_TYPE_BOOLEAN, TRUE);
615 gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
616 "focus_home_or_end", 1,
617 G_TYPE_BOOLEAN, FALSE);
618 gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
619 "focus_home_or_end", 1,
620 G_TYPE_BOOLEAN, FALSE);
622 add_ctrl_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
623 add_ctrl_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
625 g_type_class_add_private (gobject_class, sizeof (GtkToolbarPrivate));
629 gtk_toolbar_init (GtkToolbar *toolbar)
631 GtkToolbarPrivate *priv;
633 GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS);
634 GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW);
636 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
638 toolbar->orientation = GTK_ORIENTATION_HORIZONTAL;
639 toolbar->style = DEFAULT_TOOLBAR_STYLE;
640 toolbar->icon_size = DEFAULT_ICON_SIZE;
641 toolbar->tooltips = gtk_tooltips_new ();
642 g_object_ref (toolbar->tooltips);
643 gtk_object_sink (GTK_OBJECT (toolbar->tooltips));
645 priv->arrow_button = gtk_toggle_button_new ();
646 g_signal_connect (priv->arrow_button, "button_press_event",
647 G_CALLBACK (gtk_toolbar_arrow_button_press), toolbar);
648 g_signal_connect (priv->arrow_button, "clicked",
649 G_CALLBACK (gtk_toolbar_arrow_button_clicked), toolbar);
650 gtk_button_set_relief (GTK_BUTTON (priv->arrow_button),
651 get_button_relief (toolbar));
653 priv->api_mode = DONT_KNOW;
655 gtk_button_set_focus_on_click (GTK_BUTTON (priv->arrow_button), FALSE);
657 priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
658 gtk_widget_set_name (priv->arrow, "gtk-toolbar-arrow");
659 gtk_widget_show (priv->arrow);
660 gtk_container_add (GTK_CONTAINER (priv->arrow_button), priv->arrow);
662 gtk_widget_set_parent (priv->arrow_button, GTK_WIDGET (toolbar));
664 /* which child position a drop will occur at */
666 priv->show_arrow = TRUE;
667 priv->settings = NULL;
669 priv->max_homogeneous_pixels = -1;
671 priv->timer = g_timer_new ();
675 gtk_toolbar_set_property (GObject *object,
680 GtkToolbar *toolbar = GTK_TOOLBAR (object);
684 case PROP_ORIENTATION:
685 gtk_toolbar_set_orientation (toolbar, g_value_get_enum (value));
687 case PROP_TOOLBAR_STYLE:
688 gtk_toolbar_set_style (toolbar, g_value_get_enum (value));
690 case PROP_SHOW_ARROW:
691 gtk_toolbar_set_show_arrow (toolbar, g_value_get_boolean (value));
694 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
700 gtk_toolbar_get_property (GObject *object,
705 GtkToolbar *toolbar = GTK_TOOLBAR (object);
706 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
710 case PROP_ORIENTATION:
711 g_value_set_enum (value, toolbar->orientation);
713 case PROP_TOOLBAR_STYLE:
714 g_value_set_enum (value, toolbar->style);
716 case PROP_SHOW_ARROW:
717 g_value_set_boolean (value, priv->show_arrow);
720 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
726 gtk_toolbar_map (GtkWidget *widget)
728 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
730 GTK_WIDGET_CLASS (parent_class)->map (widget);
732 if (priv->event_window)
733 gdk_window_show_unraised (priv->event_window);
737 gtk_toolbar_unmap (GtkWidget *widget)
739 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
741 if (priv->event_window)
742 gdk_window_hide (priv->event_window);
744 GTK_WIDGET_CLASS (parent_class)->unmap (widget);
748 gtk_toolbar_realize (GtkWidget *widget)
750 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
751 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
753 GdkWindowAttr attributes;
754 gint attributes_mask;
757 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
759 border_width = GTK_CONTAINER (widget)->border_width;
761 attributes.wclass = GDK_INPUT_ONLY;
762 attributes.window_type = GDK_WINDOW_CHILD;
763 attributes.x = widget->allocation.x + border_width;
764 attributes.y = widget->allocation.y + border_width;
765 attributes.width = widget->allocation.width - border_width * 2;
766 attributes.height = widget->allocation.height - border_width * 2;
767 attributes.event_mask = gtk_widget_get_events (widget);
768 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
769 GDK_BUTTON_RELEASE_MASK |
770 GDK_ENTER_NOTIFY_MASK |
771 GDK_LEAVE_NOTIFY_MASK);
773 attributes_mask = GDK_WA_X | GDK_WA_Y;
775 widget->window = gtk_widget_get_parent_window (widget);
776 g_object_ref (widget->window);
777 widget->style = gtk_style_attach (widget->style, widget->window);
779 priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
780 &attributes, attributes_mask);
781 gdk_window_set_user_data (priv->event_window, toolbar);
785 gtk_toolbar_unrealize (GtkWidget *widget)
787 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
789 if (priv->event_window)
791 gdk_window_set_user_data (priv->event_window, NULL);
792 gdk_window_destroy (priv->event_window);
793 priv->event_window = NULL;
796 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
797 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
801 gtk_toolbar_expose (GtkWidget *widget,
802 GdkEventExpose *event)
804 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
805 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
810 border_width = GTK_CONTAINER (widget)->border_width;
812 if (GTK_WIDGET_DRAWABLE (widget))
814 gtk_paint_box (widget->style,
816 GTK_WIDGET_STATE (widget),
817 get_shadow_type (toolbar),
818 &event->area, widget, "toolbar",
819 border_width + widget->allocation.x,
820 border_width + widget->allocation.y,
821 widget->allocation.width - 2 * border_width,
822 widget->allocation.height - 2 * border_width);
825 for (list = priv->content; list != NULL; list = list->next)
827 ToolbarContent *content = list->data;
829 toolbar_content_expose (content, GTK_CONTAINER (widget), event);
832 gtk_container_propagate_expose (GTK_CONTAINER (widget),
840 gtk_toolbar_size_request (GtkWidget *widget,
841 GtkRequisition *requisition)
843 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
844 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
846 gint max_child_height;
847 gint max_child_width;
848 gint max_homogeneous_child_width;
849 gint max_homogeneous_child_height;
850 gint homogeneous_size;
852 gint pack_front_size;
854 GtkRequisition arrow_requisition;
856 max_homogeneous_child_width = 0;
857 max_homogeneous_child_height = 0;
859 max_child_height = 0;
860 for (list = priv->content; list != NULL; list = list->next)
862 GtkRequisition requisition;
863 ToolbarContent *content = list->data;
865 if (!toolbar_content_visible (content, toolbar))
868 toolbar_content_size_request (content, toolbar, &requisition);
870 max_child_width = MAX (max_child_width, requisition.width);
871 max_child_height = MAX (max_child_height, requisition.height);
873 if (toolbar_content_is_homogeneous (content, toolbar))
875 max_homogeneous_child_width = MAX (max_homogeneous_child_width, requisition.width);
876 max_homogeneous_child_height = MAX (max_homogeneous_child_height, requisition.height);
880 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
881 homogeneous_size = max_homogeneous_child_width;
883 homogeneous_size = max_homogeneous_child_height;
886 for (list = priv->content; list != NULL; list = list->next)
888 ToolbarContent *content = list->data;
891 if (!toolbar_content_visible (content, toolbar))
894 if (toolbar_content_is_homogeneous (content, toolbar))
896 size = homogeneous_size;
900 GtkRequisition requisition;
902 toolbar_content_size_request (content, toolbar, &requisition);
904 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
905 size = requisition.width;
907 size = requisition.height;
910 pack_front_size += size;
913 if (priv->show_arrow && priv->api_mode == NEW_API)
915 gtk_widget_size_request (priv->arrow_button, &arrow_requisition);
917 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
918 long_req = arrow_requisition.width;
920 long_req = arrow_requisition.height;
922 /* There is no point requesting space for the arrow if that would take
923 * up more space than all the items combined
925 long_req = MIN (long_req, pack_front_size);
929 arrow_requisition.height = 0;
930 arrow_requisition.width = 0;
932 long_req = pack_front_size;
935 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
937 requisition->width = long_req;
938 requisition->height = MAX (max_child_height, arrow_requisition.height);
942 requisition->height = long_req;
943 requisition->width = MAX (max_child_width, arrow_requisition.width);
947 ipadding = get_internal_padding (toolbar);
949 requisition->width += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width);
950 requisition->height += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width);
952 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
954 requisition->width += 2 * widget->style->xthickness;
955 requisition->height += 2 * widget->style->ythickness;
958 toolbar->button_maxw = max_homogeneous_child_width;
959 toolbar->button_maxh = max_homogeneous_child_height;
963 position (gint from, gint to, gdouble elapsed)
967 if (elapsed <= ACCEL_THRESHOLD)
969 n_pixels = SLIDE_SPEED * elapsed;
973 /* The formula is a second degree polynomial in
974 * @elapsed that has the line SLIDE_SPEED * @elapsed
975 * as tangent for @elapsed == ACCEL_THRESHOLD.
976 * This makes @n_pixels a smooth function of elapsed time.
978 n_pixels = (SLIDE_SPEED / ACCEL_THRESHOLD) * elapsed * elapsed -
979 SLIDE_SPEED * elapsed + SLIDE_SPEED * ACCEL_THRESHOLD;
983 return MIN (from + n_pixels, to);
985 return MAX (from - n_pixels, to);
989 compute_intermediate_allocation (GtkToolbar *toolbar,
990 const GtkAllocation *start,
991 const GtkAllocation *goal,
992 GtkAllocation *intermediate)
994 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
995 gdouble elapsed = g_timer_elapsed (priv->timer, NULL);
997 intermediate->x = position (start->x, goal->x, elapsed);
998 intermediate->y = position (start->y, goal->y, elapsed);
999 intermediate->width =
1000 position (start->x + start->width, goal->x + goal->width, elapsed) - intermediate->x;
1001 intermediate->height =
1002 position (start->y + start->height, goal->y + goal->height, elapsed) - intermediate->y;
1006 fixup_allocation_for_rtl (gint total_size,
1007 GtkAllocation *allocation)
1009 allocation->x += (total_size - (2 * allocation->x + allocation->width));
1013 fixup_allocation_for_vertical (GtkAllocation *allocation)
1017 tmp = allocation->x;
1018 allocation->x = allocation->y;
1019 allocation->y = tmp;
1021 tmp = allocation->width;
1022 allocation->width = allocation->height;
1023 allocation->height = tmp;
1027 get_item_size (GtkToolbar *toolbar,
1028 ToolbarContent *content)
1030 GtkRequisition requisition;
1032 toolbar_content_size_request (content, toolbar, &requisition);
1034 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1036 if (toolbar_content_is_homogeneous (content, toolbar))
1037 return toolbar->button_maxw;
1039 return requisition.width;
1043 if (toolbar_content_is_homogeneous (content, toolbar))
1044 return toolbar->button_maxh;
1046 return requisition.height;
1051 slide_idle_handler (gpointer data)
1053 GtkToolbar *toolbar = data;
1054 GtkToolbarPrivate *priv;
1057 GDK_THREADS_ENTER ();
1059 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;
1071 GtkAllocation goal_allocation;
1072 GtkAllocation allocation;
1075 state = toolbar_content_get_state (content);
1076 toolbar_content_get_goal_allocation (content, &goal_allocation);
1077 toolbar_content_get_allocation (content, &allocation);
1081 if (state == NOT_ALLOCATED)
1083 /* an unallocated item means that size allocate has to
1084 * called at least once more
1089 /* An invisible item with a goal allocation of
1090 * 0 is already at its goal.
1092 if ((state == NORMAL || state == OVERFLOWN) &&
1093 ((goal_allocation.width != 0 &&
1094 goal_allocation.height != 0) ||
1095 toolbar_content_child_visible (content)))
1097 if ((goal_allocation.x != allocation.x ||
1098 goal_allocation.y != allocation.y ||
1099 goal_allocation.width != allocation.width ||
1100 goal_allocation.height != allocation.height))
1102 /* An item is not in its right position yet. Note
1103 * that OVERFLOWN items do get an allocation in
1104 * gtk_toolbar_size_allocate(). This way you can see
1105 * them slide back in when you drag an item off the
1112 if (toolbar_content_is_placeholder (content) &&
1113 toolbar_content_disappearing (content) &&
1114 toolbar_content_child_visible (content))
1116 /* A disappearing placeholder is still visible.
1124 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1126 GDK_THREADS_LEAVE ();
1131 priv->is_sliding = FALSE;
1134 GDK_THREADS_LEAVE();
1139 rect_within (GtkAllocation *a1,
1142 return (a1->x >= a2->x &&
1143 a1->x + a1->width <= a2->x + a2->width &&
1145 a1->y + a1->height <= a2->y + a2->height);
1149 gtk_toolbar_begin_sliding (GtkToolbar *toolbar)
1151 GtkWidget *widget = GTK_WIDGET (toolbar);
1152 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1160 /* Start the sliding. This function copies the allocation of every
1161 * item into content->start_allocation. For items that haven't
1162 * been allocated yet, we calculate their position and save that
1163 * in start_allocatino along with zero width and zero height.
1165 * FIXME: It would be nice if we could share this code with
1166 * the equivalent in gtk_widget_size_allocate().
1168 priv->is_sliding = TRUE;
1171 priv->idle_id = g_idle_add (slide_idle_handler, toolbar);
1173 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1174 vertical = (toolbar->orientation == GTK_ORIENTATION_VERTICAL);
1175 border_width = get_internal_padding (toolbar) + GTK_CONTAINER (toolbar)->border_width;
1179 cur_x = widget->allocation.width - border_width - widget->style->xthickness;
1180 cur_y = widget->allocation.height - border_width - widget->style->ythickness;
1184 cur_x = border_width + widget->style->xthickness;
1185 cur_y = border_width + widget->style->ythickness;
1188 cur_x += widget->allocation.x;
1189 cur_y += widget->allocation.y;
1191 for (list = priv->content; list != NULL; list = list->next)
1193 ToolbarContent *content = list->data;
1194 GtkAllocation new_start_allocation;
1195 GtkAllocation item_allocation;
1198 state = toolbar_content_get_state (content);
1199 toolbar_content_get_allocation (content, &item_allocation);
1201 if ((state == NORMAL &&
1202 rect_within (&item_allocation, &(widget->allocation))) ||
1205 new_start_allocation = item_allocation;
1209 new_start_allocation.x = cur_x;
1210 new_start_allocation.y = cur_y;
1214 new_start_allocation.width = widget->allocation.width -
1215 2 * border_width - 2 * widget->style->xthickness;
1216 new_start_allocation.height = 0;
1220 new_start_allocation.width = 0;
1221 new_start_allocation.height = widget->allocation.height -
1222 2 * border_width - 2 * widget->style->ythickness;
1227 cur_y = new_start_allocation.y + new_start_allocation.height;
1229 cur_x = new_start_allocation.x;
1231 cur_x = new_start_allocation.x + new_start_allocation.width;
1233 toolbar_content_set_start_allocation (content, &new_start_allocation);
1236 /* This resize will run before the first idle handler. This
1237 * will make sure that items get the right goal allocation
1238 * so that the idle handler will not immediately return
1241 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1242 g_timer_reset (priv->timer);
1246 gtk_toolbar_stop_sliding (GtkToolbar *toolbar)
1248 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1250 if (priv->is_sliding)
1254 priv->is_sliding = FALSE;
1258 g_source_remove (priv->idle_id);
1262 list = priv->content;
1265 ToolbarContent *content = list->data;
1268 if (toolbar_content_is_placeholder (content))
1270 toolbar_content_remove (content, toolbar);
1271 toolbar_content_free (content);
1275 gtk_widget_queue_resize_no_redraw (GTK_WIDGET (toolbar));
1280 remove_item (GtkWidget *menu_item,
1283 gtk_container_remove (GTK_CONTAINER (menu_item->parent), menu_item);
1287 menu_deactivated (GtkWidget *menu,
1288 GtkToolbar *toolbar)
1290 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1291 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->arrow_button), FALSE);
1295 menu_detached (GtkWidget *toolbar,
1298 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1303 rebuild_menu (GtkToolbar *toolbar)
1305 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1306 GList *list, *children;
1310 priv->menu = GTK_MENU (gtk_menu_new());
1311 gtk_menu_attach_to_widget (priv->menu,
1312 GTK_WIDGET (toolbar),
1315 g_signal_connect (priv->menu, "deactivate", G_CALLBACK (menu_deactivated), toolbar);
1318 gtk_container_foreach (GTK_CONTAINER (priv->menu), remove_item, NULL);
1320 for (list = priv->content; list != NULL; list = list->next)
1322 ToolbarContent *content = list->data;
1324 if (toolbar_content_get_state (content) == OVERFLOWN &&
1325 !toolbar_content_is_placeholder (content))
1327 GtkWidget *menu_item = toolbar_content_retrieve_menu_item (content);
1331 g_assert (GTK_IS_MENU_ITEM (menu_item));
1332 gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_item);
1337 /* Remove leading and trailing separator items */
1338 children = gtk_container_get_children (GTK_CONTAINER (priv->menu));
1341 while (list && GTK_IS_SEPARATOR_MENU_ITEM (list->data))
1343 GtkWidget *child = list->data;
1345 gtk_container_remove (GTK_CONTAINER (priv->menu), child);
1348 g_list_free (children);
1350 /* Regenerate the list of children so we don't try to remove items twice */
1351 children = gtk_container_get_children (GTK_CONTAINER (priv->menu));
1353 list = g_list_last (children);
1354 while (list && GTK_IS_SEPARATOR_MENU_ITEM (list->data))
1356 GtkWidget *child = list->data;
1358 gtk_container_remove (GTK_CONTAINER (priv->menu), child);
1361 g_list_free (children);
1363 priv->need_rebuild = FALSE;
1367 gtk_toolbar_size_allocate (GtkWidget *widget,
1368 GtkAllocation *allocation)
1370 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1371 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1372 GtkAllocation *allocations;
1373 ItemState *new_states;
1374 GtkAllocation arrow_allocation;
1376 gint size, pos, short_size;
1379 gboolean need_arrow;
1380 gint n_expand_items;
1382 gint available_size;
1385 GtkRequisition arrow_requisition;
1386 gboolean overflowing;
1387 gboolean size_changed;
1389 GtkAllocation item_area;
1391 size_changed = FALSE;
1392 if (widget->allocation.x != allocation->x ||
1393 widget->allocation.y != allocation->y ||
1394 widget->allocation.width != allocation->width ||
1395 widget->allocation.height != allocation->height)
1397 size_changed = TRUE;
1401 gtk_toolbar_stop_sliding (toolbar);
1403 widget->allocation = *allocation;
1405 border_width = GTK_CONTAINER (toolbar)->border_width;
1407 if (GTK_WIDGET_REALIZED (widget))
1409 gdk_window_move_resize (priv->event_window,
1410 allocation->x + border_width,
1411 allocation->y + border_width,
1412 allocation->width - border_width * 2,
1413 allocation->height - border_width * 2);
1416 border_width += get_internal_padding (toolbar);
1418 gtk_widget_get_child_requisition (GTK_WIDGET (priv->arrow_button),
1419 &arrow_requisition);
1421 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
1423 available_size = size = allocation->width - 2 * border_width;
1424 short_size = allocation->height - 2 * border_width;
1425 arrow_size = arrow_requisition.width;
1427 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1429 available_size -= 2 * widget->style->xthickness;
1430 short_size -= 2 * widget->style->ythickness;
1435 available_size = size = allocation->height - 2 * border_width;
1436 short_size = allocation->width - 2 * border_width;
1437 arrow_size = arrow_requisition.height;
1439 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1441 available_size -= 2 * widget->style->ythickness;
1442 short_size -= 2 * widget->style->xthickness;
1446 n_items = g_list_length (priv->content);
1447 allocations = g_new0 (GtkAllocation, n_items);
1448 new_states = g_new0 (ItemState, n_items);
1452 for (list = priv->content; list != NULL; list = list->next)
1454 ToolbarContent *content = list->data;
1456 if (toolbar_content_visible (content, toolbar))
1458 needed_size += get_item_size (toolbar, content);
1460 /* Do we need an arrow?
1462 * Assume we don't, and see if any non-separator item with a
1463 * proxy menu item is then going to overflow.
1465 if (needed_size > available_size &&
1468 priv->api_mode == NEW_API &&
1469 toolbar_content_has_proxy_menu_item (content) &&
1470 !toolbar_content_is_separator (content))
1478 size = available_size - arrow_size;
1480 size = available_size;
1482 /* calculate widths and states of items */
1483 overflowing = FALSE;
1484 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1486 ToolbarContent *content = list->data;
1489 if (!toolbar_content_visible (content, toolbar))
1491 new_states[i] = HIDDEN;
1495 item_size = get_item_size (toolbar, content);
1496 if (item_size <= size && !overflowing)
1499 allocations[i].width = item_size;
1500 new_states[i] = NORMAL;
1505 new_states[i] = OVERFLOWN;
1506 allocations[i].width = item_size;
1510 /* calculate width of arrow */
1513 arrow_allocation.width = arrow_size;
1514 arrow_allocation.height = MAX (short_size, 1);
1517 /* expand expandable items */
1519 /* We don't expand when there is an overflow menu, because that leads to
1520 * weird jumps when items get moved to the overflow menu and the expanding
1521 * items suddenly get a lot of extra space
1526 for (i = 0, list = priv->content; list != NULL; list = list->next, ++i)
1528 ToolbarContent *content = list->data;
1530 if (toolbar_content_get_expand (content) && new_states[i] == NORMAL)
1534 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1536 ToolbarContent *content = list->data;
1538 if (toolbar_content_get_expand (content) && new_states[i] == NORMAL)
1540 gint extra = size / n_expand_items;
1541 if (size % n_expand_items != 0)
1544 allocations[i].width += extra;
1550 g_assert (n_expand_items == 0);
1553 /* position items */
1555 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1557 /* both NORMAL and OVERFLOWN items get a position. This ensures
1558 * that sliding will work for OVERFLOWN items too
1560 if (new_states[i] == NORMAL ||
1561 new_states[i] == OVERFLOWN)
1563 allocations[i].x = pos;
1564 allocations[i].y = border_width;
1565 allocations[i].height = short_size;
1567 pos += allocations[i].width;
1571 /* position arrow */
1574 arrow_allocation.x = available_size - border_width - arrow_allocation.width;
1575 arrow_allocation.y = border_width;
1578 item_area.x = border_width;
1579 item_area.y = border_width;
1580 item_area.width = available_size - (need_arrow? arrow_size : 0);
1581 item_area.height = short_size;
1583 /* fix up allocations in the vertical or RTL cases */
1584 if (toolbar->orientation == GTK_ORIENTATION_VERTICAL)
1586 for (i = 0; i < n_items; ++i)
1587 fixup_allocation_for_vertical (&(allocations[i]));
1590 fixup_allocation_for_vertical (&arrow_allocation);
1592 fixup_allocation_for_vertical (&item_area);
1594 else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1596 for (i = 0; i < n_items; ++i)
1597 fixup_allocation_for_rtl (available_size, &(allocations[i]));
1600 fixup_allocation_for_rtl (available_size, &arrow_allocation);
1602 fixup_allocation_for_rtl (available_size, &item_area);
1605 /* translate the items by allocation->(x,y) */
1606 for (i = 0; i < n_items; ++i)
1608 allocations[i].x += allocation->x;
1609 allocations[i].y += allocation->y;
1611 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1613 allocations[i].x += widget->style->xthickness;
1614 allocations[i].y += widget->style->ythickness;
1620 arrow_allocation.x += allocation->x;
1621 arrow_allocation.y += allocation->y;
1623 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1625 arrow_allocation.x += widget->style->xthickness;
1626 arrow_allocation.y += widget->style->ythickness;
1630 item_area.x += allocation->x;
1631 item_area.y += allocation->y;
1632 if (get_shadow_type (toolbar) != GTK_SHADOW_NONE)
1634 item_area.x += widget->style->xthickness;
1635 item_area.y += widget->style->ythickness;
1638 /* did anything change? */
1639 for (list = priv->content, i = 0; list != NULL; list = list->next, i++)
1641 ToolbarContent *content = list->data;
1643 if (toolbar_content_get_state (content) == NORMAL &&
1644 new_states[i] != NORMAL)
1646 /* an item disappeared and we didn't change size, so begin sliding */
1647 if (!size_changed && priv->api_mode == NEW_API)
1648 gtk_toolbar_begin_sliding (toolbar);
1652 /* finally allocate the items */
1653 if (priv->is_sliding)
1655 for (list = priv->content, i = 0; list != NULL; list = list->next, i++)
1657 ToolbarContent *content = list->data;
1659 toolbar_content_set_goal_allocation (content, &(allocations[i]));
1663 elapsed = g_timer_elapsed (priv->timer, NULL);
1664 for (list = priv->content, i = 0; list != NULL; list = list->next, ++i)
1666 ToolbarContent *content = list->data;
1668 if (new_states[i] == OVERFLOWN ||
1669 new_states[i] == NORMAL)
1671 GtkAllocation alloc;
1672 GtkAllocation start_allocation;
1673 GtkAllocation goal_allocation;
1675 if (priv->is_sliding)
1677 toolbar_content_get_start_allocation (content, &start_allocation);
1678 toolbar_content_get_goal_allocation (content, &goal_allocation);
1680 compute_intermediate_allocation (toolbar,
1685 priv->need_sync = TRUE;
1689 alloc = allocations[i];
1692 if (alloc.width <= 0 || alloc.height <= 0)
1694 toolbar_content_set_child_visible (content, toolbar, FALSE);
1698 if (!rect_within (&alloc, &item_area))
1700 toolbar_content_set_child_visible (content, toolbar, FALSE);
1701 toolbar_content_size_allocate (content, &alloc);
1705 toolbar_content_set_child_visible (content, toolbar, TRUE);
1706 toolbar_content_size_allocate (content, &alloc);
1712 toolbar_content_set_child_visible (content, toolbar, FALSE);
1715 toolbar_content_set_state (content, new_states[i]);
1718 if (priv->menu && priv->need_rebuild)
1719 rebuild_menu (toolbar);
1723 gtk_widget_size_allocate (GTK_WIDGET (priv->arrow_button),
1725 gtk_widget_show (GTK_WIDGET (priv->arrow_button));
1729 gtk_widget_hide (GTK_WIDGET (priv->arrow_button));
1731 if (priv->menu && GTK_WIDGET_VISIBLE (priv->menu))
1732 gtk_menu_shell_deactivate (GTK_MENU_SHELL (priv->menu));
1735 g_free (allocations);
1736 g_free (new_states);
1740 gtk_toolbar_update_button_relief (GtkToolbar *toolbar)
1742 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1744 gtk_toolbar_reconfigured (toolbar);
1746 gtk_button_set_relief (GTK_BUTTON (priv->arrow_button), get_button_relief (toolbar));
1750 gtk_toolbar_style_set (GtkWidget *widget,
1751 GtkStyle *prev_style)
1753 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
1755 priv->max_homogeneous_pixels = -1;
1757 if (GTK_WIDGET_REALIZED (widget))
1758 gtk_style_set_background (widget->style, widget->window, widget->state);
1761 gtk_toolbar_update_button_relief (GTK_TOOLBAR (widget));
1765 gtk_toolbar_list_children_in_focus_order (GtkToolbar *toolbar,
1766 GtkDirectionType dir)
1768 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1769 GList *result = NULL;
1773 /* generate list of children in reverse logical order */
1775 for (list = priv->content; list != NULL; list = list->next)
1777 ToolbarContent *content = list->data;
1780 widget = toolbar_content_get_widget (content);
1783 result = g_list_prepend (result, widget);
1786 result = g_list_prepend (result, priv->arrow_button);
1788 rtl = (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL);
1790 /* move in logical order when
1792 * - dir is TAB_FORWARD
1794 * - in RTL mode and moving left or up
1796 * - in LTR mode and moving right or down
1798 if (dir == GTK_DIR_TAB_FORWARD ||
1799 (rtl && (dir == GTK_DIR_UP || dir == GTK_DIR_LEFT)) ||
1800 (!rtl && (dir == GTK_DIR_DOWN || dir == GTK_DIR_RIGHT)))
1802 result = g_list_reverse (result);
1809 gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
1810 gboolean focus_home)
1812 GList *children, *list;
1813 GtkDirectionType dir = focus_home? GTK_DIR_RIGHT : GTK_DIR_LEFT;
1815 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1817 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL)
1819 children = g_list_reverse (children);
1821 dir = (dir == GTK_DIR_RIGHT)? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1824 for (list = children; list != NULL; list = list->next)
1826 GtkWidget *child = list->data;
1828 if (GTK_CONTAINER (toolbar)->focus_child == child)
1831 if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1835 g_list_free (children);
1840 /* Keybinding handler. This function is called when the user presses
1841 * Ctrl TAB or an arrow key.
1844 gtk_toolbar_move_focus (GtkToolbar *toolbar,
1845 GtkDirectionType dir)
1848 gboolean try_focus = FALSE;
1850 GtkContainer *container = GTK_CONTAINER (toolbar);
1852 if (container->focus_child &&
1853 gtk_widget_child_focus (container->focus_child, dir))
1858 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1860 for (list = children; list != NULL; list = list->next)
1862 GtkWidget *child = list->data;
1864 if (try_focus && GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1867 if (child == GTK_CONTAINER (toolbar)->focus_child)
1871 g_list_free (children);
1876 /* The focus handler for the toolbar. It called when the user presses
1877 * TAB or otherwise tries to focus the toolbar.
1880 gtk_toolbar_focus (GtkWidget *widget,
1881 GtkDirectionType dir)
1883 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1884 GList *children, *list;
1885 gboolean result = FALSE;
1887 /* if focus is already somewhere inside the toolbar then return FALSE.
1888 * The only way focus can stay inside the toolbar is when the user presses
1889 * arrow keys or Ctrl TAB (both of which are handled by the
1890 * gtk_toolbar_move_focus() keybinding function.
1892 if (GTK_CONTAINER (widget)->focus_child)
1895 children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
1897 for (list = children; list != NULL; list = list->next)
1899 GtkWidget *child = list->data;
1901 if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir))
1908 g_list_free (children);
1914 style_change_notify (GtkToolbar *toolbar)
1916 if (!toolbar->style_set)
1918 /* pretend it was set, then unset, thus reverting to new default */
1919 toolbar->style_set = TRUE;
1920 gtk_toolbar_unset_style (toolbar);
1925 icon_size_change_notify (GtkToolbar *toolbar)
1927 if (!toolbar->icon_size_set)
1929 /* pretend it was set, then unset, thus reverting to new default */
1930 toolbar->icon_size_set = TRUE;
1931 gtk_toolbar_unset_icon_size (toolbar);
1935 static GtkSettings *
1936 toolbar_get_settings (GtkToolbar *toolbar)
1938 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1939 return priv->settings;
1943 gtk_toolbar_screen_changed (GtkWidget *widget,
1944 GdkScreen *previous_screen)
1946 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
1947 GtkToolbar *toolbar = GTK_TOOLBAR (widget);
1948 GtkSettings *old_settings = toolbar_get_settings (toolbar);
1949 GtkSettings *settings;
1951 if (gtk_widget_has_screen (GTK_WIDGET (toolbar)))
1952 settings = gtk_widget_get_settings (GTK_WIDGET (toolbar));
1956 if (settings == old_settings)
1961 g_signal_handler_disconnect (old_settings, toolbar->style_set_connection);
1962 g_signal_handler_disconnect (old_settings, toolbar->icon_size_connection);
1964 g_object_unref (old_settings);
1969 toolbar->style_set_connection =
1970 g_signal_connect_swapped (settings,
1971 "notify::gtk-toolbar-style",
1972 G_CALLBACK (style_change_notify),
1974 toolbar->icon_size_connection =
1975 g_signal_connect_swapped (settings,
1976 "notify::gtk-toolbar-icon-size",
1977 G_CALLBACK (icon_size_change_notify),
1980 g_object_ref (settings);
1981 priv->settings = settings;
1984 priv->settings = NULL;
1986 style_change_notify (toolbar);
1987 icon_size_change_notify (toolbar);
1991 find_drop_index (GtkToolbar *toolbar,
1995 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
1996 GList *interesting_content;
1998 GtkOrientation orientation;
1999 GtkTextDirection direction;
2000 gint best_distance = G_MAXINT;
2004 ToolbarContent *best_content;
2005 GtkAllocation allocation;
2007 /* list items we care about wrt. drag and drop */
2008 interesting_content = NULL;
2009 for (list = priv->content; list != NULL; list = list->next)
2011 ToolbarContent *content = list->data;
2013 if (toolbar_content_get_state (content) == NORMAL)
2014 interesting_content = g_list_prepend (interesting_content, content);
2016 interesting_content = g_list_reverse (interesting_content);
2018 if (!interesting_content)
2021 orientation = toolbar->orientation;
2022 direction = gtk_widget_get_direction (GTK_WIDGET (toolbar));
2024 /* distance to first interesting item */
2025 best_content = interesting_content->data;
2026 toolbar_content_get_allocation (best_content, &allocation);
2028 if (orientation == GTK_ORIENTATION_HORIZONTAL)
2032 if (direction == GTK_TEXT_DIR_LTR)
2035 pos = allocation.x + allocation.width;
2043 best_content = NULL;
2044 best_distance = ABS (pos - cursor);
2046 /* distance to far end of each item */
2047 for (list = interesting_content; list != NULL; list = list->next)
2049 ToolbarContent *content = list->data;
2051 toolbar_content_get_allocation (content, &allocation);
2053 if (orientation == GTK_ORIENTATION_HORIZONTAL)
2055 if (direction == GTK_TEXT_DIR_LTR)
2056 pos = allocation.x + allocation.width;
2062 pos = allocation.y + allocation.height;
2065 distance = ABS (pos - cursor);
2067 if (distance < best_distance)
2069 best_distance = distance;
2070 best_content = content;
2074 g_list_free (interesting_content);
2079 return g_list_index (priv->content, best_content) + 1;
2083 reset_all_placeholders (GtkToolbar *toolbar)
2085 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2088 for (list = priv->content; list != NULL; list = list->next)
2090 ToolbarContent *content = list->data;
2091 if (toolbar_content_is_placeholder (content))
2092 toolbar_content_set_disappearing (content, TRUE);
2097 physical_to_logical (GtkToolbar *toolbar,
2100 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2104 g_assert (physical >= 0);
2107 for (list = priv->content; list && physical > 0; list = list->next)
2109 ToolbarContent *content = list->data;
2111 if (!toolbar_content_is_placeholder (content))
2116 g_assert (physical == 0);
2122 logical_to_physical (GtkToolbar *toolbar,
2125 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2129 g_assert (logical >= 0);
2132 for (list = priv->content; list; list = list->next)
2134 ToolbarContent *content = list->data;
2136 if (!toolbar_content_is_placeholder (content))
2146 g_assert (logical == 0);
2152 * gtk_toolbar_set_drop_highlight_item:
2153 * @toolbar: a #GtkToolbar
2154 * @tool_item: a #GtkToolItem, or %NULL to turn of highlighting
2155 * @index_: a position on @toolbar
2157 * Highlights @toolbar to give an idea of what it would look like
2158 * if @item was added to @toolbar at the position indicated by @index_.
2159 * If @item is %NULL, highlighting is turned off. In that case @index_
2162 * The @tool_item passed to this function must not be part of any widget
2163 * hierarchy. When an item is set as drop highlight item it can not
2164 * added to any widget hierarchy or used as highlight item for another
2170 gtk_toolbar_set_drop_highlight_item (GtkToolbar *toolbar,
2171 GtkToolItem *tool_item,
2174 ToolbarContent *content;
2175 GtkToolbarPrivate *priv;
2177 GtkRequisition requisition;
2178 GtkRequisition old_requisition;
2179 gboolean restart_sliding;
2181 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2182 g_return_if_fail (tool_item == NULL || GTK_IS_TOOL_ITEM (tool_item));
2184 gtk_toolbar_check_new_api (toolbar);
2186 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2190 if (priv->highlight_tool_item)
2192 gtk_widget_unparent (GTK_WIDGET (priv->highlight_tool_item));
2193 g_object_unref (priv->highlight_tool_item);
2194 priv->highlight_tool_item = NULL;
2197 reset_all_placeholders (toolbar);
2198 gtk_toolbar_begin_sliding (toolbar);
2202 n_items = gtk_toolbar_get_n_items (toolbar);
2203 if (index_ < 0 || index_ > n_items)
2206 if (tool_item != priv->highlight_tool_item)
2208 if (priv->highlight_tool_item)
2209 g_object_unref (priv->highlight_tool_item);
2211 g_object_ref (tool_item);
2212 gtk_object_sink (GTK_OBJECT (tool_item));
2214 priv->highlight_tool_item = tool_item;
2216 gtk_widget_set_parent (GTK_WIDGET (priv->highlight_tool_item),
2217 GTK_WIDGET (toolbar));
2220 index_ = logical_to_physical (toolbar, index_);
2222 content = g_list_nth_data (priv->content, index_);
2226 ToolbarContent *prev_content;
2228 prev_content = g_list_nth_data (priv->content, index_ - 1);
2230 if (prev_content && toolbar_content_is_placeholder (prev_content))
2231 content = prev_content;
2234 if (!content || !toolbar_content_is_placeholder (content))
2236 GtkWidget *placeholder;
2238 placeholder = GTK_WIDGET (gtk_separator_tool_item_new ());
2240 content = toolbar_content_new_tool_item (toolbar,
2241 GTK_TOOL_ITEM (placeholder),
2243 gtk_widget_show (placeholder);
2247 g_assert (toolbar_content_is_placeholder (content));
2249 gtk_widget_size_request (GTK_WIDGET (priv->highlight_tool_item),
2252 toolbar_content_set_expand (content, gtk_tool_item_get_expand (tool_item));
2254 restart_sliding = FALSE;
2255 toolbar_content_size_request (content, toolbar, &old_requisition);
2256 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
2258 requisition.height = -1;
2259 if (requisition.width != old_requisition.width)
2260 restart_sliding = TRUE;
2264 requisition.width = -1;
2265 if (requisition.height != old_requisition.height)
2266 restart_sliding = TRUE;
2269 if (toolbar_content_disappearing (content))
2270 restart_sliding = TRUE;
2272 reset_all_placeholders (toolbar);
2273 toolbar_content_set_disappearing (content, FALSE);
2275 toolbar_content_set_size_request (content,
2276 requisition.width, requisition.height);
2278 if (restart_sliding)
2279 gtk_toolbar_begin_sliding (toolbar);
2283 gtk_toolbar_get_child_property (GtkContainer *container,
2289 GtkToolItem *item = GTK_TOOL_ITEM (child);
2291 switch (property_id)
2293 case CHILD_PROP_HOMOGENEOUS:
2294 g_value_set_boolean (value, gtk_tool_item_get_homogeneous (item));
2297 case CHILD_PROP_EXPAND:
2298 g_value_set_boolean (value, gtk_tool_item_get_expand (item));
2302 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2308 gtk_toolbar_set_child_property (GtkContainer *container,
2311 const GValue *value,
2314 switch (property_id)
2316 case CHILD_PROP_HOMOGENEOUS:
2317 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
2320 case CHILD_PROP_EXPAND:
2321 gtk_tool_item_set_expand (GTK_TOOL_ITEM (child), g_value_get_boolean (value));
2325 GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
2331 gtk_toolbar_show_all (GtkWidget *widget)
2333 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
2336 for (list = priv->content; list != NULL; list = list->next)
2338 ToolbarContent *content = list->data;
2340 toolbar_content_show_all (content);
2343 gtk_widget_show (widget);
2347 gtk_toolbar_hide_all (GtkWidget *widget)
2349 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget);
2352 for (list = priv->content; list != NULL; list = list->next)
2354 ToolbarContent *content = list->data;
2356 toolbar_content_hide_all (content);
2359 gtk_widget_hide (widget);
2363 gtk_toolbar_add (GtkContainer *container,
2366 GtkToolbar *toolbar;
2368 g_return_if_fail (GTK_IS_TOOLBAR (container));
2369 g_return_if_fail (widget != NULL);
2371 toolbar = GTK_TOOLBAR (container);
2373 if (GTK_IS_TOOL_ITEM (widget))
2374 gtk_toolbar_insert (toolbar, GTK_TOOL_ITEM (widget), -1);
2376 gtk_toolbar_append_widget (toolbar, widget, NULL, NULL);
2380 gtk_toolbar_remove (GtkContainer *container,
2383 GtkToolbar *toolbar;
2384 GtkToolbarPrivate *priv;
2385 ToolbarContent *content_to_remove;
2388 g_return_if_fail (GTK_IS_TOOLBAR (container));
2389 g_return_if_fail (GTK_IS_WIDGET (widget));
2391 toolbar = GTK_TOOLBAR (container);
2392 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2394 content_to_remove = NULL;
2395 for (list = priv->content; list != NULL; list = list->next)
2397 ToolbarContent *content = list->data;
2400 child = toolbar_content_get_widget (content);
2401 if (child && child == widget)
2403 content_to_remove = content;
2408 g_return_if_fail (content_to_remove != NULL);
2410 toolbar_content_remove (content_to_remove, toolbar);
2411 toolbar_content_free (content_to_remove);
2415 gtk_toolbar_forall (GtkContainer *container,
2416 gboolean include_internals,
2417 GtkCallback callback,
2418 gpointer callback_data)
2420 GtkToolbar *toolbar = GTK_TOOLBAR (container);
2421 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2424 g_return_if_fail (callback != NULL);
2426 list = priv->content;
2429 ToolbarContent *content = list->data;
2430 GList *next = list->next;
2432 if (include_internals || !toolbar_content_is_placeholder (content))
2434 GtkWidget *child = toolbar_content_get_widget (content);
2437 (*callback) (child, callback_data);
2443 if (include_internals)
2444 (* callback) (priv->arrow_button, callback_data);
2448 gtk_toolbar_child_type (GtkContainer *container)
2450 return GTK_TYPE_TOOL_ITEM;
2454 gtk_toolbar_reconfigured (GtkToolbar *toolbar)
2456 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2459 list = priv->content;
2462 ToolbarContent *content = list->data;
2463 GList *next = list->next;
2465 toolbar_content_toolbar_reconfigured (content, toolbar);
2472 gtk_toolbar_orientation_changed (GtkToolbar *toolbar,
2473 GtkOrientation orientation)
2475 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2476 if (toolbar->orientation != orientation)
2478 toolbar->orientation = orientation;
2480 if (orientation == GTK_ORIENTATION_HORIZONTAL)
2481 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_DOWN, GTK_SHADOW_NONE);
2483 gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
2485 gtk_toolbar_reconfigured (toolbar);
2487 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2488 g_object_notify (G_OBJECT (toolbar), "orientation");
2493 gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
2494 GtkToolbarStyle style)
2496 if (toolbar->style != style)
2498 toolbar->style = style;
2500 gtk_toolbar_reconfigured (toolbar);
2502 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2503 g_object_notify (G_OBJECT (toolbar), "toolbar_style");
2508 menu_position_func (GtkMenu *menu,
2514 GtkToolbar *toolbar = GTK_TOOLBAR (user_data);
2515 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2517 GtkRequisition menu_req;
2519 gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y);
2520 gtk_widget_size_request (priv->arrow_button, &req);
2521 gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
2523 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
2525 *y += priv->arrow_button->allocation.height;
2526 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2527 *x += priv->arrow_button->allocation.width - req.width;
2529 *x += req.width - menu_req.width;
2533 if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR)
2534 *x += priv->arrow_button->allocation.width;
2536 *x -= menu_req.width;
2537 *y += priv->arrow_button->allocation.height - req.height;
2544 show_menu (GtkToolbar *toolbar,
2545 GdkEventButton *event)
2547 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2549 rebuild_menu (toolbar);
2551 gtk_widget_show_all (GTK_WIDGET (priv->menu));
2553 gtk_menu_popup (priv->menu, NULL, NULL,
2554 menu_position_func, toolbar,
2555 event? event->button : 0,
2556 event? event->time : gtk_get_current_event_time());
2560 gtk_toolbar_arrow_button_clicked (GtkWidget *button,
2561 GtkToolbar *toolbar)
2563 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2565 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->arrow_button)) &&
2566 (!priv->menu || !GTK_WIDGET_VISIBLE (priv->menu)))
2568 /* We only get here when the button is clicked with the keyboard,
2569 * because mouse button presses result in the menu being shown so
2570 * that priv->menu would be non-NULL and visible.
2572 show_menu (toolbar, NULL);
2573 gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menu), FALSE);
2578 gtk_toolbar_arrow_button_press (GtkWidget *button,
2579 GdkEventButton *event,
2580 GtkToolbar *toolbar)
2582 show_menu (toolbar, event);
2583 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2589 gtk_toolbar_button_press (GtkWidget *toolbar,
2590 GdkEventButton *event)
2592 if (event->button == 3)
2594 gboolean return_value;
2596 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2597 (int)event->x_root, (int)event->y_root, event->button,
2600 return return_value;
2607 gtk_toolbar_popup_menu (GtkWidget *toolbar)
2609 gboolean return_value;
2610 /* This function is the handler for the "popup menu" keybinding,
2611 * ie., it is called when the user presses Shift F10
2613 g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0,
2614 -1, -1, -1, &return_value);
2616 return return_value;
2622 * Creates a new toolbar.
2624 * Return Value: the newly-created toolbar.
2627 gtk_toolbar_new (void)
2629 GtkToolbar *toolbar;
2631 toolbar = g_object_new (GTK_TYPE_TOOLBAR, NULL);
2633 return GTK_WIDGET (toolbar);
2637 * gtk_toolbar_insert:
2638 * @toolbar: a #GtkToolbar
2639 * @item: a #GtkToolItem
2640 * @pos: the position of the new item
2642 * Insert a #GtkToolItem into the toolbar at position @pos. If @pos is
2643 * 0 the item is prepended to the start of the toolbar. If @pos is
2644 * negative, the item is appended to the end of the toolbar.
2649 gtk_toolbar_insert (GtkToolbar *toolbar,
2653 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2654 g_return_if_fail (GTK_IS_TOOL_ITEM (item));
2656 if (!gtk_toolbar_check_new_api (toolbar))
2660 pos = logical_to_physical (toolbar, pos);
2662 toolbar_content_new_tool_item (toolbar, item, FALSE, pos);
2666 * gtk_toolbar_get_item_index:
2667 * @toolbar: a #GtkToolbar
2668 * @item: a #GtkToolItem that is a child of @toolbar
2670 * Returns the position of @item on the toolbar, starting from 0.
2671 * It is an error if @item is not a child of the toolbar.
2673 * Return value: the position of item on the toolbar.
2678 gtk_toolbar_get_item_index (GtkToolbar *toolbar,
2681 GtkToolbarPrivate *priv;
2685 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2686 g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1);
2687 g_return_val_if_fail (GTK_WIDGET (item)->parent == GTK_WIDGET (toolbar), -1);
2689 if (!gtk_toolbar_check_new_api (toolbar))
2692 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2695 for (list = priv->content; list != NULL; list = list->next)
2697 ToolbarContent *content = list->data;
2700 widget = toolbar_content_get_widget (content);
2702 if (item == GTK_TOOL_ITEM (widget))
2708 return physical_to_logical (toolbar, n);
2712 * gtk_toolbar_set_orientation:
2713 * @toolbar: a #GtkToolbar.
2714 * @orientation: a new #GtkOrientation.
2716 * Sets whether a toolbar should appear horizontally or vertically.
2719 gtk_toolbar_set_orientation (GtkToolbar *toolbar,
2720 GtkOrientation orientation)
2722 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2724 g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0, orientation);
2728 * gtk_toolbar_get_orientation:
2729 * @toolbar: a #GtkToolbar
2731 * Retrieves the current orientation of the toolbar. See
2732 * gtk_toolbar_set_orientation().
2734 * Return value: the orientation
2737 gtk_toolbar_get_orientation (GtkToolbar *toolbar)
2739 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
2741 return toolbar->orientation;
2745 * gtk_toolbar_set_style:
2746 * @toolbar: a #GtkToolbar.
2747 * @style: the new style for @toolbar.
2749 * Alters the view of @toolbar to display either icons only, text only, or both.
2752 gtk_toolbar_set_style (GtkToolbar *toolbar,
2753 GtkToolbarStyle style)
2755 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2757 toolbar->style_set = TRUE;
2758 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2762 * gtk_toolbar_get_style:
2763 * @toolbar: a #GtkToolbar
2765 * Retrieves whether the toolbar has text, icons, or both . See
2766 * gtk_toolbar_set_style().
2768 * Return value: the current style of @toolbar
2771 gtk_toolbar_get_style (GtkToolbar *toolbar)
2773 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_TOOLBAR_STYLE);
2775 return toolbar->style;
2779 * gtk_toolbar_unset_style:
2780 * @toolbar: a #GtkToolbar
2782 * Unsets a toolbar style set with gtk_toolbar_set_style(), so that
2783 * user preferences will be used to determine the toolbar style.
2786 gtk_toolbar_unset_style (GtkToolbar *toolbar)
2788 GtkToolbarStyle style;
2790 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2792 if (toolbar->style_set)
2794 GtkSettings *settings = toolbar_get_settings (toolbar);
2797 g_object_get (settings,
2798 "gtk-toolbar-style", &style,
2801 style = DEFAULT_TOOLBAR_STYLE;
2803 if (style != toolbar->style)
2804 g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style);
2806 toolbar->style_set = FALSE;
2811 * gtk_toolbar_set_tooltips:
2812 * @toolbar: a #GtkToolbar.
2813 * @enable: set to %FALSE to disable the tooltips, or %TRUE to enable them.
2815 * Sets if the tooltips of a toolbar should be active or not.
2818 gtk_toolbar_set_tooltips (GtkToolbar *toolbar,
2821 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2824 gtk_tooltips_enable (toolbar->tooltips);
2826 gtk_tooltips_disable (toolbar->tooltips);
2830 * gtk_toolbar_get_tooltips:
2831 * @toolbar: a #GtkToolbar
2833 * Retrieves whether tooltips are enabled. See
2834 * gtk_toolbar_set_tooltips().
2836 * Return value: %TRUE if tooltips are enabled
2839 gtk_toolbar_get_tooltips (GtkToolbar *toolbar)
2841 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
2843 return toolbar->tooltips->enabled;
2847 * gtk_toolbar_get_n_items:
2848 * @toolbar: a #GtkToolbar
2850 * Returns the number of items on the toolbar.
2852 * Return value: the number of items on the toolbar
2857 gtk_toolbar_get_n_items (GtkToolbar *toolbar)
2859 GtkToolbarPrivate *priv;
2861 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
2863 if (!gtk_toolbar_check_new_api (toolbar))
2866 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2868 return physical_to_logical (toolbar, g_list_length (priv->content));
2872 * gtk_toolbar_get_nth_item:
2873 * @toolbar: a #GtkToolbar
2874 * @n: A position on the toolbar
2876 * Returns the @n<!-- -->'s item on @toolbar, or %NULL if the
2877 * toolbar does not contain an @n<!-- -->'th item.
2879 * Return value: The @n<!-- -->'th #GtkToolItem on @toolbar, or %NULL if there
2880 * isn't an @n<!-- -->th item.
2885 gtk_toolbar_get_nth_item (GtkToolbar *toolbar,
2888 GtkToolbarPrivate *priv;
2889 ToolbarContent *content;
2892 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
2894 if (!gtk_toolbar_check_new_api (toolbar))
2897 n_items = gtk_toolbar_get_n_items (toolbar);
2899 if (n < 0 || n >= n_items)
2902 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2904 content = g_list_nth_data (priv->content, logical_to_physical (toolbar, n));
2907 g_assert (!toolbar_content_is_placeholder (content));
2909 return GTK_TOOL_ITEM (toolbar_content_get_widget (content));
2913 * gtk_toolbar_get_icon_size:
2914 * @toolbar: a #GtkToolbar
2916 * Retrieves the icon size fo the toolbar. See gtk_toolbar_set_icon_size().
2918 * Return value: the current icon size for the icons on the toolbar.
2921 gtk_toolbar_get_icon_size (GtkToolbar *toolbar)
2923 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_ICON_SIZE);
2925 return toolbar->icon_size;
2929 * gtk_toolbar_get_relief_style:
2930 * @toolbar: a #GtkToolbar
2932 * Returns the relief style of buttons on @toolbar. See
2933 * gtk_button_set_relief().
2935 * Return value: The relief style of buttons on @toolbar.
2940 gtk_toolbar_get_relief_style (GtkToolbar *toolbar)
2942 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_RELIEF_NONE);
2944 return get_button_relief (toolbar);
2948 * gtk_toolbar_set_show_arrow:
2949 * @toolbar: a #GtkToolbar
2950 * @show_arrow: Whether to show an overflow menu
2952 * Sets whether to show an overflow menu when
2953 * @toolbar doesn't have room for all items on it. If %TRUE,
2954 * items that there are not room are available through an
2960 gtk_toolbar_set_show_arrow (GtkToolbar *toolbar,
2961 gboolean show_arrow)
2963 GtkToolbarPrivate *priv;
2965 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
2967 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
2968 show_arrow = show_arrow != FALSE;
2970 if (priv->show_arrow != show_arrow)
2972 priv->show_arrow = show_arrow;
2974 if (!priv->show_arrow)
2975 gtk_widget_hide (priv->arrow_button);
2977 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
2978 g_object_notify (G_OBJECT (toolbar), "show_arrow");
2983 * gtk_toolbar_get_show_arrow:
2984 * @toolbar: a #GtkToolbar
2986 * Returns whether the toolbar has an overflow menu.
2987 * See gtk_toolbar_set_show_arrow()
2994 gtk_toolbar_get_show_arrow (GtkToolbar *toolbar)
2996 GtkToolbarPrivate *priv;
2998 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE);
3000 if (!gtk_toolbar_check_new_api (toolbar))
3003 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3005 return priv->show_arrow;
3009 * gtk_toolbar_get_drop_index:
3010 * @toolbar: a #GtkToolbar
3011 * @x: x coordinate of a point on the toolbar
3012 * @y: y coordinate of a point on the toolbar
3014 * Returns the position corresponding to the indicated point on
3015 * @toolbar. This is useful when dragging items to the toolbar:
3016 * this function returns the position a new item should be
3019 * @x and @y are in @toolbar coordinates.
3021 * Return value: The position corresponding to the point (@x, @y) on the toolbar.
3026 gtk_toolbar_get_drop_index (GtkToolbar *toolbar,
3030 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1);
3032 if (!gtk_toolbar_check_new_api (toolbar))
3035 return physical_to_logical (toolbar, find_drop_index (toolbar, x, y));
3039 gtk_toolbar_finalize (GObject *object)
3042 GtkToolbar *toolbar = GTK_TOOLBAR (object);
3043 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3045 if (toolbar->tooltips)
3046 g_object_unref (toolbar->tooltips);
3048 if (priv->arrow_button)
3049 gtk_widget_unparent (priv->arrow_button);
3051 for (list = priv->content; list != NULL; list = list->next)
3053 ToolbarContent *content = list->data;
3055 toolbar_content_free (content);
3058 g_list_free (priv->content);
3059 g_list_free (toolbar->children);
3061 g_timer_destroy (priv->timer);
3064 gtk_widget_destroy (GTK_WIDGET (priv->menu));
3067 g_source_remove (priv->idle_id);
3069 G_OBJECT_CLASS (parent_class)->finalize (object);
3077 * gtk_toolbar_set_icon_size:
3078 * @toolbar: A #GtkToolbar
3079 * @icon_size: The #GtkIconSize that stock icons in the toolbar shall have.
3081 * This function sets the size of stock icons in the toolbar. You
3082 * can call it both before you add the icons and after they've been
3083 * added. The size you set will override user preferences for the default
3087 gtk_toolbar_set_icon_size (GtkToolbar *toolbar,
3088 GtkIconSize icon_size)
3090 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3092 toolbar->icon_size_set = TRUE;
3094 if (toolbar->icon_size == icon_size)
3097 toolbar->icon_size = icon_size;
3099 gtk_toolbar_reconfigured (toolbar);
3101 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3105 * gtk_toolbar_unset_icon_size:
3106 * @toolbar: a #GtkToolbar
3108 * Unsets toolbar icon size set with gtk_toolbar_set_icon_size(), so that
3109 * user preferences will be used to determine the icon size.
3112 gtk_toolbar_unset_icon_size (GtkToolbar *toolbar)
3116 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3118 if (toolbar->icon_size_set)
3120 GtkSettings *settings = toolbar_get_settings (toolbar);
3124 g_object_get (settings,
3125 "gtk-toolbar-icon-size", &size,
3129 size = DEFAULT_ICON_SIZE;
3131 if (size != toolbar->icon_size)
3132 gtk_toolbar_set_icon_size (toolbar, size);
3134 toolbar->icon_size_set = FALSE;
3139 * gtk_toolbar_append_item:
3140 * @toolbar: a #GtkToolbar.
3141 * @text: give your toolbar button a label.
3142 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3143 * @tooltip_private_text: use with #GtkTipsQuery.
3144 * @icon: a #GtkWidget that should be used as the button's icon.
3145 * @callback: the function to be executed when the button is pressed.
3146 * @user_data: a pointer to any data you wish to be passed to the callback.
3148 * Inserts a new item into the toolbar. You must specify the position
3149 * in the toolbar where it will be inserted.
3151 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3152 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3154 * Return value: the new toolbar item as a #GtkWidget.
3157 gtk_toolbar_append_item (GtkToolbar *toolbar,
3159 const char *tooltip_text,
3160 const char *tooltip_private_text,
3162 GtkSignalFunc callback,
3165 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3167 tooltip_text, tooltip_private_text,
3168 icon, callback, user_data,
3169 toolbar->num_children);
3173 * gtk_toolbar_prepend_item:
3174 * @toolbar: a #GtkToolbar.
3175 * @text: give your toolbar button a label.
3176 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3177 * @tooltip_private_text: use with #GtkTipsQuery.
3178 * @icon: a #GtkWidget that should be used as the button's icon.
3179 * @callback: the function to be executed when the button is pressed.
3180 * @user_data: a pointer to any data you wish to be passed to the callback.
3182 * Adds a new button to the beginning (top or left edges) of the given toolbar.
3184 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3185 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3187 * Return value: the new toolbar item as a #GtkWidget.
3190 gtk_toolbar_prepend_item (GtkToolbar *toolbar,
3192 const char *tooltip_text,
3193 const char *tooltip_private_text,
3195 GtkSignalFunc callback,
3198 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3200 tooltip_text, tooltip_private_text,
3201 icon, callback, user_data,
3206 * gtk_toolbar_insert_item:
3207 * @toolbar: a #GtkToolbar.
3208 * @text: give your toolbar button a label.
3209 * @tooltip_text: a string that appears when the user holds the mouse over this item.
3210 * @tooltip_private_text: use with #GtkTipsQuery.
3211 * @icon: a #GtkWidget that should be used as the button's icon.
3212 * @callback: the function to be executed when the button is pressed.
3213 * @user_data: a pointer to any data you wish to be passed to the callback.
3214 * @position: the number of widgets to insert this item after.
3216 * Inserts a new item into the toolbar. You must specify the position in the
3217 * toolbar where it will be inserted.
3219 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3220 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3222 * Return value: the new toolbar item as a #GtkWidget.
3225 gtk_toolbar_insert_item (GtkToolbar *toolbar,
3227 const char *tooltip_text,
3228 const char *tooltip_private_text,
3230 GtkSignalFunc callback,
3234 return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3236 tooltip_text, tooltip_private_text,
3237 icon, callback, user_data,
3242 * gtk_toolbar_insert_stock:
3243 * @toolbar: A #GtkToolbar
3244 * @stock_id: The id of the stock item you want to insert
3245 * @tooltip_text: The text in the tooltip of the toolbar button
3246 * @tooltip_private_text: The private text of the tooltip
3247 * @callback: The callback called when the toolbar button is clicked.
3248 * @user_data: user data passed to callback
3249 * @position: The position the button shall be inserted at.
3250 * -1 means at the end.
3252 * Inserts a stock item at the specified position of the toolbar. If
3253 * @stock_id is not a known stock item ID, it's inserted verbatim,
3254 * except that underscores used to mark mnemonics are removed.
3256 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3257 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3259 * Returns: the inserted widget
3262 gtk_toolbar_insert_stock (GtkToolbar *toolbar,
3263 const gchar *stock_id,
3264 const char *tooltip_text,
3265 const char *tooltip_private_text,
3266 GtkSignalFunc callback,
3270 return internal_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON,
3272 tooltip_text, tooltip_private_text,
3273 NULL, callback, user_data,
3278 * gtk_toolbar_append_space:
3279 * @toolbar: a #GtkToolbar.
3281 * Adds a new space to the end of the toolbar.
3284 gtk_toolbar_append_space (GtkToolbar *toolbar)
3286 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3290 toolbar->num_children);
3294 * gtk_toolbar_prepend_space:
3295 * @toolbar: a #GtkToolbar.
3297 * Adds a new space to the beginning of the toolbar.
3300 gtk_toolbar_prepend_space (GtkToolbar *toolbar)
3302 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3310 * gtk_toolbar_insert_space:
3311 * @toolbar: a #GtkToolbar
3312 * @position: the number of widgets after which a space should be inserted.
3314 * Inserts a new space in the toolbar at the specified position.
3317 gtk_toolbar_insert_space (GtkToolbar *toolbar,
3320 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_SPACE,
3328 * gtk_toolbar_remove_space:
3329 * @toolbar: a #GtkToolbar.
3330 * @position: the index of the space to remove.
3332 * Removes a space from the specified position.
3335 gtk_toolbar_remove_space (GtkToolbar *toolbar,
3338 GtkToolbarPrivate *priv;
3339 ToolbarContent *content;
3341 g_return_if_fail (GTK_IS_TOOLBAR (toolbar));
3343 if (!gtk_toolbar_check_old_api (toolbar))
3346 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3348 content = g_list_nth_data (priv->content, position);
3352 g_warning ("Toolbar position %d doesn't exist", position);
3356 if (!toolbar_content_is_separator (content))
3358 g_warning ("Toolbar position %d is not a space", position);
3362 toolbar_content_remove (content, toolbar);
3363 toolbar_content_free (content);
3367 * gtk_toolbar_append_widget:
3368 * @toolbar: a #GtkToolbar.
3369 * @widget: a #GtkWidget to add to the toolbar.
3370 * @tooltip_text: the element's tooltip.
3371 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3373 * Adds a widget to the end of the given toolbar.
3376 gtk_toolbar_append_widget (GtkToolbar *toolbar,
3378 const gchar *tooltip_text,
3379 const gchar *tooltip_private_text)
3381 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3383 tooltip_text, tooltip_private_text,
3385 toolbar->num_children);
3389 * gtk_toolbar_prepend_widget:
3390 * @toolbar: a #GtkToolbar.
3391 * @widget: a #GtkWidget to add to the toolbar.
3392 * @tooltip_text: the element's tooltip.
3393 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3395 * Adds a widget to the beginning of the given toolbar.
3398 gtk_toolbar_prepend_widget (GtkToolbar *toolbar,
3400 const gchar *tooltip_text,
3401 const gchar *tooltip_private_text)
3403 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3405 tooltip_text, tooltip_private_text,
3411 * gtk_toolbar_insert_widget:
3412 * @toolbar: a #GtkToolbar.
3413 * @widget: a #GtkWidget to add to the toolbar.
3414 * @tooltip_text: the element's tooltip.
3415 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3416 * @position: the number of widgets to insert this widget after.
3418 * Inserts a widget in the toolbar at the given position.
3421 gtk_toolbar_insert_widget (GtkToolbar *toolbar,
3423 const char *tooltip_text,
3424 const char *tooltip_private_text,
3427 gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_WIDGET,
3429 tooltip_text, tooltip_private_text,
3435 * gtk_toolbar_append_element:
3436 * @toolbar: a #GtkToolbar.
3437 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
3438 * @widget: a #GtkWidget, or %NULL.
3439 * @text: the element's label.
3440 * @tooltip_text: the element's tooltip.
3441 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3442 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3443 * @callback: the function to be executed when the button is pressed.
3444 * @user_data: any data you wish to pass to the callback.
3446 * Adds a new element to the end of a toolbar.
3448 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3449 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3450 * the radio group for the new element. In all other cases, @widget must
3453 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3454 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3456 * Return value: the new toolbar element as a #GtkWidget.
3459 gtk_toolbar_append_element (GtkToolbar *toolbar,
3460 GtkToolbarChildType type,
3463 const char *tooltip_text,
3464 const char *tooltip_private_text,
3466 GtkSignalFunc callback,
3469 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3470 tooltip_text, tooltip_private_text,
3471 icon, callback, user_data,
3472 toolbar->num_children);
3476 * gtk_toolbar_prepend_element:
3477 * @toolbar: a #GtkToolbar.
3478 * @type: a value of type #GtkToolbarChildType that determines what @widget will be.
3479 * @widget: a #GtkWidget, or %NULL
3480 * @text: the element's label.
3481 * @tooltip_text: the element's tooltip.
3482 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3483 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3484 * @callback: the function to be executed when the button is pressed.
3485 * @user_data: any data you wish to pass to the callback.
3487 * Adds a new element to the beginning of a toolbar.
3489 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3490 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3491 * the radio group for the new element. In all other cases, @widget must
3494 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3495 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3497 * Return value: the new toolbar element as a #GtkWidget.
3500 gtk_toolbar_prepend_element (GtkToolbar *toolbar,
3501 GtkToolbarChildType type,
3504 const char *tooltip_text,
3505 const char *tooltip_private_text,
3507 GtkSignalFunc callback,
3510 return gtk_toolbar_insert_element (toolbar, type, widget, text,
3511 tooltip_text, tooltip_private_text,
3512 icon, callback, user_data, 0);
3516 * gtk_toolbar_insert_element:
3517 * @toolbar: a #GtkToolbar.
3518 * @type: a value of type #GtkToolbarChildType that determines what @widget
3520 * @widget: a #GtkWidget, or %NULL.
3521 * @text: the element's label.
3522 * @tooltip_text: the element's tooltip.
3523 * @tooltip_private_text: used for context-sensitive help about this toolbar element.
3524 * @icon: a #GtkWidget that provides pictorial representation of the element's function.
3525 * @callback: the function to be executed when the button is pressed.
3526 * @user_data: any data you wish to pass to the callback.
3527 * @position: the number of widgets to insert this element after.
3529 * Inserts a new element in the toolbar at the given position.
3531 * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element.
3532 * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine
3533 * the radio group for the new element. In all other cases, @widget must
3536 * @callback must be a pointer to a function taking a #GtkWidget and a gpointer as
3537 * arguments. Use the GTK_SIGNAL_FUNC() to cast the function to #GtkSignalFunc.
3539 * Return value: the new toolbar element as a #GtkWidget.
3542 gtk_toolbar_insert_element (GtkToolbar *toolbar,
3543 GtkToolbarChildType type,
3546 const char *tooltip_text,
3547 const char *tooltip_private_text,
3549 GtkSignalFunc callback,
3553 return internal_insert_element (toolbar, type, widget, text,
3554 tooltip_text, tooltip_private_text,
3555 icon, callback, user_data, position, FALSE);
3559 set_child_packing_and_visibility(GtkToolbar *toolbar,
3560 GtkToolbarChild *child)
3565 box = gtk_bin_get_child (GTK_BIN (child->widget));
3567 g_return_if_fail (GTK_IS_BOX (box));
3571 expand = (toolbar->style != GTK_TOOLBAR_BOTH);
3573 gtk_box_set_child_packing (GTK_BOX (box), child->label,
3574 expand, expand, 0, GTK_PACK_END);
3576 if (toolbar->style != GTK_TOOLBAR_ICONS)
3577 gtk_widget_show (child->label);
3579 gtk_widget_hide (child->label);
3584 expand = (toolbar->style != GTK_TOOLBAR_BOTH_HORIZ);
3586 gtk_box_set_child_packing (GTK_BOX (box), child->icon,
3587 expand, expand, 0, GTK_PACK_END);
3589 if (toolbar->style != GTK_TOOLBAR_TEXT)
3590 gtk_widget_show (child->icon);
3592 gtk_widget_hide (child->icon);
3597 internal_insert_element (GtkToolbar *toolbar,
3598 GtkToolbarChildType type,
3601 const char *tooltip_text,
3602 const char *tooltip_private_text,
3604 GtkSignalFunc callback,
3610 ToolbarContent *content;
3611 GtkToolbarPrivate *priv;
3612 char *free_me = NULL;
3613 gboolean is_button = FALSE;
3615 GtkWidget *child_widget;
3616 GtkWidget *child_label;
3617 GtkWidget *child_icon;
3619 g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL);
3620 if (type == GTK_TOOLBAR_CHILD_WIDGET)
3621 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
3622 else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON)
3623 g_return_val_if_fail (widget == NULL, NULL);
3624 if (GTK_IS_TOOL_ITEM (widget))
3625 g_warning (MIXED_API_WARNING);
3627 if (!gtk_toolbar_check_old_api (toolbar))
3630 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3632 child_widget = NULL;
3638 case GTK_TOOLBAR_CHILD_SPACE:
3641 case GTK_TOOLBAR_CHILD_WIDGET:
3642 child_widget = widget;
3645 case GTK_TOOLBAR_CHILD_BUTTON:
3646 case GTK_TOOLBAR_CHILD_TOGGLEBUTTON:
3647 case GTK_TOOLBAR_CHILD_RADIOBUTTON:
3649 if (type == GTK_TOOLBAR_CHILD_BUTTON)
3651 child_widget = gtk_button_new ();
3653 else if (type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
3655 child_widget = gtk_toggle_button_new ();
3656 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child_widget), FALSE);
3658 else /* type == GTK_TOOLBAR_CHILD_RADIOBUTTON */
3660 GSList *group = NULL;
3663 group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
3665 child_widget = gtk_radio_button_new (group);
3666 gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child_widget), FALSE);
3669 gtk_button_set_relief (GTK_BUTTON (child_widget), get_button_relief (toolbar));
3670 gtk_button_set_focus_on_click (GTK_BUTTON (child_widget), FALSE);
3674 g_signal_connect (child_widget, "clicked",
3675 callback, user_data);
3678 if (toolbar->style == GTK_TOOLBAR_BOTH_HORIZ)
3679 box = gtk_hbox_new (FALSE, 0);
3681 box = gtk_vbox_new (FALSE, 0);
3683 gtk_container_add (GTK_CONTAINER (child_widget), box);
3684 gtk_widget_show (box);
3686 if (text && use_stock)
3688 GtkStockItem stock_item;
3689 if (gtk_stock_lookup (text, &stock_item))
3692 icon = gtk_image_new_from_stock (text, toolbar->icon_size);
3694 text = free_me = _gtk_toolbar_elide_underscores (stock_item.label);
3700 child_label = gtk_label_new (text);
3702 gtk_container_add (GTK_CONTAINER (box), child_label);
3707 child_icon = GTK_WIDGET (icon);
3708 gtk_container_add (GTK_CONTAINER (box), child_icon);
3711 gtk_widget_show (child_widget);
3715 g_assert_not_reached ();
3719 if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text)
3721 gtk_tooltips_set_tip (toolbar->tooltips, child_widget,
3722 tooltip_text, tooltip_private_text);
3725 content = toolbar_content_new_compatibility (toolbar, type, child_widget,
3726 child_icon, child_label, position);
3731 return child_widget;
3735 * ToolbarContent methods
3743 struct _ToolbarContent
3753 GtkAllocation start_allocation;
3754 GtkAllocation goal_allocation;
3755 guint is_placeholder : 1;
3756 guint disappearing : 1;
3757 TriState has_menu : 2;
3762 GtkToolbarChild child;
3763 GtkAllocation space_allocation;
3764 guint space_visible : 1;
3769 static ToolbarContent *
3770 toolbar_content_new_tool_item (GtkToolbar *toolbar,
3772 gboolean is_placeholder,
3775 ToolbarContent *content;
3776 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3778 content = g_new0 (ToolbarContent, 1);
3780 content->type = TOOL_ITEM;
3781 content->state = NOT_ALLOCATED;
3782 content->u.tool_item.item = item;
3783 content->u.tool_item.is_placeholder = is_placeholder;
3785 gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar));
3787 priv->content = g_list_insert (priv->content, content, pos);
3789 if (!is_placeholder)
3791 toolbar->num_children++;
3793 gtk_toolbar_stop_sliding (toolbar);
3796 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3797 priv->need_rebuild = TRUE;
3802 static ToolbarContent *
3803 toolbar_content_new_compatibility (GtkToolbar *toolbar,
3804 GtkToolbarChildType type,
3810 ToolbarContent *content;
3811 GtkToolbarChild *child;
3812 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3814 content = g_new0 (ToolbarContent, 1);
3816 child = &(content->u.compatibility.child);
3818 content->type = COMPATIBILITY;
3820 child->widget = widget;
3822 child->label = label;
3824 if (type != GTK_TOOLBAR_CHILD_SPACE)
3826 gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar));
3830 content->u.compatibility.space_visible = TRUE;
3831 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3834 if (type == GTK_TOOLBAR_CHILD_BUTTON ||
3835 type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
3836 type == GTK_TOOLBAR_CHILD_RADIOBUTTON)
3838 set_child_packing_and_visibility (toolbar, child);
3841 priv->content = g_list_insert (priv->content, content, pos);
3842 toolbar->children = g_list_insert (toolbar->children, child, pos);
3843 priv->need_rebuild = TRUE;
3845 toolbar->num_children++;
3851 toolbar_content_remove (ToolbarContent *content,
3852 GtkToolbar *toolbar)
3854 GtkToolbarChild *child;
3855 GtkToolbarPrivate *priv;
3857 priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
3859 switch (content->type)
3862 gtk_widget_unparent (GTK_WIDGET (content->u.tool_item.item));
3866 child = &(content->u.compatibility.child);
3868 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
3870 g_object_ref (child->widget);
3871 gtk_widget_unparent (child->widget);
3872 gtk_widget_destroy (child->widget);
3873 g_object_unref (child->widget);
3876 toolbar->children = g_list_remove (toolbar->children, child);
3880 priv->content = g_list_remove (priv->content, content);
3882 if (!toolbar_content_is_placeholder (content))
3883 toolbar->num_children--;
3885 gtk_widget_queue_resize (GTK_WIDGET (toolbar));
3886 priv->need_rebuild = TRUE;
3890 toolbar_content_free (ToolbarContent *content)
3896 calculate_max_homogeneous_pixels (GtkWidget *widget)
3898 PangoContext *context;
3899 PangoFontMetrics *metrics;
3902 context = gtk_widget_get_pango_context (widget);
3903 metrics = pango_context_get_metrics (context,
3904 widget->style->font_desc,
3905 pango_context_get_language (context));
3906 char_width = pango_font_metrics_get_approximate_char_width (metrics);
3907 pango_font_metrics_unref (metrics);
3909 return PANGO_PIXELS (MAX_HOMOGENEOUS_N_CHARS * char_width);
3913 toolbar_content_expose (ToolbarContent *content,
3914 GtkContainer *container,
3915 GdkEventExpose *expose)
3917 GtkToolbar *toolbar = GTK_TOOLBAR (container);
3918 GtkToolbarChild *child;
3919 GtkWidget *widget = NULL; /* quiet gcc */
3921 switch (content->type)
3924 if (!content->u.tool_item.is_placeholder)
3925 widget = GTK_WIDGET (content->u.tool_item.item);
3929 child = &(content->u.compatibility.child);
3931 if (child->type == GTK_TOOLBAR_CHILD_SPACE)
3933 if (get_space_style (toolbar) == GTK_TOOLBAR_SPACE_LINE &&
3934 content->u.compatibility.space_visible)
3936 _gtk_toolbar_paint_space_line (GTK_WIDGET (toolbar), toolbar,
3938 &content->u.compatibility.space_allocation);
3943 widget = child->widget;
3948 gtk_container_propagate_expose (container, widget, expose);
3952 toolbar_content_visible (ToolbarContent *content,
3953 GtkToolbar *toolbar)
3957 switch (content->type)
3960 item = content->u.tool_item.item;
3962 if (!GTK_WIDGET_VISIBLE (item))
3965 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL &&
3966 gtk_tool_item_get_visible_horizontal (item))
3971 if ((toolbar->orientation == GTK_ORIENTATION_VERTICAL &&
3972 gtk_tool_item_get_visible_vertical (item)))
3981 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
3982 return GTK_WIDGET_VISIBLE (content->u.compatibility.child.widget);
3988 g_assert_not_reached ();
3993 toolbar_content_size_request (ToolbarContent *content,
3994 GtkToolbar *toolbar,
3995 GtkRequisition *requisition)
3999 switch (content->type)
4002 gtk_widget_size_request (GTK_WIDGET (content->u.tool_item.item),
4004 if (content->u.tool_item.is_placeholder &&
4005 content->u.tool_item.disappearing)
4007 requisition->width = 0;
4008 requisition->height = 0;
4013 space_size = get_space_size (toolbar);
4015 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4017 gtk_widget_size_request (content->u.compatibility.child.widget,
4022 if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
4024 requisition->width = space_size;
4025 requisition->height = 0;
4029 requisition->height = space_size;
4030 requisition->width = 0;
4039 toolbar_content_is_homogeneous (ToolbarContent *content,
4040 GtkToolbar *toolbar)
4042 gboolean result = FALSE; /* quiet gcc */
4043 GtkRequisition requisition;
4044 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4046 if (priv->max_homogeneous_pixels < 0)
4048 priv->max_homogeneous_pixels =
4049 calculate_max_homogeneous_pixels (GTK_WIDGET (toolbar));
4052 toolbar_content_size_request (content, toolbar, &requisition);
4054 if (requisition.width > priv->max_homogeneous_pixels)
4057 switch (content->type)
4060 result = gtk_tool_item_get_homogeneous (content->u.tool_item.item) &&
4061 !GTK_IS_SEPARATOR_TOOL_ITEM (content->u.tool_item.item);
4063 if (gtk_tool_item_get_is_important (content->u.tool_item.item) &&
4064 toolbar->style == GTK_TOOLBAR_BOTH_HORIZ &&
4065 toolbar->orientation == GTK_ORIENTATION_HORIZONTAL)
4072 if (content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_BUTTON ||
4073 content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4074 content->u.compatibility.child.type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4089 toolbar_content_is_placeholder (ToolbarContent *content)
4091 if (content->type == TOOL_ITEM && content->u.tool_item.is_placeholder)
4098 toolbar_content_disappearing (ToolbarContent *content)
4100 if (content->type == TOOL_ITEM && content->u.tool_item.disappearing)
4107 toolbar_content_get_state (ToolbarContent *content)
4109 return content->state;
4113 toolbar_content_child_visible (ToolbarContent *content)
4115 switch (content->type)
4118 return GTK_WIDGET_CHILD_VISIBLE (content->u.tool_item.item);
4122 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4124 return GTK_WIDGET_CHILD_VISIBLE (content->u.compatibility.child.widget);
4128 return content->u.compatibility.space_visible;
4133 return FALSE; /* quiet gcc */
4137 toolbar_content_get_goal_allocation (ToolbarContent *content,
4138 GtkAllocation *allocation)
4140 switch (content->type)
4143 *allocation = content->u.tool_item.goal_allocation;
4147 /* Goal allocations are only relevant when we are
4148 * using the new API, so we should never get here
4150 g_assert_not_reached ();
4156 toolbar_content_get_allocation (ToolbarContent *content,
4157 GtkAllocation *allocation)
4159 GtkToolbarChild *child;
4161 switch (content->type)
4164 *allocation = GTK_WIDGET (content->u.tool_item.item)->allocation;
4168 child = &(content->u.compatibility.child);
4170 if (child->type == GTK_TOOLBAR_CHILD_SPACE)
4171 *allocation = content->u.compatibility.space_allocation;
4173 *allocation = child->widget->allocation;
4179 toolbar_content_set_start_allocation (ToolbarContent *content,
4180 GtkAllocation *allocation)
4182 switch (content->type)
4185 content->u.tool_item.start_allocation = *allocation;
4189 /* start_allocation is only relevant when using the new API */
4190 g_assert_not_reached ();
4196 toolbar_content_get_expand (ToolbarContent *content)
4198 if (content->type == TOOL_ITEM &&
4199 gtk_tool_item_get_expand (content->u.tool_item.item) &&
4200 !content->u.tool_item.disappearing)
4209 toolbar_content_set_goal_allocation (ToolbarContent *content,
4210 GtkAllocation *allocation)
4212 switch (content->type)
4215 content->u.tool_item.goal_allocation = *allocation;
4219 /* Only relevant when using new API */
4220 g_assert_not_reached ();
4226 toolbar_content_set_child_visible (ToolbarContent *content,
4227 GtkToolbar *toolbar,
4230 GtkToolbarChild *child;
4232 switch (content->type)
4235 gtk_widget_set_child_visible (GTK_WIDGET (content->u.tool_item.item),
4240 child = &(content->u.compatibility.child);
4242 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
4244 gtk_widget_set_child_visible (child->widget, visible);
4248 if (content->u.compatibility.space_visible != visible)
4250 content->u.compatibility.space_visible = visible;
4251 gtk_widget_queue_draw (GTK_WIDGET (toolbar));
4259 toolbar_content_get_start_allocation (ToolbarContent *content,
4260 GtkAllocation *start_allocation)
4262 switch (content->type)
4265 *start_allocation = content->u.tool_item.start_allocation;
4269 /* Only relevant for new API */
4270 g_assert_not_reached ();
4276 toolbar_content_size_allocate (ToolbarContent *content,
4277 GtkAllocation *allocation)
4279 switch (content->type)
4282 gtk_widget_size_allocate (GTK_WIDGET (content->u.tool_item.item),
4287 if (content->u.compatibility.child.type != GTK_TOOLBAR_CHILD_SPACE)
4289 gtk_widget_size_allocate (content->u.compatibility.child.widget,
4294 content->u.compatibility.space_allocation = *allocation;
4301 toolbar_content_set_state (ToolbarContent *content,
4304 content->state = state;
4308 toolbar_content_get_widget (ToolbarContent *content)
4310 GtkToolbarChild *child;
4312 switch (content->type)
4315 return GTK_WIDGET (content->u.tool_item.item);
4319 child = &(content->u.compatibility.child);
4320 if (child->type != GTK_TOOLBAR_CHILD_SPACE)
4321 return child->widget;
4331 toolbar_content_set_disappearing (ToolbarContent *content,
4332 gboolean disappearing)
4334 switch (content->type)
4337 content->u.tool_item.disappearing = disappearing;
4341 /* Only relevant for new API */
4342 g_assert_not_reached ();
4348 toolbar_content_set_size_request (ToolbarContent *content,
4352 switch (content->type)
4355 gtk_widget_set_size_request (GTK_WIDGET (content->u.tool_item.item),
4360 /* Setting size requests only happens with sliding,
4361 * so not relevant here
4363 g_assert_not_reached ();
4369 toolbar_child_reconfigure (GtkToolbar *toolbar,
4370 GtkToolbarChild *child)
4374 GtkToolbarStyle style;
4375 GtkIconSize icon_size;
4376 GtkReliefStyle relief;
4379 style = gtk_toolbar_get_style (toolbar);
4380 icon_size = gtk_toolbar_get_icon_size (toolbar);
4381 relief = gtk_toolbar_get_relief_style (toolbar);
4384 if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4385 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4386 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4388 box = gtk_bin_get_child (GTK_BIN (child->widget));
4390 if (style == GTK_TOOLBAR_BOTH && GTK_IS_HBOX (box))
4394 vbox = gtk_vbox_new (FALSE, 0);
4397 gtk_widget_reparent (child->label, vbox);
4399 gtk_widget_reparent (child->icon, vbox);
4401 gtk_widget_destroy (box);
4402 gtk_container_add (GTK_CONTAINER (child->widget), vbox);
4404 gtk_widget_show (vbox);
4406 else if (style == GTK_TOOLBAR_BOTH_HORIZ && GTK_IS_VBOX (box))
4410 hbox = gtk_hbox_new (FALSE, 0);
4413 gtk_widget_reparent (child->label, hbox);
4415 gtk_widget_reparent (child->icon, hbox);
4417 gtk_widget_destroy (box);
4418 gtk_container_add (GTK_CONTAINER (child->widget), hbox);
4420 gtk_widget_show (hbox);
4423 set_child_packing_and_visibility (toolbar, child);
4428 if ((child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4429 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
4430 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON) &&
4431 GTK_IS_IMAGE (child->icon))
4433 image = GTK_IMAGE (child->icon);
4434 if (gtk_image_get_storage_type (image) == GTK_IMAGE_STOCK)
4436 gtk_image_get_stock (image, &stock_id, NULL);
4437 stock_id = g_strdup (stock_id);
4438 gtk_image_set_from_stock (image,
4446 if (child->type == GTK_TOOLBAR_CHILD_BUTTON ||
4447 child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON ||
4448 child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON)
4450 gtk_button_set_relief (GTK_BUTTON (child->widget), relief);
4455 toolbar_content_toolbar_reconfigured (ToolbarContent *content,
4456 GtkToolbar *toolbar)
4458 switch (content->type)
4461 _gtk_tool_item_toolbar_reconfigured (content->u.tool_item.item);
4465 toolbar_child_reconfigure (toolbar, &(content->u.compatibility.child));
4471 toolbar_content_retrieve_menu_item (ToolbarContent *content)
4473 if (content->type == TOOL_ITEM)
4474 return gtk_tool_item_retrieve_proxy_menu_item (content->u.tool_item.item);
4476 /* FIXME - we might actually be able to do something meaningful here */
4481 toolbar_content_has_proxy_menu_item (ToolbarContent *content)
4483 if (content->type == TOOL_ITEM)
4485 GtkWidget *menu_item;
4487 if (content->u.tool_item.has_menu == YES)
4489 else if (content->u.tool_item.has_menu == NO)
4492 menu_item = toolbar_content_retrieve_menu_item (content);
4494 content->u.tool_item.has_menu = menu_item? YES : NO;
4496 return menu_item != NULL;
4505 toolbar_content_set_unknown_menu_status (ToolbarContent *content)
4507 if (content->type == TOOL_ITEM)
4508 content->u.tool_item.has_menu = UNKNOWN;
4512 toolbar_content_is_separator (ToolbarContent *content)
4514 GtkToolbarChild *child;
4516 switch (content->type)
4519 return GTK_IS_SEPARATOR_TOOL_ITEM (content->u.tool_item.item);
4523 child = &(content->u.compatibility.child);
4524 return (child->type == GTK_TOOLBAR_CHILD_SPACE);
4532 toolbar_content_set_expand (ToolbarContent *content,
4535 if (content->type == TOOL_ITEM)
4536 gtk_tool_item_set_expand (content->u.tool_item.item, expand);
4540 ignore_show_and_hide_all (ToolbarContent *content)
4542 if (content->type == COMPATIBILITY)
4544 GtkToolbarChildType type = content->u.compatibility.child.type;
4546 if (type == GTK_TOOLBAR_CHILD_BUTTON ||
4547 type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON ||
4548 type == GTK_TOOLBAR_CHILD_RADIOBUTTON)
4558 toolbar_content_show_all (ToolbarContent *content)
4562 if (ignore_show_and_hide_all (content))
4565 widget = toolbar_content_get_widget (content);
4567 gtk_widget_show_all (widget);
4571 toolbar_content_hide_all (ToolbarContent *content)
4575 if (ignore_show_and_hide_all (content))
4578 widget = toolbar_content_get_widget (content);
4580 gtk_widget_hide_all (widget);
4587 get_space_size (GtkToolbar *toolbar)
4589 gint space_size = DEFAULT_SPACE_SIZE;
4593 gtk_widget_style_get (GTK_WIDGET (toolbar),
4594 "space_size", &space_size,
4601 static GtkToolbarSpaceStyle
4602 get_space_style (GtkToolbar *toolbar)
4604 GtkToolbarSpaceStyle space_style = DEFAULT_SPACE_STYLE;
4608 gtk_widget_style_get (GTK_WIDGET (toolbar),
4609 "space_style", &space_style,
4616 static GtkReliefStyle
4617 get_button_relief (GtkToolbar *toolbar)
4619 GtkReliefStyle button_relief = GTK_RELIEF_NORMAL;
4621 gtk_widget_ensure_style (GTK_WIDGET (toolbar));
4623 gtk_widget_style_get (GTK_WIDGET (toolbar),
4624 "button_relief", &button_relief,
4627 return button_relief;
4631 get_internal_padding (GtkToolbar *toolbar)
4635 gtk_widget_style_get (GTK_WIDGET (toolbar),
4636 "internal_padding", &ipadding,
4642 static GtkShadowType
4643 get_shadow_type (GtkToolbar *toolbar)
4645 GtkShadowType shadow_type;
4647 gtk_widget_style_get (GTK_WIDGET (toolbar),
4648 "shadow_type", &shadow_type,
4658 gtk_toolbar_check_old_api (GtkToolbar *toolbar)
4660 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4662 if (priv->api_mode == NEW_API)
4664 g_warning (MIXED_API_WARNING);
4668 priv->api_mode = OLD_API;
4673 gtk_toolbar_check_new_api (GtkToolbar *toolbar)
4675 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4677 if (priv->api_mode == OLD_API)
4679 g_warning (MIXED_API_WARNING);
4683 priv->api_mode = NEW_API;
4687 /* GTK+ internal methods */
4690 _gtk_toolbar_get_default_space_size (void)
4692 return DEFAULT_SPACE_SIZE;
4696 _gtk_toolbar_paint_space_line (GtkWidget *widget,
4697 GtkToolbar *toolbar,
4699 GtkAllocation *allocation)
4701 const double start_fraction = (SPACE_LINE_START / SPACE_LINE_DIVISION);
4702 const double end_fraction = (SPACE_LINE_END / SPACE_LINE_DIVISION);
4704 GtkToolbarSpaceStyle space_style;
4705 GtkOrientation orientation;
4707 g_return_if_fail (GTK_IS_WIDGET (widget));
4709 space_style = toolbar? get_space_style (toolbar) : DEFAULT_SPACE_STYLE;
4710 orientation = toolbar? toolbar->orientation : GTK_ORIENTATION_HORIZONTAL;
4712 if (orientation == GTK_ORIENTATION_HORIZONTAL)
4714 gtk_paint_vline (widget->style, widget->window,
4715 GTK_WIDGET_STATE (widget), area, widget,
4717 allocation->y + allocation->height * start_fraction,
4718 allocation->y + allocation->height * end_fraction,
4719 allocation->x + (allocation->width - widget->style->xthickness) / 2);
4723 gtk_paint_hline (widget->style, widget->window,
4724 GTK_WIDGET_STATE (widget), area, widget,
4726 allocation->x + allocation->width * start_fraction,
4727 allocation->x + allocation->width * end_fraction,
4728 allocation->y + (allocation->height - widget->style->ythickness) / 2);
4733 _gtk_toolbar_elide_underscores (const gchar *original)
4737 gboolean last_underscore;
4739 q = result = g_malloc (strlen (original) + 1);
4740 last_underscore = FALSE;
4742 for (p = original; *p; p++)
4744 if (!last_underscore && *p == '_')
4745 last_underscore = TRUE;
4748 last_underscore = FALSE;
4759 _gtk_toolbar_rebuild_menu (GtkToolbar *toolbar)
4761 GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar);
4764 priv->need_rebuild = TRUE;
4766 for (list = priv->content; list != NULL; list = list->next)
4768 ToolbarContent *content = list->data;
4770 toolbar_content_set_unknown_menu_status (content);
4773 gtk_widget_queue_resize (GTK_WIDGET (toolbar));