pub mod color;
mod cursor;
mod error;
pub mod event;
mod input;
pub mod key;
pub mod model;
mod output;
mod raw;
mod renderer;
use model::ModelAct;
use std::{
fmt::Debug,
sync::{
mpsc::{channel, Receiver, Sender},
Arc, Mutex,
},
thread,
time::Duration,
};
use event::Event;
use input::KeyBoard;
use renderer::StandardRenderer;
pub struct Program<T, E: Send + Debug> {
renderer: Arc<Mutex<StandardRenderer>>,
event_tx: Sender<Event<E>>,
event_rx: Arc<Receiver<Event<E>>>,
model: Arc<Mutex<Box<dyn ModelAct<T, E>>>>,
}
impl<T, E: Send + Debug + 'static> Program<T, E> {
pub fn new(model: Box<dyn ModelAct<T, E>>) -> Program<T, E> {
let (e_tx, e_rx) = channel();
Program {
renderer: Arc::new(Mutex::new(StandardRenderer::new())),
event_tx: e_tx,
event_rx: Arc::new(e_rx),
model: Arc::new(Mutex::new(model)),
}
}
pub fn run(&mut self) {
self.renderer.lock().unwrap().start();
let key_tx = self.event_tx.clone();
thread::spawn(move || start_key_listener(key_tx));
let tx = self.event_tx.clone();
tx.send(Event::Init).unwrap();
self.event_loop();
}
fn event_loop(&mut self) {
let rx = self.event_rx.clone();
while let Ok(ev) = rx.recv() {
match &ev {
Event::Quit => {
self.renderer.lock().unwrap().quit();
break;
}
_ => {
if let Ok(mut model) = self.model.lock() {
let (new_model, cmd) = model.update(&ev);
if let Some(new) = new_model {
let _ = std::mem::replace(&mut *model, new);
self.renderer.lock().unwrap().write(&model.view());
}
let tx = self.event_tx.clone();
thread::spawn(move || {
if let Some(cmd) = cmd {
let ev = cmd();
tx.send(ev).unwrap();
}
});
}
}
}
}
}
}
fn start_key_listener<E: Send + Debug>(event_tx: Sender<Event<E>>) {
let mut keyboard = KeyBoard::new();
while let Ok(key) = keyboard.next_key_timeout(Duration::from_secs(0)) {
event_tx.send(Event::Keyboard(key.clone())).unwrap();
}
}