1use super::*;
2
3pub mod prelude
4{
5 pub use super::traits::*;
6 pub use super::{ButtonEvolution, ButtonRepeat, ButtonState, ButtonStateEvolution, ButtonToggle};
7}
8pub mod traits
9{
10 pub use super::{ButtonEvolutionExtension, ButtonRepeatExtension, ButtonStateExtension, ButtonToggleExtension};
11}
12
13pub type ButtonEvolution = PreviousValue<ButtonState>;
14
15#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
16#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
17pub enum ButtonToggle
18{
19 #[default]
21 Hold,
22 Toggle,
24}
25pub trait ButtonToggleExtension: Has<ButtonToggle>
26{
27 fn is_hold(&self) -> bool { self.retrieve().is_hold() }
28 fn is_toggle(&self) -> bool { self.retrieve().is_toggle() }
29}
30impl<T> ButtonToggleExtension for T where T: Has<ButtonToggle> {}
31
32impl ButtonToggle
33{
34 pub const fn is_hold(self) -> bool { matches!(self, Self::Hold) }
35 pub const fn is_toggle(self) -> bool { matches!(self, Self::Toggle) }
36}
37impl From<bool> for ButtonToggle
38{
39 fn from(value: bool) -> Self { if value { Self::Toggle } else { Self::Hold } }
40}
41impl From<ButtonToggle> for bool
42{
43 fn from(value: ButtonToggle) -> Self { value.is_toggle() }
44}
45
46#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
48#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
49pub enum ButtonState
50{
51 #[default]
53 Down,
54 Up,
56}
57pub trait ButtonStateExtension: Has<ButtonState>
58{
59 fn is_up(&self) -> bool { self.retrieve().is_up() }
60 fn is_down(&self) -> bool { self.retrieve().is_down() }
61}
62impl<T> ButtonStateExtension for T where T: Has<ButtonState> {}
63
64impl ButtonState
65{
66 pub const fn is_up(self) -> bool { matches!(self, ButtonState::Up) }
67 pub const fn is_down(self) -> bool { matches!(self, ButtonState::Down) }
68}
69impl From<bool> for ButtonState
70{
71 fn from(value: bool) -> Self { if value { Self::Down } else { Self::Up } }
72}
73impl From<ButtonState> for bool
74{
75 fn from(value: ButtonState) -> Self { value.is_down() }
76}
77
78#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
79#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
80pub enum ButtonRepeat
81{
82 #[default]
83 NotRepeated,
84 Repeated,
85}
86pub trait ButtonRepeatExtension: Has<ButtonRepeat>
87{
88 fn is_repeated(&self) -> bool { self.retrieve().is_repeated() }
89 fn is_not_repeated(&self) -> bool { self.retrieve().is_not_repeated() }
90}
91impl<T> ButtonRepeatExtension for T where T: Has<ButtonRepeat> {}
92
93impl ButtonRepeat
94{
95 pub const fn is_repeated(self) -> bool { matches!(self, ButtonRepeat::Repeated) }
96 pub const fn is_not_repeated(self) -> bool { matches!(self, ButtonRepeat::NotRepeated) }
97}
98impl From<bool> for ButtonRepeat
99{
100 fn from(value: bool) -> Self { if value { Self::Repeated } else { Self::NotRepeated } }
101}
102impl From<ButtonRepeat> for bool
103{
104 fn from(value: ButtonRepeat) -> Self { value.is_repeated() }
105}
106
107#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
108pub enum ButtonStateEvolution
109{
110 Down,
111 Up,
112 Pressed,
114 Released,
116}
117impl From<ButtonState> for ButtonStateEvolution
118{
119 fn from(value: ButtonState) -> Self
120 {
121 match value
122 {
123 ButtonState::Down => Self::Down,
124 ButtonState::Up => Self::Up,
125 }
126 }
127}
128impl Evolution<ButtonState> for ButtonStateEvolution
129{
130 fn value(&self) -> ButtonState { matches!(self, Self::Down | Self::Pressed).into() }
131 fn old_value(&self) -> ButtonState { matches!(self, Self::Down | Self::Released).into() }
132}
133
134pub trait ButtonEvolutionExtension: Evolution<ButtonState>
135{
136 fn is_down(&self) -> bool;
137 fn was_down(&self) -> bool;
138
139 fn is_up(&self) -> bool { !self.is_down() }
140 fn was_up(&self) -> bool { !self.was_down() }
141
142 fn is_pressed(&self) -> bool { self.is_down() && (!self.was_down()) }
144 fn is_released(&self) -> bool { self.was_down() && (!self.is_down()) }
146
147 fn is_toggled(&self) -> bool { self.is_down() != self.was_down() }
148 fn is_constant(&self) -> bool { self.is_down() == self.was_down() }
149
150 fn is_hold(&self) -> bool { self.is_constant() && self.is_down() }
151
152 fn evolution(&self) -> ButtonStateEvolution
153 {
154 match (self.is_down(), self.was_down())
155 {
156 (true, true) => ButtonStateEvolution::Down,
157 (true, false) => ButtonStateEvolution::Pressed,
158 (false, true) => ButtonStateEvolution::Released,
159 (false, false) => ButtonStateEvolution::Up,
160 }
161 }
162}
163
164impl<T> ButtonEvolutionExtension for T
165where
166 T: Evolution<ButtonState>,
167{
168 fn is_down(&self) -> bool { self.value().is_down() }
169 fn was_down(&self) -> bool { self.old_value().is_down() }
170}