X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=cut-n-paste%2Ftoolbar-editor%2Fegg-editable-toolbar.c;h=7772959f6dd38a29488c9e4fa3d09620b1525af6;hb=3653856f03c6a5fefc3b6ea67bd789650b5bfa1e;hp=02791ee867c5f7595a2ac85d1753e30dc489ab05;hpb=b36f3a13160e8747019c40f28df89a9a9c3917ea;p=evince.git diff --git a/cut-n-paste/toolbar-editor/egg-editable-toolbar.c b/cut-n-paste/toolbar-editor/egg-editable-toolbar.c index 02791ee8..7772959f 100644 --- a/cut-n-paste/toolbar-editor/egg-editable-toolbar.c +++ b/cut-n-paste/toolbar-editor/egg-editable-toolbar.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2003-2004 Marco Pesenti Gritti - * Copyright (C) 2004 Christian Persch + * Copyright (C) 2003, 2004 Marco Pesenti Gritti + * Copyright (C) 2003, 2004, 2005 Christian Persch * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,51 +14,39 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $Id$ */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif #include "egg-editable-toolbar.h" #include "egg-toolbars-model.h" #include "egg-toolbar-editor.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include #include -static void egg_editable_toolbar_class_init (EggEditableToolbarClass *klass); -static void egg_editable_toolbar_init (EggEditableToolbar *t); -static void egg_editable_toolbar_finalize (GObject *object); +static GdkPixbuf * new_separator_pixbuf (void); #define MIN_TOOLBAR_HEIGHT 20 +#define EGG_ITEM_NAME "egg-item-name" +#define STOCK_DRAG_MODE "stock_drag-mode" -static GtkTargetEntry dest_drag_types[] = { +static const GtkTargetEntry dest_drag_types[] = { {EGG_TOOLBAR_ITEM_TYPE, GTK_TARGET_SAME_APP, 0}, }; -static int n_dest_drag_types = G_N_ELEMENTS (dest_drag_types); enum { PROP_0, PROP_TOOLBARS_MODEL, - PROP_UI_MANAGER + PROP_UI_MANAGER, + PROP_POPUP_PATH, + PROP_SELECTED, + PROP_EDIT_MODE }; enum @@ -69,64 +57,52 @@ enum static guint egg_editable_toolbar_signals[LAST_SIGNAL] = { 0 }; -static GObjectClass *parent_class = NULL; - #define EGG_EDITABLE_TOOLBAR_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EGG_TYPE_EDITABLE_TOOLBAR, EggEditableToolbarPrivate)) -struct EggEditableToolbarPrivate +struct _EggEditableToolbarPrivate { GtkUIManager *manager; EggToolbarsModel *model; - gboolean edit_mode; - GtkWidget *selected_toolbar; - GtkToolItem *fixed; + guint edit_mode; + gboolean save_hidden; GtkWidget *fixed_toolbar; - gboolean pending; - GtkToolbar *target_toolbar; - GtkWidget *dragged_item; -}; + GtkWidget *selected; + GtkActionGroup *actions; -GType -egg_editable_toolbar_get_type (void) -{ - static GType egg_editable_toolbar_type = 0; + guint visibility_id; + GList *visibility_paths; + GPtrArray *visibility_actions; - if (egg_editable_toolbar_type == 0) - { - 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 - }; - - egg_editable_toolbar_type = g_type_register_static (GTK_TYPE_VBOX, - "EggEditableToolbar", - &our_info, 0); - } + char *popup_path; - return egg_editable_toolbar_type; -} + guint dnd_pending; + GtkToolbar *dnd_toolbar; + GtkToolItem *dnd_toolitem; +}; + +G_DEFINE_TYPE (EggEditableToolbar, egg_editable_toolbar, GTK_TYPE_VBOX); static int -get_toolbar_position (EggEditableToolbar *etoolbar, GtkWidget *toolbar) +get_dock_position (EggEditableToolbar *etoolbar, + GtkWidget *dock) { GList *l; int result; l = gtk_container_get_children (GTK_CONTAINER (etoolbar)); - result = g_list_index (l, toolbar->parent); + result = g_list_index (l, dock); g_list_free (l); return result; } +static int +get_toolbar_position (EggEditableToolbar *etoolbar, GtkWidget *toolbar) +{ + return get_dock_position (etoolbar, gtk_widget_get_parent (toolbar)); +} + static int get_n_toolbars (EggEditableToolbar *etoolbar) { @@ -163,6 +139,7 @@ get_toolbar_nth (EggEditableToolbar *etoolbar, GtkWidget *result; dock = get_dock_nth (etoolbar, position); + g_return_val_if_fail (dock != NULL, NULL); l = gtk_container_get_children (GTK_CONTAINER (dock)); result = GTK_WIDGET (l->data); @@ -172,13 +149,13 @@ get_toolbar_nth (EggEditableToolbar *etoolbar, } static GtkAction * -find_action (EggEditableToolbar *t, +find_action (EggEditableToolbar *etoolbar, const char *name) { GList *l; GtkAction *action = NULL; - l = gtk_ui_manager_get_action_groups (t->priv->manager); + l = gtk_ui_manager_get_action_groups (etoolbar->priv->manager); g_return_val_if_fail (name != NULL, NULL); @@ -200,15 +177,19 @@ drag_data_delete_cb (GtkWidget *widget, EggEditableToolbar *etoolbar) { int pos, toolbar_pos; + GtkWidget *parent; + 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)); - pos = gtk_toolbar_get_item_index (GTK_TOOLBAR (widget->parent), + parent = gtk_widget_get_parent (widget); + pos = gtk_toolbar_get_item_index (GTK_TOOLBAR (parent), GTK_TOOL_ITEM (widget)); - toolbar_pos = get_toolbar_position (etoolbar, widget->parent); + toolbar_pos = get_toolbar_position (etoolbar, parent); egg_toolbars_model_remove_item (etoolbar->priv->model, - toolbar_pos, pos); + toolbar_pos, pos); } static void @@ -216,7 +197,28 @@ drag_begin_cb (GtkWidget *widget, GdkDragContext *context, EggEditableToolbar *etoolbar) { - gtk_widget_hide (widget); + GtkAction *action; + gint flags; + + gtk_widget_hide (widget); + +#if GTK_CHECK_VERSION (2, 16, 0) + action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (widget)); +#else + action = gtk_widget_get_action (widget); +#endif + + if (action == NULL) return; + + flags = egg_toolbars_model_get_name_flags (etoolbar->priv->model, + gtk_action_get_name (action)); + if (!(flags & EGG_TB_MODEL_NAME_INFINITE)) + { + flags &= ~EGG_TB_MODEL_NAME_USED; + egg_toolbars_model_set_name_flags (etoolbar->priv->model, + gtk_action_get_name (action), + flags); + } } static void @@ -224,7 +226,31 @@ drag_end_cb (GtkWidget *widget, GdkDragContext *context, EggEditableToolbar *etoolbar) { - gtk_widget_show (widget); + GtkAction *action; + gint flags; + + if (gtk_widget_get_parent (widget) != NULL) + { + gtk_widget_show (widget); + +#if GTK_CHECK_VERSION (2, 16, 0) + action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (widget)); +#else + action = gtk_widget_get_action (widget); +#endif + + if (action == NULL) return; + + flags = egg_toolbars_model_get_name_flags (etoolbar->priv->model, + gtk_action_get_name (action)); + if (!(flags & EGG_TB_MODEL_NAME_INFINITE)) + { + flags |= EGG_TB_MODEL_NAME_USED; + egg_toolbars_model_set_name_flags (etoolbar->priv->model, + gtk_action_get_name (action), + flags); + } + } } static void @@ -235,221 +261,382 @@ drag_data_get_cb (GtkWidget *widget, guint32 time, EggEditableToolbar *etoolbar) { - const char *id, *type; - char *target; + EggToolbarsModel *model; + const char *name; + char *data; + GdkAtom target; g_return_if_fail (EGG_IS_EDITABLE_TOOLBAR (etoolbar)); + model = egg_editable_toolbar_get_model (etoolbar); - type = g_object_get_data (G_OBJECT (widget), "type"); - id = g_object_get_data (G_OBJECT (widget), "id"); - if (strcmp (id, "separator") == 0) + name = g_object_get_data (G_OBJECT (widget), EGG_ITEM_NAME); + if (name == NULL) { - target = g_strdup (id); + name = g_object_get_data (G_OBJECT (gtk_widget_get_parent (widget)), EGG_ITEM_NAME); + g_return_if_fail (name != NULL); } - else + + target = gtk_selection_data_get_target (selection_data); + data = egg_toolbars_model_get_data (model, target, name); + if (data != NULL) { - target = egg_toolbars_model_get_item_data (etoolbar->priv->model, - type, id); + gtk_selection_data_set (selection_data, target, 8, (unsigned char *)data, strlen (data)); + g_free (data); } +} - gtk_selection_data_set (selection_data, - selection_data->target, 8, target, strlen (target)); +static void +move_item_cb (GtkAction *action, + EggEditableToolbar *etoolbar) +{ + GtkWidget *toolitem = gtk_widget_get_ancestor (egg_editable_toolbar_get_selected (etoolbar), GTK_TYPE_TOOL_ITEM); + GtkTargetList *list = gtk_target_list_new (dest_drag_types, G_N_ELEMENTS (dest_drag_types)); - g_free (target); + 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 -set_drag_cursor (GtkWidget *widget) +remove_item_cb (GtkAction *action, + EggEditableToolbar *etoolbar) { - if (widget->window) + GtkWidget *toolitem = gtk_widget_get_ancestor (egg_editable_toolbar_get_selected (etoolbar), GTK_TYPE_TOOL_ITEM); + GtkWidget *parent = gtk_widget_get_parent (toolitem); + int pos, toolbar_pos; + + toolbar_pos = get_toolbar_position (etoolbar, parent); + pos = gtk_toolbar_get_item_index (GTK_TOOLBAR (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) { - GdkCursor *cursor; - GdkPixbuf *pixbuf; - - pixbuf = gdk_pixbuf_new_from_file (CURSOR_DIR "/hand-open.png", NULL); - cursor = gdk_cursor_new_from_pixbuf (gdk_display_get_default (), - pixbuf, 12, 12); - gdk_window_set_cursor (widget->window, cursor); - gdk_cursor_unref (cursor); - g_object_unref (pixbuf); + egg_toolbars_model_remove_toolbar (etoolbar->priv->model, toolbar_pos); } } static void -unset_drag_cursor (GtkWidget *widget) +remove_toolbar_cb (GtkAction *action, + EggEditableToolbar *etoolbar) { - if (widget->window) - { - gdk_window_set_cursor (widget->window, NULL); - } + GtkWidget *selected = egg_editable_toolbar_get_selected (etoolbar); + GtkWidget *toolbar = gtk_widget_get_ancestor (selected, GTK_TYPE_TOOLBAR); + int toolbar_pos; + + toolbar_pos = get_toolbar_position (etoolbar, toolbar); + egg_toolbars_model_remove_toolbar (etoolbar->priv->model, toolbar_pos); } static void -set_item_drag_source (EggToolbarsModel *model, - GtkWidget *item, - GtkAction *action, - gboolean is_separator, - const char *type) +popup_context_deactivate (GtkMenuShell *menu, + EggEditableToolbar *etoolbar) { - GtkTargetEntry target_entry; - const char *id; - - target_entry.target = (char *)type; - target_entry.flags = GTK_TARGET_SAME_APP; - target_entry.info = 0; + egg_editable_toolbar_set_selected (etoolbar, NULL); + g_object_notify (G_OBJECT (etoolbar), "selected"); +} - gtk_drag_source_set (item, GDK_BUTTON1_MASK, - &target_entry, 1, - GDK_ACTION_MOVE); +static void +popup_context_menu_cb (GtkWidget *toolbar, + gint x, + gint y, + gint button_number, + EggEditableToolbar *etoolbar) +{ + if (etoolbar->priv->popup_path != NULL) + { + GtkMenu *menu; + + egg_editable_toolbar_set_selected (etoolbar, toolbar); + g_object_notify (G_OBJECT (etoolbar), "selected"); + + menu = GTK_MENU (gtk_ui_manager_get_widget (etoolbar->priv->manager, + etoolbar->priv->popup_path)); + g_return_if_fail (menu != NULL); + gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button_number, gtk_get_current_event_time ()); + g_signal_connect_object (menu, "selection-done", + G_CALLBACK (popup_context_deactivate), + etoolbar, 0); + } +} - if (is_separator) +static gboolean +button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + EggEditableToolbar *etoolbar) +{ + if (event->button == 3 && etoolbar->priv->popup_path != NULL) { - GtkWidget *icon; - GdkPixbuf *pixbuf; + GtkMenu *menu; + + egg_editable_toolbar_set_selected (etoolbar, widget); + g_object_notify (G_OBJECT (etoolbar), "selected"); - id = "separator"; + menu = GTK_MENU (gtk_ui_manager_get_widget (etoolbar->priv->manager, + etoolbar->priv->popup_path)); + g_return_val_if_fail (menu != NULL, FALSE); + gtk_menu_popup (menu, NULL, NULL, NULL, NULL, event->button, event->time); + g_signal_connect_object (menu, "selection-done", + G_CALLBACK (popup_context_deactivate), + etoolbar, 0); - icon = _egg_editable_toolbar_new_separator_image (); - pixbuf = gtk_image_get_pixbuf (GTK_IMAGE (icon)); - gtk_drag_source_set_icon_pixbuf (item, pixbuf); + return TRUE; } - else + + return FALSE; +} + +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) { - const char *stock_id; - GValue value = { 0, }; - GdkPixbuf *pixbuf; + 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)); - id = gtk_action_get_name (action); +} - g_value_init (&value, G_TYPE_STRING); - g_object_get_property (G_OBJECT (action), "stock_id", &value); - stock_id = g_value_get_string (&value); +static void +configure_item_cursor (GtkToolItem *item, + EggEditableToolbar *etoolbar) +{ + EggEditableToolbarPrivate *priv = etoolbar->priv; + GtkWidget *widget = GTK_WIDGET (item); + GdkWindow *window = gtk_widget_get_window (widget); - if (stock_id != NULL) + if (window != NULL) + { + if (priv->edit_mode > 0) { - pixbuf = gtk_widget_render_icon (item, stock_id, - GTK_ICON_SIZE_LARGE_TOOLBAR, NULL); + GdkCursor *cursor; + GdkScreen *screen; + GdkPixbuf *pixbuf = NULL; + + screen = gtk_widget_get_screen (GTK_WIDGET (etoolbar)); + + cursor = gdk_cursor_new_for_display (gdk_screen_get_display (screen), + GDK_HAND2); + gdk_window_set_cursor (window, cursor); + g_object_unref (cursor); + + gtk_drag_source_set (widget, GDK_BUTTON1_MASK, dest_drag_types, + G_N_ELEMENTS (dest_drag_types), GDK_ACTION_MOVE); + if (GTK_IS_SEPARATOR_TOOL_ITEM (item)) + { + pixbuf = new_separator_pixbuf (); + } + else + { + char *icon_name=NULL; + char *stock_id=NULL; + GtkAction *action; + char *name; + + name = g_object_get_data (G_OBJECT (widget), EGG_ITEM_NAME); + action = name ? find_action (etoolbar, name) : NULL; + + if (action) + { + g_object_get (action, + "icon-name", &icon_name, + "stock-id", &stock_id, + NULL); + } + if (icon_name) + { + GdkScreen *screen; + GtkIconTheme *icon_theme; + GtkSettings *settings; + gint width, height; + + screen = gtk_widget_get_screen (widget); + icon_theme = gtk_icon_theme_get_for_screen (screen); + settings = gtk_settings_get_for_screen (screen); + + if (!gtk_icon_size_lookup_for_settings (settings, + GTK_ICON_SIZE_LARGE_TOOLBAR, + &width, &height)) + { + width = height = 24; + } + + pixbuf = gtk_icon_theme_load_icon (icon_theme, icon_name, + MIN (width, height), 0, NULL); + } + else if (stock_id) + { + pixbuf = gtk_widget_render_icon_pixbuf (widget, stock_id, + GTK_ICON_SIZE_LARGE_TOOLBAR); + } + g_free (icon_name); + g_free (stock_id); + } + + if (G_UNLIKELY (!pixbuf)) + { + return; + } + gtk_drag_source_set_icon_pixbuf (widget, pixbuf); + g_object_unref (pixbuf); + } else { - pixbuf = gtk_widget_render_icon (item, GTK_STOCK_DND, - GTK_ICON_SIZE_LARGE_TOOLBAR, NULL); + gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET(item)), NULL); } + } +} - gtk_drag_source_set_icon_pixbuf (item, pixbuf); - g_object_unref (pixbuf); - g_value_unset (&value); - } +static void +configure_item_tooltip (GtkToolItem *item) +{ + GtkAction *action; - g_object_set_data_full (G_OBJECT (item), "id", - g_strdup (id), g_free); - g_object_set_data_full (G_OBJECT (item), "type", - g_strdup (type), g_free); +#if GTK_CHECK_VERSION (2, 16, 0) + action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (item)); +#else + action = gtk_widget_get_action (GTK_WIDGET (item)); +#endif + + if (action != NULL) + { + g_object_notify (G_OBJECT (action), "tooltip"); + } } -static GtkWidget * -create_item_from_action (EggEditableToolbar *t, - const char *action_name, - const char *type, - gboolean is_separator, - GtkAction **ret_action) + +static void +connect_widget_signals (GtkWidget *proxy, EggEditableToolbar *etoolbar) { - GtkWidget *item; - GtkAction *action; + if (GTK_IS_CONTAINER (proxy)) + { + gtk_container_forall (GTK_CONTAINER (proxy), + (GtkCallback) connect_widget_signals, + (gpointer) etoolbar); + } - if (is_separator) + if (GTK_IS_TOOL_ITEM (proxy)) { - item = GTK_WIDGET (gtk_separator_tool_item_new ()); - action = NULL; + g_signal_connect_object (proxy, "drag_begin", + G_CALLBACK (drag_begin_cb), + etoolbar, 0); + g_signal_connect_object (proxy, "drag_end", + G_CALLBACK (drag_end_cb), + etoolbar, 0); + g_signal_connect_object (proxy, "drag_data_get", + G_CALLBACK (drag_data_get_cb), + etoolbar, 0); + g_signal_connect_object (proxy, "drag_data_delete", + G_CALLBACK (drag_data_delete_cb), + etoolbar, 0); } - else + + if (GTK_IS_BUTTON (proxy) || GTK_IS_TOOL_ITEM (proxy)) { - g_return_val_if_fail (action_name != NULL, NULL); + g_signal_connect_object (proxy, "button-press-event", + G_CALLBACK (button_press_event_cb), + etoolbar, 0); + } +} - g_signal_emit (G_OBJECT (t), egg_editable_toolbar_signals[ACTION_REQUEST], - 0, action_name); +static void +action_sensitive_cb (GtkAction *action, + GParamSpec *pspec, + GtkToolItem *item) +{ + EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR + (gtk_widget_get_ancestor (GTK_WIDGET (item), EGG_TYPE_EDITABLE_TOOLBAR)); - action = find_action (t, action_name); - if (action) - { - item = gtk_action_create_tool_item (action); - } - else - { - return NULL; - } + if (etoolbar->priv->edit_mode > 0) + { + gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE); } +} - gtk_widget_show (item); +static GtkToolItem * +create_item_from_action (EggEditableToolbar *etoolbar, + const char *name) +{ + GtkToolItem *item; - g_signal_connect (item, "drag_begin", - G_CALLBACK (drag_begin_cb), t); - g_signal_connect (item, "drag_end", - G_CALLBACK (drag_end_cb), t); - g_signal_connect (item, "drag_data_get", - G_CALLBACK (drag_data_get_cb), t); - g_signal_connect (item, "drag_data_delete", - G_CALLBACK (drag_data_delete_cb), t); + g_return_val_if_fail (name != NULL, NULL); - if (t->priv->edit_mode) + if (strcmp (name, "_separator") == 0) { - set_drag_cursor (item); - gtk_widget_set_sensitive (item, TRUE); - set_item_drag_source (t->priv->model, item, action, - is_separator, type); - gtk_tool_item_set_use_drag_window (GTK_TOOL_ITEM (item), TRUE); + item = gtk_separator_tool_item_new (); } - - if (ret_action) + else { - *ret_action = action; + GtkAction *action = find_action (etoolbar, name); + if (action == NULL) return NULL; + + item = GTK_TOOL_ITEM (gtk_action_create_tool_item (action)); + + /* Normally done on-demand by the GtkUIManager, but no + * such demand may have been made yet, so do it ourselves. + */ + gtk_action_set_accel_group + (action, gtk_ui_manager_get_accel_group(etoolbar->priv->manager)); + + g_signal_connect_object (action, "notify::sensitive", + G_CALLBACK (action_sensitive_cb), item, 0); } + gtk_widget_show (GTK_WIDGET (item)); + + g_object_set_data_full (G_OBJECT (item), EGG_ITEM_NAME, + g_strdup (name), g_free); + return item; } -static GtkWidget * -create_item (EggEditableToolbar *t, - EggToolbarsModel *model, - int toolbar_position, - int position, - GtkAction **ret_action) +static GtkToolItem * +create_item_from_position (EggEditableToolbar *etoolbar, + int toolbar_position, + int position) { - const char *action_name, *type; - gboolean is_separator; + GtkToolItem *item; + const char *name; - egg_toolbars_model_item_nth (model, toolbar_position, position, - &is_separator, &action_name, &type); - return create_item_from_action (t, action_name, type, - is_separator, ret_action); -} + name = egg_toolbars_model_item_nth (etoolbar->priv->model, toolbar_position, position); + item = create_item_from_action (etoolbar, name); -static gboolean -data_is_separator (const char *data) -{ - return strcmp (data, "separator") == 0; + return item; } static void -drag_data_received_cb (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - GtkSelectionData *selection_data, - guint info, - guint time, - EggEditableToolbar *etoolbar) +toolbar_drag_data_received_cb (GtkToolbar *toolbar, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time, + EggEditableToolbar *etoolbar) { - char *type; - char *id; - - GdkAtom target; - - target = gtk_drag_dest_find_target (widget, context, NULL); - type = egg_toolbars_model_get_item_type (etoolbar->priv->model, target); - id = egg_toolbars_model_get_item_id (etoolbar->priv->model, type, selection_data->data); - /* This function can be called for two reasons * * (1) drag_motion() needs an item to pass to @@ -461,113 +648,67 @@ drag_data_received_cb (GtkWidget *widget, * actually add a new item to the toolbar. */ - if (id == NULL) + GdkAtom type = gtk_selection_data_get_data_type (selection_data); + const char *data = (char *)gtk_selection_data_get_data (selection_data); + + int ipos = -1; + char *name = NULL; + gboolean used = FALSE; + + /* Find out where the drop is occuring, and the name of what is being dropped. */ + if (gtk_selection_data_get_length (selection_data) >= 0) { - etoolbar->priv->pending = FALSE; - g_free (type); - return; + ipos = gtk_toolbar_get_drop_index (toolbar, x, y); + name = egg_toolbars_model_get_name (etoolbar->priv->model, type, data, FALSE); + if (name != NULL) + { + used = ((egg_toolbars_model_get_name_flags (etoolbar->priv->model, name) & EGG_TB_MODEL_NAME_USED) != 0); + } } - if (etoolbar->priv->pending) + /* If we just want a highlight item, then . */ + if (etoolbar->priv->dnd_pending > 0) { - etoolbar->priv->pending = FALSE; - etoolbar->priv->dragged_item = - create_item_from_action (etoolbar, id, type, - data_is_separator (id), NULL); - g_object_ref (etoolbar->priv->dragged_item); - gtk_object_sink (GTK_OBJECT (etoolbar->priv->dragged_item)); + etoolbar->priv->dnd_pending--; + + if (name != NULL && etoolbar->priv->dnd_toolbar == toolbar && !used) + { + etoolbar->priv->dnd_toolitem = create_item_from_action (etoolbar, name); + gtk_toolbar_set_drop_highlight_item (etoolbar->priv->dnd_toolbar, + etoolbar->priv->dnd_toolitem, ipos); + } } else { - int pos, toolbar_pos; + gtk_toolbar_set_drop_highlight_item (toolbar, NULL, 0); + etoolbar->priv->dnd_toolbar = NULL; + etoolbar->priv->dnd_toolitem = NULL; - pos = gtk_toolbar_get_drop_index (GTK_TOOLBAR (widget), x, y); - toolbar_pos = get_toolbar_position (etoolbar, widget); + /* If we don't have a name to use yet, try to create one. */ + if (name == NULL && gtk_selection_data_get_length (selection_data) >= 0) + { + name = egg_toolbars_model_get_name (etoolbar->priv->model, type, data, TRUE); + } - if (data_is_separator (selection_data->data)) - { - egg_toolbars_model_add_separator (etoolbar->priv->model, - toolbar_pos, pos); - } + if (name != NULL && !used) + { + gint tpos = get_toolbar_position (etoolbar, GTK_WIDGET (toolbar)); + egg_toolbars_model_add_item (etoolbar->priv->model, tpos, ipos, name); + gtk_drag_finish (context, TRUE, + gdk_drag_context_get_selected_action (context) == GDK_ACTION_MOVE, time); + } else - { - egg_toolbars_model_add_item (etoolbar->priv->model, - toolbar_pos, pos, id, type); - } - - gtk_drag_finish (context, TRUE, context->action == GDK_ACTION_MOVE, - time); - } - - g_free (type); - g_free (id); -} - -static void -remove_toolbar_cb (GtkWidget *menuitem, - EggEditableToolbar *etoolbar) -{ - int pos; - - pos = get_toolbar_position (etoolbar, etoolbar->priv->selected_toolbar); - egg_toolbars_model_remove_toolbar (etoolbar->priv->model, pos); -} - -static void -popup_toolbar_context_menu_cb (GtkWidget *toolbar, - gint x, - gint y, - gint button_number, - EggEditableToolbar *t) -{ - GtkWidget *menu; - GtkWidget *item; - GtkWidget *image; - - if (t->priv->edit_mode) - { - EggTbModelFlags flags; - int position; - - t->priv->selected_toolbar = toolbar; - - menu = gtk_menu_new (); - - item = gtk_image_menu_item_new_with_mnemonic (_("_Remove Toolbar")); - gtk_widget_show (item); - image = gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU); - gtk_widget_show (image); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - g_signal_connect (item, "activate", - G_CALLBACK (remove_toolbar_cb), - t); - - position = get_toolbar_position (t, toolbar); - flags = egg_toolbars_model_get_flags (t->priv->model, position); - if (flags & EGG_TB_MODEL_NOT_REMOVABLE) { - gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE); + gtk_drag_finish (context, FALSE, + gdk_drag_context_get_selected_action (context) == GDK_ACTION_MOVE, time); } - - gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 2, - gtk_get_current_event_time ()); } -} -static void -free_dragged_item (EggEditableToolbar *etoolbar) -{ - if (etoolbar->priv->dragged_item) - { - gtk_widget_destroy (etoolbar->priv->dragged_item); - g_object_unref (etoolbar->priv->dragged_item); - etoolbar->priv->dragged_item = NULL; - } + g_free (name); } static gboolean -toolbar_drag_drop_cb (GtkWidget *widget, +toolbar_drag_drop_cb (GtkToolbar *toolbar, GdkDragContext *context, gint x, gint y, @@ -576,91 +717,49 @@ toolbar_drag_drop_cb (GtkWidget *widget, { GdkAtom target; - target = gtk_drag_dest_find_target (widget, context, NULL); + target = gtk_drag_dest_find_target (GTK_WIDGET (toolbar), context, NULL); if (target != GDK_NONE) { - gtk_drag_get_data (widget, context, - target, - time); + gtk_drag_get_data (GTK_WIDGET (toolbar), context, target, time); return TRUE; } - - free_dragged_item (etoolbar); - + return FALSE; } static gboolean -toolbar_drag_motion_cb (GtkWidget *widget, +toolbar_drag_motion_cb (GtkToolbar *toolbar, GdkDragContext *context, gint x, gint y, guint time, EggEditableToolbar *etoolbar) { - GdkAtom target; - int index; - GtkToolbar *toolbar = GTK_TOOLBAR (widget); - GtkToolItem *item; - GtkWidget *source; - - source = gtk_drag_get_source_widget (context); - if (source) - { - EggTbModelFlags flags; - int pos; - gboolean is_item; - - pos = get_toolbar_position (etoolbar, widget); - flags = egg_toolbars_model_get_flags (etoolbar->priv->model, pos); - - is_item = etoolbar->priv->edit_mode && - (gtk_widget_get_ancestor (source, EGG_TYPE_EDITABLE_TOOLBAR) || - gtk_widget_get_ancestor (source, EGG_TYPE_TOOLBAR_EDITOR)); - - if ((flags & EGG_TB_MODEL_ACCEPT_ITEMS_ONLY) && !is_item) - { - gdk_drag_status (context, 0, time); - return FALSE; - } - - if (gtk_widget_is_ancestor (source, widget)) - { - context->suggested_action = GDK_ACTION_MOVE; - } - } - - target = gtk_drag_dest_find_target (widget, context, NULL); + GdkAtom target = gtk_drag_dest_find_target (GTK_WIDGET (toolbar), context, NULL); if (target == GDK_NONE) { gdk_drag_status (context, 0, time); return FALSE; } - if (etoolbar->priv->target_toolbar != toolbar) + /* Make ourselves the current dnd toolbar, and request a highlight item. */ + if (etoolbar->priv->dnd_toolbar != toolbar) { - if (etoolbar->priv->target_toolbar) - gtk_toolbar_set_drop_highlight_item - (etoolbar->priv->target_toolbar, NULL, 0); - - free_dragged_item (etoolbar); - etoolbar->priv->pending = TRUE; - - etoolbar->priv->target_toolbar = toolbar; - - gtk_drag_get_data (widget, context, target, time); + etoolbar->priv->dnd_toolbar = toolbar; + etoolbar->priv->dnd_toolitem = NULL; + etoolbar->priv->dnd_pending++; + gtk_drag_get_data (GTK_WIDGET (toolbar), context, target, time); } - if (etoolbar->priv->dragged_item != NULL && - etoolbar->priv->edit_mode) + /* If a highlight item is available, use it. */ + else if (etoolbar->priv->dnd_toolitem) { - item = GTK_TOOL_ITEM (etoolbar->priv->dragged_item); - - index = gtk_toolbar_get_drop_index (toolbar, x, y); - gtk_toolbar_set_drop_highlight_item (toolbar, item, index); + gint ipos = gtk_toolbar_get_drop_index (etoolbar->priv->dnd_toolbar, x, y); + gtk_toolbar_set_drop_highlight_item (etoolbar->priv->dnd_toolbar, + etoolbar->priv->dnd_toolitem, ipos); } - gdk_drag_status (context, context->suggested_action, time); + gdk_drag_status (context, gdk_drag_context_get_suggested_action (context), time); return TRUE; } @@ -671,52 +770,256 @@ toolbar_drag_leave_cb (GtkToolbar *toolbar, guint time, EggEditableToolbar *etoolbar) { - /* This is a workaround for bug 125557. Sometimes - * we seemingly enter another toolbar *before* leaving - * the current one. - * - * In that case etoolbar->priv->target_toolbar will - * have been set to something else and the highlighting - * will already have been turned off - */ - - if (etoolbar->priv->target_toolbar == toolbar) + gtk_toolbar_set_drop_highlight_item (toolbar, NULL, 0); + + /* If we were the current dnd toolbar target, remove the item. */ + if (etoolbar->priv->dnd_toolbar == toolbar) { - gtk_toolbar_set_drop_highlight_item (toolbar, NULL, 0); + etoolbar->priv->dnd_toolbar = NULL; + etoolbar->priv->dnd_toolitem = NULL; + } +} + +static void +configure_drag_dest (EggEditableToolbar *etoolbar, + GtkToolbar *toolbar) +{ + EggToolbarsItemType *type; + GtkTargetList *targets; + GList *list; + + /* Make every toolbar able to receive drag-drops. */ + gtk_drag_dest_set (GTK_WIDGET (toolbar), 0, + dest_drag_types, G_N_ELEMENTS (dest_drag_types), + GDK_ACTION_MOVE | GDK_ACTION_COPY); - etoolbar->priv->target_toolbar = NULL; - free_dragged_item (etoolbar); + /* Add any specialist drag-drop abilities. */ + targets = gtk_drag_dest_get_target_list (GTK_WIDGET (toolbar)); + list = egg_toolbars_model_get_types (etoolbar->priv->model); + while (list) + { + type = list->data; + if (type->new_name != NULL || type->get_name != NULL) + gtk_target_list_add (targets, type->type, 0, 0); + list = list->next; + } +} + +static void +toggled_visibility_cb (GtkToggleAction *action, + EggEditableToolbar *etoolbar) +{ + EggEditableToolbarPrivate *priv = etoolbar->priv; + GtkWidget *dock; + EggTbModelFlags flags; + gboolean visible; + gint i; + + visible = gtk_toggle_action_get_active (action); + for (i = 0; i < priv->visibility_actions->len; i++) + if (g_ptr_array_index (priv->visibility_actions, i) == action) + break; + + g_return_if_fail (i < priv->visibility_actions->len); + + dock = get_dock_nth (etoolbar, i); + if (visible) + { + gtk_widget_show (dock); + } + else + { + gtk_widget_hide (dock); + } + + if (priv->save_hidden) + { + flags = egg_toolbars_model_get_flags (priv->model, i); + + if (visible) + { + flags &= ~(EGG_TB_MODEL_HIDDEN); + } + else + { + flags |= (EGG_TB_MODEL_HIDDEN); + } + + egg_toolbars_model_set_flags (priv->model, i, flags); + } +} + +static void +toolbar_visibility_refresh (EggEditableToolbar *etoolbar) +{ + EggEditableToolbarPrivate *priv = etoolbar->priv; + gint n_toolbars, n_items, i, j, k; + GtkToggleAction *action; + GList *list; + GString *string; + gboolean showing; + char action_name[40]; + char *action_label; + char *tmp; + + if (priv == NULL || priv->model == NULL || priv->manager == NULL || + priv->visibility_paths == NULL || priv->actions == NULL) + { + return; + } + + if (priv->visibility_actions == NULL) + { + priv->visibility_actions = g_ptr_array_new (); + } + + if (priv->visibility_id != 0) + { + gtk_ui_manager_remove_ui (priv->manager, priv->visibility_id); + } + + priv->visibility_id = gtk_ui_manager_new_merge_id (priv->manager); + +#if GTK_CHECK_VERSION(2,20,0) + showing = gtk_widget_get_visible (GTK_WIDGET (etoolbar)); +#else + showing = GTK_WIDGET_VISIBLE (etoolbar); +#endif + + n_toolbars = egg_toolbars_model_n_toolbars (priv->model); + for (i = 0; i < n_toolbars; i++) + { + string = g_string_sized_new (0); + n_items = egg_toolbars_model_n_items (priv->model, i); + for (k = 0, j = 0; j < n_items; j++) + { + GValue value = { 0, }; + GtkAction *action; + const char *name; + + name = egg_toolbars_model_item_nth (priv->model, i, j); + if (name == NULL) continue; + action = find_action (etoolbar, name); + if (action == NULL) continue; + + g_value_init (&value, G_TYPE_STRING); + g_object_get_property (G_OBJECT (action), "label", &value); + name = g_value_get_string (&value); + if (name == NULL) + { + g_value_unset (&value); + continue; + } + k += g_utf8_strlen (name, -1) + 2; + if (j > 0) + { + g_string_append (string, ", "); + if (j > 1 && k > 25) + { + g_value_unset (&value); + break; + } + } + g_string_append (string, name); + g_value_unset (&value); + } + if (j < n_items) + { + g_string_append (string, " ..."); + } + + tmp = g_string_free (string, FALSE); + for (j = 0, k = 0; tmp[j]; j++) + { + if (tmp[j] == '_') continue; + tmp[k] = tmp[j]; + k++; + } + tmp[k] = 0; + /* Translaters: This string is for a toggle to display a toolbar. + * The name of the toolbar is automatically computed from the widgets + * on the toolbar, and is placed at the %s. Note the _ before the %s + * which is used to add mnemonics. We know that this is likely to + * produce duplicates, but don't worry about it. If your language + * normally has a mnemonic at the start, please use the _. If not, + * please remove. */ + action_label = g_strdup_printf (_("Show “_%s”"), tmp); + g_free (tmp); + + sprintf(action_name, "ToolbarToggle%d", i); + + if (i >= priv->visibility_actions->len) + { + action = gtk_toggle_action_new (action_name, action_label, NULL, NULL); + g_ptr_array_add (priv->visibility_actions, action); + g_signal_connect_object (action, "toggled", + G_CALLBACK (toggled_visibility_cb), + etoolbar, 0); + gtk_action_group_add_action (priv->actions, GTK_ACTION (action)); + } + else + { + action = g_ptr_array_index (priv->visibility_actions, i); + g_object_set (action, "label", action_label, NULL); + } + + gtk_action_set_visible (GTK_ACTION (action), (egg_toolbars_model_get_flags (priv->model, i) + & EGG_TB_MODEL_NOT_REMOVABLE) == 0); + gtk_action_set_sensitive (GTK_ACTION (action), showing); +#if GTK_CHECK_VERSION(2,20,0) + gtk_toggle_action_set_active (action, gtk_widget_get_visible + (get_dock_nth (etoolbar, i))); +#else + gtk_toggle_action_set_active (action, GTK_WIDGET_VISIBLE + (get_dock_nth (etoolbar, i))); +#endif + + for (list = priv->visibility_paths; list != NULL; list = g_list_next (list)) + { + gtk_ui_manager_add_ui (priv->manager, priv->visibility_id, + (const char *)list->data, action_name, action_name, + GTK_UI_MANAGER_MENUITEM, FALSE); + } + + g_free (action_label); + } + + gtk_ui_manager_ensure_update (priv->manager); + + while (i < priv->visibility_actions->len) + { + action = g_ptr_array_index (priv->visibility_actions, i); + g_ptr_array_remove_index_fast (priv->visibility_actions, i); + gtk_action_group_remove_action (priv->actions, GTK_ACTION (action)); + i++; } } static GtkWidget * -create_dock (EggEditableToolbar *t) +create_dock (EggEditableToolbar *etoolbar) { GtkWidget *toolbar, *hbox; hbox = gtk_hbox_new (0, FALSE); - gtk_widget_show (hbox); toolbar = gtk_toolbar_new (); gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), TRUE); gtk_widget_show (toolbar); gtk_box_pack_start (GTK_BOX (hbox), toolbar, TRUE, TRUE, 0); - gtk_drag_dest_set (toolbar, 0, - dest_drag_types, n_dest_drag_types, - GDK_ACTION_MOVE | GDK_ACTION_COPY); - g_signal_connect (toolbar, "drag_drop", - G_CALLBACK (toolbar_drag_drop_cb), t); + G_CALLBACK (toolbar_drag_drop_cb), etoolbar); g_signal_connect (toolbar, "drag_motion", - G_CALLBACK (toolbar_drag_motion_cb), t); + G_CALLBACK (toolbar_drag_motion_cb), etoolbar); g_signal_connect (toolbar, "drag_leave", - G_CALLBACK (toolbar_drag_leave_cb), t); + G_CALLBACK (toolbar_drag_leave_cb), etoolbar); g_signal_connect (toolbar, "drag_data_received", - G_CALLBACK (drag_data_received_cb), t); + G_CALLBACK (toolbar_drag_data_received_cb), etoolbar); g_signal_connect (toolbar, "popup_context_menu", - G_CALLBACK (popup_toolbar_context_menu_cb), t); + G_CALLBACK (popup_context_menu_cb), etoolbar); + + configure_drag_dest (etoolbar, GTK_TOOLBAR (toolbar)); return hbox; } @@ -725,7 +1028,8 @@ static void set_fixed_style (EggEditableToolbar *t, GtkToolbarStyle style) { g_return_if_fail (GTK_IS_TOOLBAR (t->priv->fixed_toolbar)); - gtk_toolbar_set_style (GTK_TOOLBAR (t->priv->fixed_toolbar), style); + gtk_toolbar_set_style (GTK_TOOLBAR (t->priv->fixed_toolbar), + style == GTK_TOOLBAR_ICONS ? GTK_TOOLBAR_BOTH_HORIZ : style); } static void @@ -738,207 +1042,217 @@ unset_fixed_style (EggEditableToolbar *t) static void toolbar_changed_cb (EggToolbarsModel *model, int position, - EggEditableToolbar *t) + EggEditableToolbar *etoolbar) { GtkWidget *toolbar; EggTbModelFlags flags; GtkToolbarStyle style; flags = egg_toolbars_model_get_flags (model, position); - toolbar = get_toolbar_nth (t, position); + toolbar = get_toolbar_nth (etoolbar, position); - if (flags & EGG_TB_MODEL_ICONS_ONLY) + if (flags & EGG_TB_MODEL_ICONS) { style = GTK_TOOLBAR_ICONS; } - else if (flags & EGG_TB_MODEL_TEXT_ONLY) + else if (flags & EGG_TB_MODEL_TEXT) { style = GTK_TOOLBAR_TEXT; } - else if (flags & EGG_TB_MODEL_ICONS_TEXT) + else if (flags & EGG_TB_MODEL_BOTH) { style = GTK_TOOLBAR_BOTH; } - else if (flags & EGG_TB_MODEL_ICONS_TEXT_HORIZ) + else if (flags & EGG_TB_MODEL_BOTH_HORIZ) { style = GTK_TOOLBAR_BOTH_HORIZ; } else { gtk_toolbar_unset_style (GTK_TOOLBAR (toolbar)); - if (position == 0 && t->priv->fixed_toolbar) + if (position == 0 && etoolbar->priv->fixed_toolbar) { - unset_fixed_style (t); + unset_fixed_style (etoolbar); } return; } gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), style); - if (position == 0 && t->priv->fixed_toolbar) + if (position == 0 && etoolbar->priv->fixed_toolbar) { - set_fixed_style (t, style); + set_fixed_style (etoolbar, style); } + + toolbar_visibility_refresh (etoolbar); } static void -unparent_fixed (EggEditableToolbar *t) +unparent_fixed (EggEditableToolbar *etoolbar) { GtkWidget *toolbar, *dock; - g_return_if_fail (GTK_IS_TOOLBAR (t->priv->fixed_toolbar)); + g_return_if_fail (GTK_IS_TOOLBAR (etoolbar->priv->fixed_toolbar)); - toolbar = t->priv->fixed_toolbar; - dock = get_dock_nth (t, 0); + toolbar = etoolbar->priv->fixed_toolbar; + dock = get_dock_nth (etoolbar, 0); - if (dock && toolbar->parent != NULL) + if (dock && gtk_widget_get_parent (toolbar) != NULL) { gtk_container_remove (GTK_CONTAINER (dock), toolbar); } } static void -update_fixed (EggEditableToolbar *t) +update_fixed (EggEditableToolbar *etoolbar) { GtkWidget *toolbar, *dock; - if (!t->priv->fixed_toolbar) return; + if (!etoolbar->priv->fixed_toolbar) return; - toolbar = t->priv->fixed_toolbar; - dock = get_dock_nth (t, 0); + toolbar = etoolbar->priv->fixed_toolbar; + dock = get_dock_nth (etoolbar, 0); - if (dock && toolbar && toolbar->parent == NULL) + if (dock && toolbar && gtk_widget_get_parent (toolbar) == NULL) { gtk_box_pack_end (GTK_BOX (dock), toolbar, FALSE, TRUE, 0); - gtk_widget_show_all (toolbar); + gtk_widget_show (toolbar); + + gtk_widget_set_size_request (dock, -1, -1); + gtk_widget_queue_resize_no_redraw (dock); } } static void toolbar_added_cb (EggToolbarsModel *model, int position, - EggEditableToolbar *t) + EggEditableToolbar *etoolbar) { GtkWidget *dock; - dock = create_dock (t); + dock = create_dock (etoolbar); + if ((egg_toolbars_model_get_flags (model, position) & EGG_TB_MODEL_HIDDEN) == 0) + gtk_widget_show (dock); gtk_widget_set_size_request (dock, -1, MIN_TOOLBAR_HEIGHT); - gtk_box_pack_start (GTK_BOX (t), dock, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (etoolbar), dock, TRUE, TRUE, 0); - gtk_box_reorder_child (GTK_BOX (t), dock, position); + gtk_box_reorder_child (GTK_BOX (etoolbar), dock, position); gtk_widget_show_all (dock); - - update_fixed (t); + + update_fixed (etoolbar); + + toolbar_visibility_refresh (etoolbar); } static void toolbar_removed_cb (EggToolbarsModel *model, int position, - EggEditableToolbar *t) + EggEditableToolbar *etoolbar) { - GtkWidget *toolbar; + GtkWidget *dock; - toolbar = get_dock_nth (t, position); - gtk_widget_destroy (toolbar); + if (position == 0 && etoolbar->priv->fixed_toolbar != NULL) + { + unparent_fixed (etoolbar); + } - update_fixed (t); + dock = get_dock_nth (etoolbar, position); + gtk_widget_destroy (dock); + + update_fixed (etoolbar); + + toolbar_visibility_refresh (etoolbar); } static void item_added_cb (EggToolbarsModel *model, - int toolbar_position, - int position, - EggEditableToolbar *t) + int tpos, + int ipos, + EggEditableToolbar *etoolbar) { GtkWidget *dock; GtkWidget *toolbar; - GtkWidget *item; - GtkAction *action; + GtkToolItem *item; + + toolbar = get_toolbar_nth (etoolbar, tpos); + item = create_item_from_position (etoolbar, tpos, ipos); + if (item == NULL) return; - toolbar = get_toolbar_nth (t, toolbar_position); - item = create_item (t, model, toolbar_position, position, &action); - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), - GTK_TOOL_ITEM (item), position); + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, ipos); - dock = get_dock_nth (t, toolbar_position); + connect_widget_signals (GTK_WIDGET (item), etoolbar); + configure_item_tooltip (item); + configure_item_cursor (item, etoolbar); + configure_item_sensitivity (item, etoolbar); + + dock = get_dock_nth (etoolbar, tpos); gtk_widget_set_size_request (dock, -1, -1); gtk_widget_queue_resize_no_redraw (dock); - /* FIXME Hack to make tooltip work from gtk */ - if (action) - { - g_object_notify (G_OBJECT (action), "tooltip"); - } + toolbar_visibility_refresh (etoolbar); } static void item_removed_cb (EggToolbarsModel *model, int toolbar_position, int position, - EggEditableToolbar *t) + EggEditableToolbar *etoolbar) { + EggEditableToolbarPrivate *priv = etoolbar->priv; + GtkWidget *toolbar; GtkWidget *item; - toolbar = get_toolbar_nth (t, toolbar_position); + toolbar = get_toolbar_nth (etoolbar, toolbar_position); item = GTK_WIDGET (gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), position)); g_return_if_fail (item != NULL); - gtk_container_remove (GTK_CONTAINER (toolbar), item); - if (egg_toolbars_model_n_items (model, toolbar_position) == 0) + if (item == priv->selected) { - egg_toolbars_model_remove_toolbar (model, toolbar_position); + /* FIXME */ } + + gtk_container_remove (GTK_CONTAINER (toolbar), item); + + toolbar_visibility_refresh (etoolbar); } static void -egg_editable_toolbar_construct (EggEditableToolbar *t) +egg_editable_toolbar_build (EggEditableToolbar *etoolbar) { int i, l, n_items, n_toolbars; - EggToolbarsModel *model = t->priv->model; + EggToolbarsModel *model = etoolbar->priv->model; g_return_if_fail (model != NULL); - g_return_if_fail (t->priv->manager != NULL); + g_return_if_fail (etoolbar->priv->manager != NULL); n_toolbars = egg_toolbars_model_n_toolbars (model); for (i = 0; i < n_toolbars; i++) { GtkWidget *toolbar, *dock; - EggTbModelFlags flags; - - dock = create_dock (t); - gtk_box_pack_start (GTK_BOX (t), dock, TRUE, TRUE, 0); - toolbar = get_toolbar_nth (t, i); - flags = egg_toolbars_model_get_flags (model, i); - if (flags & EGG_TB_MODEL_ICONS_ONLY) - { - gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS); - if (i == 0 && t->priv->fixed_toolbar) - { - set_fixed_style (t, GTK_TOOLBAR_ICONS); - } - } + dock = create_dock (etoolbar); + if ((egg_toolbars_model_get_flags (model, i) & EGG_TB_MODEL_HIDDEN) == 0) + gtk_widget_show (dock); + gtk_box_pack_start (GTK_BOX (etoolbar), dock, TRUE, TRUE, 0); + toolbar = get_toolbar_nth (etoolbar, i); n_items = egg_toolbars_model_n_items (model, i); for (l = 0; l < n_items; l++) { - GtkWidget *item; - GtkAction *action; + GtkToolItem *item; - item = create_item (t, model, i, l, &action); + item = create_item_from_position (etoolbar, i, l); if (item) { - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), - GTK_TOOL_ITEM (item), l); - /* FIXME Hack to make tooltip work from gtk */ - if (action) - { - g_object_notify (G_OBJECT (action), "tooltip"); - } + gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, l); + + connect_widget_signals (GTK_WIDGET (item), etoolbar); + configure_item_tooltip (item); + configure_item_sensitivity (item, etoolbar); } else { @@ -954,7 +1268,13 @@ egg_editable_toolbar_construct (EggEditableToolbar *t) } } - update_fixed (t); + update_fixed (etoolbar); + + /* apply styles */ + for (i = 0; i < n_toolbars; i ++) + { + toolbar_changed_cb (model, i, etoolbar); + } } static void @@ -994,46 +1314,201 @@ egg_editable_toolbar_deconstruct (EggEditableToolbar *toolbar) } void -egg_editable_toolbar_set_model (EggEditableToolbar *toolbar, +egg_editable_toolbar_set_model (EggEditableToolbar *etoolbar, 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 = etoolbar->priv; - if (toolbar->priv->model == model) return; + if (priv->model == model) return; - if (toolbar->priv->model) + if (priv->model) { - egg_editable_toolbar_disconnect_model (toolbar); - egg_editable_toolbar_deconstruct (toolbar); + egg_editable_toolbar_disconnect_model (etoolbar); + egg_editable_toolbar_deconstruct (etoolbar); - g_object_unref (toolbar->priv->model); + g_object_unref (priv->model); } - toolbar->priv->model = g_object_ref (model); + priv->model = g_object_ref (model); + + egg_editable_toolbar_build (etoolbar); - egg_editable_toolbar_construct (toolbar); + toolbar_visibility_refresh (etoolbar); g_signal_connect (model, "item_added", - G_CALLBACK (item_added_cb), toolbar); + G_CALLBACK (item_added_cb), etoolbar); g_signal_connect (model, "item_removed", - G_CALLBACK (item_removed_cb), toolbar); + G_CALLBACK (item_removed_cb), etoolbar); g_signal_connect (model, "toolbar_added", - G_CALLBACK (toolbar_added_cb), toolbar); + G_CALLBACK (toolbar_added_cb), etoolbar); g_signal_connect (model, "toolbar_removed", - G_CALLBACK (toolbar_removed_cb), toolbar); + G_CALLBACK (toolbar_removed_cb), etoolbar); g_signal_connect (model, "toolbar_changed", - G_CALLBACK (toolbar_changed_cb), toolbar); + G_CALLBACK (toolbar_changed_cb), etoolbar); } static void -egg_editable_toolbar_set_ui_manager (EggEditableToolbar *t, +egg_editable_toolbar_init (EggEditableToolbar *etoolbar) +{ + EggEditableToolbarPrivate *priv; + + priv = etoolbar->priv = EGG_EDITABLE_TOOLBAR_GET_PRIVATE (etoolbar); + + priv->save_hidden = TRUE; + + g_signal_connect (etoolbar, "notify::visible", + G_CALLBACK (toolbar_visibility_refresh), NULL); +} + +static void +egg_editable_toolbar_dispose (GObject *object) +{ + EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR (object); + EggEditableToolbarPrivate *priv = etoolbar->priv; + GList *children; + + if (priv->fixed_toolbar != NULL) + { + g_object_unref (priv->fixed_toolbar); + priv->fixed_toolbar = NULL; + } + + if (priv->visibility_paths) + { + children = priv->visibility_paths; + g_list_foreach (children, (GFunc) g_free, NULL); + g_list_free (children); + priv->visibility_paths = NULL; + } + + g_free (priv->popup_path); + priv->popup_path = NULL; + + if (priv->manager != NULL) + { + if (priv->visibility_id) + { + gtk_ui_manager_remove_ui (priv->manager, priv->visibility_id); + priv->visibility_id = 0; + } + + g_object_unref (priv->manager); + priv->manager = NULL; + } + + if (priv->model) + { + egg_editable_toolbar_disconnect_model (etoolbar); + g_object_unref (priv->model); + priv->model = NULL; + } + + G_OBJECT_CLASS (egg_editable_toolbar_parent_class)->dispose (object); +} + +static void +egg_editable_toolbar_set_ui_manager (EggEditableToolbar *etoolbar, GtkUIManager *manager) { - g_return_if_fail (GTK_IS_UI_MANAGER (manager)); + static const GtkActionEntry actions[] = { + { "MoveToolItem", STOCK_DRAG_MODE, N_("_Move on Toolbar"), NULL, + N_("Move the selected item on the toolbar"), G_CALLBACK (move_item_cb) }, + { "RemoveToolItem", GTK_STOCK_REMOVE, N_("_Remove from Toolbar"), NULL, + N_("Remove the selected item from the toolbar"), G_CALLBACK (remove_item_cb) }, + { "RemoveToolbar", GTK_STOCK_DELETE, N_("_Delete Toolbar"), NULL, + N_("Remove the selected toolbar"), G_CALLBACK (remove_toolbar_cb) }, + }; + + etoolbar->priv->manager = g_object_ref (manager); + + etoolbar->priv->actions = gtk_action_group_new ("ToolbarActions"); + gtk_action_group_set_translation_domain (etoolbar->priv->actions, GETTEXT_PACKAGE); + gtk_action_group_add_actions (etoolbar->priv->actions, actions, + G_N_ELEMENTS (actions), etoolbar); + gtk_ui_manager_insert_action_group (manager, etoolbar->priv->actions, -1); + g_object_unref (etoolbar->priv->actions); + + toolbar_visibility_refresh (etoolbar); +} + +GtkWidget * egg_editable_toolbar_get_selected (EggEditableToolbar *etoolbar) +{ + return etoolbar->priv->selected; +} + +void +egg_editable_toolbar_set_selected (EggEditableToolbar *etoolbar, + GtkWidget *widget) +{ + GtkWidget *toolbar, *toolitem; + gboolean editable; + + etoolbar->priv->selected = widget; + + toolbar = (widget != NULL) ? gtk_widget_get_ancestor (widget, GTK_TYPE_TOOLBAR) : NULL; + toolitem = (widget != NULL) ? gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM) : NULL; + + if(toolbar != NULL) + { + gint tpos = get_toolbar_position (etoolbar, toolbar); + editable = ((egg_toolbars_model_get_flags (etoolbar->priv->model, tpos) & EGG_TB_MODEL_NOT_EDITABLE) == 0); + } + else + { + editable = FALSE; + } + + gtk_action_set_visible (find_action (etoolbar, "RemoveToolbar"), (toolbar != NULL) && (etoolbar->priv->edit_mode > 0)); + gtk_action_set_visible (find_action (etoolbar, "RemoveToolItem"), (toolitem != NULL) && editable); + gtk_action_set_visible (find_action (etoolbar, "MoveToolItem"), (toolitem != NULL) && editable); +} + +static void +set_edit_mode (EggEditableToolbar *etoolbar, + gboolean mode) +{ + EggEditableToolbarPrivate *priv = etoolbar->priv; + int i, l, n_items; + + i = priv->edit_mode; + if (mode) + { + priv->edit_mode++; + } + else + { + g_return_if_fail (priv->edit_mode > 0); + priv->edit_mode--; + } + i *= priv->edit_mode; + + if (i == 0) + { + for (i = get_n_toolbars (etoolbar)-1; i >= 0; i--) + { + GtkWidget *toolbar; + + toolbar = get_toolbar_nth (etoolbar, i); + n_items = gtk_toolbar_get_n_items (GTK_TOOLBAR (toolbar)); + + if (n_items == 0 && priv->edit_mode == 0) + { + egg_toolbars_model_remove_toolbar (priv->model, i); + } + else + { + for (l = 0; l < n_items; l++) + { + GtkToolItem *item; - t->priv->manager = g_object_ref (manager); + item = gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), l); + + configure_item_cursor (item, etoolbar); + configure_item_sensitivity (item, etoolbar); + } + } + } + } } static void @@ -1042,15 +1517,24 @@ egg_editable_toolbar_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - EggEditableToolbar *t = EGG_EDITABLE_TOOLBAR (object); + EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR (object); switch (prop_id) { case PROP_UI_MANAGER: - egg_editable_toolbar_set_ui_manager (t, g_value_get_object (value)); + egg_editable_toolbar_set_ui_manager (etoolbar, g_value_get_object (value)); break; case PROP_TOOLBARS_MODEL: - egg_editable_toolbar_set_model (t, g_value_get_object (value)); + egg_editable_toolbar_set_model (etoolbar, g_value_get_object (value)); + break; + case PROP_SELECTED: + egg_editable_toolbar_set_selected (etoolbar, g_value_get_object (value)); + break; + case PROP_POPUP_PATH: + etoolbar->priv->popup_path = g_strdup (g_value_get_string (value)); + break; + case PROP_EDIT_MODE: + set_edit_mode (etoolbar, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1064,15 +1548,21 @@ egg_editable_toolbar_get_property (GObject *object, GValue *value, GParamSpec *pspec) { - EggEditableToolbar *t = EGG_EDITABLE_TOOLBAR (object); + EggEditableToolbar *etoolbar = EGG_EDITABLE_TOOLBAR (object); switch (prop_id) { case PROP_UI_MANAGER: - g_value_set_object (value, t->priv->manager); + g_value_set_object (value, etoolbar->priv->manager); break; case PROP_TOOLBARS_MODEL: - g_value_set_object (value, t->priv->model); + g_value_set_object (value, etoolbar->priv->model); + break; + case PROP_SELECTED: + g_value_set_object (value, etoolbar->priv->selected); + break; + case PROP_EDIT_MODE: + g_value_set_boolean (value, etoolbar->priv->edit_mode>0); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1085,9 +1575,7 @@ egg_editable_toolbar_class_init (EggEditableToolbarClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - parent_class = g_type_class_peek_parent (klass); - - object_class->finalize = egg_editable_toolbar_finalize; + 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; @@ -1105,130 +1593,94 @@ egg_editable_toolbar_class_init (EggEditableToolbarClass *klass) "UI-Mmanager", "UI Manager", GTK_TYPE_UI_MANAGER, - G_PARAM_READWRITE)); + G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property (object_class, PROP_TOOLBARS_MODEL, g_param_spec_object ("model", "Model", "Toolbars Model", EGG_TYPE_TOOLBARS_MODEL, - G_PARAM_READWRITE)); - - g_type_class_add_private (object_class, sizeof (EggEditableToolbarPrivate)); -} - -static void -egg_editable_toolbar_init (EggEditableToolbar *t) -{ - t->priv = EGG_EDITABLE_TOOLBAR_GET_PRIVATE (t); -} - -static void -egg_editable_toolbar_finalize (GObject *object) -{ - EggEditableToolbar *t = EGG_EDITABLE_TOOLBAR (object); - - if (t->priv->fixed_toolbar) - { - g_object_unref (t->priv->fixed_toolbar); - } + 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)); - if (t->priv->manager) - { - g_object_unref (t->priv->manager); - } + g_object_class_install_property (object_class, + PROP_POPUP_PATH, + g_param_spec_string ("popup-path", + "popup-path", + "popup-path", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - if (t->priv->model) - { - egg_editable_toolbar_disconnect_model (t); - g_object_unref (t->priv->model); - } + g_object_class_install_property (object_class, + PROP_EDIT_MODE, + g_param_spec_boolean ("edit-mode", + "Edit-Mode", + "Edit Mode", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - G_OBJECT_CLASS (parent_class)->finalize (object); + g_type_class_add_private (object_class, sizeof (EggEditableToolbarPrivate)); } GtkWidget * -egg_editable_toolbar_new (GtkUIManager *manager) +egg_editable_toolbar_new (GtkUIManager *manager, + const char *popup_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, + "popup-path", popup_path, + NULL)); } GtkWidget * -egg_editable_toolbar_new_with_model (GtkUIManager *manager, - EggToolbarsModel *model) +egg_editable_toolbar_new_with_model (GtkUIManager *manager, + EggToolbarsModel *model, + const char *popup_path) { return GTK_WIDGET (g_object_new (EGG_TYPE_EDITABLE_TOOLBAR, - "ui-manager", manager, - "model", model, + "ui-manager", manager, + "model", model, + "popup-path", popup_path, NULL)); } gboolean egg_editable_toolbar_get_edit_mode (EggEditableToolbar *etoolbar) { - return etoolbar->priv->edit_mode; + EggEditableToolbarPrivate *priv = etoolbar->priv; + + return priv->edit_mode > 0; } void egg_editable_toolbar_set_edit_mode (EggEditableToolbar *etoolbar, - gboolean mode) + gboolean mode) { - int i, l, n_toolbars, n_items; - - etoolbar->priv->edit_mode = mode; - - n_toolbars = get_n_toolbars (etoolbar); - for (i = 0; i < n_toolbars; i++) - { - GtkWidget *toolbar; - - toolbar = get_toolbar_nth (etoolbar, i); - n_items = gtk_toolbar_get_n_items (GTK_TOOLBAR (toolbar)); - for (l = 0; l < n_items; l++) - { - GtkToolItem *item; - const char *action_name, *type; - gboolean is_separator; - GtkAction *action = NULL; - - egg_toolbars_model_item_nth (etoolbar->priv->model, i, l, - &is_separator, &action_name, &type); - action = find_action (etoolbar, action_name); - - item = gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), l); - gtk_tool_item_set_use_drag_window (item, mode); - - if (mode) - { - set_drag_cursor (GTK_WIDGET (item)); - gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE); - set_item_drag_source (etoolbar->priv->model, GTK_WIDGET (item), - action, is_separator, type); - } - else - { - unset_drag_cursor (GTK_WIDGET (item)); - gtk_drag_source_unset (GTK_WIDGET (item)); + set_edit_mode (etoolbar, mode); + g_object_notify (G_OBJECT (etoolbar), "edit-mode"); +} - if (!is_separator) - { - g_object_notify (G_OBJECT (action), "sensitive"); - } - } - } - } +void +egg_editable_toolbar_add_visibility (EggEditableToolbar *etoolbar, + const char *path) +{ + etoolbar->priv->visibility_paths = g_list_prepend + (etoolbar->priv->visibility_paths, g_strdup (path)); } 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++) @@ -1237,20 +1689,19 @@ egg_editable_toolbar_show (EggEditableToolbar *etoolbar, 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++) @@ -1266,89 +1717,31 @@ egg_editable_toolbar_hide (EggEditableToolbar *etoolbar, } void -egg_editable_toolbar_set_fixed (EggEditableToolbar *toolbar, - GtkToolItem *fixed) +egg_editable_toolbar_set_fixed (EggEditableToolbar *etoolbar, + GtkToolbar *toolbar) { - g_return_if_fail (EGG_IS_EDITABLE_TOOLBAR (toolbar)); - g_return_if_fail (!fixed || GTK_IS_TOOL_ITEM (fixed)); + EggEditableToolbarPrivate *priv = etoolbar->priv; - if (!toolbar->priv->fixed_toolbar) - { - toolbar->priv->fixed_toolbar = gtk_toolbar_new (); - gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar->priv->fixed_toolbar), FALSE); - g_object_ref (toolbar->priv->fixed_toolbar); - gtk_object_sink (GTK_OBJECT (toolbar->priv->fixed_toolbar)); - } + g_return_if_fail (!toolbar || GTK_IS_TOOLBAR (toolbar)); - if (toolbar->priv->fixed) + if (priv->fixed_toolbar) { - gtk_container_remove (GTK_CONTAINER (toolbar->priv->fixed_toolbar), - GTK_WIDGET (toolbar->priv->fixed)); - g_object_unref (toolbar->priv->fixed); + unparent_fixed (etoolbar); + g_object_unref (priv->fixed_toolbar); + priv->fixed_toolbar = NULL; } - toolbar->priv->fixed = fixed; - - if (fixed) + if (toolbar) { - g_object_ref (fixed); - gtk_object_sink (GTK_OBJECT (fixed)); - - gtk_toolbar_insert (GTK_TOOLBAR (toolbar->priv->fixed_toolbar), fixed, 0); + priv->fixed_toolbar = GTK_WIDGET (toolbar); + gtk_toolbar_set_show_arrow (toolbar, FALSE); + g_object_ref_sink (toolbar); } -} - -void -egg_editable_toolbar_set_drag_dest (EggEditableToolbar *etoolbar, - const GtkTargetEntry *targets, - gint n_targets, - const char *toolbar_name) -{ - 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++) - { - const char *name; - name = egg_toolbars_model_toolbar_nth (model, i); - if (strcmp (toolbar_name, name) == 0) - { - GtkWidget *widget = get_toolbar_nth (etoolbar, i); - - gtk_drag_dest_unset (widget); - gtk_drag_dest_set (widget, 0, - targets, n_targets, - GDK_ACTION_MOVE | GDK_ACTION_COPY); - } - } + update_fixed (etoolbar); } #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 @@ -1360,75 +1753,42 @@ new_pixbuf_from_widget (GtkWidget *widget) { GtkWidget *window; GdkPixbuf *pixbuf; - GtkRequisition requisition; - GtkAllocation allocation; - GdkPixmap *pixmap; - GdkVisual *visual; - gint icon_width; gint icon_height; + GdkScreen *screen; - icon_width = DEFAULT_ICON_WIDTH; + screen = gtk_widget_get_screen (widget); - if (!gtk_icon_size_lookup_for_settings (gtk_settings_get_default (), + if (!gtk_icon_size_lookup_for_settings (gtk_settings_get_for_screen (screen), GTK_ICON_SIZE_LARGE_TOOLBAR, - NULL, + NULL, &icon_height)) { icon_height = DEFAULT_ICON_HEIGHT; } - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - + window = gtk_offscreen_window_new (); + /* Set the width to -1 as we want the separator to be as thin as possible. */ + gtk_widget_set_size_request (widget, -1, icon_height); + 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, gdk_visual_get_best_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_show_all (window); + + /* Process the waiting events to have the widget actually drawn */ + gdk_window_process_updates (gtk_widget_get_window (window), TRUE); + pixbuf = gtk_offscreen_window_get_pixbuf (GTK_OFFSCREEN_WINDOW (window)); + gtk_widget_destroy (window); return pixbuf; } static GdkPixbuf * -new_separator_pixbuf () +new_separator_pixbuf (void) { GtkWidget *separator; GdkPixbuf *pixbuf; separator = gtk_vseparator_new (); pixbuf = new_pixbuf_from_widget (separator); - gtk_widget_destroy (separator); return pixbuf; }