Index: src/ephy-toolbar.c =================================================================== RCS file: /cvs/gnome/epiphany/src/ephy-toolbar.c,v retrieving revision 1.28 diff -p -u -u -p -r1.28 ephy-toolbar.c --- src/ephy-toolbar.c 12 Nov 2005 20:48:16 -0000 1.28 +++ src/ephy-toolbar.c 29 Jan 2006 21:31:48 -0000 @@ -739,5 +739,6 @@ ephy_toolbar_new (EphyWindow *window) return EPHY_TOOLBAR (g_object_new (EPHY_TYPE_TOOLBAR, "window", window, "ui-manager", ephy_window_get_ui_manager (window), + "ui-path", "/menubar/ViewMenu/ViewToolbarsMenu/ToolbarsPH", NULL)); } Index: src/ephy-window.c =================================================================== RCS file: /cvs/gnome/epiphany/src/ephy-window.c,v retrieving revision 1.336 diff -p -u -u -p -r1.336 ephy-window.c --- src/ephy-window.c 13 Jan 2006 12:54:26 -0000 1.336 +++ src/ephy-window.c 29 Jan 2006 21:31:50 -0000 @@ -93,8 +93,6 @@ static void ephy_window_notebook_switch_ EphyWindow *window); static void ephy_window_view_statusbar_cb (GtkAction *action, EphyWindow *window); -static void ephy_window_view_toolbar_cb (GtkAction *action, - EphyWindow *window); static void ephy_window_view_popup_windows_cb (GtkAction *action, EphyWindow *window); static void sync_tab_load_status (EphyTab *tab, @@ -190,15 +188,18 @@ static const GtkActionEntry ephy_menu_en N_("Manage Certificates"), G_CALLBACK (window_cmd_edit_certificates) }, #endif - { "EditToolbar", NULL, N_("T_oolbars"), NULL, - N_("Customize toolbars"), - G_CALLBACK (window_cmd_edit_toolbar) }, { "EditPrefs", GTK_STOCK_PREFERENCES, N_("P_references"), NULL, N_("Configure the web browser"), G_CALLBACK (window_cmd_edit_prefs) }, /* View menu */ + { "ViewToolbars", NULL, N_("_Toolbars"), NULL, + NULL, + NULL }, + { "ViewEditToolbars", NULL, N_("_Customize..."), NULL, + N_("Customize toolbars"), + G_CALLBACK (window_cmd_edit_toolbar) }, { "ViewStop", GTK_STOCK_STOP, N_("_Stop"), "Escape", N_("Stop current data transfer"), G_CALLBACK (window_cmd_view_stop) }, @@ -279,9 +280,6 @@ static const GtkToggleActionEntry ephy_m /* View Menu */ - { "ViewToolbar", NULL, N_("_Toolbar"), "T", - N_("Show or hide toolbar"), - G_CALLBACK (ephy_window_view_toolbar_cb), TRUE }, { "ViewStatusbar", NULL, N_("St_atusbar"), NULL, N_("Show or hide statusbar"), G_CALLBACK (ephy_window_view_statusbar_cb), TRUE }, @@ -1221,15 +1219,6 @@ update_chromes_actions (EphyWindow *wind &show_statusbar, &show_toolbar, &show_tabsbar); - action = gtk_action_group_get_action (action_group, "ViewToolbar"); - g_signal_handlers_block_by_func (G_OBJECT (action), - G_CALLBACK (ephy_window_view_toolbar_cb), - window); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), show_toolbar); - g_signal_handlers_unblock_by_func (G_OBJECT (action), - G_CALLBACK (ephy_window_view_toolbar_cb), - window); - action = gtk_action_group_get_action (action_group, "ViewStatusbar"); g_signal_handlers_block_by_func (G_OBJECT (action), G_CALLBACK (ephy_window_view_statusbar_cb), @@ -2802,7 +2791,7 @@ ephy_window_state_event (GtkWidget *widg g_signal_handlers_unblock_by_func (action, G_CALLBACK (window_cmd_view_fullscreen), window); - action = gtk_action_group_get_action (action_group, "EditToolbar"); + action = gtk_action_group_get_action (action_group, "ViewEditToolbars"); ephy_action_change_sensitivity_flags (action, SENS_FLAG_CHROME, fullscreen); } @@ -3658,14 +3647,6 @@ ephy_window_view_statusbar_cb (GtkAction { sync_chrome_with_view_toggle (action, window, EPHY_EMBED_CHROME_STATUSBAR); -} - -static void -ephy_window_view_toolbar_cb (GtkAction *action, - EphyWindow *window) -{ - sync_chrome_with_view_toggle (action, window, - EPHY_EMBED_CHROME_TOOLBAR); } static void Index: src/window-commands.c =================================================================== RCS file: /cvs/gnome/epiphany/src/window-commands.c,v retrieving revision 1.180 diff -p -u -u -p -r1.180 window-commands.c --- src/window-commands.c 6 Jan 2006 22:50:17 -0000 1.180 +++ src/window-commands.c 29 Jan 2006 21:31:50 -0000 @@ -745,11 +745,20 @@ window_cmd_help_about (GtkAction *action NULL }; + char *comments; + gboolean with_python = FALSE; +#ifdef ENABLE_PYTHON + with_python = TRUE; +#endif + comments = g_strdup_printf (_("Python: %s"), + with_python ? _("enabled") : _("disabled")); + gtk_show_about_dialog (GTK_WINDOW (window), "name", _("GNOME Web Browser"), "version", VERSION, "copyright", "Copyright © 2002-2004 Marco Pesenti Gritti\n" "Copyright © 2003-2006 The GNOME Web Browser Developers", + "comments", comments, "authors", authors, "documenters", documenters, /* Translators: This is a special message that shouldn't be translated @@ -765,6 +774,8 @@ window_cmd_help_about (GtkAction *action "website", "http://www.gnome.org/projects/epiphany", "website-label", _("GNOME Web Browser Website"), NULL); + + g_free (comments); } void Index: lib/egg/egg-editable-toolbar.c =================================================================== RCS file: /cvs/gnome/epiphany/lib/egg/egg-editable-toolbar.c,v retrieving revision 1.78 diff -p -u -u -p -r1.78 egg-editable-toolbar.c --- lib/egg/egg-editable-toolbar.c 16 Dec 2005 16:18:08 -0000 1.78 +++ lib/egg/egg-editable-toolbar.c 29 Jan 2006 21:31:51 -0000 @@ -25,6 +25,7 @@ #include "egg-toolbars-model.h" #include "egg-toolbar-editor.h" +#include #include #include #include @@ -43,16 +44,44 @@ #include #include #include -#include -#include +#include +#include +#include -static void egg_editable_toolbar_class_init (EggEditableToolbarClass *klass); -static void egg_editable_toolbar_init (EggEditableToolbar *etoolbar); -static void egg_editable_toolbar_finalize (GObject *object); +#include #define MIN_TOOLBAR_HEIGHT 20 #define EGG_ITEM_NAME "egg-item-name" -#define EGG_TOOLITEM "egg-toolitem" + +#define ACTION_NAME_FORMAT_PREFIX "EETViewToolbar" +#define ACTION_NAME_FORMAT ACTION_NAME_FORMAT_PREFIX "%u" +#define ACTION_NAME_FORMAT_LENGTH strlen (ACTION_NAME_FORMAT) + 14 + +#define LABEL_WIDTH_CHARS 32 + +#define EGG_EDITABLE_TOOLBAR_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EGG_TYPE_EDITABLE_TOOLBAR, EggEditableToolbarPrivate)) + +struct _EggEditableToolbarPrivate +{ + GtkUIManager *manager; + char *ui_path; + GtkActionGroup *action_group; + GtkActionGroup *toggles_action_group; + guint ui_id; + guint toggles_ui_id; + EggToolbarsModel *model; + guint edit_mode; + GtkWidget *fixed_toolbar; + + GtkWidget *selected; + GtkWidget *popup_menu; + + guint dnd_pending; + GtkToolbar *dnd_toolbar; + GtkToolItem *dnd_toolitem; + guint save_hidden : 1; + guint updating_view_toggles : 1; +}; static const GtkTargetEntry dest_drag_types[] = { {EGG_TOOLBAR_ITEM_TYPE, GTK_TARGET_SAME_APP, 0}, @@ -62,68 +91,57 @@ enum { PROP_0, PROP_TOOLBARS_MODEL, - PROP_UI_MANAGER + PROP_UI_MANAGER, + PROP_UI_PATH, + PROP_SELECTED }; enum { ACTION_REQUEST, + PREPARE_POPUP, LAST_SIGNAL }; -static guint egg_editable_toolbar_signals[LAST_SIGNAL] = { 0 }; +static guint signals[LAST_SIGNAL]; static GObjectClass *parent_class = NULL; -#define EGG_EDITABLE_TOOLBAR_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EGG_TYPE_EDITABLE_TOOLBAR, EggEditableToolbarPrivate)) +/* Helper functions */ -struct _EggEditableToolbarPrivate +static GtkAction * +find_action (EggEditableToolbar *toolbar, + const char *name) { - GtkUIManager *manager; - EggToolbarsModel *model; - guint edit_mode; - gboolean save_hidden; - GtkWidget *fixed_toolbar; - - guint dnd_pending; - GtkToolbar *dnd_toolbar; - GtkToolItem *dnd_toolitem; -}; + EggEditableToolbarPrivate *priv = toolbar->priv; + GList *l; + GtkAction *action = NULL, *act; -GType -egg_editable_toolbar_get_type (void) -{ - static GType type = 0; + g_return_val_if_fail (name != NULL, NULL); - if (G_UNLIKELY (type == 0)) + for (l = gtk_ui_manager_get_action_groups (priv->manager); l != NULL; l = l->next) { - static const GTypeInfo our_info = { - sizeof (EggEditableToolbarClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) egg_editable_toolbar_class_init, - NULL, - NULL, /* class_data */ - sizeof (EggEditableToolbar), - 0, /* n_preallocs */ - (GInstanceInitFunc) egg_editable_toolbar_init - }; - - type = g_type_register_static (GTK_TYPE_VBOX, - "EggEditableToolbar", - &our_info, 0); + act = gtk_action_group_get_action ((GtkActionGroup*) (l->data), name); + if (act) + { + action = act; + break; + } } - return type; + return action; } +/* Dock and toolbar helper functions */ + static int -get_dock_position (EggEditableToolbar *etoolbar, GtkWidget *dock) +get_dock_position (EggEditableToolbar *toolbar, + GtkWidget *dock) { GList *l; int result; - l = gtk_container_get_children (GTK_CONTAINER (etoolbar)); + l = gtk_container_get_children (GTK_CONTAINER (toolbar)); result = g_list_index (l, dock); g_list_free (l); @@ -131,18 +149,19 @@ get_dock_position (EggEditableToolbar *e } static int -get_toolbar_position (EggEditableToolbar *etoolbar, GtkWidget *toolbar) +get_toolbar_position (EggEditableToolbar *toolbar, + GtkWidget *toolbar) { - return get_dock_position (etoolbar, toolbar->parent); + return get_dock_position (toolbar, toolbar->parent); } static int -get_n_toolbars (EggEditableToolbar *etoolbar) +get_n_toolbars (EggEditableToolbar *toolbar) { GList *l; int result; - l = gtk_container_get_children (GTK_CONTAINER (etoolbar)); + l = gtk_container_get_children (GTK_CONTAINER (toolbar)); result = g_list_length (l); g_list_free (l); @@ -151,7 +170,7 @@ get_n_toolbars (EggEditableToolbar *etoo static GtkWidget * get_dock_nth (EggEditableToolbar *etoolbar, - int position) + int position) { GList *l; GtkWidget *result; @@ -163,15 +182,45 @@ get_dock_nth (EggEditableToolbar *etoolb return result; } +static void +set_dock_visible (EggEditableToolbar *toolbar, + GtkWidget *dock, + gboolean visible) +{ + EggEditableToolbarPrivate *priv = toolbar->priv; + + g_object_set (dock, "visible", visible, NULL); + + if (priv->save_hidden) + { + EggTbModelFlags flags; + int position; + + position = get_dock_position (toolbar, dock); + flags = egg_toolbars_model_get_flags (priv->model, position); + + if (visible) + { + flags &= ~(EGG_TB_MODEL_HIDDEN); + } + else + { + flags |= (EGG_TB_MODEL_HIDDEN); + } + + egg_toolbars_model_set_flags (etoolbar->priv->model, position, flags); + } +} + static GtkWidget * -get_toolbar_nth (EggEditableToolbar *etoolbar, - int position) +get_toolbar_nth (EggEditableToolbar *toolbar, + int position) { GList *l; GtkWidget *dock; GtkWidget *result; - dock = get_dock_nth (etoolbar, position); + dock = get_dock_nth (toolbar, position); g_return_val_if_fail (dock != NULL, NULL); l = gtk_container_get_children (GTK_CONTAINER (dock)); @@ -181,29 +230,156 @@ get_toolbar_nth (EggEditableToolbar *eto return result; } -static GtkAction * -find_action (EggEditableToolbar *etoolbar, - const char *name) +/* View toggles menu management */ + +static int +get_toolbar_position_from_action (GtkAction *action) { - GList *l; - GtkAction *action = NULL; + const char *name; + int position; - l = gtk_ui_manager_get_action_groups (etoolbar->priv->manager); + name = gtk_action_get_name (action); + position = (int) g_ascii_strtoull (name + strlen (ACTION_NAME_FORMAT_PREFIX), NULL, 10); - g_return_val_if_fail (name != NULL, NULL); + return position; +} - for (; l != NULL; l = l->next) - { - GtkAction *tmp; +static void +toolbar_view_menu_clean (EggEditableToolbar *toolbar) +{ + EggEditableToolbarPrivate *priv = toolbar->priv; - tmp = gtk_action_group_get_action (GTK_ACTION_GROUP (l->data), name); - if (tmp) - action = tmp; - } + if (priv->toggles_ui_id != 0) { + gtk_ui_manager_remove_ui (priv->manager, priv->toggles_ui_id); + gtk_ui_manager_ensure_update (priv->manager); + priv->toggles_ui_id = 0; + } +} - return action; +static void +toolbar_view_menu_rebuild (EggEditableToolbar *toolbar) +{ + EggEditableToolbarPrivate *priv = toolbar->priv; + char name[ACTION_NAME_FORMAT_LENGTH]; + int n_toolbars, i; + + if (priv->ui_path == NULL) return; + + toolbar_view_menu_clean (toolbar); + + priv->toggles_ui_id = gtk_ui_manager_new_merge_id (priv->manager); + + n_toolbars = egg_toolbars_model_n_toolbars (priv->model); + for (i = 0; i < n_toolbars; i++) { + g_snprintf (name, sizeof (name), ACTION_NAME_FORMAT, i); + + gtk_ui_manager_add_ui (priv->manager, priv->toggles_ui_id, + priv->ui_path, name, name, + GTK_UI_MANAGER_MENUITEM, FALSE); + } +} + +static void +view_action_toggled_cb (GtkAction *action, + EggEditableToolbar *toolbar) +{ + EggEditableToolbarPrivate *priv = toolbar->priv; + EggTbModelFlags flags; + GtkWidget *dock; + int position; + gboolean active; + + active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + position = get_toolbar_position_from_action (action); + + flags = egg_toolbars_model_get_flags (priv->model, position); + if (active) { + flags &= ~EGG_TB_MODEL_HIDDEN; + } else { + flags |= EGG_TB_MODEL_HIDDEN; + } + egg_toolbars_model_set_flags (priv->model, position, flags); + + dock = get_dock_nth (toolbar, position); + set_dock_visible (toolbar, dock, active); +} + +static void +add_view_action_for_toolbar (EggEditableToolbar *toolbar, + int position) +{ + EggEditableToolbarPrivate *priv = toolbar->priv; + GtkToggleAction *action; + char name[ACTION_NAME_FORMAT_LENGTH]; + EggTbModelFlags flags; + + flags = egg_toolbars_model_get_flags (priv->model, position); + + g_snprintf (name, sizeof (name), ACTION_NAME_FORMAT, position); + + action = gtk_toggle_action_new (name, name, "STATUSBAR FIXME", NULL); + gtk_toggle_action_set_active (action, (flags & EGG_TB_MODEL_HIDDEN) == 0); + + g_signal_connect (action, "toggled", + G_CALLBACK (view_action_toggled_cb), toolbar); + + gtk_action_group_add_action (priv->toggles_action_group, GTK_ACTION (action)); + g_object_unref (action); + +// sync_toolbar_name (toolbar, i); FIXME +} + +static void +toolbar_action_group_clean (EggEditableToolbar *toolbar) +{ + EggEditableToolbarPrivate *priv = toolbar->priv; + + if (priv->toggles_action_group != NULL) { + gtk_ui_manager_remove_action_group (priv->manager, priv->toggles_action_group); + priv->toggles_action_group = NULL; + } +} + +static void +connect_proxy_cb (GtkActionGroup *action_group, + GtkAction *action, + GtkWidget *proxy, + gpointer dummy) +{ + if (GTK_IS_MENU_ITEM (proxy)) { + GtkLabel *label; + + label = GTK_LABEL (GTK_BIN (proxy)->child); + + gtk_label_set_use_underline (label, FALSE); + gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_END); + gtk_label_set_max_width_chars (label, LABEL_WIDTH_CHARS); + } +} + +static void +toolbar_action_group_rebuild (EggEditableToolbar *toolbar) +{ + EggEditableToolbarPrivate *priv = toolbar->priv; + int n_toolbars, i; + + if (priv->ui_path == NULL) return; + + priv->toggles_action_group = gtk_action_group_new ("EETViewToolbarGroup"); + g_signal_connect (priv->toggles_action_group, "connect-proxy", + G_CALLBACK (connect_proxy_cb), NULL); + + gtk_ui_manager_insert_action_group (priv->manager, priv->toggles_action_group, -1); + g_object_unref (priv->toggles_action_group); + + n_toolbars = egg_toolbars_model_n_toolbars (priv->model); + for (i = 0; i < n_toolbars; i++) { + add_view_action_for_toolbar (toolbar, i); + } } +/* DND helper functions */ + static void drag_data_delete_cb (GtkWidget *widget, GdkDragContext *context, @@ -228,8 +404,6 @@ drag_begin_cb (GtkWidget *widge GdkDragContext *context, EggEditableToolbar *etoolbar) { - widget = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM); - g_return_if_fail (widget != NULL); gtk_widget_hide (widget); } @@ -238,8 +412,6 @@ drag_end_cb (GtkWidget *widget, GdkDragContext *context, EggEditableToolbar *etoolbar) { - widget = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM); - g_return_if_fail (widget != NULL); gtk_widget_show (widget); } @@ -255,9 +427,6 @@ drag_data_get_cb (GtkWidget *wi const char *name; char *data; - widget = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM); - g_return_if_fail (widget != NULL); - g_return_if_fail (EGG_IS_EDITABLE_TOOLBAR (etoolbar)); model = egg_editable_toolbar_get_model (etoolbar); @@ -276,88 +445,7 @@ drag_data_get_cb (GtkWidget *wi } } -static void -move_item_cb (GtkWidget *menuitem, - EggEditableToolbar *etoolbar) -{ - GtkWidget *toolitem = g_object_get_data (G_OBJECT (menuitem), EGG_TOOLITEM); - GtkTargetList *list = gtk_target_list_new (dest_drag_types, G_N_ELEMENTS (dest_drag_types)); - gtk_drag_begin (toolitem, list, GDK_ACTION_MOVE, 1, NULL); - gtk_target_list_unref (list); -} - -static void -set_dock_visible (EggEditableToolbar *etoolbar, - GtkWidget *dock, - gboolean visible) -{ - if (visible) - { - gtk_widget_show (dock); - } - else - { - gtk_widget_hide (dock); - } - - if (etoolbar->priv->save_hidden) - { - int position = get_dock_position (etoolbar, dock); - EggTbModelFlags flags = egg_toolbars_model_get_flags - (etoolbar->priv->model, position); - - if (visible) - { - flags &= ~(EGG_TB_MODEL_HIDDEN); - } - else - { - flags |= (EGG_TB_MODEL_HIDDEN); - } - - egg_toolbars_model_set_flags (etoolbar->priv->model, position, flags); - } -} - -static void -remove_item_cb (GtkWidget *menuitem, - EggEditableToolbar *etoolbar) -{ - GtkWidget *toolitem = g_object_get_data (G_OBJECT (menuitem), EGG_TOOLITEM); - int pos, toolbar_pos; - - toolbar_pos = get_toolbar_position (etoolbar, toolitem->parent); - pos = gtk_toolbar_get_item_index (GTK_TOOLBAR (toolitem->parent), - GTK_TOOL_ITEM (toolitem)); - - egg_toolbars_model_remove_item (etoolbar->priv->model, - toolbar_pos, pos); - - if (egg_toolbars_model_n_items (etoolbar->priv->model, toolbar_pos) == 0) - { - egg_toolbars_model_remove_toolbar (etoolbar->priv->model, toolbar_pos); - } -} - -static void -remove_toolbar_cb (GtkWidget *menuitem, - EggEditableToolbar *etoolbar) -{ - GtkWidget *toolbar = g_object_get_data (G_OBJECT (menuitem), "egg-toolbar"); - int toolbar_pos; - - toolbar_pos = get_toolbar_position (etoolbar, toolbar); - egg_toolbars_model_remove_toolbar (etoolbar->priv->model, toolbar_pos); -} - -static void -toggle_visibility_cb (GtkWidget *menuitem, - EggEditableToolbar *etoolbar) -{ - GtkWidget *dock = g_object_get_data (G_OBJECT (menuitem), "egg-dock"); - set_dock_visible (etoolbar, dock, !GTK_WIDGET_VISIBLE (dock)); -} - +#if 0 static void egg_editable_toolbar_add_visibility_items (EggEditableToolbar *etoolbar, GtkMenu *popup) @@ -365,6 +453,7 @@ egg_editable_toolbar_add_visibility_item EggToolbarsModel *model = etoolbar->priv->model; GtkCheckMenuItem *item; GtkWidget *dock; + char buffer[40]; int n_toolbars, n_items, n_visible = 0; int i, j, k, l; @@ -386,13 +475,11 @@ egg_editable_toolbar_add_visibility_item gtk_widget_show (separator); gtk_menu_shell_append (GTK_MENU_SHELL (popup), separator); } - + for (i = 0; i < n_toolbars; i++) { - char buffer[40] = "Empty"; - n_items = egg_toolbars_model_n_items (model, i); - for (k = 0, j = 0; j < n_items && k < sizeof(buffer)-1; j++) + for (j = 0; j < n_items; j++) { GValue value = { 0, }; GtkAction *action; @@ -404,10 +491,12 @@ egg_editable_toolbar_add_visibility_item if (action == NULL) continue; g_value_init (&value, G_TYPE_STRING); - g_object_get_property (G_OBJECT (action), "label", &value); + g_object_get_property (G_OBJECT (action), "short-label", &value); name = g_value_get_string (&value); if (name == NULL) continue; + /* FIXME FIXME eek! check if this is UTF-8 clean! */ + if (j > 0) { if(kchildren == NULL); - - if (etoolbar != NULL && toolitem != NULL) - { - if (!separated) - { - item = gtk_separator_menu_item_new (); - gtk_widget_show (item); - gtk_menu_shell_append (GTK_MENU_SHELL (popup), item); - separated = 1; - } - - item = gtk_menu_item_new_with_mnemonic (_("_Move on Toolbar")); - g_object_set_data (G_OBJECT (item), EGG_TOOLITEM, toolitem); - gtk_widget_show (item); - gtk_menu_shell_append (GTK_MENU_SHELL (popup), item); - g_signal_connect (item, "activate", - G_CALLBACK (move_item_cb), - etoolbar); - - item = gtk_image_menu_item_new_with_mnemonic (_("_Remove from Toolbar")); - g_object_set_data (G_OBJECT (item), EGG_TOOLITEM, toolitem); - gtk_widget_show (item); - image = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - gtk_menu_shell_append (GTK_MENU_SHELL (popup), item); - g_signal_connect (item, "activate", - G_CALLBACK (remove_item_cb), - etoolbar); - } + EggEditableToolbarPrivate *priv = etoolbar->priv; + GtkWidget *item, *toolbar; + + item = gtk_widget_get_ancestor (priv->selected, GTK_TYPE_TOOL_ITEM); + toolbar = gtk_widget_get_ancestor (item, GTK_TYPE_TOOLBAR); + g_return_if_fail (toolbar); - if (etoolbar != NULL && toolbar != NULL) + if (item_position) { - int position; - EggTbModelFlags flags; - - position = get_toolbar_position (etoolbar, toolbar); - flags = egg_toolbars_model_get_flags (etoolbar->priv->model, position); - - if (etoolbar->priv->edit_mode > 0 && (flags & EGG_TB_MODEL_NOT_REMOVABLE)==0) + if (item) { - if (!separated) - { - item = gtk_separator_menu_item_new (); - gtk_widget_show (item); - gtk_menu_shell_append (GTK_MENU_SHELL (popup), item); - separated = 1; - } - - item = gtk_image_menu_item_new_with_mnemonic (_("_Remove Toolbar")); - g_object_set_data (G_OBJECT (item), "egg-toolbar", toolbar); - gtk_widget_show (item); - image = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - gtk_menu_shell_append (GTK_MENU_SHELL (popup), item); - g_signal_connect (item, "activate", - G_CALLBACK (remove_toolbar_cb), - etoolbar); + *item_position = gtk_toolbar_get_item_index (GTK_TOOLBAR (toolbar), + GTK_TOOL_ITEM (item)); } - - if (egg_toolbars_model_n_toolbars (etoolbar->priv->model) > 1) + else { - egg_editable_toolbar_add_visibility_items (etoolbar, popup); + *item_position = -1; } } -} -static void -popup_context_menu_cb (GtkWidget *toolbar, - gint x, - gint y, - gint button_number, - EggEditableToolbar *etoolbar) -{ - GtkMenu *menu = GTK_MENU (gtk_menu_new ()); - egg_editable_toolbar_add_popup_items (toolbar, menu); - gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button_number, - gtk_get_current_event_time ()); + if (toolbar_position) + { + *toolbar_position = get_toolbar_position (etoolbar, toolbar); + } } -static gboolean -button_press_event_cb (GtkWidget *widget, - GdkEventButton *event, - EggEditableToolbar *etoolbar) +static void +prepare_popup (EggEditableToolbar *toolbar, + int toolbar, + int item) { - if (event->button == 3) - { - GtkMenu *menu = GTK_MENU (gtk_menu_new ()); - egg_editable_toolbar_add_popup_items (widget, menu); - gtk_menu_popup (menu, NULL, NULL, NULL, NULL, event->button, - event->time); - return TRUE; - } - - return FALSE; + EggEditableToolbarPrivate *priv = etoolbar->priv; + + g_return_if_fail (priv->popup_ui_id == 0); + + priv->popup_ui_id = gtk_ui_manager_new_merge_id (priv->manager); + g_signal_emit (etoolbar, signals[PREPARE_POPUP], 0, + priv->popup_ui_id, + toolbar, + item); } static void -configure_item_sensitivity (GtkToolItem *item, EggEditableToolbar *etoolbar) +popup_menu_deactivate_cb (GtkWidgt *menu, + EggEditableToolbar *toolbar) { - GtkAction *action; - char *name; - - g_return_if_fail (etoolbar != NULL); - - if (etoolbar->priv->edit_mode > 0) + EggEditableToolbarPrivate *priv = etoolbar->priv; + + g_signal_handlers_disconnect_by_func + (menu, G_CALLBACK (popup_menu_deactivate_cb), toolbar); + + priv->popup_menu = NULL; + + gtk_ui_manager_remove_ui (priv->popup_ui_id); + priv->popup_ui_id = 0; +} + +static void +toolbar_popup_context_menu_cb (GtkWidget *widget, + int x, + int y, + int button, + EggEditableToolbar *etoolbar) +{ + EggEditableToolbarPrivate *priv = etoolbar->priv; + int i; + + i = get_toolbar_position (etoolbar, widget); + prepare_popup (etoolbar, i, -1); + + priv->popup_menu = gtk_ui_manager_get_widget (priv->manager, "/EEToolbarPopup"); + g_signal_connect (priv->popup_menu, "deactivate", + G_CALLBACK (popup_menu_deactivate_cb), etoolbar); + + gtk_menu_popup (GTK_MENU (priv->popup_menu), NULL, NULL, + NULL /* FIXME ephy_gui_position_menu_on_toolbar */, NULL, + button, gtk_get_current_event_time ()); +} + +static gboolean +item_button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + EggEditableToolbar *etoolbar) +{ + EggEditableToolbarPrivate *priv = etoolbar->priv; + GtkWidget *item, *toolbar; + int tpos, ipos; + + if (event->button == 3) { - GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (item), GTK_SENSITIVE); - gtk_tool_item_set_use_drag_window (item, TRUE); - gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE); - return; + item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM); + g_return_val_if_fail (item, FALSE); + + toolbar = gtk_widget_get_ancestor (item, GTK_TYPE_TOOLBAR); + g_return_val_if_fail (toolbar, FALSE); + + tpos = get_toolbar_position (etoolbar, toolbar); + ipos = gtk_toolbar_get_item_index (GTK_TOOLBAR (toolbar), + GTK_TOOL_ITEM (item)); + + prepare_popup (etoolbar, tpos, ipos); + + priv->popup_menu = gtk_ui_manager_get_widget (priv->manager, "/EEToolbarPopup"); + g_signal_connect (priv->popup_menu, "deactivate", + G_CALLBACK (popup_menu_deactivate_cb), etoolbar); + + gtk_menu_popup (GTK_MENU (priv->popup_menu), NULL, NULL, + NULL /* FIXME ephy_gui_position_menu_on_toolbar */, NULL, + event->button, event->time); + + return TRUE; } + + return FALSE; +} + +/* FIXME keyboard popups!!! */ + +/* Widget helper functions */ + +static void +configure_item_sensitivity (GtkToolItem *item, EggEditableToolbar *etoolbar) +{ + GtkAction *action; + char *name; name = g_object_get_data (G_OBJECT (item), EGG_ITEM_NAME); action = name ? find_action (etoolbar, name) : NULL; - - if (action != NULL && gtk_action_is_sensitive (action)) - { - GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (item), GTK_SENSITIVE); - gtk_tool_item_set_use_drag_window (item, FALSE); - gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE); - } - else + + if (action) { - gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE); - gtk_tool_item_set_use_drag_window (item, TRUE); - GTK_WIDGET_SET_FLAGS (GTK_WIDGET (item), GTK_SENSITIVE); + g_object_notify (G_OBJECT (action), "sensitive"); } + + gtk_tool_item_set_use_drag_window (item, + (etoolbar->priv->edit_mode > 0) || + GTK_IS_SEPARATOR_TOOL_ITEM (item)); + } static void @@ -622,9 +719,6 @@ configure_item_cursor (GtkToolItem *item else { gdk_window_set_cursor (GTK_WIDGET(item)->window, NULL); - - gtk_drag_source_set (GTK_WIDGET (item), GDK_BUTTON2_MASK, dest_drag_types, - G_N_ELEMENTS (dest_drag_types), GDK_ACTION_MOVE); } } @@ -638,7 +732,7 @@ connect_widget_signals (GtkWidget *proxy (gpointer) etoolbar); } - if (GTK_IS_BUTTON (proxy) || GTK_IS_TOOL_ITEM (proxy)) + if (GTK_IS_TOOL_ITEM (proxy)) { g_signal_connect (proxy, "drag_begin", G_CALLBACK (drag_begin_cb), etoolbar); @@ -648,12 +742,12 @@ connect_widget_signals (GtkWidget *proxy G_CALLBACK (drag_data_get_cb), etoolbar); g_signal_connect (proxy, "drag_data_delete", G_CALLBACK (drag_data_delete_cb), etoolbar); - g_signal_connect (proxy, "drag_data_get", - G_CALLBACK (drag_data_get_cb), etoolbar); + } + + if (GTK_IS_BUTTON (proxy) || GTK_IS_TOOL_ITEM (proxy)) + { g_signal_connect (proxy, "button-press-event", - G_CALLBACK (button_press_event_cb), etoolbar); - gtk_drag_source_set (proxy, GDK_BUTTON2_MASK, dest_drag_types, - G_N_ELEMENTS (dest_drag_types), GDK_ACTION_MOVE); + G_CALLBACK (item_button_press_event_cb), etoolbar); } } @@ -664,7 +758,11 @@ action_sensitive_cb (GtkAction *action { EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR (gtk_widget_get_ancestor (GTK_WIDGET (item), EGG_TYPE_EDITABLE_TOOLBAR)); - configure_item_sensitivity (item, etoolbar); + + if (etoolbar->priv->edit_mode > 0) + { + gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE); + } } static GtkToolItem * @@ -678,7 +776,6 @@ create_item_from_action (EggEditableTool if (strcmp (name, "_separator") == 0) { item = gtk_separator_tool_item_new (); - gtk_tool_item_set_use_drag_window (item, TRUE); } else { @@ -912,8 +1009,8 @@ create_dock (EggEditableToolbar *etoolba g_signal_connect (toolbar, "drag_data_received", G_CALLBACK (toolbar_drag_data_received_cb), etoolbar); - g_signal_connect (toolbar, "popup_context_menu", - G_CALLBACK (popup_context_menu_cb), etoolbar); + g_signal_connect (toolbar, "popup-context-menu", + G_CALLBACK (toolbar_popup_context_menu_cb), etoolbar); configure_drag_dest (etoolbar, GTK_TOOLBAR (toolbar)); @@ -978,6 +1075,8 @@ toolbar_changed_cb (EggToolbarsModel * { set_fixed_style (etoolbar, style); } + + /* FIXME: update the view action label! */ } static void @@ -1035,7 +1134,12 @@ toolbar_added_cb (EggToolbarsModel *mo gtk_widget_show_all (dock); update_fixed (etoolbar); -} + + /* this relies on the fact that position == n_toolbars here!! */ + add_view_action_for_toolbar (etoolbar, position); + toolbar_view_menu_clean (etoolbar); + toolbar_view_menu_rebuild (etoolbar); +} static void toolbar_removed_cb (EggToolbarsModel *model, @@ -1106,11 +1210,17 @@ item_removed_cb (EggToolbarsModel *mod item = GTK_WIDGET (gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), position)); g_return_if_fail (item != NULL); + + if (item == priv->selected) + { + /* FIXME */ + } + gtk_container_remove (GTK_CONTAINER (toolbar), item); } static void -egg_editable_toolbar_construct (EggEditableToolbar *etoolbar) +egg_editable_toolbar_build (EggEditableToolbar *etoolbar) { int i, l, n_items, n_toolbars; EggToolbarsModel *model = etoolbar->priv->model; @@ -1202,27 +1312,266 @@ egg_editable_toolbar_deconstruct (EggEdi g_list_free (children); } + +static const char popup_ui_string[] = +"" + " + "" + "" + "" + "" +""; + +#define DEFAULT_ICON_HEIGHT 20 +#define DEFAULT_ICON_WIDTH 0 + +static void +fake_expose_widget (GtkWidget *widget, + GdkPixmap *pixmap) +{ + GdkWindow *tmp_window; + GdkEventExpose event; + + event.type = GDK_EXPOSE; + event.window = pixmap; + event.send_event = FALSE; + event.area = widget->allocation; + event.region = NULL; + event.count = 0; + + tmp_window = widget->window; + widget->window = pixmap; + gtk_widget_send_expose (widget, (GdkEvent *) &event); + widget->window = tmp_window; +} + +/* We should probably experiment some more with this. + * Right now the rendered icon is pretty good for most + * themes. However, the icon is slightly large for themes + * with large toolbar icons. + */ +static GdkPixbuf * +new_pixbuf_from_widget (GtkWidget *widget) +{ + GtkWidget *window; + GdkPixbuf *pixbuf; + GtkRequisition requisition; + GtkAllocation allocation; + GdkPixmap *pixmap; + GdkVisual *visual; + gint icon_width; + gint icon_height; + + icon_width = DEFAULT_ICON_WIDTH; + + if (!gtk_icon_size_lookup_for_settings (gtk_settings_get_default (), + GTK_ICON_SIZE_LARGE_TOOLBAR, + NULL, + &icon_height)) + { + icon_height = DEFAULT_ICON_HEIGHT; + } + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + gtk_container_add (GTK_CONTAINER (window), widget); + gtk_widget_realize (window); + gtk_widget_show (widget); + gtk_widget_realize (widget); + gtk_widget_map (widget); + + /* Gtk will never set the width or height of a window to 0. So setting the width to + * 0 and than getting it will provide us with the minimum width needed to render + * the icon correctly, without any additional window background noise. + * This is needed mostly for pixmap based themes. + */ + gtk_window_set_default_size (GTK_WINDOW (window), icon_width, icon_height); + gtk_window_get_size (GTK_WINDOW (window),&icon_width, &icon_height); + + gtk_widget_size_request (window, &requisition); + allocation.x = 0; + allocation.y = 0; + allocation.width = icon_width; + allocation.height = icon_height; + gtk_widget_size_allocate (window, &allocation); + gtk_widget_size_request (window, &requisition); + + /* Create a pixmap */ + visual = gtk_widget_get_visual (window); + pixmap = gdk_pixmap_new (NULL, icon_width, icon_height, visual->depth); + gdk_drawable_set_colormap (GDK_DRAWABLE (pixmap), gtk_widget_get_colormap (window)); + + /* Draw the window */ + gtk_widget_ensure_style (window); + g_assert (window->style); + g_assert (window->style->font_desc); + + fake_expose_widget (window, pixmap); + fake_expose_widget (widget, pixmap); + + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, icon_width, icon_height); + gdk_pixbuf_get_from_drawable (pixbuf, pixmap, NULL, 0, 0, 0, 0, icon_width, icon_height); + + gtk_widget_destroy (window); + + return pixbuf; +} + +static GdkPixbuf * +new_separator_pixbuf () +{ + GtkWidget *separator; + GdkPixbuf *pixbuf; + + separator = gtk_vseparator_new (); + pixbuf = new_pixbuf_from_widget (separator); + return pixbuf; +} + +static void +update_separator_image (GtkImage *image) +{ + GdkPixbuf *pixbuf = new_separator_pixbuf (); + gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf); + g_object_unref (pixbuf); +} + +static gboolean +style_set_cb (GtkWidget *widget, + GtkStyle *previous_style, + GtkImage *image) +{ + + update_separator_image (image); + return FALSE; +} + +GtkWidget * +_egg_editable_toolbar_new_separator_image (void) +{ + GtkWidget *image = gtk_image_new (); + update_separator_image (GTK_IMAGE (image)); + g_signal_connect (G_OBJECT (image), "style_set", + G_CALLBACK (style_set_cb), GTK_IMAGE (image)); + + return image; +} + +/* Action helper functions */ + +static void +move_item_cb (GtkAction *action, + EggEditableToolbar *toolbar) +{ + GtkWidget *toolitem; + GtkTargetList *list; + + toolitem = gtk_widget_get_ancestor (egg_editable_toolbar_get_selected (toolbar), GTK_TYPE_TOOL_ITEM); + list = gtk_target_list_new (dest_drag_types, G_N_ELEMENTS (dest_drag_types)); + + /* FIXME remove this crap now that the gtk+ bug is fixed */ + GdkEvent *realevent = gtk_get_current_event(); + GdkEventMotion event; + event.type = GDK_MOTION_NOTIFY; + event.window = realevent->any.window; + event.send_event = FALSE; + event.axes = NULL; + event.time = gdk_event_get_time (realevent); + gdk_event_get_state (realevent, &event.state); + gdk_event_get_coords (realevent, &event.x, &event.y); + gdk_event_get_root_coords (realevent, &event.x_root, &event.y_root); + + gtk_drag_begin (toolitem, list, GDK_ACTION_MOVE, 1, (GdkEvent *)&event); + gtk_target_list_unref (list); +} + +static void +remove_item_cb (GtkAction *action, + EggEditableToolbar *toolbar) +{ + EggEditableToolbarPrivate *priv = toolbar->priv; + GtkWidget *toolitem; + int pos, toolbar_pos; + + toolitem = gtk_widget_get_ancestor (egg_editable_toolbar_get_selected (toolbar), GTK_TYPE_TOOL_ITEM); + + toolbar_pos = get_toolbar_position (etoolbar, toolitem->parent); + pos = gtk_toolbar_get_item_index (GTK_TOOLBAR (toolitem->parent), + GTK_TOOL_ITEM (toolitem)); + + egg_toolbars_model_remove_item (toolbar->priv->model, + toolbar_pos, pos); + + if (egg_toolbars_model_n_items (etoolbar->priv->model, toolbar_pos) == 0) + { + egg_toolbars_model_remove_toolbar (etoolbar->priv->model, toolbar_pos); + } +} + +static void +remove_toolbar_cb (GtkAction *action, + EggEditableToolbar *etoolbar) +{ + EggEditableToolbarPrivate *priv = toolbar->priv; + GtkWidget *selected, *toolbar; + int toolbar_pos; + + /* FIXME confirmation?? */ + + selected = egg_editable_toolbar_get_selected (toolbar); + toolbar = gtk_widget_get_ancestor (selected, GTK_TYPE_TOOLBAR); + + toolbar_pos = get_toolbar_position (toolbar, toolbar); + egg_toolbars_model_remove_toolbar (priv->model, toolbar_pos); +} + +static const GtkActionEntry popup_actions[] = { + { "EETMoveItem", NULL, N_("_Move on Toolbar"), NULL, + N_("Move the selected item on the toolbar"), + G_CALLBACK (move_item_cb) }, + { "EETRemoveItem", GTK_STOCK_REMOVE, N_("_Remove from Toolbar"), NULL, + N_("Remove the selected item from the toolbar"), + G_CALLBACK (remove_item_cb) }, + { "EETRemoveToolbar", GTK_STOCK_REMOVE, N_("_Remove Toolbar"), NULL, + N_("Remove the selected toolbar"), + G_CALLBACK (remove_toolbar_cb) } +}; + +/* Public API */ + +EggToolbarsModel * +egg_editable_toolbar_get_model (EggEditableToolbar *toolbar) +{ + EggEditableToolbarPrivate *priv = toolbar->priv; + + return priv->model; +} + void egg_editable_toolbar_set_model (EggEditableToolbar *toolbar, EggToolbarsModel *model) { - g_return_if_fail (EGG_IS_TOOLBARS_MODEL (model)); - g_return_if_fail (EGG_IS_EDITABLE_TOOLBAR (toolbar)); - g_return_if_fail (toolbar->priv->manager); + EggEditableToolbarPrivate *priv = toolbar->priv; - if (toolbar->priv->model == model) return; + if (priv->model == model) return; - if (toolbar->priv->model) + if (priv->model) { + toolbar_view_menu_clean (toolbar); + toolbar_action_group_clean (toolbar); + egg_editable_toolbar_disconnect_model (toolbar); egg_editable_toolbar_deconstruct (toolbar); - g_object_unref (toolbar->priv->model); + g_object_unref (priv->model); } - toolbar->priv->model = g_object_ref (model); + priv->model = g_object_ref (model); + + toolbar_action_group_rebuild (toolbar); + toolbar_view_menu_rebuild (toolbar); - egg_editable_toolbar_construct (toolbar); + egg_editable_toolbar_build (toolbar); g_signal_connect (model, "item_added", G_CALLBACK (item_added_cb), toolbar); @@ -1236,13 +1585,106 @@ egg_editable_toolbar_set_model (EggEdita G_CALLBACK (toolbar_changed_cb), toolbar); } +/* Helpers */ + + +/* Class implementation */ + static void -egg_editable_toolbar_set_ui_manager (EggEditableToolbar *etoolbar, - GtkUIManager *manager) +egg_editable_toolbar_init (EggEditableToolbar *toolbar) { - g_return_if_fail (GTK_IS_UI_MANAGER (manager)); + EggEditableToolbarPrivate *priv; - etoolbar->priv->manager = g_object_ref (manager); + priv = toolbar->priv = EGG_EDITABLE_TOOLBAR_GET_PRIVATE (etoolbar); + + priv->save_hidden = TRUE; +} + +static GObject * +egg_editable_toolbar_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params) +{ + GObject *object; + EggEditableToolbar *toolbar; + EggEditableToolbarPrivate *priv; + + object = parent_class->constructor (type, n_construct_properties, + construct_params); + + toolbar = EGG_EDITABLE_TOOLBAR (toolbar); + priv = toolbar->priv; + + g_assert (priv->model); + g_assert (priv->manager); + + priv->action_group = gtk_action_group_new ("ETTPopupActions"); + gtk_action_group_add_actions (priv->action_group, popup_actions, + G_N_ELEMENTS (popup_actions), toolbar); + gtk_ui_manager_insert_action_group (manager, priv->action_group, -1); + g_object_unref (priv->action_group); + + priv->ui_id = gtk_ui_manager_add_ui_from_string (priv->manager, + popup_ui_string, -1, + NULL); + + return object; +} + +static void +egg_editable_toolbar_dispose (GObject *object) +{ + EggEditableToolbar *toolbar = EGG_EDITABLE_TOOLBAR (object); + EggEditableToolbarPrivate *priv = toolbar->priv; + + if (priv->fixed_toolbar != NULL) + { + g_object_unref (priv->fixed_toolbar); + priv->fixed_toolbar = NULL; + } + + if (priv->popup_menu) + { + gtk_menu_shell_deactivate (GTK_MENU_SHELL (priv->popup_menu)); + priv->popup_menu = NULL; + + g_assert (priv->popup_ui_id == 0); + } + + if (priv->manager != NULL) + { + toolbar_view_menu_clean (toolbar); + toolbar_action_group_clean (toolbar); + + if (priv->ui_id != 0) + { + gtk_ui_manager_remove_ui (priv->manager, priv->ui_id); + priv->ui_id = 0; + } + if (priv->action_group != NULL) + { + gtk_ui_manager_remove_action_group (priv->manager, priv->action_group); + priv->action_group = NULL; + } + + g_object_unref (priv->manager); + priv->manager = NULL; + } + + if (priv->ui_path != NULL) + { + g_free (priv->ui_path); + priv->ui_path = NULL; + } + + if (priv->model != NULL) + { + egg_editable_toolbar_disconnect_model (toolbar); + g_object_unref (priv->model); + priv->model = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); } static void @@ -1251,15 +1693,22 @@ egg_editable_toolbar_set_property (GObje const GValue *value, GParamSpec *pspec) { - EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR (object); + EggEditableToolbar *toolbar = EGG_EDITABLE_TOOLBAR (object); + EggEditableToolbarPrivate *priv = toolbar->priv; switch (prop_id) { case PROP_UI_MANAGER: - egg_editable_toolbar_set_ui_manager (etoolbar, g_value_get_object (value)); + priv->manager = g_value_dup_object (value); + break; + case PROP_UI_PATH: + priv->ui_path = g_value_dup_string (value); break; case PROP_TOOLBARS_MODEL: - egg_editable_toolbar_set_model (etoolbar, g_value_get_object (value)); + egg_editable_toolbar_set_model (toolbar, g_value_get_object (value)); + break; + case PROP_SELECTED: + egg_editable_toolbar_set_selected (etoolbar, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1273,15 +1722,21 @@ egg_editable_toolbar_get_property (GObje GValue *value, GParamSpec *pspec) { - EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR (object); + EggEditableToolbar *toolbar = EGG_EDITABLE_TOOLBAR (object); + EggEditableToolbarPrivate *priv = toolbar->priv; switch (prop_id) { case PROP_UI_MANAGER: - g_value_set_object (value, etoolbar->priv->manager); + g_value_set_object (value, priv->manager); break; + case PROP_UI_PATH: + g_value_set_string (value, priv->ui_path); case PROP_TOOLBARS_MODEL: - g_value_set_object (value, etoolbar->priv->model); + g_value_set_object (value, priv->model); + break; + case PROP_SELECTED: + g_value_set_object (value, etoolbar->priv->selected); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1296,18 +1751,33 @@ egg_editable_toolbar_class_init (EggEdit parent_class = g_type_class_peek_parent (klass); - object_class->finalize = egg_editable_toolbar_finalize; + object_class->constructor = egg_editable_toolbar_constructor; + object_class->dispose = egg_editable_toolbar_dispose; object_class->set_property = egg_editable_toolbar_set_property; object_class->get_property = egg_editable_toolbar_get_property; - egg_editable_toolbar_signals[ACTION_REQUEST] = - g_signal_new ("action_request", + signals[ACTION_REQUEST] = + g_signal_new ("action-request", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (EggEditableToolbarClass, action_request), - NULL, NULL, g_cclosure_marshal_VOID__STRING, + NULL, NULL, + g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); + signals[PREPARE_POPUP] = + g_signal_new ("prepare-popup", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EggEditableToolbarClass, prepare_popup), + NULL, NULL, + egg_marshal_VOID__UINT_INT_INT, + G_TYPE_NONE, + 3, + G_TYPE_UINT, + G_TYPE_INT, + G_TYPE_INT); + g_object_class_install_property (object_class, PROP_UI_MANAGER, g_param_spec_object ("ui-manager", @@ -1322,95 +1792,116 @@ egg_editable_toolbar_class_init (EggEdit "Toolbars Model", EGG_TYPE_TOOLBARS_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); + g_object_class_install_property (object_class, + PROP_SELECTED, + g_param_spec_object ("selected", + "Selected", + "Selected toolitem", + GTK_TYPE_TOOL_ITEM, + G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); + + g_object_class_install_property (object_class, + PROP_UI_PATH, + g_param_spec_string ("ui-path", + "ui-path", + "ui-path", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_type_class_add_private (object_class, sizeof (EggEditableToolbarPrivate)); } -static void -egg_editable_toolbar_init (EggEditableToolbar *etoolbar) -{ - etoolbar->priv = EGG_EDITABLE_TOOLBAR_GET_PRIVATE (etoolbar); - etoolbar->priv->save_hidden = TRUE; -} +/* public API */ -static void -egg_editable_toolbar_finalize (GObject *object) +GType +egg_editable_toolbar_get_type (void) { - EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR (object); - - if (etoolbar->priv->fixed_toolbar) - { - g_object_unref (etoolbar->priv->fixed_toolbar); - } + static GType type = 0; - if (etoolbar->priv->manager) + if (G_UNLIKELY (type == 0)) { - g_object_unref (etoolbar->priv->manager); - } + static const GTypeInfo our_info = { + sizeof (EggEditableToolbarClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) egg_editable_toolbar_class_init, + NULL, + NULL, /* class_data */ + sizeof (EggEditableToolbar), + 0, /* n_preallocs */ + (GInstanceInitFunc) egg_editable_toolbar_init + }; - if (etoolbar->priv->model) - { - egg_editable_toolbar_disconnect_model (etoolbar); - g_object_unref (etoolbar->priv->model); + type = g_type_register_static (GTK_TYPE_VBOX, + "EggEditableToolbar", + &our_info, 0); } - G_OBJECT_CLASS (parent_class)->finalize (object); + return type; } GtkWidget * -egg_editable_toolbar_new (GtkUIManager *manager) +egg_editable_toolbar_new (GtkUIManager *manager, + const char *ui_path) { - return GTK_WIDGET (g_object_new (EGG_TYPE_EDITABLE_TOOLBAR, - "ui-manager", manager, - NULL)); + return GTK_WIDGET (g_object_new (EGG_TYPE_EDITABLE_TOOLBAR, + "ui-manager", manager, + "ui-path", ui_path, + NULL)); } GtkWidget * egg_editable_toolbar_new_with_model (GtkUIManager *manager, - EggToolbarsModel *model) + EggToolbarsModel *model, + const char *ui_path) { return GTK_WIDGET (g_object_new (EGG_TYPE_EDITABLE_TOOLBAR, - "ui-manager", manager, - "model", model, + "ui-manager", manager, + "model", model, + "ui-path", ui_path, NULL)); } gboolean egg_editable_toolbar_get_edit_mode (EggEditableToolbar *etoolbar) { - return (etoolbar->priv->edit_mode > 0); + EggEditableToolbarPrivate *priv = etoolbar->priv; + + return priv->edit_mode > 0; } + void egg_editable_toolbar_set_edit_mode (EggEditableToolbar *etoolbar, - gboolean mode) + gboolean mode) { + EggEditableToolbarPrivate *priv = etoolbar->priv; int i, l, n_items; - i = etoolbar->priv->edit_mode; + i = priv->edit_mode; if (mode) { - etoolbar->priv->edit_mode++; + priv->edit_mode++; } else { - g_return_if_fail (etoolbar->priv->edit_mode > 0); - etoolbar->priv->edit_mode--; + g_return_if_fail (priv->edit_mode > 0); + priv->edit_mode--; } - i *= etoolbar->priv->edit_mode; + i *= priv->edit_mode; if (i == 0) { - for (i = get_n_toolbars (etoolbar)-1; i >= 0; i--) + for (i = get_n_toolbars (toolbar)-1; i >= 0; i--) { GtkWidget *toolbar; - toolbar = get_toolbar_nth (etoolbar, i); + toolbar = get_toolbar_nth (toolbar, i); n_items = gtk_toolbar_get_n_items (GTK_TOOLBAR (toolbar)); - if (n_items == 0 && etoolbar->priv->edit_mode == 0) + if (n_items == 0 && priv->edit_mode == 0) { - egg_toolbars_model_remove_toolbar (etoolbar->priv->model, i); + egg_toolbars_model_remove_toolbar (priv->model, i); } else { @@ -1430,12 +1921,11 @@ egg_editable_toolbar_set_edit_mode (EggE void egg_editable_toolbar_show (EggEditableToolbar *etoolbar, - const char *name) + const char *name) { + EggEditableToolbarPrivate *priv = etoolbar->priv; + EggToolbarsModel *model = priv->model; int i, n_toolbars; - EggToolbarsModel *model = etoolbar->priv->model; - - g_return_if_fail (model != NULL); n_toolbars = egg_toolbars_model_n_toolbars (model); for (i = 0; i < n_toolbars; i++) @@ -1444,20 +1934,19 @@ egg_editable_toolbar_show (EggEditableTo toolbar_name = egg_toolbars_model_toolbar_nth (model, i); if (strcmp (toolbar_name, name) == 0) - { - gtk_widget_show (get_dock_nth (etoolbar, i)); - } + { + gtk_widget_show (get_dock_nth (etoolbar, i)); + } } } void egg_editable_toolbar_hide (EggEditableToolbar *etoolbar, - const char *name) + const char *name) { + EggEditableToolbarPrivate *priv = etoolbar->priv; + EggToolbarsModel *model = priv->model; int i, n_toolbars; - EggToolbarsModel *model = etoolbar->priv->model; - - g_return_if_fail (model != NULL); n_toolbars = egg_toolbars_model_n_toolbars (model); for (i = 0; i < n_toolbars; i++) @@ -1466,17 +1955,18 @@ egg_editable_toolbar_hide (EggEditableTo toolbar_name = egg_toolbars_model_toolbar_nth (model, i); if (strcmp (toolbar_name, name) == 0) - { - gtk_widget_hide (get_dock_nth (etoolbar, i)); - } + { + gtk_widget_hide (get_dock_nth (etoolbar, i)); + } } } void egg_editable_toolbar_set_fixed (EggEditableToolbar *toolbar, - GtkToolbar *fixed_toolbar) + GtkToolbar *fixed_toolbar) { - g_return_if_fail (EGG_IS_EDITABLE_TOOLBAR (toolbar)); + EggEditableToolbarPrivate *priv = toolbar->priv; + g_return_if_fail (!fixed_toolbar || GTK_IS_TOOLBAR (fixed_toolbar)); if (toolbar->priv->fixed_toolbar) @@ -1497,143 +1987,32 @@ egg_editable_toolbar_set_fixed (EggEdita update_fixed (toolbar); } -#define DEFAULT_ICON_HEIGHT 20 -#define DEFAULT_ICON_WIDTH 0 - -static void -fake_expose_widget (GtkWidget *widget, - GdkPixmap *pixmap) +GtkWidget * +egg_editable_toolbar_get_selected (EggEditableToolbar *etoolbar) { - GdkWindow *tmp_window; - GdkEventExpose event; - - event.type = GDK_EXPOSE; - event.window = pixmap; - event.send_event = FALSE; - event.area = widget->allocation; - event.region = NULL; - event.count = 0; + EggEditableToolbarPrivate *priv = toolbar->priv; - tmp_window = widget->window; - widget->window = pixmap; - gtk_widget_send_expose (widget, (GdkEvent *) &event); - widget->window = tmp_window; + return priv->selected; } -/* We should probably experiment some more with this. - * Right now the rendered icon is pretty good for most - * themes. However, the icon is slightly large for themes - * with large toolbar icons. - */ -static GdkPixbuf * -new_pixbuf_from_widget (GtkWidget *widget) +void +egg_editable_toolbar_set_selected (EggEditableToolbar *toolbar, + GtkWidget *widget) { - GtkWidget *window; - GdkPixbuf *pixbuf; - GtkRequisition requisition; - GtkAllocation allocation; - GdkPixmap *pixmap; - GdkVisual *visual; - gint icon_width; - gint icon_height; - - icon_width = DEFAULT_ICON_WIDTH; - - if (!gtk_icon_size_lookup_for_settings (gtk_settings_get_default (), - GTK_ICON_SIZE_LARGE_TOOLBAR, - NULL, - &icon_height)) - { - icon_height = DEFAULT_ICON_HEIGHT; - } - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - - gtk_container_add (GTK_CONTAINER (window), widget); - gtk_widget_realize (window); - gtk_widget_show (widget); - gtk_widget_realize (widget); - gtk_widget_map (widget); - - /* Gtk will never set the width or height of a window to 0. So setting the width to - * 0 and than getting it will provide us with the minimum width needed to render - * the icon correctly, without any additional window background noise. - * This is needed mostly for pixmap based themes. - */ - gtk_window_set_default_size (GTK_WINDOW (window), icon_width, icon_height); - gtk_window_get_size (GTK_WINDOW (window),&icon_width, &icon_height); - - gtk_widget_size_request (window, &requisition); - allocation.x = 0; - allocation.y = 0; - allocation.width = icon_width; - allocation.height = icon_height; - gtk_widget_size_allocate (window, &allocation); - gtk_widget_size_request (window, &requisition); - - /* Create a pixmap */ - visual = gtk_widget_get_visual (window); - pixmap = gdk_pixmap_new (NULL, icon_width, icon_height, visual->depth); - gdk_drawable_set_colormap (GDK_DRAWABLE (pixmap), gtk_widget_get_colormap (window)); + EggEditableToolbarPrivate *priv = toolbar->priv; + GtkActionGroup *action_group = priv->action_group; + GtkAction *action; + gboolean is_toolitem, is_toolbar; - /* Draw the window */ - gtk_widget_ensure_style (window); - g_assert (window->style); - g_assert (window->style->font_desc); + priv->selected = widget; - fake_expose_widget (window, pixmap); - fake_expose_widget (widget, pixmap); - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, icon_width, icon_height); - gdk_pixbuf_get_from_drawable (pixbuf, pixmap, NULL, 0, 0, 0, 0, icon_width, icon_height); - - gtk_widget_destroy (window); - - return pixbuf; -} - -static GdkPixbuf * -new_separator_pixbuf () -{ - GtkWidget *separator; - GdkPixbuf *pixbuf; + is_toolitem = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM) != 0; + is_toolbar = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOLBAR) != 0; // FIXME this is so wrong! - separator = gtk_vseparator_new (); - pixbuf = new_pixbuf_from_widget (separator); - return pixbuf; -} - -static void -update_separator_image (GtkImage *image) -{ - GdkPixbuf *pixbuf = new_separator_pixbuf (); - gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf); - g_object_unref (pixbuf); -} - -static gboolean -style_set_cb (GtkWidget *widget, - GtkStyle *previous_style, - GtkImage *image) -{ - - update_separator_image (image); - return FALSE; -} - -GtkWidget * -_egg_editable_toolbar_new_separator_image (void) -{ - GtkWidget *image = gtk_image_new (); - update_separator_image (GTK_IMAGE (image)); - g_signal_connect (G_OBJECT (image), "style_set", - G_CALLBACK (style_set_cb), GTK_IMAGE (image)); - - return image; -} - -EggToolbarsModel * -egg_editable_toolbar_get_model (EggEditableToolbar *etoolbar) -{ - return etoolbar->priv->model; + action = gtk_action_group_get_action (action_group, "EETMoveItem"); + gtk_action_set_visible (action, is_toolitem); + action = gtk_action_group_get_action (action_group, "EETRemoveItem"); + gtk_action_set_visible (action, is_toolitem); + action = gtk_action_group_get_action (action_group, "EETRemoveToolbar"); + gtk_action_set_visible (action, is_toolbar && (priv->edit_mode > 0)); } Index: lib/egg/egg-editable-toolbar.h =================================================================== RCS file: /cvs/gnome/epiphany/lib/egg/egg-editable-toolbar.h,v retrieving revision 1.19 diff -p -u -u -p -r1.19 egg-editable-toolbar.h --- lib/egg/egg-editable-toolbar.h 16 Oct 2005 20:29:02 -0000 1.19 +++ lib/egg/egg-editable-toolbar.h 29 Jan 2006 21:31:51 -0000 @@ -56,33 +56,47 @@ struct _EggEditableToolbarClass { GtkVBoxClass parent_class; - void (* action_request) (EggEditableToolbar *etoolbar, + void (* action_request) (EggEditableToolbar *toolbar, const char *action_name); + void (* prepare_popup) (EggEditableToolbar *toolbar, + guint ui_id, + int toolbar_pos, + int item_pos); }; GType egg_editable_toolbar_get_type (void); -GtkWidget *egg_editable_toolbar_new (GtkUIManager *manager); + +GtkWidget *egg_editable_toolbar_new (GtkUIManager *manager, + const char *ui_path); + GtkWidget *egg_editable_toolbar_new_with_model (GtkUIManager *manager, + EggToolbarsModel *model, + const char *ui_path); + +EggToolbarsModel *egg_editable_toolbar_get_model (EggEditableToolbar *toolbar); + +void egg_editable_toolbar_set_model (EggEditableToolbar *toolbar, EggToolbarsModel *model); -void egg_editable_toolbar_set_model (EggEditableToolbar *etoolbar, - EggToolbarsModel *model); -EggToolbarsModel *egg_editable_toolbar_get_model (EggEditableToolbar *etoolbar); -void egg_editable_toolbar_set_edit_mode (EggEditableToolbar *etoolbar, + +gboolean egg_editable_toolbar_get_edit_mode (EggEditableToolbar *toolbar); + +void egg_editable_toolbar_set_edit_mode (EggEditableToolbar *toolbar, gboolean mode); -gboolean egg_editable_toolbar_get_edit_mode (EggEditableToolbar *etoolbar); -void egg_editable_toolbar_show (EggEditableToolbar *etoolbar, + +void egg_editable_toolbar_show (EggEditableToolbar *toolbar, const char *name); -void egg_editable_toolbar_hide (EggEditableToolbar *etoolbar, + +void egg_editable_toolbar_hide (EggEditableToolbar *toolbar, const char *name); -void egg_editable_toolbar_set_drag_dest (EggEditableToolbar *etoolbar, - const GtkTargetEntry *targets, - gint n_targets, - const char *toolbar_name); -void egg_editable_toolbar_set_fixed (EggEditableToolbar *etoolbar, + +void egg_editable_toolbar_set_fixed (EggEditableToolbar *toolbar, GtkToolbar *fixed_toolbar); -void egg_editable_toolbar_add_popup_items (GtkWidget *widget, - GtkMenu *popup); +GtkWidget * egg_editable_toolbar_get_selected (EggEditableToolbar *toolbar); + +void egg_editable_toolbar_set_selected (EggEditableToolbar *toolbar, + GtkWidget *widget); + /* Private Functions */ Index: lib/egg/eggmarshalers.list =================================================================== RCS file: /cvs/gnome/epiphany/lib/egg/eggmarshalers.list,v retrieving revision 1.9 diff -p -u -u -p -r1.9 eggmarshalers.list --- lib/egg/eggmarshalers.list 13 Sep 2004 10:24:56 -0000 1.9 +++ lib/egg/eggmarshalers.list 29 Jan 2006 21:31:51 -0000 @@ -10,6 +10,7 @@ OBJECT:VOID VOID:VOID VOID:INT,INT VOID:UINT,UINT +VOID:UINT,INT,INT VOID:BOOLEAN VOID:OBJECT,ENUM,BOXED VOID:BOXED