Code

Node tool: fix snapping of node rotation center
[inkscape.git] / src / ui / tool / transform-handle-set.cpp
index f3e2847e4be1da5a1079dee4519fe4db8bf1a62b..cafd592a3622017f42f62fafdd7253bd1b17f461 100644 (file)
 #include "desktop-handles.h"
 #include "display/sodipodi-ctrlrect.h"
 #include "preferences.h"
+#include "snap.h"
+#include "sp-namedview.h"
 #include "ui/tool/commit-events.h"
 #include "ui/tool/control-point.h"
 #include "ui/tool/event-utils.h"
 #include "ui/tool/transform-handle-set.h"
 
 // FIXME BRAIN DAMAGE WARNING: this is a global variable in select-context.cpp
-// Should be moved to a location where it can be accessed globally
+// It should be moved to a header
 extern GdkPixbuf *handles[];
 GType sp_select_context_get_type();
 
@@ -84,17 +86,6 @@ public:
         , _th(th)
     {
         setVisible(false);
-        signal_grabbed.connect(
-            sigc::bind_return(
-                sigc::hide(
-                    sigc::mem_fun(*this, &TransformHandle::_grabbedHandler)),
-                false));
-        signal_dragged.connect(
-            sigc::hide<0>(
-                sigc::mem_fun(*this, &TransformHandle::_draggedHandler)));
-        signal_ungrabbed.connect(
-            sigc::hide(
-                sigc::mem_fun(*this, &TransformHandle::_ungrabbedHandler)));
     }
 protected:
     virtual void startTransform() {}
@@ -106,7 +97,7 @@ protected:
     Geom::Point _origin;
     TransformHandleSet &_th;
 private:
-    void _grabbedHandler() {
+    virtual bool grabbed(GdkEventMotion *) {
         _origin = position();
         _last_transform.setIdentity();
         startTransform();
@@ -114,8 +105,9 @@ private:
         _th._setActiveHandle(this);
         _cset = &invisible_cset;
         _setState(_state);
+        return false;
     }
-    void _draggedHandler(Geom::Point &new_pos, GdkEventMotion *event)
+    virtual void dragged(Geom::Point &new_pos, GdkEventMotion *event)
     {
         Geom::Matrix t = computeTransform(new_pos, event);
         // protect against degeneracies
@@ -125,7 +117,7 @@ private:
         _th.signal_transform.emit(incr);
         _last_transform = t;
     }
-    void _ungrabbedHandler() {
+    virtual void ungrabbed(GdkEventButton *) {
         _th._clearActiveHandle();
         _cset = &thandle_cset;
         _setState(_state);
@@ -144,26 +136,28 @@ protected:
         if (state_held_control(state)) {
             if (state_held_shift(state)) {
                 return C_("Transform handle tip",
-                    "<b>Shift+Ctrl:</b> scale uniformly about the rotation center");
+                    "<b>Shift+Ctrl</b>: scale uniformly about the rotation center");
             }
             return C_("Transform handle tip", "<b>Ctrl:</b> scale uniformly");
         }
         if (state_held_shift(state)) {
             if (state_held_alt(state)) {
                 return C_("Transform handle tip",
-                    "<b>Shift+Alt:</b> scale using an integer ratio about the rotation center");
+                    "<b>Shift+Alt</b>: scale using an integer ratio about the rotation center");
             }
-            return C_("Transform handle tip", "<b>Shift:</b> scale from the rotation center");
+            return C_("Transform handle tip", "<b>Shift</b>: scale from the rotation center");
         }
         if (state_held_alt(state)) {
-            return C_("Transform handle tip", "<b>Alt:</b> scale using an integer ratio");
+            return C_("Transform handle tip", "<b>Alt</b>: scale using an integer ratio");
         }
-        return C_("Transform handle tip", "<b>Scale handle:</b> drag to scale the selection");
+        return C_("Transform handle tip", "<b>Scale handle</b>: drag to scale the selection");
     }
