From 8cd8b6ee0c2bd47add62310866479d49a2070057 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Thu, 7 Oct 2010 22:38:37 +0200 Subject: [PATCH] Fix self-snapping when dragging the transformation center of a selection containing multiple items (as reported by LucaDC in LP #607107, comment #30) --- src/object-snapper.cpp | 13 ++++++++++--- src/seltrans.cpp | 17 +++++++---------- src/snap.cpp | 8 ++++---- src/snap.h | 8 ++++---- 4 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index f1bdd94d9..b11e857dc 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -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(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); diff --git a/src/seltrans.cpp b/src/seltrans.cpp index 7dbeb4173..9a1fdf4ad 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -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)->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 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)->itemList(); + m.setRotationCenterSource(items); m.freeSnapReturnByRef(pt, Inkscape::SNAPSOURCE_ROTATION_CENTER); m.unSetup(); diff --git a/src/snap.cpp b/src/snap.cpp index 9cde24e16..cac3824ab 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -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; diff --git a/src/snap.h b/src/snap.h index 7f3c28955..0f27017a5 100644 --- a/src/snap.h +++ b/src/snap.h @@ -98,7 +98,7 @@ public: std::vector *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 _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 -- 2.30.2