gooey/interface/view/input/button/
mod.rs1use std;
2use derive_more::{From, TryInto};
3use parse_display::{Display, FromStr};
4use strum::{EnumCount, FromRepr};
5use crate::interface::controller::controls;
6use super::Modifiers;
7
8pub mod keycode;
9pub use self::keycode::Keycode;
10
11#[derive(Clone, Copy, Debug, Eq)]
12pub struct Button {
13 pub variant : Variant,
14 pub modifiers : Modifiers
15}
16
17#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
18pub enum State {
19 Pressed,
20 Released
21}
22
23#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Display, FromStr, From,
33 TryInto)]
34#[display("{0:?}")] pub enum Variant {
36 Keycode (Keycode),
37 Mouse (Mouse)
38}
39
40#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, EnumCount, FromRepr,
42 FromStr)]
43pub enum Mouse {
44 Mouse1, Mouse2, Mouse3, Mouse4, Mouse5
45}
46
47#[derive(Clone, Debug, Eq, PartialEq)]
49pub struct Binding <E : controls::Id <controls::Button> = controls::Nil>
50 (pub Button, pub controls::button::Control <E>, pub std::marker::PhantomData <E>);
51
52impl <E : controls::Id <controls::Button>> Binding <E> {
53 pub fn new (button : Button, control : controls::button::Control <E>) -> Self {
54 Binding (button, control, Default::default())
55 }
56}
57impl <E : controls::Id <controls::Button>>
58 From <controls::button::Binding <E>> for Binding <E>
59{
60 fn from (controls::button::Binding (control, input, _) : controls::button::Binding <E>)
61 -> Self
62 {
63 Binding::new (input, control)
64 }
65}
66impl <E : controls::Id <controls::Button>>
67 From <Binding <E>> for (Button, controls::button::Control <E>)
68{
69 fn from (Binding (input, control, _) : Binding <E>) -> Self {
70 (input, control)
71 }
72}
73impl <E : controls::Id <controls::Button>>
74 From <(Button, controls::button::Control <E>)> for Binding <E>
75{
76 fn from ((input, control) : (Button, controls::button::Control <E>)) -> Self {
77 Binding::new (input, control)
78 }
79}
80
81impl Button {
82 pub const fn with_modifiers (self, modifiers : Modifiers) -> Self {
83 Button { modifiers, .. self }
84 }
85}
86
87impl PartialEq for Button {
88 fn eq (&self, other : &Self) -> bool {
89 if self.variant != other.variant {
90 false
91 } else if self.modifiers.contains (Modifiers::ANY)
92 || other.modifiers.contains (Modifiers::ANY)
93 {
94 true
95 } else {
96 self.modifiers == other.modifiers
97 }
98 }
99}
100
101#[expect(clippy::non_canonical_partial_ord_impl)]
103impl PartialOrd for Button {
104 fn partial_cmp (&self, other : &Self) -> Option <std::cmp::Ordering> {
105 let out = if self == other {
106 std::cmp::Ordering::Equal
107 } else if self.variant > other.variant {
108 std::cmp::Ordering::Greater
109 } else if self.variant < other.variant {
110 std::cmp::Ordering::Less
111 } else if self.modifiers > other.modifiers {
112 std::cmp::Ordering::Greater
113 } else if self.modifiers < other.modifiers {
114 std::cmp::Ordering::Less
115 } else {
116 unreachable!()
117 };
118 Some (out)
119 }
120}
121
122impl Ord for Button {
124 fn cmp (&self, other : &Self) -> std::cmp::Ordering {
125 self.partial_cmp (other).unwrap()
126 }
127}
128
129impl <K : Into <Variant>> From <K> for Button {
130 fn from (k : K) -> Self {
131 Button {
132 variant: k.into(),
133 modifiers: Modifiers::empty()
134 }
135 }
136}
137
138struct ButtonVisitor;
143
144impl serde::Serialize for Button {
145 fn serialize <S : serde::Serializer> (&self, serializer : S)
146 -> Result <S::Ok, S::Error>
147 {
148 serializer.serialize_str (&format!("{}{}",
149 self.variant, self.modifiers.to_string().to_uppercase()))
150 }
151}
152
153impl serde::de::Visitor <'_> for ButtonVisitor {
154 type Value = Button;
155 fn expecting (&self, formatter : &mut std::fmt::Formatter) -> std::fmt::Result {
156 formatter.write_str ("A control: button pair")
157 }
158 fn visit_str <ERR : serde::de::Error> (self, v : &str) -> Result <Self::Value, ERR> {
159 use std::str::FromStr;
160 let mut iter = v.split (':').next().unwrap().split ('+');
161 let s = iter.next().unwrap();
162 let variant = Variant::from_str (s).map_err (|err|{
163 log::error!(err:?, string=s; "error parsing button");
164 panic!("error parsing button string \"{s}\": {err}")
165 }).unwrap();
166 let mut modifiers = Modifiers::empty();
167 for modifier in iter {
168 match modifier.to_lowercase().as_str() {
169 "shift" => modifiers |= Modifiers::SHIFT,
170 "ctrl" => modifiers |= Modifiers::CTRL,
171 "alt" => modifiers |= Modifiers::ALT,
172 "super" => modifiers |= Modifiers::SUPER,
173 "any" => modifiers |= Modifiers::ANY,
174 _ => return Err (
175 ERR::custom (format!("Unrecognized modifier: {modifier:?}")))
176 }
177 }
178 Ok (Button { variant, modifiers })
179 }
180}
181
182impl <'de> serde::Deserialize <'de> for Button {
183 fn deserialize <D : serde::Deserializer <'de>> (deserializer : D)
184 -> Result <Self, D::Error>
185 {
186 deserializer.deserialize_str (ButtonVisitor)
187 }
188}
189
190struct BindingVisitor <E : controls::Id <controls::Button> = controls::Nil> (
191 std::marker::PhantomData <E>);
192
193impl <E : controls::Id <controls::Button>> serde::Serialize for Binding <E> {
194 fn serialize <S : serde::Serializer> (&self, serializer : S)
195 -> Result <S::Ok, S::Error>
196 {
197 let input = serde_plain::to_string (&self.0).unwrap();
198 let control = serde_plain::to_string (&self.1).unwrap();
199 serializer.serialize_str (&format!("{input}: {control}"))
200 }
201}
202
203impl <E : controls::Id <controls::Button>>
204 serde::de::Visitor <'_> for BindingVisitor <E>
205{
206 type Value = Binding <E>;
207 fn expecting (&self, formatter : &mut std::fmt::Formatter) -> std::fmt::Result {
208 formatter.write_str ("A button: control pair")
209 }
210 fn visit_str <ERR : serde::de::Error> (self, v : &str) -> Result <Self::Value, ERR> {
211 let input = {
212 let s = v.split (':').next().unwrap();
213 serde_plain::from_str::<Button> (s).unwrap()
214 };
215 let control : controls::button::Control <E> = {
216 let s = v.split (' ').nth (1).unwrap();
217 serde_plain::from_str::<controls::button::Control <E>> (s).unwrap()
218 };
219 Ok (Binding::new (input, control))
220 }
221}
222
223impl <'de, E : controls::Id <controls::Button>>
224 serde::Deserialize <'de> for Binding <E>
225{
226 fn deserialize <D : serde::Deserializer <'de>> (deserializer : D)
227 -> Result <Self, D::Error>
228 {
229 deserializer.deserialize_str (BindingVisitor (Default::default()))
230 }
231}
232
233#[cfg(test)]
234mod test {
235 use strum;
236 use crate::interface::controller::controls;
237
238 use super::*;
239
240 #[test]
241 fn variant_unique_serialization() {
242 use strum::EnumCount;
243 for i in 0..Keycode::COUNT {
244 use std::str::FromStr;
245 let variant = Variant::from (Keycode::from_repr (i).unwrap());
246 let s = variant.to_string();
247 assert_eq!(variant, Variant::from_str (&s).unwrap());
248 }
249
250 for i in 0..Mouse::COUNT {
251 use std::str::FromStr;
252 let variant = Variant::from (Mouse::from_repr (i).unwrap());
253 let s = variant.to_string();
254 assert_eq!(variant, Variant::from_str (&s).unwrap());
255 }
256 }
257
258 #[test]
259 fn button_equality() {
260 let a = Button { modifiers: Modifiers::ANY, .. Button::from (Keycode::A) };
261 let b = Button { modifiers: Modifiers::SHIFT, .. Button::from (Keycode::A) };
262 let c = Button { modifiers: Modifiers::ANY, .. Button::from (Keycode::C) };
263 let d = Button::from (Keycode::C);
264 assert_eq!(a, b);
265 assert_eq!(&a, &b);
266 assert_ne!(a, c);
267 assert_eq!(c, d);
268 assert_eq!(&c, &d);
269 let buttons = [(a, controls::Button (0))];
270 assert_eq!(a.cmp (&b), std::cmp::Ordering::Equal);
271 let _ = buttons.binary_search_by_key (&b, |(button, _)| *button).unwrap();
272 }
273}