From 30177ef207092d95ebbc2c835d52262618436c90 Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Sun, 6 Apr 2003 20:07:14 +0000 Subject: Add a separator item to the editor. 2003-04-06 Marco Pesenti Gritti * libegg/toolbareditor/egg-editable-toolbar.c: (get_dest_targets), (editor_create_item), (update_editor_sheet): Add a separator item to the editor. --- lib/egg/Makefile.am | 2 +- lib/egg/egg-editable-toolbar.c | 81 ++++++---- lib/egg/egg-menu-merge.c | 10 +- lib/egg/eggmarshalers.c | 43 +++++- lib/egg/eggmarshalers.h | 12 +- lib/egg/eggmarshalers.list | 1 + lib/egg/eggtoggletoolbutton.c | 44 +++++- lib/egg/eggtoggletoolbutton.h | 3 + lib/egg/eggtoolbar.c | 344 ++++++++++++++++++++++++++++++++++++----- lib/egg/eggtoolbar.h | 98 ++++++------ lib/egg/eggtoolbutton.c | 10 +- lib/egg/eggtoolitem.c | 80 ++++++---- 12 files changed, 557 insertions(+), 171 deletions(-) (limited to 'lib/egg') diff --git a/lib/egg/Makefile.am b/lib/egg/Makefile.am index 4a1448a11..da634d881 100644 --- a/lib/egg/Makefile.am +++ b/lib/egg/Makefile.am @@ -69,5 +69,5 @@ EGGFILES=$(EGGSOURCES) $(EGGHEADERS) EGGDIR=$(srcdir)/../../../libegg/libegg regenerate-built-sources: - EGGFILES="$(EGGFILES)" EGGDIR="$(EGGDIR)" $(srcdir)/update-from-egg.sh + EGGFILES="$(EGGFILES) eggmarshalers.list" EGGDIR="$(EGGDIR)" $(srcdir)/update-from-egg.sh diff --git a/lib/egg/egg-editable-toolbar.c b/lib/egg/egg-editable-toolbar.c index d0f747ba5..f53910ac5 100755 --- a/lib/egg/egg-editable-toolbar.c +++ b/lib/egg/egg-editable-toolbar.c @@ -560,7 +560,7 @@ get_dest_targets (EggEditableToolbar *etoolbar) { GList *l; GtkTargetList *targets; - int i; + int i = 0; targets = gtk_target_list_new (NULL, 0); @@ -1037,6 +1037,44 @@ add_to_list (EggToolbarsItem *item, *l = g_list_append (*l, item); } +static GtkWidget * +editor_create_item (EggEditableToolbar *etoolbar, + const char *stock_id, + const char *label_text, + GdkDragAction action) +{ + GtkWidget *event_box; + GtkWidget *vbox; + GtkWidget *icon; + GtkWidget *label; + + event_box = gtk_event_box_new (); + gtk_widget_show (event_box); + gtk_drag_source_set (event_box, + GDK_BUTTON1_MASK, + source_drag_types, 1, action); + g_signal_connect (event_box, "drag_data_get", + G_CALLBACK (drag_data_get_cb), etoolbar); + g_signal_connect (event_box, "drag_data_delete", + G_CALLBACK (editor_drag_data_delete_cb), etoolbar); + + vbox = gtk_vbox_new (0, FALSE); + gtk_widget_show (vbox); + gtk_container_add (GTK_CONTAINER (event_box), vbox); + + icon = gtk_image_new_from_stock + (stock_id ? stock_id : GTK_STOCK_DND, + GTK_ICON_SIZE_LARGE_TOOLBAR); + gtk_widget_show (icon); + gtk_box_pack_start (GTK_BOX (vbox), icon, FALSE, TRUE, 0); + + label = gtk_label_new_with_mnemonic (label_text); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); + + return event_box; +} + static void update_editor_sheet (EggEditableToolbar *etoolbar) { @@ -1045,6 +1083,7 @@ update_editor_sheet (EggEditableToolbar *etoolbar) int x, y, height, width; GtkWidget *table; GtkWidget *viewport; + GtkWidget *item; g_return_if_fail (IS_EGG_EDITABLE_TOOLBAR (etoolbar)); @@ -1076,44 +1115,17 @@ update_editor_sheet (EggEditableToolbar *etoolbar) for (l = to_drag; l != NULL; l = l->next) { - GtkWidget *event_box; - GtkWidget *vbox; - GtkWidget *icon; - GtkWidget *label; EggToolbarsItem *node = (EggToolbarsItem *) (l->data); EggAction *action; action = egg_editable_toolbar_get_action (etoolbar, node->action); g_return_if_fail (action != NULL); - event_box = gtk_event_box_new (); - gtk_widget_show (event_box); - gtk_drag_source_set (event_box, - GDK_BUTTON1_MASK, - source_drag_types, 1, GDK_ACTION_MOVE); - g_signal_connect (event_box, "drag_data_get", - G_CALLBACK (drag_data_get_cb), etoolbar); - g_signal_connect (event_box, "drag_data_delete", - G_CALLBACK (editor_drag_data_delete_cb), etoolbar); - - g_object_set_data (G_OBJECT (event_box), "egg-action", action); - - vbox = gtk_vbox_new (0, FALSE); - gtk_widget_show (vbox); - gtk_container_add (GTK_CONTAINER (event_box), vbox); - - icon = gtk_image_new_from_stock - (action->stock_id ? action->stock_id : GTK_STOCK_DND, - GTK_ICON_SIZE_LARGE_TOOLBAR); - gtk_widget_show (icon); - gtk_box_pack_start (GTK_BOX (vbox), icon, FALSE, TRUE, 0); - - label = gtk_label_new_with_mnemonic (action->label); - gtk_widget_show (label); - gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); - + item = editor_create_item (etoolbar, action->stock_id, + action->label, GDK_ACTION_MOVE); + g_object_set_data (G_OBJECT (item), "egg-action", action); gtk_table_attach_defaults (GTK_TABLE (etoolbar->priv->table), - event_box, x, x + 1, y, y + 1); + item, x, x + 1, y, y + 1); x++; if (x >= width) @@ -1123,6 +1135,11 @@ update_editor_sheet (EggEditableToolbar *etoolbar) } } + item = editor_create_item (etoolbar, NULL, _("Separator"), + GDK_ACTION_COPY); + gtk_table_attach_defaults (GTK_TABLE (etoolbar->priv->table), + item, x, x + 1, y, y + 1); + g_list_free (to_drag); } diff --git a/lib/egg/egg-menu-merge.c b/lib/egg/egg-menu-merge.c index 4be261948..2332bf89b 100644 --- a/lib/egg/egg-menu-merge.c +++ b/lib/egg/egg-menu-merge.c @@ -1131,12 +1131,12 @@ update_node (EggMenuMerge *self, GNode *node) EggToolItem *item; item = egg_separator_tool_item_new(); - egg_toolbar_insert_tool_item(EGG_TOOLBAR(toolbar), item, pos); + egg_toolbar_insert (EGG_TOOLBAR(toolbar), item, pos); NODE_INFO(node)->proxy = GTK_WIDGET (item); //gtk_widget_show(NODE_INFO(node)->proxy); item = egg_separator_tool_item_new(); - egg_toolbar_insert_tool_item(EGG_TOOLBAR(toolbar), item, pos+1); + egg_toolbar_insert (EGG_TOOLBAR(toolbar), item, pos+1); NODE_INFO(node)->extra = GTK_WIDGET (item); //gtk_widget_show(NODE_INFO(node)->extra); } @@ -1192,8 +1192,8 @@ update_node (EggMenuMerge *self, GNode *node) { info->proxy = egg_action_create_tool_item (info->action); - egg_toolbar_insert_tool_item (EGG_TOOLBAR (toolbar), - EGG_TOOL_ITEM (info->proxy), pos); + egg_toolbar_insert (EGG_TOOLBAR (toolbar), + EGG_TOOL_ITEM (info->proxy), pos); } } else @@ -1218,7 +1218,7 @@ update_node (EggMenuMerge *self, GNode *node) if (find_toolbar_position(node, &toolbar, &pos)) { EggToolItem *item = egg_separator_tool_item_new(); - egg_toolbar_insert_tool_item (EGG_TOOLBAR (toolbar), item, pos); + egg_toolbar_insert (EGG_TOOLBAR (toolbar), item, pos); info->proxy = GTK_WIDGET (item); gtk_widget_show(info->proxy); } diff --git a/lib/egg/eggmarshalers.c b/lib/egg/eggmarshalers.c index 3cc9b963e..77202899a 100644 --- a/lib/egg/eggmarshalers.c +++ b/lib/egg/eggmarshalers.c @@ -201,7 +201,46 @@ _egg_marshal_VOID__OBJECT_STRING_STRING (GClosure *closure, data2); } -/* BOOLEAN:VOID (eggmarshalers.list:5) */ +/* BOOLEAN:ENUM (eggmarshalers.list:5) */ +void +_egg_marshal_BOOLEAN__ENUM (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__ENUM) (gpointer data1, + gint arg_1, + gpointer data2); + register GMarshalFunc_BOOLEAN__ENUM callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 2); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__ENUM) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_enum (param_values + 1), + data2); + + g_value_set_boolean (return_value, v_return); +} + +/* BOOLEAN:VOID (eggmarshalers.list:6) */ void _egg_marshal_BOOLEAN__VOID (GClosure *closure, GValue *return_value, @@ -238,7 +277,7 @@ _egg_marshal_BOOLEAN__VOID (GClosure *closure, g_value_set_boolean (return_value, v_return); } -/* OBJECT:VOID (eggmarshalers.list:6) */ +/* OBJECT:VOID (eggmarshalers.list:7) */ void _egg_marshal_OBJECT__VOID (GClosure *closure, GValue *return_value, diff --git a/lib/egg/eggmarshalers.h b/lib/egg/eggmarshalers.h index dac29f1d1..96af54003 100644 --- a/lib/egg/eggmarshalers.h +++ b/lib/egg/eggmarshalers.h @@ -38,7 +38,15 @@ extern void _egg_marshal_VOID__OBJECT_STRING_STRING (GClosure *closure, gpointer invocation_hint, gpointer marshal_data); -/* BOOLEAN:VOID (eggmarshalers.list:5) */ +/* BOOLEAN:ENUM (eggmarshalers.list:5) */ +extern void _egg_marshal_BOOLEAN__ENUM (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* BOOLEAN:VOID (eggmarshalers.list:6) */ extern void _egg_marshal_BOOLEAN__VOID (GClosure *closure, GValue *return_value, guint n_param_values, @@ -46,7 +54,7 @@ extern void _egg_marshal_BOOLEAN__VOID (GClosure *closure, gpointer invocation_hint, gpointer marshal_data); -/* OBJECT:VOID (eggmarshalers.list:6) */ +/* OBJECT:VOID (eggmarshalers.list:7) */ extern void _egg_marshal_OBJECT__VOID (GClosure *closure, GValue *return_value, guint n_param_values, diff --git a/lib/egg/eggmarshalers.list b/lib/egg/eggmarshalers.list index 03890af58..d1652d501 100644 --- a/lib/egg/eggmarshalers.list +++ b/lib/egg/eggmarshalers.list @@ -2,5 +2,6 @@ VOID:OBJECT,OBJECT VOID:OBJECT,STRING,LONG,LONG VOID:OBJECT,LONG VOID:OBJECT,STRING,STRING +BOOLEAN:ENUM BOOLEAN:VOID OBJECT:VOID diff --git a/lib/egg/eggtoggletoolbutton.c b/lib/egg/eggtoggletoolbutton.c index c694eb9ad..23fbff2a5 100644 --- a/lib/egg/eggtoggletoolbutton.c +++ b/lib/egg/eggtoggletoolbutton.c @@ -35,6 +35,7 @@ enum { static void egg_toggle_tool_button_init (EggToggleToolButton *button); static void egg_toggle_tool_button_class_init (EggToggleToolButtonClass *klass); +static void egg_toggle_tool_button_finalize (GObject *object); static GtkWidget *egg_toggle_tool_button_create_menu_proxy (EggToolItem *button); @@ -77,17 +78,20 @@ egg_toggle_tool_button_get_type (void) static void egg_toggle_tool_button_class_init (EggToggleToolButtonClass *klass) { + GObjectClass *object_class; EggToolItemClass *toolitem_class; EggToolButtonClass *toolbutton_class; parent_class = g_type_class_peek_parent (klass); - + + object_class = (GObjectClass *)klass; toolitem_class = (EggToolItemClass *)klass; toolbutton_class = (EggToolButtonClass *)klass; + object_class->finalize = egg_toggle_tool_button_finalize; toolitem_class->create_menu_proxy = egg_toggle_tool_button_create_menu_proxy; toolbutton_class->button_type = GTK_TYPE_TOGGLE_BUTTON; - + toggle_signals[TOGGLED] = g_signal_new ("toggled", G_OBJECT_CLASS_TYPE (klass), @@ -105,24 +109,42 @@ egg_toggle_tool_button_init (EggToggleToolButton *button) G_CALLBACK (button_toggled), button, 0); } +static void +egg_toggle_tool_button_finalize (GObject *object) +{ + EggToggleToolButton *button = EGG_TOGGLE_TOOL_BUTTON (object); + + if (button->menu_item) + g_object_remove_weak_pointer (G_OBJECT (button->menu_item), + (gpointer *)&(button->menu_item)); + + (* G_OBJECT_CLASS (parent_class)->finalize) (object); +} + static GtkWidget * egg_toggle_tool_button_create_menu_proxy (EggToolItem *item) { EggToggleToolButton *button = EGG_TOGGLE_TOOL_BUTTON (item); - GtkWidget *menu_item; const char *label; label = gtk_label_get_text (GTK_LABEL (EGG_TOOL_BUTTON (button)->label)); + + if (button->menu_item) + g_object_remove_weak_pointer (G_OBJECT (button->menu_item), + (gpointer *)&(button->menu_item)); - menu_item = gtk_check_menu_item_new_with_mnemonic (label); - gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), + button->menu_item = gtk_check_menu_item_new_with_mnemonic (label); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button->menu_item), button->active); - g_signal_connect_object (menu_item, "activate", + g_signal_connect_object (button->menu_item, "activate", G_CALLBACK (gtk_button_clicked), EGG_TOOL_BUTTON (button)->button, G_CONNECT_SWAPPED); - return menu_item; + g_object_add_weak_pointer (G_OBJECT (button->menu_item), + (gpointer *)&(button->menu_item)); + + return button->menu_item; } static void @@ -137,6 +159,12 @@ button_toggled (GtkWidget *widget, button->active = toggle_active; g_signal_emit (G_OBJECT (button), toggle_signals[TOGGLED], 0); } + + if (button->menu_item) + { + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button->menu_item), + button->active); + } } EggToolItem * @@ -155,6 +183,8 @@ egg_toggle_tool_button_new_from_stock (const gchar *stock_id) { EggToolButton *button; + g_return_val_if_fail (stock_id != NULL, NULL); + button = g_object_new (EGG_TYPE_TOGGLE_TOOL_BUTTON, "stock_id", stock_id, "use_underline", TRUE, diff --git a/lib/egg/eggtoggletoolbutton.h b/lib/egg/eggtoggletoolbutton.h index 587d42257..e0f3cd785 100644 --- a/lib/egg/eggtoggletoolbutton.h +++ b/lib/egg/eggtoggletoolbutton.h @@ -40,6 +40,9 @@ struct _EggToggleToolButton { EggToolButton parent; + /*< private >*/ + GtkWidget *menu_item; + guint active : 1; }; diff --git a/lib/egg/eggtoolbar.c b/lib/egg/eggtoolbar.c index 7c1d8c1b5..b4cdbc62e 100644 --- a/lib/egg/eggtoolbar.c +++ b/lib/egg/eggtoolbar.c @@ -32,6 +32,10 @@ #include #include #include +#include +#include +#include "eggmarshalers.h" +#include #define DEFAULT_IPADDING 0 #define DEFAULT_SPACE_SIZE 5 @@ -60,10 +64,20 @@ enum { 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 }; @@ -91,7 +105,6 @@ static void egg_toolbar_style_set (GtkWidget *widget, GtkStyle *prev_style); static void egg_toolbar_direction_changed (GtkWidget *widget, GtkTextDirection previous_direction); - static gboolean egg_toolbar_focus (GtkWidget *widget, GtkDirectionType dir); static void egg_toolbar_screen_changed (GtkWidget *widget, @@ -116,18 +129,24 @@ static void egg_toolbar_forall (GtkContainer *container, gpointer callback_data); static GType egg_toolbar_child_type (GtkContainer *container); - static void egg_toolbar_real_orientation_changed (EggToolbar *toolbar, GtkOrientation orientation); static void egg_toolbar_real_style_changed (EggToolbar *toolbar, GtkToolbarStyle style); +static gboolean egg_toolbar_move_focus (EggToolbar *toolbar, + GtkDirectionType dir); +static gboolean egg_toolbar_focus_home (EggToolbar *toolbar); +static gboolean egg_toolbar_focus_end (EggToolbar *toolbar); + static gboolean egg_toolbar_button_press (GtkWidget *button, GdkEventButton *event, EggToolbar *toolbar); -static void egg_toolbar_arrow_button_press (GtkWidget *button, +static gboolean egg_toolbar_arrow_button_press (GtkWidget *button, GdkEventButton *event, EggToolbar *toolbar); +static void egg_toolbar_arrow_button_clicked (GtkWidget *button, + EggToolbar *toolbar); static void egg_toolbar_update_button_relief (EggToolbar *toolbar); static GtkReliefStyle get_button_relief (EggToolbar *toolbar); static gint get_space_size (EggToolbar *toolbar); @@ -165,6 +184,7 @@ typedef struct gint drop_index; GdkWindow *drag_highlight; + GtkMenu *menu; } EggToolbarPrivate; static GtkContainerClass *parent_class = NULL; @@ -198,12 +218,28 @@ egg_toolbar_get_type (void) 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); +} + static void egg_toolbar_class_init (EggToolbarClass *klass) { GObjectClass *gobject_class; GtkWidgetClass *widget_class; GtkContainerClass *container_class; + GtkBindingSet *binding_set; parent_class = g_type_class_peek_parent (klass); @@ -234,7 +270,10 @@ egg_toolbar_class_init (EggToolbarClass *klass) klass->orientation_changed = egg_toolbar_real_orientation_changed; klass->style_changed = egg_toolbar_real_style_changed; - + klass->move_focus = egg_toolbar_move_focus; + klass->focus_home = egg_toolbar_focus_home; + klass->focus_end = egg_toolbar_focus_end; + toolbar_signals[ORIENTATION_CHANGED] = g_signal_new ("orientation_changed", G_OBJECT_CLASS_TYPE (klass), @@ -253,7 +292,6 @@ egg_toolbar_class_init (EggToolbarClass *klass) 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), @@ -262,7 +300,33 @@ egg_toolbar_class_init (EggToolbarClass *klass) 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 (EggToolbarClass, move_focus), + NULL, NULL, + _egg_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 (EggToolbarClass, focus_home), + NULL, NULL, + _egg_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 (EggToolbarClass, focus_end), + NULL, NULL, + _egg_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); + + /* properties */ g_object_class_install_property (gobject_class, PROP_ORIENTATION, g_param_spec_enum ("orientation", @@ -288,6 +352,34 @@ egg_toolbar_class_init (EggToolbarClass *klass) FALSE, G_PARAM_READWRITE)); +#if 0 + /* 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)); +#endif + + /* style properties */ gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("space_size", _("Spacer size"), @@ -342,6 +434,22 @@ egg_toolbar_class_init (EggToolbarClass *klass) GTK_TYPE_ICON_SIZE, DEFAULT_ICON_SIZE, G_PARAM_READWRITE)); + + binding_set = gtk_binding_set_by_class (klass); + + 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); } static void @@ -363,9 +471,15 @@ egg_toolbar_init (EggToolbar *toolbar) priv->button = gtk_toggle_button_new (); g_signal_connect (priv->button, "button_press_event", G_CALLBACK (egg_toolbar_arrow_button_press), toolbar); + g_signal_connect_after (priv->button, "clicked", + G_CALLBACK (egg_toolbar_arrow_button_clicked), toolbar); gtk_button_set_relief (GTK_BUTTON (priv->button), get_button_relief (toolbar)); - GTK_WIDGET_UNSET_FLAGS (priv->button, GTK_CAN_FOCUS); + +#if 0 + /* FIXME: enable this when we can depend on gtk+ 2.3.0 */ + gtk_button_set_focus_on_click (GTK_BUTTON (priv->button), FALSE); +#endif priv->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE); gtk_widget_show (priv->arrow); @@ -379,6 +493,8 @@ egg_toolbar_init (EggToolbar *toolbar) /* which child position a drop will occur at */ priv->drop_index = -1; priv->drag_highlight = NULL; + + priv->menu = NULL; } static void @@ -1083,7 +1199,7 @@ egg_toolbar_style_set (GtkWidget *widget, GtkStyle *prev_style) { if (GTK_WIDGET_REALIZED (widget)) - gtk_style_set_background (widget->style, widget->window, widget->state); + gtk_style_set_background (widget->style, widget->window, widget->state); if (prev_style) egg_toolbar_update_button_relief (EGG_TOOLBAR (widget)); @@ -1107,13 +1223,136 @@ egg_toolbar_direction_changed (GtkWidget *widget, GTK_WIDGET_CLASS (parent_class)->direction_changed (widget, previous_dir); } +static GList * +egg_toolbar_list_items_in_focus_order (EggToolbar *toolbar, + GtkDirectionType dir) +{ + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + GList *result = NULL; + GList *list; + + for (list = priv->items; list != NULL; list = list->next) + { + EggToolItem *item = list->data; + if (!item->pack_end) + result = g_list_prepend (result, item); + } + + for (list = priv->items; list != NULL; list = list->next) + { + EggToolItem *item = list->data; + + if (item->pack_end) + result = g_list_prepend (result, item); + } + + result = g_list_prepend (result, priv->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 +egg_toolbar_move_focus (EggToolbar *toolbar, + GtkDirectionType dir) +{ + GList *list; + gboolean retval = FALSE; + gboolean try_focus = FALSE; + GList *items = egg_toolbar_list_items_in_focus_order (toolbar, dir); + + for (list = items; list != NULL; list = list->next) + { + GtkWidget *tool_item = list->data; + + if (try_focus && gtk_widget_child_focus (tool_item, dir)) + { + retval = TRUE; + break; + } + + if (tool_item == GTK_CONTAINER (toolbar)->focus_child) + try_focus = TRUE; + } + + g_list_free (items); + return retval; +} + +static gboolean +egg_toolbar_focus_home (EggToolbar *toolbar) +{ + GList *items, *list; + GtkTextDirection direction = gtk_widget_get_direction (GTK_WIDGET (toolbar)); + + if (direction == GTK_TEXT_DIR_RTL) + items = egg_toolbar_list_items_in_focus_order (toolbar, GTK_DIR_LEFT); + else + items = egg_toolbar_list_items_in_focus_order (toolbar, GTK_DIR_RIGHT); + + for (list = items; list != NULL; list = list->next) + { + if (GTK_CONTAINER (toolbar)->focus_child == list->data) + break; + + if (gtk_widget_child_focus (list->data, GTK_DIR_RIGHT)) + break; + } + + g_list_free (items); + + return TRUE; +} + +static gboolean +egg_toolbar_focus_end (EggToolbar *toolbar) +{ + GList *items, *list; + GtkTextDirection direction = gtk_widget_get_direction (GTK_WIDGET (toolbar)); + + if (direction == GTK_TEXT_DIR_RTL) + items = egg_toolbar_list_items_in_focus_order (toolbar, GTK_DIR_RIGHT); + else + items = egg_toolbar_list_items_in_focus_order (toolbar, GTK_DIR_LEFT); + + for (list = items; list != NULL; list = list->next) + { + if (GTK_CONTAINER (toolbar)->focus_child == list->data) + break; + + if (gtk_widget_child_focus (list->data, GTK_DIR_RIGHT)) + break; + } + + g_list_free (items); + + return TRUE; +} + static gboolean egg_toolbar_focus (GtkWidget *widget, GtkDirectionType dir) { - /* Focus can't go in toolbars */ + EggToolbar *toolbar = EGG_TOOLBAR (widget); + GList *items; + gboolean retval = FALSE; + + if (GTK_CONTAINER (widget)->focus_child) + return FALSE; + + items = egg_toolbar_list_items_in_focus_order (toolbar, dir); + + if (items) + retval = gtk_widget_child_focus (items->data, dir); + + g_list_free (items); - return FALSE; + return retval; } static void @@ -1367,8 +1606,8 @@ egg_toolbar_add (GtkContainer *container, g_return_if_fail (EGG_IS_TOOLBAR (container)); g_return_if_fail (EGG_IS_TOOL_ITEM (widget)); - egg_toolbar_append_tool_item (EGG_TOOLBAR (container), - EGG_TOOL_ITEM (widget)); + egg_toolbar_append (EGG_TOOLBAR (container), + EGG_TOOL_ITEM (widget)); } static void @@ -1514,25 +1753,25 @@ menu_position_func (GtkMenu *menu, } static void -menu_deactivated (GtkWidget *menu, GtkWidget *button) +menu_deactivated (GtkWidget *menu, EggToolbar *toolbar) { - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE); + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->button), FALSE); } static void -egg_toolbar_arrow_button_press (GtkWidget *button, - GdkEventButton *event, - EggToolbar *toolbar) +show_menu (EggToolbar *toolbar, GdkEventButton *event) { - EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); - GtkWidget *menu; - GtkWidget *menu_item; + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); GList *items; + GtkWidget *menu_item; - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); - - menu = gtk_menu_new (); - g_signal_connect (menu, "deactivate", G_CALLBACK (menu_deactivated), button); + if (priv->menu) + 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); items = priv->first_non_fitting_item; while (items) @@ -1545,18 +1784,44 @@ egg_toolbar_arrow_button_press (GtkWidget *button, g_signal_emit_by_name (item, "create_menu_proxy", &menu_item); if (menu_item) - { - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); - } + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), menu_item); } items = items->next; } - gtk_widget_show_all (menu); + gtk_widget_show_all (GTK_WIDGET (priv->menu)); - gtk_menu_popup (GTK_MENU (menu), NULL, NULL, + gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL, menu_position_func, toolbar, - event->button, event->time); + event? event->button : 0, event? event->time : gtk_get_current_event_time()); +} + +static void +egg_toolbar_arrow_button_clicked (GtkWidget *button, EggToolbar *toolbar) +{ + EggToolbarPrivate *priv = EGG_TOOLBAR_GET_PRIVATE (toolbar); + + /* We only get here when the button is clicked with the keybaord, + * because we block mouse button presses by returning TRUE from + * egg_toolbar_arrow_button_press + */ + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->button))) + { + show_menu (toolbar, NULL); + gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menu), FALSE); + } +} + +static gboolean +egg_toolbar_arrow_button_press (GtkWidget *button, + GdkEventButton *event, + EggToolbar *toolbar) +{ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); + + show_menu (toolbar, event); + + return TRUE; } static gboolean @@ -1645,13 +1910,13 @@ egg_toolbar_new (void) } void -egg_toolbar_append_tool_item (EggToolbar *toolbar, - EggToolItem *item) +egg_toolbar_append (EggToolbar *toolbar, + EggToolItem *item) { g_return_if_fail (EGG_IS_TOOLBAR (toolbar)); g_return_if_fail (EGG_IS_TOOL_ITEM (item)); - egg_toolbar_insert_tool_item (toolbar, item, toolbar->num_children); + egg_toolbar_insert (toolbar, item, toolbar->num_children); } void @@ -1661,7 +1926,7 @@ egg_toolbar_prepend_tool_item (EggToolbar *toolbar, g_return_if_fail (EGG_IS_TOOLBAR (toolbar)); g_return_if_fail (EGG_IS_TOOL_ITEM (item)); - egg_toolbar_insert_tool_item (toolbar, item, 0); + egg_toolbar_insert (toolbar, item, 0); } void @@ -1699,9 +1964,9 @@ egg_toolbar_remove_tool_item (EggToolbar *toolbar, } void -egg_toolbar_insert_tool_item (EggToolbar *toolbar, - EggToolItem *item, - gint pos) +egg_toolbar_insert (EggToolbar *toolbar, + EggToolItem *item, + gint pos) { EggToolbarPrivate *priv; @@ -1718,7 +1983,6 @@ egg_toolbar_insert_tool_item (EggToolbar *toolbar, egg_tool_item_set_relief_style (item, get_button_relief (toolbar)); gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (toolbar)); - GTK_WIDGET_UNSET_FLAGS (item, GTK_CAN_FOCUS); } gint @@ -1869,6 +2133,8 @@ egg_toolbar_unset_icon_size (EggToolbar *toolbar) { GtkIconSize size; + g_return_if_fail (EGG_IS_TOOLBAR (toolbar)); + if (toolbar->icon_size_set) { GtkSettings *settings = toolbar_get_settings (toolbar); @@ -2219,7 +2485,7 @@ egg_toolbar_internal_insert_element (EggToolbar *toolbar, tooltip_text, tooltip_private_text); toolbar->children = g_list_insert (toolbar->children, child, position); - egg_toolbar_insert_tool_item (toolbar, item, position); + egg_toolbar_insert (toolbar, item, position); return child->widget; } diff --git a/lib/egg/eggtoolbar.h b/lib/egg/eggtoolbar.h index 0b07962aa..b82f7ecf5 100644 --- a/lib/egg/eggtoolbar.h +++ b/lib/egg/eggtoolbar.h @@ -35,10 +35,14 @@ #include "eggtoolitem.h" +#ifndef GTK_DISABLE_DEPRECATED + /* Not needed, retained for compatibility -Yosh */ #include #include +#endif + G_BEGIN_DECLS #define EGG_TYPE_TOOLBAR (egg_toolbar_get_type ()) @@ -67,8 +71,8 @@ struct _EggToolbarChild GtkWidget *icon; GtkWidget *label; }; - #endif /* EGG_DISABLE_DEPRECATED */ + typedef struct _EggToolbar EggToolbar; typedef struct _EggToolbarClass EggToolbarClass; @@ -98,57 +102,57 @@ struct _EggToolbarClass { GtkContainerClass parent_class; - void (* orientation_changed) (EggToolbar *toolbar, - GtkOrientation orientation); - void (* style_changed) (EggToolbar *toolbar, - GtkToolbarStyle style); - void (* popup_context_menu) (EggToolbar *toolbar); + void (* orientation_changed) (EggToolbar *toolbar, + GtkOrientation orientation); + void (* style_changed) (EggToolbar *toolbar, + GtkToolbarStyle style); + void (* popup_context_menu) (EggToolbar *toolbar); + + /* these should go away/become padding when we become part of gtk+ */ + gboolean (* move_focus) (EggToolbar *toolbar, + GtkDirectionType dir); + gboolean (* focus_home) (EggToolbar *toolbar); + gboolean (* focus_end) (EggToolbar *toolbar); /* Padding for future expansion */ void (*_gtk_reserved1) (void); - void (*_gtk_reserved2) (void); - void (*_gtk_reserved3) (void); - void (*_gtk_reserved4) (void); }; -GType egg_toolbar_get_type (void) G_GNUC_CONST; -GtkWidget* egg_toolbar_new (void); - -void egg_toolbar_append_tool_item (EggToolbar *toolbar, - EggToolItem *item); -void egg_toolbar_prepend_tool_item (EggToolbar *toolbar, - EggToolItem *item); -void egg_toolbar_insert_tool_item (EggToolbar *toolbar, - EggToolItem *item, - gint pos); -void egg_toolbar_remove_tool_item (EggToolbar *toolbar, - EggToolItem *item); - -gint egg_toolbar_get_item_index (EggToolbar *toolbar, - EggToolItem *item); - -/* Style functions */ -void egg_toolbar_set_show_arrow (EggToolbar *toolbar, - gboolean show_arrow); -void egg_toolbar_set_orientation (EggToolbar *toolbar, - GtkOrientation orientation); -void egg_toolbar_set_style (EggToolbar *toolbar, - GtkToolbarStyle style); -void egg_toolbar_set_icon_size (EggToolbar *toolbar, - GtkIconSize icon_size); -void egg_toolbar_set_tooltips (EggToolbar *toolbar, - gboolean enable); -void egg_toolbar_unset_style (EggToolbar *toolbar); -void egg_toolbar_unset_icon_size (EggToolbar *toolbar); -gboolean egg_toolbar_get_show_arrow (EggToolbar *toolbar); -GtkOrientation egg_toolbar_get_orientation (EggToolbar *toolbar); -GtkToolbarStyle egg_toolbar_get_style (EggToolbar *toolbar); -GtkIconSize egg_toolbar_get_icon_size (EggToolbar *toolbar); -gboolean egg_toolbar_get_tooltips (EggToolbar *toolbar); -GList* egg_toolbar_get_tool_items (EggToolbar *toolbar); -gint egg_toolbar_get_drop_index (EggToolbar *toolbar, - gint x, - gint y); +GType egg_toolbar_get_type (void) G_GNUC_CONST; +GtkWidget* egg_toolbar_new (void); + +void egg_toolbar_append (EggToolbar *toolbar, + EggToolItem *item); +void egg_toolbar_prepend (EggToolbar *toolbar, + EggToolItem *item); +void egg_toolbar_insert (EggToolbar *toolbar, + EggToolItem *item, + gint pos); +void egg_toolbar_remove_tool_item (EggToolbar *toolbar, + EggToolItem *item); +gint egg_toolbar_get_item_index (EggToolbar *toolbar, + EggToolItem *item); +GList* egg_toolbar_get_tool_items (EggToolbar *toolbar); +gint egg_toolbar_get_drop_index (EggToolbar *toolbar, + gint x, + gint y); +void egg_toolbar_set_show_arrow (EggToolbar *toolbar, + gboolean show_arrow); +void egg_toolbar_set_orientation (EggToolbar *toolbar, + GtkOrientation orientation); +void egg_toolbar_set_style (EggToolbar *toolbar, + GtkToolbarStyle style); +void egg_toolbar_set_icon_size (EggToolbar *toolbar, + GtkIconSize icon_size); +void egg_toolbar_set_tooltips (EggToolbar *toolbar, + gboolean enable); +void egg_toolbar_unset_style (EggToolbar *toolbar); +void egg_toolbar_unset_icon_size (EggToolbar *toolbar); +gboolean egg_toolbar_get_show_arrow (EggToolbar *toolbar); +GtkOrientation egg_toolbar_get_orientation (EggToolbar *toolbar); +GtkToolbarStyle egg_toolbar_get_style (EggToolbar *toolbar); +GtkIconSize egg_toolbar_get_icon_size (EggToolbar *toolbar); +gboolean egg_toolbar_get_tooltips (EggToolbar *toolbar); #ifndef EGG_DISABLE_DEPRECATED diff --git a/lib/egg/eggtoolbutton.c b/lib/egg/eggtoolbutton.c index 4ff471729..7eb7523b9 100644 --- a/lib/egg/eggtoolbutton.c +++ b/lib/egg/eggtoolbutton.c @@ -180,7 +180,11 @@ egg_tool_button_init (EggToolButton *button, EggToolButtonClass *klass) /* create button */ button->button = g_object_new (klass->button_type, NULL); - GTK_WIDGET_UNSET_FLAGS (button->button, GTK_CAN_FOCUS); +#if 0 + /* FIXME: enable this when we can depend on gtk+ 2.3.0 */ + gtk_button_set_focus_on_click (button->button, FALSE); +#endif + g_signal_connect_object (button->button, "clicked", G_CALLBACK (button_clicked), button, 0); @@ -328,7 +332,7 @@ egg_tool_button_get_property (GObject *object, break; case PROP_USE_UNDERLINE: g_value_set_boolean (value, - gtk_label_get_use_underline (GTK_LABEL (button->label))); + gtk_label_get_use_underline (GTK_LABEL (button->label))); break; case PROP_STOCK_ID: g_value_set_string (value, button->stock_id); @@ -602,6 +606,8 @@ egg_tool_button_new_from_stock (const gchar *stock_id) { EggToolButton *button; + g_return_val_if_fail (stock_id != NULL, NULL); + button = g_object_new (EGG_TYPE_TOOL_BUTTON, "stock_id", stock_id, "use_underline", TRUE, diff --git a/lib/egg/eggtoolitem.c b/lib/egg/eggtoolitem.c index 8f93ac369..1921c062d 100644 --- a/lib/egg/eggtoolitem.c +++ b/lib/egg/eggtoolitem.c @@ -225,12 +225,13 @@ egg_tool_item_class_init (EggToolItemClass *klass) GTK_TYPE_TOOLTIPS, G_TYPE_STRING, G_TYPE_STRING); - } static void egg_tool_item_init (EggToolItem *toolitem) { + GTK_WIDGET_UNSET_FLAGS (toolitem, GTK_CAN_FOCUS); + toolitem->visible_horizontal = TRUE; toolitem->visible_vertical = TRUE; toolitem->homogeneous = FALSE; @@ -357,10 +358,7 @@ egg_tool_item_map (GtkWidget *widget) toolitem = EGG_TOOL_ITEM (widget); GTK_WIDGET_CLASS (parent_class)->map (widget); if (toolitem->drag_window) - { - gdk_window_raise (toolitem->drag_window); - gdk_window_show (toolitem->drag_window); - } + gdk_window_show (toolitem->drag_window); } static void @@ -477,36 +475,45 @@ void egg_tool_item_set_expandable (EggToolItem *tool_item, gboolean expandable) { - if ((expandable && tool_item->expandable) || - (!expandable && !tool_item->expandable)) - return; + g_return_if_fail (EGG_IS_TOOL_ITEM (tool_item)); + + expandable = expandable != FALSE; - tool_item->expandable = expandable; - gtk_widget_queue_resize (GTK_WIDGET (tool_item)); + if (tool_item->expandable != expandable) + { + tool_item->expandable = expandable; + gtk_widget_queue_resize (GTK_WIDGET (tool_item)); + } } void egg_tool_item_set_pack_end (EggToolItem *tool_item, gboolean pack_end) { - if ((pack_end && tool_item->pack_end) || - (!pack_end && !tool_item->pack_end)) - return; + g_return_if_fail (EGG_IS_TOOL_ITEM (tool_item)); + + pack_end = pack_end != FALSE; - tool_item->pack_end = pack_end; - gtk_widget_queue_resize (GTK_WIDGET (tool_item)); + if (tool_item->pack_end != pack_end) + { + tool_item->pack_end = pack_end; + gtk_widget_queue_resize (GTK_WIDGET (tool_item)); + } } void egg_tool_item_set_homogeneous (EggToolItem *tool_item, gboolean homogeneous) { - if ((homogeneous && tool_item->homogeneous) || - (!homogeneous && !tool_item->homogeneous)) - return; + g_return_if_fail (EGG_IS_TOOL_ITEM (tool_item)); + + homogeneous = homogeneous != FALSE; - tool_item->homogeneous = homogeneous; - gtk_widget_queue_resize (GTK_WIDGET (tool_item)); + if (tool_item->homogeneous != homogeneous) + { + tool_item->homogeneous = homogeneous; + gtk_widget_queue_resize (GTK_WIDGET (tool_item)); + } } void @@ -527,24 +534,29 @@ egg_tool_item_set_use_drag_window (EggToolItem *toolitem, { g_return_if_fail (EGG_IS_TOOL_ITEM (toolitem)); - toolitem->use_drag_window = use_drag_window; + use_drag_window = use_drag_window != FALSE; - if (use_drag_window) + if (toolitem->use_drag_window != use_drag_window) { - if (!toolitem->drag_window && GTK_WIDGET_REALIZED (toolitem)) + toolitem->use_drag_window = use_drag_window; + + if (use_drag_window) { - create_drag_window(toolitem); - if (GTK_WIDGET_MAPPED (toolitem)) - gdk_window_show (toolitem->drag_window); + if (!toolitem->drag_window && GTK_WIDGET_REALIZED (toolitem)) + { + create_drag_window(toolitem); + if (GTK_WIDGET_MAPPED (toolitem)) + gdk_window_show (toolitem->drag_window); + } } - } - else - { - if (toolitem->drag_window) + else { - gdk_window_set_user_data (toolitem->drag_window, NULL); - gdk_window_destroy (toolitem->drag_window); - toolitem->drag_window = NULL; + if (toolitem->drag_window) + { + gdk_window_set_user_data (toolitem->drag_window, NULL); + gdk_window_destroy (toolitem->drag_window); + toolitem->drag_window = NULL; + } } - } + } } -- cgit v1.2.3