diff --git a/crates/engine/src/cmd/page.rs b/crates/engine/src/cmd/page.rs index 8fccd607..8bcd7c40 100644 --- a/crates/engine/src/cmd/page.rs +++ b/crates/engine/src/cmd/page.rs @@ -160,8 +160,11 @@ pub fn specs() -> Vec { } guides.remove(k); let ds = s.ds_mut()?; - if ds.guide == Some((owner, k)) { - ds.guide = None; + match ds.guide { + Some((o, i)) if o == owner && i == k => ds.guide = None, + // A later guide of the same owner moves up one place; keep the selection on it. + Some((o, i)) if o == owner && i > k => ds.guide = Some((o, i - 1)), + _ => {} } ok() }), diff --git a/crates/engine/src/view_behaviour_tests.rs b/crates/engine/src/view_behaviour_tests.rs index c22cd1f5..27bc3771 100644 --- a/crates/engine/src/view_behaviour_tests.rs +++ b/crates/engine/src/view_behaviour_tests.rs @@ -456,6 +456,23 @@ fn a_selected_guide_is_deleted_and_nudged_with_the_keyboard() { assert!(s.execute("guide.select", &json!({"index": 7})).is_err(), "only an existing guide can be selected"); } +#[test] +fn removing_an_earlier_guide_keeps_the_selected_guide() { + let mut s = Session::new(); + for offset in [100, 200, 300] { + ex(&mut s, "guide.add", json!({"vertical": true, "offset": offset})); + } + let page = s.page().unwrap(); + ex(&mut s, "guide.select", json!({"index": 1})); + ex(&mut s, "guide.remove", json!({"index": 0})); + assert_eq!(s.ds().unwrap().selected_guide(), Some((page, 0)), "the guide at 200 stays selected at its new index"); + assert!(s.tool_key("ArrowRight", false, false, false).unwrap()); + assert_eq!(guide_list(&s, page), vec![(true, 201.0), (true, 300.0)], "the arrow nudges the selected guide, not its neighbour"); + // A later guide leaves the selection alone. + ex(&mut s, "guide.remove", json!({"index": 1})); + assert_eq!(s.ds().unwrap().selected_guide(), Some((page, 0))); +} + #[test] fn guides_snap_and_measure() { let mut s = Session::new(); diff --git a/docs/mcp.md b/docs/mcp.md index 38d821f4..7d9aa0de 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -1383,7 +1383,8 @@ siblings and the frame's edges) along those axes, keeping whole pixels in the fr `guide.select {index, frame? | page?}` selects a guide (and deselects the layers; `{}` deselects it), as clicking one does in the app; `guide.remove {}` without an index removes the selected one -(the context menu's Remove guide). While a guide is selected and no layer is, Delete removes it, +(the context menu's Remove guide), and removing another guide keeps the selected one selected. +While a guide is selected and no layer is, Delete removes it, the arrows across it nudge it (Shift: the big nudge) and Escape deselects it. In the app, a guide dragged out of a ruler and dropped on a frame becomes the guide of the top-level frame there, along the frame's axis nearer the ruler's; Alt-dragging a guide drops a copy, and holding Alt while