-    virtual Glib::ustring _getDragTip(GdkEventMotion *event) {
+
+    virtual Glib::ustring _getDragTip(GdkEventMotion */*event*/) {
         return format_tip(C_("Transform handle tip",
             "Scale by %.2f%% x %.2f%%"), _last_scale_x * 100, _last_scale_y * 100);
     }
+
     virtual bool _hasDragTips() { return true; }
 
     static double _last_scale_x, _last_scale_y;
@@ -171,7 +165,7 @@ protected:
 double ScaleHandle::_last_scale_x = 1.0;
 double ScaleHandle::_last_scale_y = 1.0;
 
-/** Corner scaling handle for node transforms */
+/// Corner scaling handle for node transforms
 class ScaleCornerHandle : public ScaleHandle {
 public:
     ScaleCornerHandle(TransformHandleSet &th, unsigned corner)
@@ -225,7 +219,7 @@ private:
     unsigned _corner;
 };
 
-/** Side scaling handle for node transforms */
+/// Side scaling handle for node transforms
 class ScaleSideHandle : public ScaleHandle {
 public:
     ScaleSideHandle(TransformHandleSet &th, unsigned side)
@@ -281,7 +275,7 @@ private:
     unsigned _side;
 };
 
-/** Rotation handle for nodes */
+/// Rotation handle for node transforms
 class RotateHandle : public TransformHandle {
 public:
     RotateHandle(TransformHandleSet &th, unsigned corner)
@@ -289,11 +283,13 @@ public:
         , _corner(corner)
     {}
 protected:
+
     virtual void startTransform() {
         _rot_center = _th.rotationCenter();
         _rot_opposite = _th.bounds().corner(_corner + 2);
         _last_angle = 0;
     }
+
     virtual Geom::Matrix computeTransform(Geom::Point const &new_pos, GdkEventMotion *event)
     {
         Geom::Point rotc = held_shift(*event) ? _rot_opposite : _rot_center;
@@ -307,28 +303,33 @@ protected:
             * Geom::Translate(rotc);
         return t;
     }
+
     virtual CommitEvent getCommitEvent() { return COMMIT_MOUSE_ROTATE; }
+
     virtual Glib::ustring _getTip(unsigned state) {
         if (state_held_shift(state)) {
             if (state_held_control(state)) {
                 return format_tip(C_("Transform handle tip",
-                    "<b>Shift+Ctrl:</b> rotate around the opposite corner and snap "
+                    "<b>Shift+Ctrl</b>: rotate around the opposite corner and snap "
                     "angle to %f° increments"), snap_increment_degrees());
             }
-            return C_("Transform handle tip", "<b>Shift:</b> rotate around the opposite corner");
+            return C_("Transform handle tip", "<b>Shift</b>: rotate around the opposite corner");
         }
         if (state_held_control(state)) {
             return format_tip(C_("Transform handle tip",
-                "<b>Ctrl:</b> snap angle to %f° increments"), snap_increment_degrees());
+                "<b>Ctrl</b>: snap angle to %f° increments"), snap_increment_degrees());
         }
-        return C_("Transform handle tip", "<b>Rotation handle:</b> drag to rotate "
+        return C_("Transform handle tip", "<b>Rotation handle</b>: drag to rotate "
             "the selection around the rotation center");
     }
-    virtual Glib::ustring _getDragTip(GdkEventMotion *event) {
+
+    virtual Glib::ustring _getDragTip(GdkEventMotion */*event*/) {
         return format_tip(C_("Transform handle tip", "Rotate by %.2f°"),
             _last_angle * 360.0);
     }
+
     virtual bool _hasDragTips() { return true; }
+
 private:
     static Glib::RefPtr<Gdk::Pixbuf> _corner_to_pixbuf(unsigned c) {
         sp_select_context_get_type();
@@ -339,15 +340,6 @@ private:
         default: return Glib::wrap(handles[4], true);
         }
     }
-    /*
-    static Geom::Point _corner_to_offset_unit(unsigned c) {
-        switch (c % 4) {
-        case 0: return Geom::Point(-1, 1);
-        case 1: return Geom::Point(1, 1);
-        case 2: return Geom::Point(1, -1);
-        default: return Geom::Point(-1, -1);
-        }
-    }*/
     Geom::Point _rot_center;
     Geom::Point _rot_opposite;
     unsigned _corner;
@@ -361,7 +353,9 @@ public:
         : TransformHandle(th, side_to_anchor(side), _side_to_pixbuf(side))
         , _side(side)
     {}
+
 protected:
+
     virtual void startTransform() {
         _skew_center = _th.rotationCenter();
         Geom::Rect b = _th.bounds();
@@ -369,6 +363,7 @@ protected:
         _last_angle = 0;
         _last_horizontal = _side % 2;
     }
+
     virtual Geom::Matrix computeTransform(Geom::Point const &new_pos, GdkEventMotion *event)
     {
         Geom::Point scc = held_shift(*event) ? _skew_center : _skew_opposite;
@@ -412,29 +407,32 @@ protected:
             * Geom::Translate(scc);
         return t;
     }
+
     virtual CommitEvent getCommitEvent() {
         return _side % 2
             ? COMMIT_MOUSE_SKEW_Y
             : COMMIT_MOUSE_SKEW_X;
     }
+
     virtual Glib::ustring _getTip(unsigned state) {
         if (state_held_shift(state)) {
             if (state_held_control(state)) {
                 return format_tip(C_("Transform handle tip",
-                    "<b>Shift+Ctrl:</b> skew about the rotation center with snapping "
+                    "<b>Shift+Ctrl</b>: skew about the rotation center with snapping "
                     "to %f° increments"), snap_increment_degrees());
             }
-            return C_("Transform handle tip", "<b>Shift:</b> skew about the rotation center");
+            return C_("Transform handle tip", "<b>Shift</b>: skew about the rotation center");
         }
         if (state_held_control(state)) {
             return format_tip(C_("Transform handle tip",
-                "<b>Ctrl:</b> snap skew angle to %f° increments"), snap_increment_degrees());
+                "<b>Ctrl</b>: snap skew angle to %f° increments"), snap_increment_degrees());
         }
         return C_("Transform handle tip",
-            "<b>Skew handle:</b> drag to skew (shear) selection about "
+            "<b>Skew handle</b>: drag to skew (shear) selection about "
             "the opposite handle");
     }
