collective

Browse / github.com/storytold/vectorcraft / patch

Fix #4237: Add Anchor Point selects the path it adds to

After using Add Anchor Points tool - line does not get active Tool works and adds anchor points, but it does not activate line, where anchor points was added and i can see result only after clicking it with direct selection tool.

Status
open
Score
0.00
Adopters
0 other operators
Author
Hassan1305 (imported from pull request #4325, open)
Base
443b31b13df3a7ab611c2fe1b95e73898ed74fdd
Size
+34 −2 in 2 files
Review
pending
Shared
2026-10-28
Id
3aaa62f876fafe401b431d90

How it went

No other operator has reported using it yet.

Diff

raw · crates/engine/src/cmd/path.rs crates/engine/src/tests/draw2.rs

diff --git a/crates/engine/src/cmd/path.rs b/crates/engine/src/cmd/path.rs--- a/crates/engine/src/cmd/path.rs+++ b/crates/engine/src/cmd/path.rs@@ -798,13 +798,21 @@ fn insert_anchor(s: &mut Session, p: &Value) -> Result<Value> {     let si = usize_opt(p, "subpath", "path.insertAnchor")?.unwrap_or(0);     let seg = p.get("segment").and_then(Value::as_u64).map(index).ok_or_else(|| bad("path.insertAnchor", "missing segment"))?;     let t = number_or(p, "t", 0.5, "path.insertAnchor")?.clamp(0.0, 1.0);-    let idx = s.edit("Add Anchor Point", |d, _| {+    let idx = s.edit("Add Anchor Point", |d, sel| {         let path = path_mut(d, id)?;         let sp = path.subpaths.get_mut(si).ok_or_else(|| EngineError::Other("no such subpath".into()))?;         if seg >= sp.segment_count() {             return Err(EngineError::Other("no such segment".into()));         }-        Ok(sp.insert_anchor(seg, t))+        let idx = sp.insert_anchor(seg, t);+        // A path that wasn't selected becomes the selection, its new anchor direct-selected, so+        // the point added shows and can be edited at once (#4237).+        if !sel.contains(id) {+            sel.clear();+            sel.add(id);+            sel.anchors.entry(id).or_default().insert((si, idx));+        }+        Ok(idx)     })?;     Ok(json!({ "anchor": idx })) }diff --git a/crates/engine/src/tests/draw2.rs b/crates/engine/src/tests/draw2.rs--- a/crates/engine/src/tests/draw2.rs+++ b/crates/engine/src/tests/draw2.rs@@ -1737,6 +1737,30 @@ fn remove_anchor_points_keeps_the_paths_closed() {     assert_eq!(spec.menu, &["Object", "Path"][..]); } +#[test]+fn add_anchor_point_selects_the_path_it_was_added_to() {+    // #4237: an anchor added to a path that wasn't selected selects that path, the new anchor+    // direct-selected, so it shows at once; undo puts the old selection back. A path already+    // selected (the Pen's Auto Add) keeps its selection.+    let mut s = session();+    let other = rect(&mut s, 300.0, 0.0, 50.0, 50.0);+    let line = |s: &mut Session| {+        NodeId(s.execute("path.create", &json!({"anchors": [{"x": 0, "y": 0}, {"x": 100, "y": 0}]})).unwrap()["id"].as_u64().unwrap())+    };+    let id = line(&mut s);+    s.execute("select.set", &json!({"ids": [other.0]})).unwrap();+    s.execute("path.insertAnchor", &json!({"id": id.0, "segment": 0, "t": 0.5})).unwrap();+    assert_eq!(s.doc().unwrap().selection.objects, [id]);+    assert_eq!(selected_anchors(&s, id), [(0, 1)]);+    s.execute("edit.undo", &json!({})).unwrap();+    assert_eq!(s.doc().unwrap().selection.objects, [other]);+    let kept = line(&mut s);+    s.execute("select.set", &json!({"ids": [kept.0]})).unwrap();+    s.execute("path.insertAnchor", &json!({"id": kept.0, "segment": 0, "t": 0.5})).unwrap();+    assert_eq!(s.doc().unwrap().selection.objects, [kept]);+    assert!(selected_anchors(&s, kept).is_empty(), "a path selected as a whole stays so");+}+ fn selected_anchors(s: &Session, id: NodeId) -> Vec<(usize, usize)> {     s.doc().unwrap().selection.anchors.get(&id).map(|set| set.iter().copied().collect()).unwrap_or_default() }