diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs index 6f890e4ac..95e822fdd 100644 --- a/crates/engine/src/lib.rs +++ b/crates/engine/src/lib.rs @@ -329,9 +329,11 @@ pub struct Session { pub prefs: Prefs, pub cache: Arc, pub(crate) tool: Box, - /// The Selection (or Direct Selection) tool a Cmd-held press borrows for one gesture while - /// another tool stays chosen, as InDesign's Cmd/Ctrl does (#919). Dropped on release. + /// The selection tool a Cmd-held press borrows for one gesture while another tool stays + /// chosen (#919). Dropped on release. pub(crate) temp_tool: Option>, + /// The selection tool (`selection` or `directSelection`) chosen last: the one Cmd borrows. + pub(crate) last_selection_tool: &'static str, pub journal: Vec<(String, Value)>, pub(crate) find_context: Option, pub clipboard: Option>, @@ -394,6 +396,7 @@ impl Session { cache: Arc::new(Cache::new()), tool: designcraft_tools::create("selection"), temp_tool: None, + last_selection_tool: "selection", journal: vec![], find_context: None, clipboard: None, diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 9816a3649..9aacf469d 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -56,7 +56,7 @@ fn smart_quotes_and_formatting() { } /// Issue #919: with Cmd held, a press with the Type (or any drawing) tool selects and drags like -/// the Selection tool, and the chosen tool stays; the Pen family borrows Direct Selection. +/// the Selection tool, and the chosen tool stays. #[test] fn cmd_held_press_borrows_the_selection_tool_for_one_gesture() { use designcraft_tools::{Mods, PointerEvent, PointerKind}; @@ -86,14 +86,37 @@ fn cmd_held_press_borrows_the_selection_tool_for_one_gesture() { s.pointer(&PointerEvent::new(PointerKind::Down, 200.0, 150.0).with_mods(cmd), v).unwrap(); assert!(s.temp_tool.is_none()); s.pointer(&PointerEvent::new(PointerKind::Up, 200.0, 150.0).with_mods(cmd), v).unwrap(); - // The Pen borrows the Direct Selection tool. s.set_tool("pen"); s.pointer(&PointerEvent::new(PointerKind::Down, 200.0, 150.0).with_mods(cmd), v).unwrap(); - assert_eq!(s.temp_tool.as_ref().map(|t| t.id()), Some("directSelection")); + assert_eq!(s.temp_tool.as_ref().map(|t| t.id()), Some("selection")); s.pointer(&PointerEvent::new(PointerKind::Up, 200.0, 150.0).with_mods(cmd), v).unwrap(); assert_eq!(s.tool_id(), "pen"); } +/// Cmd borrows whichever selection tool was chosen last, whatever the chosen tool is. +#[test] +fn cmd_borrows_the_last_used_selection_tool() { + use designcraft_tools::{Mods, PointerEvent, PointerKind}; + let mut s = session(); + let v = ViewInfo::at_zoom(1.0); + let cmd = Mods { cmd: true, ..Mods::default() }; + let borrowed = |s: &mut Session| { + s.pointer(&PointerEvent::new(PointerKind::Down, 400.0, 400.0).with_mods(cmd), v).unwrap(); + let id = s.temp_tool.as_ref().map(|t| t.id()); + s.pointer(&PointerEvent::new(PointerKind::Up, 400.0, 400.0).with_mods(cmd), v).unwrap(); + id + }; + s.set_tool("directSelection"); + s.set_tool("rectangle"); + assert_eq!(borrowed(&mut s), Some("directSelection")); + s.set_tool("selection"); + s.set_tool("rectangle"); + assert_eq!(borrowed(&mut s), Some("selection")); + s.set_tool("directSelection"); + s.set_tool("pen"); + assert_eq!(borrowed(&mut s), Some("directSelection")); +} + #[test] fn tool_gesture_creates_one_undo_step() { let mut s = session(); diff --git a/crates/engine/src/tooling.rs b/crates/engine/src/tooling.rs index 47f1ff6c0..c58236090 100644 --- a/crates/engine/src/tooling.rs +++ b/crates/engine/src/tooling.rs @@ -66,6 +66,9 @@ impl Session { } self.tool = designcraft_tools::create(id); self.temp_tool = None; + if matches!(self.tool.id(), "selection" | "directSelection") { + self.last_selection_tool = self.tool.id(); + } // Any other tool unloads the place cursor. if id != "placeGun" { self.loaded = None; @@ -118,15 +121,13 @@ impl Session { } } - /// Which selection tool a Cmd-held press borrows while `tool` is chosen, as InDesign's - /// Cmd/Ctrl does: the Direct Selection tool for the Pen family and Pencil, the Selection - /// tool for the drawing, type and other tools; none for the selection tools themselves, + /// Which selection tool a Cmd-held press borrows while another tool is chosen: whichever of + /// Selection and Direct Selection was chosen last. None for the selection tools themselves, /// Hand, Zoom and a loaded place cursor, where Cmd means something else or nothing. - fn borrowed_selection_tool(tool: &str) -> Option<&'static str> { - match tool { + fn borrowed_selection_tool(&self) -> Option<&'static str> { + match self.tool.id() { "selection" | "directSelection" | "hand" | "zoom" | "placeGun" => None, - "pen" | "addAnchor" | "deleteAnchor" | "convertDirection" | "pencil" | "smooth" | "erase" | "scissors" => Some("directSelection"), - _ => Some("selection"), + _ => Some(self.last_selection_tool), } } @@ -142,7 +143,7 @@ impl Session { && ev.mods.cmd && self.temp_tool.is_none() && !self.tool.busy() - && let Some(id) = Self::borrowed_selection_tool(self.tool.id()) + && let Some(id) = self.borrowed_selection_tool() { self.temp_tool = Some(designcraft_tools::create(id)); } @@ -181,7 +182,7 @@ impl Session { if mods.cmd && self.temp_tool.is_none() && !self.tool.busy() - && let Some(id) = Self::borrowed_selection_tool(self.tool.id()) + && let Some(id) = self.borrowed_selection_tool() { let borrowed = designcraft_tools::create(id); return self.with_ctx(view, |_, cx| borrowed.cursor(cx, p, mods)).unwrap_or_default(); diff --git a/docs/ui-parity.md b/docs/ui-parity.md index fe276cfde..73d548b5b 100644 --- a/docs/ui-parity.md +++ b/docs/ui-parity.md @@ -28,7 +28,7 @@ basics of editing fail for too many users on Windows and Linux. |---|---|---|---|---| | Chrome: app bar, Control panel, Tools panel, dock, doc tabs, status bar | Medium Dark, measured sizes | measured look | ✓ | 11-observed-ui.md | | Properties panel and Contextual Task Bar | per selection | ✓, task bar movable (#143) | ✓ | | -| Selection tool: click, marquee, move, Alt-duplicate, resize handles, rotate from corners | ✓ | ✓ | ✓ | Cmd/Ctrl held with another tool borrows it for one gesture (Direct Selection with the Pen family), #919 | +| Selection tool: click, marquee, move, Alt-duplicate, resize handles, rotate from corners | ✓ | ✓ | ✓ | Cmd/Ctrl held with another tool borrows the selection tool used last (Selection or Direct Selection) for one gesture, #919 | | Direct Selection, Pen family, Pencil, Scissors | ✓ | ✓ | ~ | moving reference point "0" fails (#337) | | Live corners (yellow handle) | ✓ | ✓ widget on a selected rectangle frame; diamonds drag the corner size (Shift: one corner), Alt-click steps the shape (Shift+Alt: all) | ✓ | #186 | | Content grabber, frame fitting by double-click | ✓ | ✓ | ✓ | |