gooey/interface/view/input/button/
keycode.rs

1use std::convert::TryFrom;
2use parse_display::FromStr;
3use strum::{EnumCount, FromRepr};
4use crate::interface::view::input::Modifiers;
5
6#[cfg(feature = "opengl")] use nsys::gl::winit;
7
8macro_rules! impl_keycode {
9  ($($winit : ident => $keycode : ident),+) => {
10    #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, EnumCount,
11      FromRepr, FromStr)]
12    pub enum Keycode {
13      $($keycode),+
14    }
15
16    #[cfg(feature = "opengl")]
17    #[cfg_attr(docsrs, doc(cfg(feature="opengl")))]
18    impl From <winit::keyboard::KeyCode> for Keycode {
19      fn from (keycode : winit::keyboard::KeyCode) -> Self {
20        match keycode {
21          $(winit::keyboard::KeyCode::$winit => Keycode::$keycode),+,
22          _ => unimplemented!("unimplemented keycode conversion: {:?}", keycode)
23        }
24      }
25    }
26  }
27}
28
29// The following keycodes are meant to correspond 1:1 with glutin keycodes, but
30// to implement `From <winit::event::VirtualKeyCode>` requires the `opengl`
31// feature to be enabled.
32impl_keycode! {
33  Backquote            => Grave,
34  Backslash            => Backslash,
35  BracketLeft          => LBracket,
36  BracketRight         => RBracket,
37  Comma                => Comma,
38  Digit0               => Key0,
39  Digit1               => Key1,
40  Digit2               => Key2,
41  Digit3               => Key3,
42  Digit4               => Key4,
43  Digit5               => Key5,
44  Digit6               => Key6,
45  Digit7               => Key7,
46  Digit8               => Key8,
47  Digit9               => Key9,
48  Equal                => Equal,
49  IntlBackslash        => IntlBackslash,
50  IntlRo               => IntlRo,
51  IntlYen              => IntlYen,
52  KeyA                 => A,
53  KeyB                 => B,
54  KeyC                 => C,
55  KeyD                 => D,
56  KeyE                 => E,
57  KeyF                 => F,
58  KeyG                 => G,
59  KeyH                 => H,
60  KeyI                 => I,
61  KeyJ                 => J,
62  KeyK                 => K,
63  KeyL                 => L,
64  KeyM                 => M,
65  KeyN                 => N,
66  KeyO                 => O,
67  KeyP                 => P,
68  KeyQ                 => Q,
69  KeyR                 => R,
70  KeyS                 => S,
71  KeyT                 => T,
72  KeyU                 => U,
73  KeyV                 => V,
74  KeyW                 => W,
75  KeyX                 => X,
76  KeyY                 => Y,
77  KeyZ                 => Z,
78  Minus                => Minus,
79  Period               => Period,
80  Quote                => Quote,
81  Semicolon            => Semicolon,
82  Slash                => Slash,
83  AltLeft              => LAlt,
84  AltRight             => RAlt,
85  Backspace            => Backspace,
86  CapsLock             => CapsLock,
87  ContextMenu          => ContextMenu,
88  ControlLeft          => LControl,
89  ControlRight         => RControl,
90  Enter                => Enter,
91  SuperLeft            => LWin,
92  SuperRight           => RWin,
93  ShiftLeft            => LShift,
94  ShiftRight           => RShift,
95  Space                => Space,
96  Tab                  => Tab,
97  Convert              => Convert,
98  KanaMode             => KanaMode,
99  Lang1                => Lang1,
100  Lang2                => Lang2,
101  Lang3                => Lang3,
102  Lang4                => Lang4,
103  Lang5                => Lang5,
104  NonConvert           => NonConvert,
105  Delete               => Delete,
106  End                  => End,
107  Help                 => Help,
108  Home                 => Home,
109  Insert               => Insert,
110  PageDown             => PageDown,
111  PageUp               => PageUp,
112  ArrowDown            => Down,
113  ArrowLeft            => Left,
114  ArrowRight           => Right,
115  ArrowUp              => Up,
116  NumLock              => NumLock,
117  Numpad0              => Numpad0,
118  Numpad1              => Numpad1,
119  Numpad2              => Numpad2,
120  Numpad3              => Numpad3,
121  Numpad4              => Numpad4,
122  Numpad5              => Numpad5,
123  Numpad6              => Numpad6,
124  Numpad7              => Numpad7,
125  Numpad8              => Numpad8,
126  Numpad9              => Numpad9,
127  NumpadAdd            => NumpadAdd,
128  NumpadBackspace      => NumpadBackspace,
129  NumpadClear          => NumpadClear,
130  NumpadClearEntry     => NumpadClearEntry,
131  NumpadComma          => NumpadComma,
132  NumpadDecimal        => NumpadDecimal,
133  NumpadDivide         => NumpadDivide,
134  NumpadEnter          => NumpadEnter,
135  NumpadEqual          => NumpadEqual,
136  NumpadHash           => NumpadHash,
137  NumpadMemoryAdd      => NumpadMemoryAdd,
138  NumpadMemoryClear    => NumpadMemoryClear,
139  NumpadMemoryRecall   => NumpadMemoryRecall,
140  NumpadMemoryStore    => NumpadMemoryStore,
141  NumpadMemorySubtract => NumpadMemorySubtract,
142  NumpadMultiply       => NumpadMultiply,
143  NumpadParenLeft      => NumpadLParen,
144  NumpadParenRight     => NumpadRParen,
145  NumpadStar           => NumpadStar,
146  NumpadSubtract       => NumpadSubtract,
147  Escape               => Escape,
148  Fn                   => Fn,
149  FnLock               => FnLock,
150  PrintScreen          => PrintScreen,
151  ScrollLock           => ScrollLock,
152  Pause                => Pause,
153  BrowserBack          => BrowserBack,
154  BrowserFavorites     => BrowserFavorites,
155  BrowserForward       => BrowserForward,
156  BrowserHome          => BrowserHome,
157  BrowserRefresh       => BrowserRefresh,
158  BrowserSearch        => BrowserSearch,
159  BrowserStop          => BrowserStop,
160  Eject                => Eject,
161  LaunchApp1           => LaunchApp1,
162  LaunchApp2           => LaunchApp2,
163  LaunchMail           => LaunchMail,
164  MediaPlayPause       => MediaPlayPause,
165  MediaSelect          => MediaSelect,
166  MediaStop            => MediaStop,
167  MediaTrackNext       => MediaTrackNext,
168  MediaTrackPrevious   => MediaTrackPrevious,
169  Power                => Power,
170  Sleep                => Sleep,
171  AudioVolumeDown      => AudioVolumeDown,
172  AudioVolumeMute      => AudioVolumeMute,
173  AudioVolumeUp        => AudioVolumeUp,
174  WakeUp               => WakeUp,
175  Meta                 => Meta,
176  Hyper                => Hyper,
177  Turbo                => Turbo,
178  Abort                => Abort,
179  Resume               => Resume,
180  Suspend              => Suspend,
181  Again                => Again,
182  Copy                 => Copy,
183  Cut                  => Cut,
184  Find                 => Find,
185  Open                 => Open,
186  Paste                => Paste,
187  Props                => Props,
188  Select               => Select,
189  Undo                 => Undo,
190  Hiragana             => Hiragana,
191  Katakana             => Katakana,
192  F1                   => F1,
193  F2                   => F2,
194  F3                   => F3,
195  F4                   => F4,
196  F5                   => F5,
197  F6                   => F6,
198  F7                   => F7,
199  F8                   => F8,
200  F9                   => F9,
201  F10                  => F10,
202  F11                  => F11,
203  F12                  => F12,
204  F13                  => F13,
205  F14                  => F14,
206  F15                  => F15,
207  F16                  => F16,
208  F17                  => F17,
209  F18                  => F18,
210  F19                  => F19,
211  F20                  => F20,
212  F21                  => F21,
213  F22                  => F22,
214  F23                  => F23,
215  F24                  => F24,
216  F25                  => F25,
217  F26                  => F26,
218  F27                  => F27,
219  F28                  => F28,
220  F29                  => F29,
221  F30                  => F30,
222  F31                  => F31,
223  F32                  => F32,
224  F33                  => F33,
225  F34                  => F34,
226  F35                  => F35
227}
228
229impl Keycode {
230  /// Space, alphanumeric, punctuation keys
231  pub fn is_printable (self) -> bool {
232    use Keycode::*;
233    match self {
234      Space | Grave |
235      Key1 | Key2 | Key3 | Key4 | Key5 | Key6 | Key7 | Key8 | Key9 | Key0 |
236      Minus | Equal | LBracket | RBracket | Backslash | Semicolon | Quote |
237      Comma | Period | Slash |
238      A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R |
239      S | T | U | V | W | X | Y | Z => true,
240      _ => false
241    }
242  }
243
244  pub fn to_char (self, modifiers : Modifiers) -> Option <char> {
245    use Keycode::*;
246    if modifiers
247      .intersects (Modifiers::ALT | Modifiers::CTRL | Modifiers::SUPER)
248    {
249      return None
250    }
251    let shift = modifiers.contains (Modifiers::SHIFT);
252    let ch    = match self {
253      Space     => ' ',
254      // TODO: see if keys with modifiers still produce return, tab events
255      Enter     => if !shift { '\n' } else { return None },
256      Tab       => if !shift { '\t' } else { return None },
257      Grave     => if !shift { '`'  } else { '~' },
258      Key1      => if !shift { '1'  } else { '!' },
259      Key2      => if !shift { '2'  } else { '@' },
260      Key3      => if !shift { '3'  } else { '#' },
261      Key4      => if !shift { '4'  } else { '$' },
262      Key5      => if !shift { '5'  } else { '%' },
263      Key6      => if !shift { '6'  } else { '^' },
264      Key7      => if !shift { '7'  } else { '&' },
265      Key8      => if !shift { '8'  } else { '*' },
266      Key9      => if !shift { '9'  } else { '(' },
267      Key0      => if !shift { '0'  } else { ')' },
268      Minus     => if !shift { '-'  } else { '_' },
269      Equal     => if !shift { '='  } else { '+' },
270      LBracket  => if !shift { '['  } else { '{' },
271      RBracket  => if !shift { ']'  } else { '}' },
272      Backslash => if !shift { '\\' } else { '|' },
273      Semicolon => if !shift { ';'  } else { ':' },
274      Quote     => if !shift { '\'' } else { '"' },
275      Comma     => if !shift { ','  } else { '<' },
276      Period    => if !shift { '.'  } else { '>' },
277      Slash     => if !shift { '/'  } else { '?' },
278      A         => if !shift { 'a' } else { 'A' },
279      B         => if !shift { 'b' } else { 'B' },
280      C         => if !shift { 'c' } else { 'C' },
281      D         => if !shift { 'd' } else { 'D' },
282      E         => if !shift { 'e' } else { 'E' },
283      F         => if !shift { 'f' } else { 'F' },
284      G         => if !shift { 'g' } else { 'G' },
285      H         => if !shift { 'h' } else { 'H' },
286      I         => if !shift { 'i' } else { 'I' },
287      J         => if !shift { 'j' } else { 'J' },
288      K         => if !shift { 'k' } else { 'K' },
289      L         => if !shift { 'l' } else { 'L' },
290      M         => if !shift { 'm' } else { 'M' },
291      N         => if !shift { 'n' } else { 'N' },
292      O         => if !shift { 'o' } else { 'O' },
293      P         => if !shift { 'p' } else { 'P' },
294      Q         => if !shift { 'q' } else { 'Q' },
295      R         => if !shift { 'r' } else { 'R' },
296      S         => if !shift { 's' } else { 'S' },
297      T         => if !shift { 't' } else { 'T' },
298      U         => if !shift { 'u' } else { 'U' },
299      V         => if !shift { 'v' } else { 'V' },
300      W         => if !shift { 'w' } else { 'W' },
301      X         => if !shift { 'x' } else { 'X' },
302      Y         => if !shift { 'y' } else { 'Y' },
303      Z         => if !shift { 'z' } else { 'Z' },
304      _         => return None
305    };
306    Some (ch)
307  }
308}
309
310impl TryFrom <char> for Keycode {
311  type Error = ();
312  fn try_from (ch : char) -> Result <Self, Self::Error> {
313    use Keycode::*;
314    let keycode = match ch {
315      ' '        => Space,
316      '\n'       => Enter,
317      '\t'       => Tab,
318      '`' | '~'  => Grave,
319      '1' | '!'  => Key1,
320      '2' | '@'  => Key2,
321      '3' | '#'  => Key3,
322      '4' | '$'  => Key4,
323      '5' | '%'  => Key5,
324      '6' | '^'  => Key6,
325      '7' | '&'  => Key7,
326      '8' | '*'  => Key8,
327      '9' | '('  => Key9,
328      '0' | ')'  => Key0,
329      '-' | '_'  => Minus,
330      '=' | '+'  => Equal,
331      '[' | '{'  => LBracket,
332      ']' | '}'  => RBracket,
333      '|' | '\\' => Backslash,
334      ';' | ':'  => Semicolon,
335      '\'' | '"' => Quote,
336      ',' | '<'  => Comma,
337      '.' | '>'  => Period,
338      '/' | '?'  => Slash,
339      'a' | 'A'  => A,
340      'b' | 'B'  => B,
341      'c' | 'C'  => C,
342      'd' | 'D'  => D,
343      'e' | 'E'  => E,
344      'f' | 'F'  => F,
345      'g' | 'G'  => G,
346      'h' | 'H'  => H,
347      'i' | 'I'  => I,
348      'j' | 'J'  => J,
349      'k' | 'K'  => K,
350      'l' | 'L'  => L,
351      'm' | 'M'  => M,
352      'n' | 'N'  => N,
353      'o' | 'O'  => O,
354      'p' | 'P'  => P,
355      'q' | 'Q'  => Q,
356      'r' | 'R'  => R,
357      's' | 'S'  => S,
358      't' | 'T'  => T,
359      'u' | 'U'  => U,
360      'v' | 'V'  => V,
361      'w' | 'W'  => W,
362      'x' | 'X'  => X,
363      'y' | 'Y'  => Y,
364      'z' | 'Z'  => Z,
365      _ => return Err(())
366    };
367    Ok (keycode)
368  }
369}
370
371#[cfg(feature = "opengl")]
372#[cfg_attr(docsrs, doc(cfg(feature="opengl")))]
373impl From <(winit::keyboard::NamedKey, winit::keyboard::KeyLocation)>
374  for Keycode
375{
376  fn from (
377    (key, location) : (winit::keyboard::NamedKey, winit::keyboard::KeyLocation)
378  ) -> Self {
379    use winit::keyboard::NamedKey::*;
380    use winit::keyboard::KeyLocation::*;
381    match key {
382      //Backquote                     => Keycode::Backquote,
383      //Backslash                     => Keycode::Backslash,
384      //BracketLeft                   => Keycode::BracketLeft,
385      //BracketRight                  => Keycode::BracketRight,
386      //Comma                         => Keycode::Comma,
387      //Digit0                        => Keycode::Digit0,
388      //Digit1                        => Keycode::Digit1,
389      //Digit2                        => Keycode::Digit2,
390      //Digit3                        => Keycode::Digit3,
391      //Digit4                        => Keycode::Digit4,
392      //Digit5                        => Keycode::Digit5,
393      //Digit6                        => Keycode::Digit6,
394      //Digit7                        => Keycode::Digit7,
395      //Digit8                        => Keycode::Digit8,
396      //Digit9                        => Keycode::Digit9,
397      //Equal                         => Keycode::Equal,
398      //IntlBackslash                 => Keycode::IntlBackslash,
399      //IntlRo                        => Keycode::IntlRo,
400      //IntlYen                       => Keycode::IntlYen,
401      //KeyA                          => Keycode::KeyA,
402      //KeyB                          => Keycode::KeyB,
403      //KeyC                          => Keycode::KeyC,
404      //KeyD                          => Keycode::KeyD,
405      //KeyE                          => Keycode::KeyE,
406      //KeyF                          => Keycode::KeyF,
407      //KeyG                          => Keycode::KeyG,
408      //KeyH                          => Keycode::KeyH,
409      //KeyI                          => Keycode::KeyI,
410      //KeyJ                          => Keycode::KeyJ,
411      //KeyK                          => Keycode::KeyK,
412      //KeyL                          => Keycode::KeyL,
413      //KeyM                          => Keycode::KeyM,
414      //KeyN                          => Keycode::KeyN,
415      //KeyO                          => Keycode::KeyO,
416      //KeyP                          => Keycode::KeyP,
417      //KeyQ                          => Keycode::KeyQ,
418      //KeyR                          => Keycode::KeyR,
419      //KeyS                          => Keycode::KeyS,
420      //KeyT                          => Keycode::KeyT,
421      //KeyU                          => Keycode::KeyU,
422      //KeyV                          => Keycode::KeyV,
423      //KeyW                          => Keycode::KeyW,
424      //KeyX                          => Keycode::KeyX,
425      //KeyY                          => Keycode::KeyY,
426      //KeyZ                          => Keycode::KeyZ,
427      //Minus                         => Keycode::Minus,
428      //Period                        => Keycode::Period,
429      //Quote                         => Keycode::Quote,
430      //Semicolon                     => Keycode::Semicolon,
431      //Slash                         => Keycode::Slash,
432      Alt if location == Left         => Keycode::LAlt,
433      Alt if location == Right        => Keycode::RAlt,
434      Backspace if location != Numpad => Keycode::Backspace,
435      CapsLock                        => Keycode::CapsLock,
436      ContextMenu                     => Keycode::ContextMenu,
437      Control if location == Left     => Keycode::LControl,
438      Control if location == Right    => Keycode::RControl,
439      Enter if location != Numpad     => Keycode::Enter,
440      Super if location == Left       => Keycode::LWin,
441      Super if location == Right      => Keycode::RWin,
442      Shift if location == Left       => Keycode::LShift,
443      Shift if location == Right      => Keycode::RShift,
444      Space                           => Keycode::Space,
445      Tab                             => Keycode::Tab,
446      Convert                         => Keycode::Convert,
447      KanaMode                        => Keycode::KanaMode,
448      //Lang1                         => Keycode::Lang1,
449      //Lang2                         => Keycode::Lang2,
450      //Lang3                         => Keycode::Lang3,
451      //Lang4                         => Keycode::Lang4,
452      //Lang5                         => Keycode::Lang5,
453      NonConvert                      => Keycode::NonConvert,
454      Delete                          => Keycode::Delete,
455      End                             => Keycode::End,
456      Help                            => Keycode::Help,
457      Home                            => Keycode::Home,
458      Insert                          => Keycode::Insert,
459      PageDown                        => Keycode::PageDown,
460      PageUp                          => Keycode::PageUp,
461      ArrowDown                       => Keycode::Down,
462      ArrowLeft                       => Keycode::Left,
463      ArrowRight                      => Keycode::Right,
464      ArrowUp                         => Keycode::Up,
465      NumLock                         => Keycode::NumLock,
466      //Numpad0                       => Keycode::Numpad0,
467      //Numpad1                       => Keycode::Numpad1,
468      //Numpad2                       => Keycode::Numpad2,
469      //Numpad3                       => Keycode::Numpad3,
470      //Numpad4                       => Keycode::Numpad4,
471      //Numpad5                       => Keycode::Numpad5,
472      //Numpad6                       => Keycode::Numpad6,
473      //Numpad7                       => Keycode::Numpad7,
474      //Numpad8                       => Keycode::Numpad8,
475      //Numpad9                       => Keycode::Numpad9,
476      //NumpadAdd                     => Keycode::NumpadAdd,
477      Backspace if location == Numpad => Keycode::NumpadBackspace,
478      Clear if location == Numpad     => Keycode::NumpadClear,
479      //NumpadClearEntry              => Keycode::NumpadClearEntry,
480      //NumpadComma                   => Keycode::NumpadComma,
481      //NumpadDecimal                 => Keycode::NumpadDecimal,
482      //NumpadDivide                  => Keycode::NumpadDivide,
483      Enter if location == Numpad     => Keycode::NumpadEnter,
484      //NumpadEqual                   => Keycode::NumpadEqual,
485      //NumpadHash                    => Keycode::NumpadHash,
486      //NumpadMemoryAdd               => Keycode::NumpadMemoryAdd,
487      //NumpadMemoryClear             => Keycode::NumpadMemoryClear,
488      //NumpadMemoryRecall            => Keycode::NumpadMemoryRecall,
489      //NumpadMemoryStore             => Keycode::NumpadMemoryStore,
490      //NumpadMemorySubtract          => Keycode::NumpadMemorySubtract,
491      //NumpadMultiply                => Keycode::NumpadMultiply,
492      //NumpadParenLeft               => Keycode::NumpadParenLeft,
493      //NumpadParenRight              => Keycode::NumpadParenRight,
494      //NumpadStar                    => Keycode::NumpadStar,
495      //NumpadSubtract                => Keycode::NumpadSubtract,
496      Escape                          => Keycode::Escape,
497      Fn                              => Keycode::Fn,
498      FnLock                          => Keycode::FnLock,
499      PrintScreen                     => Keycode::PrintScreen,
500      ScrollLock                      => Keycode::ScrollLock,
501      Pause                           => Keycode::Pause,
502      BrowserBack                     => Keycode::BrowserBack,
503      BrowserFavorites                => Keycode::BrowserFavorites,
504      BrowserForward                  => Keycode::BrowserForward,
505      BrowserHome                     => Keycode::BrowserHome,
506      BrowserRefresh                  => Keycode::BrowserRefresh,
507      BrowserSearch                   => Keycode::BrowserSearch,
508      BrowserStop                     => Keycode::BrowserStop,
509      Eject                           => Keycode::Eject,
510      LaunchApplication1              => Keycode::LaunchApp1,
511      LaunchApplication2              => Keycode::LaunchApp2,
512      LaunchMail                      => Keycode::LaunchMail,
513      MediaPlayPause                  => Keycode::MediaPlayPause,
514      //MediaSelect                   => Keycode::MediaSelect,
515      MediaStop                       => Keycode::MediaStop,
516      MediaTrackNext                  => Keycode::MediaTrackNext,
517      MediaTrackPrevious              => Keycode::MediaTrackPrevious,
518      Power                           => Keycode::Power,
519      Standby                         => Keycode::Sleep,
520      AudioVolumeDown                 => Keycode::AudioVolumeDown,
521      AudioVolumeMute                 => Keycode::AudioVolumeMute,
522      AudioVolumeUp                   => Keycode::AudioVolumeUp,
523      WakeUp                          => Keycode::WakeUp,
524      Meta                            => Keycode::Meta,
525      Hyper                           => Keycode::Hyper,
526      //Turbo                         => Keycode::Turbo,
527      //Abort                         => Keycode::Abort,
528      //Resume                        => Keycode::Resume,
529      //Suspend                       => Keycode::Suspend,
530      Again                           => Keycode::Again,
531      Copy                            => Keycode::Copy,
532      Cut                             => Keycode::Cut,
533      Find                            => Keycode::Find,
534      Open                            => Keycode::Open,
535      Paste                           => Keycode::Paste,
536      Props                           => Keycode::Props,
537      Select                          => Keycode::Select,
538      Undo                            => Keycode::Undo,
539      Hiragana                        => Keycode::Hiragana,
540      Katakana                        => Keycode::Katakana,
541      F1                              => Keycode::F1,
542      F2                              => Keycode::F2,
543      F3                              => Keycode::F3,
544      F4                              => Keycode::F4,
545      F5                              => Keycode::F5,
546      F6                              => Keycode::F6,
547      F7                              => Keycode::F7,
548      F8                              => Keycode::F8,
549      F9                              => Keycode::F9,
550      F10                             => Keycode::F10,
551      F11                             => Keycode::F11,
552      F12                             => Keycode::F12,
553      F13                             => Keycode::F13,
554      F14                             => Keycode::F14,
555      F15                             => Keycode::F15,
556      F16                             => Keycode::F16,
557      F17                             => Keycode::F17,
558      F18                             => Keycode::F18,
559      F19                             => Keycode::F19,
560      F20                             => Keycode::F20,
561      F21                             => Keycode::F21,
562      F22                             => Keycode::F22,
563      F23                             => Keycode::F23,
564      F24                             => Keycode::F24,
565      F25                             => Keycode::F25,
566      F26                             => Keycode::F26,
567      F27                             => Keycode::F27,
568      F28                             => Keycode::F28,
569      F29                             => Keycode::F29,
570      F30                             => Keycode::F30,
571      F31                             => Keycode::F31,
572      F32                             => Keycode::F32,
573      F33                             => Keycode::F33,
574      F34                             => Keycode::F34,
575      F35                             => Keycode::F35,
576      _ => unimplemented!("unimplemented named key conversion: {:?}",
577        (key, location))
578    }
579  }
580}