From c464072ee705747ef3e80b2545365b1607e4fbda Mon Sep 17 00:00:00 2001 From: aiongg Date: Tue, 20 Oct 2026 16:07:19 +0000 Subject: [PATCH] #1298: craft-keymap 9aaf9df (craft-libs#164 review fixes) Keymap::catalog(), Platform's non-exhaustive match, and the web platform from craft_keymap::egui::platform. --- Cargo.lock | 2 +- Cargo.toml | 2 +- crates/ui-egui/src/dialogs.rs | 2 +- crates/ui-egui/src/keys.rs | 51 ++++++++++++++++------------------- crates/ui-egui/src/lib.rs | 2 +- crates/ui-egui/src/menus.rs | 2 +- 6 files changed, 28 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 742a5bbe7..2ceb0c2e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -832,7 +832,7 @@ source = "git+https://github.com/storytold/craft-libs?rev=82a24b006eefa036b43c09 [[package]] name = "craft-keymap" version = "0.1.0" -source = "git+https://github.com/aiongg/craft-libs?rev=1e4ab21708793dbe66ff7e1cfc5b5094c3c9a305#1e4ab21708793dbe66ff7e1cfc5b5094c3c9a305" +source = "git+https://github.com/aiongg/craft-libs?rev=9aaf9dfd3882c12b6aab5604cc2567fc3b64127b#9aaf9dfd3882c12b6aab5604cc2567fc3b64127b" dependencies = [ "egui", "serde", diff --git a/Cargo.toml b/Cargo.toml index 9cc47de24..eb2ee13c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ repository = "https://github.com/storytold/designcraft" # Shared writer; the immutable revision must be published before this consumer. craft-pdf = { git = "https://github.com/storytold/craft-libs", rev = "c3487320b2d1de657b860b3c8abb44e1f2b32bd8", version = "=0.1.0", default-features = false } # Shared keyboard bindings: chords, overrides, conflicts, egui dispatch. -craft-keymap = { git = "https://github.com/aiongg/craft-libs", rev = "1e4ab21708793dbe66ff7e1cfc5b5094c3c9a305", version = "=0.1.0", features = ["egui"] } +craft-keymap = { git = "https://github.com/aiongg/craft-libs", rev = "9aaf9dfd3882c12b6aab5604cc2567fc3b64127b", version = "=0.1.0", features = ["egui"] } # internal designcraft-geom = { path = "crates/geom" } designcraft-color = { path = "crates/color" } diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index ba4759852..7152d6fb8 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -296,7 +296,7 @@ fn keyboard_shortcuts(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) { // UI commands, the panels and the tools. let mut rows: Vec<(String, String, String)> = app .keymap - .catalogue() + .catalog() .iter() .filter(|b| { let ui_command = crate::menus::UI_COMMANDS.iter().any(|c| c.0 == b.command.id); diff --git a/crates/ui-egui/src/keys.rs b/crates/ui-egui/src/keys.rs index 394643a50..3c7f42a9e 100644 --- a/crates/ui-egui/src/keys.rs +++ b/crates/ui-egui/src/keys.rs @@ -1,4 +1,4 @@ -//! Keyboard shortcuts on `craft-keymap`: the catalogue (UI commands, engine commands, panels and +//! Keyboard shortcuts on `craft-keymap`: the catalog (UI commands, engine commands, panels and //! tools with their default keys and menu paths), shortcut text, and the edits that //! `window.setShortcut`, the Keyboard Shortcuts dialog and the shortcut-set importer make. @@ -89,8 +89,8 @@ pub fn command_ref(id: &str, params: &Value) -> CommandRef { } } -/// The browser's operating system as [`note_os`] recorded it, by [`platform_code`]; 0 before the -/// first frame. +/// The browser's operating system as [`note_platform`] recorded it, by [`platform_code`]; 0 +/// before the first frame. static WEB_PLATFORM: AtomicU8 = AtomicU8::new(0); fn platform_code(p: Platform) -> u8 { @@ -98,6 +98,7 @@ fn platform_code(p: Platform) -> u8 { Platform::Mac => 1, Platform::Windows => 2, Platform::Linux => 3, + _ => 0, } } @@ -115,21 +116,10 @@ pub fn platform() -> Platform { } } -/// The platform for an operating system egui reports (on the web, guessed from the browser's user -/// agent). An iPad with a keyboard has ⌘ as on a Mac. -pub fn platform_of(os: egui::os::OperatingSystem) -> Platform { - use egui::os::OperatingSystem as Os; - match os { - Os::Mac | Os::IOS => Platform::Mac, - Os::Windows => Platform::Windows, - Os::Nix | Os::Android | Os::Unknown => Platform::Linux, - } -} - -/// Records the operating system egui reports, which the web build reads from the browser. -pub fn note_os(os: egui::os::OperatingSystem) { +/// Records the platform egui reports, which the web build reads from the browser's user agent. +pub fn note_platform(ctx: &egui::Context) { if cfg!(target_arch = "wasm32") { - WEB_PLATFORM.store(platform_code(platform_of(os)), Ordering::Relaxed); + WEB_PLATFORM.store(platform_code(craft_keymap::egui::platform(ctx)), Ordering::Relaxed); } } @@ -141,7 +131,7 @@ pub fn new_keymap(overrides: Overrides) -> Keymap { /// The keymap for `platform`: the system's own chords are reserved, so neither a user edit nor an /// imported set can take them. pub fn keymap_for(platform: Platform, overrides: Overrides) -> Keymap { - Keymap::new(catalogue().to_vec(), Scopes::new().with_context(TEXT_CONTEXT), platform) + Keymap::new(catalog().to_vec(), Scopes::new().with_context(TEXT_CONTEXT), platform) .with_reserved(craft_keymap::reserved::system(platform)) .with_overrides(overrides) } @@ -149,12 +139,12 @@ pub fn keymap_for(platform: Platform, overrides: Overrides) -> Keymap { /// Every bindable command, in dispatch order: where two share keys the earlier one runs. UI /// commands come first (⌘N is the New Document dialog, not a bare `file.new`), then engine /// commands, panels and tools. -pub fn catalogue() -> &'static [Bindable] { - static CATALOGUE: OnceLock> = OnceLock::new(); - CATALOGUE.get_or_init(build_catalogue) +pub fn catalog() -> &'static [Bindable] { + static CATALOG: OnceLock> = OnceLock::new(); + CATALOG.get_or_init(build_catalog) } -fn build_catalogue() -> Vec { +fn build_catalog() -> Vec { let paths = menu_paths(); // An engine command's own menu placement counts only where no menu row stands: a row there // runs a UI command in its place (File › Save is the Save dialog when needed), and two @@ -334,7 +324,7 @@ mod tests { for p in PLATFORMS { let km = keymap_for(p, Overrides::new()); let reserved: Vec = km - .catalogue() + .catalog() .iter() .flat_map(|b| km.default_bindings(&b.command).into_iter().map(move |d| (b.command.key(), d))) .filter(|(_, d)| km.is_reserved(&d.trigger.chord)) @@ -349,7 +339,7 @@ mod tests { match p { Platform::Mac => "Cmd+Tab", Platform::Windows => "Alt+F4", - Platform::Linux => "Cmd+Alt+F2", + _ => "Cmd+Alt+F2", } } @@ -379,11 +369,16 @@ mod tests { assert_eq!(menus::shortcut_of(&app, "app.palette").as_deref(), Some("Cmd+Enter")); } - /// The web build follows the operating system in the browser's user agent. + /// The web build follows the operating system in the browser's user agent; an iPad counts as a + /// Mac. #[test] fn browser_user_agent_picks_the_platform() { use egui::os::OperatingSystem as Os; - let of = |ua: &str| platform_of(Os::from_user_agent(ua)); + let ctx = egui::Context::default(); + let of = |ua: &str| { + ctx.set_os(Os::from_user_agent(ua)); + craft_keymap::egui::platform(&ctx) + }; let mac = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15"; let ipad = "Mozilla/5.0 (iPad; CPU OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1"; let windows = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"; @@ -394,10 +389,10 @@ mod tests { assert_eq!(of(windows), Platform::Windows); assert_eq!(of(linux), Platform::Linux); assert_eq!(of(android), Platform::Linux); - assert_eq!(platform_of(Os::Unknown), Platform::Linux); // Native builds keep their own platform whatever egui reports. if !cfg!(target_arch = "wasm32") { - note_os(Os::Mac); + ctx.set_os(Os::Mac); + note_platform(&ctx); assert_eq!(platform(), Platform::current()); } } diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index 957ccd836..a1c6574e5 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -1149,7 +1149,7 @@ impl DesignApp { if self.egui_ctx.is_none() { self.egui_ctx = Some(ctx.clone()); } - keys::note_os(ctx.os()); + keys::note_platform(ctx); self.sync_keymap(); self.window_maximized = ctx.input(|i| i.viewport().maximized.unwrap_or(false)); if !self.color_applied { diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs index 4e2392a7b..c680da7c5 100644 --- a/crates/ui-egui/src/menus.rs +++ b/crates/ui-egui/src/menus.rs @@ -2168,7 +2168,7 @@ pub fn tool_shortcut_label(app: &DesignApp, tool: &str) -> Option { /// commands come first: where one shares keys with an engine command (⌘N, ⌘O…) it's the one /// with the dialog. pub fn effective_shortcuts(app: &DesignApp) -> Vec<(String, String)> { - app.keymap.catalogue().iter().filter_map(|b| crate::keys::shortcut(&app.keymap, &b.command).map(|s| (b.command.key(), s))).collect() + app.keymap.catalog().iter().filter_map(|b| crate::keys::shortcut(&app.keymap, &b.command).map(|s| (b.command.key(), s))).collect() } /// A shortcut as written in this app ("Cmd+Alt+Shift+K") from a key press.