diff options
Diffstat (limited to 'lib/widgets')
-rwxr-xr-x | lib/widgets/ephy-editable-toolbar.c | 414 |
1 files changed, 199 insertions, 215 deletions
diff --git a/lib/widgets/ephy-editable-toolbar.c b/lib/widgets/ephy-editable-toolbar.c index eca819e12..5cfc21aff 100755 --- a/lib/widgets/ephy-editable-toolbar.c +++ b/lib/widgets/ephy-editable-toolbar.c @@ -20,6 +20,7 @@ #include "ephy-editable-toolbar.h" #include "ephy-file-helpers.h" #include "ephy-debug.h" +#include "eggtoolitem.h" #include <libxml/parser.h> #include <string.h> @@ -40,7 +41,7 @@ static void ephy_editable_toolbar_class_init (EphyEditableToolbarClass *klass); static void ephy_editable_toolbar_init (EphyEditableToolbar *t); static void ephy_editable_toolbar_finalize (GObject *object); -static void do_merge (EphyEditableToolbar *t, GList *toolbars); +static void do_merge (EphyEditableToolbar *t); enum { @@ -61,16 +62,28 @@ static gint EphyEditableToolbarSignals[LAST_SIGNAL]; struct EphyEditableToolbarPrivate { EggMenuMerge *merge; - GList *available_actions; - GList *toolbars; + GNode *available_actions; + GNode *toolbars; char *filename; GtkWidget *editor; GtkWidget *table; guint ui_id; + gboolean ui_dirty; }; +typedef struct +{ + GtkWidget *widget; +} ToolbarNode; + +typedef struct +{ + gboolean separator; + EggAction *action; +} ItemNode; + GType ephy_editable_toolbar_get_type (void) { @@ -100,45 +113,27 @@ ephy_editable_toolbar_get_type (void) } -static void -copy_toolbars (EphyEditableToolbar *t, GList **copy) +static ToolbarNode * +toolbar_node_new (void) { - GList *l; + ToolbarNode *node; - *copy = NULL; + node = g_new0 (ToolbarNode, 1); + node->widget = NULL; - for (l = t->priv->toolbars; l != NULL; l = l->next) - { - GList *l2; - - l2 = g_list_copy (l->data); - - *copy = g_list_append (*copy, l2); - } + return node; } -static gboolean -is_action_in_toolbars (EphyEditableToolbar *t, EggAction *action) +static ItemNode * +item_node_new (EggAction *action, gboolean separator) { - GList *l1, *l2; + ItemNode *item; - for (l1 = t->priv->toolbars; l1 != NULL; l1 = l1->next) - { - for (l2 = l1->data; l2 != NULL; l2 = l2->next) - { - if (l2->data == action) return TRUE; - } - } + item = g_new0 (ItemNode, 1); + item->action = action; + item->separator = separator; - return FALSE; -} - -static gboolean -is_separator (EggAction *action) -{ - g_return_val_if_fail (action != NULL, FALSE); - - return (strcmp (action->name, "separator") == 0); + return item; } static EggAction * @@ -159,64 +154,55 @@ find_action (EphyEditableToolbar *t, const char *name) return action; } -static GList ** -find_toolbar_from_widget (EphyEditableToolbar *t, GList *toolbars, GtkWidget *widget) +static GNode * +find_node_from_action (EphyEditableToolbar *t, EggAction *action) { - GList *l; - int i = 0; + GNode *n1, *n2; - for (l = toolbars; l != NULL; l = l->next) + for (n1 = t->priv->toolbars->children; n1 != NULL; n1 = n1->next) { - char path[255]; - GtkWidget *toolbar; - - sprintf (path, "/Toolbar%d", i); - toolbar = egg_menu_merge_get_widget (t->priv->merge, path); + for (n2 = n1->children; n2 != NULL; n2 = n2->next) + { + ItemNode *item = (ItemNode *) (n2->data); - if (widget == toolbar) return (GList **)(&(l->data)); - i++; + if (!item->separator && item->action == action) + return n2; + } } return NULL; } static void -add_action_to_list (EphyEditableToolbar *t, - GList **list, - const char *name, - EggAction *sibling) +add_action (EphyEditableToolbar *t, + GNode *parent, + GNode *sibling, + const char *name) { EggAction *action = NULL; + gboolean separator; + ItemNode *item; + GNode *node; action = find_action (t, name); + separator = (strcmp (name, "separator") == 0); - if (!action) + if (!action && !separator) { g_signal_emit (t, EphyEditableToolbarSignals[REQUEST_ACTION], 0, name); + action = find_action (t, name); } - action = find_action (t, name); - - if (action && sibling) - { - GList *s; - - LOG ("Adding action %s to list, sibling is %s", name, sibling->name) + item = item_node_new (action, separator); + node = g_node_new (item); - s = g_list_find (*list, sibling); - g_return_if_fail (s != NULL); - *list = g_list_insert_before (*list, s, action); - } - else - { - *list = g_list_append (*list, action); - } + g_node_insert_before (parent, sibling, node); } static void parse_item_list (EphyEditableToolbar *t, xmlNodePtr child, - GList **actions) + GNode *parent) { while (child) { @@ -225,19 +211,13 @@ parse_item_list (EphyEditableToolbar *t, xmlChar *verb; verb = xmlGetProp (child, "verb"); - add_action_to_list (t, actions, verb, NULL); + add_action (t, parent, NULL, verb); xmlFree (verb); } else if (xmlStrEqual (child->name, "separator")) { - EggAction *separator; - - separator = g_object_new (EGG_TYPE_ACTION, - "name", "separator", - NULL); - - *actions = g_list_append (*actions, separator); + add_action (t, parent, NULL, "separator"); } child = child->next; @@ -247,16 +227,20 @@ parse_item_list (EphyEditableToolbar *t, static void parse_toolbars (EphyEditableToolbar *t, xmlNodePtr child, - GList **toolbars) + GNode *toolbars) { while (child) { if (xmlStrEqual (child->name, "toolbar")) { - GList *list = NULL; + ToolbarNode *toolbar; + GNode *node; + + toolbar = toolbar_node_new (); + node = g_node_new (toolbar); + g_node_append (toolbars, node); - parse_item_list (t, child->children, &list); - *toolbars = g_list_append (*toolbars, list); + parse_item_list (t, child->children, node); } child = child->next; @@ -283,14 +267,16 @@ load_defaults (EphyEditableToolbar *t) { if (xmlStrEqual (child->name, "available")) { + t->priv->available_actions = g_node_new (NULL); parse_item_list (t, child->children, - &t->priv->available_actions); + t->priv->available_actions); } else if (xmlStrEqual (child->name, "default") && t->priv->toolbars == NULL) { + t->priv->toolbars = g_node_new (NULL); parse_toolbars (t, child->children, - &t->priv->toolbars); + t->priv->toolbars); } child = child->next; @@ -311,39 +297,40 @@ load_toolbar (EphyEditableToolbar *t) doc = xmlParseFile (xml_filepath); root = xmlDocGetRootElement (doc); + t->priv->toolbars = g_node_new (NULL); parse_toolbars (t, root->children, - &t->priv->toolbars); + t->priv->toolbars); } static xmlDocPtr -toolbar_list_to_xml (EphyEditableToolbar *t, GList *tl) +toolbar_list_to_xml (EphyEditableToolbar *t, GNode *tl) { - GList *l1, *l2; + GNode *l1, *l2; xmlDocPtr doc; xmlIndentTreeOutput = TRUE; doc = xmlNewDoc ("1.0"); doc->children = xmlNewDocNode (doc, NULL, "toolbars", NULL); - for (l1 = tl; l1 != NULL; l1 = l1->next) + for (l1 = tl->children; l1 != NULL; l1 = l1->next) { xmlNodePtr tnode; tnode = xmlNewChild (doc->children, NULL, "toolbar", NULL); - for (l2 = l1->data; l2 != NULL; l2 = l2->next) + for (l2 = l1->children; l2 != NULL; l2 = l2->next) { xmlNodePtr node; - EggAction *action = EGG_ACTION (l2->data); + ItemNode *item = (ItemNode *) (l2->data); - if (is_separator (action)) + if (item->separator) { node = xmlNewChild (tnode, NULL, "separator", NULL); } else { node = xmlNewChild (tnode, NULL, "toolitem", NULL); - xmlSetProp (node, "verb", action->name); + xmlSetProp (node, "verb", item->action->name); } } } @@ -352,27 +339,27 @@ toolbar_list_to_xml (EphyEditableToolbar *t, GList *tl) } static char * -toolbar_list_to_string (EphyEditableToolbar *t, GList *tl) +toolbar_list_to_string (EphyEditableToolbar *t, GNode *tl) { GString *s; - GList *l1, *l2; + GNode *l1, *l2; char *result; + int k = 0; s = g_string_new (NULL); g_string_append (s, "<Root>"); - for (l1 = tl; l1 != NULL; l1 = l1->next) + for (l1 = tl->children; l1 != NULL; l1 = l1->next) { int i = 0; g_string_append_printf - (s, "<dockitem name=\"Toolbar%d\">\n", - g_list_index (tl, l1->data)); + (s, "<dockitem name=\"Toolbar%d\">\n", k); - for (l2 = l1->data; l2 != NULL; l2 = l2->next) + for (l2 = l1->children; l2 != NULL; l2 = l2->next) { - EggAction *action = EGG_ACTION (l2->data); + ItemNode *item = (ItemNode *) (l2->data); - if (is_separator (action)) + if (item->separator) { g_string_append_printf (s, "<placeholder name=\"PlaceHolder%d\">" @@ -385,12 +372,14 @@ toolbar_list_to_string (EphyEditableToolbar *t, GList *tl) (s, "<placeholder name=\"PlaceHolder%d\">" "<toolitem name=\"ToolItem\" verb=\"%s\"/>" "</placeholder>\n", - i, action->name); + i, item->action->name); } i++; } g_string_append (s, "</dockitem>\n"); + + k++; } g_string_append (s, "</Root>"); @@ -401,6 +390,24 @@ toolbar_list_to_string (EphyEditableToolbar *t, GList *tl) return result; } +static gboolean +ui_update (gpointer data) +{ + EphyEditableToolbar *etoolbar = EPHY_EDITABLE_TOOLBAR (data); + + do_merge (etoolbar); + + return FALSE; +} + +static void +queue_ui_update (EphyEditableToolbar *etoolbar) +{ + etoolbar->priv->ui_dirty = TRUE; + + g_idle_add (ui_update, etoolbar); +} + static void drag_data_received_cb (GtkWidget *widget, GdkDragContext *context, @@ -411,99 +418,69 @@ drag_data_received_cb (GtkWidget *widget, guint time_, EphyEditableToolbar *etoolbar) { - EggAction *action; - gboolean motion; - GList **toolbar; - GList *toolbars; - - LOG ("Received data, action is %s", (char *)selection_data->data); - - action = EGG_ACTION (g_object_get_data (G_OBJECT (widget), "egg-action")); - g_return_if_fail (action != NULL); - - /* Dragging over itself, ignore */ - if (strcmp (action->name, selection_data->data) == 0) return; + GNode *parent; + GNode *sibling; - motion = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "motion")); - if (motion) - { - copy_toolbars (etoolbar, &toolbars); - } - else - { - toolbars = etoolbar->priv->toolbars; - } + sibling = (GNode *)g_object_get_data (G_OBJECT (widget), "item_node"); + parent = sibling->parent; - toolbar = find_toolbar_from_widget (etoolbar, toolbars, widget->parent); - g_return_if_fail (toolbar != NULL); + add_action (etoolbar, parent, sibling, selection_data->data); - add_action_to_list (etoolbar, toolbar, selection_data->data, action); - - do_merge (etoolbar, motion ? toolbars : NULL); + queue_ui_update (etoolbar); } -static gboolean -drag_motion_cb (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time) +static void +drag_data_delete_cb (GtkWidget *widget, + GdkDragContext *context, + EphyEditableToolbar *etoolbar) { - GdkAtom target; + GNode *node; - LOG ("Motion") + node = (GNode *)g_object_get_data (G_OBJECT (widget), "item_node"); + g_node_unlink (node); - target = gtk_drag_dest_find_target (widget, context, NULL); - if (target != GDK_NONE) - { - g_object_set_data (G_OBJECT (widget), "motion", GINT_TO_POINTER (TRUE)); - gtk_drag_get_data (widget, context, target, time); - } - - gdk_drag_status (context, GDK_ACTION_MOVE, time); - - return TRUE; + queue_ui_update (etoolbar); } -static gboolean -drag_drop_cb (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time) +static void +drag_data_get_cb (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint32 time, + EphyEditableToolbar *etoolbar) { - GdkAtom target; + EggAction *action; + const char *target; - LOG ("Drop") + action = EGG_ACTION (g_object_get_data (G_OBJECT (widget), "egg-action")); + target = action->name; - target = gtk_drag_dest_find_target (widget, context, NULL); - if (target != GDK_NONE) - { - g_object_set_data (G_OBJECT (widget), "motion", GINT_TO_POINTER (FALSE)); - gtk_drag_get_data (widget, context, target, time); - } + LOG ("Drag data get %s", action->name); - return TRUE; + gtk_selection_data_set (selection_data, + selection_data->target, + 8, target, strlen (target)); } static void -setup_toolbar_drag (EphyEditableToolbar *etoolbar, GList *toolbars) +setup_toolbar_drag (EphyEditableToolbar *etoolbar, GNode *toolbars) { - GList *l1, *l2; + GNode *l1, *l2; int k = 0; - for (l1 = toolbars; l1 != NULL; l1 = l1->next) + for (l1 = toolbars->children; l1 != NULL; l1 = l1->next) { int i = 0; - for (l2 = l1->data; l2 != NULL; l2 = l2->next) + for (l2 = l1->children; l2 != NULL; l2 = l2->next) { - EggAction *action = EGG_ACTION (l2->data); + ItemNode *node = (ItemNode *) (l2->data); GtkWidget *toolitem; char path[255]; const char *type; - if (is_separator (action)) + if (node->separator) { type ="ToolSeparator"; } @@ -513,30 +490,28 @@ setup_toolbar_drag (EphyEditableToolbar *etoolbar, GList *toolbars) } sprintf (path, "/Toolbar%d/PlaceHolder%d/%s", k, i, type); - LOG ("Setup drag dest for toolbar item %s", path); toolitem = egg_menu_merge_get_widget (etoolbar->priv->merge, path); - if (is_separator (action)) - { - g_object_set_data (G_OBJECT (toolitem), "egg-action", action); - } + g_object_set_data (G_OBJECT (toolitem), "item_node", l2); + + LOG ("Setup drag dest for toolbar item %s %p", path, toolitem); if (!g_object_get_data (G_OBJECT (toolitem), "drag_dest_set")) { g_object_set_data (G_OBJECT (toolitem), "drag_dest_set", GINT_TO_POINTER (TRUE)); - - gtk_drag_dest_set (GTK_WIDGET (toolitem), 0, + gtk_drag_dest_set (toolitem, GTK_DEST_DEFAULT_ALL, drag_types, 1, GDK_ACTION_MOVE); g_signal_connect (toolitem, "drag_data_received", G_CALLBACK (drag_data_received_cb), etoolbar); - g_signal_connect (toolitem, "drag_motion", - G_CALLBACK (drag_motion_cb), + + g_signal_connect (toolitem, "drag_data_get", + G_CALLBACK (drag_data_get_cb), etoolbar); - g_signal_connect (toolitem, "drag_drop", - G_CALLBACK (drag_drop_cb), + g_signal_connect (toolitem, "drag_data_delete", + G_CALLBACK (drag_data_delete_cb), etoolbar); } @@ -548,15 +523,12 @@ setup_toolbar_drag (EphyEditableToolbar *etoolbar, GList *toolbars) } static void -do_merge (EphyEditableToolbar *t, GList *toolbars) +do_merge (EphyEditableToolbar *t) { - GList *tl; char *str; guint ui_id; - tl = toolbars ? toolbars : t->priv->toolbars; - - str = toolbar_list_to_string (t, tl); + str = toolbar_list_to_string (t, t->priv->toolbars); LOG ("Merge UI\n%s", str) @@ -575,7 +547,7 @@ do_merge (EphyEditableToolbar *t, GList *toolbars) egg_menu_merge_ensure_update (t->priv->merge); - setup_toolbar_drag (t, tl); + setup_toolbar_drag (t, t->priv->toolbars); g_free (str); } @@ -589,7 +561,7 @@ ephy_editable_toolbar_set_merge (EphyEditableToolbar *t, EggMenuMerge *merge) load_toolbar (t); load_defaults (t); - do_merge (t, NULL); + do_merge (t); } static void @@ -666,6 +638,7 @@ ephy_editable_toolbar_init (EphyEditableToolbar *t) t->priv->filename = g_build_filename (ephy_dot_dir (), "toolbar.xml", NULL); t->priv->editor = NULL; t->priv->ui_id = 0; + t->priv->ui_dirty = FALSE; } static void @@ -763,41 +736,21 @@ editor_get_dimensions (GtkWidget *window, GtkWidget *toolbar, GtkWidget *table, *x = *x + (real_width/2 - *width/2); } -static void -drag_data_get_cb (GtkWidget *widget, - GdkDragContext *context, - GtkSelectionData *selection_data, - guint info, - guint32 time, - EphyEditableToolbar *etoolbar) -{ - EggAction *action; - const char *target; - - action = EGG_ACTION (g_object_get_data (G_OBJECT (widget), "egg-action")); - target = action->name; - - LOG ("Drag data get %s", action->name); - - gtk_selection_data_set (selection_data, - selection_data->target, - 8, target, strlen (target)); -} - static GList * build_to_drag_actions_list (EphyEditableToolbar *etoolbar) { - GList *l; + GNode *l; GList *result = NULL; - for (l = etoolbar->priv->available_actions; l != NULL; l = l->next) + for (l = etoolbar->priv->available_actions->children; l != NULL; l = l->next) { - EggAction *action; + ItemNode *item; + + item = (ItemNode *) (l->data); - action = EGG_ACTION (l->data); - if (!is_action_in_toolbars (etoolbar, action)) + if (!find_node_from_action (etoolbar, item->action)) { - result = g_list_append (result, action); + result = g_list_append (result, item); } } @@ -851,7 +804,8 @@ setup_editor (EphyEditableToolbar *etoolbar) GtkWidget *vbox; GtkWidget *icon; GtkWidget *label; - EggAction *action = EGG_ACTION (l->data); + ItemNode *node = (ItemNode *) (l->data); + EggAction *action = EGG_ACTION (node->action); event_box = gtk_event_box_new (); gtk_widget_show (event_box); @@ -893,6 +847,33 @@ setup_editor (EphyEditableToolbar *etoolbar) g_list_free (to_drag); } +static gboolean +button_press_cb (GtkWidget *w, + GdkEvent *event, + EphyEditableToolbar *etoolbar) +{ + GtkWidget *widget; + GtkWidget *toolitem; + + widget = gtk_get_event_widget (event); + toolitem = gtk_widget_get_ancestor (widget, EGG_TYPE_TOOL_ITEM); + + if (toolitem == NULL) return FALSE; + + switch (event->type) + { + case GDK_BUTTON_PRESS: + gtk_drag_begin (toolitem, + gtk_target_list_new (drag_types, 1), + GDK_ACTION_MOVE, 1, event); + return TRUE; + default: + break; + } + + return FALSE; +} + static void show_editor (EphyEditableToolbar *etoolbar, GtkWidget *toolbar) { @@ -907,19 +888,22 @@ show_editor (EphyEditableToolbar *etoolbar, GtkWidget *toolbar) gtk_window_move (GTK_WINDOW (editor), x, y); gtk_widget_show (GTK_WIDGET (editor)); gtk_grab_add (editor); + + g_signal_connect (editor, "button_press_event", + G_CALLBACK (button_press_cb), + etoolbar); } static void set_all_actions_sensitive (EphyEditableToolbar *etoolbar) { - GList *l; + GNode *l; - for (l = etoolbar->priv->available_actions; l != NULL; l = l->next) + for (l = etoolbar->priv->available_actions->children; l != NULL; l = l->next) { - EggAction *action; + ItemNode *node = (ItemNode *) (l->data); - action = EGG_ACTION (l->data); - g_object_set (action, "sensitive", TRUE, NULL); + g_object_set (node->action, "sensitive", TRUE, NULL); } } @@ -929,7 +913,7 @@ ephy_editable_toolbar_edit (EphyEditableToolbar *etoolbar) GtkWidget *last_toolbar; char path[255]; - sprintf (path, "/Toolbar%d", g_list_length (etoolbar->priv->toolbars) - 1); + sprintf (path, "/Toolbar%d", g_node_n_children (etoolbar->priv->toolbars) - 1); last_toolbar = egg_menu_merge_get_widget (etoolbar->priv->merge, path); set_all_actions_sensitive (etoolbar); |