mal/event/
events.rs

1use crate::event::Key;
2use crossterm::event::{self, Event as CEvent};
3use std::{
4    sync::mpsc,
5    thread,
6    time::{Duration, Instant},
7};
8
9#[derive(Debug, Clone, Copy)]
10pub struct EventConfig {
11    pub exit_key: Key,
12    pub tick_rate: Duration,
13}
14
15impl Default for EventConfig {
16    fn default() -> EventConfig {
17        EventConfig {
18            exit_key: Key::Ctrl('c'),
19            tick_rate: Duration::from_millis(250),
20        }
21    }
22}
23
24pub enum Event<I> {
25    Input(I),
26    Tick,
27}
28
29pub struct Events {
30    rx: mpsc::Receiver<Event<Key>>,
31    _tx: mpsc::Sender<Event<Key>>,
32}
33
34impl Events {
35    pub fn new(tick_rate: u64) -> Self {
36        Events::with_config(EventConfig {
37            tick_rate: Duration::from_millis(tick_rate),
38            ..Default::default()
39        })
40    }
41
42    pub fn with_config(config: EventConfig) -> Events {
43        let (tx, rx) = mpsc::channel();
44        let event_tx = tx.clone();
45        let tick_rate = config.tick_rate;
46
47        thread::spawn(move || {
48            let mut last_tick = Instant::now();
49
50            loop {
51                let timeout = tick_rate
52                    .checked_sub(last_tick.elapsed())
53                    .unwrap_or_else(|| Duration::from_secs(0));
54
55                if event::poll(timeout).unwrap() {
56                    if let CEvent::Key(key_event) = event::read().unwrap() {
57                        let key = Key::from(key_event);
58                        if event_tx.send(Event::Input(key)).is_err() {
59                            break;
60                        }
61                    }
62                }
63
64                if last_tick.elapsed() >= tick_rate {
65                    if event_tx.send(Event::Tick).is_err() {
66                        break;
67                    }
68                    last_tick = Instant::now();
69                }
70            }
71        });
72
73        Events { rx, _tx: tx }
74    }
75
76    pub fn next(&self) -> Result<Event<Key>, mpsc::RecvError> {
77        self.rx.recv()
78    }
79}