1 #include "document-interface.h"
2 #include <string.h>
4 #include "verbs.h"
5 #include "helper/action.h" //sp_action_perform
7 #include "inkscape.h" //inkscape_find_desktop_by_dkey, activate desktops
9 #include "desktop-handles.h" //sp_desktop_document()
10 #include "xml/repr.h" //sp_repr_document_new
12 #include "sp-object.h"
14 #include "document.h" // sp_document_repr_doc
16 #include "desktop-style.h" //sp_desktop_get_style
18 #include "selection.h" //selection struct
19 #include "selection-chemistry.h"// lots of selection functions
21 #include "sp-ellipse.h"
23 #include "layer-fns.h" //LPOS_BELOW
25 #include "style.h" //style_write
27 #include "file.h" //IO
29 #include "extension/system.h" //IO
31 #include "extension/output.h" //IO
33 #include "print.h" //IO
35 #include "live_effects/parameter/text.h" //text
36 #include "display/canvas-text.h" //text
38 //#include "2geom/svg-path-parser.h" //get_node_coordinates
40 /****************************************************************************
41 HELPER / SHORTCUT FUNCTIONS
42 ****************************************************************************/
44 const gchar* intToCString(int i)
45 {
46 std::stringstream ss;
47 ss << i;
48 return ss.str().c_str();
49 }
51 Inkscape::XML::Node *
52 get_repr_by_name (SPDesktop *desk, gchar *name, GError **error)
53 {
54 /* ALTERNATIVE (is this faster if only repr is needed?)
55 Inkscape::XML::Node *node = sp_repr_lookup_name((doc->root)->repr, name);
56 */
57 Inkscape::XML::Node * node = sp_desktop_document(desk)->getObjectById(name)->repr;
58 if (!node)
59 {
60 g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OBJECT, "Object '%s' not found in document.", name);
61 return NULL;
62 }
63 return node;
64 }
66 SPObject *
67 get_object_by_name (SPDesktop *desk, gchar *name, GError **error)
68 {
69 SPObject * obj = sp_desktop_document(desk)->getObjectById(name);
70 if (!obj)
71 {
72 g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OBJECT, "Object '%s' not found in document.", name);
73 return NULL;
74 }
75 return obj;
76 }
78 gboolean
79 dbus_check_string (gchar *string, GError ** error, gchar * errorstr)
80 {
81 if (string == NULL)
82 {
83 g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OTHER, "%s", errorstr);
84 return FALSE;
85 }
86 return TRUE;
87 }
89 const gchar *
90 get_name_from_object (SPObject * obj)
91 {
92 return obj->repr->attribute("id");
93 }
95 void
96 desktop_ensure_active (SPDesktop* desk) {
97 if (desk != SP_ACTIVE_DESKTOP)
98 inkscape_activate_desktop (desk);
99 return;
100 }
102 gdouble
103 selection_get_center_x (Inkscape::Selection *sel){
104 NRRect *box = g_new(NRRect, 1);;
105 box = sel->boundsInDocument(box);
106 return box->x0 + ((box->x1 - box->x0)/2);
107 }
109 gdouble
110 selection_get_center_y (Inkscape::Selection *sel){
111 NRRect *box = g_new(NRRect, 1);;
112 box = sel->boundsInDocument(box);
113 return box->y0 + ((box->y1 - box->y0)/2);
114 }
115 //move_to etc
116 const GSList *
117 selection_swap(SPDesktop *desk, gchar *name, GError **error)
118 {
119 Inkscape::Selection *sel = sp_desktop_selection(desk);
120 const GSList *oldsel = g_slist_copy((GSList *)sel->list());
122 sel->set(get_object_by_name(desk, name, error));
123 return oldsel;
124 }
126 void
127 selection_restore(SPDesktop *desk, const GSList * oldsel)
128 {
129 Inkscape::Selection *sel = sp_desktop_selection(desk);
130 sel->setList(oldsel);
131 }
133 Inkscape::XML::Node *
134 dbus_create_node (SPDesktop *desk, gboolean isrect)
135 {
136 SPDocument * doc = sp_desktop_document (desk);
137 Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
138 gchar *type;
139 if (isrect)
140 type = (gchar *)"svg:rect";
141 else
142 type = (gchar *)"svg:path";
143 return xml_doc->createElement(type);
144 }
146 gchar *
147 finish_create_shape (DocumentInterface *object, GError **error, Inkscape::XML::Node *newNode, gchar *desc)
148 {
150 SPCSSAttr *style = sp_desktop_get_style(object->desk, TRUE);
152 if (style) {
153 newNode->setAttribute("style", sp_repr_css_write_string(style), TRUE);
154 }
155 else {
156 newNode->setAttribute("style", "fill:#0000ff;fill-opacity:1;stroke:#c900b9;stroke-width:0;stroke-miterlimit:0;stroke-opacity:1;stroke-dasharray:none", TRUE);
157 }
159 object->desk->currentLayer()->appendChildRepr(newNode);
160 object->desk->currentLayer()->updateRepr();
162 if (object->updates)
163 sp_document_done(sp_desktop_document(object->desk), 0, (gchar *)desc);
164 //else
165 //document_interface_pause_updates(object, error);
167 return strdup(newNode->attribute("id"));
168 }
170 gboolean
171 dbus_call_verb (DocumentInterface *object, int verbid, GError **error)
172 {
173 SPDesktop *desk2 = object->desk;
174 desktop_ensure_active (desk2);
176 if ( desk2 ) {
177 Inkscape::Verb *verb = Inkscape::Verb::get( verbid );
178 if ( verb ) {
179 SPAction *action = verb->get_action(desk2);
180 if ( action ) {
181 //if (!object->updates)
182 //document_interface_pause_updates (object, error);
183 sp_action_perform( action, NULL );
184 if (object->updates)
185 sp_document_done(sp_desktop_document(desk2), verb->get_code(), g_strdup(verb->get_tip()));
186 //if (!object->updates)
187 //document_interface_pause_updates (object, error);
188 return TRUE;
189 }
190 }
191 }
192 g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_VERB, "Verb failed to execute");
193 return FALSE;
194 }
196 /****************************************************************************
197 DOCUMENT INTERFACE CLASS STUFF
198 ****************************************************************************/
200 G_DEFINE_TYPE(DocumentInterface, document_interface, G_TYPE_OBJECT)
202 static void
203 document_interface_finalize (GObject *object)
204 {
205 G_OBJECT_CLASS (document_interface_parent_class)->finalize (object);
206 }
209 static void
210 document_interface_class_init (DocumentInterfaceClass *klass)
211 {
212 GObjectClass *object_class;
213 object_class = G_OBJECT_CLASS (klass);
214 object_class->finalize = document_interface_finalize;
215 }
217 static void
218 document_interface_init (DocumentInterface *object)
219 {
220 object->desk = NULL;
221 }
224 DocumentInterface *
225 document_interface_new (void)
226 {
227 return (DocumentInterface*)g_object_new (TYPE_DOCUMENT_INTERFACE, NULL);
228 }
230 GQuark
231 inkscape_error_quark (void)
232 {
233 static GQuark quark = 0;
234 if (!quark)
235 quark = g_quark_from_static_string ("inkscape_error");
237 return quark;
238 }
240 /* This should really be standard. */
241 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
243 GType
244 inkscape_error_get_type (void)
245 {
246 static GType etype = 0;
248 if (etype == 0)
249 {
250 static const GEnumValue values[] =
251 {
253 ENUM_ENTRY (INKSCAPE_ERROR_SELECTION, "Incompatible_Selection"),
254 ENUM_ENTRY (INKSCAPE_ERROR_OBJECT, "Incompatible_Object"),
255 ENUM_ENTRY (INKSCAPE_ERROR_VERB, "Failed_Verb"),
256 ENUM_ENTRY (INKSCAPE_ERROR_OTHER, "Generic_Error"),
257 { 0, 0, 0 }
258 };
260 etype = g_enum_register_static ("InkscapeError", values);
261 }
263 return etype;
264 }
266 /****************************************************************************
267 MISC FUNCTIONS
268 ****************************************************************************/
270 gboolean
271 document_interface_delete_all (DocumentInterface *object, GError **error)
272 {
273 sp_edit_clear_all (object->desk);
274 return TRUE;
275 }
277 gboolean
278 document_interface_call_verb (DocumentInterface *object, gchar *verbid, GError **error)
279 {
280 SPDesktop *desk2 = object->desk;
281 desktop_ensure_active (object->desk);
282 if ( desk2 ) {
283 Inkscape::Verb *verb = Inkscape::Verb::getbyid( verbid );
284 if ( verb ) {
285 SPAction *action = verb->get_action(desk2);
286 if ( action ) {
287 sp_action_perform( action, NULL );
288 if (object->updates) {
289 sp_document_done(sp_desktop_document(desk2), verb->get_code(), g_strdup(verb->get_tip()));
290 }
291 }
292 }
293 }
294 g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_VERB, "Verb '%s' failed to execute or was not found.", verbid);
295 return FALSE;
296 }
299 /****************************************************************************
300 CREATION FUNCTIONS
301 ****************************************************************************/
303 gchar*
304 document_interface_rectangle (DocumentInterface *object, int x, int y,
305 int width, int height, GError **error)
306 {
309 Inkscape::XML::Node *newNode = dbus_create_node(object->desk, TRUE);
310 sp_repr_set_int(newNode, "x", x); //could also use newNode->setAttribute()
311 sp_repr_set_int(newNode, "y", y);
312 sp_repr_set_int(newNode, "width", width);
313 sp_repr_set_int(newNode, "height", height);
314 return finish_create_shape (object, error, newNode, (gchar *)"create rectangle");
315 }
317 gchar*
318 document_interface_ellipse_center (DocumentInterface *object, int cx, int cy,
319 int rx, int ry, GError **error)
320 {
321 Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE);
322 newNode->setAttribute("sodipodi:type", "arc");
323 sp_repr_set_int(newNode, "sodipodi:cx", cx);
324 sp_repr_set_int(newNode, "sodipodi:cy", cy);
325 sp_repr_set_int(newNode, "sodipodi:rx", rx);
326 sp_repr_set_int(newNode, "sodipodi:ry", ry);
327 return finish_create_shape (object, error, newNode, (gchar *)"create circle");
328 }
330 gchar*
331 document_interface_polygon (DocumentInterface *object, int cx, int cy,
332 int radius, int rotation, int sides,
333 GError **error)
334 {
335 gdouble rot = ((rotation / 180.0) * 3.14159265) - ( 3.14159265 / 2.0);
336 Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE);
337 newNode->setAttribute("inkscape:flatsided", "true");
338 newNode->setAttribute("sodipodi:type", "star");
339 sp_repr_set_int(newNode, "sodipodi:cx", cx);
340 sp_repr_set_int(newNode, "sodipodi:cy", cy);
341 sp_repr_set_int(newNode, "sodipodi:r1", radius);
342 sp_repr_set_int(newNode, "sodipodi:r2", radius);
343 sp_repr_set_int(newNode, "sodipodi:sides", sides);
344 sp_repr_set_int(newNode, "inkscape:randomized", 0);
345 sp_repr_set_svg_double(newNode, "sodipodi:arg1", rot);
346 sp_repr_set_svg_double(newNode, "sodipodi:arg2", rot);
347 sp_repr_set_svg_double(newNode, "inkscape:rounded", 0);
349 return finish_create_shape (object, error, newNode, (gchar *)"create polygon");
350 }
352 gchar*
353 document_interface_star (DocumentInterface *object, int cx, int cy,
354 int r1, int r2, int sides, gdouble rounded,
355 gdouble arg1, gdouble arg2, GError **error)
356 {
357 Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE);
358 newNode->setAttribute("inkscape:flatsided", "false");
359 newNode->setAttribute("sodipodi:type", "star");
360 sp_repr_set_int(newNode, "sodipodi:cx", cx);
361 sp_repr_set_int(newNode, "sodipodi:cy", cy);
362 sp_repr_set_int(newNode, "sodipodi:r1", r1);
363 sp_repr_set_int(newNode, "sodipodi:r2", r2);
364 sp_repr_set_int(newNode, "sodipodi:sides", sides);
365 sp_repr_set_int(newNode, "inkscape:randomized", 0);
366 sp_repr_set_svg_double(newNode, "sodipodi:arg1", arg1);
367 sp_repr_set_svg_double(newNode, "sodipodi:arg2", arg2);
368 sp_repr_set_svg_double(newNode, "inkscape:rounded", rounded);
370 return finish_create_shape (object, error, newNode, (gchar *)"create star");
371 }
373 gchar*
374 document_interface_ellipse (DocumentInterface *object, int x, int y,
375 int width, int height, GError **error)
376 {
377 int rx = width/2;
378 int ry = height/2;
379 return document_interface_ellipse_center (object, x+rx, y+ry, rx, ry, error);
380 }
382 gchar*
383 document_interface_line (DocumentInterface *object, int x, int y,
384 int x2, int y2, GError **error)
385 {
386 Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE);
387 std::stringstream out;
388 printf("X2: %d\nY2 %d\n", x2, y2);
389 out << "m " << x << "," << y << " " << x2 << "," << y2;
390 printf ("PATH: %s\n", out.str().c_str());
391 newNode->setAttribute("d", out.str().c_str());
392 return finish_create_shape (object, error, newNode, (gchar *)"create line");
393 }
395 gchar*
396 document_interface_spiral (DocumentInterface *object, int cx, int cy,
397 int r, int revolutions, GError **error)
398 {
399 Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE);
400 newNode->setAttribute("sodipodi:type", "spiral");
401 sp_repr_set_int(newNode, "sodipodi:cx", cx);
402 sp_repr_set_int(newNode, "sodipodi:cy", cy);
403 sp_repr_set_int(newNode, "sodipodi:radius", r);
404 sp_repr_set_int(newNode, "sodipodi:revolution", revolutions);
405 sp_repr_set_int(newNode, "sodipodi:t0", 0);
406 sp_repr_set_int(newNode, "sodipodi:argument", 0);
407 sp_repr_set_int(newNode, "sodipodi:expansion", 1);
408 gchar * retval = finish_create_shape (object, error, newNode, (gchar *)"create spiral");
409 newNode->setAttribute("style", "fill:none");
410 return retval;
411 }
413 gboolean
414 document_interface_text (DocumentInterface *object, int x, int y, gchar *text, GError **error)
415 {
416 //FIXME: Not selectable.
418 SPDesktop *desktop = object->desk;
419 SPCanvasText * canvas_text = (SPCanvasText *) sp_canvastext_new(sp_desktop_tempgroup(desktop), desktop, Geom::Point(0,0), "");
420 sp_canvastext_set_text (canvas_text, text);
421 sp_canvastext_set_coords (canvas_text, x, y);
423 return TRUE;
424 }
426 gchar*
427 document_interface_node (DocumentInterface *object, gchar *type, GError **error)
428 {
429 SPDocument * doc = sp_desktop_document (object->desk);
430 Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
432 Inkscape::XML::Node *newNode = xml_doc->createElement(type);
434 object->desk->currentLayer()->appendChildRepr(newNode);
435 object->desk->currentLayer()->updateRepr();
437 if (object->updates)
438 sp_document_done(sp_desktop_document(object->desk), 0, (gchar *)"created empty node");
439 //else
440 //document_interface_pause_updates(object, error);
442 return strdup(newNode->attribute("id"));
443 }
445 /****************************************************************************
446 ENVIORNMENT FUNCTIONS
447 ****************************************************************************/
448 gdouble
449 document_interface_document_get_width (DocumentInterface *object)
450 {
451 return sp_document_width(sp_desktop_document(object->desk));
452 }
454 gdouble
455 document_interface_document_get_height (DocumentInterface *object)
456 {
457 return sp_document_height(sp_desktop_document(object->desk));
458 }
460 gchar *
461 document_interface_document_get_css (DocumentInterface *object, GError **error)
462 {
463 SPCSSAttr *current = (object->desk)->current;
464 return sp_repr_css_write_string(current);
465 }
467 gboolean
468 document_interface_document_merge_css (DocumentInterface *object,
469 gchar *stylestring, GError **error)
470 {
471 SPCSSAttr * style = sp_repr_css_attr_new();
472 sp_repr_css_attr_add_from_string (style, stylestring);
473 sp_desktop_set_style (object->desk, style);
474 return TRUE;
475 }
477 gboolean
478 document_interface_document_set_css (DocumentInterface *object,
479 gchar *stylestring, GError **error)
480 {
481 SPCSSAttr * style = sp_repr_css_attr_new();
482 sp_repr_css_attr_add_from_string (style, stylestring);
483 //Memory leak?
484 object->desk->current = style;
485 return TRUE;
486 }
488 gboolean
489 document_interface_document_resize_to_fit_selection (DocumentInterface *object,
490 GError **error)
491 {
492 return dbus_call_verb (object, SP_VERB_FIT_CANVAS_TO_SELECTION, error);
493 return TRUE;
494 }
496 /****************************************************************************
497 OBJECT FUNCTIONS
498 ****************************************************************************/
500 gboolean
501 document_interface_set_attribute (DocumentInterface *object, char *shape,
502 char *attribute, char *newval, GError **error)
503 {
504 Inkscape::XML::Node *newNode = get_repr_by_name(object->desk, shape, error);
506 /* ALTERNATIVE (is this faster?)
507 Inkscape::XML::Node *newnode = sp_repr_lookup_name((doc->root)->repr, name);
508 */
509 if (!dbus_check_string(newval, error, "New value string was empty."))
510 return FALSE;
512 if (!newNode)
513 return FALSE;
515 newNode->setAttribute(attribute, newval, TRUE);
516 return TRUE;
517 }
519 gboolean
520 document_interface_set_int_attribute (DocumentInterface *object,
521 char *shape, char *attribute,
522 int newval, GError **error)
523 {
524 Inkscape::XML::Node *newNode = get_repr_by_name (object->desk, shape, error);
525 if (!newNode)
526 return FALSE;
528 sp_repr_set_int (newNode, attribute, newval);
529 return TRUE;
530 }
533 gboolean
534 document_interface_set_double_attribute (DocumentInterface *object,
535 char *shape, char *attribute,
536 double newval, GError **error)
537 {
538 Inkscape::XML::Node *newNode = get_repr_by_name (object->desk, shape, error);
540 if (!dbus_check_string (attribute, error, "New value string was empty."))
541 return FALSE;
542 if (!newNode)
543 return FALSE;
545 sp_repr_set_svg_double (newNode, attribute, newval);
546 return TRUE;
547 }
549 gchar *
550 document_interface_get_attribute (DocumentInterface *object, char *shape,
551 char *attribute, GError **error)
552 {
553 Inkscape::XML::Node *newNode = get_repr_by_name(object->desk, shape, error);
555 if (!dbus_check_string (attribute, error, "Attribute name empty."))
556 return NULL;
557 if (!newNode)
558 return NULL;
560 return g_strdup(newNode->attribute(attribute));
561 }
563 gboolean
564 document_interface_move (DocumentInterface *object, gchar *name, gdouble x,
565 gdouble y, GError **error)
566 {
567 const GSList *oldsel = selection_swap(object->desk, name, error);
568 if (!oldsel)
569 return FALSE;
570 sp_selection_move (object->desk, x, 0 - y);
571 selection_restore(object->desk, oldsel);
572 return TRUE;
573 }
575 gboolean
576 document_interface_move_to (DocumentInterface *object, gchar *name, gdouble x,
577 gdouble y, GError **error)
578 {
579 const GSList *oldsel = selection_swap(object->desk, name, error);
580 if (!oldsel)
581 return FALSE;
582 Inkscape::Selection * sel = sp_desktop_selection(object->desk);
583 sp_selection_move (object->desk, x - selection_get_center_x(sel),
584 0 - (y - selection_get_center_y(sel)));
585 selection_restore(object->desk, oldsel);
586 return TRUE;
587 }
589 gboolean
590 document_interface_object_to_path (DocumentInterface *object,
591 char *shape, GError **error)
592 {
593 const GSList *oldsel = selection_swap(object->desk, shape, error);
594 if (!oldsel)
595 return FALSE;
596 dbus_call_verb (object, SP_VERB_OBJECT_TO_CURVE, error);
597 selection_restore(object->desk, oldsel);
598 return TRUE;
599 }
601 gchar *
602 document_interface_get_path (DocumentInterface *object, char *pathname, GError **error)
603 {
604 Inkscape::XML::Node *node = get_repr_by_name(object->desk, pathname, error);
606 if (!node)
607 return NULL;
609 if (node->attribute("d") == NULL)
610 {
611 g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OBJECT, "Object is not a path.");
612 return NULL;
613 }
614 return strdup(node->attribute("d"));
615 }
617 gboolean
618 document_interface_transform (DocumentInterface *object, gchar *shape,
619 gchar *transformstr, GError **error)
620 {
621 //FIXME: This should merge transformations.
622 gchar trans[] = "transform";
623 document_interface_set_attribute (object, shape, trans, transformstr, error);
624 return TRUE;
625 }
627 gchar *
628 document_interface_get_css (DocumentInterface *object, gchar *shape,
629 GError **error)
630 {
631 gchar style[] = "style";
632 return document_interface_get_attribute (object, shape, style, error);
633 }
635 gboolean
636 document_interface_modify_css (DocumentInterface *object, gchar *shape,
637 gchar *cssattrb, gchar *newval, GError **error)
638 {
639 // Doesn't like non-variable strings for some reason.
640 gchar style[] = "style";
641 Inkscape::XML::Node *node = get_repr_by_name(object->desk, shape, error);
643 if (!dbus_check_string (cssattrb, error, "Attribute string empty."))
644 return FALSE;
645 if (!node)
646 return FALSE;
648 SPCSSAttr * oldstyle = sp_repr_css_attr (node, style);
649 sp_repr_css_set_property(oldstyle, cssattrb, newval);
650 node->setAttribute (style, sp_repr_css_write_string (oldstyle), TRUE);
651 return TRUE;
652 }
654 gboolean
655 document_interface_merge_css (DocumentInterface *object, gchar *shape,
656 gchar *stylestring, GError **error)
657 {
658 gchar style[] = "style";
660 Inkscape::XML::Node *node = get_repr_by_name(object->desk, shape, error);
662 if (!dbus_check_string (stylestring, error, "Style string empty."))
663 return FALSE;
664 if (!node)
665 return FALSE;
667 SPCSSAttr * newstyle = sp_repr_css_attr_new();
668 sp_repr_css_attr_add_from_string (newstyle, stylestring);
670 SPCSSAttr * oldstyle = sp_repr_css_attr (node, style);
672 sp_repr_css_merge(oldstyle, newstyle);
673 node->setAttribute (style, sp_repr_css_write_string (oldstyle), TRUE);
674 return TRUE;
675 }
677 gboolean
678 document_interface_move_to_layer (DocumentInterface *object, gchar *shape,
679 gchar *layerstr, GError **error)
680 {
681 const GSList *oldsel = selection_swap(object->desk, shape, error);
682 if (!oldsel)
683 return FALSE;
685 document_interface_selection_move_to_layer(object, layerstr, error);
686 selection_restore(object->desk, oldsel);
687 return TRUE;
688 }
690 GArray *
691 document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape)
692 {
693 //FIXME: Needs lot's of work.
694 /*
695 Inkscape::XML::Node *shapenode = get_repr_by_name (object->desk, shape, error);
696 if (shapenode == NULL || shapenode->attribute("d") == NULL) {
697 return FALSE;
698 }
699 char * path = strdup(shapenode->attribute("d"));
700 printf("PATH: %s\n", path);
702 Geom::parse_svg_path (path);
703 return NULL;
704 */
705 return NULL;
706 }
709 /****************************************************************************
710 FILE I/O FUNCTIONS
711 ****************************************************************************/
713 gboolean
714 document_interface_save (DocumentInterface *object, GError **error)
715 {
716 SPDocument * doc = sp_desktop_document(object->desk);
717 printf("1: %s\n2: %s\n3: %s\n", doc->uri, doc->base, doc->name);
718 if (doc->uri)
719 return document_interface_save_as (object, doc->uri, error);
720 return FALSE;
721 }
723 gboolean
724 document_interface_load (DocumentInterface *object,
725 gchar *filename, GError **error)
726 {
727 desktop_ensure_active (object->desk);
728 const Glib::ustring file(filename);
729 sp_file_open(file, NULL, TRUE, TRUE);
730 if (object->updates)
731 sp_document_done(sp_desktop_document(object->desk), SP_VERB_FILE_OPEN, "Opened File");
732 return TRUE;
733 }
735 gboolean
736 document_interface_save_as (DocumentInterface *object,
737 gchar *filename, GError **error)
738 {
739 SPDocument * doc = sp_desktop_document(object->desk);
740 #ifdef WITH_GNOME_VFS
741 const Glib::ustring file(filename);
742 return file_save_remote(doc, file, NULL, TRUE, TRUE);
743 #endif
744 if (!doc || strlen(filename)<1) //Safety check
745 return false;
747 try {
748 Inkscape::Extension::save(NULL, doc, filename,
749 false, false, true);
750 } catch (...) {
751 //SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved."));
752 return false;
753 }
755 //SP_ACTIVE_DESKTOP->event_log->rememberFileSave();
756 //SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::NORMAL_MESSAGE, "Document saved.");
757 return true;
758 }
760 gboolean
761 document_interface_mark_as_unmodified (DocumentInterface *object, GError **error)
762 {
763 SPDocument * doc = sp_desktop_document(object->desk);
764 if (doc)
765 doc->modified_since_save = FALSE;
766 return TRUE;
767 }
769 /*
770 gboolean
771 document_interface_print_to_file (DocumentInterface *object, GError **error)
772 {
773 SPDocument * doc = sp_desktop_document(object->desk);
774 sp_print_document_to_file (doc, g_strdup("/home/soren/test.pdf"));
776 return TRUE;
777 }
778 */
779 /****************************************************************************
780 PROGRAM CONTROL FUNCTIONS
781 ****************************************************************************/
783 gboolean
784 document_interface_close (DocumentInterface *object, GError **error)
785 {
786 return dbus_call_verb (object, SP_VERB_FILE_CLOSE_VIEW, error);
787 }
789 gboolean
790 document_interface_exit (DocumentInterface *object, GError **error)
791 {
792 return dbus_call_verb (object, SP_VERB_FILE_QUIT, error);
793 }
795 gboolean
796 document_interface_undo (DocumentInterface *object, GError **error)
797 {
798 return dbus_call_verb (object, SP_VERB_EDIT_UNDO, error);
799 }
801 gboolean
802 document_interface_redo (DocumentInterface *object, GError **error)
803 {
804 return dbus_call_verb (object, SP_VERB_EDIT_REDO, error);
805 }
809 /****************************************************************************
810 UPDATE FUNCTIONS
811 FIXME: This would work better by adding a flag to SPDesktop to prevent
812 updating but that would be very intrusive so for now there is a workaround.
813 Need to make sure it plays well with verbs because they are used so much.
814 ****************************************************************************/
816 void
817 document_interface_pause_updates (DocumentInterface *object, GError **error)
818 {
819 object->updates = FALSE;
820 object->desk->canvas->drawing_disabled = 1;
821 //object->desk->canvas->need_redraw = 0;
822 //object->desk->canvas->need_repick = 0;
823 //sp_desktop_document(object->desk)->root->uflags = FALSE;
824 //sp_desktop_document(object->desk)->root->mflags = FALSE;
825 }
827 void
828 document_interface_resume_updates (DocumentInterface *object, GError **error)
829 {
830 object->updates = TRUE;
831 object->desk->canvas->drawing_disabled = 0;
832 //object->desk->canvas->need_redraw = 1;
833 //object->desk->canvas->need_repick = 1;
834 //sp_desktop_document(object->desk)->root->uflags = TRUE;
835 //sp_desktop_document(object->desk)->root->mflags = TRUE;
836 //sp_desktop_document(object->desk)->_updateDocument();
837 //FIXME: use better verb than rect.
838 sp_document_done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions");
839 }
841 void
842 document_interface_update (DocumentInterface *object, GError **error)
843 {
844 sp_desktop_document(object->desk)->root->uflags = TRUE;
845 sp_desktop_document(object->desk)->root->mflags = TRUE;
846 object->desk->enableInteraction();
847 sp_desktop_document(object->desk)->_updateDocument();
848 object->desk->disableInteraction();
849 sp_desktop_document(object->desk)->root->uflags = FALSE;
850 sp_desktop_document(object->desk)->root->mflags = FALSE;
851 //sp_document_done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions");
852 }
854 /****************************************************************************
855 SELECTION FUNCTIONS FIXME: use call_verb where appropriate (once update system is tested.)
856 ****************************************************************************/
858 gboolean
859 document_interface_selection_get (DocumentInterface *object, char ***out, GError **error)
860 {
861 Inkscape::Selection * sel = sp_desktop_selection(object->desk);
862 GSList const *oldsel = sel->list();
864 int size = g_slist_length((GSList *) oldsel);
866 *out = g_new0 (char *, size + 1);
868 int i = 0;
869 for (GSList const *iter = oldsel; iter != NULL; iter = iter->next) {
870 (*out)[i] = g_strdup(SP_OBJECT(iter->data)->repr->attribute("id"));
871 i++;
872 }
873 (*out)[i] = NULL;
875 return TRUE;
876 }
878 gboolean
879 document_interface_selection_add (DocumentInterface *object, char *name, GError **error)
880 {
881 SPObject * obj = get_object_by_name(object->desk, name, error);
882 if (!obj)
883 return FALSE;
885 Inkscape::Selection *selection = sp_desktop_selection(object->desk);
887 selection->add(obj);
888 return TRUE;
889 }
891 gboolean
892 document_interface_selection_add_list (DocumentInterface *object,
893 char **names, GError **error)
894 {
895 int i;
896 for (i=0;names[i] != NULL;i++) {
897 document_interface_selection_add(object, names[i], error);
898 }
899 return TRUE;
900 }
902 gboolean
903 document_interface_selection_set (DocumentInterface *object, char *name, GError **error)
904 {
905 SPDocument * doc = sp_desktop_document (object->desk);
906 Inkscape::Selection *selection = sp_desktop_selection(object->desk);
907 selection->set(doc->getObjectById(name));
908 return TRUE;
909 }
911 gboolean
912 document_interface_selection_set_list (DocumentInterface *object,
913 gchar **names, GError **error)
914 {
915 sp_desktop_selection(object->desk)->clear();
916 int i;
917 for (i=0;names[i] != NULL;i++) {
918 document_interface_selection_add(object, names[i], error);
919 }
920 return TRUE;
921 }
923 gboolean
924 document_interface_selection_rotate (DocumentInterface *object, int angle, GError **error)
925 {
926 Inkscape::Selection *selection = sp_desktop_selection(object->desk);
927 sp_selection_rotate(selection, angle);
928 return TRUE;
929 }
931 gboolean
932 document_interface_selection_delete (DocumentInterface *object, GError **error)
933 {
934 //sp_selection_delete (object->desk);
935 return dbus_call_verb (object, SP_VERB_EDIT_DELETE, error);
936 }
938 gboolean
939 document_interface_selection_clear (DocumentInterface *object, GError **error)
940 {
941 sp_desktop_selection(object->desk)->clear();
942 return TRUE;
943 }
945 gboolean
946 document_interface_select_all (DocumentInterface *object, GError **error)
947 {
948 //sp_edit_select_all (object->desk);
949 return dbus_call_verb (object, SP_VERB_EDIT_SELECT_ALL, error);
950 }
952 gboolean
953 document_interface_select_all_in_all_layers(DocumentInterface *object,
954 GError **error)
955 {
956 //sp_edit_select_all_in_all_layers (object->desk);
957 return dbus_call_verb (object, SP_VERB_EDIT_SELECT_ALL_IN_ALL_LAYERS, error);
958 }
960 gboolean
961 document_interface_selection_box (DocumentInterface *object, int x, int y,
962 int x2, int y2, gboolean replace,
963 GError **error)
964 {
965 //FIXME: implement.
966 return FALSE;
967 }
969 gboolean
970 document_interface_selection_invert (DocumentInterface *object, GError **error)
971 {
972 //sp_edit_invert (object->desk);
973 return dbus_call_verb (object, SP_VERB_EDIT_INVERT, error);
974 }
976 gboolean
977 document_interface_selection_group (DocumentInterface *object, GError **error)
978 {
979 //sp_selection_group (object->desk);
980 return dbus_call_verb (object, SP_VERB_SELECTION_GROUP, error);
981 }
982 gboolean
983 document_interface_selection_ungroup (DocumentInterface *object, GError **error)
984 {
985 //sp_selection_ungroup (object->desk);
986 return dbus_call_verb (object, SP_VERB_SELECTION_UNGROUP, error);
987 }
989 gboolean
990 document_interface_selection_cut (DocumentInterface *object, GError **error)
991 {
992 //desktop_ensure_active (object->desk);
993 //sp_selection_cut (object->desk);
994 return dbus_call_verb (object, SP_VERB_EDIT_CUT, error);
995 }
997 gboolean
998 document_interface_selection_copy (DocumentInterface *object, GError **error)
999 {
1000 //desktop_ensure_active (object->desk);
1001 //sp_selection_copy ();
1002 return dbus_call_verb (object, SP_VERB_EDIT_COPY, error);
1003 }
1004 /*
1005 gboolean
1006 document_interface_selection_paste (DocumentInterface *object, GError **error)
1007 {
1008 desktop_ensure_active (object->desk);
1009 if (!object->updates)
1010 document_interface_pause_updates (object, error);
1011 sp_selection_paste (object->desk, TRUE);
1012 if (!object->updates)
1013 document_interface_pause_updates (object, error);
1014 return TRUE;
1015 //return dbus_call_verb (object, SP_VERB_EDIT_PASTE, error);
1016 }
1017 */
1018 gboolean
1019 document_interface_selection_paste (DocumentInterface *object, GError **error)
1020 {
1021 return dbus_call_verb (object, SP_VERB_EDIT_PASTE, error);
1022 }
1024 gboolean
1025 document_interface_selection_scale (DocumentInterface *object, gdouble grow, GError **error)
1026 {
1027 Inkscape::Selection *selection = sp_desktop_selection(object->desk);
1028 if (!selection)
1029 {
1030 return FALSE;
1031 }
1032 sp_selection_scale (selection, grow);
1033 return TRUE;
1034 }
1036 gboolean
1037 document_interface_selection_move (DocumentInterface *object, gdouble x, gdouble y, GError **error)
1038 {
1039 sp_selection_move (object->desk, x, 0 - y); //switching coordinate systems.
1040 return TRUE;
1041 }
1043 gboolean
1044 document_interface_selection_move_to (DocumentInterface *object, gdouble x, gdouble y, GError **error)
1045 {
1046 Inkscape::Selection * sel = sp_desktop_selection(object->desk);
1048 Geom::OptRect sel_bbox = sel->bounds();
1049 if (sel_bbox) {
1050 Geom::Point m( x - selection_get_center_x(sel) , 0 - (y - selection_get_center_y(sel)) );
1051 sp_selection_move_relative(sel, m, true);
1052 }
1053 return TRUE;
1054 }
1056 //FIXME: does not paste in new layer.
1057 gboolean
1058 document_interface_selection_move_to_layer (DocumentInterface *object,
1059 gchar *layerstr, GError **error)
1060 {
1061 SPDesktop * dt = object->desk;
1063 Inkscape::Selection *selection = sp_desktop_selection(dt);
1065 // check if something is selected
1066 if (selection->isEmpty())
1067 return FALSE;
1069 SPObject *next = get_object_by_name(object->desk, layerstr, error);
1071 if (!next)
1072 return FALSE;
1074 if (strcmp("layer", (next->repr)->attribute("inkscape:groupmode")) == 0) {
1076 sp_selection_cut(dt);
1078 dt->setCurrentLayer(next);
1080 sp_selection_paste(dt, TRUE);
1081 }
1082 return TRUE;
1083 }
1085 GArray *
1086 document_interface_selection_get_center (DocumentInterface *object)
1087 {
1088 Inkscape::Selection * sel = sp_desktop_selection(object->desk);
1090 if (sel)
1091 {
1092 gdouble x = selection_get_center_x(sel);
1093 gdouble y = selection_get_center_y(sel);
1094 GArray * intArr = g_array_new (TRUE, TRUE, sizeof(double));
1096 g_array_append_val (intArr, x);
1097 g_array_append_val (intArr, y);
1098 return intArr;
1099 }
1101 return NULL;
1102 }
1104 gboolean
1105 document_interface_selection_to_path (DocumentInterface *object, GError **error)
1106 {
1107 return dbus_call_verb (object, SP_VERB_OBJECT_TO_CURVE, error);
1108 }
1111 gchar *
1112 document_interface_selection_combine (DocumentInterface *object, gchar *cmd,
1113 GError **error)
1114 {
1115 if (strcmp(cmd, "union") == 0)
1116 dbus_call_verb (object, SP_VERB_SELECTION_UNION, error);
1117 else if (strcmp(cmd, "intersection") == 0)
1118 dbus_call_verb (object, SP_VERB_SELECTION_INTERSECT, error);
1119 else if (strcmp(cmd, "difference") == 0)
1120 dbus_call_verb (object, SP_VERB_SELECTION_DIFF, error);
1121 else if (strcmp(cmd, "exclusion") == 0)
1122 dbus_call_verb (object, SP_VERB_SELECTION_SYMDIFF, error);
1123 else
1124 return NULL;
1126 if (sp_desktop_selection(object->desk)->singleRepr() != NULL)
1127 return g_strdup((sp_desktop_selection(object->desk)->singleRepr())->attribute("id"));
1128 return NULL;
1129 }
1131 gboolean
1132 document_interface_selection_divide (DocumentInterface *object, char ***out, GError **error)
1133 {
1134 dbus_call_verb (object, SP_VERB_SELECTION_CUT, error);
1136 return document_interface_selection_get (object, out, error);
1137 }
1139 gboolean
1140 document_interface_selection_change_level (DocumentInterface *object, gchar *cmd,
1141 GError **error)
1142 {
1143 if (strcmp(cmd, "raise") == 0)
1144 return dbus_call_verb (object, SP_VERB_SELECTION_RAISE, error);
1145 if (strcmp(cmd, "lower") == 0)
1146 return dbus_call_verb (object, SP_VERB_SELECTION_LOWER, error);
1147 if ((strcmp(cmd, "to_top") == 0) || (strcmp(cmd, "to_front") == 0))
1148 return dbus_call_verb (object, SP_VERB_SELECTION_TO_FRONT, error);
1149 if ((strcmp(cmd, "to_bottom") == 0) || (strcmp(cmd, "to_back") == 0))
1150 return dbus_call_verb (object, SP_VERB_SELECTION_TO_BACK, error);
1151 return TRUE;
1152 }
1154 /****************************************************************************
1155 LAYER FUNCTIONS
1156 ****************************************************************************/
1158 gchar *
1159 document_interface_layer_new (DocumentInterface *object, GError **error)
1160 {
1161 SPDesktop * dt = object->desk;
1162 SPObject *new_layer = Inkscape::create_layer(dt->currentRoot(), dt->currentLayer(), Inkscape::LPOS_BELOW);
1163 dt->setCurrentLayer(new_layer);
1164 return g_strdup(get_name_from_object (new_layer));
1165 }
1167 gboolean
1168 document_interface_layer_set (DocumentInterface *object,
1169 gchar *layerstr, GError **error)
1170 {
1171 SPObject * obj = get_object_by_name (object->desk, layerstr, error);
1173 if (!obj)
1174 return FALSE;
1176 object->desk->setCurrentLayer (obj);
1177 return TRUE;
1178 }
1180 gchar **
1181 document_interface_layer_get_all (DocumentInterface *object)
1182 {
1183 //FIXME: implement.
1184 return NULL;
1185 }
1187 gboolean
1188 document_interface_layer_change_level (DocumentInterface *object,
1189 gchar *cmd, GError **error)
1190 {
1191 if (strcmp(cmd, "raise") == 0)
1192 return dbus_call_verb (object, SP_VERB_LAYER_RAISE, error);
1193 if (strcmp(cmd, "lower") == 0)
1194 return dbus_call_verb (object, SP_VERB_LAYER_LOWER, error);
1195 if ((strcmp(cmd, "to_top") == 0) || (strcmp(cmd, "to_front") == 0))
1196 return dbus_call_verb (object, SP_VERB_LAYER_TO_TOP, error);
1197 if ((strcmp(cmd, "to_bottom") == 0) || (strcmp(cmd, "to_back") == 0))
1198 return dbus_call_verb (object, SP_VERB_LAYER_TO_BOTTOM, error);
1199 return TRUE;
1200 }
1202 gboolean
1203 document_interface_layer_next (DocumentInterface *object, GError **error)
1204 {
1205 return dbus_call_verb (object, SP_VERB_LAYER_NEXT, error);
1206 }
1208 gboolean
1209 document_interface_layer_previous (DocumentInterface *object, GError **error)
1210 {
1211 return dbus_call_verb (object, SP_VERB_LAYER_PREV, error);
1212 }