1use crate::app::AppResult;
2use crossterm::event::{self, Event as CrosstermEvent, KeyEvent, MouseEvent};
3use std::sync::mpsc;
4use std::thread;
5use std::time::{Duration, Instant};
6
7#[derive(Clone, Copy, Debug)]
8pub enum Event {
9 Tick,
10 Key(KeyEvent),
11 Mouse(MouseEvent),
12 Resize(u16, u16),
13}
14
15#[allow(dead_code)]
16#[derive(Debug)]
17pub struct EventHandler {
18 sender: mpsc::Sender<Event>,
19 receiver: mpsc::Receiver<Event>,
20 handler: thread::JoinHandle<()>,
21}
22
23impl EventHandler {
24 pub fn new(tick_rate: u64) -> Self {
25 let tick_rate = Duration::from_millis(tick_rate);
26 let (sender, receiver) = mpsc::channel();
27 let handler = {
28 let sender = sender.clone();
29 thread::spawn(move || {
30 let mut last_tick = Instant::now();
31 loop {
32 let timeout = tick_rate
33 .checked_sub(last_tick.elapsed())
34 .unwrap_or(tick_rate);
35
36 if event::poll(timeout).expect("no events available") {
37 match event::read().expect("unable to read event") {
38 CrosstermEvent::Key(e) => sender.send(Event::Key(e)),
39 CrosstermEvent::Mouse(e) => sender.send(Event::Mouse(e)),
40 CrosstermEvent::Resize(w, h) => sender.send(Event::Resize(w, h)),
41 _ => Ok(()),
42 }
43 .ok();
44 }
45
46 if last_tick.elapsed() >= tick_rate {
47 sender.send(Event::Tick).ok();
48 last_tick = Instant::now();
49 }
50 }
51 })
52 };
53 Self {
54 sender,
55 receiver,
56 handler,
57 }
58 }
59
60 pub fn next(&self) -> AppResult<Event> {
61 Ok(self.receiver.recv()?)
62 }
63}