Merge pull request #7037 from dotCooCoo/fix/move-guide-snap-tolerance

Smart Guides: a moved selection reaches ruler guides within the Snapping Tolerance
This commit is contained in:
BFlat
2026-11-13 12:27:26 +07:00
committed by GitHub
2 changed files with 39 additions and 5 deletions
+5 -4
View File
@@ -239,7 +239,8 @@ pub(crate) struct MoveSnap {
copy_targets: Option<Targets>,
copy_points: Option<Targets>,
/// With Smart Guides on, the ruler guides View › Snap to Point still pulls the grabbed point
/// onto (#1534), and lines the bounds up with (#5746); `points` holds them with Smart Guides off.
/// onto (#1534), and lines the bounds up with (#5746), within the Snapping Tolerance as drawing
/// does; `points` holds them with Smart Guides off.
rulers: Option<Targets>,
}
@@ -303,7 +304,7 @@ impl MoveSnap {
// axis without one that Smart Guides left free, the bounds line up with the ruler guides
// (#5746), alongside the Smart Guides.
if let Some(t) = &self.rulers {
let (adj, ov, held) = t.snap_moved_to_rulers(start + d, self.bounds.map(|b| b + d), cx.tol(cx.snap_tolerance), taken);
let (adj, ov, held) = t.snap_moved_to_rulers(start + d, self.bounds.map(|b| b + d), cx.snap_tol(), taken);
if adj != Vec2::ZERO {
d += adj;
if held {
@@ -373,7 +374,7 @@ impl MoveSnap {
}
}
if let Some(t) = &self.rulers {
let (q, ov) = t.snap_point_along(start + d, u, cx.tol(cx.snap_tolerance));
let (q, ov) = t.snap_point_along(start + d, u, cx.snap_tol());
if q != start + d {
d = q - start;
guides = ov;
@@ -382,7 +383,7 @@ impl MoveSnap {
{
// Nothing else lined up: the bounds slide along the line onto a ruler guide, as
// they do without Shift (#4312).
let (adj, ov) = t.snap_moved_along_to_rulers(start + d, b + d, u, cx.tol(cx.snap_tolerance));
let (adj, ov) = t.snap_moved_along_to_rulers(start + d, b + d, u, cx.snap_tol());
d += adj;
guides = ov;
}
+34 -1
View File
@@ -751,7 +751,7 @@ fn escape_cancels_a_move_or_an_alt_drag_copy() {
}
/// #1534: with Smart Guides on (the default), the point a selection is dragged by still snaps
/// to a ruler guide within the Snap to Point distance; not with Snap to Point off.
/// to a ruler guide within the Snapping Tolerance; not with Snap to Point off.
#[test]
fn a_move_snaps_the_grabbed_point_to_a_ruler_guide_with_smart_guides_on() {
let (mut d, id) = doc_with_rect();
@@ -797,6 +797,39 @@ fn a_shift_move_lands_the_edges_on_a_ruler_guide() {
assert!(moved_by(m, (231.0, 0.0)), "{m:?}");
}
/// With Smart Guides on, a moved selection reaches a ruler guide within the Snapping Tolerance
/// (4 px), as drawing and handle drags do; with Smart Guides off, Snap to Point reaches it within
/// its own distance (2 px).
#[test]
fn a_move_reaches_ruler_guides_within_the_snapping_tolerance() {
let (mut d, id) = doc_with_rect();
d.add_ruler_guide(&vectorcraft_doc::Guide::new(true, 340.0));
let mut s = Selection::default();
s.add(id);
let p = paint();
let dx = |c: &ToolContext, to: f64| {
let mut t = SelectionTool::default();
t.pointer(c, &ev(PointerKind::Down, 150.0, 150.0));
let a = t.pointer(c, &ev(PointerKind::Drag, to, 150.0));
let Some(Action::Preview(_, v)) = a.last() else { panic!("{a:?}") };
v["matrix"][4].as_f64().unwrap()
};
let c = cx(&d, &s, &p);
assert!(c.smart_guides && c.snap_to_point && c.guides);
// The right edge, 3 px short of the guide, lands on it, with or without Shift.
assert_eq!(dx(&c, 150.0 + 137.0), 140.0);
let (m, _) = shift_moved(&c, (150.0 + 137.0, 150.0));
assert!(moved_by(m, (140.0, 0.0)), "{m:?}");
// The grabbed point, 3 px from the guide, lands on it.
assert_eq!(dx(&c, 337.0), 190.0);
// 5 px away is out of reach.
assert_eq!(dx(&c, 150.0 + 135.0), 135.0);
// Smart Guides off: the grabbed point lands on the guide from 1.5 px, not from 3 px.
let off = ToolContext { smart_guides: false, ..cx(&d, &s, &p) };
assert_eq!(dx(&off, 338.5), 190.0);
assert_eq!(dx(&off, 337.0), 187.0);
}
/// Alt pressed during a move makes a copy, which snaps to the original it leaves behind (as
/// gathered before the previews moved it); released, the move doesn't.
#[test]