mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-22 02:38:13 +08:00
Refactor the old menu bar plumbing to use standard TextButtons (#3444)
* Refactor the old menu bar plumbing to use standard TextButtons * WIP: Fix Mac native menu bar * WIP: fix desktop menu bar mac * Refactor menu bar definitions to use the builder pattern * WIP: fixup desktop * cleanup * fix linux * Remove dead code that was failing to lint --------- Co-authored-by: Timon Schelling <me@timon.zip>
This commit is contained in:
co-authored by
Timon Schelling
parent
3fd0460d03
commit
600fb5c28f
@@ -1,14 +1,10 @@
|
||||
use graphene_std::Color;
|
||||
use graphene_std::raster::Image;
|
||||
use graphite_editor::messages::app_window::app_window_message_handler::AppWindowPlatform;
|
||||
use graphite_editor::messages::layout::LayoutMessage;
|
||||
use graphite_editor::messages::prelude::*;
|
||||
use graphite_editor::messages::tool::tool_messages::tool_prelude::{LayoutTarget, WidgetId};
|
||||
|
||||
use crate::messages::Platform;
|
||||
|
||||
use super::DesktopWrapperMessageDispatcher;
|
||||
use super::messages::{DesktopFrontendMessage, DesktopWrapperMessage, EditorMessage, OpenFileDialogContext, SaveFileDialogContext};
|
||||
use super::messages::{DesktopFrontendMessage, DesktopWrapperMessage, EditorMessage, OpenFileDialogContext, Platform, SaveFileDialogContext};
|
||||
|
||||
pub(super) fn handle_desktop_wrapper_message(dispatcher: &mut DesktopWrapperMessageDispatcher, message: DesktopWrapperMessage) {
|
||||
match message {
|
||||
@@ -150,13 +146,15 @@ pub(super) fn handle_desktop_wrapper_message(dispatcher: &mut DesktopWrapperMess
|
||||
let message = PreferencesMessage::Load { preferences };
|
||||
dispatcher.queue_editor_message(message);
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
DesktopWrapperMessage::MenuEvent { id } => {
|
||||
let message = LayoutMessage::WidgetValueUpdate {
|
||||
layout_target: LayoutTarget::MenuBar,
|
||||
widget_id: WidgetId(id),
|
||||
value: serde_json::Value::Bool(true),
|
||||
};
|
||||
dispatcher.queue_editor_message(message);
|
||||
if let Some(message) = crate::utils::menu::parse_item_path(id) {
|
||||
dispatcher.queue_editor_message(message);
|
||||
} else {
|
||||
tracing::error!("Received a malformed MenuEvent id");
|
||||
}
|
||||
}
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
DesktopWrapperMessage::MenuEvent { id: _ } => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use graphite_editor::messages::input_mapper::utility_types::input_keyboard::{Key, LayoutKey, LayoutKeysGroup};
|
||||
use graphite_editor::messages::input_mapper::utility_types::misc::ActionKeys;
|
||||
use graphite_editor::messages::layout::utility_types::widgets::menu_widgets::MenuBarEntry;
|
||||
use graphite_editor::messages::prelude::FrontendMessage;
|
||||
|
||||
use super::DesktopWrapperMessageDispatcher;
|
||||
use super::messages::{DesktopFrontendMessage, Document, FileFilter, KeyCode, MenuItem, Modifiers, OpenFileDialogContext, SaveFileDialogContext, Shortcut};
|
||||
use super::messages::{DesktopFrontendMessage, Document, FileFilter, OpenFileDialogContext, SaveFileDialogContext};
|
||||
|
||||
pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageDispatcher, message: FrontendMessage) -> Option<FrontendMessage> {
|
||||
match message {
|
||||
@@ -113,11 +110,24 @@ pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageD
|
||||
FrontendMessage::TriggerLoadPreferences => {
|
||||
dispatcher.respond(DesktopFrontendMessage::PersistenceLoadPreferences);
|
||||
}
|
||||
FrontendMessage::UpdateMenuBarLayout { layout_target, layout } => {
|
||||
let entries = convert_menu_bar_entries_to_menu_items(&layout);
|
||||
dispatcher.respond(DesktopFrontendMessage::UpdateMenu { entries });
|
||||
|
||||
return Some(FrontendMessage::UpdateMenuBarLayout { layout, layout_target });
|
||||
#[cfg(target_os = "macos")]
|
||||
FrontendMessage::UpdateMenuBarLayout {
|
||||
layout_target: graphite_editor::messages::tool::tool_messages::tool_prelude::LayoutTarget::MenuBar,
|
||||
diff,
|
||||
} => {
|
||||
use graphite_editor::messages::tool::tool_messages::tool_prelude::{DiffUpdate, WidgetDiff};
|
||||
match diff.as_slice() {
|
||||
[
|
||||
WidgetDiff {
|
||||
widget_path,
|
||||
new_value: DiffUpdate::SubLayout(layout),
|
||||
},
|
||||
] if widget_path.is_empty() => {
|
||||
let entries = crate::utils::menu::convert_menu_bar_layout_to_menu_items(layout);
|
||||
dispatcher.respond(DesktopFrontendMessage::UpdateMenu { entries });
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
FrontendMessage::WindowClose => {
|
||||
dispatcher.respond(DesktopFrontendMessage::WindowClose);
|
||||
@@ -144,191 +154,3 @@ pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageD
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn convert_menu_bar_entries_to_menu_items(layout: &[MenuBarEntry]) -> Vec<MenuItem> {
|
||||
layout.iter().filter_map(convert_menu_bar_entry_to_menu_item).collect()
|
||||
}
|
||||
|
||||
fn convert_menu_bar_entry_to_menu_item(
|
||||
MenuBarEntry {
|
||||
label,
|
||||
icon,
|
||||
shortcut,
|
||||
action,
|
||||
children,
|
||||
disabled,
|
||||
}: &MenuBarEntry,
|
||||
) -> Option<MenuItem> {
|
||||
let id = action.widget_id.0;
|
||||
let text = label.clone();
|
||||
let enabled = !*disabled;
|
||||
|
||||
if !children.0.is_empty() {
|
||||
let items = convert_menu_bar_entry_children_to_menu_items(&children.0);
|
||||
return Some(MenuItem::SubMenu { id, text, enabled, items });
|
||||
}
|
||||
|
||||
let shortcut = match shortcut {
|
||||
Some(ActionKeys::Keys(LayoutKeysGroup(keys))) => convert_layout_keys_to_shortcut(keys),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
// TODO: Find a better way to determine if this is a checkbox
|
||||
match icon.as_deref() {
|
||||
Some("CheckboxChecked") => {
|
||||
return Some(MenuItem::Checkbox {
|
||||
id,
|
||||
text,
|
||||
enabled,
|
||||
shortcut,
|
||||
checked: true,
|
||||
});
|
||||
}
|
||||
Some("CheckboxUnchecked") => {
|
||||
return Some(MenuItem::Checkbox {
|
||||
id,
|
||||
text,
|
||||
enabled,
|
||||
shortcut,
|
||||
checked: false,
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Some(MenuItem::Action { id, text, shortcut, enabled })
|
||||
}
|
||||
|
||||
fn convert_menu_bar_entry_children_to_menu_items(children: &[Vec<MenuBarEntry>]) -> Vec<MenuItem> {
|
||||
let mut items = Vec::new();
|
||||
for (i, section) in children.iter().enumerate() {
|
||||
for entry in section.iter() {
|
||||
if let Some(item) = convert_menu_bar_entry_to_menu_item(entry) {
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
if i != children.len() - 1 {
|
||||
items.push(MenuItem::Separator);
|
||||
}
|
||||
}
|
||||
items
|
||||
}
|
||||
|
||||
fn convert_layout_keys_to_shortcut(layout_keys: &Vec<LayoutKey>) -> Option<Shortcut> {
|
||||
let mut key: Option<KeyCode> = None;
|
||||
let mut modifiers = Modifiers::default();
|
||||
for layout_key in layout_keys {
|
||||
match layout_key.key() {
|
||||
Key::Shift => modifiers |= Modifiers::SHIFT,
|
||||
Key::Control => modifiers |= Modifiers::CONTROL,
|
||||
Key::Alt => modifiers |= Modifiers::ALT,
|
||||
Key::Meta => modifiers |= Modifiers::META,
|
||||
Key::Command => modifiers |= Modifiers::ALT,
|
||||
Key::Accel => modifiers |= Modifiers::META,
|
||||
Key::Digit0 => key = Some(KeyCode::Digit0),
|
||||
Key::Digit1 => key = Some(KeyCode::Digit1),
|
||||
Key::Digit2 => key = Some(KeyCode::Digit2),
|
||||
Key::Digit3 => key = Some(KeyCode::Digit3),
|
||||
Key::Digit4 => key = Some(KeyCode::Digit4),
|
||||
Key::Digit5 => key = Some(KeyCode::Digit5),
|
||||
Key::Digit6 => key = Some(KeyCode::Digit6),
|
||||
Key::Digit7 => key = Some(KeyCode::Digit7),
|
||||
Key::Digit8 => key = Some(KeyCode::Digit8),
|
||||
Key::Digit9 => key = Some(KeyCode::Digit9),
|
||||
Key::KeyA => key = Some(KeyCode::KeyA),
|
||||
Key::KeyB => key = Some(KeyCode::KeyB),
|
||||
Key::KeyC => key = Some(KeyCode::KeyC),
|
||||
Key::KeyD => key = Some(KeyCode::KeyD),
|
||||
Key::KeyE => key = Some(KeyCode::KeyE),
|
||||
Key::KeyF => key = Some(KeyCode::KeyF),
|
||||
Key::KeyG => key = Some(KeyCode::KeyG),
|
||||
Key::KeyH => key = Some(KeyCode::KeyH),
|
||||
Key::KeyI => key = Some(KeyCode::KeyI),
|
||||
Key::KeyJ => key = Some(KeyCode::KeyJ),
|
||||
Key::KeyK => key = Some(KeyCode::KeyK),
|
||||
Key::KeyL => key = Some(KeyCode::KeyL),
|
||||
Key::KeyM => key = Some(KeyCode::KeyM),
|
||||
Key::KeyN => key = Some(KeyCode::KeyN),
|
||||
Key::KeyO => key = Some(KeyCode::KeyO),
|
||||
Key::KeyP => key = Some(KeyCode::KeyP),
|
||||
Key::KeyQ => key = Some(KeyCode::KeyQ),
|
||||
Key::KeyR => key = Some(KeyCode::KeyR),
|
||||
Key::KeyS => key = Some(KeyCode::KeyS),
|
||||
Key::KeyT => key = Some(KeyCode::KeyT),
|
||||
Key::KeyU => key = Some(KeyCode::KeyU),
|
||||
Key::KeyV => key = Some(KeyCode::KeyV),
|
||||
Key::KeyW => key = Some(KeyCode::KeyW),
|
||||
Key::KeyX => key = Some(KeyCode::KeyX),
|
||||
Key::KeyY => key = Some(KeyCode::KeyY),
|
||||
Key::KeyZ => key = Some(KeyCode::KeyZ),
|
||||
Key::Backquote => key = Some(KeyCode::Backquote),
|
||||
Key::Backslash => key = Some(KeyCode::Backslash),
|
||||
Key::BracketLeft => key = Some(KeyCode::BracketLeft),
|
||||
Key::BracketRight => key = Some(KeyCode::BracketRight),
|
||||
Key::Comma => key = Some(KeyCode::Comma),
|
||||
Key::Equal => key = Some(KeyCode::Equal),
|
||||
Key::Minus => key = Some(KeyCode::Minus),
|
||||
Key::Period => key = Some(KeyCode::Period),
|
||||
Key::Quote => key = Some(KeyCode::Quote),
|
||||
Key::Semicolon => key = Some(KeyCode::Semicolon),
|
||||
Key::Slash => key = Some(KeyCode::Slash),
|
||||
Key::Backspace => key = Some(KeyCode::Backspace),
|
||||
Key::CapsLock => key = Some(KeyCode::CapsLock),
|
||||
Key::ContextMenu => key = Some(KeyCode::ContextMenu),
|
||||
Key::Enter => key = Some(KeyCode::Enter),
|
||||
Key::Space => key = Some(KeyCode::Space),
|
||||
Key::Tab => key = Some(KeyCode::Tab),
|
||||
Key::Delete => key = Some(KeyCode::Delete),
|
||||
Key::End => key = Some(KeyCode::End),
|
||||
Key::Help => key = Some(KeyCode::Help),
|
||||
Key::Home => key = Some(KeyCode::Home),
|
||||
Key::Insert => key = Some(KeyCode::Insert),
|
||||
Key::PageDown => key = Some(KeyCode::PageDown),
|
||||
Key::PageUp => key = Some(KeyCode::PageUp),
|
||||
Key::ArrowDown => key = Some(KeyCode::ArrowDown),
|
||||
Key::ArrowLeft => key = Some(KeyCode::ArrowLeft),
|
||||
Key::ArrowRight => key = Some(KeyCode::ArrowRight),
|
||||
Key::ArrowUp => key = Some(KeyCode::ArrowUp),
|
||||
Key::NumLock => key = Some(KeyCode::NumLock),
|
||||
Key::NumpadAdd => key = Some(KeyCode::NumpadAdd),
|
||||
Key::NumpadHash => key = Some(KeyCode::NumpadHash),
|
||||
Key::NumpadMultiply => key = Some(KeyCode::NumpadMultiply),
|
||||
Key::NumpadParenLeft => key = Some(KeyCode::NumpadParenLeft),
|
||||
Key::NumpadParenRight => key = Some(KeyCode::NumpadParenRight),
|
||||
Key::Escape => key = Some(KeyCode::Escape),
|
||||
Key::F1 => key = Some(KeyCode::F1),
|
||||
Key::F2 => key = Some(KeyCode::F2),
|
||||
Key::F3 => key = Some(KeyCode::F3),
|
||||
Key::F4 => key = Some(KeyCode::F4),
|
||||
Key::F5 => key = Some(KeyCode::F5),
|
||||
Key::F6 => key = Some(KeyCode::F6),
|
||||
Key::F7 => key = Some(KeyCode::F7),
|
||||
Key::F8 => key = Some(KeyCode::F8),
|
||||
Key::F9 => key = Some(KeyCode::F9),
|
||||
Key::F10 => key = Some(KeyCode::F10),
|
||||
Key::F11 => key = Some(KeyCode::F11),
|
||||
Key::F12 => key = Some(KeyCode::F12),
|
||||
Key::F13 => key = Some(KeyCode::F13),
|
||||
Key::F14 => key = Some(KeyCode::F14),
|
||||
Key::F15 => key = Some(KeyCode::F15),
|
||||
Key::F16 => key = Some(KeyCode::F16),
|
||||
Key::F17 => key = Some(KeyCode::F17),
|
||||
Key::F18 => key = Some(KeyCode::F18),
|
||||
Key::F19 => key = Some(KeyCode::F19),
|
||||
Key::F20 => key = Some(KeyCode::F20),
|
||||
Key::F21 => key = Some(KeyCode::F21),
|
||||
Key::F22 => key = Some(KeyCode::F22),
|
||||
Key::F23 => key = Some(KeyCode::F23),
|
||||
Key::F24 => key = Some(KeyCode::F24),
|
||||
Key::Fn => key = Some(KeyCode::Fn),
|
||||
Key::FnLock => key = Some(KeyCode::FnLock),
|
||||
Key::PrintScreen => key = Some(KeyCode::PrintScreen),
|
||||
Key::ScrollLock => key = Some(KeyCode::ScrollLock),
|
||||
Key::Pause => key = Some(KeyCode::Pause),
|
||||
Key::Unidentified => key = Some(KeyCode::Unidentified),
|
||||
Key::FakeKeyPlus => key = Some(KeyCode::Equal),
|
||||
_ => key = None,
|
||||
}
|
||||
}
|
||||
key.map(|key| Shortcut { key, modifiers })
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ mod handle_desktop_wrapper_message;
|
||||
mod intercept_editor_message;
|
||||
mod intercept_frontend_message;
|
||||
|
||||
pub(crate) mod utils;
|
||||
|
||||
pub struct DesktopWrapper {
|
||||
editor: Editor,
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ pub enum DesktopWrapperMessage {
|
||||
preferences: Option<Preferences>,
|
||||
},
|
||||
MenuEvent {
|
||||
id: u64,
|
||||
id: String,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -147,20 +147,20 @@ pub enum Platform {
|
||||
|
||||
pub enum MenuItem {
|
||||
Action {
|
||||
id: u64,
|
||||
id: String,
|
||||
text: String,
|
||||
enabled: bool,
|
||||
shortcut: Option<Shortcut>,
|
||||
},
|
||||
Checkbox {
|
||||
id: u64,
|
||||
id: String,
|
||||
text: String,
|
||||
enabled: bool,
|
||||
shortcut: Option<Shortcut>,
|
||||
checked: bool,
|
||||
},
|
||||
SubMenu {
|
||||
id: u64,
|
||||
id: String,
|
||||
text: String,
|
||||
enabled: bool,
|
||||
items: Vec<MenuItem>,
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
#[cfg(target_os = "macos")]
|
||||
pub(crate) mod menu {
|
||||
use base64::engine::Engine;
|
||||
use base64::engine::general_purpose::STANDARD as BASE64;
|
||||
|
||||
use graphite_editor::messages::input_mapper::utility_types::input_keyboard::{Key, LayoutKey, LayoutKeysGroup};
|
||||
use graphite_editor::messages::input_mapper::utility_types::misc::ActionKeys;
|
||||
use graphite_editor::messages::layout::LayoutMessage;
|
||||
use graphite_editor::messages::tool::tool_messages::tool_prelude::{LayoutGroup, LayoutTarget, MenuListEntry, SubLayout, Widget, WidgetId};
|
||||
|
||||
use crate::messages::{EditorMessage, KeyCode, MenuItem, Modifiers, Shortcut};
|
||||
|
||||
pub(crate) fn convert_menu_bar_layout_to_menu_items(layout: &SubLayout) -> Vec<MenuItem> {
|
||||
let layout_group = match layout.as_slice() {
|
||||
[layout_group] => layout_group,
|
||||
_ => panic!("Menu bar layout is supposed to have exactly one layout group"),
|
||||
};
|
||||
let LayoutGroup::Row { widgets } = layout_group else {
|
||||
panic!("Menu bar layout group is supposed to be a row");
|
||||
};
|
||||
widgets
|
||||
.into_iter()
|
||||
.map(|widget| {
|
||||
let text_button = match &widget.widget {
|
||||
Widget::TextButton(text_button) => text_button,
|
||||
_ => panic!("Menu bar layout top-level widgets are supposed to be text buttons"),
|
||||
};
|
||||
|
||||
MenuItem::SubMenu {
|
||||
id: widget.widget_id.to_string(),
|
||||
text: text_button.label.clone(),
|
||||
enabled: !text_button.disabled,
|
||||
items: convert_menu_bar_entry_children_to_menu_items(&text_button.menu_list_children, widget.widget_id.0, Vec::new()),
|
||||
}
|
||||
})
|
||||
.collect::<Vec<MenuItem>>()
|
||||
}
|
||||
|
||||
pub(crate) fn parse_item_path(id: String) -> Option<EditorMessage> {
|
||||
let mut id_parts = id.split(':');
|
||||
let widget_id = id_parts.next()?.parse::<u64>().ok()?;
|
||||
|
||||
let value = id_parts
|
||||
.map(|part| {
|
||||
let bytes = BASE64.decode(part).ok()?;
|
||||
String::from_utf8(bytes).ok()
|
||||
})
|
||||
.collect::<Option<Vec<String>>>()?;
|
||||
let value = serde_json::to_value(value).ok()?;
|
||||
|
||||
Some(
|
||||
LayoutMessage::WidgetValueUpdate {
|
||||
layout_target: LayoutTarget::MenuBar,
|
||||
widget_id: WidgetId(widget_id),
|
||||
value,
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
fn item_path_to_string(widget_id: u64, path: Vec<String>) -> String {
|
||||
let path = path.into_iter().map(|element| BASE64.encode(element)).collect::<Vec<_>>().join(":");
|
||||
format!("{widget_id}:{path}")
|
||||
}
|
||||
|
||||
fn convert_menu_bar_layout_to_menu_item(entry: &MenuListEntry, root_widget_id: u64, mut path: Vec<String>) -> MenuItem {
|
||||
let MenuListEntry {
|
||||
value,
|
||||
label,
|
||||
icon,
|
||||
shortcut_keys,
|
||||
children,
|
||||
disabled,
|
||||
..
|
||||
}: &MenuListEntry = entry;
|
||||
path.push(value.clone());
|
||||
let id = item_path_to_string(root_widget_id, path.clone());
|
||||
let text = label.clone();
|
||||
let enabled = !*disabled;
|
||||
|
||||
if !children.is_empty() {
|
||||
let items = convert_menu_bar_entry_children_to_menu_items(&children, root_widget_id, path.clone());
|
||||
return MenuItem::SubMenu { id, text, enabled, items };
|
||||
}
|
||||
|
||||
let shortcut = match shortcut_keys {
|
||||
Some(ActionKeys::Keys(LayoutKeysGroup(keys))) => convert_layout_keys_to_shortcut(keys),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
match icon.as_str() {
|
||||
"CheckboxChecked" => {
|
||||
return MenuItem::Checkbox {
|
||||
id,
|
||||
text,
|
||||
enabled,
|
||||
shortcut,
|
||||
checked: true,
|
||||
};
|
||||
}
|
||||
"CheckboxUnchecked" => {
|
||||
return MenuItem::Checkbox {
|
||||
id,
|
||||
text,
|
||||
enabled,
|
||||
shortcut,
|
||||
checked: false,
|
||||
};
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
MenuItem::Action { id, text, shortcut, enabled }
|
||||
}
|
||||
|
||||
fn convert_menu_bar_entry_children_to_menu_items(children: &[Vec<MenuListEntry>], root_widget_id: u64, path: Vec<String>) -> Vec<MenuItem> {
|
||||
let mut items = Vec::new();
|
||||
for (i, section) in children.iter().enumerate() {
|
||||
for entry in section.iter() {
|
||||
items.push(convert_menu_bar_layout_to_menu_item(entry, root_widget_id, path.clone()));
|
||||
}
|
||||
if i != children.len() - 1 {
|
||||
items.push(MenuItem::Separator);
|
||||
}
|
||||
}
|
||||
items
|
||||
}
|
||||
|
||||
fn convert_layout_keys_to_shortcut(layout_keys: &Vec<LayoutKey>) -> Option<Shortcut> {
|
||||
let mut key: Option<KeyCode> = None;
|
||||
let mut modifiers = Modifiers::default();
|
||||
for layout_key in layout_keys {
|
||||
match layout_key.key() {
|
||||
Key::Shift => modifiers |= Modifiers::SHIFT,
|
||||
Key::Control => modifiers |= Modifiers::CONTROL,
|
||||
Key::Alt => modifiers |= Modifiers::ALT,
|
||||
Key::Meta => modifiers |= Modifiers::META,
|
||||
Key::Command => modifiers |= Modifiers::ALT,
|
||||
Key::Accel => modifiers |= Modifiers::META,
|
||||
Key::Digit0 => key = Some(KeyCode::Digit0),
|
||||
Key::Digit1 => key = Some(KeyCode::Digit1),
|
||||
Key::Digit2 => key = Some(KeyCode::Digit2),
|
||||
Key::Digit3 => key = Some(KeyCode::Digit3),
|
||||
Key::Digit4 => key = Some(KeyCode::Digit4),
|
||||
Key::Digit5 => key = Some(KeyCode::Digit5),
|
||||
Key::Digit6 => key = Some(KeyCode::Digit6),
|
||||
Key::Digit7 => key = Some(KeyCode::Digit7),
|
||||
Key::Digit8 => key = Some(KeyCode::Digit8),
|
||||
Key::Digit9 => key = Some(KeyCode::Digit9),
|
||||
Key::KeyA => key = Some(KeyCode::KeyA),
|
||||
Key::KeyB => key = Some(KeyCode::KeyB),
|
||||
Key::KeyC => key = Some(KeyCode::KeyC),
|
||||
Key::KeyD => key = Some(KeyCode::KeyD),
|
||||
Key::KeyE => key = Some(KeyCode::KeyE),
|
||||
Key::KeyF => key = Some(KeyCode::KeyF),
|
||||
Key::KeyG => key = Some(KeyCode::KeyG),
|
||||
Key::KeyH => key = Some(KeyCode::KeyH),
|
||||
Key::KeyI => key = Some(KeyCode::KeyI),
|
||||
Key::KeyJ => key = Some(KeyCode::KeyJ),
|
||||
Key::KeyK => key = Some(KeyCode::KeyK),
|
||||
Key::KeyL => key = Some(KeyCode::KeyL),
|
||||
Key::KeyM => key = Some(KeyCode::KeyM),
|
||||
Key::KeyN => key = Some(KeyCode::KeyN),
|
||||
Key::KeyO => key = Some(KeyCode::KeyO),
|
||||
Key::KeyP => key = Some(KeyCode::KeyP),
|
||||
Key::KeyQ => key = Some(KeyCode::KeyQ),
|
||||
Key::KeyR => key = Some(KeyCode::KeyR),
|
||||
Key::KeyS => key = Some(KeyCode::KeyS),
|
||||
Key::KeyT => key = Some(KeyCode::KeyT),
|
||||
Key::KeyU => key = Some(KeyCode::KeyU),
|
||||
Key::KeyV => key = Some(KeyCode::KeyV),
|
||||
Key::KeyW => key = Some(KeyCode::KeyW),
|
||||
Key::KeyX => key = Some(KeyCode::KeyX),
|
||||
Key::KeyY => key = Some(KeyCode::KeyY),
|
||||
Key::KeyZ => key = Some(KeyCode::KeyZ),
|
||||
Key::Backquote => key = Some(KeyCode::Backquote),
|
||||
Key::Backslash => key = Some(KeyCode::Backslash),
|
||||
Key::BracketLeft => key = Some(KeyCode::BracketLeft),
|
||||
Key::BracketRight => key = Some(KeyCode::BracketRight),
|
||||
Key::Comma => key = Some(KeyCode::Comma),
|
||||
Key::Equal => key = Some(KeyCode::Equal),
|
||||
Key::Minus => key = Some(KeyCode::Minus),
|
||||
Key::Period => key = Some(KeyCode::Period),
|
||||
Key::Quote => key = Some(KeyCode::Quote),
|
||||
Key::Semicolon => key = Some(KeyCode::Semicolon),
|
||||
Key::Slash => key = Some(KeyCode::Slash),
|
||||
Key::Backspace => key = Some(KeyCode::Backspace),
|
||||
Key::CapsLock => key = Some(KeyCode::CapsLock),
|
||||
Key::ContextMenu => key = Some(KeyCode::ContextMenu),
|
||||
Key::Enter => key = Some(KeyCode::Enter),
|
||||
Key::Space => key = Some(KeyCode::Space),
|
||||
Key::Tab => key = Some(KeyCode::Tab),
|
||||
Key::Delete => key = Some(KeyCode::Delete),
|
||||
Key::End => key = Some(KeyCode::End),
|
||||
Key::Help => key = Some(KeyCode::Help),
|
||||
Key::Home => key = Some(KeyCode::Home),
|
||||
Key::Insert => key = Some(KeyCode::Insert),
|
||||
Key::PageDown => key = Some(KeyCode::PageDown),
|
||||
Key::PageUp => key = Some(KeyCode::PageUp),
|
||||
Key::ArrowDown => key = Some(KeyCode::ArrowDown),
|
||||
Key::ArrowLeft => key = Some(KeyCode::ArrowLeft),
|
||||
Key::ArrowRight => key = Some(KeyCode::ArrowRight),
|
||||
Key::ArrowUp => key = Some(KeyCode::ArrowUp),
|
||||
Key::NumLock => key = Some(KeyCode::NumLock),
|
||||
Key::NumpadAdd => key = Some(KeyCode::NumpadAdd),
|
||||
Key::NumpadHash => key = Some(KeyCode::NumpadHash),
|
||||
Key::NumpadMultiply => key = Some(KeyCode::NumpadMultiply),
|
||||
Key::NumpadParenLeft => key = Some(KeyCode::NumpadParenLeft),
|
||||
Key::NumpadParenRight => key = Some(KeyCode::NumpadParenRight),
|
||||
Key::Escape => key = Some(KeyCode::Escape),
|
||||
Key::F1 => key = Some(KeyCode::F1),
|
||||
Key::F2 => key = Some(KeyCode::F2),
|
||||
Key::F3 => key = Some(KeyCode::F3),
|
||||
Key::F4 => key = Some(KeyCode::F4),
|
||||
Key::F5 => key = Some(KeyCode::F5),
|
||||
Key::F6 => key = Some(KeyCode::F6),
|
||||
Key::F7 => key = Some(KeyCode::F7),
|
||||
Key::F8 => key = Some(KeyCode::F8),
|
||||
Key::F9 => key = Some(KeyCode::F9),
|
||||
Key::F10 => key = Some(KeyCode::F10),
|
||||
Key::F11 => key = Some(KeyCode::F11),
|
||||
Key::F12 => key = Some(KeyCode::F12),
|
||||
Key::F13 => key = Some(KeyCode::F13),
|
||||
Key::F14 => key = Some(KeyCode::F14),
|
||||
Key::F15 => key = Some(KeyCode::F15),
|
||||
Key::F16 => key = Some(KeyCode::F16),
|
||||
Key::F17 => key = Some(KeyCode::F17),
|
||||
Key::F18 => key = Some(KeyCode::F18),
|
||||
Key::F19 => key = Some(KeyCode::F19),
|
||||
Key::F20 => key = Some(KeyCode::F20),
|
||||
Key::F21 => key = Some(KeyCode::F21),
|
||||
Key::F22 => key = Some(KeyCode::F22),
|
||||
Key::F23 => key = Some(KeyCode::F23),
|
||||
Key::F24 => key = Some(KeyCode::F24),
|
||||
Key::Fn => key = Some(KeyCode::Fn),
|
||||
Key::FnLock => key = Some(KeyCode::FnLock),
|
||||
Key::PrintScreen => key = Some(KeyCode::PrintScreen),
|
||||
Key::ScrollLock => key = Some(KeyCode::ScrollLock),
|
||||
Key::Pause => key = Some(KeyCode::Pause),
|
||||
Key::Unidentified => key = Some(KeyCode::Unidentified),
|
||||
Key::FakeKeyPlus => key = Some(KeyCode::Equal),
|
||||
_ => key = None,
|
||||
}
|
||||
}
|
||||
key.map(|key| Shortcut { key, modifiers })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user