1use egui::{InputState, Key, KeyboardShortcut, ModifierNames, PointerButton};
2
3pub trait Bind: Clone {
10 fn set(&mut self, keyboard: Option<KeyboardShortcut>, pointer: Option<PointerButton>);
16
17 fn format(&self, names: &ModifierNames<'_>, is_mac: bool) -> String;
26
27 fn pressed(&self, input: &mut InputState) -> bool;
35}
36
37impl Bind for KeyboardShortcut {
39 fn set(&mut self, keyboard: Option<KeyboardShortcut>, _pointer: Option<PointerButton>) {
40 if let Some(keyboard) = keyboard {
41 *self = keyboard
42 }
43 }
44
45 fn format(&self, names: &ModifierNames<'_>, is_mac: bool) -> String {
46 self.format(names, is_mac)
47 }
48
49 fn pressed(&self, input: &mut InputState) -> bool {
50 input.consume_shortcut(self)
51 }
52}
53
54impl Bind for Option<KeyboardShortcut> {
55 fn set(&mut self, keyboard: Option<KeyboardShortcut>, _pointer: Option<PointerButton>) {
56 *self = keyboard;
57 }
58
59 fn format(&self, names: &ModifierNames<'_>, is_mac: bool) -> String {
60 self.as_ref().map_or_else(
61 || "None".to_string(),
62 |shortcut| shortcut.format(names, is_mac),
63 )
64 }
65
66 fn pressed(&self, input: &mut InputState) -> bool {
67 if let Some(shortcut) = self {
68 input.consume_shortcut(shortcut)
69 } else {
70 false
71 }
72 }
73}
74
75impl Bind for Key {
77 fn set(&mut self, keyboard: Option<KeyboardShortcut>, _pointer: Option<PointerButton>) {
78 if let Some(keyboard) = keyboard {
79 *self = keyboard.logical_key
80 }
81 }
82
83 fn format(&self, _names: &ModifierNames<'_>, _is_mac: bool) -> String {
84 self.name().to_string()
85 }
86
87 fn pressed(&self, input: &mut InputState) -> bool {
88 input.key_pressed(*self)
89 }
90}
91
92impl Bind for Option<Key> {
93 fn set(&mut self, keyboard: Option<KeyboardShortcut>, _pointer: Option<PointerButton>) {
94 if let Some(keyboard) = keyboard {
95 *self = Some(keyboard.logical_key)
96 }
97 }
98
99 fn format(&self, _names: &ModifierNames<'_>, _is_mac: bool) -> String {
100 self.as_ref()
101 .map_or_else(|| "None".to_string(), |key| key.name().to_string())
102 }
103
104 fn pressed(&self, input: &mut InputState) -> bool {
105 if let Some(key) = self {
106 input.key_pressed(*key)
107 } else {
108 false
109 }
110 }
111}
112
113impl Bind for PointerButton {
115 fn set(&mut self, _keyboard: Option<KeyboardShortcut>, pointer: Option<PointerButton>) {
116 if let Some(pointer) = pointer {
117 *self = pointer
118 }
119 }
120
121 fn format(&self, _names: &ModifierNames<'_>, _is_mac: bool) -> String {
122 format!("{:?}", self)
123 }
124
125 fn pressed(&self, input: &mut InputState) -> bool {
126 input.pointer.button_pressed(*self)
127 }
128}
129
130impl Bind for Option<PointerButton> {
131 fn set(&mut self, _keyboard: Option<KeyboardShortcut>, pointer: Option<PointerButton>) {
132 *self = pointer;
133 }
134
135 fn format(&self, _names: &ModifierNames<'_>, _is_mac: bool) -> String {
136 self.as_ref()
137 .map_or_else(|| "None".to_string(), |button| format!("{:?}", button))
138 }
139
140 fn pressed(&self, input: &mut InputState) -> bool {
141 if let Some(button) = self {
142 input.pointer.button_pressed(*button)
143 } else {
144 false
145 }
146 }
147}
148
149#[derive(Debug, Clone, Copy, Default, PartialEq)]
151#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
152pub struct Shortcut {
153 keyboard: Option<KeyboardShortcut>,
155 pointer: Option<PointerButton>,
157}
158
159impl Shortcut {
160 pub const NONE: Self = Self {
162 keyboard: None,
163 pointer: None,
164 };
165
166 pub fn new(keyboard: Option<KeyboardShortcut>, pointer: Option<PointerButton>) -> Self {
173 Self { keyboard, pointer }
174 }
175
176 #[inline]
178 pub fn keyboard(&self) -> Option<KeyboardShortcut> {
179 self.keyboard
180 }
181
182 #[inline]
184 pub const fn pointer(&self) -> Option<PointerButton> {
185 self.pointer
186 }
187}
188
189impl Bind for Shortcut {
190 fn set(&mut self, keyboard: Option<KeyboardShortcut>, pointer: Option<PointerButton>) {
191 self.keyboard = keyboard;
192 self.pointer = pointer;
193 }
194
195 fn format(&self, names: &ModifierNames<'_>, is_mac: bool) -> String {
196 let mut string = self.keyboard.map_or_else(
197 || String::with_capacity(9),
198 |kb| Into::<KeyboardShortcut>::into(kb).format(names, is_mac),
199 );
200 if let Some(pointer) = self.pointer {
201 if !string.is_empty() {
202 string.push('+');
203 }
204 string.push_str(&pointer.format(names, is_mac));
205 }
206 if string.is_empty() {
207 string.push_str("None");
208 }
209 string
210 }
211
212 fn pressed(&self, input: &mut InputState) -> bool {
213 let mut pressed = false;
214 if let Some(kb) = &self.keyboard {
215 pressed = input.consume_shortcut(kb);
216 }
217 if let Some(button) = self.pointer {
218 if self.keyboard.is_none() {
219 return input.pointer.button_clicked(button);
220 }
221 pressed &= input.pointer.button_clicked(button);
222 }
223 pressed
224 }
225}
226
227impl From<Shortcut> for Option<KeyboardShortcut> {
228 fn from(value: Shortcut) -> Self {
229 value.keyboard
230 }
231}
232
233impl From<Shortcut> for Option<PointerButton> {
234 fn from(value: Shortcut) -> Self {
235 value.pointer
236 }
237}