index d6181dbf4db69b54a56efdcbb114ec343d8a627e..209b7fe98f7587c5690a868507bfc9067a346a91 100644 (file)
#include "desktop-handles.h"
#include "display/sodipodi-ctrlrect.h"
#include "preferences.h"
+#include "snap.h"
+#include "snap-candidate.h"
+#include "sp-namedview.h"
#include "ui/tool/commit-events.h"
#include "ui/tool/control-point.h"
+#include "ui/tool/control-point-selection.h"
+#include "ui/tool/selectable-control-point.h"
#include "ui/tool/event-utils.h"
#include "ui/tool/transform-handle-set.h"
+#include "ui/tool/node-tool.h"
// FIXME BRAIN DAMAGE WARNING: this is a global variable in select-context.cpp
// It should be moved to a header
, _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() {}
Geom::Matrix _last_transform;
Geom::Point _origin;
TransformHandleSet &_th;
+ std::vector<Inkscape::SnapCandidatePoint> _snap_points;
+
private:
- void _grabbedHandler() {
+ virtual bool grabbed(GdkEventMotion *) {
_origin = position();
_last_transform.setIdentity();
startTransform();
_th._setActiveHandle(this);
_cset = &invisible_cset;
_setState(_state);
+
+ // Collect the snap-candidates, one for each selected node. These will be stored in the _snap_points vector.
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SnapManager &m = desktop->namedview->snap_manager;
+ InkNodeTool *nt = INK_NODE_TOOL(_desktop->event_context);
+ ControlPointSelection *selection = nt->_selected_nodes.get();
+
+ _snap_points = selection->getOriginalPoints();
+
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ if (prefs->getBool("/options/snapclosestonly/value", false)) {
+ m.keepClosestPointOnly(_snap_points, _origin);
+ }
+
+ 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
_th.signal_transform.emit(incr);
_last_transform = t;
}
- void _ungrabbedHandler() {
+ virtual void ungrabbed(GdkEventButton *) {
+ _snap_points.clear();
_th._clearActiveHandle();
_cset = &thandle_cset;
_setState(_state);
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;
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)
_sc_center = _th.rotationCenter();
_sc_opposite = _th.bounds().corner(_corner + 2);
_last_scale_x = _last_scale_y = 1.0;
+ InkNodeTool *nt = INK_NODE_TOOL(_desktop->event_context);
+ ControlPointSelection *selection = nt->_selected_nodes.get();
+ std::cout << "startTransform()" << std::endl;
+ selection->setOriginalPoints();
}
virtual Geom::Matrix computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) {
Geom::Point scc = held_shift(*event) ? _sc_center : _sc_opposite;
Geom::Point vold = _origin - scc, vnew = new_pos - scc;
+
// avoid exploding the selection
if (Geom::are_near(vold[Geom::X], 0) || Geom::are_near(vold[Geom::Y], 0))
return Geom::identity();
double scale[2] = { vnew[Geom::X] / vold[Geom::X], vnew[Geom::Y] / vold[Geom::Y] };
+
if (held_alt(*event)) {
for (unsigned i = 0; i < 2; ++i) {
if (scale[i] >= 1.0) scale[i] = round(scale[i]);
else scale[i] = 1.0 / round(1.0 / scale[i]);
}
- } else if (held_control(*event)) {
- scale[0] = scale[1] = std::min(scale[0], scale[1]);
+ } else {
+ //SPDesktop *desktop = _th._desktop; // Won't work as _desktop is protected
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SnapManager &m = desktop->namedview->snap_manager;
+
+ // The lines below have been copied from Handle::dragged() in node.cpp, and need to be
+ // activated if we want to snap to unselected (i.e. stationary) nodes and stationary pieces of paths of the
+ // path that's currently being edited
+ /*
+ std::vector<Inkscape::SnapCandidatePoint> unselected;
+ typedef ControlPointSelection::Set Set;
+ Set &nodes = _parent->_selection.allPoints();
+ for (Set::iterator i = nodes.begin(); i != nodes.end(); ++i) {
+ Node *n = static_cast<Node*>(*i);
+ Inkscape::SnapCandidatePoint p(n->position(), n->_snapSourceType(), n->_snapTargetType());
+ unselected.push_back(p);
+ }
+ m.setupIgnoreSelection(_desktop, true, &unselected);
+ */
+
+ m.setupIgnoreSelection(_desktop);
+
+ Inkscape::SnappedPoint sp;
+ if (held_control(*event)) {
+ scale[0] = scale[1] = std::min(scale[0], scale[1]);
+ sp = m.constrainedSnapScale(_snap_points, _origin, Geom::Scale(scale[0], scale[1]), scc);
+ } else {
+ sp = m.freeSnapScale(_snap_points, _origin, Geom::Scale(scale[0], scale[1]), scc);
+ }
+ m.unSetup();
+
+ if (sp.getSnapped()) {
+ Geom::Point result = sp.getTransformation();
+ scale[0] = result[0];
+ scale[1] = result[1];
+ }
}
+
_last_scale_x = scale[0];
_last_scale_y = scale[1];
Geom::Matrix t = Geom::Translate(-scc)
unsigned _corner;
};
-/** Side scaling handle for node transforms */
+/// Side scaling handle for node transforms
class ScaleSideHandle : public ScaleHandle {
public:
ScaleSideHandle(TransformHandleSet &th, unsigned side)
unsigned _side;
};
-/** Rotation handle for nodes */
+/// Rotation handle for node transforms
class RotateHandle : public TransformHandle {
public:
RotateHandle(TransformHandleSet &th, unsigned corner)
, _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;
* 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();
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;
: 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();
_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;
* 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);
_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) {
{
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;
};
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 :