diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp
index 69c09602e98a0cd179789bbc161feae102484708..12d04dd2b74541e3e4b804c73e600000f4ae16a2 100644 (file)
--- a/src/ui/tool/node.cpp
+++ b/src/ui/tool/node.cpp
_parent->position() - node_away->position());
Inkscape::SnappedPoint p;
p = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, SNAPSOURCE_NODE_HANDLE), cl);
- if (p.getSnapped()) {
- p.getPoint(new_pos);
- }
+ new_pos = p.getPoint();
} else {
sm.freeSnapReturnByRef(new_pos, SNAPSOURCE_NODE_HANDLE);
}
+ sm.unSetup();
}
+
// with Shift, if the node is cusp, rotate the other handle as well
if (_parent->type() == NODE_CUSP && !_drag_out) {
if (held_shift(*event)) {
if (update_handles) {
switch (type) {
case NODE_CUSP:
- // if the existing type is also NODE_CUSP, retract handles
- if (_type == NODE_CUSP) {
- _front.retract();
- _back.retract();
- }
+ // nothing to do
break;
case NODE_AUTO:
// auto handles make no sense for endnodes
_updateAutoHandles();
break;
case NODE_SMOOTH: {
+ // ignore attempts to make smooth endnodes.
+ if (isEndNode()) return;
// rotate handles to be colinear
// for degenerate nodes set positions like auto handles
bool prev_line = _is_line_segment(_prev(), this);
bool next_line = _is_line_segment(this, _next());
if (_type == NODE_SMOOTH) {
- // for a node that is already smooth and has a degenerate handle,
- // drag out the second handle to 1/3 the length of the linear segment
+ // For a node that is already smooth and has a degenerate handle,
+ // drag out the second handle without changing the direction of the first one.
if (_front.isDegenerate()) {
double dist = Geom::distance(_next()->position(), position());
_front.setRelativePos(Geom::unit_vector(-_back.relativePos()) * dist / 3);
/** Customized event handler to catch scroll events needed for selection grow/shrink. */
bool Node::_eventHandler(GdkEvent *event)
{
- static NodeList::iterator origin;
- static int dir;
+ int dir = 0;
switch (event->type)
{
dir = -1;
} else break;
if (held_control(event->scroll)) {
- _selection.spatialGrow(this, dir);
+ _linearGrow(dir);
} else {
+ _selection.spatialGrow(this, dir);
+ }
+ return true;
+ case GDK_KEY_PRESS:
+ switch (shortcut_key(event->key))
+ {
+ case GDK_Page_Up:
+ dir = 1;
+ break;
+ case GDK_Page_Down:
+ dir = -1;
+ break;
+ default: goto bail_out;
+ }
+
+ if (held_control(event->key)) {
_linearGrow(dir);
+ } else {
+ _selection.spatialGrow(this, dir);
}
return true;
default:
break;
}
+
+ bail_out:
return ControlPoint::_eventHandler(event);
}
{
// For a note on how snapping is implemented in Inkscape, see snap.h.
SnapManager &sm = _desktop->namedview->snap_manager;
- bool snap = sm.someSnapperMightSnap();
+ // even if we won't really snap, we might still call the one of the
+ // constrainedSnap() methods to enforce the constraints, so we need
+ // to setup the snapmanager anyway; this is also required for someSnapperMightSnap()
+ sm.setup(_desktop);
+
+ // do not snap when Shift is pressed
+ bool snap = !held_shift(*event) && sm.someSnapperMightSnap();
+
+ Inkscape::SnappedPoint sp;
std::vector<Inkscape::SnapCandidatePoint> unselected;
if (snap) {
/* setup
unselected.push_back(p);
}
}
- sm.setupIgnoreSelection(_desktop, false, &unselected);
+ sm.unSetup();
+ sm.setupIgnoreSelection(_desktop, true, &unselected);
}
if (held_control(*event)) {
Geom::Point origin = _last_drag_origin();
- Inkscape::SnappedPoint fp, bp, fpp, bpp;
+ std::vector<Inkscape::Snapper::SnapConstraint> constraints;
if (held_alt(*event)) {
// with Ctrl+Alt, constrain to handle lines
// project the new position onto a handle line that is closer;
// also snap to perpendiculars of handle lines
- // TODO: this code is repetitive to the point of sillyness. Find a way
- // to express this concisely by modifying the semantics of snapping calls.
- // During a non-snap invocation, we should call constrainedSnap()
- // anyway, but it should just return the closest point matching the constraint
- // rather than snapping to an object. There should be comparison
- // operators defined for snap results, to simplify determining the best one,
- // or the snapping calls should take a reference to a snapping result and
- // replace it with the current result if it's better.
-
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
int snaps = prefs->getIntLimited("/options/rotationsnapsperpi/value", 12, 1, 1000);
double min_angle = M_PI / snaps;
boost::optional<Geom::Point> front_point, back_point, fperp_point, bperp_point;
- boost::optional<Inkscape::Snapper::SnapConstraint> line_front, line_back, line_fperp, line_bperp;
if (_front.isDegenerate()) {
if (_is_line_segment(this, _next()))
front_point = _next()->position() - origin;
back_point = _back.relativePos();
}
if (front_point) {
- line_front = Inkscape::Snapper::SnapConstraint(origin, *front_point);
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, *front_point));
fperp_point = Geom::rot90(*front_point);
}
if (back_point) {
- line_back = Inkscape::Snapper::SnapConstraint(origin, *back_point);
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, *back_point));
bperp_point = Geom::rot90(*back_point);
}
// perpendiculars only snap when they are further than snap increment away
(fabs(Geom::angle_between(*fperp_point, *back_point)) > min_angle &&
fabs(Geom::angle_between(*fperp_point, *back_point)) < M_PI - min_angle)))
{
- line_fperp = Inkscape::Snapper::SnapConstraint(origin, *fperp_point);
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, *fperp_point));
}
if (bperp_point && (!front_point ||
(fabs(Geom::angle_between(*bperp_point, *front_point)) > min_angle &&
fabs(Geom::angle_between(*bperp_point, *front_point)) < M_PI - min_angle)))
{
- line_bperp = Inkscape::Snapper::SnapConstraint(origin, *bperp_point);
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, *bperp_point));
}
- // TODO: combine the snap and non-snap branches by modifying snap.h / snap.cpp
- if (snap) {
- if (line_front) {
- fp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos,
- _snapSourceType()), *line_front);
- }
- if (line_back) {
- bp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos,
- _snapSourceType()), *line_back);
- }
- if (line_fperp) {
- fpp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos,
- _snapSourceType()), *line_fperp);
- }
- if (line_bperp) {
- bpp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos,
- _snapSourceType()), *line_bperp);
- }
- }
- if (fp.getSnapped() || bp.getSnapped() || fpp.getSnapped() || bpp.getSnapped()) {
- if (fp.isOtherSnapBetter(bp, false)) {
- fp = bp;
- }
- if (fp.isOtherSnapBetter(fpp, false)) {
- fp = fpp;
- }
- if (fp.isOtherSnapBetter(bpp, false)) {
- fp = bpp;
- }
- fp.getPoint(new_pos);
- _desktop->snapindicator->set_new_snaptarget(fp);
- } else {
- boost::optional<Geom::Point> pos;
- if (line_front) {
- pos = line_front->projection(new_pos);
- }
- if (line_back) {
- Geom::Point pos2 = line_back->projection(new_pos);
- if (!pos || (pos && Geom::distance(new_pos, *pos) > Geom::distance(new_pos, pos2)))
- pos = pos2;
- }
- if (line_fperp) {
- Geom::Point pos2 = line_fperp->projection(new_pos);
- if (!pos || (pos && Geom::distance(new_pos, *pos) > Geom::distance(new_pos, pos2)))
- pos = pos2;
- }
- if (line_bperp) {
- Geom::Point pos2 = line_bperp->projection(new_pos);
- if (!pos || (pos && Geom::distance(new_pos, *pos) > Geom::distance(new_pos, pos2)))
- pos = pos2;
- }
- if (pos) {
- new_pos = *pos;
- } else {
- new_pos = origin;
- }
- }
+ sp = sm.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), constraints, held_shift(*event));
} else {
// with Ctrl, constrain to axes
- // TODO combine the two branches
- if (snap) {
- Inkscape::Snapper::SnapConstraint line_x(origin, Geom::Point(1, 0));
- Inkscape::Snapper::SnapConstraint line_y(origin, Geom::Point(0, 1));
- fp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), line_x);
- bp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), line_y);
- }
- if (fp.getSnapped() || bp.getSnapped()) {
- if (fp.isOtherSnapBetter(bp, false)) {
- fp = bp;
- }
- fp.getPoint(new_pos);
- _desktop->snapindicator->set_new_snaptarget(fp);
- } else {
- Geom::Point origin = _last_drag_origin();
- Geom::Point delta = new_pos - origin;
- Geom::Dim2 d = (fabs(delta[Geom::X]) < fabs(delta[Geom::Y])) ? Geom::X : Geom::Y;
- new_pos[d] = origin[d];
- }
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, Geom::Point(1, 0)));
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, Geom::Point(0, 1)));
+ sp = sm.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), constraints, held_shift(*event));
}
+ new_pos = sp.getPoint();
} else if (snap) {
- Inkscape::SnappedPoint p = sm.freeSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()));
- if (p.getSnapped()) {
- p.getPoint(new_pos);
- _desktop->snapindicator->set_new_snaptarget(p);
- }
+ sp = sm.freeSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()));
+ new_pos = sp.getPoint();
}
+ sm.unSetup();
+
SelectableControlPoint::dragged(new_pos, event);
}
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 :