Code

Fix LPEs and break mask transform undo
authorKrzysztof Kosiński <tweenk.pl@gmail.com>
Tue, 8 Dec 2009 02:21:08 +0000 (03:21 +0100)
committerKrzysztof Kosiński <tweenk.pl@gmail.com>
Tue, 8 Dec 2009 02:21:08 +0000 (03:21 +0100)
16 files changed:
src/live_effects/effect.cpp
src/live_effects/effect.h
src/live_effects/lpe-constructgrid.cpp
src/live_effects/lpe-constructgrid.h
src/live_effects/lpe-gears.cpp
src/live_effects/lpe-gears.h
src/live_effects/lpe-spiro.cpp
src/live_effects/lpe-spiro.h
src/live_effects/lpe-vonkoch.cpp
src/live_effects/parameter/path.cpp
src/nodepath.cpp
src/ui/tool/multi-path-manipulator.cpp
src/ui/tool/node-tool.cpp
src/ui/tool/path-manipulator.cpp
src/ui/tool/path-manipulator.h
src/ui/tool/shape-record.h

index 9232792f68426f4ba15a6b4f69d63051769ae3dd..dfa9fe6b2b0e2d80c9902f1ea7c6ca361767869b 100644 (file)
@@ -664,13 +664,6 @@ Effect::resetDefaults(SPItem * /*item*/)
     }
 }
 
-void
-Effect::setup_nodepath(Inkscape::NodePath::Path *np)
-{
-    np->helperpath_rgba = 0xff0000ff;
-    np->helperpath_width = 1.0;
-}
-
 void
 Effect::transform_multiply(Geom::Matrix const& postmul, bool set)
 {
index 5d67ed0167f01c89e68257096e5256e96ddc120d..a8d34a2338a864ffd514ea996b63e4a742e12786 100644 (file)
@@ -92,8 +92,6 @@ public:
      */
     virtual void resetDefaults(SPItem * item);
 
-    virtual void setup_nodepath(Inkscape::NodePath::Path *np);
-
     /// /todo: is this method really necessary? it causes UI inconsistensies... (johan)
     virtual void transform_multiply(Geom::Matrix const& postmul, bool set);
 
index 144f4720d92d7d7970ee51967712f951f86b02e9..d83529957986788f76ea107e48dffd63a8f4db60 100644 (file)
@@ -81,13 +81,6 @@ LPEConstructGrid::doEffect_path (std::vector<Geom::Path> const & path_in)
     }
 }
 
-void
-LPEConstructGrid::setup_nodepath(Inkscape::NodePath::Path *np)
-{
-    Effect::setup_nodepath(np);
-    sp_nodepath_make_straight_path(np);
-}
-
 } //namespace LivePathEffect
 } /* namespace Inkscape */
 
index 716960d32d8e0489318abc29e9b597ff1817fb4c..c7e6957941d1fc61dbfff73aaacbdb43467bb1d5 100644 (file)
@@ -27,8 +27,6 @@ public:
 
     virtual std::vector<Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);
 
-    virtual void setup_nodepath(Inkscape::NodePath::Path *np);
-
 private:
     ScalarParam nr_x;
     ScalarParam nr_y;
index e211483c629c8ac619da054a33688d1421c84f18..bd1ce79989fba16c112df5bf2c41a94c2c149ffc 100644 (file)
@@ -261,13 +261,6 @@ LPEGears::doEffect_path (std::vector<Geom::Path> const & path_in)
     return path_out;
 }
 
-void
-LPEGears::setup_nodepath(Inkscape::NodePath::Path *np)
-{
-    Effect::setup_nodepath(np);
-    sp_nodepath_make_straight_path(np);
-}
-
 } // namespace LivePathEffect
 } /* namespace Inkscape */
 
index 4c3a9938bd4385f52111a9f36f17838801f3d24d..bd5e4c4f9728c465e81bc97c3be255054ce0dccb 100644 (file)
@@ -24,8 +24,6 @@ public:
 
     virtual std::vector<Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);
 
-    virtual void setup_nodepath(Inkscape::NodePath::Path *np);
-
 private:
     ScalarParam teeth;
     ScalarParam phi;
