wip: generic render

This commit is contained in:
🪞👃🪞 2024-09-03 00:57:32 +03:00
parent 7bd2a70e85
commit fcd2d16de9
12 changed files with 314 additions and 351 deletions

View file

@ -55,11 +55,13 @@ submod! {
render
render_axis
render_border
render_buffer
render_collect
render_fill
render_layered
render_split
render_theme
render_tui
render_tui_fill
render_tui_theme
time_base
time_note
time_tick
@ -80,59 +82,39 @@ submod! {
/// Standard result type.
pub type Usually<T> = Result<T, Box<dyn Error>>;
/// Standard optional result type.
pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
/// A UI component.
pub trait Component: Render + Handle + Sync {
pub trait Component<T, U>: Render<T, U> + Handle + Sync {
/// Perform type erasure for collecting heterogeneous components.
fn boxed (self) -> Box<dyn Component> where Self: Sized + 'static {
fn boxed (self) -> Box<dyn Component<T, U>> where Self: Sized + 'static {
Box::new(self)
}
}
impl<T: Render + Handle + Sync> Component for T {}
impl<C, T, U> Component<T, U> for C where C: Render<T, U> + Handle + Sync {}
/// Marker trait for [Component]s that can [Exit]
pub trait ExitableComponent: Exit + Component {
pub trait ExitableComponent<T, U>: Exit + Component<T, U> {
/// Perform type erasure for collecting heterogeneous components.
fn boxed (self) -> Box<dyn ExitableComponent> where Self: Sized + 'static {
fn boxed (self) -> Box<dyn ExitableComponent<T, U>> where Self: Sized + 'static {
Box::new(self)
}
}
impl<T: Exit + Component> ExitableComponent for T {}
impl<E: Exit + Component<T, U>, T, U> ExitableComponent<T, U> for E {}
/// Run the main loop.
pub fn run <T> (state: Arc<RwLock<T>>) -> Usually<Arc<RwLock<T>>>
where T: Render + Handle + Send + Sync + Sized + 'static
pub fn run <'a, R> (state: Arc<RwLock<R>>) -> Usually<Arc<RwLock<R>>>
where R: Render<TuiOutput<'a>, Rect> + Handle + Sized + 'static
{
let exited = Arc::new(AtomicBool::new(false));
let _input_thread = input_thread(&exited, &state);
terminal_setup()?;
panic_hook_setup();
let main_thread = render_thread(&exited, &state)?;
let main_thread = tui_render_thread(&exited, &state)?;
main_thread.join().expect("main thread failed");
terminal_teardown()?;
Ok(state)
}
/// Set up panic hook
pub fn panic_hook_setup () {
let better_panic_handler = Settings::auto().verbosity(Verbosity::Full).create_panic_handler();
std::panic::set_hook(Box::new(move |info: &std::panic::PanicInfo|{
stdout().execute(LeaveAlternateScreen).unwrap();
disable_raw_mode().unwrap();
better_panic_handler(info);
}));
}
/// Set up terminal
pub fn terminal_setup () -> Usually<()> {
stdout().execute(EnterAlternateScreen)?;
enable_raw_mode()?;
Ok(())
}
/// Cleanup
pub fn terminal_teardown () -> Usually<()> {
stdout().execute(LeaveAlternateScreen)?;
disable_raw_mode()?;
Ok(())
}