1 #define __SP_OBJECT_UI_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 "object-ui.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_DT_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);
122 }
124 static void
125 sp_item_properties(GtkMenuItem *menuitem, SPItem *item)
126 {
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_DT_SELECTION(desktop)->set(item);
136 sp_item_dialog();
137 }
139 static void
140 sp_item_select_this(GtkMenuItem *menuitem, SPItem *item)
141 {
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_DT_SELECTION(desktop)->set(item);
150 }
152 static void
153 sp_item_create_link(GtkMenuItem *menuitem, SPItem *item)
154 {
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));
173 sp_object_attributes_dialog(object, "SPAnchor");
175 SP_DT_SELECTION(desktop)->set(SP_ITEM(object));
176 }
178 /* SPGroup */
180 static void sp_item_group_ungroup_activate(GtkMenuItem *menuitem, SPGroup *group);
182 static void
183 sp_group_menu(SPObject *object, SPDesktop *desktop, GtkMenu *menu)
184 {
185 SPItem *item=SP_ITEM(object);
186 GtkWidget *w;
188 /* "Ungroup" */
189 w = gtk_menu_item_new_with_mnemonic(_("_Ungroup"));
190 gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
191 gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_item_group_ungroup_activate), item);
192 gtk_widget_show(w);
193 gtk_menu_append(GTK_MENU(menu), w);
194 }
196 static void
197 sp_item_group_ungroup_activate(GtkMenuItem *menuitem, SPGroup *group)
198 {
199 SPDesktop *desktop;
200 GSList *children;
202 g_assert(SP_IS_GROUP(group));
204 desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop");
205 g_return_if_fail(desktop != NULL);
207 children = NULL;
208 sp_item_group_ungroup(group, &children);
210 SP_DT_SELECTION(desktop)->setList(children);
211 g_slist_free(children);
212 }
214 /* SPAnchor */
216 static void sp_anchor_link_properties(GtkMenuItem *menuitem, SPAnchor *anchor);
217 static void sp_anchor_link_follow(GtkMenuItem *menuitem, SPAnchor *anchor);
218 static void sp_anchor_link_remove(GtkMenuItem *menuitem, SPAnchor *anchor);
220 static void
221 sp_anchor_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m)
222 {
223 SPItem *item;
224 GtkWidget *w;
226 item = (SPItem *) object;
228 /* Link dialog */
229 w = gtk_menu_item_new_with_mnemonic(_("Link _Properties"));
230 gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
231 gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_anchor_link_properties), item);
232 gtk_widget_show(w);
233 gtk_menu_append(GTK_MENU(m), w);
234 /* Separator */
235 w = gtk_menu_item_new();
236 gtk_widget_show(w);
237 gtk_menu_append(GTK_MENU(m), w);
238 /* Select item */
239 w = gtk_menu_item_new_with_mnemonic(_("_Follow Link"));
240 gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_anchor_link_follow), item);
241 gtk_widget_show(w);
242 gtk_menu_append(GTK_MENU(m), w);
243 /* Reset transformations */
244 w = gtk_menu_item_new_with_mnemonic(_("_Remove Link"));
245 gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
246 gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_anchor_link_remove), item);
247 gtk_widget_show(w);
248 gtk_menu_append(GTK_MENU(m), w);
249 }
251 static void
252 sp_anchor_link_properties(GtkMenuItem *menuitem, SPAnchor *anchor)
253 {
254 sp_object_attributes_dialog(SP_OBJECT(anchor), "Link");
255 }
257 static void
258 sp_anchor_link_follow(GtkMenuItem *menuitem, SPAnchor *anchor)
259 {
260 g_return_if_fail(anchor != NULL);
261 g_return_if_fail(SP_IS_ANCHOR(anchor));
263 /* shell out to an external browser here */
264 }
266 static void
267 sp_anchor_link_remove(GtkMenuItem *menuitem, SPAnchor *anchor)
268 {
269 GSList *children;
271 g_return_if_fail(anchor != NULL);
272 g_return_if_fail(SP_IS_ANCHOR(anchor));
274 children = NULL;
275 sp_item_group_ungroup(SP_GROUP(anchor), &children);
277 g_slist_free(children);
278 }
280 /* Image */
282 static void sp_image_image_properties(GtkMenuItem *menuitem, SPAnchor *anchor);
284 static void
285 sp_image_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m)
286 {
287 SPItem *item;
288 GtkWidget *w;
290 item = (SPItem *) object;
292 /* Link dialog */
293 w = gtk_menu_item_new_with_mnemonic(_("Image _Properties"));
294 gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
295 gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_image_image_properties), item);
296 gtk_widget_show(w);
297 gtk_menu_append(GTK_MENU(m), w);
298 }
300 static void
301 sp_image_image_properties(GtkMenuItem *menuitem, SPAnchor *anchor)
302 {
303 sp_object_attributes_dialog(SP_OBJECT(anchor), "Image");
304 }
306 /* SPShape */
308 static void
309 sp_shape_fill_settings(GtkMenuItem *menuitem, SPItem *item)
310 {
311 SPDesktop *desktop;
313 g_assert(SP_IS_ITEM(item));
315 desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop");
316 g_return_if_fail(desktop != NULL);
318 if (SP_DT_SELECTION(desktop)->isEmpty()) {
319 SP_DT_SELECTION(desktop)->set(item);
320 }
322 sp_object_properties_dialog();
323 }
325 static void
326 sp_shape_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m)
327 {
328 SPItem *item;
329 GtkWidget *w;
331 item = (SPItem *) object;
333 /* Item dialog */
334 w = gtk_menu_item_new_with_mnemonic(_("_Fill and Stroke"));
335 gtk_object_set_data(GTK_OBJECT(w), "desktop", desktop);
336 gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_shape_fill_settings), item);
337 gtk_widget_show(w);
338 gtk_menu_append(GTK_MENU(m), w);
339 }
342 /*
343 Local Variables:
344 mode:c++
345 c-file-style:"stroustrup"
346 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
347 indent-tabs-mode:nil
348 fill-column:99
349 End:
350 */
351 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :