Code

Node tool: snap while scaling a selection of nodes. Consider this as experimental...
[inkscape.git] / src / seltrans.cpp
index f96fce228083359e2d5d39a5598f30f9a11fe486..b1d184986da06c3d2b7248c8a211beea641b5bcc 100644 (file)
@@ -6,6 +6,7 @@
  *   bulia byak <buliabyak@users.sf.net>
  *   Carl Hetherington <inkscape@carlh.net>
  *   Diederik van Lierop <mail@diedenrezi.nl>
+ *   Abhishek Sharma
  *
  * Copyright (C) 1999-2002 Lauris Kaplinski
  * Copyright (C) 1999-2008 Authors
@@ -45,6 +46,7 @@
 #include <2geom/angle.h>
 #include "display/snap-indicator.h"
 
+using Inkscape::DocumentUndo;
 
 static void sp_remove_handles(SPKnot *knot[], gint num);
 
@@ -265,7 +267,7 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s
         SPItem *it = (SPItem *)sp_object_ref(SP_OBJECT(l->data), NULL);
         _items.push_back(it);
         _items_const.push_back(it);
-        _items_affines.push_back(sp_item_i2d_affine(it));
+        _items_affines.push_back(it->i2d_affine());
         _items_centers.push_back(it->getCenter()); // for content-dragging, we need to remember original centers
     }
 
@@ -297,7 +299,7 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s
         An average user would rarely ever try to snap such a large number of nodes anyway, because
         (s)he could hardly discern which node would be snapping */
         if (prefs->getBool("/options/snapclosestonly/value", false)) {
-            _keepClosestPointOnly(_snap_points, p);
+            m.keepClosestPointOnly(_snap_points, p);
         } else {
             _snap_points = snap_points_hull;
         }
@@ -333,7 +335,7 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s
             // More than 50 items will produce at least 200 bbox points, which might make Inkscape crawl
             // (see the comment a few lines above). In that case we will use the bbox of the selection as a whole
             for (unsigned i = 0; i < _items.size(); i++) {
-                getBBoxPoints(sp_item_bbox_desktop(_items[i], _snap_bbox_type), &_bbox_points_for_translating, false, true, emp, mp);
+                getBBoxPoints(_items[i]->getBboxDesktop(_snap_bbox_type), &_bbox_points_for_translating, false, true, emp, mp);
             }
         } else {
             _bbox_points_for_translating = _bbox_points; // use the bbox points of the selection as a whole
@@ -358,14 +360,14 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s
 
     if (prefs->getBool("/options/snapclosestonly/value", false)) {
         if (m.snapprefs.getSnapModeNode()) {
-            _keepClosestPointOnly(_snap_points, p);
+            m.keepClosestPointOnly(_snap_points, p);
         } else {
             _snap_points.clear(); // don't keep any point
         }
 
         if (m.snapprefs.getSnapModeBBox()) {
-            _keepClosestPointOnly(_bbox_points, p);
-            _keepClosestPointOnly(_bbox_points_for_translating, p);
+            m.keepClosestPointOnly(_bbox_points, p);
+            m.keepClosestPointOnly(_bbox_points_for_translating, p);
         } else {
             _bbox_points.clear(); // don't keep any point
             _bbox_points_for_translating.clear();
@@ -429,7 +431,7 @@ void Inkscape::SelTrans::transform(Geom::Matrix const &rel_affine, Geom::Point c
         for (unsigned i = 0; i < _items.size(); i++) {
             SPItem &item = *_items[i];
             Geom::Matrix const &prev_transform = _items_affines[i];
-            sp_item_set_i2d_affine(&item, prev_transform * affine);
+            item.set_i2d_affine(prev_transform * affine);
         }
     } else {
         if (_bbox) {
@@ -505,17 +507,17 @@ void Inkscape::SelTrans::ungrab()
         _items_centers.clear();
 
         if (_current_relative_affine.isTranslation()) {
-            sp_document_done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
-                             _("Move"));
+            DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
+                               _("Move"));
         } else if (_current_relative_affine.without_translation().isScale()) {
-            sp_document_done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
-                             _("Scale"));
+            DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
+                               _("Scale"));
         } else if (_current_relative_affine.without_translation().isRotation()) {
-            sp_document_done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
-                             _("Rotate"));
+            DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
+                               _("Rotate"));
         } else {
-            sp_document_done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
-                             _("Skew"));
+            DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
+                               _("Skew"));
         }
 
     } else {
@@ -526,8 +528,8 @@ void Inkscape::SelTrans::ungrab()
                 SPItem *it = (SPItem*)SP_OBJECT(l->data);
                 SP_OBJECT(it)->updateRepr();
             }
-            sp_document_done (sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
-                            _("Set center"));
+            DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
+                               _("Set center"));
         }
 
         _items.clear();
