mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-14 14:41:52 +00:00
Dimension tool: the first preview of a drag-out is drawn at the pointer
Dragging out a dimension from a segment (Linear) or a corner (Angular) drew its first preview frame at the wrong distance. The preview placed the dimension at the pointer before reading the segment's end points or the corner from the art, and measured the offset from the placeholder points the dimension starts with. A drag from the top edge of a rectangle to 40 pt above it showed an offset of 60 instead of -40. The preview now clears the offset, reads the art's points, places the dimension at the pointer and checks the result. Clearing the offset keeps an out-of-range offset from the last pointer position from failing the read. Tests: the segment and corner drag-out tests fail without the change. placement_recovers_after_a_position_out_of_range also passes on main; it fails when only the offset clear is removed.
This commit is contained in:
@@ -344,10 +344,19 @@ impl DimensionTool {
|
||||
_ => Orientation::Aligned,
|
||||
};
|
||||
}
|
||||
d.place(p);
|
||||
// A dimension dragged out from art starts with placeholder points. Read the art's points
|
||||
// before placing the dimension at the pointer. Clear the offset first: an out-of-range
|
||||
// offset from the last pointer position fails the read.
|
||||
if !matches!(d.mode, DimensionMode::Radius | DimensionMode::Diameter) {
|
||||
d.offset = 0.0;
|
||||
}
|
||||
if d.resolve(cx.doc).is_err() {
|
||||
return vec![];
|
||||
}
|
||||
d.place(p);
|
||||
if d.validate().is_err() {
|
||||
return vec![];
|
||||
}
|
||||
let mut actions = vec![];
|
||||
if !self.began {
|
||||
actions.push(Action::Begin("Create Dimension".into()));
|
||||
@@ -675,6 +684,53 @@ mod tests {
|
||||
assert!(matches!(placed.last(), Some(Action::Commit)), "{placed:?}");
|
||||
}
|
||||
|
||||
/// A pointer position too far away to place the dimension shows no preview, and the preview
|
||||
/// comes back where the pointer returns.
|
||||
#[test]
|
||||
fn placement_recovers_after_a_position_out_of_range() {
|
||||
let (d, _) = doc_with_rect();
|
||||
let (s, p) = (Selection::default(), paint());
|
||||
let c = cx(&d, &s, &p);
|
||||
let mut t = DimensionTool::default();
|
||||
for (x, y) in [(400.0, 400.0), (450.0, 400.0)] {
|
||||
t.pointer(&c, &PointerEvent::new(PointerKind::Down, x, y));
|
||||
t.pointer(&c, &PointerEvent::new(PointerKind::Up, x, y));
|
||||
}
|
||||
assert!(t.pointer(&c, &PointerEvent::new(PointerKind::Move, 420.0, 3.0e6)).is_empty());
|
||||
let acts = t.pointer(&c, &PointerEvent::new(PointerKind::Move, 420.0, 450.0));
|
||||
let Some(Action::Preview(_, params)) = acts.last() else { panic!("{acts:?}") };
|
||||
assert_eq!(params["offset"], json!(50.0));
|
||||
}
|
||||
|
||||
/// Dragging out from a segment previews the dimension at the pointer from the first drag on.
|
||||
#[test]
|
||||
fn the_first_preview_of_a_segment_drag_is_at_the_pointer() {
|
||||
let (d, _) = doc_with_rect();
|
||||
let (s, p) = (Selection::default(), paint());
|
||||
let c = cx(&d, &s, &p);
|
||||
let mut t = DimensionTool::default();
|
||||
t.pointer(&c, &PointerEvent::new(PointerKind::Down, 150.0, 100.0));
|
||||
let acts = t.pointer(&c, &PointerEvent::new(PointerKind::Drag, 150.0, 60.0));
|
||||
let Some(Action::Preview(_, params)) = acts.last() else { panic!("{acts:?}") };
|
||||
assert_eq!(params["offset"], json!(-40.0), "40 pt above the top edge");
|
||||
}
|
||||
|
||||
/// Dragging out from a corner previews the angle at the pointer's distance from the corner
|
||||
/// from the first drag on.
|
||||
#[test]
|
||||
fn the_first_preview_of_a_corner_drag_is_at_the_pointer() {
|
||||
let (d, _) = doc_with_rect();
|
||||
let (s, p) = (Selection::default(), paint());
|
||||
let c = cx(&d, &s, &p);
|
||||
let mut t = DimensionTool::default();
|
||||
t.set_option("mode", &json!("angular"));
|
||||
t.pointer(&c, &PointerEvent::new(PointerKind::Down, 100.0, 100.0));
|
||||
let acts = t.pointer(&c, &PointerEvent::new(PointerKind::Drag, 130.0, 140.0));
|
||||
let Some(Action::Preview(_, params)) = acts.last() else { panic!("{acts:?}") };
|
||||
assert_eq!(params["vertex"], json!([100.0, 100.0]));
|
||||
assert_eq!(params["offset"], json!(50.0), "50 pt from the corner");
|
||||
}
|
||||
|
||||
/// A Linear press on an anchor picks that anchor even when the pointer moves a few pixels
|
||||
/// before the release: it does not drag out the dimension of a segment that ends there. Both
|
||||
/// picks keep their links to the path, so the dimension measures between the two anchors.
|
||||
|
||||
Reference in New Issue
Block a user