Code

Fix self-snapping when dragging the transformation center of a selection containing...
authorDiederik van Lierop <mailat-signdiedenrezidotnl>
Thu, 7 Oct 2010 20:38:37 +0000 (22:38 +0200)
committerDiederik van Lierop <mailat-signdiedenrezidotnl>
Thu, 7 Oct 2010 20:38:37 +0000 (22:38 +0200)
src/object-snapper.cpp
src/seltrans.cpp
src/snap.cpp
src/snap.h

index f1bdd94d998505e640b9880fe534f60d0ac4e2ee..b11e857dcd067a7c6e17ceba4328ce704129fa4b 100644 (file)
@@ -229,10 +229,17 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapSourceType const &t,
                     _snapmanager->snapprefs.setSnapIntersectionCS(false);
                 }
 
+                // We should not snap a transformation center to any of the centers of the items in the
+                // current selection (see the comment in SelTrans::centerRequest())
                 bool old_pref2 = _snapmanager->snapprefs.getIncludeItemCenter();
-                if ((*i).item == _snapmanager->getRotationCenterSource()) {
-                    // don't snap to this item's rotation center
-                    _snapmanager->snapprefs.setIncludeItemCenter(false);
+                if (old_pref2) {
+                    for ( GSList const *itemlist = _snapmanager->getRotationCenterSource(); itemlist != NULL; itemlist = g_slist_next(itemlist) ) {
+                        if ((*i).item == reinterpret_cast<SPItem*>(itemlist->data)) {
+                            // don't snap to this item's rotation center
+                            _snapmanager->snapprefs.setIncludeItemCenter(false);
+                            break;
+                        }
+                    }
                 }
 
                 sp_item_snappoints(root_item, *_points_to_snap_to, &_snapmanager->snapprefs);
index 7dbeb41739a533b332e37c1f8296cc3f5aaadf55..9a1fdf4adcd8d8b6d45c15cf730a8a41ce2d88b5 100644 (file)
@@ -1338,18 +1338,15 @@ gboolean Inkscape::SelTrans::rotateRequest(Geom::Point &pt, guint state)
 // Move the item's transformation center
 gboolean Inkscape::SelTrans::centerRequest(Geom::Point &pt, guint state)
 {
-    // Center is being dragged for the first item in the selection only
-    // Find out which item is first ...
-    GSList *items = (GSList *) const_cast<Selection *>(_selection)->itemList();
-    SPItem *first = NULL;
-    if (items) {
-        first = reinterpret_cast<SPItem*>(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
     SnapManager &m = _desktop->namedview->snap_manager;
     m.setup(_desktop);
-    m.setRotationCenterSource(first);
+
+    // When dragging the transformation center while multiple items have been selected, then those
+    // items will share a single center. While dragging that single center, it should never snap to the
+    // centers of any of the selected objects. Therefore we will have to pass the list of selected items
+    // to the snapper, to avoid self-snapping of the rotation center
+    GSList *items = (GSList *) const_cast<Selection *>(_selection)->itemList();
+    m.setRotationCenterSource(items);
     m.freeSnapReturnByRef(pt, Inkscape::SNAPSOURCE_ROTATION_CENTER);
     m.unSetup();
 
index 9cde24e16b25ed80354a7ebe0843308e24ad070d..cac3824ab4c406c643ec3c295f0a179d1ca085c8 100644 (file)
@@ -47,7 +47,7 @@ SnapManager::SnapManager(SPNamedView const *v) :
     object(this, 0),
     snapprefs(),
     _named_view(v),
-    _rotation_center_source_item(NULL),
+    _rotation_center_source_items(NULL),
     _guide_to_ignore(NULL),
     _desktop(NULL),
     _unselected_nodes(NULL)
@@ -1161,7 +1161,7 @@ void SnapManager::setup(SPDesktop const *desktop,
     _snapindicator = snapindicator;
     _unselected_nodes = unselected_nodes;
     _guide_to_ignore = guide_to_ignore;
-    _rotation_center_source_item = NULL;
+    _rotation_center_source_items = NULL;
 }
 
 /**
@@ -1195,7 +1195,7 @@ void SnapManager::setup(SPDesktop const *desktop,
     _snapindicator = snapindicator;
     _unselected_nodes = unselected_nodes;
     _guide_to_ignore = guide_to_ignore;
-    _rotation_center_source_item = NULL;
+    _rotation_center_source_items = NULL;
 }
 
 /// Setup, taking the list of items to ignore from the desktop's selection.
@@ -1213,7 +1213,7 @@ void SnapManager::setupIgnoreSelection(SPDesktop const *desktop,
     _snapindicator = snapindicator;
     _unselected_nodes = unselected_nodes;
     _guide_to_ignore = guide_to_ignore;
-    _rotation_center_source_item = NULL;
+    _rotation_center_source_items = NULL;
     _items_to_ignore.clear();
 
     Inkscape::Selection *sel = _desktop->selection;
index 7f3c289551ed461bdbed9e4588f3a107478561ed..0f27017a5619c403703f3a592120808da4cc9ce0 100644 (file)
@@ -98,7 +98,7 @@ public:
                               std::vector<Inkscape::SnapCandidatePoint> *unselected_nodes = NULL,
                               SPGuide *guide_to_ignore = NULL);
 
-    void unSetup() {_rotation_center_source_item = NULL;
+    void unSetup() {_rotation_center_source_items = NULL;
                     _guide_to_ignore = NULL;
                     _desktop = NULL;
                     _unselected_nodes = NULL;}
@@ -107,8 +107,8 @@ public:
     // 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;}
+    void setRotationCenterSource(GSList *items) {_rotation_center_source_items = items;}
+    GSList const *getRotationCenterSource() {return _rotation_center_source_items;}
 
     // freeSnapReturnByRef() is preferred over freeSnap(), because it only returns a
     // point if snapping has occurred (by overwriting p); otherwise p is untouched
@@ -200,7 +200,7 @@ protected:
 
 private:
     std::vector<SPItem const *> _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
+    GSList *_rotation_center_source_items; // 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