I think the EggToolbar in libegg is more or less ready to go into gtk+ now. It would be good to get it in quickly, because adding the new toolbar to gtk+ uncovered lots of incompatibilities with old one, and I'm not confident that I found them all. Some notes: - should the popup_context_menu signal include x, y? That way users won't have to query and get a position that could possibly be far from the point they actually clicked. - When the toolbar is in old API mode it ignores EggToolItems whose children are hidden. From the toolbar_item_visible() function: if (priv->api_mode == OLD_API) { GtkWidget *bin_child = GTK_BIN (item)->child; if (!bin_child || !GTK_WIDGET_VISIBLE (bin_child)) return FALSE; } This is a compatibility measure; some applications will hide the widgets they added to the toolbar expecting them to disappear from the toolbar, but since the corresponding EggToolItem is not hidden, there will be a blank space instead without the hack above. - Do we really need GDK_EXPOSURE_MASK on input-only windows? It doesn't make any sense to me, but we do it on other input-only windows (GtkButton, GtkMenuItem) - Some applications expect the toolbar to gtk_widget_show() the icon and label widgets they pass in. The old toolbar also called gtk_widget_hide() and gtk_widget_show() depending on the toolbar style. I think that was a bad idea, because then the user couldn't control the visibility of the widgets themselves. (They *could* control the visibility of the buttons, so this doesn't contradict the above). Libgnome (I think) depends on the toolbar calling gtk_widget_show() on the icon widgets, so when widgets are added using the old API, the toolbar calls gtk_widget_show(). - Someone needs to write documentation - There are still a few things to do that will be easier to do as part of gtk+ (using _gtk_binding_signal_new etc). Søren
? toolbar.patch ? toolbar.tar.gz ? demos/gtk-demo/geninclude.pl ? gdk/gdkmarshalers.c ? gtk/gtkradiotoolbutton.c ? gtk/gtkradiotoolbutton.h ? gtk/gtkseparatortoolitem.c ? gtk/gtkseparatortoolitem.h ? gtk/gtktoggletoolbutton.c ? gtk/gtktoggletoolbutton.h ? gtk/gtktoolbutton.c ? gtk/gtktoolbutton.h ? gtk/gtktoolitem.c ? gtk/gtktoolitem.h ? gtk/hatch.sh ? gtk/tarb Index: gtk/Makefile.am =================================================================== RCS file: /cvs/gnome/gtk+/gtk/Makefile.am,v retrieving revision 1.223 diff -u -p -u -r1.223 Makefile.am --- gtk/Makefile.am 6 May 2003 21:54:29 -0000 1.223 +++ gtk/Makefile.am 8 Jun 2003 15:59:54 -0000 @@ -94,28 +94,27 @@ gtk_public_h_sources = \ gtkalignment.h \ gtkarrow.h \ gtkaspectframe.h \ + gtkbbox.h \ gtkbin.h \ gtkbindings.h \ - gtkbbox.h \ gtkbox.h \ gtkbutton.h \ gtkcalendar.h \ + gtkcelleditable.h \ + gtkcellrenderer.h \ + gtkcellrendererpixbuf.h \ + gtkcellrenderertext.h \ + gtkcellrenderertoggle.h \ gtkcheckbutton.h \ gtkcheckmenuitem.h \ - gtkseparatormenuitem.h \ - gtkclist.h \ gtkclipboard.h \ + gtkclist.h \ gtkcolorsel.h \ gtkcolorseldialog.h \ gtkcombo.h \ gtkcontainer.h \ gtkctree.h \ gtkcurve.h \ - gtkcellrenderer.h \ - gtkcelleditable.h \ - gtkcellrenderertext.h \ - gtkcellrenderertoggle.h \ - gtkcellrendererpixbuf.h \ gtkdebug.h \ gtkdialog.h \ gtkdnd.h \ @@ -162,8 +161,8 @@ gtk_public_h_sources = \ gtkmessagedialog.h \ gtkmisc.h \ gtknotebook.h \ - gtkoldeditable.h \ gtkobject.h \ + gtkoldeditable.h \ gtkoptionmenu.h \ gtkpaned.h \ gtkpixmap.h \ @@ -174,6 +173,7 @@ gtk_public_h_sources = \ gtkprogressbar.h \ gtkradiobutton.h \ gtkradiomenuitem.h \ + gtkradiotoolbutton.h \ gtkrange.h \ gtkrc.h \ gtkruler.h \ @@ -182,16 +182,19 @@ gtk_public_h_sources = \ gtkscrolledwindow.h \ gtkselection.h \ gtkseparator.h \ + gtkseparatormenuitem.h \ + gtkseparatortoolitem.h \ gtksettings.h \ gtksignal.h \ gtksizegroup.h \ gtksocket.h \ gtkspinbutton.h \ - gtkstyle.h \ gtkstatusbar.h \ gtkstock.h \ + gtkstyle.h \ gtktable.h \ gtktearoffmenuitem.h \ + gtktext.h \ gtktextbuffer.h \ gtktextchild.h \ gtktextdisplay.h \ @@ -201,10 +204,12 @@ gtk_public_h_sources = \ gtktexttag.h \ gtktexttagtable.h \ gtktextview.h \ - gtktext.h \ gtktipsquery.h \ gtktogglebutton.h \ + gtktoggletoolbutton.h \ gtktoolbar.h \ + gtktoolbutton.h \ + gtktoolitem.h \ gtktooltips.h \ gtktree.h \ gtktreednd.h \ @@ -249,6 +254,12 @@ gtk_c_sources = \ gtkaccelgroup.c \ gtkaccelmap.c \ gtkaccellabel.c \ + gtkradiotoolbutton.c \ + gtktoggletoolbutton.c \ + gtktoolbar.c \ + gtktoolbutton.c \ + gtkseparatortoolitem.c \ + gtktoolitem.c \ gtkaccessible.c \ gtkadjustment.c \ gtkalignment.c \ @@ -374,7 +385,6 @@ gtk_c_sources = \ gtkthemes.c \ gtktipsquery.c \ gtktogglebutton.c \ - gtktoolbar.c \ gtktooltips.c \ gtktree.c \ gtktreeitem.c \ Index: gtk/gtktoolbar.c =================================================================== RCS file: /cvs/gnome/gtk+/gtk/gtktoolbar.c,v retrieving revision 1.87 diff -u -p -u -r1.87 gtktoolbar.c --- gtk/gtktoolbar.c 5 Jun 2003 23:37:03 -0000 1.87 +++ gtk/gtktoolbar.c 8 Jun 2003 15:59:57 -0000 @@ -25,22 +25,23 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ -#include <string.h> +#undef GTK_DISABLE_DEPRECATED -#include "gtkbutton.h" -#include "gtktogglebutton.h" +#include "gtkarrow.h" +#include "gtktoolbar.h" +#include "gtkradiotoolbutton.h" +#include "gtkseparatortoolitem.h" +#include "gtkmenu.h" #include "gtkradiobutton.h" -#include "gtklabel.h" -#include "gtkvbox.h" -#include "gtkhbox.h" #include "gtktoolbar.h" -#include "gtkstock.h" -#include "gtkiconfactory.h" -#include "gtkimage.h" -#include "gtksettings.h" -#include "gtkintl.h" +#include "gtkbindings.h" +#include <gdk/gdkkeysyms.h> #include "gtkmarshalers.h" - +#include "gtkmain.h" +#include "gtkstock.h" +#include "gtklabel.h" +#include "gtkprivate.h" +#include <string.h> #define DEFAULT_IPADDING 0 #define DEFAULT_SPACE_SIZE 5 @@ -53,140 +54,234 @@ #define SPACE_LINE_START 3 #define SPACE_LINE_END 7 +#ifndef _ +# define _(s) (s) +#endif + enum { PROP_0, PROP_ORIENTATION, - PROP_TOOLBAR_STYLE + PROP_TOOLBAR_STYLE, + PROP_SHOW_ARROW +}; + +enum { + CHILD_PROP_0, + CHILD_PROP_EXPAND, + CHILD_PROP_HOMOGENEOUS, + CHILD_PROP_PACK_END, }; enum { ORIENTATION_CHANGED, STYLE_CHANGED, + POPUP_CONTEXT_MENU, + MOVE_FOCUS, + FOCUS_HOME, + FOCUS_END, LAST_SIGNAL }; -typedef struct _GtkToolbarChildSpace GtkToolbarChildSpace; -struct _GtkToolbarChildSpace -{ - GtkToolbarChild child; - - gint alloc_x, alloc_y; -}; +static void gtk_toolbar_init (GtkToolbar *toolbar); +static void gtk_toolbar_class_init (GtkToolbarClass *klass); -static void gtk_toolbar_class_init (GtkToolbarClass *class); -static void gtk_toolbar_init (GtkToolbar *toolbar); -static void gtk_toolbar_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void gtk_toolbar_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void gtk_toolbar_destroy (GtkObject *object); -static gint gtk_toolbar_expose (GtkWidget *widget, - GdkEventExpose *event); -static void gtk_toolbar_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void gtk_toolbar_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static void gtk_toolbar_style_set (GtkWidget *widget, - GtkStyle *prev_style); -static gboolean gtk_toolbar_focus (GtkWidget *widget, - GtkDirectionType dir); -static void gtk_toolbar_screen_changed (GtkWidget *widget, - GdkScreen *previous_screen); -static void gtk_toolbar_show_all (GtkWidget *widget); -static void gtk_toolbar_hide_all (GtkWidget *widget); -static void gtk_toolbar_add (GtkContainer *container, - GtkWidget *widget); -static void gtk_toolbar_remove (GtkContainer *container, - GtkWidget *widget); -static void gtk_toolbar_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data); +static void gtk_toolbar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_toolbar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static gint gtk_toolbar_expose (GtkWidget *widget, + GdkEventExpose *event); +static void gtk_toolbar_realize (GtkWidget *widget); +static void gtk_toolbar_unrealize (GtkWidget *widget); +static void gtk_toolbar_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_toolbar_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void gtk_toolbar_style_set (GtkWidget *widget, + GtkStyle *prev_style); +static void gtk_toolbar_direction_changed (GtkWidget *widget, + GtkTextDirection previous_direction); +static gboolean gtk_toolbar_focus (GtkWidget *widget, + GtkDirectionType dir); +static void gtk_toolbar_screen_changed (GtkWidget *widget, + GdkScreen *previous_screen); +static void gtk_toolbar_map (GtkWidget *widget); +static void gtk_toolbar_unmap (GtkWidget *widget); + +static void gtk_toolbar_drag_leave (GtkWidget *widget, + GdkDragContext *context, + guint time_); +static gboolean gtk_toolbar_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time_); +static void gtk_toolbar_set_child_property (GtkContainer *container, + GtkWidget *child, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_toolbar_get_child_property (GtkContainer *container, + GtkWidget *child, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static void gtk_toolbar_add (GtkContainer *container, + GtkWidget *widget); +static void gtk_toolbar_remove (GtkContainer *container, + GtkWidget *widget); +static void gtk_toolbar_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static GType gtk_toolbar_child_type (GtkContainer *container); -static void gtk_real_toolbar_orientation_changed (GtkToolbar *toolbar, +static void gtk_toolbar_real_orientation_changed (GtkToolbar *toolbar, GtkOrientation orientation); -static void gtk_real_toolbar_style_changed (GtkToolbar *toolbar, +static void gtk_toolbar_real_style_changed (GtkToolbar *toolbar, GtkToolbarStyle style); -static GtkWidget * gtk_toolbar_internal_insert_element (GtkToolbar *toolbar, - GtkToolbarChildType type, - GtkWidget *widget, - const char *text, - const char *tooltip_text, - const char *tooltip_private_text, - GtkWidget *icon, - GtkSignalFunc callback, - gpointer user_data, - gint position); - -static GtkWidget * gtk_toolbar_internal_insert_item (GtkToolbar *toolbar, - const char *text, - const char *tooltip_text, - const char *tooltip_private_text, - GtkWidget *icon, - GtkSignalFunc callback, - gpointer user_data, - gint position); - -static void gtk_toolbar_update_button_relief (GtkToolbar *toolbar); - -static GtkReliefStyle get_button_relief (GtkToolbar *toolbar); -static gint get_space_size (GtkToolbar *toolbar); -static GtkToolbarSpaceStyle get_space_style (GtkToolbar *toolbar); - - -static GtkContainerClass *parent_class; - -static guint toolbar_signals[LAST_SIGNAL] = { 0 }; +static gboolean gtk_toolbar_move_focus (GtkToolbar *toolbar, + GtkDirectionType dir); +static gboolean gtk_toolbar_focus_home (GtkToolbar *toolbar); +static gboolean gtk_toolbar_focus_end (GtkToolbar *toolbar); + +static gboolean gtk_toolbar_button_press (GtkWidget *button, + GdkEventButton *event, + GtkToolbar *toolbar); +static gboolean gtk_toolbar_arrow_button_press (GtkWidget *button, + GdkEventButton *event, + GtkToolbar *toolbar); +static void gtk_toolbar_arrow_button_clicked (GtkWidget *button, + GtkToolbar *toolbar); +static void gtk_toolbar_update_button_relief (GtkToolbar *toolbar); +static GtkReliefStyle get_button_relief (GtkToolbar *toolbar); +static gint get_space_size (GtkToolbar *toolbar); +static GtkToolbarSpaceStyle get_space_style (GtkToolbar *toolbar); +static void gtk_toolbar_remove_tool_item (GtkToolbar *toolbar, + GtkToolItem *item); + +static GtkWidget *gtk_toolbar_internal_insert_element (GtkToolbar *toolbar, + GtkToolbarChildType type, + GtkWidget *widget, + const char *text, + const char *tooltip_text, + const char *tooltip_private_text, + GtkWidget *icon, + GtkSignalFunc callback, + gpointer user_data, + gint position, + gboolean use_stock); + + +#define PRIVATE_KEY "gtk-toolbar-private" + +#define GTK_TOOLBAR_GET_PRIVATE(toolbar) (g_object_get_data (G_OBJECT (toolbar), PRIVATE_KEY)) + +typedef enum { + DONT_KNOW, + OLD_API, + NEW_API +} ApiMode; + +typedef struct +{ + GList *items; + + GtkWidget *arrow; + GtkWidget *arrow_button; + + gboolean show_arrow; + + gint drop_index; + GdkWindow *drag_highlight; + GtkMenu *menu; + + GdkWindow *event_window; + ApiMode api_mode; +} GtkToolbarPrivate; +static GtkContainerClass *parent_class = NULL; +static guint toolbar_signals [LAST_SIGNAL] = { 0 }; GType gtk_toolbar_get_type (void) { - static GType toolbar_type = 0; + static GtkType type = 0; - if (!toolbar_type) + if (!type) { - static const GTypeInfo toolbar_info = - { - sizeof (GtkToolbarClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) gtk_toolbar_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GtkToolbar), - 0, /* n_preallocs */ - (GInstanceInitFunc) gtk_toolbar_init, - }; + static const GTypeInfo type_info = + { + sizeof (GtkToolbarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gtk_toolbar_class_init, + (GClassFinalizeFunc) NULL, + NULL, + sizeof (GtkToolbar), + 0, /* n_preallocs */ + (GInstanceInitFunc) gtk_toolbar_init, + }; - toolbar_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkToolbar", - &toolbar_info, 0); + type = g_type_register_static (GTK_TYPE_CONTAINER, + "GtkToolbar", + &type_info, 0); } + + return type; +} + +static void +add_arrow_bindings (GtkBindingSet *binding_set, + guint keysym, + GtkDirectionType dir) +{ + guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left; + + gtk_binding_entry_add_signal (binding_set, keysym, 0, + "move_focus", 1, + GTK_TYPE_DIRECTION_TYPE, dir); + gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0, + "move_focus", 1, + GTK_TYPE_DIRECTION_TYPE, dir); +} - return toolbar_type; +static void +add_ctrl_tab_bindings (GtkBindingSet *binding_set, + GdkModifierType modifiers, + GtkDirectionType direction) +{ + gtk_binding_entry_add_signal (binding_set, + GDK_Tab, GDK_CONTROL_MASK | modifiers, + "move_focus", 1, + GTK_TYPE_DIRECTION_TYPE, direction); + gtk_binding_entry_add_signal (binding_set, + GDK_KP_Tab, GDK_CONTROL_MASK | modifiers, + "move_focus", 1, + GTK_TYPE_DIRECTION_TYPE, direction); } static void -gtk_toolbar_class_init (GtkToolbarClass *class) +gtk_toolbar_class_init (GtkToolbarClass *klass) { - GObjectClass *gobject_class; - GtkObjectClass *object_class; + GObjectClass *gobject_class; GtkWidgetClass *widget_class; GtkContainerClass *container_class; + GtkBindingSet *binding_set; - gobject_class = G_OBJECT_CLASS (class); - object_class = (GtkObjectClass *) class; - widget_class = (GtkWidgetClass *) class; - container_class = (GtkContainerClass *) class; - - parent_class = g_type_class_peek_parent (class); - - object_class->destroy = gtk_toolbar_destroy; + parent_class = g_type_class_peek_parent (klass); + + gobject_class = (GObjectClass *)klass; + widget_class = (GtkWidgetClass *)klass; + container_class = (GtkContainerClass *)klass; + gobject_class->set_property = gtk_toolbar_set_property; gobject_class->get_property = gtk_toolbar_get_property; @@ -194,37 +289,83 @@ gtk_toolbar_class_init (GtkToolbarClass widget_class->size_request = gtk_toolbar_size_request; widget_class->size_allocate = gtk_toolbar_size_allocate; widget_class->style_set = gtk_toolbar_style_set; - widget_class->show_all = gtk_toolbar_show_all; - widget_class->hide_all = gtk_toolbar_hide_all; + widget_class->direction_changed = gtk_toolbar_direction_changed; widget_class->focus = gtk_toolbar_focus; widget_class->screen_changed = gtk_toolbar_screen_changed; + widget_class->realize = gtk_toolbar_realize; + widget_class->unrealize = gtk_toolbar_unrealize; + widget_class->map = gtk_toolbar_map; + widget_class->unmap = gtk_toolbar_unmap; + + widget_class->drag_leave = gtk_toolbar_drag_leave; + widget_class->drag_motion = gtk_toolbar_drag_motion; - container_class->add = gtk_toolbar_add; + container_class->add = gtk_toolbar_add; container_class->remove = gtk_toolbar_remove; container_class->forall = gtk_toolbar_forall; + container_class->child_type = gtk_toolbar_child_type; + container_class->get_child_property = gtk_toolbar_get_child_property; + container_class->set_child_property = gtk_toolbar_set_child_property; + + klass->orientation_changed = gtk_toolbar_real_orientation_changed; + klass->style_changed = gtk_toolbar_real_style_changed; + klass->move_focus = gtk_toolbar_move_focus; + klass->focus_home = gtk_toolbar_focus_home; + klass->focus_end = gtk_toolbar_focus_end; - class->orientation_changed = gtk_real_toolbar_orientation_changed; - class->style_changed = gtk_real_toolbar_style_changed; - toolbar_signals[ORIENTATION_CHANGED] = g_signal_new ("orientation_changed", - G_OBJECT_CLASS_TYPE (gobject_class), + G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GtkToolbarClass, orientation_changed), NULL, NULL, - _gtk_marshal_VOID__ENUM, + g_cclosure_marshal_VOID__ENUM, G_TYPE_NONE, 1, GTK_TYPE_ORIENTATION); toolbar_signals[STYLE_CHANGED] = g_signal_new ("style_changed", - G_OBJECT_CLASS_TYPE (gobject_class), + G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GtkToolbarClass, style_changed), NULL, NULL, - _gtk_marshal_VOID__ENUM, + g_cclosure_marshal_VOID__ENUM, G_TYPE_NONE, 1, GTK_TYPE_TOOLBAR_STYLE); - + toolbar_signals[POPUP_CONTEXT_MENU] = + g_signal_new ("popup_context_menu", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GtkToolbarClass, popup_context_menu), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + toolbar_signals[MOVE_FOCUS] = + g_signal_new ("move_focus", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkToolbarClass, move_focus), + NULL, NULL, + _gtk_marshal_BOOLEAN__ENUM, + G_TYPE_BOOLEAN, 1, + GTK_TYPE_DIRECTION_TYPE); + toolbar_signals[FOCUS_HOME] = + g_signal_new ("focus_home", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkToolbarClass, focus_home), + NULL, NULL, + _gtk_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + toolbar_signals[FOCUS_END] = + g_signal_new ("focus_end", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkToolbarClass, focus_end), + NULL, NULL, + _gtk_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + /* properties */ g_object_class_install_property (gobject_class, PROP_ORIENTATION, g_param_spec_enum ("orientation", @@ -233,17 +374,49 @@ gtk_toolbar_class_init (GtkToolbarClass GTK_TYPE_ORIENTATION, GTK_ORIENTATION_HORIZONTAL, G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - PROP_TOOLBAR_STYLE, - g_param_spec_enum ("toolbar_style", + + g_object_class_install_property (gobject_class, + PROP_TOOLBAR_STYLE, + g_param_spec_enum ("toolbar_style", _("Toolbar Style"), _("How to draw the toolbar"), GTK_TYPE_TOOLBAR_STYLE, GTK_TOOLBAR_ICONS, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, + PROP_SHOW_ARROW, + g_param_spec_boolean ("show_arrow", + _("Show Arrow"), + _("If an arrow should be shown if the toolbar doesn't fit"), + FALSE, + G_PARAM_READWRITE)); + + /* child properties */ + gtk_container_class_install_child_property (container_class, + CHILD_PROP_EXPAND, + g_param_spec_boolean ("expand", + _("Expand"), + _("Whether the item should receive extra space when the toolbar grows"), + TRUE, + G_PARAM_READWRITE)); + + gtk_container_class_install_child_property (container_class, + CHILD_PROP_HOMOGENEOUS, + g_param_spec_boolean ("homogeneous", + _("Homogeneous"), + _("Whether the item should be the same size as other homogeneous items"), + TRUE, + G_PARAM_READWRITE)); + + gtk_container_class_install_child_property (container_class, + CHILD_PROP_PACK_END, + g_param_spec_uint ("pack_end", + _("Pack End"), + _("Whether the item is positioned at the end of the toolbar"), + 0, G_MAXINT, 0, + G_PARAM_READWRITE)); - + /* style properties */ gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("space_size", _("Spacer size"), @@ -252,7 +425,7 @@ gtk_toolbar_class_init (GtkToolbarClass G_MAXINT, DEFAULT_SPACE_SIZE, G_PARAM_READABLE)); - + gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("internal_padding", _("Internal padding"), @@ -261,24 +434,22 @@ gtk_toolbar_class_init (GtkToolbarClass G_MAXINT, DEFAULT_IPADDING, G_PARAM_READABLE)); - + gtk_widget_class_install_style_property (widget_class, g_param_spec_enum ("space_style", _("Space style"), _("Whether spacers are vertical lines or just blank"), GTK_TYPE_TOOLBAR_SPACE_STYLE, DEFAULT_SPACE_STYLE, - G_PARAM_READABLE)); - + gtk_widget_class_install_style_property (widget_class, g_param_spec_enum ("button_relief", - _("Button relief"), - _("Type of bevel around toolbar buttons"), + _("Button relief"), + _("Type of bevel around toolbar buttons"), GTK_TYPE_RELIEF_STYLE, GTK_RELIEF_NONE, G_PARAM_READABLE)); - gtk_widget_class_install_style_property (widget_class, g_param_spec_enum ("shadow_type", _("Shadow type"), @@ -300,115 +471,111 @@ gtk_toolbar_class_init (GtkToolbarClass GTK_TYPE_ICON_SIZE, DEFAULT_ICON_SIZE, G_PARAM_READWRITE)); -} - -static void -style_change_notify (GtkToolbar *toolbar) -{ - if (!toolbar->style_set) - { - /* pretend it was set, then unset, thus reverting to new default */ - toolbar->style_set = TRUE; - gtk_toolbar_unset_style (toolbar); - } -} - -static void -icon_size_change_notify (GtkToolbar *toolbar) -{ - if (!toolbar->icon_size_set) - { - /* pretend it was set, then unset, thus reverting to new default */ - toolbar->icon_size_set = TRUE; - gtk_toolbar_unset_icon_size (toolbar); - } -} - -static GtkSettings * -toolbar_get_settings (GtkToolbar *toolbar) -{ - return g_object_get_data (G_OBJECT (toolbar), "gtk-toolbar-settings"); -} - -static void -gtk_toolbar_screen_changed (GtkWidget *widget, - GdkScreen *previous_screen) -{ - GtkToolbar *toolbar = GTK_TOOLBAR (widget); - GtkSettings *old_settings = toolbar_get_settings (toolbar); - GtkSettings *settings; - - if (gtk_widget_has_screen (GTK_WIDGET (toolbar))) - settings = gtk_widget_get_settings (GTK_WIDGET (toolbar)); - else - settings = NULL; - - if (settings == old_settings) - return; - - if (old_settings) - { - g_signal_handler_disconnect (old_settings, toolbar->style_set_connection); - g_signal_handler_disconnect (old_settings, toolbar->icon_size_connection); - - g_object_unref (old_settings); - } - - if (settings) - { - toolbar->style_set_connection = - g_signal_connect_swapped (settings, - "notify::gtk-toolbar-style", - G_CALLBACK (style_change_notify), - toolbar); - - toolbar->icon_size_connection = - g_signal_connect_swapped (settings, - "notify::gtk-toolbar-icon-size", - G_CALLBACK (icon_size_change_notify), - toolbar); + binding_set = gtk_binding_set_by_class (klass); - g_object_ref (settings); - g_object_set_data (G_OBJECT (toolbar), "gtk-toolbar-settings", settings); - } - else - g_object_set_data (G_OBJECT (toolbar), "gtk-toolbar-settings", NULL); + add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT); + add_arrow_bindings (binding_set, GDK_Right, GTK_DIR_RIGHT); + add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP); + add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN); + + gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0, + "focus_home", 0); + gtk_binding_entry_add_signal (binding_set, GDK_Home, 0, + "focus_home", 0); + gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0, + "focus_end", 0); + gtk_binding_entry_add_signal (binding_set, GDK_End, 0, + "focus_end", 0); - style_change_notify (toolbar); - icon_size_change_notify (toolbar); + add_ctrl_tab_bindings (binding_set, 0, GTK_DIR_RIGHT); + add_ctrl_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_LEFT); } static void gtk_toolbar_init (GtkToolbar *toolbar) { - GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW); + GtkToolbarPrivate *priv; + GTK_WIDGET_UNSET_FLAGS (toolbar, GTK_CAN_FOCUS); + GTK_WIDGET_SET_FLAGS (toolbar, GTK_NO_WINDOW); - toolbar->num_children = 0; - toolbar->children = NULL; - toolbar->orientation = GTK_ORIENTATION_HORIZONTAL; - toolbar->icon_size = DEFAULT_ICON_SIZE; - toolbar->style = DEFAULT_TOOLBAR_STYLE; - toolbar->tooltips = gtk_tooltips_new (); + priv = g_new0 (GtkToolbarPrivate, 1); + g_object_set_data (G_OBJECT (toolbar), PRIVATE_KEY, priv); + + toolbar->orientation = GTK_ORIENTATION_HORIZONTAL; + toolbar->style = DEFAULT_TOOLBAR_STYLE; + toolbar->icon_size = DEFAULT_ICON_SIZE; + toolbar->tooltips = gtk_tooltips_new (); g_object_ref (toolbar->tooltips); gtk_object_sink (GTK_OBJECT (toolbar->tooltips)); - toolbar->button_maxw = 0; - toolbar->button_maxh = 0; + priv->arrow_button = gtk_toggle_button_new (); + g_signal_connect (priv->arrow_button, "button_press_event", + G_CALLBACK (gtk_toolbar_arrow_button_press), toolbar); + g_signal_connect (priv->arrow_button, "clicked", + G_CALLBACK (gtk_toolbar_arrow_button_clicked), toolbar); + gtk_button_set_relief (GTK_BUTTON (priv->arrow_button), + get_button_relief (toolbar)); + + priv->api_mode = DONT_KNOW; + +#if 0 + /* FIXME: enable this when we can depend on gtk+ 2.3.0 */ + gtk_button_set_focus_on_click (GTK_BUTTON (priv->arrow_button), FALSE); +#endif + + priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE); + gtk_widget_show (priv->arrow); + gtk_container_add (GTK_CONTAINER (priv->arrow_button), priv->arrow); + + gtk_widget_set_parent (priv->arrow_button, GTK_WIDGET (toolbar)); + + g_signal_connect (GTK_WIDGET (toolbar), "button_press_event", + G_CALLBACK (gtk_toolbar_button_press), toolbar); + + /* which child position a drop will occur at */ + priv->drop_index = -1; + priv->drag_highlight = NULL; + + priv->menu = NULL; +} - toolbar->style_set = FALSE; - toolbar->icon_size_set = FALSE; +static gboolean +toolbar_item_visible (GtkToolbar *toolbar, GtkToolItem *item) +{ + if (GTK_WIDGET_VISIBLE (item) && + ((toolbar->orientation == GTK_ORIENTATION_HORIZONTAL && item->visible_horizontal) || + (toolbar->orientation == GTK_ORIENTATION_VERTICAL && item->visible_vertical))) + { + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + /* With the old toolbar you could hide a button by calling gtk_widget_hide() + * on it. This doesn't work with the new API because the GtkToolItem will not be + * hidden. + */ + if (priv->api_mode == OLD_API) + { + GtkWidget *bin_child = GTK_BIN (item)->child; + + if (!bin_child || !GTK_WIDGET_VISIBLE (bin_child)) + return FALSE; + } + + return TRUE; + } + + return FALSE; } static void -gtk_toolbar_set_property (GObject *object, - guint prop_id, +gtk_toolbar_set_property (GObject *object, + guint prop_id, const GValue *value, GParamSpec *pspec) { GtkToolbar *toolbar = GTK_TOOLBAR (object); - + switch (prop_id) { case PROP_ORIENTATION: @@ -417,17 +584,24 @@ gtk_toolbar_set_property (GObject * case PROP_TOOLBAR_STYLE: gtk_toolbar_set_style (toolbar, g_value_get_enum (value)); break; + case PROP_SHOW_ARROW: + gtk_toolbar_set_show_arrow (toolbar, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; } } static void -gtk_toolbar_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +gtk_toolbar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { GtkToolbar *toolbar = GTK_TOOLBAR (object); - + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + switch (prop_id) { case PROP_ORIENTATION: @@ -436,122 +610,153 @@ gtk_toolbar_get_property (GObject * case PROP_TOOLBAR_STYLE: g_value_set_enum (value, toolbar->style); break; + case PROP_SHOW_ARROW: + g_value_set_boolean (value, priv->show_arrow); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } -GtkWidget* -gtk_toolbar_new (void) +static void +gtk_toolbar_map (GtkWidget *widget) { - GtkToolbar *toolbar; + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget); - toolbar = g_object_new (GTK_TYPE_TOOLBAR, NULL); + GTK_WIDGET_CLASS (parent_class)->map (widget); - return GTK_WIDGET (toolbar); + if (priv->event_window) + gdk_window_show_unraised (priv->event_window); } static void -gtk_toolbar_destroy (GtkObject *object) +gtk_toolbar_unmap (GtkWidget *widget) { - GtkToolbar *toolbar; - GList *children; - - g_return_if_fail (GTK_IS_TOOLBAR (object)); + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget); - toolbar = GTK_TOOLBAR (object); - - if (toolbar->tooltips) - { - g_object_unref (toolbar->tooltips); - toolbar->tooltips = NULL; - } - - for (children = toolbar->children; children; children = children->next) - { - GtkToolbarChild *child; - - child = children->data; - - if (child->type != GTK_TOOLBAR_CHILD_SPACE) - { - g_object_ref (child->widget); - gtk_widget_unparent (child->widget); - gtk_widget_destroy (child->widget); - g_object_unref (child->widget); - } + if (priv->event_window) + gdk_window_hide (priv->event_window); - g_free (child); - } - g_list_free (toolbar->children); - toolbar->children = NULL; - - GTK_OBJECT_CLASS (parent_class)->destroy (object); + GTK_WIDGET_CLASS (parent_class)->unmap (widget); } static void -gtk_toolbar_paint_space_line (GtkWidget *widget, - GdkRectangle *area, - GtkToolbarChild *child) +gtk_toolbar_paint_space_line (GtkWidget *widget, + GdkRectangle *area, + GtkToolItem *item) { GtkToolbar *toolbar; - GtkToolbarChildSpace *child_space; + GtkAllocation *allocation; gint space_size; - g_return_if_fail (GTK_IS_TOOLBAR (widget)); - g_return_if_fail (child != NULL); - g_return_if_fail (child->type == GTK_TOOLBAR_CHILD_SPACE); + g_return_if_fail (GTK_BIN (item)->child == NULL); toolbar = GTK_TOOLBAR (widget); - child_space = (GtkToolbarChildSpace *) child; + allocation = >K_WIDGET (item)->allocation; space_size = get_space_size (toolbar); if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) gtk_paint_vline (widget->style, widget->window, GTK_WIDGET_STATE (widget), area, widget, "toolbar", - child_space->alloc_y + toolbar->button_maxh * + allocation->y + allocation->height * SPACE_LINE_START / SPACE_LINE_DIVISION, - child_space->alloc_y + toolbar->button_maxh * + allocation->y + allocation->height * SPACE_LINE_END / SPACE_LINE_DIVISION, - child_space->alloc_x + - (space_size - - widget->style->xthickness) / 2); - else + allocation->x + (space_size-widget->style->xthickness)/2); + else if (toolbar->orientation == GTK_ORIENTATION_VERTICAL) gtk_paint_hline (widget->style, widget->window, GTK_WIDGET_STATE (widget), area, widget, "toolbar", - child_space->alloc_x + toolbar->button_maxw * + allocation->x + allocation->width * SPACE_LINE_START / SPACE_LINE_DIVISION, - child_space->alloc_x + toolbar->button_maxw * + allocation->x + allocation->width * SPACE_LINE_END / SPACE_LINE_DIVISION, - child_space->alloc_y + - (space_size - - widget->style->ythickness) / 2); + allocation->y + (space_size-widget->style->ythickness)/2); +} + +static void +gtk_toolbar_realize (GtkWidget *widget) +{ + GtkToolbar *toolbar = GTK_TOOLBAR (widget); + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + GdkWindowAttr attributes; + gint attributes_mask; + gint border_width; + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + + border_width = GTK_CONTAINER (widget)->border_width; + + attributes.wclass = GDK_INPUT_ONLY; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = widget->allocation.x + border_width; + attributes.y = widget->allocation.y + border_width; + attributes.width = widget->allocation.width - border_width * 2; + attributes.height = widget->allocation.height - border_width * 2; + attributes.event_mask = gtk_widget_get_events (widget); + /* FIXME: does GDK_EXPOSURE_MASK make sense for an input-only window? + * If it doesn't, then it should be removed here and in gtkbutton.c, + * gtkmenuitem.c, and maybe other places + */ + attributes.event_mask |= (GDK_EXPOSURE_MASK | + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_ENTER_NOTIFY_MASK | + GDK_LEAVE_NOTIFY_MASK); + + attributes_mask = GDK_WA_X | GDK_WA_Y; + + widget->window = gtk_widget_get_parent_window (widget); + g_object_ref (widget->window); + + priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + gdk_window_set_user_data (priv->event_window, toolbar); +} + +static void +gtk_toolbar_unrealize (GtkWidget *widget) +{ + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (widget); + + if (priv->drag_highlight) + { + gdk_window_set_user_data (priv->drag_highlight, NULL); + gdk_window_destroy (priv->drag_highlight); + priv->drag_highlight = NULL; + } + + if (priv->event_window) + { + gdk_window_set_user_data (priv->event_window, NULL); + gdk_window_destroy (priv->event_window); + priv->event_window = NULL; + } + + if (GTK_WIDGET_CLASS (parent_class)->unrealize) + (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); } static gint gtk_toolbar_expose (GtkWidget *widget, GdkEventExpose *event) { - GtkToolbar *toolbar; - GList *children; - GtkToolbarChild *child; + GtkToolbar *toolbar = GTK_TOOLBAR (widget); + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + GList *items; gint border_width; - g_return_val_if_fail (GTK_IS_TOOLBAR (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - border_width = GTK_CONTAINER (widget)->border_width; if (GTK_WIDGET_DRAWABLE (widget)) { GtkShadowType shadow_type; - toolbar = GTK_TOOLBAR (widget); - gtk_widget_style_get (widget, "shadow_type", &shadow_type, NULL); gtk_paint_box (widget->style, @@ -559,27 +764,31 @@ gtk_toolbar_expose (GtkWidget *widg GTK_WIDGET_STATE (widget), shadow_type, &event->area, widget, "toolbar", - widget->allocation.x + border_width, - widget->allocation.y + border_width, + border_width + widget->allocation.x, + border_width + widget->allocation.y, widget->allocation.width - 2 * border_width, widget->allocation.height - 2 * border_width); - - for (children = toolbar->children; children; children = children->next) - { - child = children->data; + } - if (child->type == GTK_TOOLBAR_CHILD_SPACE) - { - if (get_space_style (toolbar) == GTK_TOOLBAR_SPACE_LINE) - gtk_toolbar_paint_space_line (widget, &event->area, child); - } - else - gtk_container_propagate_expose (GTK_CONTAINER (widget), - child->widget, - event); - } + items = priv->items; + while (items) + { + GtkToolItem *item = GTK_TOOL_ITEM (items->data); + + if (GTK_BIN (item)->child) + gtk_container_propagate_expose (GTK_CONTAINER (widget), + GTK_WIDGET (item), + event); + else if (GTK_WIDGET_MAPPED (item) && get_space_style (toolbar) == GTK_TOOLBAR_SPACE_LINE) + gtk_toolbar_paint_space_line (widget, &event->area, item); + + items = items->next; } + gtk_container_propagate_expose (GTK_CONTAINER (widget), + priv->arrow_button, + event); + return FALSE; } @@ -587,358 +796,1614 @@ static void gtk_toolbar_size_request (GtkWidget *widget, GtkRequisition *requisition) { - GtkToolbar *toolbar; - GList *children; - GtkToolbarChild *child; - gint nbuttons; - gint button_maxw, button_maxh; - gint widget_maxw, widget_maxh; - GtkRequisition child_requisition; - gint space_size; + GtkToolbar *toolbar = GTK_TOOLBAR (widget); + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + gint space_size = get_space_size (toolbar); + GList *list; + gint max_child_height; + gint max_child_width; + gint max_homogeneous_child_width; + gint max_homogeneous_child_height; + gint homogeneous_size; + gint long_req; + gint pack_end_size; + gint pack_front_size; gint ipadding; - - g_return_if_fail (GTK_IS_TOOLBAR (widget)); - g_return_if_fail (requisition != NULL); + GtkRequisition arrow_requisition; - toolbar = GTK_TOOLBAR (widget); + max_homogeneous_child_width = 0; + max_homogeneous_child_height = 0; + max_child_width = 0; + max_child_height = 0; + for (list = priv->items; list != NULL; list = list->next) + { + GtkRequisition requisition; + GtkToolItem *item = list->data; + + if (!toolbar_item_visible (toolbar, item)) + continue; - requisition->width = GTK_CONTAINER (toolbar)->border_width * 2; - requisition->height = GTK_CONTAINER (toolbar)->border_width * 2; - nbuttons = 0; - button_maxw = 0; - button_maxh = 0; - widget_maxw = 0; - widget_maxh = 0; + gtk_widget_size_request (GTK_WIDGET (item), &requisition); + + max_child_width = MAX (max_child_width, requisition.width); + max_child_height = MAX (max_child_height, requisition.height); - space_size = get_space_size (toolbar); + if (GTK_TOOL_ITEM (item)->homogeneous && GTK_BIN (item)->child) + { + max_homogeneous_child_width = MAX (max_homogeneous_child_width, requisition.width); + max_homogeneous_child_height = MAX (max_homogeneous_child_height, requisition.height); + } + } - for (children = toolbar->children; children; children = children->next) + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + homogeneous_size = max_homogeneous_child_width; + else + homogeneous_size = max_homogeneous_child_height; + + pack_end_size = 0; + pack_front_size = 0; + for (list = priv->items; list != NULL; list = list->next) { - child = children->data; - - switch (child->type) + GtkToolItem *item = list->data; + guint size; + + if (!toolbar_item_visible (toolbar, item)) + continue; + + if (!GTK_BIN (item)->child) + { + size = space_size; + } + else if (item->homogeneous) { - case GTK_TOOLBAR_CHILD_SPACE: + size = homogeneous_size; + } + else + { + GtkRequisition requisition; + + gtk_widget_size_request (GTK_WIDGET (item), &requisition); + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) - requisition->width += space_size; + size = requisition.width; else - requisition->height += space_size; - - break; - - case GTK_TOOLBAR_CHILD_BUTTON: - case GTK_TOOLBAR_CHILD_RADIOBUTTON: - case GTK_TOOLBAR_CHILD_TOGGLEBUTTON: - if (GTK_WIDGET_VISIBLE (child->widget)) - { - gtk_widget_size_request (child->widget, &child_requisition); - - nbuttons++; - button_maxw = MAX (button_maxw, child_requisition.width); - button_maxh = MAX (button_maxh, child_requisition.height); - } - - break; - - case GTK_TOOLBAR_CHILD_WIDGET: - if (GTK_WIDGET_VISIBLE (child->widget)) - { - gtk_widget_size_request (child->widget, &child_requisition); - - widget_maxw = MAX (widget_maxw, child_requisition.width); - widget_maxh = MAX (widget_maxh, child_requisition.height); - - if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) - requisition->width += child_requisition.width; - else - requisition->height += child_requisition.height; - } - - break; - - default: - g_assert_not_reached (); + size = requisition.height; } + + if (item->pack_end) + pack_end_size += size; + else + pack_front_size += size; } - - if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + + long_req = pack_end_size; + + if (priv->show_arrow) { - requisition->width += nbuttons * button_maxw; - requisition->height += MAX (button_maxh, widget_maxh); + gtk_widget_size_request (priv->arrow_button, &arrow_requisition); + + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + long_req = pack_end_size + MIN (pack_front_size, arrow_requisition.width); + else + long_req = pack_end_size + MIN (pack_front_size, arrow_requisition.height); } else { - requisition->width += MAX (button_maxw, widget_maxw); - requisition->height += nbuttons * button_maxh; + arrow_requisition.height = 0; + arrow_requisition.width = 0; + + long_req = pack_end_size + pack_front_size; } - + + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + requisition->width = long_req; + requisition->height = MAX (max_child_height, arrow_requisition.height); + } + else + { + requisition->height = long_req; + requisition->width = MAX (max_child_width, arrow_requisition.width); + } + /* Extra spacing */ gtk_widget_style_get (widget, "internal_padding", &ipadding, NULL); + + requisition->width += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width); + requisition->height += 2 * (ipadding + GTK_CONTAINER (toolbar)->border_width); + + toolbar->button_maxw = max_homogeneous_child_width; + toolbar->button_maxh = max_homogeneous_child_height; +} + +static void +fixup_allocation_for_rtl (gint total_size, + GtkAllocation *allocation) +{ + allocation->x += (total_size - (2 * allocation->x + allocation->width)); +} + +static void +fixup_allocation_for_vertical (GtkAllocation *allocation) +{ + gint tmp; - requisition->width += 2 * ipadding; - requisition->height += 2 * ipadding; + tmp = allocation->x; + allocation->x = allocation->y; + allocation->y = tmp; + + tmp = allocation->width; + allocation->width = allocation->height; + allocation->height = tmp; +} + +static gint +get_item_size (GtkToolbar *toolbar, + GtkWidget *child) +{ + GtkRequisition requisition; + GtkToolItem *item = GTK_TOOL_ITEM (child); + + if (!GTK_BIN (item)->child) + return get_space_size (toolbar); + + gtk_widget_get_child_requisition (child, &requisition); - toolbar->button_maxw = button_maxw; - toolbar->button_maxh = button_maxh; + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + if (item->homogeneous) + return toolbar->button_maxw; + else + return requisition.width; + } + else + { + if (item->homogeneous) + return toolbar->button_maxh; + else + return requisition.height; + } } static void gtk_toolbar_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { - GtkToolbar *toolbar; - GList *children; - GtkToolbarChild *child; - GtkToolbarChildSpace *child_space; - GtkAllocation alloc; - GtkRequisition child_requisition; - gint x_border_width, y_border_width; + GtkToolbar *toolbar = GTK_TOOLBAR (widget); + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); gint space_size; - gint ipadding; - GtkTextDirection direction; - gint ltr_x = 0; /* Quiet GCC */ - - g_return_if_fail (GTK_IS_TOOLBAR (widget)); - g_return_if_fail (allocation != NULL); + GtkAllocation *allocations; + GtkAllocation arrow_allocation; + gint arrow_size; + gint size, pos, short_size; + GList *list; + gint i; + gboolean need_arrow; + gint n_expand_items; + gint border_width, internal_padding; + gint available_size; + gint n_items; + gint needed_size; + GList *items; + GtkRequisition arrow_requisition; - toolbar = GTK_TOOLBAR (widget); widget->allocation = *allocation; - - direction = gtk_widget_get_direction (widget); - x_border_width = GTK_CONTAINER (toolbar)->border_width; - y_border_width = GTK_CONTAINER (toolbar)->border_width; + space_size = get_space_size (toolbar); - gtk_widget_style_get (widget, "internal_padding", &ipadding, NULL); + border_width = GTK_CONTAINER (toolbar)->border_width; + + if (GTK_WIDGET_REALIZED (widget)) + { + gdk_window_move_resize (priv->event_window, + allocation->x + border_width, + allocation->y + border_width, + allocation->width - border_width * 2, + allocation->height - border_width * 2); + } + + gtk_widget_style_get (widget, "internal_padding", &internal_padding, NULL); + border_width += internal_padding; - x_border_width += ipadding; - y_border_width += ipadding; + gtk_widget_get_child_requisition (GTK_WIDGET (priv->arrow_button), + &arrow_requisition); if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) - ltr_x = allocation->x + x_border_width; + { + available_size = size = allocation->width - 2 * border_width; + short_size = allocation->height - 2 * border_width; + arrow_size = arrow_requisition.width; + } else - alloc.y = allocation->y + y_border_width; + { + available_size = size = allocation->height - 2 * border_width; + short_size = allocation->width - 2 * border_width; + arrow_size = arrow_requisition.height; + } - space_size = get_space_size (toolbar); - - for (children = toolbar->children; children; children = children->next) + n_items = g_list_length (priv->items); + allocations = g_new0 (GtkAllocation, n_items); + + needed_size = 0; + for (list = priv->items; list != NULL; list = list->next) { - child = children->data; + GtkToolItem *item = list->data; + + if (toolbar_item_visible (toolbar, item)) + needed_size += get_item_size (toolbar, GTK_WIDGET (item)); + } - switch (child->type) - { - case GTK_TOOLBAR_CHILD_SPACE: + need_arrow = (needed_size > available_size) && priv->show_arrow; - child_space = (GtkToolbarChildSpace *) child; + if (need_arrow) + size = available_size - arrow_size; + else + size = available_size; - if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) - { - if (direction == GTK_TEXT_DIR_LTR) - child_space->alloc_x = ltr_x; - else - child_space->alloc_x = allocation->width - ltr_x - space_size; - child_space->alloc_y = allocation->y + (allocation->height - toolbar->button_maxh) / 2; - ltr_x += space_size; - } - else + items = g_list_copy (priv->items); + + /* calculate widths of pack end items */ + items = g_list_reverse (items); + for (list = items, i = 0; list != NULL; list = list->next, ++i) + { + GtkToolItem *item = list->data; + GtkAllocation *allocation = &(allocations[n_items - i - 1]); + gint item_size; + + if (!item->pack_end || !toolbar_item_visible (toolbar, item)) + continue; + + item_size = get_item_size (toolbar, GTK_WIDGET (item)); + if (item_size <= size) + { + size -= item_size; + allocation->width = item_size; + item->overflow_item = FALSE; + } + else + { + while (list) { - child_space->alloc_x = allocation->x + (allocation->width - toolbar->button_maxw) / 2; - child_space->alloc_y = alloc.y; - alloc.y += space_size; + item = list->data; + if (item->pack_end) + item->overflow_item = TRUE; + + list = list->next; } - break; + } + } + items = g_list_reverse (items); - case GTK_TOOLBAR_CHILD_BUTTON: - case GTK_TOOLBAR_CHILD_RADIOBUTTON: - case GTK_TOOLBAR_CHILD_TOGGLEBUTTON: - if (!GTK_WIDGET_VISIBLE (child->widget)) - break; + /* calculate widths of pack front items */ + for (list = items, i = 0; list != NULL; list = list->next, ++i) + { + GtkToolItem *item = list->data; + gint item_size; - alloc.width = toolbar->button_maxw; - alloc.height = toolbar->button_maxh; + if (item->pack_end || !toolbar_item_visible (toolbar, item)) + continue; - if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + item_size = get_item_size (toolbar, GTK_WIDGET (item)); + if (item_size <= size) + { + size -= item_size; + allocations[i].width = item_size; + item->overflow_item = FALSE; + } + else + { + while (list) { - if (direction == GTK_TEXT_DIR_LTR) - alloc.x = ltr_x; - else - alloc.x = allocation->width - ltr_x - alloc.width; - alloc.y = allocation->y + (allocation->height - toolbar->button_maxh) / 2; + item = list->data; + if (!item->pack_end) + item->overflow_item = TRUE; + list = list->next; } - else - alloc.x = allocation->x + (allocation->width - toolbar->button_maxw) / 2; + break; + } + } + + if (need_arrow) + { + arrow_allocation.width = arrow_size; + arrow_allocation.height = short_size; + } + + /* expand expandable items */ + n_expand_items = 0; + for (list = priv->items; list != NULL; list = list->next) + { + GtkToolItem *item = list->data; + + if (toolbar_item_visible (toolbar, item) && item->expand && + !item->overflow_item && GTK_BIN (item)->child) + { + n_expand_items++; + } + } + + for (list = items, i = 0; list != NULL; list = list->next, ++i) + { + GtkToolItem *item = list->data; + + if (toolbar_item_visible (toolbar, item) && item->expand && + !item->overflow_item && GTK_BIN (item)->child) + { + gint extra = size / n_expand_items; + if (size % n_expand_items != 0) + extra++; + + allocations[i].width += extra; + size -= extra; + n_expand_items--; + } + } + + g_assert (n_expand_items == 0); + + /* position pack front items */ + pos = border_width; + for (list = items, i = 0; list != NULL; list = list->next, ++i) + { + GtkToolItem *item = list->data; + + if (toolbar_item_visible (toolbar, item) && !item->overflow_item && !item->pack_end) + { + allocations[i].x = pos; + allocations[i].y = border_width; + allocations[i].height = short_size; + + pos += allocations[i].width; + } + } + + /* position pack end items */ + pos = available_size + border_width; + items = g_list_reverse (items); + for (list = items, i = 0; list != NULL; list = list->next, ++i) + { + GtkToolItem *item = list->data; + + if (toolbar_item_visible (toolbar, item) && !item->overflow_item && item->pack_end) + { + GtkAllocation *allocation = &(allocations[n_items - i - 1]); + + allocation->x = pos - allocation->width; + allocation->y = border_width; + allocation->height = short_size; - gtk_widget_size_allocate (child->widget, &alloc); + pos -= allocation->width; + } + } + items = g_list_reverse (items); - if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) - ltr_x += toolbar->button_maxw; - else - alloc.y += toolbar->button_maxh; + /* position arrow */ + if (need_arrow) + { + arrow_allocation.x = pos - arrow_allocation.width; + arrow_allocation.y = border_width; + } + + /* fix up allocations in the vertical or RTL cases */ + if (toolbar->orientation == GTK_ORIENTATION_VERTICAL) + { + for (i = 0; i < n_items; ++i) + fixup_allocation_for_vertical (&(allocations[i])); + + if (need_arrow) + fixup_allocation_for_vertical (&arrow_allocation); + } + else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL) + { + for (i = 0; i < n_items; ++i) + fixup_allocation_for_rtl (available_size, &(allocations[i])); + if (need_arrow) + fixup_allocation_for_rtl (available_size, &arrow_allocation); + } + + /* translate the items by allocation->(x,y) */ + for (i = 0; i < n_items; ++i) + { + allocations[i].x += allocation->x; + allocations[i].y += allocation->y; + } + + if (need_arrow) + { + arrow_allocation.x += allocation->x; + arrow_allocation.y += allocation->y; + } + + /* finally allocate the items */ + for (list = items, i = 0; list != NULL; list = list->next, i++) + { + GtkToolItem *item = list->data; + + if (toolbar_item_visible (toolbar, item) && !item->overflow_item) + { + gtk_widget_size_allocate (GTK_WIDGET (item), &(allocations[i])); + gtk_widget_set_child_visible (GTK_WIDGET (item), TRUE); + } + else + { + gtk_widget_set_child_visible (GTK_WIDGET (item), FALSE); + } + } + + if (need_arrow) + { + gtk_widget_size_allocate (GTK_WIDGET (priv->arrow_button), + &arrow_allocation); + gtk_widget_show (GTK_WIDGET (priv->arrow_button)); + } + else + { + gtk_widget_hide (GTK_WIDGET (priv->arrow_button)); + } + + g_free (allocations); + g_list_free (items); +} + +static void +gtk_toolbar_style_set (GtkWidget *widget, + GtkStyle *prev_style) +{ + if (GTK_WIDGET_REALIZED (widget)) + gtk_style_set_background (widget->style, widget->window, widget->state); + + if (prev_style) + gtk_toolbar_update_button_relief (GTK_TOOLBAR (widget)); +} + +static void +gtk_toolbar_direction_changed (GtkWidget *widget, + GtkTextDirection previous_dir) +{ + GtkToolbar *toolbar = GTK_TOOLBAR (widget); + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + if (toolbar->orientation == GTK_ORIENTATION_VERTICAL) + { + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) + gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE); + else + gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_LEFT, GTK_SHADOW_NONE); + } + + GTK_WIDGET_CLASS (parent_class)->direction_changed (widget, previous_dir); +} + +static GList * +gtk_toolbar_list_children_in_focus_order (GtkToolbar *toolbar, + GtkDirectionType dir) +{ + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + GList *result = NULL; + GList *list; + + for (list = priv->items; list != NULL; list = list->next) + { + GtkToolItem *item = list->data; + if (!item->pack_end) + result = g_list_prepend (result, item); + } + + for (list = priv->items; list != NULL; list = list->next) + { + GtkToolItem *item = list->data; + + if (item->pack_end) + result = g_list_prepend (result, item); + } + + result = g_list_prepend (result, priv->arrow_button); + + if (dir == GTK_DIR_RIGHT || dir == GTK_DIR_DOWN || dir == GTK_DIR_TAB_FORWARD) + result = g_list_reverse (result); + + if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_RTL) + result = g_list_reverse (result); + + return result; +} + +static gboolean +gtk_toolbar_move_focus (GtkToolbar *toolbar, + GtkDirectionType dir) +{ + GList *list; + gboolean try_focus = FALSE; + GList *children = gtk_toolbar_list_children_in_focus_order (toolbar, dir); + + for (list = children; list != NULL; list = list->next) + { + GtkWidget *child = list->data; + + if (try_focus && GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, dir)) + break; + + if (child == GTK_CONTAINER (toolbar)->focus_child) + try_focus = TRUE; + } + + g_list_free (children); + + return TRUE; +} + +static gboolean +gtk_toolbar_focus_home (GtkToolbar *toolbar) +{ + GList *children, *list; + GtkTextDirection direction = gtk_widget_get_direction (GTK_WIDGET (toolbar)); + + if (direction == GTK_TEXT_DIR_RTL) + children = gtk_toolbar_list_children_in_focus_order (toolbar, GTK_DIR_LEFT); + else + children = gtk_toolbar_list_children_in_focus_order (toolbar, GTK_DIR_RIGHT); + + for (list = children; list != NULL; list = list->next) + { + GtkWidget *child = list->data; + + if (GTK_CONTAINER (toolbar)->focus_child == child) + break; + + if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, GTK_DIR_RIGHT)) + break; + } + + g_list_free (children); + + return TRUE; +} + +static gboolean +gtk_toolbar_focus_end (GtkToolbar *toolbar) +{ + GList *children, *list; + GtkTextDirection direction = gtk_widget_get_direction (GTK_WIDGET (toolbar)); + + if (direction == GTK_TEXT_DIR_RTL) + children = gtk_toolbar_list_children_in_focus_order (toolbar, GTK_DIR_RIGHT); + else + children = gtk_toolbar_list_children_in_focus_order (toolbar, GTK_DIR_LEFT); + + for (list = children; list != NULL; list = list->next) + { + GtkWidget *child = list->data; + + if (GTK_CONTAINER (toolbar)->focus_child == child) + break; + + if (GTK_WIDGET_MAPPED (child) && gtk_widget_child_focus (child, GTK_DIR_RIGHT)) + break; + } + + g_list_free (children); + + return TRUE; +} + +static gboolean +gtk_toolbar_focus (GtkWidget *widget, + GtkDirectionType dir) +{ + GtkToolbar *toolbar = GTK_TOOLBAR (widget); + GList *children, *list; + gboolean retval = FALSE; + + if (GTK_CONTAINER (widget)->focus_child) + return FALSE; + + children = gtk_toolbar_list_children_in_focus_order (toolbar, dir); + + for (list = children; list != NULL; list = list->next) + { + GtkWidget *child = list->data; + + if (GTK_WIDGET_MAPPED (child)) + { + retval = gtk_widget_child_focus (child, dir); break; + } + } + + g_list_free (children); + + return retval; +} + +static void +style_change_notify (GtkToolbar *toolbar) +{ + if (!toolbar->style_set) + { + /* pretend it was set, then unset, thus reverting to new default */ + toolbar->style_set = TRUE; + gtk_toolbar_unset_style (toolbar); + } +} + +static void +icon_size_change_notify (GtkToolbar *toolbar) +{ + if (!toolbar->icon_size_set) + { + /* pretend it was set, then unset, thus reverting to new default */ + toolbar->icon_size_set = TRUE; + gtk_toolbar_unset_icon_size (toolbar); + } +} - case GTK_TOOLBAR_CHILD_WIDGET: - if (!GTK_WIDGET_VISIBLE (child->widget)) - break; +static GtkSettings * +toolbar_get_settings (GtkToolbar *toolbar) +{ + return g_object_get_data (G_OBJECT (toolbar), "gtk-toolbar-settings"); +} + +static void +gtk_toolbar_screen_changed (GtkWidget *widget, + GdkScreen *previous_screen) +{ + GtkToolbar *toolbar = GTK_TOOLBAR (widget); + GtkSettings *old_settings = toolbar_get_settings (toolbar); + GtkSettings *settings; + + if (gtk_widget_has_screen (GTK_WIDGET (toolbar))) + settings = gtk_widget_get_settings (GTK_WIDGET (toolbar)); + else + settings = NULL; + + if (settings == old_settings) + return; + + if (old_settings) + { + g_signal_handler_disconnect (old_settings, toolbar->style_set_connection); + g_signal_handler_disconnect (old_settings, toolbar->icon_size_connection); + + g_object_unref (old_settings); + } + + if (settings) + { + toolbar->style_set_connection = + g_signal_connect_swapped (settings, + "notify::gtk-toolbar-style", + G_CALLBACK (style_change_notify), + toolbar); + toolbar->icon_size_connection = + g_signal_connect_swapped (settings, + "notify::gtk-toolbar-icon-size", + G_CALLBACK (icon_size_change_notify), + toolbar); + + g_object_ref (settings); + g_object_set_data (G_OBJECT (toolbar), "gtk-toolbar-settings", settings); + } + else + g_object_set_data (G_OBJECT (toolbar), "gtk-toolbar-settings", NULL); + + style_change_notify (toolbar); + icon_size_change_notify (toolbar); +} + +static void +find_drop_pos (GtkToolbar *toolbar, + gint x, + gint y, + gint *drop_index, + gint *drop_pos) +{ + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + GtkOrientation orientation; + GtkTextDirection direction; + GList *items; + GtkToolItem *item; + gint border_width, ipadding; + gint best_distance, best_pos, best_index, index; + + orientation = toolbar->orientation; + direction = gtk_widget_get_direction (GTK_WIDGET (toolbar)); + border_width = GTK_CONTAINER (toolbar)->border_width; + gtk_widget_style_get (GTK_WIDGET (toolbar), "internal_padding", + &ipadding, NULL); + border_width += ipadding; + + items = priv->items; + if (!items) + { + *drop_index = 0; + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + if (direction == GTK_TEXT_DIR_LTR) + *drop_pos = border_width; + else + *drop_pos = GTK_WIDGET (toolbar)->allocation.width - border_width; + } + else + { + *drop_pos = border_width; + } + return; + } + + /* initial conditions */ + item = GTK_TOOL_ITEM (items->data); + best_index = 0; + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + if (direction == GTK_TEXT_DIR_LTR) + best_pos = GTK_WIDGET (item)->allocation.x; + else + best_pos = GTK_WIDGET (item)->allocation.x + + GTK_WIDGET (item)->allocation.width; + best_distance = ABS (best_pos - x); + } + else + { + best_pos = GTK_WIDGET (item)->allocation.y; + best_distance = ABS (best_pos - y); + } + + index = 0; + while (items) + { + item = GTK_TOOL_ITEM (items->data); + index++; + if (GTK_WIDGET_DRAWABLE (item) && !item->pack_end) + { + gint pos, distance; + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + if (direction == GTK_TEXT_DIR_LTR) + pos = GTK_WIDGET (item)->allocation.x + + GTK_WIDGET (item)->allocation.width; + else + pos = GTK_WIDGET (item)->allocation.x; + distance = ABS (pos - x); + } + else + { + pos = GTK_WIDGET (item)->allocation.y + + GTK_WIDGET (item)->allocation.height; + distance = ABS (pos - y); + } + if (distance < best_distance) + { + best_index = index; + best_pos = pos; + best_distance = distance; + } + } + items = items->next; + } + *drop_index = best_index; + *drop_pos = best_pos; +} + +static void +gtk_toolbar_drag_leave (GtkWidget *widget, + GdkDragContext *context, + guint time_) +{ + GtkToolbar *toolbar = GTK_TOOLBAR (widget); + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + if (priv->drag_highlight) + { + gdk_window_set_user_data (priv->drag_highlight, NULL); + gdk_window_destroy (priv->drag_highlight); + priv->drag_highlight = NULL; + } + + priv->drop_index = -1; +} + +static gboolean +gtk_toolbar_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time_) +{ + GtkToolbar *toolbar = GTK_TOOLBAR (widget); + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + gint new_index, new_pos; + + find_drop_pos(toolbar, x, y, &new_index, &new_pos); + + if (!priv->drag_highlight) + { + GdkWindowAttr attributes; + guint attributes_mask; + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK; + attributes.width = 1; + attributes.height = 1; + attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP; + priv->drag_highlight = gdk_window_new (widget->window, + &attributes, attributes_mask); + gdk_window_set_user_data (priv->drag_highlight, widget); + gdk_window_set_background (priv->drag_highlight, + &widget->style->fg[widget->state]); + } + + if (priv->drop_index < 0 || + priv->drop_index != new_index) + { + gint border_width = GTK_CONTAINER (toolbar)->border_width; + priv->drop_index = new_index; + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + gdk_window_move_resize (priv->drag_highlight, + widget->allocation.x + new_pos - 1, + widget->allocation.y + border_width, + 2, widget->allocation.height-border_width*2); + } + else + { + gdk_window_move_resize (priv->drag_highlight, + widget->allocation.x + border_width, + widget->allocation.y + new_pos - 1, + widget->allocation.width-border_width*2, 2); + } + } + + gdk_window_show (priv->drag_highlight); + + gdk_drag_status (context, context->suggested_action, time_); + + return TRUE; +} + +static void +gtk_toolbar_get_child_property (GtkContainer *container, + GtkWidget *child, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GtkToolItem *item = GTK_TOOL_ITEM (child); + + switch (property_id) + { + case CHILD_PROP_PACK_END: + g_value_set_boolean (value, item->pack_end); + break; + + case CHILD_PROP_HOMOGENEOUS: + g_value_set_boolean (value, item->homogeneous); + break; + + case CHILD_PROP_EXPAND: + g_value_set_boolean (value, item->expand); + break; + + default: + GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec); + break; + } +} + +static void +gtk_toolbar_set_child_property (GtkContainer *container, + GtkWidget *child, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) + { + case CHILD_PROP_PACK_END: + gtk_tool_item_set_pack_end (GTK_TOOL_ITEM (child), g_value_get_boolean (value)); + break; + + case CHILD_PROP_HOMOGENEOUS: + gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (child), g_value_get_boolean (value)); + break; + + case CHILD_PROP_EXPAND: + gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (child), g_value_get_boolean (value)); + break; + + default: + GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec); + break; + } +} + +static void +gtk_toolbar_add (GtkContainer *container, + GtkWidget *widget) +{ + GtkToolbar *toolbar; + + g_return_if_fail (GTK_IS_TOOLBAR (container)); + g_return_if_fail (widget != NULL); + + toolbar = GTK_TOOLBAR (container); + + if (GTK_IS_TOOL_ITEM (widget)) + gtk_toolbar_append (toolbar, GTK_TOOL_ITEM (widget)); + else + gtk_toolbar_append_widget (toolbar, widget, NULL, NULL); +} + +static void +gtk_toolbar_remove (GtkContainer *container, + GtkWidget *widget) +{ + GtkToolbar *toolbar; + GtkToolItem *item = NULL; + + g_return_if_fail (GTK_IS_TOOLBAR (container)); + + toolbar = GTK_TOOLBAR (container); + + if (GTK_IS_TOOL_ITEM (widget)) + { + item = GTK_TOOL_ITEM (widget); + } + else + { + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + GList *list; + + for (list = priv->items; list != NULL; list = list->next) + { + if (GTK_BIN (list->data)->child == widget) + { + item = list->data; + break; + } + } + } + + g_return_if_fail (item != NULL); + + gtk_toolbar_remove_tool_item (GTK_TOOLBAR (container), item); +} + +static void +gtk_toolbar_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + GtkToolbar *toolbar = GTK_TOOLBAR (container); + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + GList *items; + + g_return_if_fail (callback != NULL); + + items = priv->items; + + while (items) + { + GtkToolItem *item = GTK_TOOL_ITEM (items->data); + + items = items->next; + + (*callback) (GTK_WIDGET (item), callback_data); + } + + if (include_internals) + (* callback) (priv->arrow_button, callback_data); +} + +static GType +gtk_toolbar_child_type (GtkContainer *container) +{ + return GTK_TYPE_TOOL_ITEM; +} + +static void +gtk_toolbar_reconfigured (GtkToolbar *toolbar) +{ + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + GList *items; + + items = priv->items; + while (items) + { + GtkToolItem *item = GTK_TOOL_ITEM (items->data); + + gtk_tool_item_toolbar_reconfigured (item); + + items = items->next; + } +} + +static void +gtk_toolbar_real_orientation_changed (GtkToolbar *toolbar, + GtkOrientation orientation) +{ + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + if (toolbar->orientation != orientation) + { + toolbar->orientation = orientation; + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_DOWN, GTK_SHADOW_NONE); + else if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR) + gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_RIGHT, GTK_SHADOW_NONE); + else + gtk_arrow_set (GTK_ARROW (priv->arrow), GTK_ARROW_LEFT, GTK_SHADOW_NONE); + + gtk_toolbar_reconfigured (toolbar); + + gtk_widget_queue_resize (GTK_WIDGET (toolbar)); + g_object_notify (G_OBJECT (toolbar), "orientation"); + } +} + +static void +gtk_toolbar_real_style_changed (GtkToolbar *toolbar, + GtkToolbarStyle style) +{ + if (toolbar->style != style) + { + toolbar->style = style; + + gtk_toolbar_reconfigured (toolbar); + + gtk_widget_queue_resize (GTK_WIDGET (toolbar)); + g_object_notify (G_OBJECT (toolbar), "toolbar_style"); + } +} + +static void +menu_position_func (GtkMenu *menu, + gint *x, + gint *y, + gboolean *push_in, + gpointer user_data) +{ + GtkToolbar *toolbar = GTK_TOOLBAR (user_data); + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + GtkRequisition req; + GtkRequisition menu_req; + + gdk_window_get_origin (GTK_BUTTON (priv->arrow_button)->event_window, x, y); + gtk_widget_size_request (priv->arrow_button, &req); + gtk_widget_size_request (GTK_WIDGET (menu), &menu_req); + + if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) + { + *y += priv->arrow_button->allocation.height; + if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR) + *x += priv->arrow_button->allocation.width - req.width; + else + *x += req.width - menu_req.width; + } + else + { + if (gtk_widget_get_direction (GTK_WIDGET (toolbar)) == GTK_TEXT_DIR_LTR) + *x += priv->arrow_button->allocation.width; + else + *x -= menu_req.width; + *y += priv->arrow_button->allocation.height - req.height; + } + + *push_in = TRUE; +} + +static void +menu_deactivated (GtkWidget *menu, + GtkToolbar *toolbar) +{ + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->arrow_button), FALSE); +} + +static void +remove_item (GtkWidget *menu_item, + gpointer data) +{ + gtk_container_remove (GTK_CONTAINER (menu_item->parent), menu_item); +} + +static void +show_menu (GtkToolbar *toolbar, + GdkEventButton *event) +{ + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + GList *list; + + if (priv->menu) + { + gtk_container_foreach (GTK_CONTAINER (priv->menu), remove_item, NULL); + gtk_widget_destroy (GTK_WIDGET (priv->menu)); + } + + priv->menu = GTK_MENU (gtk_menu_new ()); + g_signal_connect (priv->menu, "deactivate", G_CALLBACK (menu_deactivated), toolbar); + + for (list = priv->items; list != NULL; list = list->next) + { + GtkToolItem *item = list->data; + + if (toolbar_item_visible (toolbar, item) && item->overflow_item) + { + GtkWidget *menu_item = gtk_tool_item_retrieve_proxy_menu_item (item); + + if (menu_item) + { + g_assert (GTK_IS_MENU_ITEM (menu_item)); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_item); + } + } + } + + gtk_widget_show_all (GTK_WIDGET (priv->menu)); + + gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL, + menu_position_func, toolbar, + event? event->button : 0, event? event->time : gtk_get_current_event_time()); +} + +static void +gtk_toolbar_arrow_button_clicked (GtkWidget *button, + GtkToolbar *toolbar) +{ + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->arrow_button)) && + (!priv->menu || !GTK_WIDGET_VISIBLE (GTK_WIDGET (priv->menu)))) + { + /* We only get here when the button is clicked with the keybaord, + * because mouse button presses result in the menu being shown. + */ + show_menu (toolbar, NULL); + gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menu), FALSE); + } +} + +static gboolean +gtk_toolbar_arrow_button_press (GtkWidget *button, + GdkEventButton *event, + GtkToolbar *toolbar) +{ + show_menu (toolbar, event); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); + + return TRUE; +} + +static gboolean +gtk_toolbar_button_press (GtkWidget *button, + GdkEventButton *event, + GtkToolbar *toolbar) +{ + if (event->button == 3) + { + g_signal_emit (toolbar, toolbar_signals[POPUP_CONTEXT_MENU], 0, NULL); + return FALSE; + } + + return FALSE; +} + +static void +gtk_toolbar_update_button_relief (GtkToolbar *toolbar) +{ + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + gtk_toolbar_reconfigured (toolbar); + + gtk_button_set_relief (GTK_BUTTON (priv->arrow_button), get_button_relief (toolbar)); +} + +static GtkReliefStyle +get_button_relief (GtkToolbar *toolbar) +{ + GtkReliefStyle button_relief = GTK_RELIEF_NORMAL; + + gtk_widget_ensure_style (GTK_WIDGET (toolbar)); + + gtk_widget_style_get (GTK_WIDGET (toolbar), + "button_relief", &button_relief, + NULL); + + return button_relief; +} + +static gint +get_space_size (GtkToolbar *toolbar) +{ + gint space_size = DEFAULT_SPACE_SIZE; + + gtk_widget_style_get (GTK_WIDGET (toolbar), + "space_size", &space_size, + NULL); + + return space_size; +} + +static GtkToolbarSpaceStyle +get_space_style (GtkToolbar *toolbar) +{ + GtkToolbarSpaceStyle space_style = DEFAULT_SPACE_STYLE; + + gtk_widget_style_get (GTK_WIDGET (toolbar), + "space_style", &space_style, + NULL); + + + return space_style; +} + +static void +gtk_toolbar_use_old_api (GtkToolbar *toolbar) +{ + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + if (priv->api_mode == NEW_API) + g_warning ("mixing deprecated and non-deprecated GtkToolbar API is not allowed"); + else if (priv->api_mode == DONT_KNOW) + priv->api_mode = OLD_API; +} + +static void +gtk_toolbar_use_new_api (GtkToolbar *toolbar) +{ + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + if (priv->api_mode == OLD_API) + g_warning ("mixing deprecated and non-deprecated GtkToolbar API is not allowed"); + else if (priv->api_mode == DONT_KNOW) + priv->api_mode = NEW_API; +} + +static void +gtk_toolbar_insert_tool_item (GtkToolbar *toolbar, + GtkToolItem *item, + gint pos) +{ + GtkToolbarPrivate *priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + priv->items = g_list_insert (priv->items, item, pos); + toolbar->num_children++; + + gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar)); +} + +static void +gtk_toolbar_remove_tool_item (GtkToolbar *toolbar, + GtkToolItem *item) +{ + GtkToolbarPrivate *priv; + GList *tmp; + + g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); + g_return_if_fail (GTK_IS_TOOL_ITEM (item)); + + priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + for (tmp = priv->items; tmp != NULL; tmp = tmp->next) + { + GtkWidget *child = tmp->data; + + if (child == GTK_WIDGET (item)) + { + gboolean was_visible; + + was_visible = GTK_WIDGET_VISIBLE (item); + gtk_widget_unparent (GTK_WIDGET (item)); + + priv->items = g_list_remove_link (priv->items, tmp); + toolbar->num_children--; + + if (was_visible && GTK_WIDGET_VISIBLE (toolbar)) + gtk_widget_queue_resize (GTK_WIDGET (toolbar)); + + break; + } + } +} + +#define apin gtk_toolbar_use_new_api (toolbar) +#define apio gtk_toolbar_use_old_api (toolbar) + +GtkWidget * +gtk_toolbar_new (void) +{ + GtkToolbar *toolbar; + + toolbar = g_object_new (GTK_TYPE_TOOLBAR, NULL); + + return GTK_WIDGET (toolbar); +} + +void +gtk_toolbar_append (GtkToolbar *toolbar, + GtkToolItem *item) +{ + g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); + g_return_if_fail (GTK_IS_TOOL_ITEM (item)); + + apin; + + gtk_toolbar_insert (toolbar, item, toolbar->num_children); +} + +void +gtk_toolbar_prepend (GtkToolbar *toolbar, + GtkToolItem *item) +{ + g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); + g_return_if_fail (GTK_IS_TOOL_ITEM (item)); + + apin; + + gtk_toolbar_insert (toolbar, item, 0); +} + +void +gtk_toolbar_insert (GtkToolbar *toolbar, + GtkToolItem *item, + gint pos) +{ + g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); + g_return_if_fail (GTK_IS_TOOL_ITEM (item)); + + apin; + + gtk_toolbar_insert_tool_item (toolbar, item, pos); +} + +gint +gtk_toolbar_get_item_index (GtkToolbar *toolbar, + GtkToolItem *item) +{ + GtkToolbarPrivate *priv; + + g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1); + g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1); + + apin; + + priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + g_return_val_if_fail (g_list_find (priv->items, item) != NULL, -1); + + return g_list_index (priv->items, item); +} + +void +gtk_toolbar_set_orientation (GtkToolbar *toolbar, + GtkOrientation orientation) +{ + g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); + + g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0, orientation); +} + +GtkOrientation +gtk_toolbar_get_orientation (GtkToolbar *toolbar) +{ + g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL); + + return toolbar->orientation; +} + +void +gtk_toolbar_set_style (GtkToolbar *toolbar, + GtkToolbarStyle style) +{ + g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); + + toolbar->style_set = TRUE; + g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style); +} + +GtkToolbarStyle +gtk_toolbar_get_style (GtkToolbar *toolbar) +{ + g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_TOOLBAR_STYLE); + + return toolbar->style; +} - gtk_widget_get_child_requisition (child->widget, &child_requisition); - - alloc.width = child_requisition.width; - alloc.height = child_requisition.height; +void +gtk_toolbar_unset_style (GtkToolbar *toolbar) +{ + GtkToolbarStyle style; - if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) - { - if (direction == GTK_TEXT_DIR_LTR) - alloc.x = ltr_x; - else - alloc.x = allocation->width - ltr_x - alloc.width; - alloc.y = allocation->y + (allocation->height - child_requisition.height) / 2; - } - else - alloc.x = allocation->x + (allocation->width - child_requisition.width) / 2; + g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); - gtk_widget_size_allocate (child->widget, &alloc); + if (toolbar->style_set) + { + GtkSettings *settings = toolbar_get_settings (toolbar); - if (toolbar->orientation == GTK_ORIENTATION_HORIZONTAL) - ltr_x += child_requisition.width; - else - alloc.y += child_requisition.height; + if (settings) + g_object_get (settings, + "gtk-toolbar-style", &style, + NULL); + else + style = DEFAULT_TOOLBAR_STYLE; - break; + if (style != toolbar->style) + g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style); - default: - g_assert_not_reached (); - } + toolbar->style_set = FALSE; } } -static void -gtk_toolbar_style_set (GtkWidget *widget, - GtkStyle *prev_style) +void +gtk_toolbar_set_tooltips (GtkToolbar *toolbar, + gboolean enable) { - if (prev_style) - gtk_toolbar_update_button_relief (GTK_TOOLBAR (widget)); -} + g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); -static gboolean -gtk_toolbar_focus (GtkWidget *widget, - GtkDirectionType dir) -{ - /* Focus can't go in toolbars */ - - return FALSE; + if (enable) + gtk_tooltips_enable (toolbar->tooltips); + else + gtk_tooltips_disable (toolbar->tooltips); } -static void -child_show_all (GtkWidget *widget) +gboolean +gtk_toolbar_get_tooltips (GtkToolbar *toolbar) { - /* Don't show our own children, since that would - * show labels we may intend to hide in icons-only mode - */ - if (!g_object_get_data (G_OBJECT (widget), - "gtk-toolbar-is-child")) - gtk_widget_show_all (widget); + g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE); + + return toolbar->tooltips->enabled; } -static void -gtk_toolbar_show_all (GtkWidget *widget) +gint +gtk_toolbar_get_n_items (GtkToolbar *toolbar) { - gtk_container_foreach (GTK_CONTAINER (widget), - (GtkCallback) child_show_all, - NULL); - gtk_widget_show (widget); + GtkToolbarPrivate *priv; + + g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), -1); + + apin; + + priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + return g_list_length (priv->items); } -static void -child_hide_all (GtkWidget *widget) +/* + * returns NULL if n is out of range + */ +GtkToolItem * +gtk_toolbar_get_nth_item (GtkToolbar *toolbar, + gint n) { - /* Don't hide our own children, since that would also hide - * widgets that won't be shown again by gtk_toolbar_show_all(). - */ - if (!g_object_get_data (G_OBJECT (widget), - "gtk-toolbar-is-child")) - gtk_widget_hide_all (widget); + GtkToolbarPrivate *priv; + + g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL); + + apin; + + priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + return g_list_nth_data (priv->items, n); } -static void -gtk_toolbar_hide_all (GtkWidget *widget) +void +gtk_toolbar_set_icon_size (GtkToolbar *toolbar, + GtkIconSize icon_size) { - gtk_container_foreach (GTK_CONTAINER (widget), - (GtkCallback) child_hide_all, - NULL); - gtk_widget_hide (widget); + g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); + + toolbar->icon_size_set = TRUE; + + if (toolbar->icon_size == icon_size) + return; + + toolbar->icon_size = icon_size; + + gtk_toolbar_reconfigured (toolbar); + + gtk_widget_queue_resize (GTK_WIDGET (toolbar)); } -static void -gtk_toolbar_add (GtkContainer *container, - GtkWidget *widget) +GtkIconSize +gtk_toolbar_get_icon_size (GtkToolbar *toolbar) { - g_return_if_fail (GTK_IS_TOOLBAR (container)); - g_return_if_fail (widget != NULL); + g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_ICON_SIZE); - gtk_toolbar_append_widget (GTK_TOOLBAR (container), widget, NULL, NULL); + return toolbar->icon_size; } -static void -gtk_toolbar_remove (GtkContainer *container, - GtkWidget *widget) +GtkReliefStyle +gtk_toolbar_get_relief_style (GtkToolbar *toolbar) { - GtkToolbar *toolbar; - GList *children; - GtkToolbarChild *child; + g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_RELIEF_NONE); - g_return_if_fail (GTK_IS_TOOLBAR (container)); - g_return_if_fail (widget != NULL); + return get_button_relief (toolbar); +} - toolbar = GTK_TOOLBAR (container); +void +gtk_toolbar_unset_icon_size (GtkToolbar *toolbar) +{ + GtkIconSize size; - for (children = toolbar->children; children; children = children->next) + g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); + + if (toolbar->icon_size_set) { - child = children->data; + GtkSettings *settings = toolbar_get_settings (toolbar); - if ((child->type != GTK_TOOLBAR_CHILD_SPACE) && (child->widget == widget)) + if (settings) { - gboolean was_visible; + g_object_get (settings, + "gtk-toolbar-icon-size", &size, + NULL); + } + else + size = DEFAULT_ICON_SIZE; - was_visible = GTK_WIDGET_VISIBLE (widget); - gtk_widget_unparent (widget); + if (size != toolbar->icon_size) + gtk_toolbar_set_icon_size (toolbar, size); - toolbar->children = g_list_remove_link (toolbar->children, children); - g_free (child); - g_list_free (children); - toolbar->num_children--; + toolbar->icon_size_set = FALSE; + } +} + +void +gtk_toolbar_set_show_arrow (GtkToolbar *toolbar, + gboolean show_arrow) +{ + GtkToolbarPrivate *priv; + + g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); - if (was_visible && GTK_WIDGET_VISIBLE (container)) - gtk_widget_queue_resize (GTK_WIDGET (container)); + priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + show_arrow = show_arrow != FALSE; - break; - } + if (priv->show_arrow != show_arrow) + { + priv->show_arrow = show_arrow; + + if (!priv->show_arrow) + gtk_widget_hide (priv->arrow_button); + + gtk_widget_queue_resize (GTK_WIDGET (toolbar)); + g_object_notify (G_OBJECT (toolbar), "show_arrow"); } } -static void -gtk_toolbar_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data) +gboolean +gtk_toolbar_get_show_arrow (GtkToolbar *toolbar) { - GtkToolbar *toolbar; - GList *children; - GtkToolbarChild *child; + GtkToolbarPrivate *priv; - g_return_if_fail (GTK_IS_TOOLBAR (container)); - g_return_if_fail (callback != NULL); + g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE); - toolbar = GTK_TOOLBAR (container); + apin; + + priv = GTK_TOOLBAR_GET_PRIVATE (toolbar); + + return priv->show_arrow; +} - for (children = toolbar->children; children; children = children->next) - { - child = children->data; +gint +gtk_toolbar_get_drop_index (GtkToolbar *toolbar, + gint x, + gint y) +{ + gint drop_index, drop_pos; - if (child->type != GTK_TOOLBAR_CHILD_SPACE) - (*callback) (child->widget, callback_data); - } + g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE); + + apin; + + find_drop_pos (toolbar, x, y, &drop_index, &drop_pos); + + return drop_index; } GtkWidget * @@ -973,23 +2438,6 @@ gtk_toolbar_prepend_item (GtkToolbar 0); } -static GtkWidget * -gtk_toolbar_internal_insert_item (GtkToolbar *toolbar, - const char *text, - const char *tooltip_text, - const char *tooltip_private_text, - GtkWidget *icon, - GtkSignalFunc callback, - gpointer user_data, - gint position) -{ - return gtk_toolbar_internal_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON, - NULL, text, - tooltip_text, tooltip_private_text, - icon, callback, user_data, - position); -} - GtkWidget * gtk_toolbar_insert_item (GtkToolbar *toolbar, const char *text, @@ -1000,153 +2448,13 @@ gtk_toolbar_insert_item (GtkToolbar * gpointer user_data, gint position) { - return gtk_toolbar_internal_insert_item (toolbar, - text, tooltip_text, tooltip_private_text, - icon, callback, user_data, - position); -} - -/** - * gtk_toolbar_set_icon_size: - * @toolbar: A #GtkToolbar - * @icon_size: The #GtkIconSize that stock icons in the toolbar shall have. - * - * This function sets the size of stock icons in the toolbar. You - * can call it both before you add the icons and after they've been - * added. The size you set will override user preferences for the default - * icon size. - **/ -void -gtk_toolbar_set_icon_size (GtkToolbar *toolbar, - GtkIconSize icon_size) -{ - GList *children; - GtkToolbarChild *child; - GtkImage *image; - gchar *stock_id; - - g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); - - toolbar->icon_size_set = TRUE; - - if (toolbar->icon_size == icon_size) - return; - - toolbar->icon_size = icon_size; - - for (children = toolbar->children; children; children = children->next) - { - child = children->data; - if ((child->type == GTK_TOOLBAR_CHILD_BUTTON || - child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON || - child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON) && - GTK_IS_IMAGE (child->icon)) - { - image = GTK_IMAGE (child->icon); - if (gtk_image_get_storage_type (image) == GTK_IMAGE_STOCK) - { - gtk_image_get_stock (image, &stock_id, NULL); - stock_id = g_strdup (stock_id); - gtk_image_set_from_stock (image, - stock_id, - icon_size); - g_free (stock_id); - } - } - } - - gtk_widget_queue_resize (GTK_WIDGET (toolbar)); -} - -/** - * gtk_toolbar_get_icon_size: - * @toolbar: a #GtkToolbar - * - * Retrieves the icon size fo the toolbar. See gtk_toolbar_set_icon_size(). - * - * Return value: the current icon size for the icons on the toolbar. - **/ -GtkIconSize -gtk_toolbar_get_icon_size (GtkToolbar *toolbar) -{ - g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_ICON_SIZE); - - return toolbar->icon_size; -} - -/** - * gtk_toolbar_unset_icon_size: - * @toolbar: a #GtkToolbar - * - * Unsets toolbar icon size set with gtk_toolbar_set_icon_size(), so that - * user preferences will be used to determine the icon size. - **/ -void -gtk_toolbar_unset_icon_size (GtkToolbar *toolbar) -{ - GtkIconSize size; - - if (toolbar->icon_size_set) - { - GtkSettings *settings = toolbar_get_settings (toolbar); - - if (settings) - g_object_get (settings, - "gtk-toolbar-icon-size", &size, - NULL); - else - size = DEFAULT_ICON_SIZE; - - if (size != toolbar->icon_size) - gtk_toolbar_set_icon_size (toolbar, size); - - toolbar->icon_size_set = FALSE; - } -} - -static gchar * -elide_underscores (const gchar *original) -{ - gchar *q, *result; - const gchar *p; - gboolean last_underscore; - - q = result = g_malloc (strlen (original) + 1); - last_underscore = FALSE; - - for (p = original; *p; p++) - { - if (!last_underscore && *p == '_') - last_underscore = TRUE; - else - { - last_underscore = FALSE; - *q++ = *p; - } - } - - *q = '\0'; - - return result; + return gtk_toolbar_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON, + NULL, text, + tooltip_text, tooltip_private_text, + icon, callback, user_data, + position); } -/** - * gtk_toolbar_insert_stock: - * @toolbar: A #GtkToolbar - * @stock_id: The id of the stock item you want to insert - * @tooltip_text: The text in the tooltip of the toolbar button - * @tooltip_private_text: The private text of the tooltip - * @callback: The callback called when the toolbar button is clicked. - * @user_data: user data passed to callback - * @position: The position the button shall be inserted at. - * -1 means at the end. - * - * Inserts a stock item at the specified position of the toolbar. If - * @stock_id is not a known stock item ID, it's inserted verbatim, - * except that underscores used to mark mnemonics are removed. - * - * Returns: the inserted widget - */ GtkWidget* gtk_toolbar_insert_stock (GtkToolbar *toolbar, const gchar *stock_id, @@ -1156,38 +2464,13 @@ gtk_toolbar_insert_stock (GtkToolbar gpointer user_data, gint position) { - GtkStockItem item; - GtkWidget *image = NULL; - const gchar *label; - gchar *label_no_mnemonic; - GtkWidget *retval; - - if (gtk_stock_lookup (stock_id, &item)) - { - image = gtk_image_new_from_stock (stock_id, toolbar->icon_size); - label = item.label; - } - else - label = stock_id; - - label_no_mnemonic = elide_underscores (label); - - retval = gtk_toolbar_internal_insert_item (toolbar, - label_no_mnemonic, - tooltip_text, - tooltip_private_text, - image, - callback, - user_data, - position); - - g_free (label_no_mnemonic); - - return retval; + return gtk_toolbar_internal_insert_element (toolbar, GTK_TOOLBAR_CHILD_BUTTON, + NULL, stock_id, + tooltip_text, tooltip_private_text, + NULL, callback, user_data, + position, TRUE); } - - void gtk_toolbar_append_space (GtkToolbar *toolbar) { @@ -1219,62 +2502,32 @@ gtk_toolbar_insert_space (GtkToolbar *to position); } -/** - * gtk_toolbar_remove_space: - * @toolbar: a #GtkToolbar. - * @position: the index of the space to remove. - * - * Removes a space from the specified position. - **/ void gtk_toolbar_remove_space (GtkToolbar *toolbar, - gint position) + gint position) { - GList *children; - GtkToolbarChild *child; - gint i; - + GtkToolItem *item; + g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); + + apio; - i = 0; - for (children = toolbar->children; children; children = children->next) + item = g_list_nth_data (toolbar->children, position); + + if (!item) + { + g_warning ("Toolbar position %d doesn't exist", position); + return; + } + + if (GTK_BIN (item)->child) { - child = children->data; + g_warning ("Toolbar position %d is not a space", position); + } + + gtk_toolbar_remove_tool_item (toolbar, item); +} - if (i == position) - { - if (child->type == GTK_TOOLBAR_CHILD_SPACE) - { - toolbar->children = g_list_remove_link (toolbar->children, children); - g_free (child); - g_list_free (children); - toolbar->num_children--; - - gtk_widget_queue_resize (GTK_WIDGET (toolbar)); - } - else - { - g_warning ("Toolbar position %d is not a space", position); - } - - return; - } - - ++i; - } - - g_warning ("Toolbar position %d doesn't exist", position); -} - -/** - * gtk_toolbar_append_widget: - * @toolbar: a #GtkToolbar. - * @widget: a #GtkWidget to add to the toolbar. - * @tooltip_text: the element's tooltip. - * @tooltip_private_text: used for context-sensitive help about this toolbar element. - * - * Adds a widget to the end of the given toolbar. - **/ void gtk_toolbar_append_widget (GtkToolbar *toolbar, GtkWidget *widget, @@ -1288,15 +2541,6 @@ gtk_toolbar_append_widget (GtkToolbar * toolbar->num_children); } -/** - * gtk_toolbar_prepend_widget: - * @toolbar: a #GtkToolbar. - * @widget: a #GtkWidget to add to the toolbar. - * @tooltip_text: the element's tooltip. - * @tooltip_private_text: used for context-sensitive help about this toolbar element. - * - * Adds a widget to the beginning of the given toolbar. - **/ void gtk_toolbar_prepend_widget (GtkToolbar *toolbar, GtkWidget *widget, @@ -1310,16 +2554,6 @@ gtk_toolbar_prepend_widget (GtkToolbar 0); } -/** - * gtk_toolbar_insert_widget: - * @toolbar: a #GtkToolbar. - * @widget: a #GtkWidget to add to the toolbar. - * @tooltip_text: the element's tooltip. - * @tooltip_private_text: used for context-sensitive help about this toolbar element. - * @position: the number of widgets to insert this widget after. - * - * Inserts a widget in the toolbar at the given position. - **/ void gtk_toolbar_insert_widget (GtkToolbar *toolbar, GtkWidget *widget, @@ -1367,29 +2601,6 @@ gtk_toolbar_prepend_element (GtkToolbar icon, callback, user_data, 0); } -/** - * gtk_toolbar_insert_element: - * @toolbar: a #GtkToolbar. - * @type: a value of type #GtkToolbarChildType that determines what @widget - * will be. - * @widget: a #GtkWidget, or %NULL. - * @text: the element's label. - * @tooltip_text: the element's tooltip. - * @tooltip_private_text: used for context-sensitive help about this toolbar element. - * @icon: a #GtkWidget that provides pictorial representation of the element's function. - * @callback: the function to be executed when the button is pressed. - * @user_data: any data you wish to pass to the callback. - * @position: the number of widgets to insert this element after. - * - * Inserts a new element in the toolbar at the given position. - * - * If @type == %GTK_TOOLBAR_CHILD_WIDGET, @widget is used as the new element. - * If @type == %GTK_TOOLBAR_CHILD_RADIOBUTTON, @widget is used to determine - * the radio group for the new element. In all other cases, @widget must - * be %NULL. - * - * Return value: the new toolbar element as a #GtkWidget. - **/ GtkWidget * gtk_toolbar_insert_element (GtkToolbar *toolbar, GtkToolbarChildType type, @@ -1402,85 +2613,63 @@ gtk_toolbar_insert_element (GtkToolbar gpointer user_data, gint position) { - g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL); - if (type == GTK_TOOLBAR_CHILD_WIDGET) - { - g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - } - else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON) - g_return_val_if_fail (widget == NULL, NULL); - return gtk_toolbar_internal_insert_element (toolbar, type, widget, text, - tooltip_text, tooltip_private_text, - icon, callback, user_data, - position); + tooltip_text, tooltip_private_text, + icon, callback, user_data, position, FALSE); } -static void -set_child_packing_and_visibility(GtkToolbar *toolbar, - GtkToolbarChild *child) +static gchar * +elide_underscores (const gchar *original) { - GtkWidget *box; - gboolean expand; - - box = gtk_bin_get_child (GTK_BIN (child->widget)); - - g_return_if_fail (GTK_IS_BOX (box)); - - if (child->label) - { - expand = (toolbar->style != GTK_TOOLBAR_BOTH); - - gtk_box_set_child_packing (GTK_BOX (box), child->label, - expand, expand, 0, GTK_PACK_END); - - if (toolbar->style != GTK_TOOLBAR_ICONS) - gtk_widget_show (child->label); - else - gtk_widget_hide (child->label); - } + gchar *q, *result; + const gchar *p; + gboolean last_underscore; - if (child->icon) + q = result = g_malloc (strlen (original) + 1); + last_underscore = FALSE; + + for (p = original; *p; p++) { - expand = (toolbar->style != GTK_TOOLBAR_BOTH_HORIZ); - - gtk_box_set_child_packing (GTK_BOX (box), child->icon, - expand, expand, 0, GTK_PACK_END); - - if (toolbar->style != GTK_TOOLBAR_TEXT) - gtk_widget_show (child->icon); + if (!last_underscore && *p == '_') + last_underscore = TRUE; else - gtk_widget_hide (child->icon); + { + last_underscore = FALSE; + *q++ = *p; + } } + + *q = '\0'; + + return result; } static GtkWidget * gtk_toolbar_internal_insert_element (GtkToolbar *toolbar, - GtkToolbarChildType type, - GtkWidget *widget, - const char *text, - const char *tooltip_text, - const char *tooltip_private_text, - GtkWidget *icon, - GtkSignalFunc callback, - gpointer user_data, - gint position) + GtkToolbarChildType type, + GtkWidget *widget, + const char *text, + const char *tooltip_text, + const char *tooltip_private_text, + GtkWidget *icon, + GtkSignalFunc callback, + gpointer user_data, + gint position, + gboolean use_stock) { GtkToolbarChild *child; - GtkWidget *box; - + GtkToolItem *item = NULL; + g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), NULL); + + apio; + if (type == GTK_TOOLBAR_CHILD_WIDGET) - { - g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - } + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); else if (type != GTK_TOOLBAR_CHILD_RADIOBUTTON) g_return_val_if_fail (widget == NULL, NULL); - if (type == GTK_TOOLBAR_CHILD_SPACE) - child = (GtkToolbarChild *) g_new (GtkToolbarChildSpace, 1); - else - child = g_new (GtkToolbarChild, 1); + child = g_new (GtkToolbarChild, 1); child->type = type; child->icon = NULL; @@ -1489,343 +2678,87 @@ gtk_toolbar_internal_insert_element (Gtk switch (type) { case GTK_TOOLBAR_CHILD_SPACE: + item = gtk_separator_tool_item_new (); child->widget = NULL; - ((GtkToolbarChildSpace *) child)->alloc_x = - ((GtkToolbarChildSpace *) child)->alloc_y = 0; break; case GTK_TOOLBAR_CHILD_WIDGET: + item = gtk_tool_item_new (); child->widget = widget; + gtk_container_add (GTK_CONTAINER (item), child->widget); break; case GTK_TOOLBAR_CHILD_BUTTON: - case GTK_TOOLBAR_CHILD_TOGGLEBUTTON: - case GTK_TOOLBAR_CHILD_RADIOBUTTON: - if (type == GTK_TOOLBAR_CHILD_BUTTON) - { - child->widget = gtk_button_new (); - gtk_button_set_relief (GTK_BUTTON (child->widget), get_button_relief (toolbar)); - } - else if (type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON) - { - child->widget = gtk_toggle_button_new (); - gtk_button_set_relief (GTK_BUTTON (child->widget), get_button_relief (toolbar)); - gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child->widget), - FALSE); - } - else - { - child->widget = gtk_radio_button_new (widget - ? gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget)) - : NULL); - gtk_button_set_relief (GTK_BUTTON (child->widget), get_button_relief (toolbar)); - gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (child->widget), FALSE); - } - - GTK_WIDGET_UNSET_FLAGS (child->widget, GTK_CAN_FOCUS); - - if (callback) - g_signal_connect (child->widget, "clicked", - callback, user_data); - - if (toolbar->style == GTK_TOOLBAR_BOTH_HORIZ) - box = gtk_hbox_new (FALSE, 0); - else - box = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (child->widget), box); - gtk_widget_show (box); - - if (text) - { - child->label = gtk_label_new (text); - gtk_container_add (GTK_CONTAINER (box), child->label); - } - - if (icon) - { - child->icon = GTK_WIDGET (icon); - gtk_container_add (GTK_CONTAINER (box), child->icon); - } - - set_child_packing_and_visibility (toolbar, child); - - /* Mark child as ours */ - g_object_set_data (G_OBJECT (child->widget), - "gtk-toolbar-is-child", - GINT_TO_POINTER (TRUE)); - - gtk_widget_show (child->widget); + item = gtk_tool_button_new (); + child->widget = GTK_TOOL_BUTTON (item)->button; break; - - default: - g_assert_not_reached (); - } - - if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text) - gtk_tooltips_set_tip (toolbar->tooltips, child->widget, - tooltip_text, tooltip_private_text); - - toolbar->children = g_list_insert (toolbar->children, child, position); - toolbar->num_children++; - - if (type != GTK_TOOLBAR_CHILD_SPACE) - gtk_widget_set_parent (child->widget, GTK_WIDGET (toolbar)); - else - gtk_widget_queue_resize (GTK_WIDGET (toolbar)); - - return child->widget; -} - -void -gtk_toolbar_set_orientation (GtkToolbar *toolbar, - GtkOrientation orientation) -{ - g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); - - g_signal_emit (toolbar, toolbar_signals[ORIENTATION_CHANGED], 0, orientation); -} - -/** - * gtk_toolbar_get_orientation: - * @toolbar: a #GtkToolbar - * - * Retrieves the current orientation of the toolbar. See - * gtk_toolbar_set_orientation(). - * - * Return value: the orientation - **/ -GtkOrientation -gtk_toolbar_get_orientation (GtkToolbar *toolbar) -{ - g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL); - - return toolbar->orientation; -} - -void -gtk_toolbar_set_style (GtkToolbar *toolbar, - GtkToolbarStyle style) -{ - g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); - - toolbar->style_set = TRUE; - g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style); -} - -/** - * gtk_toolbar_get_style: - * @toolbar: a #GtkToolbar - * - * Retrieves whether the toolbar has text, icons, or both . See - * gtk_toolbar_set_style(). - - * Return value: the current style of @toolbar - **/ -GtkToolbarStyle -gtk_toolbar_get_style (GtkToolbar *toolbar) -{ - g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), DEFAULT_TOOLBAR_STYLE); - - return toolbar->style; -} - -/** - * gtk_toolbar_unset_style: - * @toolbar: a #GtkToolbar - * - * Unsets a toolbar style set with gtk_toolbar_set_style(), so that - * user preferences will be used to determine the toolbar style. - **/ -void -gtk_toolbar_unset_style (GtkToolbar *toolbar) -{ - GtkToolbarStyle style; - - g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); - - if (toolbar->style_set) - { - GtkSettings *settings = toolbar_get_settings (toolbar); - - if (settings) - g_object_get (settings, - "gtk-toolbar-style", &style, - NULL); - else - style = DEFAULT_TOOLBAR_STYLE; - - if (style != toolbar->style) - g_signal_emit (toolbar, toolbar_signals[STYLE_CHANGED], 0, style); - toolbar->style_set = FALSE; - } -} - -void -gtk_toolbar_set_tooltips (GtkToolbar *toolbar, - gboolean enable) -{ - g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); - - if (enable) - gtk_tooltips_enable (toolbar->tooltips); - else - gtk_tooltips_disable (toolbar->tooltips); -} - -/** - * gtk_toolbar_get_tooltips: - * @toolbar: a #GtkToolbar - * - * Retrieves whether tooltips are enabled. See - * gtk_toolbar_set_tooltips(). - * - * Return value: %TRUE if tooltips are enabled - **/ -gboolean -gtk_toolbar_get_tooltips (GtkToolbar *toolbar) -{ - g_return_val_if_fail (GTK_IS_TOOLBAR (toolbar), FALSE); - - return toolbar->tooltips->enabled; -} - -static void -gtk_toolbar_update_button_relief (GtkToolbar *toolbar) -{ - GList *children; - GtkToolbarChild *child; - GtkReliefStyle relief; - - g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); - - relief = get_button_relief (toolbar); - - for (children = toolbar->children; children; children = children->next) - { - child = children->data; - if (child->type == GTK_TOOLBAR_CHILD_BUTTON || - child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON || - child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON) - gtk_button_set_relief (GTK_BUTTON (child->widget), relief); - } -} - -static void -gtk_real_toolbar_orientation_changed (GtkToolbar *toolbar, - GtkOrientation orientation) -{ - g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); + case GTK_TOOLBAR_CHILD_TOGGLEBUTTON: + item = gtk_toggle_tool_button_new (); + child->widget = GTK_TOOL_BUTTON (item)->button; + break; - if (toolbar->orientation != orientation) - { - toolbar->orientation = orientation; - gtk_widget_queue_resize (GTK_WIDGET (toolbar)); - g_object_notify (G_OBJECT (toolbar), "orientation"); + case GTK_TOOLBAR_CHILD_RADIOBUTTON: + item = gtk_radio_tool_button_new (widget + ? gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget)) + : NULL); + child->widget = GTK_TOOL_BUTTON (item)->button; + break; } -} -static void -gtk_real_toolbar_style_changed (GtkToolbar *toolbar, - GtkToolbarStyle style) -{ - GList *children; - GtkToolbarChild *child; - GtkWidget* box; + gtk_widget_show (GTK_WIDGET (item)); - g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); - - if (toolbar->style != style) + if (type == GTK_TOOLBAR_CHILD_BUTTON || + type == GTK_TOOLBAR_CHILD_RADIOBUTTON || + type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON) { - toolbar->style = style; - - for (children = toolbar->children; children; children = children->next) + if (text) { - child = children->data; - - if (child->type == GTK_TOOLBAR_CHILD_BUTTON || - child->type == GTK_TOOLBAR_CHILD_RADIOBUTTON || - child->type == GTK_TOOLBAR_CHILD_TOGGLEBUTTON) - { - box = gtk_bin_get_child (GTK_BIN (child->widget)); - - if (style == GTK_TOOLBAR_BOTH && GTK_IS_HBOX (box)) - { - GtkWidget *vbox; - - vbox = gtk_vbox_new (FALSE, 0); - - if (child->label) - gtk_widget_reparent (child->label, vbox); - if (child->icon) - gtk_widget_reparent (child->icon, vbox); - - gtk_widget_destroy (box); - gtk_container_add (GTK_CONTAINER (child->widget), vbox); - - gtk_widget_show (vbox); - } - else if (style == GTK_TOOLBAR_BOTH_HORIZ && GTK_IS_VBOX (box)) - { - GtkWidget *hbox; - - hbox = gtk_hbox_new (FALSE, 0); + if (use_stock) + { + GtkStockItem stock_item; + gchar *label_text; - if (child->label) - gtk_widget_reparent (child->label, hbox); - if (child->icon) - gtk_widget_reparent (child->icon, hbox); + gtk_tool_button_set_stock_id (GTK_TOOL_BUTTON (item), text); - gtk_widget_destroy (box); - gtk_container_add (GTK_CONTAINER (child->widget), hbox); + gtk_stock_lookup (text, &stock_item); + label_text = elide_underscores (stock_item.label); + child->label = GTK_WIDGET (gtk_label_new (label_text)); + g_free (label_text); + } + else + { + child->label = gtk_label_new (text); + } + gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (item), child->label); + gtk_widget_show (child->label); + } - gtk_widget_show (hbox); - } + if (icon) + { + child->icon = icon; + gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (item), icon); - set_child_packing_and_visibility (toolbar, child); - } + /* Applications depend on the toolbar showing the widget for them */ + gtk_widget_show (GTK_WIDGET (icon)); } - gtk_widget_queue_resize (GTK_WIDGET (toolbar)); - g_object_notify (G_OBJECT (toolbar), "toolbar_style"); + /* + * We need to connect to the button's clicked callback because some + * programs may rely on that the widget in the callback is a GtkButton + */ + if (callback) + g_signal_connect (child->widget, "clicked", + callback, user_data); } -} - - -static GtkReliefStyle -get_button_relief (GtkToolbar *toolbar) -{ - GtkReliefStyle button_relief = GTK_RELIEF_NORMAL; - gtk_widget_ensure_style (GTK_WIDGET (toolbar)); - gtk_widget_style_get (GTK_WIDGET (toolbar), - "button_relief", &button_relief, - NULL); - - return button_relief; -} - -static gint -get_space_size (GtkToolbar *toolbar) -{ - gint space_size = DEFAULT_SPACE_SIZE; - - gtk_widget_style_get (GTK_WIDGET (toolbar), - "space_size", &space_size, - NULL); - - return space_size; -} - -static GtkToolbarSpaceStyle -get_space_style (GtkToolbar *toolbar) -{ - GtkToolbarSpaceStyle space_style = DEFAULT_SPACE_STYLE; - - gtk_widget_style_get (GTK_WIDGET (toolbar), - "space_style", &space_style, - NULL); + if ((type != GTK_TOOLBAR_CHILD_SPACE) && tooltip_text) + gtk_tool_item_set_tooltip (item, toolbar->tooltips, + tooltip_text, tooltip_private_text); + + toolbar->children = g_list_insert (toolbar->children, child, position); + gtk_toolbar_insert_tool_item (toolbar, item, position); - return space_style; + return child->widget; } Index: gtk/gtktoolbar.h =================================================================== RCS file: /cvs/gnome/gtk+/gtk/gtktoolbar.h,v retrieving revision 1.31 diff -u -p -u -r1.31 gtktoolbar.h --- gtk/gtktoolbar.h 9 Oct 2002 00:36:28 -0000 1.31 +++ gtk/gtktoolbar.h 8 Jun 2003 15:59:57 -0000 @@ -28,21 +28,22 @@ #ifndef __GTK_TOOLBAR_H__ #define __GTK_TOOLBAR_H__ - #include <gdk/gdk.h> #include <gtk/gtkcontainer.h> #include <gtk/gtkenums.h> #include <gtk/gtktooltips.h> +#include "gtktoolitem.h" + +#ifndef GTK_DISABLE_DEPRECATED + /* Not needed, retained for compatibility -Yosh */ #include <gtk/gtkpixmap.h> #include <gtk/gtksignal.h> +#endif -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - +G_BEGIN_DECLS #define GTK_TYPE_TOOLBAR (gtk_toolbar_get_type ()) #define GTK_TOOLBAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_TOOLBAR, GtkToolbar)) @@ -51,7 +52,7 @@ extern "C" { #define GTK_IS_TOOLBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TOOLBAR)) #define GTK_TOOLBAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_TOOLBAR, GtkToolbarClass)) - +#ifndef GTK_DISABLE_DEPRECATED typedef enum { GTK_TOOLBAR_CHILD_SPACE, @@ -61,15 +62,7 @@ typedef enum GTK_TOOLBAR_CHILD_WIDGET } GtkToolbarChildType; -typedef enum -{ - GTK_TOOLBAR_SPACE_EMPTY, - GTK_TOOLBAR_SPACE_LINE -} GtkToolbarSpaceStyle; - -typedef struct _GtkToolbarChild GtkToolbarChild; -typedef struct _GtkToolbar GtkToolbar; -typedef struct _GtkToolbarClass GtkToolbarClass; +typedef struct _GtkToolbarChild GtkToolbarChild; struct _GtkToolbarChild { @@ -79,6 +72,17 @@ struct _GtkToolbarChild GtkWidget *label; }; +typedef enum +{ + GTK_TOOLBAR_SPACE_EMPTY, + GTK_TOOLBAR_SPACE_LINE +} GtkToolbarSpaceStyle; + +#endif /* GTK_DISABLE_DEPRECATED */ + +typedef struct _GtkToolbar GtkToolbar; +typedef struct _GtkToolbarClass GtkToolbarClass; + struct _GtkToolbar { GtkContainer container; @@ -90,13 +94,13 @@ struct _GtkToolbar GtkIconSize icon_size; GtkTooltips *tooltips; - - gint button_maxw; - gint button_maxh; + + gint button_maxw; /* maximum width of homogeneous children */ + gint button_maxh; /* maximum height of homogeneous children */ guint style_set_connection; guint icon_size_connection; - + guint style_set : 1; guint icon_size_set : 1; }; @@ -105,22 +109,62 @@ struct _GtkToolbarClass { GtkContainerClass parent_class; - void (* orientation_changed) (GtkToolbar *toolbar, - GtkOrientation orientation); - void (* style_changed) (GtkToolbar *toolbar, - GtkToolbarStyle style); + void (* orientation_changed) (GtkToolbar *toolbar, + GtkOrientation orientation); + void (* style_changed) (GtkToolbar *toolbar, + GtkToolbarStyle style); + void (* popup_context_menu) (GtkToolbar *toolbar); + + /* these should go away/become padding when we become part of gtk+ */ + gboolean (* move_focus) (GtkToolbar *toolbar, + GtkDirectionType dir); + gboolean (* focus_home) (GtkToolbar *toolbar); + gboolean (* focus_end) (GtkToolbar *toolbar); /* Padding for future expansion */ void (*_gtk_reserved1) (void); - void (*_gtk_reserved2) (void); - void (*_gtk_reserved3) (void); - void (*_gtk_reserved4) (void); }; +GType gtk_toolbar_get_type (void) G_GNUC_CONST; +GtkWidget* gtk_toolbar_new (void); -GType gtk_toolbar_get_type (void) G_GNUC_CONST; -GtkWidget* gtk_toolbar_new (void); +void gtk_toolbar_append (GtkToolbar *toolbar, + GtkToolItem *item); +void gtk_toolbar_prepend (GtkToolbar *toolbar, + GtkToolItem *item); +void gtk_toolbar_insert (GtkToolbar *toolbar, + GtkToolItem *item, + gint pos); +gint gtk_toolbar_get_item_index (GtkToolbar *toolbar, + GtkToolItem *item); +gint gtk_toolbar_get_n_items (GtkToolbar *toolbar); +GtkToolItem * gtk_toolbar_get_nth_item (GtkToolbar *toolbar, + gint n); +gint gtk_toolbar_get_drop_index (GtkToolbar *toolbar, + gint x, + gint y); +void gtk_toolbar_set_show_arrow (GtkToolbar *toolbar, + gboolean show_arrow); +void gtk_toolbar_set_orientation (GtkToolbar *toolbar, + GtkOrientation orientation); +/* FIXME: shouldn't these be deprecated? */ +void gtk_toolbar_set_style (GtkToolbar *toolbar, + GtkToolbarStyle style); +void gtk_toolbar_set_icon_size (GtkToolbar *toolbar, + GtkIconSize icon_size); +void gtk_toolbar_unset_style (GtkToolbar *toolbar); +/* -------- */ +void gtk_toolbar_set_tooltips (GtkToolbar *toolbar, + gboolean enable); +void gtk_toolbar_unset_icon_size (GtkToolbar *toolbar); +gboolean gtk_toolbar_get_show_arrow (GtkToolbar *toolbar); +GtkOrientation gtk_toolbar_get_orientation (GtkToolbar *toolbar); +GtkToolbarStyle gtk_toolbar_get_style (GtkToolbar *toolbar); +GtkIconSize gtk_toolbar_get_icon_size (GtkToolbar *toolbar); +gboolean gtk_toolbar_get_tooltips (GtkToolbar *toolbar); +GtkReliefStyle gtk_toolbar_get_relief_style (GtkToolbar *toolbar); +#ifndef GTK_DISABLE_DEPRECATED /* Simple button items */ GtkWidget* gtk_toolbar_append_item (GtkToolbar *toolbar, const char *text, @@ -154,8 +198,6 @@ GtkWidget* gtk_toolbar_insert_stock ( gpointer user_data, gint position); - - /* Space Items */ void gtk_toolbar_append_space (GtkToolbar *toolbar); void gtk_toolbar_prepend_space (GtkToolbar *toolbar); @@ -163,7 +205,6 @@ void gtk_toolbar_insert_space ( gint position); void gtk_toolbar_remove_space (GtkToolbar *toolbar, gint position); - /* Any element type */ GtkWidget* gtk_toolbar_append_element (GtkToolbar *toolbar, GtkToolbarChildType type, @@ -211,25 +252,9 @@ void gtk_toolbar_insert_widget ( const char *tooltip_private_text, gint position); -/* Style functions */ -void gtk_toolbar_set_orientation (GtkToolbar *toolbar, - GtkOrientation orientation); -void gtk_toolbar_set_style (GtkToolbar *toolbar, - GtkToolbarStyle style); -void gtk_toolbar_set_icon_size (GtkToolbar *toolbar, - GtkIconSize icon_size); -void gtk_toolbar_set_tooltips (GtkToolbar *toolbar, - gboolean enable); -void gtk_toolbar_unset_style (GtkToolbar *toolbar); -void gtk_toolbar_unset_icon_size (GtkToolbar *toolbar); - -GtkOrientation gtk_toolbar_get_orientation (GtkToolbar *toolbar); -GtkToolbarStyle gtk_toolbar_get_style (GtkToolbar *toolbar); -GtkIconSize gtk_toolbar_get_icon_size (GtkToolbar *toolbar); -gboolean gtk_toolbar_get_tooltips (GtkToolbar *toolbar); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ +#endif /* GTK_DISABLE_DEPRECATED */ + + +G_END_DECLS #endif /* __GTK_TOOLBAR_H__ */
Attachment:
toolbar.tar.gz
Description: Tarball with new toolbar files