-    virtual Glib::ustring _getDragTip(GdkEventMotion *event) {
+
+    virtual Glib::ustring _getDragTip(GdkEventMotion */*event*/) {
         if (_last_horizontal) {
             return format_tip(C_("Transform handle tip", "Skew horizontally by %.2f°"),
                 _last_angle * 360.0);
@@ -443,8 +441,11 @@ protected:
                 _last_angle * 360.0);
         }
     }
+
     virtual bool _hasDragTips() { return true; }
+
 private:
+
     static Glib::RefPtr<Gdk::Pixbuf> _side_to_pixbuf(unsigned s) {
         sp_select_context_get_type();
         switch (s % 4) {
@@ -472,16 +473,37 @@ public:
     {
         setVisible(false);
     }
+
 protected:
-    virtual Glib::ustring _getTip(unsigned state) {
+    virtual void dragged(Geom::Point &new_pos, GdkEventMotion *event) {
+        SnapManager &sm = _desktop->namedview->snap_manager;
+        sm.setup(_desktop);
+        bool snap = !held_shift(*event) && sm.someSnapperMightSnap();
+        if (held_control(*event)) {
+            // constrain to axes
+            Geom::Point origin = _last_drag_origin();
+            std::vector<Inkscape::Snapper::SnapConstraint> constraints;
+            constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, Geom::Point(1, 0)));
+            constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, Geom::Point(0, 1)));
+            new_pos = sm.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(new_pos,
+                SNAPSOURCE_ROTATION_CENTER), constraints, held_shift(*event)).getPoint();
+        } else if (snap) {
+            sm.freeSnapReturnByRef(new_pos, SNAPSOURCE_ROTATION_CENTER);
+        }
+        sm.unSetup();
+    }
+    virtual Glib::ustring _getTip(unsigned /*state*/) {
         return C_("Transform handle tip",
-            "<b>Rotation center:</b> drag to change the origin of transforms");
+            "<b>Rotation center</b>: drag to change the origin of transforms");
     }
+
 private:
+
     static Glib::RefPtr<Gdk::Pixbuf> _get_pixbuf() {
         sp_select_context_get_type();
         return Glib::wrap(handles[12], true);
     }
+
     TransformHandleSet &_th;
 };
 
@@ -650,4 +672,4 @@ void TransformHandleSet::_updateVisibility(bool v)
   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 :