egui_keybinds/
keycodes.rs

1use std::collections::HashMap;
2
3use once_cell::sync::Lazy;
4
5#[allow(dead_code)]
6#[derive(PartialEq, Clone, Hash, Eq)]
7pub enum KeyCode {
8    Escape,
9    F1,
10    F2,
11    F3,
12    F4,
13    F5,
14    F6,
15    F7,
16    F8,
17    F9,
18    F10,
19    F11,
20    F12,
21    Backtick,
22    Tilde,
23    Num1,
24    ExclamationPoint,
25    Num2,
26    At,
27    Num3,
28    Hashtag,
29    Num4,
30    Dollar,
31    Num5,
32    Percent,
33    Num6,
34    Caret,
35    Num7,
36    Ampersand,
37    Num8,
38    Asterisks,
39    Num9,
40    OpenParenthesis,
41    Num0,
42    CloseParenthesis,
43    Minus,
44    Underscore,
45    Equals,
46    Plus,
47    Backspace,
48    Tab,
49    Q,
50    W,
51    E,
52    R,
53    T,
54    Y,
55    U,
56    I,
57    O,
58    P,
59    OpenBracket,
60    OpenBrace,
61    CloseBracket,
62    CloseBrace,
63    Backslash,
64    Pipe,
65    CapsLock,
66    A,
67    S,
68    D,
69    F,
70    G,
71    H,
72    J,
73    K,
74    L,
75    SemiColon,
76    Colon,
77    Apostrophe,
78    Quote,
79    Return,
80    LShift,
81    Z,
82    X,
83    C,
84    V,
85    B,
86    N,
87    M,
88    Comma,
89    LessThan,
90    Period,
91    GreaterThan,
92    ForwardSlash,
93    QuestionMark,
94    RShift,
95    LFunction,
96    LControl,
97    LOption,
98    LWindows,
99    LCommand,
100    Space,
101    RAlt,
102    LAlt,
103    RCommand,
104    RWindows,
105    ROption,
106    RFunction,
107    RControl,
108
109    Insert,
110    Delete,
111    Home,
112    End,
113    PageUp,
114    PageDown,
115
116    UpArrow,
117    DownArrow,
118    LeftArrow,
119    RightArrow,
120}
121
122static KEY_STRING_MAP: Lazy<HashMap<KeyCode, &str>> = Lazy::new(|| {
123    HashMap::from([
124        (KeyCode::Escape, "Escape"),
125        (KeyCode::F1, "F1"),
126        (KeyCode::F2, "F2"),
127        (KeyCode::F3, "F3"),
128        (KeyCode::F4, "F4"),
129        (KeyCode::F5, "F5"),
130        (KeyCode::F6, "F6"),
131        (KeyCode::F7, "F7"),
132        (KeyCode::F8, "F8"),
133        (KeyCode::F9, "F9"),
134        (KeyCode::F10, "F10"),
135        (KeyCode::F11, "F11"),
136        (KeyCode::F12, "F12"),
137        (KeyCode::Backtick, "`"),
138        (KeyCode::Tilde, "~"),
139        (KeyCode::Num1, "1"),
140        (KeyCode::ExclamationPoint, "!"),
141        (KeyCode::Num2, "2"),
142        (KeyCode::At, "@"),
143        (KeyCode::Num3, "3"),
144        (KeyCode::Hashtag, "#"),
145        (KeyCode::Num4, "4"),
146        (KeyCode::Dollar, "$"),
147        (KeyCode::Num5, "5"),
148        (KeyCode::Percent, "%"),
149        (KeyCode::Num6, "6"),
150        (KeyCode::Caret, "^"),
151        (KeyCode::Num7, "7"),
152        (KeyCode::Ampersand, "&"),
153        (KeyCode::Num8, "8"),
154        (KeyCode::Asterisks, "*"),
155        (KeyCode::Num9, "9"),
156        (KeyCode::OpenParenthesis, "("),
157        (KeyCode::Num0, "0"),
158        (KeyCode::CloseParenthesis, ")"),
159        (KeyCode::Minus, "-"),
160        (KeyCode::Underscore, "_"),
161        (KeyCode::Equals, "="),
162        (KeyCode::Plus, "+"),
163        (KeyCode::Backspace, "Backspace"),
164        (KeyCode::Tab, "Tab"),
165        (KeyCode::Q, "Q"),
166        (KeyCode::W, "W"),
167        (KeyCode::E, "E"),
168        (KeyCode::R, "R"),
169        (KeyCode::T, "T"),
170        (KeyCode::Y, "Y"),
171        (KeyCode::U, "U"),
172        (KeyCode::I, "I"),
173        (KeyCode::O, "O"),
174        (KeyCode::P, "P"),
175        (KeyCode::OpenBracket, "["),
176        (KeyCode::OpenBrace, "{"),
177        (KeyCode::CloseBracket, "]"),
178        (KeyCode::CloseBrace, "}"),
179        (KeyCode::Backslash, "\\"),
180        (KeyCode::Pipe, "|"),
181        (KeyCode::CapsLock, "CapsLock"),
182        (KeyCode::A, "A"),
183        (KeyCode::S, "S"),
184        (KeyCode::D, "D"),
185        (KeyCode::F, "F"),
186        (KeyCode::G, "G"),
187        (KeyCode::H, "H"),
188        (KeyCode::J, "J"),
189        (KeyCode::K, "K"),
190        (KeyCode::L, "L"),
191        (KeyCode::SemiColon, ";"),
192        (KeyCode::Colon, ":"),
193        (KeyCode::Apostrophe, "'"),
194        (KeyCode::Quote, "\""),
195        (KeyCode::Return, "Return"),
196        (KeyCode::LShift, "LShift"),
197        (KeyCode::Z, "Z"),
198        (KeyCode::X, "X"),
199        (KeyCode::C, "C"),
200        (KeyCode::V, "V"),
201        (KeyCode::B, "B"),
202        (KeyCode::N, "N"),
203        (KeyCode::M, "M"),
204        (KeyCode::Comma, "),"),
205        (KeyCode::LessThan, "<"),
206        (KeyCode::Period, "."),
207        (KeyCode::GreaterThan, ">"),
208        (KeyCode::ForwardSlash, "/"),
209        (KeyCode::QuestionMark, "?"),
210        (KeyCode::RShift, "RShift"),
211        (KeyCode::LFunction, "LFunction"),
212        (KeyCode::LControl, "LControl"),
213        (KeyCode::LOption, "LOption"),
214        (KeyCode::LWindows, "LWindows"),
215        (KeyCode::LCommand, "LCommand"),
216        (KeyCode::Space, "Space"),
217        (KeyCode::RAlt, "RAlt"),
218        (KeyCode::LAlt, "LAlt"),
219        (KeyCode::RCommand, "RCommand"),
220        (KeyCode::RWindows, "RWindows"),
221        (KeyCode::ROption, "ROption"),
222        (KeyCode::RFunction, "RFunction"),
223        (KeyCode::RControl, "RControl"),
224        (KeyCode::Insert, "Insert"),
225        (KeyCode::Delete, "Delete"),
226        (KeyCode::Home, "Home"),
227        (KeyCode::End, "End"),
228        (KeyCode::PageUp, "PageUp"),
229        (KeyCode::PageDown, "PageDown"),
230        (KeyCode::UpArrow, "UpArrow"),
231        (KeyCode::DownArrow, "DownArrow"),
232        (KeyCode::LeftArrow, "LeftArrow"),
233        (KeyCode::RightArrow, "RightArrow"),
234    ])
235});
236
237impl KeyCode {
238    pub fn serialize(&self) -> String {
239        KEY_STRING_MAP[self].to_string()
240    }
241
242    pub fn deserialize(data: String) -> Result<Option<Self>, ()> {
243        let mut result: Result<Option<Self>, ()> = Err(());
244
245        if data == "..." {
246            return Ok(None);
247        }
248
249        for (key, str) in KEY_STRING_MAP.iter() {
250            if str.eq_ignore_ascii_case(data.as_str()) {
251                result = Ok(Some(key.clone()));
252                break;
253            }
254        }
255
256        result
257    }
258}
259
260impl From<device_query::Keycode> for KeyCode {
261    fn from(item: device_query::Keycode) -> KeyCode {
262        match item {
263            device_query::Keycode::Key0 => KeyCode::Num0,
264            device_query::Keycode::Key1 => KeyCode::Num1,
265            device_query::Keycode::Key2 => KeyCode::Num2,
266            device_query::Keycode::Key3 => KeyCode::Num3,
267            device_query::Keycode::Key4 => KeyCode::Num4,
268            device_query::Keycode::Key5 => KeyCode::Num5,
269            device_query::Keycode::Key6 => KeyCode::Num6,
270            device_query::Keycode::Key7 => KeyCode::Num7,
271            device_query::Keycode::Key8 => KeyCode::Num8,
272            device_query::Keycode::Key9 => KeyCode::Num9,
273            device_query::Keycode::A => KeyCode::A,
274            device_query::Keycode::B => KeyCode::B,
275            device_query::Keycode::C => KeyCode::C,
276            device_query::Keycode::D => KeyCode::D,
277            device_query::Keycode::E => KeyCode::E,
278            device_query::Keycode::F => KeyCode::F,
279            device_query::Keycode::G => KeyCode::G,
280            device_query::Keycode::H => KeyCode::H,
281            device_query::Keycode::I => KeyCode::I,
282            device_query::Keycode::J => KeyCode::J,
283            device_query::Keycode::K => KeyCode::K,
284            device_query::Keycode::L => KeyCode::L,
285            device_query::Keycode::M => KeyCode::M,
286            device_query::Keycode::N => KeyCode::N,
287            device_query::Keycode::O => KeyCode::O,
288            device_query::Keycode::P => KeyCode::P,
289            device_query::Keycode::Q => KeyCode::Q,
290            device_query::Keycode::R => KeyCode::R,
291            device_query::Keycode::S => KeyCode::S,
292            device_query::Keycode::T => KeyCode::T,
293            device_query::Keycode::U => KeyCode::U,
294            device_query::Keycode::V => KeyCode::V,
295            device_query::Keycode::W => KeyCode::W,
296            device_query::Keycode::X => KeyCode::X,
297            device_query::Keycode::Y => KeyCode::Y,
298            device_query::Keycode::Z => KeyCode::Z,
299            device_query::Keycode::F1 => KeyCode::F1,
300            device_query::Keycode::F2 => KeyCode::F2,
301            device_query::Keycode::F3 => KeyCode::F3,
302            device_query::Keycode::F4 => KeyCode::F4,
303            device_query::Keycode::F5 => KeyCode::F5,
304            device_query::Keycode::F6 => KeyCode::F6,
305            device_query::Keycode::F7 => KeyCode::F7,
306            device_query::Keycode::F8 => KeyCode::F8,
307            device_query::Keycode::F9 => KeyCode::F9,
308            device_query::Keycode::F10 => KeyCode::F10,
309            device_query::Keycode::F11 => KeyCode::F11,
310            device_query::Keycode::F12 => KeyCode::F12,
311            device_query::Keycode::Escape => KeyCode::Escape,
312            device_query::Keycode::Space => KeyCode::Space,
313            device_query::Keycode::LControl => KeyCode::LControl,
314            device_query::Keycode::RControl => KeyCode::RControl,
315            device_query::Keycode::LShift => KeyCode::LShift,
316            device_query::Keycode::RShift => KeyCode::RShift,
317            device_query::Keycode::LAlt => KeyCode::LAlt,
318            device_query::Keycode::RAlt => KeyCode::RAlt,
319            device_query::Keycode::Meta => KeyCode::LWindows, // rip
320            device_query::Keycode::Enter => KeyCode::Return,
321            device_query::Keycode::Up => KeyCode::UpArrow,
322            device_query::Keycode::Down => KeyCode::DownArrow,
323            device_query::Keycode::Left => KeyCode::LeftArrow,
324            device_query::Keycode::Right => KeyCode::RightArrow,
325            device_query::Keycode::Backspace => KeyCode::Backspace,
326            device_query::Keycode::CapsLock => KeyCode::CapsLock,
327            device_query::Keycode::Tab => KeyCode::Tab,
328            device_query::Keycode::Home => KeyCode::Home,
329            device_query::Keycode::End => KeyCode::End,
330            device_query::Keycode::PageUp => KeyCode::PageUp,
331            device_query::Keycode::PageDown => KeyCode::PageDown,
332            device_query::Keycode::Insert => KeyCode::Insert,
333            device_query::Keycode::Delete => KeyCode::Delete,
334            device_query::Keycode::Numpad0 => KeyCode::Num0,
335            device_query::Keycode::Numpad1 => KeyCode::Num1,
336            device_query::Keycode::Numpad2 => KeyCode::Num2,
337            device_query::Keycode::Numpad3 => KeyCode::Num3,
338            device_query::Keycode::Numpad4 => KeyCode::Num4,
339            device_query::Keycode::Numpad5 => KeyCode::Num5,
340            device_query::Keycode::Numpad6 => KeyCode::Num6,
341            device_query::Keycode::Numpad7 => KeyCode::Num7,
342            device_query::Keycode::Numpad8 => KeyCode::Num8,
343            device_query::Keycode::Numpad9 => KeyCode::Num9,
344            device_query::Keycode::NumpadSubtract => KeyCode::Minus,
345            device_query::Keycode::NumpadAdd => KeyCode::Plus,
346            device_query::Keycode::NumpadDivide => KeyCode::ForwardSlash,
347            device_query::Keycode::NumpadMultiply => KeyCode::Asterisks,
348            device_query::Keycode::Grave => KeyCode::Backtick,
349            device_query::Keycode::Minus => KeyCode::Minus,
350            device_query::Keycode::Equal => KeyCode::Equals,
351            device_query::Keycode::LeftBracket => KeyCode::OpenBracket,
352            device_query::Keycode::RightBracket => KeyCode::CloseBracket,
353            device_query::Keycode::BackSlash => KeyCode::Backslash,
354            device_query::Keycode::Semicolon => KeyCode::SemiColon,
355            device_query::Keycode::Apostrophe => KeyCode::Apostrophe,
356            device_query::Keycode::Comma => KeyCode::Comma,
357            device_query::Keycode::Dot => KeyCode::Period,
358            device_query::Keycode::Slash => KeyCode::ForwardSlash,
359        }
360    }
361}
362
363impl KeyCode {
364    pub fn as_modifier(&self) -> Option<KeyModifier> {
365        return match self {
366            KeyCode::LControl => Some(KeyModifier::CtrlCmd),
367            KeyCode::RControl => Some(KeyModifier::CtrlCmd),
368            KeyCode::RAlt => Some(KeyModifier::AltOpt),
369            KeyCode::LAlt => Some(KeyModifier::AltOpt),
370            KeyCode::LOption => Some(KeyModifier::AltOpt),
371            KeyCode::ROption => Some(KeyModifier::AltOpt),
372            KeyCode::LCommand => Some(KeyModifier::CtrlCmd),
373            KeyCode::RCommand => Some(KeyModifier::CtrlCmd),
374            KeyCode::LWindows => Some(KeyModifier::CtrlCmd),
375            KeyCode::RWindows => Some(KeyModifier::CtrlCmd),
376            KeyCode::LFunction => Some(KeyModifier::Function),
377            KeyCode::RFunction => Some(KeyModifier::Function),
378            KeyCode::LShift => Some(KeyModifier::Shift),
379            KeyCode::RShift => Some(KeyModifier::Shift),
380            _ => None,
381        };
382    }
383}
384
385// include discriminant and Ord for Vec<KeyModifier>.sort(), should end up as: Control, Alt, Shift, Fn
386#[derive(PartialEq, Clone, PartialOrd, Eq, Ord, Hash)]
387pub enum KeyModifier {
388    CtrlCmd = 1,  // Control, Left or Right + Command, Left or Right
389    AltOpt = 2,   // Alt on windows, Option on MacOS
390    Shift = 3,    // Shift, Left or Right
391    Function = 4, // Function key (windows only?)
392}
393
394impl KeyModifier {
395    pub fn serialize(&self) -> char {
396        match self {
397            KeyModifier::CtrlCmd => '^',
398            KeyModifier::Shift => '_',
399            KeyModifier::AltOpt => '*',
400            KeyModifier::Function => '~',
401        }
402    }
403
404    pub fn deserialize(data: char) -> Result<Self, ()> {
405        match data {
406            '^' => Ok(KeyModifier::CtrlCmd),
407            '_' => Ok(KeyModifier::Shift),
408            '*' => Ok(KeyModifier::AltOpt),
409            '~' => Ok(KeyModifier::Function),
410            _ => Err(()),
411        }
412    }
413}