Integration: #1002 Cmd borrows the last-used selection tool

Holding Cmd/Ctrl with a non-selection tool borrows whichever of Selection and Direct Selection was chosen last, instead of a fixed tool per tool family. The session records the last chosen selection tool; the busy() guard stays.
This commit is contained in:
aiongg
2026-10-16 04:33:07 +00:00
parent 6a22e38b1e
commit 7e539fee8d
4 changed files with 42 additions and 15 deletions
+5 -2
View File
@@ -329,9 +329,11 @@ pub struct Session {
pub prefs: Prefs,
pub cache: Arc<Cache>,
pub(crate) tool: Box<dyn designcraft_tools::Tool>,
/// 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<Box<dyn designcraft_tools::Tool>>,
/// 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<cmd::find::FindContext>,
pub clipboard: Option<Arc<Document>>,
@@ -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,
+26 -3
View File
@@ -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();
+10 -9
View File
@@ -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();
+1 -1
View File
@@ -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 | ✓ | ✓ | ✓ | |