Code

76eeec509d7ea8323f9007a278b2dcdb06ef13d2
[inkscape.git] / src / extension / dbus / document-interface.cpp
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;
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);
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);
115 //move_to etc
116 const GSList *
117 selection_swap(SPDesktop *desk, gchar *name, GError **error)
119     Inkscape::Selection *sel = sp_desktop_selection(desk);
120     const GSList *oldsel = g_slist_copy((GSList *)sel->list());
121     
122     sel->set(get_object_by_name(desk, name, error));
123     return oldsel;
126 void
127 selection_restore(SPDesktop *desk, const GSList * oldsel)
129     Inkscape::Selection *sel = sp_desktop_selection(desk);
130     sel->setList(oldsel);
133 Inkscape::XML::Node *
134 dbus_create_node (SPDesktop *desk, gboolean isrect)
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);
146 gchar *
147 finish_create_shape (DocumentInterface *object, GError **error, Inkscape::XML::Node *newNode, gchar *desc)
150     SPCSSAttr *style = sp_desktop_get_style(object->desk, TRUE);
151     
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"));
170 gboolean
171 dbus_call_verb (DocumentInterface *object, int verbid, GError **error)
172 {    
173     SPDesktop *desk2 = object->desk;
174     desktop_ensure_active (desk2);
175     
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;
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)
205         G_OBJECT_CLASS (document_interface_parent_class)->finalize (object);
209 static void
210 document_interface_class_init (DocumentInterfaceClass *klass)
212         GObjectClass *object_class;
213         object_class = G_OBJECT_CLASS (klass);
214         object_class->finalize = document_interface_finalize;
217 static void
218 document_interface_init (DocumentInterface *object)
220         object->desk = NULL;
224 DocumentInterface *
225 document_interface_new (void)
227         return (DocumentInterface*)g_object_new (TYPE_DOCUMENT_INTERFACE, NULL);
230 GQuark
231 inkscape_error_quark (void)
233   static GQuark quark = 0;
234   if (!quark)
235     quark = g_quark_from_static_string ("inkscape_error");
237   return quark;
240 /* This should really be standard. */
241 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
243 GType
244 inkscape_error_get_type (void)
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;
266 /****************************************************************************
267      MISC FUNCTIONS
268 ****************************************************************************/
270 gboolean
271 document_interface_delete_all (DocumentInterface *object, GError **error)
273     sp_edit_clear_all (object->desk);
274     return TRUE;
277 gboolean
278 document_interface_call_verb (DocumentInterface *object, gchar *verbid, GError **error)
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;
299 /****************************************************************************
300      CREATION FUNCTIONS
301 ****************************************************************************/
303 gchar* 
304 document_interface_rectangle (DocumentInterface *object, int x, int y, 
305                               int width, int height, GError **error)
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");
317 gchar*
318 document_interface_ellipse_center (DocumentInterface *object, int cx, int cy, 
319                                    int rx, int ry, GError **error)
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");
330 gchar* 
331 document_interface_polygon (DocumentInterface *object, int cx, int cy, 
332                             int radius, int rotation, int sides, 
333                             GError **error)
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");
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)
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");
373 gchar* 
374 document_interface_ellipse (DocumentInterface *object, int x, int y, 
375                             int width, int height, GError **error)
377     int rx = width/2;
378     int ry = height/2;
379     return document_interface_ellipse_center (object, x+rx, y+ry, rx, ry, error);
382 gchar* 
383 document_interface_line (DocumentInterface *object, int x, int y, 
384                               int x2, int y2, GError **error)
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");
395 gchar* 
396 document_interface_spiral (DocumentInterface *object, int cx, int cy, 
397                            int r, int revolutions, GError **error)
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;
413 gboolean
414 document_interface_text (DocumentInterface *object, int x, int y, gchar *text, GError **error)
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;
426 gchar* 
427 document_interface_node (DocumentInterface *object, gchar *type, GError **error)
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"));
445 /****************************************************************************
446      ENVIORNMENT FUNCTIONS
447 ****************************************************************************/
448 gdouble
449 document_interface_document_get_width (DocumentInterface *object)
451     return sp_document_width(sp_desktop_document(object->desk));
454 gdouble
455 document_interface_document_get_height (DocumentInterface *object)
457     return sp_document_height(sp_desktop_document(object->desk));
460 gchar *
461 document_interface_document_get_css (DocumentInterface *object, GError **error)
463     SPCSSAttr *current = (object->desk)->current;
464     return sp_repr_css_write_string(current);
467 gboolean 
468 document_interface_document_merge_css (DocumentInterface *object,
469                                        gchar *stylestring, GError **error)
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;
477 gboolean 
478 document_interface_document_set_css (DocumentInterface *object,
479                                      gchar *stylestring, GError **error)
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;
488 gboolean 
489 document_interface_document_resize_to_fit_selection (DocumentInterface *object,
490                                                      GError **error)
492     return dbus_call_verb (object, SP_VERB_FIT_CANVAS_TO_SELECTION, error);
493     return TRUE;
496 /****************************************************************************
497      OBJECT FUNCTIONS
498 ****************************************************************************/
500 gboolean
501 document_interface_set_attribute (DocumentInterface *object, char *shape, 
502                                   char *attribute, char *newval, GError **error)
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;
511         
512     if (!newNode)
513         return FALSE;
514         
515     newNode->setAttribute(attribute, newval, TRUE);
516     return TRUE;
519 gboolean 
520 document_interface_set_int_attribute (DocumentInterface *object, 
521                                       char *shape, char *attribute, 
522                                       int newval, GError **error)
524     Inkscape::XML::Node *newNode = get_repr_by_name (object->desk, shape, error);
525     if (!newNode)
526         return FALSE;
527         
528     sp_repr_set_int (newNode, attribute, newval);
529     return TRUE;
533 gboolean
534 document_interface_set_double_attribute (DocumentInterface *object, 
535                                          char *shape, char *attribute, 
536                                          double newval, GError **error)
538     Inkscape::XML::Node *newNode = get_repr_by_name (object->desk, shape, error);
539     
540     if (!dbus_check_string (attribute, error, "New value string was empty."))
541         return FALSE;
542     if (!newNode)
543         return FALSE;
544     
545     sp_repr_set_svg_double (newNode, attribute, newval);
546     return TRUE;
549 gchar *
550 document_interface_get_attribute (DocumentInterface *object, char *shape, 
551                                   char *attribute, GError **error)
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;
559         
560     return g_strdup(newNode->attribute(attribute));
563 gboolean
564 document_interface_move (DocumentInterface *object, gchar *name, gdouble x, 
565                          gdouble y, GError **error)
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;
575 gboolean
576 document_interface_move_to (DocumentInterface *object, gchar *name, gdouble x, 
577                          gdouble y, GError **error)
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;
589 gboolean
590 document_interface_object_to_path (DocumentInterface *object, 
591                                    char *shape, GError **error)
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;
601 gchar *
602 document_interface_get_path (DocumentInterface *object, char *pathname, GError **error)
604     Inkscape::XML::Node *node = get_repr_by_name(object->desk, pathname, error);
605     
606     if (!node)
607         return NULL;
608         
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"));
617 gboolean 
618 document_interface_transform (DocumentInterface *object, gchar *shape,
619                               gchar *transformstr, GError **error)
621     //FIXME: This should merge transformations.
622     gchar trans[] = "transform";
623     document_interface_set_attribute (object, shape, trans, transformstr, error);
624     return TRUE;
627 gchar *
628 document_interface_get_css (DocumentInterface *object, gchar *shape,
629                             GError **error)
631     gchar style[] = "style";
632     return document_interface_get_attribute (object, shape, style, error);
635 gboolean 
636 document_interface_modify_css (DocumentInterface *object, gchar *shape,
637                                gchar *cssattrb, gchar *newval, GError **error)
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);
642     
643     if (!dbus_check_string (cssattrb, error, "Attribute string empty."))
644         return FALSE;
645     if (!node)
646         return FALSE;
647         
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;
654 gboolean 
655 document_interface_merge_css (DocumentInterface *object, gchar *shape,
656                                gchar *stylestring, GError **error)
658     gchar style[] = "style";
659     
660     Inkscape::XML::Node *node = get_repr_by_name(object->desk, shape, error);
661     
662     if (!dbus_check_string (stylestring, error, "Style string empty."))
663         return FALSE;
664     if (!node)
665         return FALSE;
666         
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;
677 gboolean 
678 document_interface_move_to_layer (DocumentInterface *object, gchar *shape, 
679                               gchar *layerstr, GError **error)
681     const GSList *oldsel = selection_swap(object->desk, shape, error);
682     if (!oldsel)
683         return FALSE;
684         
685     document_interface_selection_move_to_layer(object, layerstr, error);
686     selection_restore(object->desk, oldsel);
687     return TRUE;
690 GArray *
691 document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape)
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);
701     
702     Geom::parse_svg_path (path);
703     return NULL;
704     */
705     return NULL;
709 /****************************************************************************
710      FILE I/O FUNCTIONS
711 ****************************************************************************/
713 gboolean 
714 document_interface_save (DocumentInterface *object, GError **error)
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;
723 gboolean 
724 document_interface_load (DocumentInterface *object, 
725                         gchar *filename, GError **error)
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;
735 gboolean 
736 document_interface_save_as (DocumentInterface *object, 
737                            gchar *filename, GError **error)
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;
760 gboolean
761 document_interface_mark_as_unmodified (DocumentInterface *object, GError **error)
763     SPDocument * doc = sp_desktop_document(object->desk);
764     if (doc)
765         doc->modified_since_save = FALSE;
766     return TRUE;
769 /*
770 gboolean 
771 document_interface_print_to_file (DocumentInterface *object, GError **error)
773     SPDocument * doc = sp_desktop_document(object->desk);
774     sp_print_document_to_file (doc, g_strdup("/home/soren/test.pdf"));
775                                
776     return TRUE;
778 */
779 /****************************************************************************
780      PROGRAM CONTROL FUNCTIONS
781 ****************************************************************************/
783 gboolean
784 document_interface_close (DocumentInterface *object, GError **error)
786     return dbus_call_verb (object, SP_VERB_FILE_CLOSE_VIEW, error);
789 gboolean
790 document_interface_exit (DocumentInterface *object, GError **error)
792     return dbus_call_verb (object, SP_VERB_FILE_QUIT, error);
795 gboolean
796 document_interface_undo (DocumentInterface *object, GError **error)
798     return dbus_call_verb (object, SP_VERB_EDIT_UNDO, error);
801 gboolean
802 document_interface_redo (DocumentInterface *object, GError **error)
804     return dbus_call_verb (object, SP_VERB_EDIT_REDO, error);
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)
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;
827 void
828 document_interface_resume_updates (DocumentInterface *object, GError **error)
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");
841 void
842 document_interface_update (DocumentInterface *object, GError **error)
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");
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)
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;
878 gboolean
879 document_interface_selection_add (DocumentInterface *object, char *name, GError **error)
881     SPObject * obj = get_object_by_name(object->desk, name, error);
882     if (!obj)
883         return FALSE;
884     
885     Inkscape::Selection *selection = sp_desktop_selection(object->desk);
887     selection->add(obj);
888     return TRUE;
891 gboolean
892 document_interface_selection_add_list (DocumentInterface *object, 
893                                        char **names, GError **error)
895     int i;
896     for (i=0;names[i] != NULL;i++) {
897         document_interface_selection_add(object, names[i], error);       
898     }
899     return TRUE;
902 gboolean
903 document_interface_selection_set (DocumentInterface *object, char *name, GError **error)
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;
911 gboolean
912 document_interface_selection_set_list (DocumentInterface *object, 
913                                        gchar **names, GError **error)
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;
923 gboolean
924 document_interface_selection_rotate (DocumentInterface *object, int angle, GError **error)
926     Inkscape::Selection *selection = sp_desktop_selection(object->desk);
927     sp_selection_rotate(selection, angle);
928     return TRUE;
931 gboolean
932 document_interface_selection_delete (DocumentInterface *object, GError **error)
934     //sp_selection_delete (object->desk);
935     return dbus_call_verb (object, SP_VERB_EDIT_DELETE, error);
938 gboolean
939 document_interface_selection_clear (DocumentInterface *object, GError **error)
941     sp_desktop_selection(object->desk)->clear();
942     return TRUE;
945 gboolean
946 document_interface_select_all (DocumentInterface *object, GError **error)
948     //sp_edit_select_all (object->desk);
949     return dbus_call_verb (object, SP_VERB_EDIT_SELECT_ALL, error);
952 gboolean
953 document_interface_select_all_in_all_layers(DocumentInterface *object, 
954                                             GError **error)
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);
960 gboolean
961 document_interface_selection_box (DocumentInterface *object, int x, int y,
962                                   int x2, int y2, gboolean replace, 
963                                   GError **error)
965     //FIXME: implement.
966     return FALSE;
969 gboolean
970 document_interface_selection_invert (DocumentInterface *object, GError **error)
972     //sp_edit_invert (object->desk);
973     return dbus_call_verb (object, SP_VERB_EDIT_INVERT, error);
976 gboolean
977 document_interface_selection_group (DocumentInterface *object, GError **error)
979     //sp_selection_group (object->desk);
980     return dbus_call_verb (object, SP_VERB_SELECTION_GROUP, error);
982 gboolean
983 document_interface_selection_ungroup (DocumentInterface *object, GError **error)
985     //sp_selection_ungroup (object->desk);
986     return dbus_call_verb (object, SP_VERB_SELECTION_UNGROUP, error);
988  
989 gboolean
990 document_interface_selection_cut (DocumentInterface *object, GError **error)
992     //desktop_ensure_active (object->desk);
993     //sp_selection_cut (object->desk);
994     return dbus_call_verb (object, SP_VERB_EDIT_CUT, error);
997 gboolean
998 document_interface_selection_copy (DocumentInterface *object, GError **error)
1000     //desktop_ensure_active (object->desk);
1001     //sp_selection_copy ();
1002     return dbus_call_verb (object, SP_VERB_EDIT_COPY, error);
1004 /*
1005 gboolean
1006 document_interface_selection_paste (DocumentInterface *object, GError **error)
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);
1017 */
1018 gboolean
1019 document_interface_selection_paste (DocumentInterface *object, GError **error)
1021     return dbus_call_verb (object, SP_VERB_EDIT_PASTE, error);
1024 gboolean
1025 document_interface_selection_scale (DocumentInterface *object, gdouble grow, GError **error)
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;
1036 gboolean
1037 document_interface_selection_move (DocumentInterface *object, gdouble x, gdouble y, GError **error)
1039     sp_selection_move (object->desk, x, 0 - y); //switching coordinate systems.
1040     return TRUE;
1043 gboolean
1044 document_interface_selection_move_to (DocumentInterface *object, gdouble x, gdouble y, GError **error)
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;
1056 //FIXME: does not paste in new layer.
1057 gboolean 
1058 document_interface_selection_move_to_layer (DocumentInterface *object,
1059                                             gchar *layerstr, GError **error)
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);
1070     
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;
1085 GArray *
1086 document_interface_selection_get_center (DocumentInterface *object)
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;
1104 gboolean 
1105 document_interface_selection_to_path (DocumentInterface *object, GError **error)
1107     return dbus_call_verb (object, SP_VERB_OBJECT_TO_CURVE, error);    
1111 gchar *
1112 document_interface_selection_combine (DocumentInterface *object, gchar *cmd,
1113                                       GError **error)
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;
1131 gboolean
1132 document_interface_selection_divide (DocumentInterface *object, char ***out, GError **error)
1134     dbus_call_verb (object, SP_VERB_SELECTION_CUT, error);
1136     return document_interface_selection_get (object, out, error);
1139 gboolean
1140 document_interface_selection_change_level (DocumentInterface *object, gchar *cmd,
1141                                       GError **error)
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;
1154 /****************************************************************************
1155      LAYER FUNCTIONS
1156 ****************************************************************************/
1158 gchar *
1159 document_interface_layer_new (DocumentInterface *object, GError **error)
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));
1167 gboolean 
1168 document_interface_layer_set (DocumentInterface *object,
1169                               gchar *layerstr, GError **error)
1171     SPObject * obj = get_object_by_name (object->desk, layerstr, error);
1172     
1173     if (!obj)
1174         return FALSE;
1175         
1176     object->desk->setCurrentLayer (obj);
1177     return TRUE;
1180 gchar **
1181 document_interface_layer_get_all (DocumentInterface *object)
1183     //FIXME: implement.
1184     return NULL;
1187 gboolean 
1188 document_interface_layer_change_level (DocumentInterface *object,
1189                                        gchar *cmd, GError **error)
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;
1202 gboolean 
1203 document_interface_layer_next (DocumentInterface *object, GError **error)
1205     return dbus_call_verb (object, SP_VERB_LAYER_NEXT, error);
1208 gboolean 
1209 document_interface_layer_previous (DocumentInterface *object, GError **error)
1211     return dbus_call_verb (object, SP_VERB_LAYER_PREV, error);