Copy and paste guides: Cut takes the selected guides with the objects

Cut with objects and ruler guides selected now removes both, in one
undo step: edit.clear takes guides: true beside ids to delete the
selected guides with the objects it names.
This commit is contained in:
Don Omondi
2026-11-04 20:11:59 +07:00
committed by bflatastic
parent f3faa115c6
commit 484a78f812
2 changed files with 16 additions and 4 deletions
+6 -4
View File
@@ -193,7 +193,7 @@ pub fn specs() -> Vec<CommandSpec> {
"Clear",
["Edit"],
Some("Delete"),
"{ids?} delete the objects `ids`, else the selection (fully selected objects and direct-selected anchors together, else ruler guides)",
"{ids?, guides?: bool (with ids: also delete the selected ruler guides)} delete the objects `ids`, else the selection (fully selected objects and direct-selected anchors together, else ruler guides)",
has_selection_or_guides,
clear
),
@@ -712,7 +712,8 @@ fn cut(s: &mut Session, p: &Value) -> Result<Value> {
}
let ids = selected_roots(s)?;
copy(s, p)?;
if s.doc()?.selection.anchors.is_empty() { clear(s, &json!({ "ids": ids })) } else { clear(s, &json!({})) }
// The selected ruler guides it copied go with the objects, in the same undo step (#3226).
if s.doc()?.selection.anchors.is_empty() { clear(s, &json!({ "ids": ids, "guides": true })) } else { clear(s, &json!({})) }
}
fn clear(s: &mut Session, p: &Value) -> Result<Value> {
@@ -726,8 +727,9 @@ fn clear(s: &mut Session, p: &Value) -> Result<Value> {
return super::docmenu::guide_remove(s, &json!({}));
}
let st = s.doc()?;
// Guides selected with the art go with it (not when ids are given).
let with_guides = explicit.is_none();
// Guides selected with the art go with it (not when ids are given, unless `guides` says so:
// Cut, which names the objects it copied).
let with_guides = explicit.is_none() || bool_or(p, "guides", false);
let targets = explicit.unwrap_or_else(|| st.selection.in_paint_order(&st.doc));
// Keep the selected ids themselves, without promoting compound members. Delete a selected
// ancestor just once; its selected descendants leave with it. Layers themselves are kept.
@@ -64,6 +64,16 @@ fn guides_paste_in_place_onto_another_artboard_and_cut_removes_them() {
let mut at: Vec<f64> = guides(&s).iter().map(|g| g.1).collect();
at.sort_by(f64::total_cmp);
assert_eq!(at, [a.x0 + 30.0, b.x0 + 30.0, b.x0 + 30.0]);
// Cut with an object and a guide selected takes both away, in one undo step.
let rect = run(&mut s, "shape.rectangle", json!({"x": 10, "y": 10, "width": 20, "height": 20}))["id"].as_u64().unwrap();
let before = guides(&s).len();
run(&mut s, "select.set", json!({"ids": [rect]}));
run(&mut s, "guide.select", json!({"indexes": [0], "toggle": true}));
let undo = s.doc().unwrap().history.undo.len();
run(&mut s, "edit.cut", json!({}));
assert!(s.doc().unwrap().doc.node(NodeId(rect)).is_none());
assert_eq!(guides(&s).len(), before - 1, "the selected guide goes too");
assert_eq!(s.doc().unwrap().history.undo.len(), undo + 1);
// Nothing selected: Copy is off.
run(&mut s, "select.none", json!({}));
assert!(s.execute("edit.copy", &json!({})).is_err());