1use crate::{Button, Event, Input};
2
3#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
5pub enum ButtonState {
6    Press,
8    Release,
10}
11
12#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
14pub struct ButtonArgs {
15    pub state: ButtonState,
17    pub button: Button,
19    pub scancode: Option<i32>,
29}
30
31pub trait ButtonEvent: Sized {
33    fn from_button_args(args: ButtonArgs, old_event: &Self) -> Option<Self>;
37    fn button<U, F>(&self, f: F) -> Option<U>
39    where
40        F: FnMut(ButtonArgs) -> U;
41    fn button_args(&self) -> Option<ButtonArgs> {
43        self.button(|args| args)
44    }
45}
46
47impl ButtonEvent for Event {
48    fn from_button_args(args: ButtonArgs, old_event: &Self) -> Option<Self> {
49        let timestamp = if let Event::Input(_, x) = old_event {
50            *x
51        } else {
52            None
53        };
54        Some(Event::Input(Input::Button(args), timestamp))
55    }
56    fn button<U, F>(&self, mut f: F) -> Option<U>
57    where
58        F: FnMut(ButtonArgs) -> U,
59    {
60        match *self {
61            Event::Input(Input::Button(args), _) => Some(f(args)),
62            _ => None,
63        }
64    }
65}
66
67pub trait PressEvent: Sized {
69    fn from_button(button: Button, old_event: &Self) -> Option<Self>;
74    fn press<U, F>(&self, f: F) -> Option<U>
76    where
77        F: FnMut(Button) -> U;
78    fn press_args(&self) -> Option<Button> {
80        self.press(|button| button)
81    }
82}
83
84impl<T> PressEvent for T
85where
86    T: ButtonEvent,
87{
88    fn from_button(button: Button, old_event: &Self) -> Option<Self> {
89        if let Some(mut args) = old_event.button_args() {
90            args.state = ButtonState::Press;
91            args.button = button;
92            ButtonEvent::from_button_args(args, old_event)
93        } else {
94            ButtonEvent::from_button_args(
95                ButtonArgs {
96                    state: ButtonState::Press,
97                    button,
98                    scancode: None,
99                },
100                old_event,
101            )
102        }
103    }
104
105    fn press<U, F>(&self, mut f: F) -> Option<U>
106    where
107        F: FnMut(Button) -> U,
108    {
109        if let Some(ButtonArgs {
110            state: ButtonState::Press,
111            button,
112            ..
113        }) = self.button_args()
114        {
115            Some(f(button))
116        } else {
117            None
118        }
119    }
120}
121
122pub trait ReleaseEvent: Sized {
124    fn from_button(button: Button, old_event: &Self) -> Option<Self>;
129    fn release<U, F>(&self, f: F) -> Option<U>
131    where
132        F: FnMut(Button) -> U;
133    fn release_args(&self) -> Option<Button> {
135        self.release(|button| button)
136    }
137}
138
139impl<T> ReleaseEvent for T
140where
141    T: ButtonEvent,
142{
143    fn from_button(button: Button, old_event: &Self) -> Option<Self> {
144        if let Some(mut args) = old_event.button_args() {
145            args.state = ButtonState::Release;
146            args.button = button;
147            ButtonEvent::from_button_args(args, old_event)
148        } else {
149            ButtonEvent::from_button_args(
150                ButtonArgs {
151                    state: ButtonState::Release,
152                    button,
153                    scancode: None,
154                },
155                old_event,
156            )
157        }
158    }
159
160    fn release<U, F>(&self, mut f: F) -> Option<U>
161    where
162        F: FnMut(Button) -> U,
163    {
164        if let Some(ButtonArgs {
165            state: ButtonState::Release,
166            button,
167            ..
168        }) = self.button_args()
169        {
170            Some(f(button))
171        } else {
172            None
173        }
174    }
175}
176
177#[cfg(test)]
178mod tests {
179    use super::*;
180
181    #[test]
182    fn test_input_press() {
183        use super::super::{Button, Key};
184
185        let e: Event = ButtonArgs {
186            state: ButtonState::Press,
187            button: Key::S.into(),
188            scancode: None,
189        }
190        .into();
191        let button = Button::Keyboard(Key::A);
192        let x: Option<Event> = PressEvent::from_button(button, &e);
193        let y: Option<Event> = x
194            .clone()
195            .unwrap()
196            .press(|button| PressEvent::from_button(button, x.as_ref().unwrap()))
197            .unwrap();
198        assert_eq!(x, y);
199    }
200
201    #[test]
202    fn test_input_release() {
203        use super::super::{Button, Key};
204
205        let e: Event = ButtonArgs {
206            state: ButtonState::Release,
207            button: Key::S.into(),
208            scancode: None,
209        }
210        .into();
211        let button = Button::Keyboard(Key::A);
212        let x: Option<Event> = ReleaseEvent::from_button(button, &e);
213        let y: Option<Event> = x
214            .clone()
215            .unwrap()
216            .release(|button| ReleaseEvent::from_button(button, x.as_ref().unwrap()))
217            .unwrap();
218        assert_eq!(x, y);
219    }
220}