gooey/interface/view/input/button/
mod.rs1use std;
2use derive_more::{From, TryInto};
3use parse_display::{Display, FromStr};
4use strum::{EnumCount, FromRepr};
5use super::Modifiers;
6
7pub mod keycode;
8pub use self::keycode::Keycode;
9
10#[derive(Clone, Copy, Debug, Eq)]
11pub struct Button {
12 pub variant : Variant,
13 pub modifiers : Modifiers
14}
15
16#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
17pub enum State {
18 Pressed,
19 Released
20}
21
22#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd,
32 Display, FromStr, From, TryInto)]
33#[display("{0:?}")] pub enum Variant {
35 Keycode (Keycode),
36 Mouse (Mouse)
37}
38
39#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, EnumCount,
41 FromRepr, FromStr)]
42pub enum Mouse {
43 Mouse1, Mouse2, Mouse3, Mouse4, Mouse5
44}
45
46impl PartialEq for Button {
47 fn eq (&self, other : &Self) -> bool {
48 if self.variant != other.variant {
49 false
50 } else {
51 if self.modifiers.contains (Modifiers::ANY) ||
52 other.modifiers.contains (Modifiers::ANY)
53 {
54 true
55 } else {
56 self.modifiers == other.modifiers
57 }
58 }
59 }
60}
61
62impl PartialOrd for Button {
64 fn partial_cmp (&self, other : &Self) -> Option <std::cmp::Ordering> {
65 let out = if self == other {
66 std::cmp::Ordering::Equal
67 } else {
68 if self.variant > other.variant {
69 std::cmp::Ordering::Greater
70 } else if self.variant < other.variant {
71 std::cmp::Ordering::Less
72 } else if self.modifiers > other.modifiers {
73 std::cmp::Ordering::Greater
74 } else if self.modifiers < other.modifiers {
75 std::cmp::Ordering::Less
76 } else {
77 unreachable!()
78 }
79 };
80 Some (out)
81 }
82}
83
84impl Ord for Button {
86 fn cmp (&self, other : &Self) -> std::cmp::Ordering {
87 self.partial_cmp (other).unwrap()
88 }
89}
90
91impl <K : Into <Variant>> From <K> for Button {
92 fn from (k : K) -> Self {
93 Button {
94 variant: k.into(),
95 modifiers: Modifiers::empty()
96 }
97 }
98}
99
100#[cfg(test)]
101mod test {
102 use strum;
103 use crate::interface::controller::controls;
104
105 use super::*;
106
107 #[test]
108 fn variant_unique_serialization() {
109 use strum::EnumCount;
110 for i in 0..Keycode::COUNT {
111 use std::str::FromStr;
112
113 let variant = Variant::from (Keycode::from_repr (i).unwrap());
114 let s = variant.to_string();
115 assert_eq!(variant, Variant::from_str (&s).unwrap());
116 }
117
118 for i in 0..Mouse::COUNT {
119 use std::str::FromStr;
120
121 let variant = Variant::from (Mouse::from_repr (i).unwrap());
122 let s = variant.to_string();
123 assert_eq!(variant, Variant::from_str (&s).unwrap());
124 }
125 }
126
127 #[test]
128 fn button_equality() {
129 let a = Button {
130 modifiers: Modifiers::ANY,
131 .. Button::from (Keycode::A)
132 };
133 let b = Button {
134 modifiers: Modifiers::SHIFT,
135 .. Button::from (Keycode::A)
136 };
137 let c = Button {
138 modifiers: Modifiers::ANY,
139 .. Button::from (Keycode::C)
140 };
141 let d = Button::from (Keycode::C);
142 assert_eq!(a, b);
143 assert_eq!(&a, &b);
144 assert_ne!(a, c);
145 assert_eq!(c, d);
146 assert_eq!(&c, &d);
147 let buttons = vec![(a, controls::Button (0))];
148 assert_eq!(a.cmp (&b), std::cmp::Ordering::Equal);
149 assert!(buttons.binary_search_by_key (&b, |(button, _)| *button).is_ok());
150 }
151}