index 794fd980e8b1ad06aeef83b3b8914dc343d53555..087b883515a3c27924d001c836239e6597e5a91d 100644 (file)
@@ -115,14 +115,6 @@ LPESpiro::~LPESpiro()
 {
 }
 
-void
-LPESpiro::setup_nodepath(Inkscape::NodePath::Path *np)
-{
-    Effect::setup_nodepath(np);
-    sp_nodepath_show_handles(np, false);
-//    sp_nodepath_show_helperpath(np, false);
-}
-
 void
 LPESpiro::doEffect(SPCurve * curve)
 {
index 7256665a2ea3254ea465bf89c9093c26ef2dbb9f..4fcd9eaaaad081699d8bc48b2bf121d5bbee0c3e 100644 (file)
@@ -24,7 +24,6 @@ public:
 
     virtual LPEPathFlashType pathFlashType() { return SUPPRESS_FLASH; }
 
-    virtual void setup_nodepath(Inkscape::NodePath::Path *np);
     virtual void doEffect(SPCurve * curve);
 
 private:
index 7fd0ac0b493c1ee4258747f7dc005af6829a55f0..b2a5d56fa1184defd1c861f56f06dfe798b94f95 100644 (file)
@@ -19,7 +19,7 @@ void
 VonKochPathParam::param_setup_nodepath(Inkscape::NodePath::Path *np)
 {  
     PathParam::param_setup_nodepath(np);
-    sp_nodepath_make_straight_path(np);
+    //sp_nodepath_make_straight_path(np);
 }
 
 //FIXME: a path is used here instead of 2 points to work around path/point param incompatibility bug.
@@ -27,12 +27,12 @@ void
 VonKochRefPathParam::param_setup_nodepath(Inkscape::NodePath::Path *np)
 {  
     PathParam::param_setup_nodepath(np);
-    sp_nodepath_make_straight_path(np);
+    //sp_nodepath_make_straight_path(np);
 }
 bool
 VonKochRefPathParam::param_readSVGValue(const gchar * strvalue)
 {  
-    std::vector<Geom::Path> old = _pathvector;
+    Geom::PathVector old = _pathvector;
     bool res = PathParam::param_readSVGValue(strvalue);
     if (res && _pathvector.size()==1 && _pathvector.front().size()==1){
         return true;
index 93dfd2667a68da7ed3311b9f8a87217317918781..3a03de51cf6f0735651b0bf155784ab8f4d2d904 100644 (file)
 #include "sp-text.h"
 #include "display/curve.h"
 
+#include "ui/tool/node-tool.h"
+#include "ui/tool/multi-path-manipulator.h"
+#include "ui/tool/shape-record.h"
+
 
 namespace Inkscape {
 
@@ -195,16 +199,33 @@ PathParam::param_newWidget(Gtk::Tooltips * tooltips)
 void
 PathParam::param_editOncanvas(SPItem * item, SPDesktop * dt)
 {
-    // TODO this whole method is broken!
+    using namespace Inkscape::UI;
+
+    // TODO remove the tools_switch atrocity.
+    if (!tools_isactive(dt, TOOLS_NODES)) {
+        tools_switch(dt, TOOLS_NODES);
+    }
+
+    InkNodeTool *nt = static_cast<InkNodeTool*>(dt->event_context);
+    std::set<ShapeRecord> shapes;
+    ShapeRecord r;
+
+    r.role = SHAPE_ROLE_LPE_PARAM;
+    r.edit_transform = Geom::identity(); // TODO this is almost certainly wrong
+    if (!href) {
+        r.item = reinterpret_cast<SPItem*>(param_effect->getLPEObj());
+        r.lpe_key = param_key;
+    } else {
+        r.item = ref.getObject();
+    }
+    shapes.insert(r);
+    nt->_multipath->setItems(shapes);
 }
 
 void
-PathParam::param_setup_nodepath(Inkscape::NodePath::Path *np)
+PathParam::param_setup_nodepath(Inkscape::NodePath::Path *)
 {   
-    // TODO this too!
-    np->show_helperpath = true;
-    np->helperpath_rgba = 0x009000ff;
-    np->helperpath_width = 1.0;
+    // TODO this method should not exist at all!
 }
 
 void
index 8f17ae0133122477bd60f9583553eed265fa15fb..36e4e0d8c5dd6d3e6c44cdfed84c0c4dcc80a8ec 100644 (file)
@@ -352,7 +352,7 @@ Inkscape::NodePath::Path *sp_nodepath_new(SPDesktop *desktop, SPObject *object,
 
             Inkscape::LivePathEffect::Effect* lpe = sp_lpe_item_get_current_lpe(SP_LPE_ITEM(np->object));
             if (lpe) {
-                lpe->setup_nodepath(np);
+                //lpe->setup_nodepath(np);
             }
         } else {
             np->repr_key = g_strdup("d");
index 7c539f6b90850e5140d63337a24bb1a4b4966a0e..aaf7e413cdfd303805a7ec4002502cbca9f6eb7d 100644 (file)
@@ -15,6 +15,7 @@
 #include "desktop.h"
 #include "desktop-handles.h"
 #include "document.h"
+#include "live_effects/lpeobject.h"
 #include "message-stack.h"
 #include "preferences.h"
 #include "sp-path.h"
@@ -131,6 +132,9 @@ void MultiPathManipulator::cleanup()
     }
 }
 
+/** @brief Change the set of items to edit.
+ *
+ * This method attempts to preserve as much of the state as possible. */
 void MultiPathManipulator::setItems(std::set<ShapeRecord> const &s)
 {
     std::set<ShapeRecord> shapes(s);
@@ -165,9 +169,9 @@ void MultiPathManipulator::setItems(std::set<ShapeRecord> const &s)
     // add newly selected items
     for (std::set<ShapeRecord>::iterator i = shapes.begin(); i != shapes.end(); ++i) {
         ShapeRecord const &r = *i;
-        if (!SP_IS_PATH(r.item)) continue;
+        if (!SP_IS_PATH(r.item) && !IS_LIVEPATHEFFECT(r.item)) continue;
         boost::shared_ptr<PathManipulator> newpm(new PathManipulator(_path_data, (SPPath*) r.item,
-            r.edit_transform, _getOutlineColor(r.role)));
+            r.edit_transform, _getOutlineColor(r.role), r.lpe_key));
         newpm->showHandles(_show_handles);
         // always show outlines for clips and masks
         newpm->showOutline(_show_outline || r.role != SHAPE_ROLE_NORMAL);
@@ -241,6 +245,7 @@ void MultiPathManipulator::insertNodes()
 
 void MultiPathManipulator::joinNodes()
 {
+    invokeForAll(&PathManipulator::hideDragPoint);
     // Node join has two parts. In the first one we join two subpaths by fusing endpoints
     // into one. In the second we fuse nodes in each subpath.
     IterPairList joins;
@@ -585,7 +590,7 @@ guint32 MultiPathManipulator::_getOutlineColor(ShapeRole role)
     case SHAPE_ROLE_MASK:
         return prefs->getColor("/tools/nodes/mask_color", 0x0000ffff);
     case SHAPE_ROLE_LPE_PARAM:
-        return prefs->getColor("/tools/nodes/lpe_param_color", 0xb700ffff);
+        return prefs->getColor("/tools/nodes/lpe_param_color", 0x009000ff);
     case SHAPE_ROLE_NORMAL:
     default:
         return prefs->getColor("/tools/nodes/outline_color", 0xff0000ff);
index 31c7227447226d9ba83d3b4b945fdb9aa32ab95e..9103f066f9bc4e65ea7e6733652a6c1a6389ae9c 100644 (file)
@@ -16,6 +16,7 @@
 #include "display/curve.h"
 #include "display/sp-canvas.h"
 #include "document.h"
+#include "live_effects/lpeobject.h"
 #include "message-context.h"
 #include "selection.h"
 #include "shape-editor.h" // temporary!
@@ -187,12 +188,12 @@ void ink_node_tool_setup(SPEventContext *ec)
             sigc::bind<0>(
                 sigc::ptr_fun(&ink_node_tool_selection_changed),
                 nt));
-    nt->_selection_modified_connection.disconnect();
+    /*nt->_selection_modified_connection.disconnect();
     nt->_selection_modified_connection =
         selection->connectModified(
             sigc::hide(sigc::bind<0>(
-                sigc::ptr_fun(&ink_node_tool_selection_changed),
-                nt)));
+                sigc::ptr_fun(&ink_node_tool_selection_modified),
+                nt)));*/
     nt->_mouseover_changed_connection.disconnect();
     nt->_mouseover_changed_connection = 
         Inkscape::UI::ControlPoint::signal_mouseover_change.connect(
@@ -293,28 +294,20 @@ void ink_node_tool_set(SPEventContext *ec, Inkscape::Preferences::Entry *value)
     }
 }
 
-void store_clip_mask_items(SPItem *clipped, SPObject *obj, std::map<SPItem*,
-    std::pair<Geom::Matrix, guint32> > &s, Geom::Matrix const &postm, guint32 color)
-{
-    if (!obj) return;
-    if (SP_IS_GROUP(obj) || SP_IS_OBJECTGROUP(obj)) {
-        //TODO is checking for obj->children != NULL above better?
-        for (SPObject *c = obj->children; c; c = c->next) {
-            store_clip_mask_items(clipped, c, s, postm, color);
-        }
-    } else if (SP_IS_ITEM(obj)) {
-        s.insert(std::make_pair(SP_ITEM(obj),
-            std::make_pair(sp_item_i2d_affine(clipped) * postm, color)));
-    }
-}
-
 /** Recursively collect ShapeRecords */
 void gather_items(InkNodeTool *nt, SPItem *base, SPObject *obj, Inkscape::UI::ShapeRole role,
     std::set<Inkscape::UI::ShapeRecord> &s)
 {
     using namespace Inkscape::UI;
     if (!obj) return;
-    if (role != SHAPE_ROLE_NORMAL && (SP_IS_GROUP(obj) || SP_IS_OBJECTGROUP(obj))) {
+
+    if (SP_IS_PATH(obj) && obj->repr->attribute("inkscape:original-d") != NULL) {
+        ShapeRecord r;
+        r.item = static_cast<SPItem*>(obj);
+        r.edit_transform = Geom::identity(); // TODO wrong?
+        r.role = SHAPE_ROLE_LPE_PARAM;
+        s.insert(r);
+    } else if (role != SHAPE_ROLE_NORMAL && (SP_IS_GROUP(obj) || SP_IS_OBJECTGROUP(obj))) {
         for (SPObject *c = obj->children; c; c = c->next) {
             gather_items(nt, base, c, role, s);
         }
@@ -325,7 +318,6 @@ void gather_items(InkNodeTool *nt, SPItem *base, SPObject *obj, Inkscape::UI::Sh
         // TODO add support for objectBoundingBox
         r.edit_transform = base ? sp_item_i2doc_affine(base) : Geom::identity();
         r.role = role;
-        r.edit_original = false;
         if (s.insert(r).second) {
             // this item was encountered the first time
             if (nt->edit_clipping_paths && item->clip_ref) {
index e9ec78b2e08a51d6e892d7d4ec90421c7207a35c..0ad509a9b473ab06586834a3245c968dd3a967e1 100644 (file)
@@ -26,6 +26,9 @@
 #include "display/curve.h"
 #include "display/canvas-bpath.h"
 #include "document.h"
+#include "live_effects/effect.h"
+#include "live_effects/lpeobject.h"
+#include "live_effects/parameter/path.h"
 #include "sp-path.h"
 #include "helper/geom.h"
 #include "preferences.h"
@@ -59,13 +62,15 @@ public:
     virtual void notifyAttributeChanged(Inkscape::XML::Node &, GQuark attr,
         Util::ptr_shared<char>, Util::ptr_shared<char>)
     {
-        GQuark path_d = g_quark_from_static_string("d");
-        GQuark path_transform = g_quark_from_static_string("transform");
         // do nothing if blocked
         if (_blocked) return;
 
+        GQuark path_d = g_quark_from_static_string("d");
+        GQuark path_transform = g_quark_from_static_string("transform");
+        GQuark lpe_quark = _pm->_lpe_key.empty() ? 0 : g_quark_from_string(_pm->_lpe_key.data());
+
         // only react to "d" (path data) and "transform" attribute changes
-        if (attr == path_d) {
+        if (attr == lpe_quark || attr == path_d) {
             _pm->_externalChange(PATH_CHANGE_D);
         } else if (attr == path_transform) {
             _pm->_externalChange(PATH_CHANGE_TRANSFORM);
@@ -81,22 +86,29 @@ private:
 void build_segment(Geom::PathBuilder &, Node *, Node *);
 
 PathManipulator::PathManipulator(PathSharedData const &data, SPPath *path,
-        Geom::Matrix const &et, guint32 outline_color)
+        Geom::Matrix const &et, guint32 outline_color, Glib::ustring lpe_key)
     : PointManipulator(data.node_data.desktop, *data.node_data.selection)
     , _path_data(data)
     , _path(path)
-    , _spcurve(sp_path_get_curve_for_edit(path))
+    , _spcurve(NULL)
     , _dragpoint(new CurveDragPoint(*this))
     , _observer(new PathManipulatorObserver(this))
     , _edit_transform(et)
     , _show_handles(true)
     , _show_outline(false)
+    , _lpe_key(lpe_key)
 {
     /* Because curve drag point is always created first, it does not cover nodes */
-    _i2d_transform = sp_item_i2d_affine(SP_ITEM(path));
+    if (_lpe_key.empty()) {
+        _i2d_transform = sp_item_i2d_affine(SP_ITEM(path));
+    } else {
+        _i2d_transform = Geom::identity();
+    }
     _d2i_transform = _i2d_transform.inverse();
     _dragpoint->setVisible(false);
 
+    _getGeometry();
+
     _outline = sp_canvas_bpath_new(_path_data.outline_group, NULL);
     sp_canvas_item_hide(_outline);
     sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(_outline), outline_color, 1.0,
@@ -127,7 +139,7 @@ PathManipulator::~PathManipulator()
     if (_path) _path->repr->removeObserver(*_observer);
     delete _observer;
     gtk_object_destroy(_outline);
-    _spcurve->unref();
+    if (_spcurve) _spcurve->unref();
     clear();
 }
 
@@ -163,11 +175,11 @@ void PathManipulator::writeXML()
     if (!_path) return;
     _observer->block();
     if (!empty()) {
-        _path->updateRepr();
-        _path->repr->setAttribute("sodipodi:nodetypes", _createTypeString().data());
+        SP_OBJECT(_path)->updateRepr();
+        _getXMLNode()->setAttribute(_nodetypesKey().data(), _createTypeString().data());
     } else {
         // this manipulator will have to be destroyed right after this call
-        _path->repr->removeObserver(*_observer);
+        _getXMLNode()->removeObserver(*_observer);
         sp_object_ref(_path);
         _path->deleteObject(true, true);
         sp_object_unref(_path);
@@ -333,6 +345,9 @@ void PathManipulator::insertNodes()
 /** Replace contiguous selections of nodes in each subpath with one node. */
 void PathManipulator::weldNodes(NodeList::iterator const &preserve_pos)
 {
+    if (!_num_selected) return;
+    _dragpoint->setVisible(false);
+
     bool pos_valid = preserve_pos;
     for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) {
         SubpathPtr sp = *i;
@@ -458,7 +473,8 @@ void PathManipulator::breakNodes()
 void PathManipulator::deleteNodes(bool keep_shape)
 {
     if (!_num_selected) return;
-
+    hideDragPoint();
+    
     unsigned const samples_per_segment = 10;
     double const t_step = 1.0 / samples_per_segment;
 
@@ -472,7 +488,10 @@ void PathManipulator::deleteNodes(bool keep_shape)
             if (j->selected()) ++num_selected;
             else ++num_unselected;
         }
-        if (num_selected == 0) continue;
+        if (num_selected == 0) {
+            ++i;
+            continue;
+        }
         if (sp->closed() ? (num_unselected < 1) : (num_unselected < 2)) {
             _subpaths.erase(i++);
             continue;
@@ -500,8 +519,8 @@ void PathManipulator::deleteNodes(bool keep_shape)
             // 2. we are deleting at the end or beginning of an open path
             // if !sel_end then sel_beg.prev() must be valid, otherwise the entire subpath
             // would be deleted before we get here
-            if (keep_shape || !sel_end) sel_beg.prev()->setType(NODE_CUSP, false);
-            if (keep_shape || !sel_beg.prev()) sel_end->setType(NODE_CUSP, false);
+            if ((keep_shape || !sel_end) && sel_beg.prev()) sel_beg.prev()->setType(NODE_CUSP, false);
+            if ((keep_shape || !sel_beg.prev()) && sel_end) sel_end->setType(NODE_CUSP, false);
 
             if (keep_shape && sel_beg.prev() && sel_end) {
                 // Fill fit data
@@ -520,7 +539,7 @@ void PathManipulator::deleteNodes(bool keep_shape)
                 // Fill last point
                 bezier_data[num_samples - 1] = sel_end->position();
                 // Compute replacement bezier curve
-                // TODO find out optimal error value
+                // TODO the fitting algorithm sucks - rewrite it to be awesome
                 bezier_fit_cubic(result, bezier_data, num_samples, 0.5);
                 delete[] bezier_data;
 
@@ -544,6 +563,8 @@ void PathManipulator::deleteNodes(bool keep_shape)
 void PathManipulator::deleteSegments()
 {
     if (_num_selected == 0) return;
+    hideDragPoint();
+
     for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end();) {
         SubpathPtr sp = *i;
         bool has_unselected = false;
@@ -702,6 +723,12 @@ void PathManipulator::setControlsTransform(Geom::Matrix const &tnew)
     _createGeometryFromControlPoints();
 }
 
+void PathManipulator::hideDragPoint()
+{
+    _dragpoint->setVisible(false);
+    _dragpoint->setIterator(NodeList::iterator());
+}
+
 /** Insert a node in the segment beginning with the supplied iterator,
  * at the given time value */
 NodeList::iterator PathManipulator::subdivideSegment(NodeList::iterator first, double t)
@@ -749,8 +776,7 @@ void PathManipulator::_externalChange(unsigned type)
 {
     switch (type) {
     case PATH_CHANGE_D: {
-        _spcurve->unref();
-        _spcurve = sp_path_get_curve_for_edit(_path);
+        _getGeometry();
 
         // ugly: stored offsets of selected nodes in a vector
         // vector<bool> should be specialized so that it takes only 1 bit per value
@@ -851,7 +877,7 @@ void PathManipulator::_createControlPointsFromGeometry()
     // we need to set the nodetypes after all the handles are in place,
     // so that pickBestType works correctly
     // TODO maybe migrate to inkscape:node-types?
-    gchar const *nts_raw = _path ? _path->repr->attribute("sodipodi:nodetypes") : 0;
+    gchar const *nts_raw = _path ? _path->repr->attribute(_nodetypesKey().data()) : 0;
     std::string nodetype_string = nts_raw ? nts_raw : "";
     /* Calculate the needed length of the nodetype string.
      * For closed paths, the entry is duplicated for the starting node,
@@ -913,7 +939,7 @@ void PathManipulator::_createGeometryFromControlPoints()
     builder.finish();
     _spcurve->set_pathvector(builder.peek() * (_edit_transform * _i2d_transform).inverse());
     _updateOutline();
-    if (!empty()) sp_shape_set_curve(SP_SHAPE(_path), _spcurve, false);
+    _setGeometry();
 }
 
 /** Build one segment of the geometric representation.
@@ -990,6 +1016,63 @@ void PathManipulator::_updateOutline()
     _hc->unref();
 }
 
+/** Retrieve the geometry of the edited object from the object tree */
+void PathManipulator::_getGeometry()
+{
+    using namespace Inkscape::LivePathEffect;
+    if (!_lpe_key.empty()) {
+        Effect *lpe = LIVEPATHEFFECT(_path)->get_lpe();
+        if (lpe) {
+            PathParam *pathparam = dynamic_cast<PathParam *>(lpe->getParameter(_lpe_key.data()));
+            if (!_spcurve)
+                _spcurve = new SPCurve(pathparam->get_pathvector());
+            else
+                _spcurve->set_pathvector(pathparam->get_pathvector());
+        }
+    } else {
+        if (_spcurve) _spcurve->unref();
+        _spcurve = sp_path_get_curve_for_edit(_path);
+    }
+}
+
+/** Set the geometry of the edited object in the object tree, but do not commit to XML */
+void PathManipulator::_setGeometry()
+{
+    using namespace Inkscape::LivePathEffect;
+    if (empty()) return;
+
+    if (!_lpe_key.empty()) {
+        // LPE brain damage follows - copied from nodepath.cpp
+        // NOTE: if we are editing an LPE param, _path is not actually an SPPath, it is
+        // a LivePathEffectObject.
+        Effect *lpe = LIVEPATHEFFECT(_path)->get_lpe();
+        if (lpe) {
+            PathParam *pathparam = dynamic_cast<PathParam *>(lpe->getParameter(_lpe_key.data()));
+            pathparam->set_new_value(_spcurve->get_pathvector(), false);
+            LIVEPATHEFFECT(_path)->requestModified(SP_OBJECT_MODIFIED_FLAG);
+        }
+    } else {
+        if (_path->repr->attribute("inkscape:original-d"))
+            sp_path_set_original_curve(_path, _spcurve, true, false);
+        else
+            sp_shape_set_curve(SP_SHAPE(_path), _spcurve, false);
+    }
+}
+
+/** LPE brain damage */
+Glib::ustring PathManipulator::_nodetypesKey()
+{
+    if (_lpe_key.empty()) return "sodipodi:nodetypes";
+    return _lpe_key + "-nodetypes";
+}
+
+/** LPE brain damage */
+Inkscape::XML::Node *PathManipulator::_getXMLNode()
+{
+    if (_lpe_key.empty()) return _path->repr;
+    return LIVEPATHEFFECT(_path)->repr;
+}
+
 void PathManipulator::_attachNodeHandlers(Node *node)
 {
     Handle *handles[2] = { node->front(), node->back() };
index 01a2b6cbf5bbc3c756c7d812252e044d69f0508d..e0d8c68ca9490e9668f5dcf280c536f9b42b793d 100644 (file)
@@ -25,6 +25,7 @@
 struct SPCanvasItem;
 
 namespace Inkscape {
+namespace XML { class Node; }
 namespace UI {
 
 class PathManipulator;
@@ -48,8 +49,8 @@ class PathManipulator : public PointManipulator {
 public:
     typedef SPPath *ItemType;
 
-    PathManipulator(PathSharedData const &data, SPPath *path,
-        Geom::Matrix const &edit_trans, guint32 outline_color);
+    PathManipulator(PathSharedData const &data, SPPath *path, Geom::Matrix const &edit_trans,
+        guint32 outline_color, Glib::ustring lpe_key);
     ~PathManipulator();
     virtual bool event(GdkEvent *);
 
@@ -81,6 +82,7 @@ public:
     void showHandles(bool show);
     void showPathDirection(bool show);
     void setControlsTransform(Geom::Matrix const &);
+    void hideDragPoint();
 
     NodeList::iterator subdivideSegment(NodeList::iterator after, double t);
 
@@ -94,6 +96,10 @@ private:
     std::string _createTypeString();
     void _updateOutline();
     //void _setOutline(Geom::PathVector const &);
+    void _getGeometry();
+    void _setGeometry();
+    Glib::ustring _nodetypesKey();
+    Inkscape::XML::Node *_getXMLNode();
 
     void _attachNodeHandlers(Node *n);
     void _removeNodeHandlers(Node *n);
@@ -124,6 +130,7 @@ private:
     bool _show_handles;
     bool _show_outline;
     bool _show_path_direction;
+    Glib::ustring _lpe_key;
 
     friend class PathManipulatorObserver;
     friend class CurveDragPoint;
index cc2f8be4073c6c48e64dbee4b1a23f7ce798f220..96c1551f6473b99476f4f9ae78750a58beef67b6 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef SEEN_UI_TOOL_SHAPE_RECORD_H
 #define SEEN_UI_TOOL_SHAPE_RECORD_H
 
+#include <glibmm/ustring.h>
 #include <boost/operators.hpp>
 #include <2geom/matrix.h>
 
@@ -33,7 +34,7 @@ struct ShapeRecord :
     SPItem *item; // SP node for the edited shape
     Geom::Matrix edit_transform; // how to transform controls - used for clipping paths and masks
     ShapeRole role;
-    bool edit_original; // whether to use original-d instead of d for editing
+    Glib::ustring lpe_key; // This is LPE brain damage that I do not want to speak of
 
     inline bool operator==(ShapeRecord const &o) const { return item == o.item; }
     inline bool operator<(ShapeRecord const &o) const { return item < o.item; }