From 0ec91bfe01a7ca3a97cf4c7f073ccb13731b11d8 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Wed, 5 Feb 2025 18:30:10 -0800 Subject: [PATCH] Add pin and cut icons; improve menu bar shortcut labels to choose shortest --- .../input_mapper_message_handler.rs | 6 ++--- .../input_mapper/utility_types/misc.rs | 26 +++++++++++++++++-- .../menu_bar/menu_bar_message_handler.rs | 1 + frontend/assets/icon-16px-solid/cut.svg | 5 ++++ .../assets/icon-16px-solid/pin-active.svg | 5 ++++ .../assets/icon-16px-solid/pin-inactive.svg | 4 +++ .../components/widgets/WidgetSection.svelte | 2 +- frontend/src/utility-functions/icons.ts | 6 +++++ 8 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 frontend/assets/icon-16px-solid/cut.svg create mode 100644 frontend/assets/icon-16px-solid/pin-active.svg create mode 100644 frontend/assets/icon-16px-solid/pin-inactive.svg diff --git a/editor/src/messages/input_mapper/input_mapper_message_handler.rs b/editor/src/messages/input_mapper/input_mapper_message_handler.rs index 1af4364a6..87e38346c 100644 --- a/editor/src/messages/input_mapper/input_mapper_message_handler.rs +++ b/editor/src/messages/input_mapper/input_mapper_message_handler.rs @@ -92,11 +92,9 @@ impl InputMapperMessageHandler { .collect::>(); // Append the key button for the entry + use InputMapperMessage as IMM; match entry.input { - InputMapperMessage::KeyDown(key) => keys.push(key), - InputMapperMessage::KeyUp(key) => keys.push(key), - InputMapperMessage::KeyDownNoRepeat(key) => keys.push(key), - InputMapperMessage::KeyUpNoRepeat(key) => keys.push(key), + IMM::KeyDown(key) | IMM::KeyUp(key) | IMM::KeyDownNoRepeat(key) | IMM::KeyUpNoRepeat(key) => keys.push(key), _ => (), } diff --git a/editor/src/messages/input_mapper/utility_types/misc.rs b/editor/src/messages/input_mapper/utility_types/misc.rs index 0e019d40b..97b60f07a 100644 --- a/editor/src/messages/input_mapper/utility_types/misc.rs +++ b/editor/src/messages/input_mapper/utility_types/misc.rs @@ -1,4 +1,4 @@ -use super::input_keyboard::{all_required_modifiers_pressed, KeysGroup, LayoutKeysGroup}; +use super::input_keyboard::{all_required_modifiers_pressed, Key, KeysGroup, LayoutKeysGroup}; use crate::messages::input_mapper::key_mapping::MappingVariant; use crate::messages::input_mapper::utility_types::input_keyboard::{KeyStates, NUMBER_OF_KEYS}; use crate::messages::input_mapper::utility_types::input_mouse::NUMBER_OF_MOUSE_BUTTONS; @@ -134,7 +134,29 @@ impl ActionKeys { pub fn to_keys(&mut self, action_input_mapping: &impl Fn(&MessageDiscriminant) -> Vec) -> String { match self { Self::Action(action) => { - if let Some(keys) = action_input_mapping(action).get_mut(0) { + // Take the shortest sequence of keys + let mut key_sequences = action_input_mapping(action); + key_sequences.sort_by_key(|keys| keys.0.len()); + let mut secondary_key_sequence = key_sequences.get(1).cloned(); + let mut key_sequence = key_sequences.get_mut(0); + + // TODO: Replace this exception with a per-action choice of canonical hotkey + if let Some(key_sequence) = &mut key_sequence { + if key_sequence.0.as_slice() == [Key::MouseBack] { + if let Some(replacement) = &mut secondary_key_sequence { + std::mem::swap(*key_sequence, replacement); + } + } + } + if let Some(key_sequence) = &mut key_sequence { + if key_sequence.0.as_slice() == [Key::MouseForward] { + if let Some(replacement) = &mut secondary_key_sequence { + std::mem::swap(*key_sequence, replacement); + } + } + } + + if let Some(keys) = key_sequence { let mut taken_keys = KeysGroup::default(); std::mem::swap(keys, &mut taken_keys); let description = taken_keys.to_string(); diff --git a/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs b/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs index 231ed952c..7c5ba0179 100644 --- a/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs +++ b/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs @@ -156,6 +156,7 @@ impl LayoutHolder for MenuBarMessageHandler { vec![ MenuBarEntry { label: "Cut".into(), + icon: Some("Cut".into()), shortcut: action_keys!(PortfolioMessageDiscriminant::Cut), action: MenuBarEntry::create_action(|_| PortfolioMessage::Cut { clipboard: Clipboard::Device }.into()), disabled: no_active_document || !has_selected_layers, diff --git a/frontend/assets/icon-16px-solid/cut.svg b/frontend/assets/icon-16px-solid/cut.svg new file mode 100644 index 000000000..4381c828d --- /dev/null +++ b/frontend/assets/icon-16px-solid/cut.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend/assets/icon-16px-solid/pin-active.svg b/frontend/assets/icon-16px-solid/pin-active.svg new file mode 100644 index 000000000..169a6cc6b --- /dev/null +++ b/frontend/assets/icon-16px-solid/pin-active.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend/assets/icon-16px-solid/pin-inactive.svg b/frontend/assets/icon-16px-solid/pin-inactive.svg new file mode 100644 index 000000000..21fe58d39 --- /dev/null +++ b/frontend/assets/icon-16px-solid/pin-inactive.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/src/components/widgets/WidgetSection.svelte b/frontend/src/components/widgets/WidgetSection.svelte index 7b4692218..ccb07f03e 100644 --- a/frontend/src/components/widgets/WidgetSection.svelte +++ b/frontend/src/components/widgets/WidgetSection.svelte @@ -28,7 +28,7 @@
{widgetData.name} { diff --git a/frontend/src/utility-functions/icons.ts b/frontend/src/utility-functions/icons.ts index 69abfb1d9..20b34f641 100644 --- a/frontend/src/utility-functions/icons.ts +++ b/frontend/src/utility-functions/icons.ts @@ -109,6 +109,7 @@ import CheckboxUnchecked from "@graphite-frontend/assets/icon-16px-solid/checkbo import Copy from "@graphite-frontend/assets/icon-16px-solid/copy.svg"; import Credits from "@graphite-frontend/assets/icon-16px-solid/credits.svg"; import CustomColor from "@graphite-frontend/assets/icon-16px-solid/custom-color.svg"; +import Cut from "@graphite-frontend/assets/icon-16px-solid/cut.svg"; import Edit from "@graphite-frontend/assets/icon-16px-solid/edit.svg"; import EyeHidden from "@graphite-frontend/assets/icon-16px-solid/eye-hidden.svg"; import EyeHide from "@graphite-frontend/assets/icon-16px-solid/eye-hide.svg"; @@ -144,6 +145,8 @@ import Node from "@graphite-frontend/assets/icon-16px-solid/node.svg"; import PadlockLocked from "@graphite-frontend/assets/icon-16px-solid/padlock-locked.svg"; import PadlockUnlocked from "@graphite-frontend/assets/icon-16px-solid/padlock-unlocked.svg"; import Paste from "@graphite-frontend/assets/icon-16px-solid/paste.svg"; +import PinActive from "@graphite-frontend/assets/icon-16px-solid/pin-active.svg"; +import PinInactive from "@graphite-frontend/assets/icon-16px-solid/pin-inactive.svg"; import Random from "@graphite-frontend/assets/icon-16px-solid/random.svg"; import Regenerate from "@graphite-frontend/assets/icon-16px-solid/regenerate.svg"; import Reload from "@graphite-frontend/assets/icon-16px-solid/reload.svg"; @@ -188,6 +191,7 @@ const SOLID_16PX = { Copy: { svg: Copy, size: 16 }, Credits: { svg: Credits, size: 16 }, CustomColor: { svg: CustomColor, size: 16 }, + Cut: { svg: Cut, size: 16 }, Edit: { svg: Edit, size: 16 }, Eyedropper: { svg: Eyedropper, size: 16 }, EyeHidden: { svg: EyeHidden, size: 16 }, @@ -223,6 +227,8 @@ const SOLID_16PX = { PadlockLocked: { svg: PadlockLocked, size: 16 }, PadlockUnlocked: { svg: PadlockUnlocked, size: 16 }, Paste: { svg: Paste, size: 16 }, + PinActive: { svg: PinActive, size: 16 }, + PinInactive: { svg: PinInactive, size: 16 }, Random: { svg: Random, size: 16 }, Regenerate: { svg: Regenerate, size: 16 }, Reload: { svg: Reload, size: 16 },