Code

plumb XML::Document parameter into duplication, courtesy of bryce
[inkscape.git] / src / ui / context-menu.cpp
1 #define __CONTEXT_MENU_C__
3 /*
4  * Unser-interface related object extension
5  *
6  * Authors:
7  *   Lauris Kaplinski <lauris@kaplinski.com>
8  *
9  * This code is in public domain
10  */
12 #ifdef HAVE_CONFIG_H
13 # include "config.h"
14 #endif
16 #include "context-menu.h"
17 #include "../xml/repr.h"
18 #include "desktop.h"
19 #include "document.h"
21 static void sp_object_type_menu(GType type, SPObject *object, SPDesktop *desktop, GtkMenu *menu);
23 /* Append object-specific part to context menu */
25 void
26 sp_object_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu)
27 {
28     GObjectClass *klass;
29     klass = G_OBJECT_GET_CLASS(object);
30     while (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_OBJECT)) {
31         GType type;
32         type = G_TYPE_FROM_CLASS(klass);
33         sp_object_type_menu(type, object, desktop, menu);
34         klass = (GObjectClass*)g_type_class_peek_parent(klass);
35     }
36 }
38 /* Implementation */
40 #include <gtk/gtkmenuitem.h>
42 #include <glibmm/i18n.h>
44 #include "sp-anchor.h"
45 #include "sp-image.h"
47 #include "document.h"
48 #include "desktop-handles.h"
49 #include "selection.h"
51 #include "dialogs/item-properties.h"
52 #include "dialogs/object-attributes.h"
53 #include "dialogs/object-properties.h"
55 #include "sp-path.h"
58 static void sp_item_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu);
59 static void sp_group_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu);
60 static void sp_anchor_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu);
61 static void sp_image_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu);
62 static void sp_shape_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu);
64 static void
65 sp_object_type_menu(GType type, SPObject *object, SPDesktop *desktop, GtkMenu *menu)
66 {
67     static GHashTable *t2m = NULL;
68     void (* handler)(SPObject *object, SPDesktop *desktop, GtkMenu *menu);
69     if (!t2m) {
70         t2m = g_hash_table_new(NULL, NULL);
71         g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_ITEM), (void*)sp_item_menu);
72         g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_GROUP), (void*)sp_group_menu);
73         g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_ANCHOR), (void*)sp_anchor_menu);
74         g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_IMAGE), (void*)sp_image_menu);
75         g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_SHAPE), (void*)sp_shape_menu);
76     }
77     handler = (void (*)(SPObject*, SPDesktop*, GtkMenu*))g_hash_table_lookup(t2m, GUINT_TO_POINTER(type));
78     if (handler) handler(object, desktop, menu);
79 }
81 /* SPItem */
83 static void sp_item_properties(GtkMenuItem *menuitem, SPItem *item);
84 static void sp_item_select_this(GtkMenuItem *menuitem, SPItem *item);
85 static void sp_item_create_link(GtkMenuItem *menuitem, SPItem *item);
87 /* Generate context menu item section */
89 static void
90 sp_item_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m)
91 {
92     SPItem *item;
93     GtkWidget *w;
95     item = (SPItem *) object;
97     /* Item dialog */
98     w = gtk_menu_item_new_with_mnemonic(_("Object _Properties"));
99     gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
100     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_item_properties), item);
101     gtk_widget_show(w);
102     gtk_menu_append(GTK_MENU(m), w);
103     /* Separator */
104     w = gtk_menu_item_new();
105     gtk_widget_show(w);
106     gtk_menu_append(GTK_MENU(m), w);
107     /* Select item */
108     w = gtk_menu_item_new_with_mnemonic(_("_Select This"));
109     if (sp_desktop_selection(desktop)->includes(item)) {
110         gtk_widget_set_sensitive(w, FALSE);
111     } else {
112         gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
113         gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_item_select_this), item);
114     }
115     gtk_widget_show(w);
116     gtk_menu_append(GTK_MENU(m), w);
117     /* Create link */
118     w = gtk_menu_item_new_with_mnemonic(_("_Create Link"));
119     gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
120     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_item_create_link), item);
121     gtk_widget_set_sensitive(w, !SP_IS_ANCHOR(item));
122     gtk_widget_show(w);
123     gtk_menu_append(GTK_MENU(m), w);
126 static void
127 sp_item_properties(GtkMenuItem *menuitem, SPItem *item)
129     SPDesktop *desktop;
131     g_assert(SP_IS_ITEM(item));
133     desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop");
134     g_return_if_fail(desktop != NULL);
136     sp_desktop_selection(desktop)->set(item);
138     sp_item_dialog();
141 static void
142 sp_item_select_this(GtkMenuItem *menuitem, SPItem *item)
144     SPDesktop *desktop;
146     g_assert(SP_IS_ITEM(item));
148     desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop");
149     g_return_if_fail(desktop != NULL);
151     sp_desktop_selection(desktop)->set(item);
154 static void
155 sp_item_create_link(GtkMenuItem *menuitem, SPItem *item)
157     g_assert(SP_IS_ITEM(item));
158     g_assert(!SP_IS_ANCHOR(item));
160     SPDesktop *desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop");
161     g_return_if_fail(desktop != NULL);
163     Inkscape::XML::Document *xml_doc = sp_document_repr_doc(desktop->doc());
164     Inkscape::XML::Node *repr = xml_doc->createElement("svg:a");
165     SP_OBJECT_REPR(SP_OBJECT_PARENT(item))->addChild(repr, SP_OBJECT_REPR(item));
166     SPObject *object = SP_OBJECT_DOCUMENT(item)->getObjectByRepr(repr);
167     g_return_if_fail(SP_IS_ANCHOR(object));
169     const char *id = SP_OBJECT_REPR(item)->attribute("id");
170     Inkscape::XML::Node *child = SP_OBJECT_REPR(item)->duplicate(xml_doc);
171     SP_OBJECT(item)->deleteObject(false);
172     repr->addChild(child, NULL);
173     child->setAttribute("id", id);
174     sp_document_done(SP_OBJECT_DOCUMENT(object), SP_VERB_NONE, 
175                      _("Create link"));
177     sp_object_attributes_dialog(object, "SPAnchor");
179     sp_desktop_selection(desktop)->set(SP_ITEM(object));
182 /* SPGroup */
184 static void sp_item_group_ungroup_activate(GtkMenuItem *menuitem, SPGroup *group);
186 static void
187 sp_group_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu)
189     SPItem *item=SP_ITEM(object);
190     GtkWidget *w;
192     /* "Ungroup" */
193     w = gtk_menu_item_new_with_mnemonic(_("_Ungroup"));
194     gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
195     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_item_group_ungroup_activate), item);
196     gtk_widget_show(w);
197     gtk_menu_append(GTK_MENU(menu), w);
200 static void
201 sp_item_group_ungroup_activate(GtkMenuItem *menuitem, SPGroup *group)
203     SPDesktop *desktop;
204     GSList *children;
206     g_assert(SP_IS_GROUP(group));
208     desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop");
209     g_return_if_fail(desktop != NULL);
211     children = NULL;
212     sp_item_group_ungroup(group, &children);
214     sp_desktop_selection(desktop)->setList(children);
215     g_slist_free(children);
218 /* SPAnchor */
220 static void sp_anchor_link_properties(GtkMenuItem *menuitem, SPAnchor *anchor);
221 static void sp_anchor_link_follow(GtkMenuItem *menuitem, SPAnchor *anchor);
222 static void sp_anchor_link_remove(GtkMenuItem *menuitem, SPAnchor *anchor);
224 static void
225 sp_anchor_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m)
227     SPItem *item;
228     GtkWidget *w;
230     item = (SPItem *) object;
232     /* Link dialog */
233     w = gtk_menu_item_new_with_mnemonic(_("Link _Properties"));
234     gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
235     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_anchor_link_properties), item);
236     gtk_widget_show(w);
237     gtk_menu_append(GTK_MENU(m), w);
238     /* Separator */
239     w = gtk_menu_item_new();
240     gtk_widget_show(w);
241     gtk_menu_append(GTK_MENU(m), w);
242     /* Select item */
243     w = gtk_menu_item_new_with_mnemonic(_("_Follow Link"));
244     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_anchor_link_follow), item);
245     gtk_widget_show(w);
246     gtk_menu_append(GTK_MENU(m), w);
247     /* Reset transformations */
248     w = gtk_menu_item_new_with_mnemonic(_("_Remove Link"));
249     gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
250     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_anchor_link_remove), item);
251     gtk_widget_show(w);
252     gtk_menu_append(GTK_MENU(m), w);
255 static void
256 sp_anchor_link_properties(GtkMenuItem *menuitem, SPAnchor *anchor)
258     sp_object_attributes_dialog(SP_OBJECT(anchor), "Link");
261 static void
262 sp_anchor_link_follow(GtkMenuItem *menuitem, SPAnchor *anchor)
264     g_return_if_fail(anchor != NULL);
265     g_return_if_fail(SP_IS_ANCHOR(anchor));
267     /* shell out to an external browser here */
270 static void
271 sp_anchor_link_remove(GtkMenuItem *menuitem, SPAnchor *anchor)
273     GSList *children;
275     g_return_if_fail(anchor != NULL);
276     g_return_if_fail(SP_IS_ANCHOR(anchor));
278     children = NULL;
279     sp_item_group_ungroup(SP_GROUP(anchor), &children);
281     g_slist_free(children);
284 /* Image */
286 static void sp_image_image_properties(GtkMenuItem *menuitem, SPAnchor *anchor);
288 static void
289 sp_image_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m)
291     SPItem *item;
292     GtkWidget *w;
294     item = (SPItem *) object;
296     /* Link dialog */
297     w = gtk_menu_item_new_with_mnemonic(_("Image _Properties"));
298     gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
299     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_image_image_properties), item);
300     gtk_widget_show(w);
301     gtk_menu_append(GTK_MENU(m), w);
304 static void
305 sp_image_image_properties(GtkMenuItem *menuitem, SPAnchor *anchor)
307     sp_object_attributes_dialog(SP_OBJECT(anchor), "Image");
310 /* SPShape */
312 static void
313 sp_shape_fill_settings(GtkMenuItem *menuitem, SPItem *item)
315     SPDesktop *desktop;
317     g_assert(SP_IS_ITEM(item));
319     desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop");
320     g_return_if_fail(desktop != NULL);
322     if (sp_desktop_selection(desktop)->isEmpty()) {
323         sp_desktop_selection(desktop)->set(item);
324     }
326     sp_object_properties_dialog();
329 static void
330 sp_shape_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m)
332     SPItem *item;
333     GtkWidget *w;
335     item = (SPItem *) object;
337     /* Item dialog */
338     w = gtk_menu_item_new_with_mnemonic(_("_Fill and Stroke"));
339     gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
340     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_shape_fill_settings), item);
341     gtk_widget_show(w);
342     gtk_menu_append(GTK_MENU(m), w);
346 /*
347   Local Variables:
348   mode:c++
349   c-file-style:"stroustrup"
350   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
351   indent-tabs-mode:nil
352   fill-column:99
353   End:
354 */
355 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :