1use crate::grid::Pos;
4use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
7pub struct KeyModifiers(u8);
13
14impl KeyModifiers {
15 pub const NONE: Self = Self(0);
17 pub const SHIFT: Self = Self(1 << 0);
19 pub const CONTROL: Self = Self(1 << 1);
21 pub const ALT: Self = Self(1 << 2);
23
24 #[must_use]
26 pub const fn contains(self, other: Self) -> bool {
27 (self.0 & other.0) == other.0
28 }
29
30 #[must_use]
32 pub const fn is_empty(self) -> bool {
33 self.0 == 0
34 }
35}
36
37impl BitOr for KeyModifiers {
38 type Output = Self;
39 fn bitor(self, rhs: Self) -> Self {
40 Self(self.0 | rhs.0)
41 }
42}
43
44impl BitOrAssign for KeyModifiers {
45 fn bitor_assign(&mut self, rhs: Self) {
46 self.0 |= rhs.0;
47 }
48}
49
50impl BitAnd for KeyModifiers {
51 type Output = Self;
52 fn bitand(self, rhs: Self) -> Self {
53 Self(self.0 & rhs.0)
54 }
55}
56
57impl BitAndAssign for KeyModifiers {
58 fn bitand_assign(&mut self, rhs: Self) {
59 self.0 &= rhs.0;
60 }
61}
62
63impl Not for KeyModifiers {
64 type Output = Self;
65 fn not(self) -> Self {
66 Self(!self.0)
67 }
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
71pub enum KeyCode {
73 Char(char),
75 F(u8),
77 Backspace,
79 Enter,
81 Left,
83 Right,
85 Up,
87 Down,
89 Home,
91 End,
93 PageUp,
95 PageDown,
97 Tab,
99 BackTab,
101 Delete,
103 Insert,
105 Escape,
107}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
110pub struct KeyEvent {
112 pub code: KeyCode,
114 pub modifiers: KeyModifiers,
116}
117
118#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
119pub enum MouseButton {
121 Left,
123 Right,
125 Middle,
127}
128
129#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
130pub enum MouseEventKind {
132 Down(MouseButton),
134 Up(MouseButton),
136 Moved,
138 ScrollUp,
140 ScrollDown,
142}
143
144#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
145pub struct MouseEvent {
147 pub kind: MouseEventKind,
149 pub position: Pos,
151 pub modifiers: KeyModifiers,
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
156pub enum Event {
158 Key(KeyEvent),
160 Mouse(MouseEvent),
162 Resize(u16, u16),
164 Close,
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171
172 #[test]
173 fn test_key_modifiers() {
174 let mods = KeyModifiers::SHIFT | KeyModifiers::CONTROL;
175 assert!(mods.contains(KeyModifiers::SHIFT));
176 assert!(mods.contains(KeyModifiers::CONTROL));
177 assert!(!mods.contains(KeyModifiers::ALT));
178 assert!(!mods.is_empty());
179
180 let inverse = !mods;
181 assert!(inverse.contains(KeyModifiers::ALT));
182 assert!(!inverse.contains(KeyModifiers::SHIFT));
183 assert!(!inverse.contains(KeyModifiers::CONTROL));
184 }
185
186 #[test]
187 fn test_event_construction() {
188 let key_event = KeyEvent {
189 code: KeyCode::Char('a'),
190 modifiers: KeyModifiers::SHIFT,
191 };
192 let event = Event::Key(key_event);
193
194 if let Event::Key(ke) = event {
195 assert_eq!(ke.code, KeyCode::Char('a'));
196 assert!(ke.modifiers.contains(KeyModifiers::SHIFT));
197 } else {
198 panic!("Expected Event::Key");
199 }
200 }
201
202 #[test]
203 fn test_mouse_event() {
204 let mouse_event = MouseEvent {
205 kind: MouseEventKind::Down(MouseButton::Left),
206 position: Pos { x: 10, y: 5 },
207 modifiers: KeyModifiers::NONE,
208 };
209 let event = Event::Mouse(mouse_event);
210
211 assert!(matches!(event, Event::Mouse(_)));
212 }
213}