use crate::{Event, Result, TerminalWindow, Window};
use std::time::{Duration, Instant};
pub struct App<S> {
window: TerminalWindow,
state: S,
tick_rate: Option<Duration>,
}
impl<S> App<S> {
pub fn new(initial_state: S) -> Result<Self> {
let mut window = TerminalWindow::new()?;
window.set_auto_flush(false);
Ok(App {
window,
state: initial_state,
tick_rate: None, })
}
pub fn with_tick_rate(mut self, tick_rate: Duration) -> Self {
self.tick_rate = Some(tick_rate);
self
}
pub fn run<U, D>(&mut self, mut update: U, mut draw: D) -> Result<()>
where
U: FnMut(&mut S, Event) -> bool, D: FnMut(&mut S, &mut dyn Window) -> Result<()>,
{
let mut last_tick = Instant::now();
loop {
if let Some(event) = self.window.poll_input()?
&& !update(&mut self.state, event)
{
break; }
if let Some(tick_rate) = self.tick_rate
&& last_tick.elapsed() >= tick_rate
{
if !update(&mut self.state, Event::Tick) {
break; }
last_tick = Instant::now();
}
self.window.clear_screen()?;
draw(&mut self.state, &mut self.window)?;
self.window.flush()?;
std::thread::sleep(Duration::from_millis(1));
}
Ok(())
}
}