@@ -584,15 +586,15 @@ void Inkscape::SelTrans::stamp()
 
             Geom::Matrix const *new_affine;
             if (_show == SHOW_OUTLINE) {
-                Geom::Matrix const i2d(sp_item_i2d_affine(original_item));
+                Geom::Matrix const i2d(original_item->i2d_affine());
                 Geom::Matrix const i2dnew( i2d * _current_relative_affine );
-                sp_item_set_i2d_affine(copy_item, i2dnew);
+                copy_item->set_i2d_affine(i2dnew);
                 new_affine = &copy_item->transform;
             } else {
                 new_affine = &original_item->transform;
             }
 
-            sp_item_write_transform(copy_item, copy_repr, *new_affine);
+            copy_item->doWriteTransform(copy_repr, *new_affine);
 
             if ( copy_item->isCenterSet() && _center ) {
                 copy_item->setCenter(*_center * _current_relative_affine);
@@ -601,8 +603,8 @@ void Inkscape::SelTrans::stamp()
             Inkscape::GC::release(copy_repr);
             l = l->next;
         }
-        sp_document_done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
-                         _("Stamp"));
+        DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
+                           _("Stamp"));
     }
 
     if ( fixup && _stamp_cache ) {
@@ -790,8 +792,8 @@ void Inkscape::SelTrans::handleClick(SPKnot */*knot*/, guint state, SPSelTransHa
                     _center_is_set = false;  // center has changed
                     _updateHandles();
                 }
-                sp_document_done (sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
-                                        _("Reset center"));
+                DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT,
+                                   _("Reset center"));
             }
             break;
         default:
@@ -1323,26 +1325,30 @@ gboolean Inkscape::SelTrans::rotateRequest(Geom::Point &pt, guint state)
 // Move the item's transformation center
 gboolean Inkscape::SelTrans::centerRequest(Geom::Point &pt, guint state)
 {
-    SnapManager &m = _desktop->namedview->snap_manager;
-    m.setup(_desktop);
-
     // 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();
+    SnapManager &m = _desktop->namedview->snap_manager;
+    m.setup(_desktop);
     m.setRotationCenterSource(items);
-    m.freeSnapReturnByRef(pt, Inkscape::SNAPSOURCE_ROTATION_CENTER);
-    m.unSetup();
 
-    if (state & GDK_CONTROL_MASK) {
-        if ( fabs(_point[Geom::X] - pt[Geom::X]) > fabs(_point[Geom::Y] - pt[Geom::Y]) ) {
-            pt[Geom::Y] = _point[Geom::Y];
-        } else {
-            pt[Geom::X] = _point[Geom::X];
+    if (state & GDK_CONTROL_MASK) { // with Ctrl, constrain to axes
+        std::vector<Inkscape::Snapper::SnapConstraint> constraints;
+        constraints.push_back(Inkscape::Snapper::SnapConstraint(_point, Geom::Point(1, 0)));
+        constraints.push_back(Inkscape::Snapper::SnapConstraint(_point, Geom::Point(0, 1)));
+        Inkscape::SnappedPoint sp = m.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_ROTATION_CENTER), constraints, state & GDK_SHIFT_MASK);
+        pt = sp.getPoint();
+    }
+    else {
+        if (!(state & GDK_SHIFT_MASK)) { // Shift disables snapping
+            m.freeSnapReturnByRef(pt, Inkscape::SNAPSOURCE_ROTATION_CENTER);
         }
     }
 
+    m.unSetup();
+
     // status text
     GString *xs = SP_PX_TO_METRIC_STRING(pt[Geom::X], _desktop->namedview->getDefaultMetric());
     GString *ys = SP_PX_TO_METRIC_STRING(pt[Geom::Y], _desktop->namedview->getDefaultMetric());
@@ -1626,26 +1632,6 @@ Geom::Point Inkscape::SelTrans::_calcAbsAffineGeom(Geom::Scale const geom_scale)
     return _calcAbsAffineDefault(geom_scale); // this is bogus, but we must return _something_
 }
 
-void Inkscape::SelTrans::_keepClosestPointOnly(std::vector<Inkscape::SnapCandidatePoint> &points, const Geom::Point &reference)
-{
-    if (points.size() < 2) return;
-
-    Inkscape::SnapCandidatePoint closest_point = Inkscape::SnapCandidatePoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, SNAPTARGET_UNDEFINED);
-    Geom::Coord closest_dist = NR_HUGE;
-
-    for(std::vector<Inkscape::SnapCandidatePoint>::const_iterator i = points.begin(); i != points.end(); i++) {
-        Geom::Coord dist = Geom::L2((*i).getPoint() - reference);
-        if (i == points.begin() || dist < closest_dist) {
-            closest_point = *i;
-            closest_dist = dist;
-        }
-    }
-
-    closest_point.setSourceNum(-1);
-    points.clear();
-    points.push_back(closest_point);
-}
-
 /*
   Local Variables:
   mode:c++
@@ -1655,4 +1641,4 @@ void Inkscape::SelTrans::_keepClosestPointOnly(std::vector<Inkscape::SnapCandida
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :