vtui_core/
runtime.rs

1use std::time::{Duration, Instant};
2
3use ratatui::prelude::Backend;
4
5use crate::{
6    canvas::Canvas, component::Component, context::Context, driver::Driver, error::RuntimeError,
7    transport::EventSource,
8};
9
10pub struct Runtime {
11    root: Component,
12    context: Context,
13}
14
15impl Runtime {
16    pub fn new(root: Component) -> Self {
17        let context = Context::default();
18        Self { root, context }
19    }
20
21    pub fn draw<D>(&self, driver: &mut D) -> Result<(), RuntimeError>
22    where
23        D: Driver,
24        RuntimeError: From<<D::Backend as Backend>::Error>,
25    {
26        let terminal = driver.terminal();
27        terminal.draw(|f| {
28            let mut canvas = Canvas::new(f.area(), f.buffer_mut());
29            self.root.render(&mut canvas);
30        })?;
31        Ok(())
32    }
33
34    pub fn update(&mut self, source: &EventSource) {
35        let deadline = Instant::now() + Duration::from_millis(16);
36        let msg = source.recv();
37
38        self.root.update(&msg, &mut self.context);
39
40        while Instant::now() < deadline {
41            let msg = source.recv_timeout(deadline - Instant::now());
42            if let Some(msg) = msg {
43                self.root.update(&msg, &mut self.context);
44            }
45        }
46    }
47
48    pub fn should_exit(&self) -> bool {
49        self.context.shutdown_requested
50    }
51}