mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-01 21:57:12 -06:00
Fix #4980: Pen with Cmd/Ctrl drags the path, not hidden bounding-box handles
Cmd/Ctrl held with the Pen lends the last-used selection tool (Direct Selection until one is chosen), which already moved anchors, straight segments and curves of the path being drawn, one undo step each, and handed the path back to the Pen. With the Selection tool used last, the lent tool hit-tested the bounding box even though the canvas hides it while anchors are selected on their own, as the end anchor of a path being drawn is. Over the path it showed a resize pointer, and the drag scaled the path by a handle nobody could see: a flat path did nothing at all. The Selection tool's handles now take the pointer only while the box is shown (View > Show Bounding Box, no anchors selected on their own), so the lent Selection tool moves the path being drawn. Tests: select::tests::hidden_box_handles_take_no_press_while_anchors_are_selected, tests::draw2::pen_cmd_drag_edits_anchors_and_segments_and_goes_on_drawing.
This commit is contained in:
@@ -2579,6 +2579,60 @@ fn pen_with_cmd_borrows_direct_selection_and_goes_on_drawing() {
|
||||
assert_eq!(s.tool_id(), "rectangle");
|
||||
}
|
||||
|
||||
/// #4980: Cmd/Ctrl held with the Pen drags as Direct Selection: an anchor of the path being drawn
|
||||
/// moves on its own and the Pen goes on drawing that path from it; another path's straight segment
|
||||
/// moves both its ends and a curved one bends; each drag is one undo step and the pointer is the
|
||||
/// Pen's again once Cmd is let go. With the Selection tool used last, a Cmd drag on the path being
|
||||
/// drawn moves it: the bounding box isn't shown, so its handles don't scale it to nothing.
|
||||
#[test]
|
||||
fn pen_cmd_drag_edits_anchors_and_segments_and_goes_on_drawing() {
|
||||
let (none, cmd) = (Mods::default(), Mods { cmd: true, ..Mods::default() });
|
||||
let v = view();
|
||||
let mut s = session();
|
||||
let straight = line(&mut s, 100.0, 500.0, 300.0, 500.0);
|
||||
let anchors = json!([{"x": 400, "y": 500, "out": [450, 400]}, {"x": 600, "y": 500, "in": [550, 400]}]);
|
||||
let curve = NodeId(s.execute("path.create", &json!({"anchors": anchors})).unwrap()["id"].as_u64().unwrap());
|
||||
s.execute("select.none", &json!({})).unwrap();
|
||||
s.select_tool("pen", v).unwrap();
|
||||
for x in [100.0, 200.0, 300.0] {
|
||||
gesture(&mut s, &[(x, 100.0)], none);
|
||||
}
|
||||
let id = s.doc().unwrap().selection.objects[0];
|
||||
let points = |s: &Session, id| path(s, id).subpaths[0].anchors.iter().map(|a| (a.p.x, a.p.y)).collect::<Vec<_>>();
|
||||
assert_eq!(gesture(&mut s, &[(200.0, 100.0), (205.0, 120.0), (210.0, 140.0)], cmd), 1);
|
||||
assert_eq!(points(&s, id), [(100.0, 100.0), (210.0, 140.0), (300.0, 100.0)]);
|
||||
assert_eq!(s.tool_id(), "pen");
|
||||
let pen = s.cursor(Point::new(700.0, 300.0), none, v);
|
||||
assert!(matches!(pen, vectorcraft_tools::Cursor::Pen | vectorcraft_tools::Cursor::PenDrawing), "{pen:?}");
|
||||
// The next click goes on drawing the same path from its end.
|
||||
gesture(&mut s, &[(400.0, 200.0)], none);
|
||||
assert_eq!(paths(&s).len(), 3, "no new path");
|
||||
assert_eq!(path(&s, id).subpaths[0].anchors.len(), 4);
|
||||
assert_eq!(gesture(&mut s, &[(200.0, 500.0), (200.0, 510.0), (200.0, 530.0)], cmd), 1);
|
||||
assert_eq!(points(&s, straight), [(100.0, 530.0), (300.0, 530.0)]);
|
||||
let before = path(&s, curve).subpaths[0].anchors.clone();
|
||||
assert_eq!(gesture(&mut s, &[(500.0, 425.0), (500.0, 410.0), (500.0, 380.0)], cmd), 1);
|
||||
let after = &path(&s, curve).subpaths[0].anchors;
|
||||
assert_eq!((after[0].p, after[1].p), (before[0].p, before[1].p), "the ends stay");
|
||||
assert!(after[0].h_out.y < before[0].h_out.y && after[1].h_in.y < before[1].h_in.y, "{after:?}");
|
||||
// A Cmd-click away from the art deselects: the path is done, the next click starts another.
|
||||
gesture(&mut s, &[(700.0, 300.0)], cmd);
|
||||
assert!(s.doc().unwrap().selection.is_empty());
|
||||
gesture(&mut s, &[(700.0, 50.0)], none);
|
||||
assert_eq!(paths(&s).len(), 4);
|
||||
// Selection used last, a flat path being drawn: a Cmd drag where its box's top handle would be moves it.
|
||||
s.select_tool("selection", v).unwrap();
|
||||
s.execute("select.none", &json!({})).unwrap();
|
||||
s.select_tool("pen", v).unwrap();
|
||||
gesture(&mut s, &[(100.0, 300.0)], none);
|
||||
gesture(&mut s, &[(300.0, 300.0)], none);
|
||||
let flat = s.doc().unwrap().selection.objects[0];
|
||||
assert_ne!(s.cursor(Point::new(200.0, 300.0), cmd, v), vectorcraft_tools::Cursor::ResizeV);
|
||||
assert_eq!(gesture(&mut s, &[(200.0, 300.0), (200.0, 320.0), (200.0, 340.0)], cmd), 1);
|
||||
assert_eq!(points(&s, flat), [(100.0, 340.0), (300.0, 340.0)]);
|
||||
assert_eq!(s.tool_id(), "pen");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cmd_alt_lends_group_selection_while_direct_selection_is_active() {
|
||||
let (cmd, cmd_alt) = (Mods { cmd: true, ..Mods::default() }, Mods { cmd: true, alt: true, ..Mods::default() });
|
||||
|
||||
Reference in New Issue
Block a user