X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=inline;f=src%2Fextension%2Fdbus%2Fdocument-interface.cpp;h=e2d7a41a2e3c01dd8e61bb485d966d49c543b249;hb=989fc06869090cc6b38cb54c4f3194009addd260;hp=914303a91a3e7401632b7d9050ec6865a9fea615;hpb=19efd0181486d2d0802a9b3d1dac269f7994f4f6;p=inkscape.git diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index 914303a91..e2d7a41a2 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -1,3 +1,20 @@ +/* + * This is where the implementation of the DBus based document API lives. + * All the methods in here (except in the helper section) are + * designed to be called remotly via DBus. application-interface.cpp + * has the methods used to connect to the bus and get a document instance. + * + * Documentation for these methods is in document-interface.xml + * which is the "gold standard" as to how the interface should work. + * + * Authors: + * Soren Berg + * + * Copyright (C) 2009 Soren Berg + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + #include "document-interface.h" #include @@ -32,29 +49,84 @@ #include "print.h" //IO +#include "live_effects/parameter/text.h" //text +#include "display/canvas-text.h" //text + +//#include "2geom/svg-path-parser.h" //get_node_coordinates + /**************************************************************************** HELPER / SHORTCUT FUNCTIONS ****************************************************************************/ -const gchar* intToCString(int i) +/* + * This function or the one below it translates the user input for an object + * into Inkscapes internal representation. It is called by almost every + * method so it should be as fast as possible. + * + * (eg turns "rect2234" to an SPObject or Inkscape::XML::Node) + * + * If the internal representation changes (No more 'id' attributes) this is the + * place to adjust things. + */ +Inkscape::XML::Node * +get_repr_by_name (SPDesktop *desk, gchar *name, GError **error) { - std::stringstream ss; - ss << i; - return ss.str().c_str(); + /* ALTERNATIVE (is this faster if only repr is needed?) + Inkscape::XML::Node *node = sp_repr_lookup_name((doc->root)->repr, name); + */ + Inkscape::XML::Node * node = sp_desktop_document(desk)->getObjectById(name)->repr; + if (!node) + { + g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OBJECT, "Object '%s' not found in document.", name); + return NULL; + } + return node; } +/* + * See comment for get_repr_by_name, above. + */ SPObject * -get_object_by_name (SPDesktop *desk, gchar *name) +get_object_by_name (SPDesktop *desk, gchar *name, GError **error) +{ + SPObject * obj = sp_desktop_document(desk)->getObjectById(name); + if (!obj) + { + g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OBJECT, "Object '%s' not found in document.", name); + return NULL; + } + return obj; +} + +/* + * Tests for NULL strings and throws an appropriate error. + * Every method that takes a string parameter (other than the + * name of an object, that's tested seperatly) should call this. + */ +gboolean +dbus_check_string (gchar *string, GError ** error, const gchar * errorstr) { - return sp_desktop_document(desk)->getObjectById(name); + if (string == NULL) + { + g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OTHER, "%s", errorstr); + return FALSE; + } + return TRUE; } +/* + * This is used to return object values to the user + */ const gchar * get_name_from_object (SPObject * obj) { - return obj->repr->attribute("id"); + return obj->repr->attribute("id"); } +/* + * Some verbs (cut, paste) only work on the active layer. + * This makes sure that the document that is about to recive a command is active. + */ void desktop_ensure_active (SPDesktop* desk) { if (desk != SP_ACTIVE_DESKTOP) @@ -62,11 +134,6 @@ desktop_ensure_active (SPDesktop* desk) { return; } -Inkscape::XML::Node * -document_retrive_node (SPDocument *doc, gchar *name) { - return (doc->getObjectById(name))->repr; -} - gdouble selection_get_center_x (Inkscape::Selection *sel){ NRRect *box = g_new(NRRect, 1);; @@ -80,17 +147,34 @@ selection_get_center_y (Inkscape::Selection *sel){ box = sel->boundsInDocument(box); return box->y0 + ((box->y1 - box->y0)/2); } -//move_to etc + +/* + * This function is used along with selection_restore to + * take advantage of functionality provided by a selection + * for a single object. + * + * It saves the current selection and sets the selection to + * the object specified. Any selection verb can be used on the + * object and then selection_restore is called, restoring the + * original selection. + * + * This should be mostly transparent to the user who need never + * know we never bothered to implement it seperatly. Although + * they might see the selection box flicker if used in a loop. + */ const GSList * -selection_swap(SPDesktop *desk, gchar *name) +selection_swap(SPDesktop *desk, gchar *name, GError **error) { Inkscape::Selection *sel = sp_desktop_selection(desk); const GSList *oldsel = g_slist_copy((GSList *)sel->list()); - sel->set(get_object_by_name(desk, name)); + sel->set(get_object_by_name(desk, name, error)); return oldsel; } +/* + * See selection_swap, above + */ void selection_restore(SPDesktop *desk, const GSList * oldsel) { @@ -98,19 +182,25 @@ selection_restore(SPDesktop *desk, const GSList * oldsel) sel->setList(oldsel); } +/* + * Shortcut for creating a Node. + */ Inkscape::XML::Node * -dbus_create_node (SPDesktop *desk, gboolean isrect) +dbus_create_node (SPDesktop *desk, const gchar *type) { SPDocument * doc = sp_desktop_document (desk); Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); - gchar *type; - if (isrect) - type = (gchar *)"svg:rect"; - else - type = (gchar *)"svg:path"; + return xml_doc->createElement(type); } +/* + * Called by the shape creation functions. Gets the default style for the doc + * or sets it arbitrarily if none. + * + * There is probably a better way to do this (use the shape tools default styles) + * but I'm not sure how. + */ gchar * finish_create_shape (DocumentInterface *object, GError **error, Inkscape::XML::Node *newNode, gchar *desc) { @@ -129,30 +219,43 @@ finish_create_shape (DocumentInterface *object, GError **error, Inkscape::XML::N if (object->updates) sp_document_done(sp_desktop_document(object->desk), 0, (gchar *)desc); - else - document_interface_pause_updates(object, error); + //else + //document_interface_pause_updates(object, error); return strdup(newNode->attribute("id")); } +/* + * This is the code used internally to call all the verbs. + * + * It handles error reporting and update pausing (which needs some work.) + * This is a good place to improve efficiency as it is called a lot. + * + * document_interface_call_verb is similar but is called by the user. + */ gboolean dbus_call_verb (DocumentInterface *object, int verbid, GError **error) { SPDesktop *desk2 = object->desk; - + desktop_ensure_active (desk2); + if ( desk2 ) { Inkscape::Verb *verb = Inkscape::Verb::get( verbid ); if ( verb ) { SPAction *action = verb->get_action(desk2); if ( action ) { + //if (!object->updates) + //document_interface_pause_updates (object, error); sp_action_perform( action, NULL ); - if (object->updates) { + if (object->updates) sp_document_done(sp_desktop_document(desk2), verb->get_code(), g_strdup(verb->get_tip())); - } + //if (!object->updates) + //document_interface_pause_updates (object, error); return TRUE; } } } + g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_VERB, "Verb failed to execute"); return FALSE; } @@ -190,6 +293,46 @@ document_interface_new (void) return (DocumentInterface*)g_object_new (TYPE_DOCUMENT_INTERFACE, NULL); } +/* + * Error stuff... + * + * To add a new error type, edit here and in the .h InkscapeError enum. + */ +GQuark +inkscape_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("inkscape_error"); + + return quark; +} + +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +inkscape_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) + { + static const GEnumValue values[] = + { + + ENUM_ENTRY (INKSCAPE_ERROR_SELECTION, "Incompatible_Selection"), + ENUM_ENTRY (INKSCAPE_ERROR_OBJECT, "Incompatible_Object"), + ENUM_ENTRY (INKSCAPE_ERROR_VERB, "Failed_Verb"), + ENUM_ENTRY (INKSCAPE_ERROR_OTHER, "Generic_Error"), + { 0, 0, 0 } + }; + + etype = g_enum_register_static ("InkscapeError", values); + } + + return etype; +} + /**************************************************************************** MISC FUNCTIONS ****************************************************************************/ @@ -201,7 +344,7 @@ document_interface_delete_all (DocumentInterface *object, GError **error) return TRUE; } -void +gboolean document_interface_call_verb (DocumentInterface *object, gchar *verbid, GError **error) { SPDesktop *desk2 = object->desk; @@ -218,6 +361,8 @@ document_interface_call_verb (DocumentInterface *object, gchar *verbid, GError * } } } + g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_VERB, "Verb '%s' failed to execute or was not found.", verbid); + return FALSE; } @@ -231,7 +376,7 @@ document_interface_rectangle (DocumentInterface *object, int x, int y, { - Inkscape::XML::Node *newNode = dbus_create_node(object->desk, TRUE); + Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:rect"); sp_repr_set_int(newNode, "x", x); //could also use newNode->setAttribute() sp_repr_set_int(newNode, "y", y); sp_repr_set_int(newNode, "width", width); @@ -243,7 +388,7 @@ gchar* document_interface_ellipse_center (DocumentInterface *object, int cx, int cy, int rx, int ry, GError **error) { - Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE); + Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:path"); newNode->setAttribute("sodipodi:type", "arc"); sp_repr_set_int(newNode, "sodipodi:cx", cx); sp_repr_set_int(newNode, "sodipodi:cy", cy); @@ -258,7 +403,7 @@ document_interface_polygon (DocumentInterface *object, int cx, int cy, GError **error) { gdouble rot = ((rotation / 180.0) * 3.14159265) - ( 3.14159265 / 2.0); - Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE); + Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:path"); newNode->setAttribute("inkscape:flatsided", "true"); newNode->setAttribute("sodipodi:type", "star"); sp_repr_set_int(newNode, "sodipodi:cx", cx); @@ -279,7 +424,7 @@ document_interface_star (DocumentInterface *object, int cx, int cy, int r1, int r2, int sides, gdouble rounded, gdouble arg1, gdouble arg2, GError **error) { - Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE); + Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:path"); newNode->setAttribute("inkscape:flatsided", "false"); newNode->setAttribute("sodipodi:type", "star"); sp_repr_set_int(newNode, "sodipodi:cx", cx); @@ -308,11 +453,10 @@ gchar* document_interface_line (DocumentInterface *object, int x, int y, int x2, int y2, GError **error) { - Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE); + Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:path"); std::stringstream out; - printf("X2: %d\nY2 %d\n", x2, y2); - out << "m " << x << "," << y << " " << x2 << "," << y2; - printf ("PATH: %s\n", out.str().c_str()); + // Not sure why this works. + out << "m " << x << "," << y << " " << x2 - x << "," << y2 - y; newNode->setAttribute("d", out.str().c_str()); return finish_create_shape (object, error, newNode, (gchar *)"create line"); } @@ -321,7 +465,7 @@ gchar* document_interface_spiral (DocumentInterface *object, int cx, int cy, int r, int revolutions, GError **error) { - Inkscape::XML::Node *newNode = dbus_create_node(object->desk, FALSE); + Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:path"); newNode->setAttribute("sodipodi:type", "spiral"); sp_repr_set_int(newNode, "sodipodi:cx", cx); sp_repr_set_int(newNode, "sodipodi:cy", cy); @@ -331,15 +475,46 @@ document_interface_spiral (DocumentInterface *object, int cx, int cy, sp_repr_set_int(newNode, "sodipodi:argument", 0); sp_repr_set_int(newNode, "sodipodi:expansion", 1); gchar * retval = finish_create_shape (object, error, newNode, (gchar *)"create spiral"); - newNode->setAttribute("style", "fill:none"); + //Makes sure there is no fill for spirals by default. + gchar* newString = g_strconcat(newNode->attribute("style"), ";fill:none", NULL); + newNode->setAttribute("style", newString); + g_free(newString); return retval; } -gchar* -document_interface_text (DocumentInterface *object, gchar *text, GError **error) +gboolean +document_interface_text (DocumentInterface *object, int x, int y, gchar *text, GError **error) { - //FIXME: implement. - return NULL; + //FIXME: Not selectable (aka broken). Needs to be rewritten completely. + + SPDesktop *desktop = object->desk; + SPCanvasText * canvas_text = (SPCanvasText *) sp_canvastext_new(sp_desktop_tempgroup(desktop), desktop, Geom::Point(0,0), ""); + sp_canvastext_set_text (canvas_text, text); + sp_canvastext_set_coords (canvas_text, x, y); + + return TRUE; +} + +gchar * +document_interface_image (DocumentInterface *object, int x, int y, gchar *filename, GError **error) +{ + gchar * uri = g_filename_to_uri (filename, FALSE, error); + if (!uri) + return FALSE; + + Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:image"); + sp_repr_set_int(newNode, "x", x); + sp_repr_set_int(newNode, "y", y); + newNode->setAttribute("xlink:href", uri); + + object->desk->currentLayer()->appendChildRepr(newNode); + object->desk->currentLayer()->updateRepr(); + + if (object->updates) + sp_document_done(sp_desktop_document(object->desk), 0, "Imported bitmap."); + + //g_free(uri); + return strdup(newNode->attribute("id")); } gchar* @@ -355,8 +530,8 @@ document_interface_node (DocumentInterface *object, gchar *type, GError **error) if (object->updates) sp_document_done(sp_desktop_document(object->desk), 0, (gchar *)"created empty node"); - else - document_interface_pause_updates(object, error); + //else + //document_interface_pause_updates(object, error); return strdup(newNode->attribute("id")); } @@ -408,7 +583,7 @@ gboolean document_interface_document_resize_to_fit_selection (DocumentInterface *object, GError **error) { - dbus_call_verb (object, SP_VERB_FIT_CANVAS_TO_SELECTION, error); + return dbus_call_verb (object, SP_VERB_FIT_CANVAS_TO_SELECTION, error); return TRUE; } @@ -420,56 +595,72 @@ gboolean document_interface_set_attribute (DocumentInterface *object, char *shape, char *attribute, char *newval, GError **error) { - Inkscape::XML::Node *newNode = get_object_by_name(object->desk, shape)->repr; + Inkscape::XML::Node *newNode = get_repr_by_name(object->desk, shape, error); /* ALTERNATIVE (is this faster?) Inkscape::XML::Node *newnode = sp_repr_lookup_name((doc->root)->repr, name); */ - if (newNode) - { - newNode->setAttribute(attribute, newval, TRUE); - return TRUE; - } - return FALSE; + if (!dbus_check_string(newval, error, "New value string was empty.")) + return FALSE; + + if (!newNode) + return FALSE; + + newNode->setAttribute(attribute, newval, TRUE); + return TRUE; } -void +gboolean document_interface_set_int_attribute (DocumentInterface *object, char *shape, char *attribute, int newval, GError **error) { - Inkscape::XML::Node *newNode = get_object_by_name (object->desk, shape)->repr; - if (newNode) - sp_repr_set_int (newNode, attribute, newval); + Inkscape::XML::Node *newNode = get_repr_by_name (object->desk, shape, error); + if (!newNode) + return FALSE; + + sp_repr_set_int (newNode, attribute, newval); + return TRUE; } -void +gboolean document_interface_set_double_attribute (DocumentInterface *object, char *shape, char *attribute, double newval, GError **error) { - Inkscape::XML::Node *newNode = get_object_by_name (object->desk, shape)->repr; - if (newNode) - sp_repr_set_svg_double (newNode, attribute, newval); + Inkscape::XML::Node *newNode = get_repr_by_name (object->desk, shape, error); + + if (!dbus_check_string (attribute, error, "New value string was empty.")) + return FALSE; + if (!newNode) + return FALSE; + + sp_repr_set_svg_double (newNode, attribute, newval); + return TRUE; } gchar * document_interface_get_attribute (DocumentInterface *object, char *shape, char *attribute, GError **error) { - Inkscape::XML::Node *newNode = get_object_by_name(object->desk, shape)->repr; + Inkscape::XML::Node *newNode = get_repr_by_name(object->desk, shape, error); - if (newNode) - return g_strdup(newNode->attribute(attribute)); - return FALSE; + if (!dbus_check_string (attribute, error, "Attribute name empty.")) + return NULL; + if (!newNode) + return NULL; + + return g_strdup(newNode->attribute(attribute)); } gboolean document_interface_move (DocumentInterface *object, gchar *name, gdouble x, gdouble y, GError **error) { - const GSList *oldsel = selection_swap(object->desk, name); + const GSList *oldsel = selection_swap(object->desk, name, error); + if (!oldsel) + return FALSE; sp_selection_move (object->desk, x, 0 - y); selection_restore(object->desk, oldsel); return TRUE; @@ -479,7 +670,9 @@ gboolean document_interface_move_to (DocumentInterface *object, gchar *name, gdouble x, gdouble y, GError **error) { - const GSList *oldsel = selection_swap(object->desk, name); + const GSList *oldsel = selection_swap(object->desk, name, error); + if (!oldsel) + return FALSE; Inkscape::Selection * sel = sp_desktop_selection(object->desk); sp_selection_move (object->desk, x - selection_get_center_x(sel), 0 - (y - selection_get_center_y(sel))); @@ -491,7 +684,9 @@ gboolean document_interface_object_to_path (DocumentInterface *object, char *shape, GError **error) { - const GSList *oldsel = selection_swap(object->desk, shape); + const GSList *oldsel = selection_swap(object->desk, shape, error); + if (!oldsel) + return FALSE; dbus_call_verb (object, SP_VERB_OBJECT_TO_CURVE, error); selection_restore(object->desk, oldsel); return TRUE; @@ -500,10 +695,15 @@ document_interface_object_to_path (DocumentInterface *object, gchar * document_interface_get_path (DocumentInterface *object, char *pathname, GError **error) { - Inkscape::XML::Node *node = document_retrive_node (sp_desktop_document (object->desk), pathname); - if (node == NULL || node->attribute("d") == NULL) { - g_set_error(error, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION, "Object is not a path or does not exist."); - return FALSE; + Inkscape::XML::Node *node = get_repr_by_name(object->desk, pathname, error); + + if (!node) + return NULL; + + if (node->attribute("d") == NULL) + { + g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OBJECT, "Object is not a path."); + return NULL; } return strdup(node->attribute("d")); } @@ -530,8 +730,15 @@ gboolean document_interface_modify_css (DocumentInterface *object, gchar *shape, gchar *cssattrb, gchar *newval, GError **error) { + // Doesn't like non-variable strings for some reason. gchar style[] = "style"; - Inkscape::XML::Node *node = get_object_by_name(object->desk, shape)->repr; + Inkscape::XML::Node *node = get_repr_by_name(object->desk, shape, error); + + if (!dbus_check_string (cssattrb, error, "Attribute string empty.")) + return FALSE; + if (!node) + return FALSE; + SPCSSAttr * oldstyle = sp_repr_css_attr (node, style); sp_repr_css_set_property(oldstyle, cssattrb, newval); node->setAttribute (style, sp_repr_css_write_string (oldstyle), TRUE); @@ -542,11 +749,18 @@ gboolean document_interface_merge_css (DocumentInterface *object, gchar *shape, gchar *stylestring, GError **error) { + gchar style[] = "style"; + + Inkscape::XML::Node *node = get_repr_by_name(object->desk, shape, error); + + if (!dbus_check_string (stylestring, error, "Style string empty.")) + return FALSE; + if (!node) + return FALSE; + SPCSSAttr * newstyle = sp_repr_css_attr_new(); sp_repr_css_attr_add_from_string (newstyle, stylestring); - gchar style[] = "style"; - Inkscape::XML::Node *node = get_object_by_name(object->desk, shape)->repr; SPCSSAttr * oldstyle = sp_repr_css_attr (node, style); sp_repr_css_merge(oldstyle, newstyle); @@ -554,28 +768,56 @@ document_interface_merge_css (DocumentInterface *object, gchar *shape, return TRUE; } +gboolean +document_interface_set_color (DocumentInterface *object, gchar *shape, + int r, int g, int b, gboolean fill, GError **error) +{ + gchar style[15]; + if (r<0 || r>255 || g<0 || g>255 || b<0 || b>255) + { + g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OTHER, "Given (%d,%d,%d). All values must be between 0-255 inclusive.", r, g, b); + return FALSE; + } + + if (fill) + snprintf(style, 15, "fill:#%.2x%.2x%.2x", r, g, b); + else + snprintf(style, 15, "stroke:#%.2x%.2x%.2x", r, g, b); + + if (strcmp(shape, "document") == 0) + return document_interface_document_merge_css (object, style, error); + + return document_interface_merge_css (object, shape, style, error); +} + gboolean document_interface_move_to_layer (DocumentInterface *object, gchar *shape, gchar *layerstr, GError **error) { - const GSList *oldsel = selection_swap(object->desk, shape); + const GSList *oldsel = selection_swap(object->desk, shape, error); + if (!oldsel) + return FALSE; + document_interface_selection_move_to_layer(object, layerstr, error); selection_restore(object->desk, oldsel); return TRUE; } -DBUSPoint ** +GArray * document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape) { //FIXME: Needs lot's of work. /* - Inkscape::XML::Node *node = document_retrive_node (sp_desktop_document (object->desk), pathname); - if (node == NULL || node->attribute("d") == NULL) { - g_set_error(error, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION, "Object is not a path or does not exist."); + Inkscape::XML::Node *shapenode = get_repr_by_name (object->desk, shape, error); + if (shapenode == NULL || shapenode->attribute("d") == NULL) { return FALSE; } - //char * path = strdup(node->attribute("d")); -*/ + char * path = strdup(shapenode->attribute("d")); + printf("PATH: %s\n", path); + + Geom::parse_svg_path (path); + return NULL; + */ return NULL; } @@ -630,6 +872,16 @@ document_interface_save_as (DocumentInterface *object, //SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::NORMAL_MESSAGE, "Document saved."); return true; } + +gboolean +document_interface_mark_as_unmodified (DocumentInterface *object, GError **error) +{ + SPDocument * doc = sp_desktop_document(object->desk); + if (doc) + doc->modified_since_save = FALSE; + return TRUE; +} + /* gboolean document_interface_print_to_file (DocumentInterface *object, GError **error) @@ -671,24 +923,34 @@ document_interface_redo (DocumentInterface *object, GError **error) /**************************************************************************** - UPDATE FUNCTIONS + UPDATE FUNCTIONS + FIXME: This would work better by adding a flag to SPDesktop to prevent + updating but that would be very intrusive so for now there is a workaround. + Need to make sure it plays well with verbs because they are used so much. ****************************************************************************/ void document_interface_pause_updates (DocumentInterface *object, GError **error) { object->updates = FALSE; - sp_desktop_document(object->desk)->root->uflags = FALSE; - sp_desktop_document(object->desk)->root->mflags = FALSE; + object->desk->canvas->drawing_disabled = 1; + //object->desk->canvas->need_redraw = 0; + //object->desk->canvas->need_repick = 0; + //sp_desktop_document(object->desk)->root->uflags = FALSE; + //sp_desktop_document(object->desk)->root->mflags = FALSE; } void document_interface_resume_updates (DocumentInterface *object, GError **error) { object->updates = TRUE; - sp_desktop_document(object->desk)->root->uflags = TRUE; - sp_desktop_document(object->desk)->root->mflags = TRUE; + object->desk->canvas->drawing_disabled = 0; + //object->desk->canvas->need_redraw = 1; + //object->desk->canvas->need_repick = 1; + //sp_desktop_document(object->desk)->root->uflags = TRUE; + //sp_desktop_document(object->desk)->root->mflags = TRUE; //sp_desktop_document(object->desk)->_updateDocument(); + //FIXME: use better verb than rect. sp_document_done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions"); } @@ -697,57 +959,48 @@ document_interface_update (DocumentInterface *object, GError **error) { sp_desktop_document(object->desk)->root->uflags = TRUE; sp_desktop_document(object->desk)->root->mflags = TRUE; + object->desk->enableInteraction(); sp_desktop_document(object->desk)->_updateDocument(); + object->desk->disableInteraction(); sp_desktop_document(object->desk)->root->uflags = FALSE; sp_desktop_document(object->desk)->root->mflags = FALSE; //sp_document_done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions"); } /**************************************************************************** - SELECTION FUNCTIONS FIXME: use call_verb where appropriate. + SELECTION FUNCTIONS FIXME: use call_verb where appropriate (once update system is tested.) ****************************************************************************/ gboolean -document_interface_selection_get (DocumentInterface *object, GSList const * listy, GError **error) +document_interface_selection_get (DocumentInterface *object, char ***out, GError **error) { Inkscape::Selection * sel = sp_desktop_selection(object->desk); GSList const *oldsel = sel->list(); int size = g_slist_length((GSList *) oldsel); - int i; - printf("premalloc\n"); - gchar **list = (gchar **)malloc(size); - printf("postmalloc\n"); - for(i = 0; i < size; i++) - list[i] = (gchar *)malloc(sizeof(gchar) * 10); - printf("postmalloc2\n"); - i=0; - printf("prealloc\n"); + + *out = g_new0 (char *, size + 1); + + int i = 0; for (GSList const *iter = oldsel; iter != NULL; iter = iter->next) { - strcpy (list[i], SP_OBJECT(iter->data)->repr->attribute("id")); + (*out)[i] = g_strdup(SP_OBJECT(iter->data)->repr->attribute("id")); i++; } - printf("postalloc\n"); - for (i=0; idesk, name, error); + if (!obj) return FALSE; - SPDocument * doc = sp_desktop_document (object->desk); + Inkscape::Selection *selection = sp_desktop_selection(object->desk); - /* WORKS - Inkscape::XML::Node *repr2 = sp_repr_lookup_name((doc->root)->repr, name); - selection->add(repr2, TRUE); - */ - selection->add(doc->getObjectById(name)); + + selection->add(obj); return TRUE; } @@ -755,8 +1008,11 @@ gboolean document_interface_selection_add_list (DocumentInterface *object, char **names, GError **error) { - //FIXME: implement. - return FALSE; + int i; + for (i=0;names[i] != NULL;i++) { + document_interface_selection_add(object, names[i], error); + } + return TRUE; } gboolean @@ -772,11 +1028,9 @@ gboolean document_interface_selection_set_list (DocumentInterface *object, gchar **names, GError **error) { - //FIXME: broken array passing. sp_desktop_selection(object->desk)->clear(); int i; - for (i=0;((i<30000) && (names[i] != NULL));i++) { - printf("NAME: %s\n", names[i]); + for (i=0;names[i] != NULL;i++) { document_interface_selection_add(object, names[i], error); } return TRUE; @@ -793,8 +1047,8 @@ document_interface_selection_rotate (DocumentInterface *object, int angle, GErro gboolean document_interface_selection_delete (DocumentInterface *object, GError **error) { - sp_selection_delete (object->desk); - return TRUE; + //sp_selection_delete (object->desk); + return dbus_call_verb (object, SP_VERB_EDIT_DELETE, error); } gboolean @@ -807,16 +1061,16 @@ document_interface_selection_clear (DocumentInterface *object, GError **error) gboolean document_interface_select_all (DocumentInterface *object, GError **error) { - sp_edit_select_all (object->desk); - return TRUE; + //sp_edit_select_all (object->desk); + return dbus_call_verb (object, SP_VERB_EDIT_SELECT_ALL, error); } gboolean document_interface_select_all_in_all_layers(DocumentInterface *object, GError **error) { - sp_edit_select_all_in_all_layers (object->desk); - return TRUE; + //sp_edit_select_all_in_all_layers (object->desk); + return dbus_call_verb (object, SP_VERB_EDIT_SELECT_ALL_IN_ALL_LAYERS, error); } gboolean @@ -831,48 +1085,66 @@ document_interface_selection_box (DocumentInterface *object, int x, int y, gboolean document_interface_selection_invert (DocumentInterface *object, GError **error) { - sp_edit_invert (object->desk); - return TRUE; + //sp_edit_invert (object->desk); + return dbus_call_verb (object, SP_VERB_EDIT_INVERT, error); } gboolean document_interface_selection_group (DocumentInterface *object, GError **error) { - sp_selection_group (object->desk); - return TRUE; + //sp_selection_group (object->desk); + return dbus_call_verb (object, SP_VERB_SELECTION_GROUP, error); } gboolean document_interface_selection_ungroup (DocumentInterface *object, GError **error) { - sp_selection_ungroup (object->desk); - return TRUE; + //sp_selection_ungroup (object->desk); + return dbus_call_verb (object, SP_VERB_SELECTION_UNGROUP, error); } gboolean document_interface_selection_cut (DocumentInterface *object, GError **error) { - sp_selection_cut (object->desk); - return TRUE; + //desktop_ensure_active (object->desk); + //sp_selection_cut (object->desk); + return dbus_call_verb (object, SP_VERB_EDIT_CUT, error); } + gboolean document_interface_selection_copy (DocumentInterface *object, GError **error) { - desktop_ensure_active (object->desk); - sp_selection_copy (); - return TRUE; + //desktop_ensure_active (object->desk); + //sp_selection_copy (); + return dbus_call_verb (object, SP_VERB_EDIT_COPY, error); } +/* gboolean document_interface_selection_paste (DocumentInterface *object, GError **error) { desktop_ensure_active (object->desk); + if (!object->updates) + document_interface_pause_updates (object, error); sp_selection_paste (object->desk, TRUE); + if (!object->updates) + document_interface_pause_updates (object, error); return TRUE; + //return dbus_call_verb (object, SP_VERB_EDIT_PASTE, error); +} +*/ +gboolean +document_interface_selection_paste (DocumentInterface *object, GError **error) +{ + return dbus_call_verb (object, SP_VERB_EDIT_PASTE, error); } gboolean document_interface_selection_scale (DocumentInterface *object, gdouble grow, GError **error) { Inkscape::Selection *selection = sp_desktop_selection(object->desk); + if (!selection) + { + return FALSE; + } sp_selection_scale (selection, grow); return TRUE; } @@ -891,7 +1163,6 @@ document_interface_selection_move_to (DocumentInterface *object, gdouble x, gdou Geom::OptRect sel_bbox = sel->bounds(); if (sel_bbox) { - //Geom::Point m( (object->desk)->point() - sel_bbox->midpoint() ); Geom::Point m( x - selection_get_center_x(sel) , 0 - (y - selection_get_center_y(sel)) ); sp_selection_move_relative(sel, m, true); } @@ -899,6 +1170,8 @@ document_interface_selection_move_to (DocumentInterface *object, gdouble x, gdou } //FIXME: does not paste in new layer. +// This needs to use lower level cut_impl and paste_impl (messy) +// See the built-in sp_selection_to_next_layer and duplicate. gboolean document_interface_selection_move_to_layer (DocumentInterface *object, gchar *layerstr, GError **error) @@ -911,9 +1184,12 @@ document_interface_selection_move_to_layer (DocumentInterface *object, if (selection->isEmpty()) return FALSE; - SPObject *next = get_object_by_name(object->desk, layerstr); + SPObject *next = get_object_by_name(object->desk, layerstr, error); + + if (!next) + return FALSE; - if (next && (strcmp("layer", (next->repr)->attribute("inkscape:groupmode")) == 0)) { + if (strcmp("layer", (next->repr)->attribute("inkscape:groupmode")) == 0) { sp_selection_cut(dt); @@ -924,11 +1200,23 @@ document_interface_selection_move_to_layer (DocumentInterface *object, return TRUE; } -gboolean +GArray * document_interface_selection_get_center (DocumentInterface *object) { - //FIXME: implement: pass struct. - return FALSE; + Inkscape::Selection * sel = sp_desktop_selection(object->desk); + + if (sel) + { + gdouble x = selection_get_center_x(sel); + gdouble y = selection_get_center_y(sel); + GArray * intArr = g_array_new (TRUE, TRUE, sizeof(double)); + + g_array_append_val (intArr, x); + g_array_append_val (intArr, y); + return intArr; + } + + return NULL; } gboolean @@ -942,7 +1230,6 @@ gchar * document_interface_selection_combine (DocumentInterface *object, gchar *cmd, GError **error) { - if (strcmp(cmd, "union") == 0) dbus_call_verb (object, SP_VERB_SELECTION_UNION, error); else if (strcmp(cmd, "intersection") == 0) @@ -951,13 +1238,20 @@ document_interface_selection_combine (DocumentInterface *object, gchar *cmd, dbus_call_verb (object, SP_VERB_SELECTION_DIFF, error); else if (strcmp(cmd, "exclusion") == 0) dbus_call_verb (object, SP_VERB_SELECTION_SYMDIFF, error); - else if (strcmp(cmd, "division") == 0) - dbus_call_verb (object, SP_VERB_SELECTION_CUT, error); else return NULL; - //FIXME: this WILL cause problems with division - return g_strdup((sp_desktop_selection(object->desk)->singleRepr())->attribute("id")); + if (sp_desktop_selection(object->desk)->singleRepr() != NULL) + return g_strdup((sp_desktop_selection(object->desk)->singleRepr())->attribute("id")); + return NULL; +} + +gboolean +document_interface_selection_divide (DocumentInterface *object, char ***out, GError **error) +{ + dbus_call_verb (object, SP_VERB_SELECTION_CUT, error); + + return document_interface_selection_get (object, out, error); } gboolean @@ -992,7 +1286,12 @@ gboolean document_interface_layer_set (DocumentInterface *object, gchar *layerstr, GError **error) { - object->desk->setCurrentLayer (get_object_by_name (object->desk, layerstr)); + SPObject * obj = get_object_by_name (object->desk, layerstr, error); + + if (!obj) + return FALSE; + + object->desk->setCurrentLayer (obj); return TRUE; }