Code

apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
authorjohanengelen <johanengelen@users.sourceforge.net>
Tue, 9 Oct 2007 18:05:31 +0000 (18:05 +0000)
committerjohanengelen <johanengelen@users.sourceforge.net>
Tue, 9 Oct 2007 18:05:31 +0000 (18:05 +0000)
src/marker.cpp
src/marker.h
src/menus-skeleton.h
src/selection-chemistry.cpp
src/selection-chemistry.h
src/verbs.cpp
src/verbs.h

index 1fb7584623320724c76b0c964349b8347e55d10d..5cc63d9d7f0c7303f2c86c7e3cedb44c258124c0 100644 (file)
@@ -26,6 +26,7 @@
 #include "attributes.h"
 #include "marker.h"
 #include "document.h"
+#include "document-private.h"
 
 struct SPMarkerView {
        SPMarkerView *next;
@@ -713,3 +714,37 @@ sp_marker_view_remove (SPMarker *marker, SPMarkerView *view, unsigned int destro
        }
        g_free (view);
 }
+
+const gchar *
+generate_marker (GSList *reprs, NR::Rect bounds, SPDocument *document, NR::Matrix transform, NR::Matrix move)
+{
+    Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document);
+    Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document));
+
+    Inkscape::XML::Node *repr = xml_doc->createElement("svg:marker");
+    repr->setAttribute("markerUnits", "userSpaceOnUse");
+    sp_repr_set_svg_double(repr, "markerWidth", bounds.extent(NR::X));
+    sp_repr_set_svg_double(repr, "markerHeight", bounds.extent(NR::Y));
+
+    repr->setAttribute("orient", "auto");
+
+
+    defsrepr->appendChild(repr);
+    const gchar *mark_id = repr->attribute("id");
+    SPObject *mark_object = document->getObjectById(mark_id);
+
+    for (GSList *i = reprs; i != NULL; i = i->next) {
+            Inkscape::XML::Node *node = (Inkscape::XML::Node *)(i->data);
+        SPItem *copy = SP_ITEM(mark_object->appendChildRepr(node));
+
+        NR::Matrix dup_transform;
+        if (!sp_svg_transform_read (node->attribute("transform"), &dup_transform))
+            dup_transform = NR::identity();
+        dup_transform *= move;
+
+        sp_item_write_transform(copy, SP_OBJECT_REPR(copy), dup_transform);
+    }
+
+    Inkscape::GC::release(repr);
+    return mark_id;
+}
index 1fba52d36b820eafb163a959f914f646880cf302..ef8fcd583c9a0f7b9c9eed2f2b09af563394579d 100644 (file)
@@ -89,5 +89,7 @@ NRArenaItem *sp_marker_show_instance (SPMarker *marker, NRArenaItem *parent,
                                      unsigned int key, unsigned int pos,
                                      NR::Matrix const &base, float linewidth);
 void sp_marker_hide (SPMarker *marker, unsigned int key);
+const gchar *generate_marker (GSList *reprs, NR::Rect bounds, SPDocument *document, NR::Matrix transform, NR::Matrix move);
+
 
 #endif
index 97b9a34ad76e1bdaeac56250a25b625655be3204..71c07e1f946f024ee18e07106384f4a3fcaebd17 100644 (file)
@@ -175,6 +175,7 @@ static char const menus_skeleton[] =
 "           <verb verb-id=\"ObjectsToPattern\" />\n"
 "           <verb verb-id=\"ObjectsFromPattern\" />\n"
 "       </submenu>\n"
+"       <verb verb-id=\"ObjectsToMarker\" />\n"
 "       <separator/>\n"
 "       <verb verb-id=\"SelectionRaise\" />\n"
 "       <verb verb-id=\"SelectionLower\" />\n"
index 0d7654bb1efd8fdcd32b9097162aec3dca176459..ec4f096dd4164290f04695316f792e412ee5c0c6 100644 (file)
@@ -2272,6 +2272,83 @@ sp_select_clone_original()
     }
 }
 
