diff --git a/crates/tek_core/src/engine.rs b/crates/tek_core/src/engine.rs index c7fae556..8c76bec5 100644 --- a/crates/tek_core/src/engine.rs +++ b/crates/tek_core/src/engine.rs @@ -1,6 +1,4 @@ use crate::*; -use std::ops::{Add, Sub}; -use std::cmp::{Ord, Eq, PartialEq}; /// Entry point for main loop pub trait App { @@ -29,18 +27,6 @@ pub trait Engine: Sized { -> &mut Self; } -pub trait Number: Send + Sync + Copy - + Add - + Sub - + Ord + PartialEq + Eq {} - -impl Number for T where - T: Send + Sync + Copy - + Add - + Sub - + Ord + PartialEq + Eq -{} - submod! { collect component diff --git a/crates/tek_core/src/engine/collect.rs b/crates/tek_core/src/engine/collect.rs index 5ef3a398..f3a6067a 100644 --- a/crates/tek_core/src/engine/collect.rs +++ b/crates/tek_core/src/engine/collect.rs @@ -54,6 +54,13 @@ impl<'a, E: Engine> Collect<'a, E> for Collection<'a, E> { } } +pub struct Layers<'a, E: Engine>(pub &'a [&'a dyn Render]); + +// this actually works, except for the type inference +//pub struct Layers<'a, E: Engine + 'a, I: std::iter::IntoIterator>>( + //pub &'a I +//); + pub struct Layered<'a, E: Engine>(pub Collection<'a, E>); impl<'a, E: Engine> Layered<'a, E> { diff --git a/crates/tek_core/src/engine/render.rs b/crates/tek_core/src/engine/render.rs index e0c54f6a..497ec6cd 100644 --- a/crates/tek_core/src/engine/render.rs +++ b/crates/tek_core/src/engine/render.rs @@ -57,13 +57,15 @@ impl Render for RwLock where R: Render { } } -/// Boxed closures can be rendered. -/// -/// Rendering unboxed closures should also be possible; -/// but in practice implementing the trait for an unboxed -/// `Fn` closure causes an impl conflict. -impl<'a, E: Engine> Render for Box Perhaps + Send + Sync + 'a> { - fn render (&self, to: &mut E) -> Perhaps { - (*self)(to) - } -} +// FIXME: components are now 2 thunks (layout and render). +// maybe this resolves the conflict describe below? +///// Boxed closures can be rendered. +///// +///// Rendering unboxed closures should also be possible; +///// but in practice implementing the trait for an unboxed +///// `Fn` closure causes an impl conflict. +//impl<'a, E: Engine> Render for Box Perhaps + Send + Sync + 'a> { + //fn render (&self, to: &mut E) -> Perhaps { + //(*self)(to) + //} +//} diff --git a/crates/tek_core/src/lib.rs b/crates/tek_core/src/lib.rs index ea624cd7..55dcab69 100644 --- a/crates/tek_core/src/lib.rs +++ b/crates/tek_core/src/lib.rs @@ -15,6 +15,9 @@ pub(crate) use std::thread::{spawn, JoinHandle}; pub(crate) use std::time::Duration; pub(crate) use atomic_float::*; use better_panic::{Settings, Verbosity}; +use std::ops::{Add, Sub}; +use std::cmp::{Ord, Eq, PartialEq}; +use std::fmt::{Debug, Display}; /// Define and reexport submodules. #[macro_export] macro_rules! submod { @@ -40,3 +43,18 @@ pub type Usually = Result>; /// Standard optional result type. pub type Perhaps = Result, Box>; + +/// Standard numeric type. +pub trait Number: Send + Sync + Copy + + Add + + Sub + + Ord + PartialEq + Eq + + Debug + Display {} + +impl Number for T where + T: Send + Sync + Copy + + Add + + Sub + + Ord + PartialEq + Eq + + Debug + Display +{} diff --git a/crates/tek_core/src/space.rs b/crates/tek_core/src/space.rs index 76ab9281..2d21e87b 100644 --- a/crates/tek_core/src/space.rs +++ b/crates/tek_core/src/space.rs @@ -30,6 +30,13 @@ pub trait Area: Copy { fn lrtb (&self) -> [N;4] { [self.x(), self.x2(), self.y(), self.y2()] } + fn expect_min (&self, w: N, h: N) -> Usually<&Self> { + if self.w() < w || self.h() < h { + Err(format!("min {w}x{h}").into()) + } else { + Ok(self) + } + } } impl Area for (N, N, N, N) { diff --git a/crates/tek_core/src/tui.rs b/crates/tek_core/src/tui.rs index 0bd0c4eb..33f8196c 100644 --- a/crates/tek_core/src/tui.rs +++ b/crates/tek_core/src/tui.rs @@ -201,7 +201,14 @@ pub enum TuiEvent { /// Rendering unit struct to Ratatui returns zero-sized [Area] at render coordinates. impl Render for () { fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { - Ok(Some([to.area.x(), to.area.y(), 0, 0])) + self.layout(to.area()) + } +} + +/// Layout of unit struct in Ratatui is zero-sized [Area] at render coordinates. +impl Layout for () { + fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> { + Ok(Some([area.x(), area.y(), 0, 0])) } } diff --git a/crates/tek_core/src/tui/tui_border.rs b/crates/tek_core/src/tui/tui_border.rs index 987b3a1f..78c97859 100644 --- a/crates/tek_core/src/tui/tui_border.rs +++ b/crates/tek_core/src/tui/tui_border.rs @@ -86,8 +86,8 @@ macro_rules! border { ($($T:ty { $nw:literal $n:literal $ne:literal $w:literal $e:literal $sw:literal $s:literal $se:literal $($x:tt)* - }),+) => { - $(impl BorderStyle for $T { + }),+) => {$( + impl BorderStyle for $T { const NW: &'static str = $nw; const N: &'static str = $n; const NE: &'static str = $ne; @@ -97,8 +97,13 @@ macro_rules! border { const S: &'static str = $s; const SE: &'static str = $se; $($x)* - })+ - } + } + impl Render for $T { + fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { + self.draw(to) + } + } + )+} } pub struct Lozenge(pub Style); diff --git a/crates/tek_core/src/tui/tui_colors.rs b/crates/tek_core/src/tui/tui_colors.rs index 375aa4ba..467b9d8d 100644 --- a/crates/tek_core/src/tui/tui_colors.rs +++ b/crates/tek_core/src/tui/tui_colors.rs @@ -1,5 +1,36 @@ use crate::*; +impl Layout for &str { + fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> { + let [x, y, ..] = area; + // TODO: line breaks + Ok(Some([x, y, self.len() as u16, 1])) + } +} + +impl Render for &str { + fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { + let area = self.layout(to.area())?.unwrap(); + to.blit(&self, area.x(), area.y(), None)?; + Ok(Some(area)) + } +} + +pub struct Styled>(pub Option