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 /****************************************************************************
36 HELPER / SHORTCUT FUNCTIONS
37 ****************************************************************************/
39 const gchar* intToCString(int i)
40 {
41 std::stringstream ss;
42 ss << i;
43 return ss.str().c_str();
44 }
46 SPObject *
47 get_object_by_name (SPDesktop *desk, gchar *name)
48 {
49 return sp_desktop_document(desk)->getObjectById(name);
50 }
52 const gchar *
53 get_name_from_object (SPObject * obj)
54 {
55 return obj->repr->attribute("id");
56 }
58 void
59 desktop_ensure_active (SPDesktop* desk) {
60 if (desk != SP_ACTIVE_DESKTOP)
61 inkscape_activate_desktop (desk);
62 return;
63 }
65 Inkscape::XML::Node *
66 document_retrive_node (SPDocument *doc, gchar *name) {
67 return (doc->getObjectById(name))->repr;
68 }
70 gdouble
71 selection_get_center_x (Inkscape::Selection *sel){
72 NRRect *box = g_new(NRRect, 1);;
73 box = sel->boundsInDocument(box);
74 return box->x0 + ((box->x1 - box->x0)/2);
75 }
77 gdouble
78 selection_get_center_y (Inkscape::Selection *sel){
79 NRRect *box = g_new(NRRect, 1);;
80 box = sel->boundsInDocument(box);
81 return box->y0 + ((box->y1 - box->y0)/2);
82 }
83 //move_to etc
84 const GSList *
85 selection_swap(SPDesktop *desk, gchar *name)
86 {
87 Inkscape::Selection *sel = sp_desktop_selection(desk);
88 const GSList *oldsel = g_slist_copy((GSList *)sel->list());
90 sel->set(get_object_by_name(desk, name));
91 return oldsel;
92 }
94 void
95 selection_restore(SPDesktop *desk, const GSList * oldsel)
96 {
97 Inkscape::Selection *sel = sp_desktop_selection(desk);
98 sel->setList(oldsel);
99 }
101 Inkscape::XML::Node *
102 dbus_create_node (SPDesktop *desk, gboolean isrect)
103 {
104 SPDocument * doc = sp_desktop_document (desk);
105 Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
106 gchar *type;
107 if (isrect)
108 type = (gchar *)"svg:rect";
109 else
110 type = (gchar *)"svg:path";
111 return xml_doc->createElement(type);
112 }
114 gchar *
115 finish_create_shape (DocumentInterface *object, GError **error, Inkscape::XML::Node *newNode, gchar *desc)
116 {
118 SPCSSAttr *style = sp_desktop_get_style(object->desk, TRUE);
120 if (style) {
121 newNode->setAttribute("style", sp_repr_css_write_string(style), TRUE);
122 }
123 else {
124 newNode->setAttribute("style", "fill:#0000ff;fill-opacity:1;stroke:#c900b9;stroke-width:0;stroke-miterlimit:0;stroke-opacity:1;stroke-dasharray:none", TRUE);
125 }
127 object->desk->currentLayer()->appendChildRepr(newNode);
128 object->desk->currentLayer()->updateRepr();
130 if (object->updates)
131 sp_document_done(sp_desktop_document(object->desk), 0, (gchar *)desc);
132 else
133 document_interface_pause_updates(object, error);
135 return strdup(newNode->attribute("id"));
136 }
138 gboolean
139 dbus_call_verb (DocumentInterface *object, int verbid, GError **error)
140 {
141 SPDesktop *desk2 = object->desk;
143 if ( desk2 ) {
144 Inkscape::Verb *verb = Inkscape::Verb::get( verbid );
145 if ( verb ) {
146 SPAction *action = verb->get_action(desk2);
147 if ( action ) {
148 sp_action_perform( action, NULL );
149 if (object->updates) {
150 sp_document_done(sp_desktop_document(desk2), verb->get_code(), g_strdup(verb->get_tip()));
151 }
152 return TRUE;
153 }
154 }
155 }
156 return FALSE;
157 }
159 /****************************************************************************
160 DOCUMENT INTERFACE CLASS STUFF
161 ****************************************************************************/
163 G_DEFINE_TYPE(DocumentInterface, document_interface, G_TYPE_OBJECT)
165 static void
166 document_interface_finalize (GObject *object)
167 {
168 G_OBJECT_CLASS (document_interface_parent_class)->finalize (object);
169 }
172 static void
173 document_interface_class_init (DocumentInterfaceClass *klass)
174 {
175 GObjectClass *object_class;
176 object_class = G_OBJECT_CLASS (klass);
177 object_class->finalize = document_interface_finalize;
178 }
180 static void
181 document_interface_init (DocumentInterface *object)
182 {
183 object->desk = NULL;
184 }
187 DocumentInterface *
188 document_interface_new (void)
189 {
190 return (DocumentInterface*)g_object_new (TYPE_DOCUMENT_INTERFACE, NULL);
191 }
193 /****************************************************************************
194 MISC FUNCTIONS
195 ****************************************************************************/
197 gboolean
198 document_interface_delete_all (DocumentInterface *object, GError **error)
199 {
200 sp_edit_clear_all (object->desk);
201 return TRUE;
202 }
204 void
205 document_interface_call_verb (DocumentInterface *object, gchar *verbid, GError **error)
206 {
207 SPDesktop *desk2 = object->desk;
208 desktop_ensure_active (object->desk);
209 if ( desk2 ) {
210 Inkscape::Verb *verb = Inkscape::Verb::getbyid( verbid );
211 if ( verb ) {
212 SPAction *action = verb->get_action(desk2);
213 if ( action ) {
214 sp_action_perform( action, NULL );
215 if (object->updates) {
216 sp_document_done(sp_desktop_document(desk2), verb->get_code(), g_strdup(verb->get_tip()));
217 }
218 }
219 }
220 }
221 }
224 /****************************************************************************
225 CREATION FUNCTIONS
226 ****************************************************************************/
228 gchar*
229 document_interface_rectangle (DocumentInterface *object, int x, int y,
230 int width, int height, GError **error)
231 {
234 Inkscape::XML::Node *newNode = dbus_create_node(object->desk, TRUE);
235 sp_repr_set_int(newNode, "x", x); //could also use newNode->setAttribute()
236 sp_repr_set_int(newNode, "y", y);
237 sp_repr_set_int(newNode, "width", width);
238 sp_repr_set_int(newNode, "height", height);
239 return finish_create_shape (object, error, newNode, (gchar *)"create rectangle");
240 }
242 gchar*
243 document_interface_ellipse_center (DocumentInterface *object, int cx, int cy,
244 int rx, int ry, GError **error)
245 {
246 Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE);
247 newNode->setAttribute("sodipodi:type", "arc");
248 sp_repr_set_int(newNode, "sodipodi:cx", cx);
249 sp_repr_set_int(newNode, "sodipodi:cy", cy);
250 sp_repr_set_int(newNode, "sodipodi:rx", rx);
251 sp_repr_set_int(newNode, "sodipodi:ry", ry);
252 return finish_create_shape (object, error, newNode, (gchar *)"create circle");
253 }
255 gchar*
256 document_interface_polygon (DocumentInterface *object, int cx, int cy,
257 int radius, int rotation, int sides,
258 GError **error)
259 {
260 gdouble rot = ((rotation / 180.0) * 3.14159265) - ( 3.14159265 / 2.0);
261 Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE);
262 newNode->setAttribute("inkscape:flatsided", "true");
263 newNode->setAttribute("sodipodi:type", "star");
264 sp_repr_set_int(newNode, "sodipodi:cx", cx);
265 sp_repr_set_int(newNode, "sodipodi:cy", cy);
266 sp_repr_set_int(newNode, "sodipodi:r1", radius);
267 sp_repr_set_int(newNode, "sodipodi:r2", radius);
268 sp_repr_set_int(newNode, "sodipodi:sides", sides);
269 sp_repr_set_int(newNode, "inkscape:randomized", 0);
270 sp_repr_set_svg_double(newNode, "sodipodi:arg1", rot);
271 sp_repr_set_svg_double(newNode, "sodipodi:arg2", rot);
272 sp_repr_set_svg_double(newNode, "inkscape:rounded", 0);
274 return finish_create_shape (object, error, newNode, (gchar *)"create polygon");
275 }
277 gchar*
278 document_interface_star (DocumentInterface *object, int cx, int cy,
279 int r1, int r2, int sides, gdouble rounded,
280 gdouble arg1, gdouble arg2, GError **error)
281 {
282 Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE);
283 newNode->setAttribute("inkscape:flatsided", "false");
284 newNode->setAttribute("sodipodi:type", "star");
285 sp_repr_set_int(newNode, "sodipodi:cx", cx);
286 sp_repr_set_int(newNode, "sodipodi:cy", cy);
287 sp_repr_set_int(newNode, "sodipodi:r1", r1);
288 sp_repr_set_int(newNode, "sodipodi:r2", r2);
289 sp_repr_set_int(newNode, "sodipodi:sides", sides);
290 sp_repr_set_int(newNode, "inkscape:randomized", 0);
291 sp_repr_set_svg_double(newNode, "sodipodi:arg1", arg1);
292 sp_repr_set_svg_double(newNode, "sodipodi:arg2", arg2);
293 sp_repr_set_svg_double(newNode, "inkscape:rounded", rounded);
295 return finish_create_shape (object, error, newNode, (gchar *)"create star");
296 }
298 gchar*
299 document_interface_ellipse (DocumentInterface *object, int x, int y,
300 int width, int height, GError **error)
301 {
302 int rx = width/2;
303 int ry = height/2;
304 return document_interface_ellipse_center (object, x+rx, y+ry, rx, ry, error);
305 }
307 gchar*
308 document_interface_line (DocumentInterface *object, int x, int y,
309 int x2, int y2, GError **error)
310 {
311 Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE);
312 std::stringstream out;
313 printf("X2: %d\nY2 %d\n", x2, y2);
314 out << "m " << x << "," << y << " " << x2 << "," << y2;
315 printf ("PATH: %s\n", out.str().c_str());
316 newNode->setAttribute("d", out.str().c_str());
317 return finish_create_shape (object, error, newNode, (gchar *)"create line");
318 }
320 gchar*
321 document_interface_spiral (DocumentInterface *object, int cx, int cy,
322 int r, int revolutions, GError **error)
323 {
324 Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE);
325 newNode->setAttribute("sodipodi:type", "spiral");
326 sp_repr_set_int(newNode, "sodipodi:cx", cx);
327 sp_repr_set_int(newNode, "sodipodi:cy", cy);
328 sp_repr_set_int(newNode, "sodipodi:radius", r);
329 sp_repr_set_int(newNode, "sodipodi:revolution", revolutions);
330 sp_repr_set_int(newNode, "sodipodi:t0", 0);
331 sp_repr_set_int(newNode, "sodipodi:argument", 0);
332 sp_repr_set_int(newNode, "sodipodi:expansion", 1);
333 gchar * retval = finish_create_shape (object, error, newNode, (gchar *)"create spiral");
334 newNode->setAttribute("style", "fill:none");
335 return retval;
336 }
338 gchar*
339 document_interface_text (DocumentInterface *object, gchar *text, GError **error)
340 {
341 //FIXME: implement.
342 return NULL;
343 }
345 gchar*
346 document_interface_node (DocumentInterface *object, gchar *type, GError **error)
347 {
348 SPDocument * doc = sp_desktop_document (object->desk);
349 Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
351 Inkscape::XML::Node *newNode = xml_doc->createElement(type);
353 object->desk->currentLayer()->appendChildRepr(newNode);
354 object->desk->currentLayer()->updateRepr();
356 if (object->updates)
357 sp_document_done(sp_desktop_document(object->desk), 0, (gchar *)"created empty node");
358 else
359 document_interface_pause_updates(object, error);
361 return strdup(newNode->attribute("id"));
362 }
364 /****************************************************************************
365 ENVIORNMENT FUNCTIONS
366 ****************************************************************************/
367 gdouble
368 document_interface_document_get_width (DocumentInterface *object)
369 {
370 return sp_document_width(sp_desktop_document(object->desk));
371 }
373 gdouble
374 document_interface_document_get_height (DocumentInterface *object)
375 {
376 return sp_document_height(sp_desktop_document(object->desk));
377 }
379 gchar *
380 document_interface_document_get_css (DocumentInterface *object, GError **error)
381 {
382 SPCSSAttr *current = (object->desk)->current;
383 return sp_repr_css_write_string(current);
384 }
386 gboolean
387 document_interface_document_merge_css (DocumentInterface *object,
388 gchar *stylestring, GError **error)
389 {
390 SPCSSAttr * style = sp_repr_css_attr_new();
391 sp_repr_css_attr_add_from_string (style, stylestring);
392 sp_desktop_set_style (object->desk, style);
393 return TRUE;
394 }
396 gboolean
397 document_interface_document_set_css (DocumentInterface *object,
398 gchar *stylestring, GError **error)
399 {
400 SPCSSAttr * style = sp_repr_css_attr_new();
401 sp_repr_css_attr_add_from_string (style, stylestring);
402 //Memory leak?
403 object->desk->current = style;
404 return TRUE;
405 }
407 gboolean
408 document_interface_document_resize_to_fit_selection (DocumentInterface *object,
409 GError **error)
410 {
411 dbus_call_verb (object, SP_VERB_FIT_CANVAS_TO_SELECTION, error);
412 return TRUE;
413 }
415 /****************************************************************************
416 OBJECT FUNCTIONS
417 ****************************************************************************/
419 gboolean
420 document_interface_set_attribute (DocumentInterface *object, char *shape,
421 char *attribute, char *newval, GError **error)
422 {
423 Inkscape::XML::Node *newNode = get_object_by_name(object->desk, shape)->repr;
425 /* ALTERNATIVE (is this faster?)
426 Inkscape::XML::Node *newnode = sp_repr_lookup_name((doc->root)->repr, name);
427 */
428 if (newNode)
429 {
430 newNode->setAttribute(attribute, newval, TRUE);
431 return TRUE;
432 }
433 return FALSE;
434 }
436 void
437 document_interface_set_int_attribute (DocumentInterface *object,
438 char *shape, char *attribute,
439 int newval, GError **error)
440 {
441 Inkscape::XML::Node *newNode = get_object_by_name (object->desk, shape)->repr;
442 if (newNode)
443 sp_repr_set_int (newNode, attribute, newval);
444 }
447 void
448 document_interface_set_double_attribute (DocumentInterface *object,
449 char *shape, char *attribute,
450 double newval, GError **error)
451 {
452 Inkscape::XML::Node *newNode = get_object_by_name (object->desk, shape)->repr;
453 if (newNode)
454 sp_repr_set_svg_double (newNode, attribute, newval);
455 }
457 gchar *
458 document_interface_get_attribute (DocumentInterface *object, char *shape,
459 char *attribute, GError **error)
460 {
461 Inkscape::XML::Node *newNode = get_object_by_name(object->desk, shape)->repr;
463 if (newNode)
464 return g_strdup(newNode->attribute(attribute));
465 return FALSE;
466 }
468 gboolean
469 document_interface_move (DocumentInterface *object, gchar *name, gdouble x,
470 gdouble y, GError **error)
471 {
472 const GSList *oldsel = selection_swap(object->desk, name);
473 sp_selection_move (object->desk, x, 0 - y);
474 selection_restore(object->desk, oldsel);
475 return TRUE;
476 }
478 gboolean
479 document_interface_move_to (DocumentInterface *object, gchar *name, gdouble x,
480 gdouble y, GError **error)
481 {
482 const GSList *oldsel = selection_swap(object->desk, name);
483 Inkscape::Selection * sel = sp_desktop_selection(object->desk);
484 sp_selection_move (object->desk, x - selection_get_center_x(sel),
485 0 - (y - selection_get_center_y(sel)));
486 selection_restore(object->desk, oldsel);
487 return TRUE;
488 }
490 gboolean
491 document_interface_object_to_path (DocumentInterface *object,
492 char *shape, GError **error)
493 {
494 const GSList *oldsel = selection_swap(object->desk, shape);
495 dbus_call_verb (object, SP_VERB_OBJECT_TO_CURVE, error);
496 selection_restore(object->desk, oldsel);
497 return TRUE;
498 }
500 gchar *
501 document_interface_get_path (DocumentInterface *object, char *pathname, GError **error)
502 {
503 Inkscape::XML::Node *node = document_retrive_node (sp_desktop_document (object->desk), pathname);
504 if (node == NULL || node->attribute("d") == NULL) {
505 g_set_error(error, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION, "Object is not a path or does not exist.");
506 return FALSE;
507 }
508 return strdup(node->attribute("d"));
509 }
511 gboolean
512 document_interface_transform (DocumentInterface *object, gchar *shape,
513 gchar *transformstr, GError **error)
514 {
515 //FIXME: This should merge transformations.
516 gchar trans[] = "transform";
517 document_interface_set_attribute (object, shape, trans, transformstr, error);
518 return TRUE;
519 }
521 gchar *
522 document_interface_get_css (DocumentInterface *object, gchar *shape,
523 GError **error)
524 {
525 gchar style[] = "style";
526 return document_interface_get_attribute (object, shape, style, error);
527 }
529 gboolean
530 document_interface_modify_css (DocumentInterface *object, gchar *shape,
531 gchar *cssattrb, gchar *newval, GError **error)
532 {
533 gchar style[] = "style";
534 Inkscape::XML::Node *node = get_object_by_name(object->desk, shape)->repr;
535 SPCSSAttr * oldstyle = sp_repr_css_attr (node, style);
536 sp_repr_css_set_property(oldstyle, cssattrb, newval);
537 node->setAttribute (style, sp_repr_css_write_string (oldstyle), TRUE);
538 return TRUE;
539 }
541 gboolean
542 document_interface_merge_css (DocumentInterface *object, gchar *shape,
543 gchar *stylestring, GError **error)
544 {
545 SPCSSAttr * newstyle = sp_repr_css_attr_new();
546 sp_repr_css_attr_add_from_string (newstyle, stylestring);
548 gchar style[] = "style";
549 Inkscape::XML::Node *node = get_object_by_name(object->desk, shape)->repr;
550 SPCSSAttr * oldstyle = sp_repr_css_attr (node, style);
552 sp_repr_css_merge(oldstyle, newstyle);
553 node->setAttribute (style, sp_repr_css_write_string (oldstyle), TRUE);
554 return TRUE;
555 }
557 gboolean
558 document_interface_move_to_layer (DocumentInterface *object, gchar *shape,
559 gchar *layerstr, GError **error)
560 {
561 const GSList *oldsel = selection_swap(object->desk, shape);
562 document_interface_selection_move_to_layer(object, layerstr, error);
563 selection_restore(object->desk, oldsel);
564 return TRUE;
565 }
567 DBUSPoint **
568 document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape)
569 {
570 //FIXME: Needs lot's of work.
571 /*
572 Inkscape::XML::Node *node = document_retrive_node (sp_desktop_document (object->desk), pathname);
573 if (node == NULL || node->attribute("d") == NULL) {
574 g_set_error(error, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION, "Object is not a path or does not exist.");
575 return FALSE;
576 }
577 //char * path = strdup(node->attribute("d"));
578 */
579 return NULL;
580 }
583 /****************************************************************************
584 FILE I/O FUNCTIONS
585 ****************************************************************************/
587 gboolean
588 document_interface_save (DocumentInterface *object, GError **error)
589 {
590 SPDocument * doc = sp_desktop_document(object->desk);
591 printf("1: %s\n2: %s\n3: %s\n", doc->uri, doc->base, doc->name);
592 if (doc->uri)
593 return document_interface_save_as (object, doc->uri, error);
594 return FALSE;
595 }
597 gboolean
598 document_interface_load (DocumentInterface *object,
599 gchar *filename, GError **error)
600 {
601 desktop_ensure_active (object->desk);
602 const Glib::ustring file(filename);
603 sp_file_open(file, NULL, TRUE, TRUE);
604 if (object->updates)
605 sp_document_done(sp_desktop_document(object->desk), SP_VERB_FILE_OPEN, "Opened File");
606 return TRUE;
607 }
609 gboolean
610 document_interface_save_as (DocumentInterface *object,
611 gchar *filename, GError **error)
612 {
613 SPDocument * doc = sp_desktop_document(object->desk);
614 #ifdef WITH_GNOME_VFS
615 const Glib::ustring file(filename);
616 return file_save_remote(doc, file, NULL, TRUE, TRUE);
617 #endif
618 if (!doc || strlen(filename)<1) //Safety check
619 return false;
621 try {
622 Inkscape::Extension::save(NULL, doc, filename,
623 false, false, true);
624 } catch (...) {
625 //SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved."));
626 return false;
627 }
629 //SP_ACTIVE_DESKTOP->event_log->rememberFileSave();
630 //SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::NORMAL_MESSAGE, "Document saved.");
631 return true;
632 }
633 /*
634 gboolean
635 document_interface_print_to_file (DocumentInterface *object, GError **error)
636 {
637 SPDocument * doc = sp_desktop_document(object->desk);
638 sp_print_document_to_file (doc, g_strdup("/home/soren/test.pdf"));
640 return TRUE;
641 }
642 */
643 /****************************************************************************
644 PROGRAM CONTROL FUNCTIONS
645 ****************************************************************************/
647 gboolean
648 document_interface_close (DocumentInterface *object, GError **error)
649 {
650 return dbus_call_verb (object, SP_VERB_FILE_CLOSE_VIEW, error);
651 }
653 gboolean
654 document_interface_exit (DocumentInterface *object, GError **error)
655 {
656 return dbus_call_verb (object, SP_VERB_FILE_QUIT, error);
657 }
659 gboolean
660 document_interface_undo (DocumentInterface *object, GError **error)
661 {
662 return dbus_call_verb (object, SP_VERB_EDIT_UNDO, error);
663 }
665 gboolean
666 document_interface_redo (DocumentInterface *object, GError **error)
667 {
668 return dbus_call_verb (object, SP_VERB_EDIT_REDO, error);
669 }
673 /****************************************************************************
674 UPDATE FUNCTIONS FIXME: test update system again.
675 ****************************************************************************/
677 void
678 document_interface_pause_updates (DocumentInterface *object, GError **error)
679 {
680 object->updates = FALSE;
681 sp_desktop_document(object->desk)->root->uflags = FALSE;
682 sp_desktop_document(object->desk)->root->mflags = FALSE;
683 }
685 void
686 document_interface_resume_updates (DocumentInterface *object, GError **error)
687 {
688 object->updates = TRUE;
689 sp_desktop_document(object->desk)->root->uflags = TRUE;
690 sp_desktop_document(object->desk)->root->mflags = TRUE;
691 //sp_desktop_document(object->desk)->_updateDocument();
692 //FIXME: use better verb than rect.
693 sp_document_done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions");
694 }
696 void
697 document_interface_update (DocumentInterface *object, GError **error)
698 {
699 sp_desktop_document(object->desk)->root->uflags = TRUE;
700 sp_desktop_document(object->desk)->root->mflags = TRUE;
701 sp_desktop_document(object->desk)->_updateDocument();
702 sp_desktop_document(object->desk)->root->uflags = FALSE;
703 sp_desktop_document(object->desk)->root->mflags = FALSE;
704 //sp_document_done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions");
705 }
707 /****************************************************************************
708 SELECTION FUNCTIONS FIXME: use call_verb where appropriate.
709 ****************************************************************************/
711 gboolean
712 document_interface_selection_get (DocumentInterface *object, char ***out, GError **error)
713 {
714 Inkscape::Selection * sel = sp_desktop_selection(object->desk);
715 GSList const *oldsel = sel->list();
717 int size = g_slist_length((GSList *) oldsel);
719 *out = g_new0 (char *, size + 1);
721 int i = 0;
722 for (GSList const *iter = oldsel; iter != NULL; iter = iter->next) {
723 (*out)[i] = g_strdup(SP_OBJECT(iter->data)->repr->attribute("id"));
724 i++;
725 }
726 (*out)[i] = NULL;
728 return TRUE;
729 }
731 gboolean
732 document_interface_selection_add (DocumentInterface *object, char *name, GError **error)
733 {
734 if (name == NULL)
735 return FALSE;
736 Inkscape::Selection *selection = sp_desktop_selection(object->desk);
738 selection->add(get_object_by_name(object->desk, name));
739 return TRUE;
740 }
742 gboolean
743 document_interface_selection_add_list (DocumentInterface *object,
744 char **names, GError **error)
745 {
746 int i;
747 for (i=0;names[i] != NULL;i++) {
748 document_interface_selection_add(object, names[i], error);
749 }
750 return TRUE;
751 }
753 gboolean
754 document_interface_selection_set (DocumentInterface *object, char *name, GError **error)
755 {
756 SPDocument * doc = sp_desktop_document (object->desk);
757 Inkscape::Selection *selection = sp_desktop_selection(object->desk);
758 selection->set(doc->getObjectById(name));
759 return TRUE;
760 }
762 gboolean
763 document_interface_selection_set_list (DocumentInterface *object,
764 gchar **names, GError **error)
765 {
766 sp_desktop_selection(object->desk)->clear();
767 int i;
768 for (i=0;names[i] != NULL;i++) {
769 document_interface_selection_add(object, names[i], error);
770 }
771 return TRUE;
772 }
774 gboolean
775 document_interface_selection_rotate (DocumentInterface *object, int angle, GError **error)
776 {
777 Inkscape::Selection *selection = sp_desktop_selection(object->desk);
778 sp_selection_rotate(selection, angle);
779 return TRUE;
780 }
782 gboolean
783 document_interface_selection_delete (DocumentInterface *object, GError **error)
784 {
785 sp_selection_delete (object->desk);
786 return TRUE;
787 }
789 gboolean
790 document_interface_selection_clear (DocumentInterface *object, GError **error)
791 {
792 sp_desktop_selection(object->desk)->clear();
793 return TRUE;
794 }
796 gboolean
797 document_interface_select_all (DocumentInterface *object, GError **error)
798 {
799 sp_edit_select_all (object->desk);
800 return TRUE;
801 }
803 gboolean
804 document_interface_select_all_in_all_layers(DocumentInterface *object,
805 GError **error)
806 {
807 sp_edit_select_all_in_all_layers (object->desk);
808 return TRUE;
809 }
811 gboolean
812 document_interface_selection_box (DocumentInterface *object, int x, int y,
813 int x2, int y2, gboolean replace,
814 GError **error)
815 {
816 //FIXME: implement.
817 return FALSE;
818 }
820 gboolean
821 document_interface_selection_invert (DocumentInterface *object, GError **error)
822 {
823 sp_edit_invert (object->desk);
824 return TRUE;
825 }
827 gboolean
828 document_interface_selection_group (DocumentInterface *object, GError **error)
829 {
830 sp_selection_group (object->desk);
831 return TRUE;
832 }
833 gboolean
834 document_interface_selection_ungroup (DocumentInterface *object, GError **error)
835 {
836 sp_selection_ungroup (object->desk);
837 return TRUE;
838 }
840 gboolean
841 document_interface_selection_cut (DocumentInterface *object, GError **error)
842 {
843 sp_selection_cut (object->desk);
844 return TRUE;
845 }
846 gboolean
847 document_interface_selection_copy (DocumentInterface *object, GError **error)
848 {
849 desktop_ensure_active (object->desk);
850 sp_selection_copy ();
851 return TRUE;
852 }
853 gboolean
854 document_interface_selection_paste (DocumentInterface *object, GError **error)
855 {
856 desktop_ensure_active (object->desk);
857 sp_selection_paste (object->desk, TRUE);
858 return TRUE;
859 }
861 gboolean
862 document_interface_selection_scale (DocumentInterface *object, gdouble grow, GError **error)
863 {
864 Inkscape::Selection *selection = sp_desktop_selection(object->desk);
865 sp_selection_scale (selection, grow);
866 return TRUE;
867 }
869 gboolean
870 document_interface_selection_move (DocumentInterface *object, gdouble x, gdouble y, GError **error)
871 {
872 sp_selection_move (object->desk, x, 0 - y); //switching coordinate systems.
873 return TRUE;
874 }
876 gboolean
877 document_interface_selection_move_to (DocumentInterface *object, gdouble x, gdouble y, GError **error)
878 {
879 Inkscape::Selection * sel = sp_desktop_selection(object->desk);
881 Geom::OptRect sel_bbox = sel->bounds();
882 if (sel_bbox) {
883 Geom::Point m( x - selection_get_center_x(sel) , 0 - (y - selection_get_center_y(sel)) );
884 sp_selection_move_relative(sel, m, true);
885 }
886 return TRUE;
887 }
889 //FIXME: does not paste in new layer.
890 gboolean
891 document_interface_selection_move_to_layer (DocumentInterface *object,
892 gchar *layerstr, GError **error)
893 {
894 SPDesktop * dt = object->desk;
896 Inkscape::Selection *selection = sp_desktop_selection(dt);
898 // check if something is selected
899 if (selection->isEmpty())
900 return FALSE;
902 SPObject *next = get_object_by_name(object->desk, layerstr);
904 if (next && (strcmp("layer", (next->repr)->attribute("inkscape:groupmode")) == 0)) {
906 sp_selection_cut(dt);
908 dt->setCurrentLayer(next);
910 sp_selection_paste(dt, TRUE);
911 }
912 return TRUE;
913 }
915 GArray *
916 document_interface_selection_get_center (DocumentInterface *object)
917 {
918 Inkscape::Selection * sel = sp_desktop_selection(object->desk);
920 if (sel)
921 {
922 gdouble x = selection_get_center_x(sel);
923 gdouble y = selection_get_center_y(sel);
924 GArray * intArr = g_array_new (TRUE, TRUE, sizeof(double));
926 g_array_append_val (intArr, x);
927 g_array_append_val (intArr, y);
928 return intArr;
929 }
931 return NULL;
932 }
934 gboolean
935 document_interface_selection_to_path (DocumentInterface *object, GError **error)
936 {
937 return dbus_call_verb (object, SP_VERB_OBJECT_TO_CURVE, error);
938 }
941 gchar *
942 document_interface_selection_combine (DocumentInterface *object, gchar *cmd,
943 GError **error)
944 {
945 if (strcmp(cmd, "union") == 0)
946 dbus_call_verb (object, SP_VERB_SELECTION_UNION, error);
947 else if (strcmp(cmd, "intersection") == 0)
948 dbus_call_verb (object, SP_VERB_SELECTION_INTERSECT, error);
949 else if (strcmp(cmd, "difference") == 0)
950 dbus_call_verb (object, SP_VERB_SELECTION_DIFF, error);
951 else if (strcmp(cmd, "exclusion") == 0)
952 dbus_call_verb (object, SP_VERB_SELECTION_SYMDIFF, error);
953 else if (strcmp(cmd, "division") == 0)
954 dbus_call_verb (object, SP_VERB_SELECTION_CUT, error);
955 else
956 return NULL;
958 if (sp_desktop_selection(object->desk)->singleRepr() != NULL)
959 return g_strdup((sp_desktop_selection(object->desk)->singleRepr())->attribute("id"));
961 //Division will have a list of things selected, should have it's own function.
962 return NULL;
963 }
965 gboolean
966 document_interface_selection_divide (DocumentInterface *object, char ***out, GError **error)
967 {
968 dbus_call_verb (object, SP_VERB_SELECTION_CUT, error);
970 return document_interface_selection_get (object, out, error);
971 }
973 gboolean
974 document_interface_selection_change_level (DocumentInterface *object, gchar *cmd,
975 GError **error)
976 {
977 if (strcmp(cmd, "raise") == 0)
978 return dbus_call_verb (object, SP_VERB_SELECTION_RAISE, error);
979 if (strcmp(cmd, "lower") == 0)
980 return dbus_call_verb (object, SP_VERB_SELECTION_LOWER, error);
981 if ((strcmp(cmd, "to_top") == 0) || (strcmp(cmd, "to_front") == 0))
982 return dbus_call_verb (object, SP_VERB_SELECTION_TO_FRONT, error);
983 if ((strcmp(cmd, "to_bottom") == 0) || (strcmp(cmd, "to_back") == 0))
984 return dbus_call_verb (object, SP_VERB_SELECTION_TO_BACK, error);
985 return TRUE;
986 }
988 /****************************************************************************
989 LAYER FUNCTIONS
990 ****************************************************************************/
992 gchar *
993 document_interface_layer_new (DocumentInterface *object, GError **error)
994 {
995 SPDesktop * dt = object->desk;
996 SPObject *new_layer = Inkscape::create_layer(dt->currentRoot(), dt->currentLayer(), Inkscape::LPOS_BELOW);
997 dt->setCurrentLayer(new_layer);
998 return g_strdup(get_name_from_object (new_layer));
999 }
1001 gboolean
1002 document_interface_layer_set (DocumentInterface *object,
1003 gchar *layerstr, GError **error)
1004 {
1005 object->desk->setCurrentLayer (get_object_by_name (object->desk, layerstr));
1006 return TRUE;
1007 }
1009 gchar **
1010 document_interface_layer_get_all (DocumentInterface *object)
1011 {
1012 //FIXME: implement.
1013 return NULL;
1014 }
1016 gboolean
1017 document_interface_layer_change_level (DocumentInterface *object,
1018 gchar *cmd, GError **error)
1019 {
1020 if (strcmp(cmd, "raise") == 0)
1021 return dbus_call_verb (object, SP_VERB_LAYER_RAISE, error);
1022 if (strcmp(cmd, "lower") == 0)
1023 return dbus_call_verb (object, SP_VERB_LAYER_LOWER, error);
1024 if ((strcmp(cmd, "to_top") == 0) || (strcmp(cmd, "to_front") == 0))
1025 return dbus_call_verb (object, SP_VERB_LAYER_TO_TOP, error);
1026 if ((strcmp(cmd, "to_bottom") == 0) || (strcmp(cmd, "to_back") == 0))
1027 return dbus_call_verb (object, SP_VERB_LAYER_TO_BOTTOM, error);
1028 return TRUE;
1029 }
1031 gboolean
1032 document_interface_layer_next (DocumentInterface *object, GError **error)
1033 {
1034 return dbus_call_verb (object, SP_VERB_LAYER_NEXT, error);
1035 }
1037 gboolean
1038 document_interface_layer_previous (DocumentInterface *object, GError **error)
1039 {
1040 return dbus_call_verb (object, SP_VERB_LAYER_PREV, error);
1041 }