mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-15 21:57:04 +00:00
Align: a rejected select.key keeps the key anchor that was set
select.key {id, anchor} set the new key anchor before checking it, so a
point that is in the selection but not on the path cleared the key
anchor and then returned an error. The point is now checked first: an
anchor the path does not have is not a selected anchor point, and the
other conditions are checked on a copy of the selection.
This commit is contained in:
@@ -670,14 +670,20 @@ fn key_anchor(s: &mut Session, id: Option<NodeId>, guide: Option<usize>, v: &Val
|
||||
return Err(bad(C, "give `anchor` or `guide`, not both"));
|
||||
}
|
||||
let id = id.ok_or_else(|| bad(C, "`anchor` needs `id`, the path the point is on"))?;
|
||||
let sel = &s.doc()?.selection;
|
||||
if sel.segments.contains_key(&id) || !sel.anchors.get(&id).is_some_and(|set| set.contains(&r)) {
|
||||
let st = s.doc()?;
|
||||
let sel = &st.selection;
|
||||
let on_path = st.doc.node(id).and_then(|n| n.path_data()).is_some_and(|p| p.subpaths.get(r.0).is_some_and(|sp| r.1 < sp.anchors.len()));
|
||||
if !on_path || sel.segments.contains_key(&id) || !sel.anchors.get(&id).is_some_and(|set| set.contains(&r)) {
|
||||
return Err(bad(C, format!("anchor [{}, {}] of object {id} is not a selected anchor point", r.0, r.1)));
|
||||
}
|
||||
s.select(|_, sel| sel.key_anchor = Some((id, r)))?;
|
||||
if s.doc()?.selection.key_anchor.is_none() {
|
||||
// Check the new key on a copy first, so a request that fails leaves the key as it was.
|
||||
let mut trial = sel.clone();
|
||||
trial.key_anchor = Some((id, r));
|
||||
trial.prune(&st.doc);
|
||||
if trial.key_anchor.is_none() {
|
||||
return Err(bad(C, "select another anchor point to align to the key anchor"));
|
||||
}
|
||||
s.select(|_, sel| sel.key_anchor = Some((id, r)))?;
|
||||
key_result(s)
|
||||
}
|
||||
|
||||
|
||||
@@ -147,3 +147,16 @@ fn select_key_rejects_an_anchor_that_cannot_be_the_key() {
|
||||
assert!(err(&mut s, json!({"id": a.0, "anchor": [0, 0]})).contains("is not a selected anchor point"));
|
||||
assert_eq!(key_anchor(&s), None, "the key stays as it was");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_rejected_select_key_keeps_the_key_anchor() {
|
||||
let mut s = session();
|
||||
let a = path(&mut s, "M100 40 L200 60 L150 160 Z");
|
||||
s.execute("select.anchors", &json!({"id": a.0, "anchors": [[0, 0], [0, 9]], "mode": "set"})).unwrap();
|
||||
s.execute("select.anchors", &json!({"id": a.0, "anchors": [[0, 1]], "mode": "add"})).unwrap();
|
||||
assert_eq!(key_anchor(&s), Some((a, (0, 1))));
|
||||
// [0, 9] is in the selection but not on the path.
|
||||
let err = s.execute("select.key", &json!({"id": a.0, "anchor": [0, 9]})).expect_err("a point the path does not have").to_string();
|
||||
assert!(err.contains("is not a selected anchor point"), "{err}");
|
||||
assert_eq!(key_anchor(&s), Some((a, (0, 1))), "the key stays as it was");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user