From: Diederik van Lierop Date: Sat, 24 Jul 2010 12:37:50 +0000 (+0200) Subject: Avoid self-snapping when dragging a rotation center, and draw the rotation center... X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=cc1dc1d8b7721543eac3fd52b7c5aaa1dc4fa154;p=inkscape.git Avoid self-snapping when dragging a rotation center, and draw the rotation center at the snapped position --- diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index ef5dcc7d0..c1ed08f12 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -228,11 +228,17 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapSourceType const &t, _snapmanager->snapprefs.setSnapIntersectionCS(false); } + bool old_pref2 = _snapmanager->snapprefs.getIncludeItemCenter(); + if ((*i).item == _snapmanager->getRotationCenterSource()) { + // don't snap to this item's rotation center + _snapmanager->snapprefs.setIncludeItemCenter(false); + } + sp_item_snappoints(root_item, *_points_to_snap_to, &_snapmanager->snapprefs); - if (_snapmanager->snapprefs.getSnapToItemPath()) { - _snapmanager->snapprefs.setSnapIntersectionCS(old_pref); - } + // restore the original snap preferences + _snapmanager->snapprefs.setSnapIntersectionCS(old_pref); + _snapmanager->snapprefs.setIncludeItemCenter(old_pref2); } //Collect the bounding box's corners so we can snap to them diff --git a/src/selection.cpp b/src/selection.cpp index 96c66e0c5..3f333e4e2 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -406,6 +406,8 @@ Geom::OptRect Selection::boundsInDocument(SPItem::BBoxType type) const { } /** Extract the position of the center from the first selected object */ +// If we have a selection of multiple items, then the center of the first item +// will be returned; this is also the case in SelTrans::centerRequest() boost::optional Selection::center() const { GSList *items = (GSList *) const_cast(this)->itemList(); Geom::Point center; diff --git a/src/seltrans.cpp b/src/seltrans.cpp index b9bf4c6ce..764c222a8 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -883,7 +883,11 @@ gboolean Inkscape::SelTrans::handleRequest(SPKnot *knot, Geom::Point *position, if (handle.request(this, handle, *position, state)) { sp_knot_set_position(knot, *position, state); SP_CTRL(_grip)->moveto(*position); - SP_CTRL(_norm)->moveto(_origin); + if (&handle == &handle_center) { + SP_CTRL(_norm)->moveto(*position); + } else { + SP_CTRL(_norm)->moveto(_origin); + } } return TRUE; @@ -1329,7 +1333,18 @@ gboolean Inkscape::SelTrans::centerRequest(Geom::Point &pt, guint state) { SnapManager &m = _desktop->namedview->snap_manager; m.setup(_desktop); - m.freeSnapReturnByRef(pt, Inkscape::SNAPSOURCE_OTHER_HANDLE); + + // Center is being dragged for the first item in the selection only + // Find out which item is first ... + GSList *items = (GSList *) const_cast(_selection)->itemList(); + SPItem *first = NULL; + if (items) { + first = reinterpret_cast(g_slist_last(items)->data); // from the first item in selection + } + // ... and store that item because later on we need to make sure that + // this transformation center won't snap to itself + m.setRotationCenterSource(first); + m.freeSnapReturnByRef(pt, Inkscape::SNAPSOURCE_ROTATION_CENTER); if (state & GDK_CONTROL_MASK) { if ( fabs(_point[Geom::X] - pt[Geom::X]) > fabs(_point[Geom::Y] - pt[Geom::Y]) ) { diff --git a/src/snap.cpp b/src/snap.cpp index ccbd449bd..fc8837c43 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -1079,6 +1079,7 @@ void SnapManager::setup(SPDesktop const *desktop, _snapindicator = snapindicator; _unselected_nodes = unselected_nodes; _guide_to_ignore = guide_to_ignore; + _rotation_center_source_item = NULL; } /** @@ -1109,6 +1110,7 @@ void SnapManager::setup(SPDesktop const *desktop, _snapindicator = snapindicator; _unselected_nodes = unselected_nodes; _guide_to_ignore = guide_to_ignore; + _rotation_center_source_item = NULL; } /// Setup, taking the list of items to ignore from the desktop's selection. @@ -1121,6 +1123,7 @@ void SnapManager::setupIgnoreSelection(SPDesktop const *desktop, _snapindicator = snapindicator; _unselected_nodes = unselected_nodes; _guide_to_ignore = guide_to_ignore; + _rotation_center_source_item = NULL; _items_to_ignore.clear(); Inkscape::Selection *sel = _desktop->selection; diff --git a/src/snap.h b/src/snap.h index 26e599cc6..f740f3c62 100644 --- a/src/snap.h +++ b/src/snap.h @@ -92,11 +92,19 @@ public: std::vector &items_to_ignore, std::vector *unselected_nodes = NULL, SPGuide *guide_to_ignore = NULL); + void setupIgnoreSelection(SPDesktop const *desktop, bool snapindicator = true, std::vector *unselected_nodes = NULL, SPGuide *guide_to_ignore = NULL); + // If we're dragging a rotation center, then setRotationCenterSource() stores the parent item + // of this rotation center; this reference is used to make sure that we do not snap a rotation + // center to itself + // NOTE: Must be called after calling setup(), not before! + void setRotationCenterSource(SPItem *item) {_rotation_center_source_item = item;} + SPItem* getRotationCenterSource() {return _rotation_center_source_item;} + // freeSnapReturnByRef() is preferred over freeSnap(), because it only returns a // point if snapping has occurred (by overwriting p); otherwise p is untouched void freeSnapReturnByRef(Geom::Point &p, @@ -183,6 +191,7 @@ protected: private: std::vector _items_to_ignore; ///< Items that should not be snapped to, for example the items that are currently being dragged. Set using the setup() method + SPItem *_rotation_center_source_item; // to avoid snapping a rotation center to itself SPGuide *_guide_to_ignore; ///< A guide that should not be snapped to, e.g. the guide that is currently being dragged SPDesktop const *_desktop; bool _snapindicator; ///< When true, an indicator will be drawn at the position that was being snapped to diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp index 0038908bf..b64ad45e0 100644 --- a/src/sp-shape.cpp +++ b/src/sp-shape.cpp @@ -1208,57 +1208,57 @@ static void sp_shape_snappoints(SPItem const *item, std::vectorgetSnapToItemNode()) { - // Add the first point of the path - p.push_back(Inkscape::SnapCandidatePoint(path_it->initialPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); + // Add the first point of the path + p.push_back(Inkscape::SnapCandidatePoint(path_it->initialPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); } Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve while (curve_it1 != path_it->end_default()) { - // For each path: consider midpoints of line segments for snapping - if (snapprefs->getSnapLineMidpoints()) { // only do this when we're snapping nodes (enforces strict snapping) - if (Geom::LineSegment const* line_segment = dynamic_cast(&(*curve_it1))) { - p.push_back(Inkscape::SnapCandidatePoint(Geom::middle_point(*line_segment) * i2d, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT)); - } - } - - if (curve_it2 == path_it->end_default()) { // Test will only pass for the last iteration of the while loop - if (snapprefs->getSnapToItemNode() && !path_it->closed()) { - // Add the last point of the path, but only for open paths - // (for closed paths the first and last point will coincide) - p.push_back(Inkscape::SnapCandidatePoint((*curve_it1).finalPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); - } - } else { - /* Test whether to add the node between curve_it1 and curve_it2. - * Loop to end_default (so only iterating through the stroked part); */ - - Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2); - - bool c1 = snapprefs->getSnapToItemNode() && (nodetype == Geom::NODE_CUSP || nodetype == Geom::NODE_NONE); - bool c2 = snapprefs->getSnapSmoothNodes() && (nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM); - - if (c1 || c2) { - Inkscape::SnapSourceType sst; - Inkscape::SnapTargetType stt; - switch (nodetype) { - case Geom::NODE_CUSP: - sst = Inkscape::SNAPSOURCE_NODE_CUSP; - stt = Inkscape::SNAPTARGET_NODE_CUSP; - break; - case Geom::NODE_SMOOTH: - case Geom::NODE_SYMM: - sst = Inkscape::SNAPSOURCE_NODE_SMOOTH; - stt = Inkscape::SNAPTARGET_NODE_SMOOTH; - break; - default: - sst = Inkscape::SNAPSOURCE_UNDEFINED; - stt = Inkscape::SNAPTARGET_UNDEFINED; - break; - } - p.push_back(Inkscape::SnapCandidatePoint(curve_it1->finalPoint() * i2d, sst, stt)); - } - } + // For each path: consider midpoints of line segments for snapping + if (snapprefs->getSnapLineMidpoints()) { // only do this when we're snapping nodes (enforces strict snapping) + if (Geom::LineSegment const* line_segment = dynamic_cast(&(*curve_it1))) { + p.push_back(Inkscape::SnapCandidatePoint(Geom::middle_point(*line_segment) * i2d, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT)); + } + } + + if (curve_it2 == path_it->end_default()) { // Test will only pass for the last iteration of the while loop + if (snapprefs->getSnapToItemNode() && !path_it->closed()) { + // Add the last point of the path, but only for open paths + // (for closed paths the first and last point will coincide) + p.push_back(Inkscape::SnapCandidatePoint((*curve_it1).finalPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); + } + } else { + /* Test whether to add the node between curve_it1 and curve_it2. + * Loop to end_default (so only iterating through the stroked part); */ + + Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2); + + bool c1 = snapprefs->getSnapToItemNode() && (nodetype == Geom::NODE_CUSP || nodetype == Geom::NODE_NONE); + bool c2 = snapprefs->getSnapSmoothNodes() && (nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM); + + if (c1 || c2) { + Inkscape::SnapSourceType sst; + Inkscape::SnapTargetType stt; + switch (nodetype) { + case Geom::NODE_CUSP: + sst = Inkscape::SNAPSOURCE_NODE_CUSP; + stt = Inkscape::SNAPTARGET_NODE_CUSP; + break; + case Geom::NODE_SMOOTH: + case Geom::NODE_SYMM: + sst = Inkscape::SNAPSOURCE_NODE_SMOOTH; + stt = Inkscape::SNAPTARGET_NODE_SMOOTH; + break; + default: + sst = Inkscape::SNAPSOURCE_UNDEFINED; + stt = Inkscape::SNAPTARGET_UNDEFINED; + break; + } + p.push_back(Inkscape::SnapCandidatePoint(curve_it1->finalPoint() * i2d, sst, stt)); + } + } ++curve_it1; ++curve_it2;