Code

patch from Gustav Broberg: undo annotations and history dialog
[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"
19 static void sp_object_type_menu(GType type, SPObject *object, SPDesktop *desktop, GtkMenu *menu);
21 /* Append object-specific part to context menu */
23 void
24 sp_object_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu)
25 {
26     GObjectClass *klass;
27     klass = G_OBJECT_GET_CLASS(object);
28     while (G_TYPE_CHECK_CLASS_TYPE((klass), SP_TYPE_OBJECT)) {
29         GType type;
30         type = G_TYPE_FROM_CLASS(klass);
31         sp_object_type_menu(type, object, desktop, menu);
32         klass = (GObjectClass*)g_type_class_peek_parent(klass);
33     }
34 }
36 /* Implementation */
38 #include <gtk/gtkmenuitem.h>
40 #include <glibmm/i18n.h>
42 #include "sp-anchor.h"
43 #include "sp-image.h"
45 #include "document.h"
46 #include "desktop-handles.h"
47 #include "selection.h"
49 #include "dialogs/item-properties.h"
50 #include "dialogs/object-attributes.h"
51 #include "dialogs/object-properties.h"
53 #include "sp-path.h"
56 static void sp_item_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu);
57 static void sp_group_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu);
58 static void sp_anchor_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu);
59 static void sp_image_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu);
60 static void sp_shape_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu);
62 static void
63 sp_object_type_menu(GType type, SPObject *object, SPDesktop *desktop, GtkMenu *menu)
64 {
65     static GHashTable *t2m = NULL;
66     void (* handler)(SPObject *object, SPDesktop *desktop, GtkMenu *menu);
67     if (!t2m) {
68         t2m = g_hash_table_new(NULL, NULL);
69         g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_ITEM), (void*)sp_item_menu);
70         g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_GROUP), (void*)sp_group_menu);
71         g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_ANCHOR), (void*)sp_anchor_menu);
72         g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_IMAGE), (void*)sp_image_menu);
73         g_hash_table_insert(t2m, GUINT_TO_POINTER(SP_TYPE_SHAPE), (void*)sp_shape_menu);
74     }
75     handler = (void (*)(SPObject*, SPDesktop*, GtkMenu*))g_hash_table_lookup(t2m, GUINT_TO_POINTER(type));
76     if (handler) handler(object, desktop, menu);
77 }
79 /* SPItem */
81 static void sp_item_properties(GtkMenuItem *menuitem, SPItem *item);
82 static void sp_item_select_this(GtkMenuItem *menuitem, SPItem *item);
83 static void sp_item_create_link(GtkMenuItem *menuitem, SPItem *item);
85 /* Generate context menu item section */
87 static void
88 sp_item_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m)
89 {
90     SPItem *item;
91     GtkWidget *w;
93     item = (SPItem *) object;
95     /* Item dialog */
96     w = gtk_menu_item_new_with_mnemonic(_("Object _Properties"));
97     gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
98     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_item_properties), item);
99     gtk_widget_show(w);
100     gtk_menu_append(GTK_MENU(m), w);
101     /* Separator */
102     w = gtk_menu_item_new();
103     gtk_widget_show(w);
104     gtk_menu_append(GTK_MENU(m), w);
105     /* Select item */
106     w = gtk_menu_item_new_with_mnemonic(_("_Select This"));
107     if (sp_desktop_selection(desktop)->includes(item)) {
108         gtk_widget_set_sensitive(w, FALSE);
109     } else {
110         gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
111         gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_item_select_this), item);
112     }
113     gtk_widget_show(w);
114     gtk_menu_append(GTK_MENU(m), w);
115     /* Create link */
116     w = gtk_menu_item_new_with_mnemonic(_("_Create Link"));
117     gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
118     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_item_create_link), item);
119     gtk_widget_set_sensitive(w, !SP_IS_ANCHOR(item));
120     gtk_widget_show(w);
121     gtk_menu_append(GTK_MENU(m), w);
124 static void
125 sp_item_properties(GtkMenuItem *menuitem, SPItem *item)
127     SPDesktop *desktop;
129     g_assert(SP_IS_ITEM(item));
131     desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop");
132     g_return_if_fail(desktop != NULL);
134     sp_desktop_selection(desktop)->set(item);
136     sp_item_dialog();
139 static void
140 sp_item_select_this(GtkMenuItem *menuitem, SPItem *item)
142     SPDesktop *desktop;
144     g_assert(SP_IS_ITEM(item));
146     desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop");
147     g_return_if_fail(desktop != NULL);
149     sp_desktop_selection(desktop)->set(item);
152 static void
153 sp_item_create_link(GtkMenuItem *menuitem, SPItem *item)
155     g_assert(SP_IS_ITEM(item));
156     g_assert(!SP_IS_ANCHOR(item));
158     SPDesktop *desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop");
159     g_return_if_fail(desktop != NULL);
161     Inkscape::XML::Node *repr = sp_repr_new("svg:a");
162     SP_OBJECT_REPR(SP_OBJECT_PARENT(item))->addChild(repr, SP_OBJECT_REPR(item));
163     SPObject *object = SP_OBJECT_DOCUMENT(item)->getObjectByRepr(repr);
164     g_return_if_fail(SP_IS_ANCHOR(object));
166     const char *id = SP_OBJECT_REPR(item)->attribute("id");
167     Inkscape::XML::Node *child = SP_OBJECT_REPR(item)->duplicate();
168     SP_OBJECT(item)->deleteObject(false);
169     repr->addChild(child, NULL);
170     child->setAttribute("id", id);
171     sp_document_done(SP_OBJECT_DOCUMENT(object), SP_VERB_NONE, 
172                      /* TODO: annotate */ "context-menu.cpp:172");
174     sp_object_attributes_dialog(object, "SPAnchor");
176     sp_desktop_selection(desktop)->set(SP_ITEM(object));
179 /* SPGroup */
181 static void sp_item_group_ungroup_activate(GtkMenuItem *menuitem, SPGroup *group);
183 static void
184 sp_group_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu)
186     SPItem *item=SP_ITEM(object);
187     GtkWidget *w;
189     /* "Ungroup" */
190     w = gtk_menu_item_new_with_mnemonic(_("_Ungroup"));
191     gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
192     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_item_group_ungroup_activate), item);
193     gtk_widget_show(w);
194     gtk_menu_append(GTK_MENU(menu), w);
197 static void
198 sp_item_group_ungroup_activate(GtkMenuItem *menuitem, SPGroup *group)
200     SPDesktop *desktop;
201     GSList *children;
203     g_assert(SP_IS_GROUP(group));
205     desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop");
206     g_return_if_fail(desktop != NULL);
208     children = NULL;
209     sp_item_group_ungroup(group, &children);
211     sp_desktop_selection(desktop)->setList(children);
212     g_slist_free(children);
215 /* SPAnchor */
217 static void sp_anchor_link_properties(GtkMenuItem *menuitem, SPAnchor *anchor);
218 static void sp_anchor_link_follow(GtkMenuItem *menuitem, SPAnchor *anchor);
219 static void sp_anchor_link_remove(GtkMenuItem *menuitem, SPAnchor *anchor);
221 static void
222 sp_anchor_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m)
224     SPItem *item;
225     GtkWidget *w;
227     item = (SPItem *) object;
229     /* Link dialog */
230     w = gtk_menu_item_new_with_mnemonic(_("Link _Properties"));
231     gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
232     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_anchor_link_properties), item);
233     gtk_widget_show(w);
234     gtk_menu_append(GTK_MENU(m), w);
235     /* Separator */
236     w = gtk_menu_item_new();
237     gtk_widget_show(w);
238     gtk_menu_append(GTK_MENU(m), w);
239     /* Select item */
240     w = gtk_menu_item_new_with_mnemonic(_("_Follow Link"));
241     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_anchor_link_follow), item);
242     gtk_widget_show(w);
243     gtk_menu_append(GTK_MENU(m), w);
244     /* Reset transformations */
245     w = gtk_menu_item_new_with_mnemonic(_("_Remove Link"));
246     gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
247     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_anchor_link_remove), item);
248     gtk_widget_show(w);
249     gtk_menu_append(GTK_MENU(m), w);
252 static void
253 sp_anchor_link_properties(GtkMenuItem *menuitem, SPAnchor *anchor)
255     sp_object_attributes_dialog(SP_OBJECT(anchor), "Link");
258 static void
259 sp_anchor_link_follow(GtkMenuItem *menuitem, SPAnchor *anchor)
261     g_return_if_fail(anchor != NULL);
262     g_return_if_fail(SP_IS_ANCHOR(anchor));
264     /* shell out to an external browser here */
267 static void
268 sp_anchor_link_remove(GtkMenuItem *menuitem, SPAnchor *anchor)
270     GSList *children;
272     g_return_if_fail(anchor != NULL);
273     g_return_if_fail(SP_IS_ANCHOR(anchor));
275     children = NULL;
276     sp_item_group_ungroup(SP_GROUP(anchor), &children);
278     g_slist_free(children);
281 /* Image */
283 static void sp_image_image_properties(GtkMenuItem *menuitem, SPAnchor *anchor);
285 static void
286 sp_image_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m)
288     SPItem *item;
289     GtkWidget *w;
291     item = (SPItem *) object;
293     /* Link dialog */
294     w = gtk_menu_item_new_with_mnemonic(_("Image _Properties"));
295     gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
296     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_image_image_properties), item);
297     gtk_widget_show(w);
298     gtk_menu_append(GTK_MENU(m), w);
301 static void
302 sp_image_image_properties(GtkMenuItem *menuitem, SPAnchor *anchor)
304     sp_object_attributes_dialog(SP_OBJECT(anchor), "Image");
307 /* SPShape */
309 static void
310 sp_shape_fill_settings(GtkMenuItem *menuitem, SPItem *item)
312     SPDesktop *desktop;
314     g_assert(SP_IS_ITEM(item));
316     desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop");
317     g_return_if_fail(desktop != NULL);
319     if (sp_desktop_selection(desktop)->isEmpty()) {
320         sp_desktop_selection(desktop)->set(item);
321     }
323     sp_object_properties_dialog();
326 static void
327 sp_shape_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m)
329     SPItem *item;
330     GtkWidget *w;
332     item = (SPItem *) object;
334     /* Item dialog */
335     w = gtk_menu_item_new_with_mnemonic(_("_Fill and Stroke"));
336     gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
337     gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_shape_fill_settings), item);
338     gtk_widget_show(w);
339     gtk_menu_append(GTK_MENU(m), w);
343 /*
344   Local Variables:
345   mode:c++
346   c-file-style:"stroustrup"
347   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
348   indent-tabs-mode:nil
349   fill-column:99
350   End:
351 */
352 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :