use std::sync::mpsc::{self, Receiver, Sender};
use std::thread;
use std::time::Duration;
use crossterm::event::{read, Event as CrossTermEvent};
pub use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
type Rx<T> = Receiver<Event<T>>;
type Tx<T> = Sender<Event<T>>;
#[derive(Debug, Clone, Copy)]
pub enum Event<T> {
Tick,
Key(KeyEvent),
Resize(u16, u16),
User(T),
}
pub struct Events<T> {
rx: Rx<T>,
blocking: bool,
}
impl<T> Iterator for Events<T> {
type Item = Event<T>;
fn next(&mut self) -> Option<Self::Item> {
if self.blocking {
self.rx.recv().ok()
} else {
self.rx.try_recv().ok()
}
}
}
pub enum EventModel {
Fps(u64),
Blocking,
NonBlocking,
}
pub fn events<T: Send + 'static>(event_model: EventModel) -> (Tx<T>, Events<T>) {
let (tx, rx) = mpsc::channel();
let tx_clone = tx.clone();
thread::spawn(move || loop {
if let Ok(ev) = read() {
match ev {
CrossTermEvent::Key(k) => {
let _ = tx_clone.send(Event::Key(k));
}
CrossTermEvent::Resize(w, h) => {
let _ = tx_clone.send(Event::Resize(w, h));
}
_ => {}
}
}
});
if let EventModel::Fps(fps) = event_model {
let tx = tx.clone();
thread::spawn(move || loop {
let _ = tx.send(Event::Tick);
thread::sleep(Duration::from_millis(1000 / fps));
});
}
let blocking = match event_model {
EventModel::NonBlocking => false,
_ => true,
};
(tx, Events { rx, blocking })
}