+
+void sp_selection_to_marker(bool apply)
+{
+    SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+    if (desktop == NULL)
+        return;
+
+    SPDocument *doc = sp_desktop_document(desktop);
+    Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
+
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
+
+    // check if something is selected
+    if (selection->isEmpty()) {
+        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to convert to marker."));
+        return;
+    }
+
+    sp_document_ensure_up_to_date(doc);
+    NR::Maybe<NR::Rect> r = selection->bounds();
+    if ( !r || r->isEmpty() ) {
+        return;
+    }
+
+    // calculate the transform to be applied to objects to move them to 0,0
+    NR::Point move_p = NR::Point(0, sp_document_height(doc)) - (r->min() + NR::Point ((r->extent(NR::X))/2, (r->extent(NR::Y))/2));
+    move_p[NR::Y] = -move_p[NR::Y];
+    NR::Matrix move = NR::Matrix (NR::translate (move_p));
+
+    GSList *items = g_slist_copy((GSList *) selection->itemList());
+
+    items = g_slist_sort (items, (GCompareFunc) sp_object_compare_position);
+
+    // bottommost object, after sorting
+    SPObject *parent = SP_OBJECT_PARENT (items->data);
+
+    NR::Matrix parent_transform = sp_item_i2root_affine(SP_ITEM(parent));
+
+    // remember the position of the first item
+    gint pos = SP_OBJECT_REPR (items->data)->position();
+
+    // create a list of duplicates
+    GSList *repr_copies = NULL;
+    for (GSList *i = items; i != NULL; i = i->next) {
+        Inkscape::XML::Node *dup = (SP_OBJECT_REPR (i->data))->duplicate(xml_doc);
+        repr_copies = g_slist_prepend (repr_copies, dup);
+    }
+
+    NR::Rect bounds(desktop->dt2doc(r->min()), desktop->dt2doc(r->max()));
+
+    if (apply) {
+        // delete objects so that their clones don't get alerted; this object will be restored shortly
+        for (GSList *i = items; i != NULL; i = i->next) {
+            SPObject *item = SP_OBJECT (i->data);
+            item->deleteObject (false);
+        }
+    }
+
+    // Hack: Temporarily set clone compensation to unmoved, so that we can move clone-originals
+    // without disturbing clones.
+    // See ActorAlign::on_button_click() in src/ui/dialog/align-and-distribute.cpp
+    int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+    prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+
+    const gchar *mark_id = generate_marker (repr_copies, bounds, doc,
+                                        NR::Matrix(NR::translate(desktop->dt2doc(NR::Point(r->min()[NR::X], r->max()[NR::Y])))) * parent_transform.inverse(), parent_transform * move);
+
+    // restore compensation setting
+    prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
+
+
+    g_slist_free (items);
+
+    sp_document_done (doc, SP_VERB_EDIT_SELECTION_2_MARKER,
+                      _("Objects to marker"));
+}
+
 void
 sp_selection_tile(bool apply)
 {
index a132161ef7ff0e7e463eefafac4ed3ddc66a738c..9313711cf7245868bd84a26fa1b0e08d6beeda6f 100644 (file)
@@ -35,6 +35,8 @@ void sp_selection_clone();
 void sp_selection_unlink();
 void sp_select_clone_original ();
 
+void sp_selection_to_marker(bool apply = true);
+
 void sp_selection_tile(bool apply = true);
 void sp_selection_untile();
 
@@ -127,3 +129,4 @@ SPCycleType SP_CYCLING = SP_CYCLE_FOCUS;
 #endif
 
 
+
index e49263ede6a7dc73be3d59ca0aa4847ef4517c5f..a84500c4406f63a62a31d2a4ac6bd3f0c03dcd74 100644 (file)
@@ -930,6 +930,9 @@ EditVerb::perform(SPAction *action, void *data, void *pdata)
         case SP_VERB_EDIT_CLONE_ORIGINAL:
             sp_select_clone_original();
             break;
+        case SP_VERB_EDIT_SELECTION_2_MARKER:
+            sp_selection_to_marker();
+            break;
         case SP_VERB_EDIT_TILE:
             sp_selection_tile();
             break;
@@ -2218,6 +2221,9 @@ Verb *Verb::_base_verbs[] = {
                  N_("Cut the selected clone's link to its original, turning it into a standalone object"), "edit_unlink_clone"),
     new EditVerb(SP_VERB_EDIT_CLONE_ORIGINAL, "EditCloneOriginal", N_("Select _Original"),
                  N_("Select the object to which the selected clone is linked"), "edit_select_original"),
+    // TRANSLATORS: Convert selection to a line marker
+    new EditVerb(SP_VERB_EDIT_SELECTION_2_MARKER, "ObjectsToMarker", N_("Objects to _Marker"),
+                 N_("Convert selection to a line marker"), NULL),
     // TRANSLATORS: Convert selection to a rectangle with tiled pattern fill
     new EditVerb(SP_VERB_EDIT_TILE, "ObjectsToPattern", N_("Objects to Patter_n"),
                  N_("Convert selection to a rectangle with tiled pattern fill"), NULL),
index 48bf8982553e64ecf4a93d6166b45184be266e00..34a633b2f082a520cadedef4bbf05482b7dc0210 100644 (file)
@@ -67,6 +67,7 @@ enum {
     SP_VERB_EDIT_CLONE,
     SP_VERB_EDIT_UNLINK_CLONE,
     SP_VERB_EDIT_CLONE_ORIGINAL,
+    SP_VERB_EDIT_SELECTION_2_MARKER,
     SP_VERB_EDIT_TILE,
     SP_VERB_EDIT_UNTILE,
     SP_VERB_EDIT_CLEAR_ALL,