the wild Layout trait appears

This commit is contained in:
🪞👃🪞 2024-12-31 00:38:47 +01:00
parent 7c652135ad
commit d37bd3e0c5
7 changed files with 576 additions and 595 deletions

View file

@ -46,13 +46,13 @@ pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
fn area_mut (&mut self) -> &mut [u16;4] {
&mut self.0
}
fn render_in (&mut self, _: [u16;4], _: &dyn Render<TestEngine>) -> Usually<()> {
fn render_in (&mut self, _: [u16;4], _: &impl Render<TestEngine>) -> Usually<()> {
Ok(())
}
}
impl Render<TestEngine> for String {
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
Ok(Some([self.len() as u16, 1]))
fn render (&self, to: &mut TestOutput) {
to.area_mut().set_w(self.len() as u16);
}
}
Ok(())
@ -62,9 +62,9 @@ pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
use crate::tui::*;
use std::sync::{Arc, RwLock};
struct TestComponent(String);
impl Content<Tui> for TestComponent {
fn content (&self) -> Option<impl Render<Tui>> {
Some(&self.0)
impl Layout<Tui> for TestComponent {
fn layout (&self) -> Option<impl Render<Tui>> {
Some(self.0.as_str())
}
}
impl Handle<Tui> for TestComponent {

View file

@ -7,158 +7,212 @@ pub trait Output<E: Engine> {
fn area (&self) -> E::Area;
/// Mutable pointer to area
fn area_mut (&mut self) -> &mut E::Area;
/// Render widget in area
///// Render widget in area
fn render_in (&mut self, area: E::Area, widget: &impl Render<E>) -> Usually<()>;
#[inline] fn x (&self) -> E::Unit { self.area().x() }
#[inline] fn y (&self) -> E::Unit { self.area().y() }
#[inline] fn w (&self) -> E::Unit { self.area().w() }
#[inline] fn h (&self) -> E::Unit { self.area().h() }
}
/// Something that can be represented by a renderable component.
pub trait Content<E: Engine>: Send + Sync {
fn content (&self) -> Option<impl Render<E>>;
}
impl<E: Engine, C: Content<E>> Content<E> for &C {
fn content (&self) -> Option<impl Render<E>> {
(*self).content()
pub trait Layout<E: Engine>: Send + Sync {
fn layout (&self) -> Option<impl Render<E>> {
None::<()>
}
}
/// Something that writes to an [Output].
impl<E: Engine> Layout<E> for () {}
impl<E: Engine, L: Layout<E>> Layout<E> for &L {}
pub trait Render<E: Engine>: Send + Sync {
/// Minimum size to use
fn min_size (&self, _: E::Size) -> Perhaps<E::Size> {
Ok(None)
}
/// Draw to output render target
fn render (&self, _: &mut E::Output) -> Usually<()> {
Ok(())
}
fn render (&self, _: &mut E::Output);
}
impl<E: Engine> Render<E> for &dyn Render<E> {
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> { (*self).min_size(to) }
fn render (&self, to: &mut E::Output) -> Usually<()> { (*self).render(to) }
}
impl<E: Engine, R: Render<E>> Render<E> for &R {
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> { (*self).min_size(to) }
fn render (&self, to: &mut E::Output) -> Usually<()> { (*self).render(to) }
}
impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
if let Some(content) = self {
content.min_size(to)
} else {
Ok(None)
impl<E: Engine, L: Layout<E>> Render<E> for L {
fn render (&self, to: &mut E::Output) {
if let Some(content) = self.layout() {
content.render(to)
}
}
fn render (&self, to: &mut E::Output) -> Usually<()> {
if let Some(content) = self {
content.render(to)?;
}
Ok(())
}
}
/// Define custom content for a struct.
///
/// This code wires the `Content` and `Render` traits together,
/// since the only way to have the cake and eat it too is by
/// implementing both traits for a given renderable.
#[macro_export] macro_rules! render {
//impl<E: Engine, L: Layout<E>> Layout<E> for &L {}
// Implement from [Content] for all [Engine]s
(|$self:ident:$Struct:ident$(<$($L:lifetime),*E$(,$T:ident$(:$U:path)?)*$(,)?>)?|$cb:expr) => {
impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Content<E> for $Struct $(<$($L,)* E, $($T),*>)? {
fn content (&$self) -> Option<impl Render<$E>> { Some($cb) }
}
impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Render<E> for $Struct $(<$($L,)* E, $($T),*>)? {
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
self.content().unwrap().min_size(to)
}
fn render (&self, to: &mut E::Output) -> Usually<()> {
self.content().unwrap().render(to)
}
}
};
///// Something that can be represented by a renderable component.
//pub trait Content<E: Engine>: Send + Sync {
//fn content (&self) -> Option<impl Render<E>>;
//}
//impl<E: Engine, C: Content<E>> Content<E> for &C {
//fn content (&self) -> Option<impl Render<E>> {
//(*self).content()
//}
//}
// Implement from [min_size] and [render] callbacks for all engines
($Struct:ident$(<$($L:lifetime),*E$(,$T:ident$(:$U:path)?)*$(,)?>)?
|$self1:ident, $to1:ident|$min_size:expr,
|$self2:ident, $to2:ident|$render:expr) =>
{
impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Content<E> for $Struct $(<$($L,)* E, $($T),*>)? {
fn content (&self) -> Option<impl Render<E>> { Some(self) }
}
impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Render<E> for $Struct $(<$($L,)* E, $($T),*>)? {
fn min_size (&$self1, $to1: E::Size) -> Perhaps<E::Size> { $min_size }
fn render (&$self2, $to2: &mut E::Output) -> Usually<()> { $render }
}
};
///// Something that writes to an [Output].
//pub trait Render<E: Engine>: Send + Sync {
///// Minimum size to use
//fn min_size (&self, _: E::Size) -> Perhaps<E::Size> {
//Ok(None)
//}
///// Draw to output render target
//fn render (&self, _: &mut E::Output) -> Usually<()> {
//Ok(())
//}
//}
//impl<E: Engine> Render<E> for &dyn Render<E> {
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> { (*self).min_size(to) }
//fn render (&self, to: &mut E::Output) -> Usually<()> { (*self).render(to) }
//}
//impl<E: Engine, R: Render<E>> Render<E> for &R {
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> { (*self).min_size(to) }
//fn render (&self, to: &mut E::Output) -> Usually<()> { (*self).render(to) }
//}
//impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
//if let Some(content) = self {
//content.min_size(to)
//} else {
//Ok(None)
//}
//}
//fn render (&self, to: &mut E::Output) -> Usually<()> {
//if let Some(content) = self {
//content.render(to)?;
//}
//Ok(())
//}
//}
// Implement from [Content] for a particular [Engine]
(<$E:ty>|$self:ident:$Struct:ident$(<
$($($L:lifetime),+)?
$($($T:ident$(:$U:path)?),+)?
>)?|$cb:expr) => {
impl $(<
$($($L),+)?
$($($T$(:$U)?),+)?
>)? Content<$E> for $Struct $(<
$($($L),+)?
$($($T),+)?
>)? {
fn content (&$self) -> Option<impl Render<$E>> {
Some($cb)
}
}
impl $(<
$($($L),+)?
$($($T$(:$U)?),+)?
>)? Render<$E> for $Struct $(<
$($($L),+)?
$($($T),+)?
>)? {
fn min_size (&self, to: <$E as Engine>::Size) -> Perhaps<<$E as Engine>::Size> {
self.content().map(|content|content.min_size(to)).unwrap_or(Ok(None))
}
fn render (&self, to: &mut <$E as Engine>::Output) -> Usually<()> {
self.content().map(|content|content.render(to)).unwrap_or(Ok(()))
}
}
};
///// Define custom content for a struct.
/////
///// This code wires the `Content` and `Render` traits together,
///// since the only way to have the cake and eat it too is by
///// implementing both traits for a given renderable.
//#[macro_export] macro_rules! render {
// Implement from [min_size] and [render] callbacks for a particular [Engine]
(<$E:ty>($self:ident:$Struct:ident$(<$($L:lifetime),*$(,$T:ident$(:$U:path)?)*$(,)?>)?)
|$to1:ident|$min_size:expr, |$to2:ident|$render:expr) =>
{
impl $(<
$($L),* $($($T$(:$U)?),+)?
>)? Content<$E> for $Struct $(<
$($L),* $($($T),+)?
>)? {
fn content (&self) -> Option<impl Render<$E>> { Some(self) }
}
impl $(<
$($L),* $($($T$(:$U)?),+)?
>)? Render<$E> for $Struct $(<
$($L),* $($($T),+)?
>)? {
fn min_size (&$self, $to1: <$E as Engine>::Size) -> Perhaps<<$E as Engine>::Size> {
$min_size
}
fn render (&$self, $to2: &mut <$E as Engine>::Output) -> Usually<()> {
$render
}
}
}
//// Implement from [Content] for all [Engine]s
//(|$self:ident:$Struct:ident$(<$($L:lifetime),*E$(,$T:ident$(:$U:path)?)*$(,)?>)?|$cb:expr) => {
//impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Content<E> for $Struct $(<$($L,)* E, $($T),*>)? {
//fn content (&$self) -> Option<impl Render<$E>> { Some($cb) }
//}
//impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Render<E> for $Struct $(<$($L,)* E, $($T),*>)? {
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
//self.content().unwrap().min_size(to)
//}
//fn render (&self, to: &mut E::Output) -> Usually<()> {
//self.content().unwrap().render(to)
//}
//}
//};
}
//// Implement from [min_size] and [render] callbacks for all engines
//($Struct:ident$(<$($L:lifetime),*E$(,$T:ident$(:$U:path)?)*$(,)?>)?
//|$self1:ident, $to1:ident|$min_size:expr,
//|$self2:ident, $to2:ident|$render:expr) =>
//{
//impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Content<E> for $Struct $(<$($L,)* E, $($T),*>)? {
//fn content (&self) -> Option<impl Render<E>> { Some(self) }
//}
//impl<E: Engine, $($($L),*$($T $(: $U)?),*)?> Render<E> for $Struct $(<$($L,)* E, $($T),*>)? {
//fn min_size (&$self1, $to1: E::Size) -> Perhaps<E::Size> { $min_size }
//fn render (&$self2, $to2: &mut E::Output) -> Usually<()> { $render }
//}
//};
//impl<E: Engine, C: Content<E>> Content<E> for &mut C {}
//impl<E: Engine, C: Content<E>> Content<E> for Option<C> {}
//impl<E: Engine, C: Content<E>> Content<E> for Arc<C> {}
//impl<E: Engine, C: Content<E>> Content<E> for Mutex<C> {}
//impl<E: Engine, C: Content<E>> Content<E> for RwLock<C> {}
//// Implement from [Content] for a particular [Engine]
//(<$E:ty>|$self:ident:$Struct:ident$(<
//$($($L:lifetime),+)?
//$($($T:ident$(:$U:path)?),+)?
//>)?|$cb:expr) => {
//impl $(<
//$($($L),+)?
//$($($T$(:$U)?),+)?
//>)? Content<$E> for $Struct $(<
//$($($L),+)?
//$($($T),+)?
//>)? {
//fn content (&$self) -> Option<impl Render<$E>> {
//Some($cb)
//}
//}
//impl $(<
//$($($L),+)?
//$($($T$(:$U)?),+)?
//>)? Render<$E> for $Struct $(<
//$($($L),+)?
//$($($T),+)?
//>)? {
//fn min_size (&self, to: <$E as Engine>::Size) -> Perhaps<<$E as Engine>::Size> {
//self.content().map(|content|content.min_size(to)).unwrap_or(Ok(None))
//}
//fn render (&self, to: &mut <$E as Engine>::Output) -> Usually<()> {
//self.content().map(|content|content.render(to)).unwrap_or(Ok(()))
//}
//}
//};
//impl<E: Engine, C: Content<E>> Render<E> for C {}
//// Implement from [min_size] and [render] callbacks for a particular [Engine]
//(<$E:ty>($self:ident:$Struct:ident$(<$($L:lifetime),*$(,$T:ident$(:$U:path)?)*$(,)?>)?)
//|$to1:ident|$min_size:expr, |$to2:ident|$render:expr) =>
//{
//impl $(<
//$($L),* $($($T$(:$U)?),+)?
//>)? Content<$E> for $Struct $(<
//$($L),* $($($T),+)?
//>)? {
//fn content (&self) -> Option<impl Render<$E>> { Some(self) }
//}
//impl $(<
//$($L),* $($($T$(:$U)?),+)?
//>)? Render<$E> for $Struct $(<
//$($L),* $($($T),+)?
//>)? {
//fn min_size (&$self, $to1: <$E as Engine>::Size) -> Perhaps<<$E as Engine>::Size> {
//$min_size
//}
//fn render (&$self, $to2: &mut <$E as Engine>::Output) -> Usually<()> {
//$render
//}
//}
//}
//}
////impl<E: Engine, C: Content<E>> Content<E> for &mut C {}
////impl<E: Engine, C: Content<E>> Content<E> for Option<C> {}
////impl<E: Engine, C: Content<E>> Content<E> for Arc<C> {}
////impl<E: Engine, C: Content<E>> Content<E> for Mutex<C> {}
////impl<E: Engine, C: Content<E>> Content<E> for RwLock<C> {}
////impl<E: Engine, C: Content<E>> Render<E> for C {}
////impl<E: Engine, C: Content<E>> Render<E> for C {
/////// Minimum size to use
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
////self.content().map(|content|content.min_size(to))
////.unwrap_or(Ok(None))
////}
/////// Draw to output render target
////fn render (&self, to: &mut E::Output) -> Usually<()> {
////self.content().map(|content|content.render(to))
////.unwrap_or(Ok(()))
////}
////}
//[>***
//impl<E: Engine, R: Render<E> + Send + Sync> Content<E> for R {}
////impl<E: Engine, R: Render<E>> Content<E> for R {
////fn content (&self) -> Option<impl Render<E>> {
////Some(self)
////}
////}
///// All implementors of [Content] can be [Render]ed.
//impl<E: Engine, C: Content<E>> Render<E> for C {
///// Minimum size to use
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
@ -172,65 +226,20 @@ impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
//}
//}
/****
////impl<E: Engine, C: Content<E>> Content<E> for &C {
////fn content (&self) -> Option<impl Render<E>> {
////Some(self)
////}
////}
////impl<E: Engine, C: Content<E>> Content<E> for Option<C> {
////fn content (&self) -> Option<impl Render<E>> {
////Some(self)
////}
////}
impl<E: Engine, R: Render<E> + Send + Sync> Content<E> for R {}
//impl<E: Engine, R: Render<E>> Content<E> for R {
//fn content (&self) -> Option<impl Render<E>> {
//Some(self)
//}
//}
/// All implementors of [Content] can be [Render]ed.
impl<E: Engine, C: Content<E>> Render<E> for C {
/// Minimum size to use
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
self.content().map(|content|content.min_size(to))
.unwrap_or(Ok(None))
}
/// Draw to output render target
fn render (&self, to: &mut E::Output) -> Usually<()> {
self.content().map(|content|content.render(to))
.unwrap_or(Ok(()))
}
}
//impl<E: Engine, C: Content<E>> Content<E> for &C {
//fn content (&self) -> Option<impl Render<E>> {
//Some(self)
//}
//}
//impl<E: Engine, C: Content<E>> Content<E> for Option<C> {
//fn content (&self) -> Option<impl Render<E>> {
//Some(self)
//}
//}
impl<E: Engine, R: Render<E>> Render<E> for &R {
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
(*self).min_size(to)
}
fn render (&self, to: &mut E::Output) -> Usually<()> {
(*self).render(to)
}
}
impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
self.map(|content|content.min_size(to))
.unwrap_or(Ok(None))
}
fn render (&self, to: &mut E::Output) -> Usually<()> {
self.map(|content|content.render(to))
.unwrap_or(Ok(()))
}
}
//impl<E: Engine> Render<E> for &dyn Render<E> {
//impl<E: Engine, R: Render<E>> Render<E> for &R {
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
//(*self).min_size(to)
//}
@ -239,124 +248,144 @@ impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
//}
//}
//impl<E: Engine> Render<E> for &mut dyn Render<E> {
//impl<E: Engine, R: Render<E>> Render<E> for Option<R> {
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
//(*self).min_size(to)
//self.map(|content|content.min_size(to))
//.unwrap_or(Ok(None))
//}
//fn render (&self, to: &mut E::Output) -> Usually<()> {
//(*self).render(to)
//self.map(|content|content.render(to))
//.unwrap_or(Ok(()))
//}
//}
//impl<E: Engine> Render<E> for Box<dyn Render<E> + '_> {
////impl<E: Engine> Render<E> for &dyn Render<E> {
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
////(*self).min_size(to)
////}
////fn render (&self, to: &mut E::Output) -> Usually<()> {
////(*self).render(to)
////}
////}
////impl<E: Engine> Render<E> for &mut dyn Render<E> {
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
////(*self).min_size(to)
////}
////fn render (&self, to: &mut E::Output) -> Usually<()> {
////(*self).render(to)
////}
////}
////impl<E: Engine> Render<E> for Box<dyn Render<E> + '_> {
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
////(**self).min_size(to)
////}
////fn render (&self, to: &mut E::Output) -> Usually<()> {
////(**self).render(to)
////}
////}
////impl<E: Engine, W: Render<E>> Render<E> for Arc<W> {
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
////self.as_ref().min_size(to)
////}
////fn render (&self, to: &mut E::Output) -> Usually<()> {
////self.as_ref().render(to)
////}
////}
////impl<E: Engine, W: Render<E>> Render<E> for Mutex<W> {
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
////self.lock().unwrap().min_size(to)
////}
////fn render (&self, to: &mut E::Output) -> Usually<()> {
////self.lock().unwrap().render(to)
////}
////}
////impl<E: Engine, W: Render<E>> Render<E> for RwLock<W> {
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
////self.read().unwrap().min_size(to)
////}
////fn render (&self, to: &mut E::Output) -> Usually<()> {
////self.read().unwrap().render(to)
////}
////}
////impl<E: Engine, W: Render<E>> Render<E> for Option<W> {
////fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
////Ok(self.as_ref().map(|widget|widget.min_size(to)).transpose()?.flatten())
////}
////fn render (&self, to: &mut E::Output) -> Usually<()> {
////self.as_ref().map(|widget|widget.render(to)).unwrap_or(Ok(()))
////}
////}
///// Cast to dynamic pointer
//pub fn widget <E, T> (w: &T) -> &dyn Render<E>
//where E: Engine, T: Render<E>
//{
//w as &dyn Render<E>
//}
///// Ad-hoc widget with custom rendering.
//pub fn render <E, F> (render: F) -> impl Render<E>
//where E: Engine, F: Fn(&mut E::Output)->Usually<()>+Send+Sync
//{
//Widget::new(|_|Ok(Some([0.into(),0.into()].into())), render)
//}
///// A custom [Render] defined by passing layout and render closures in place.
//pub struct Widget<
//E: Engine,
//L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
//R: Send + Sync + Fn(&mut E::Output)->Usually<()>
//>(L, R, PhantomData<E>);
//impl<
//E: Engine,
//L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
//R: Send + Sync + Fn(&mut E::Output)->Usually<()>
//> Widget<E, L, R> {
//pub fn new (layout: L, render: R) -> Self {
//Self(layout, render, Default::default())
//}
//}
//impl<
//E: Engine,
//L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
//R: Send + Sync + Fn(&mut E::Output)->Usually<()>
//> Render<E> for Widget<E, L, R> {
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
//(**self).min_size(to)
//self.0(to)
//}
//fn render (&self, to: &mut E::Output) -> Usually<()> {
//(**self).render(to)
//self.1(to)
//}
//}
//impl<E: Engine, W: Render<E>> Render<E> for Arc<W> {
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
//self.as_ref().min_size(to)
///// Has static methods for conditional rendering,
///// in unary and binary forms.
//pub struct Cond;
//impl Cond {
///// Render `item` when `cond` is true.
//pub fn when <E: Engine, A: Render<E>> (cond: bool, item: A) -> When<E, A> {
//When(cond, item, Default::default())
//}
//fn render (&self, to: &mut E::Output) -> Usually<()> {
//self.as_ref().render(to)
///// Render `item` if `cond` is true, otherwise render `other`.
//pub fn either <E: Engine, A: Render<E>, B: Render<E>> (cond: bool, item: A, other: B) -> Either<E, A, B> {
//Either(cond, item, other, Default::default())
//}
//}
//impl<E: Engine, W: Render<E>> Render<E> for Mutex<W> {
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
//self.lock().unwrap().min_size(to)
//}
//fn render (&self, to: &mut E::Output) -> Usually<()> {
//self.lock().unwrap().render(to)
//}
//}
///// Renders `self.1` when `self.0` is true.
//pub struct When<E: Engine, A: Render<E>>(bool, A, PhantomData<E>);
//impl<E: Engine, W: Render<E>> Render<E> for RwLock<W> {
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
//self.read().unwrap().min_size(to)
//}
//fn render (&self, to: &mut E::Output) -> Usually<()> {
//self.read().unwrap().render(to)
//}
//}
//impl<E: Engine, W: Render<E>> Render<E> for Option<W> {
//fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
//Ok(self.as_ref().map(|widget|widget.min_size(to)).transpose()?.flatten())
//}
//fn render (&self, to: &mut E::Output) -> Usually<()> {
//self.as_ref().map(|widget|widget.render(to)).unwrap_or(Ok(()))
//}
//}
/// Cast to dynamic pointer
pub fn widget <E, T> (w: &T) -> &dyn Render<E>
where E: Engine, T: Render<E>
{
w as &dyn Render<E>
}
/// Ad-hoc widget with custom rendering.
pub fn render <E, F> (render: F) -> impl Render<E>
where E: Engine, F: Fn(&mut E::Output)->Usually<()>+Send+Sync
{
Widget::new(|_|Ok(Some([0.into(),0.into()].into())), render)
}
/// A custom [Render] defined by passing layout and render closures in place.
pub struct Widget<
E: Engine,
L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
R: Send + Sync + Fn(&mut E::Output)->Usually<()>
>(L, R, PhantomData<E>);
impl<
E: Engine,
L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
R: Send + Sync + Fn(&mut E::Output)->Usually<()>
> Widget<E, L, R> {
pub fn new (layout: L, render: R) -> Self {
Self(layout, render, Default::default())
}
}
impl<
E: Engine,
L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
R: Send + Sync + Fn(&mut E::Output)->Usually<()>
> Render<E> for Widget<E, L, R> {
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
self.0(to)
}
fn render (&self, to: &mut E::Output) -> Usually<()> {
self.1(to)
}
}
/// Has static methods for conditional rendering,
/// in unary and binary forms.
pub struct Cond;
impl Cond {
/// Render `item` when `cond` is true.
pub fn when <E: Engine, A: Render<E>> (cond: bool, item: A) -> When<E, A> {
When(cond, item, Default::default())
}
/// Render `item` if `cond` is true, otherwise render `other`.
pub fn either <E: Engine, A: Render<E>, B: Render<E>> (cond: bool, item: A, other: B) -> Either<E, A, B> {
Either(cond, item, other, Default::default())
}
}
/// Renders `self.1` when `self.0` is true.
pub struct When<E: Engine, A: Render<E>>(bool, A, PhantomData<E>);
/// Renders `self.1` when `self.0` is true, otherwise renders `self.2`
pub struct Either<E: Engine, A: Render<E>, B: Render<E>>(bool, A, B, PhantomData<E>);
///// Renders `self.1` when `self.0` is true, otherwise renders `self.2`
//pub struct Either<E: Engine, A: Render<E>, B: Render<E>>(bool, A, B, PhantomData<E>);
**/
//**/

View file

@ -89,7 +89,7 @@ impl Tui {
}
}
pub trait TuiRun<R: Render<Tui> + Handle<Tui> + Sized + 'static> {
pub trait TuiRun<R: Layout<Tui> + Handle<Tui> + Sized + 'static> {
/// Run an app in the main loop.
fn run (&self, state: &Arc<RwLock<R>>) -> Usually<()>;
/// Spawn the input thread.
@ -98,7 +98,7 @@ pub trait TuiRun<R: Render<Tui> + Handle<Tui> + Sized + 'static> {
fn run_output (&self, state: &Arc<RwLock<R>>, sleep: Duration) -> JoinHandle<()>;
}
impl<T: Render<Tui> + Handle<Tui> + Sized + 'static> TuiRun<T> for Arc<RwLock<Tui>> {
impl<T: Layout<Tui> + Handle<Tui> + Sized + 'static> TuiRun<T> for Arc<RwLock<Tui>> {
fn run (&self, state: &Arc<RwLock<T>>) -> Usually<()> {
let _input_thread = self.run_input(state, Duration::from_millis(100));
self.write().unwrap().setup()?;
@ -151,7 +151,7 @@ impl<T: Render<Tui> + Handle<Tui> + Sized + 'static> TuiRun<T> for Arc<RwLock<Tu
buffer.reset();
}
let mut output = TuiOutput { buffer, area: [0, 0, width, height] };
state.render(&mut output).expect("render failed");
state.render(&mut output);
buffer = engine.write().unwrap().flip(output.buffer, size);
}
std::thread::sleep(sleep);
@ -257,7 +257,7 @@ impl Output<Tui> for TuiOutput {
#[inline] fn render_in (&mut self, area: [u16;4], widget: &impl Render<Tui>) -> Usually<()> {
let last = self.area();
*self.area_mut() = area;
widget.render(self)?;
widget.render(self);
*self.area_mut() = last;
Ok(())
}
@ -331,26 +331,14 @@ pub fn half_block (lower: bool, upper: bool) -> Option<char> {
//impl<T: Content<Tui>> Render<Tui> for T {}
impl Render<Tui> for &str {
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
// TODO: line breaks
Ok(Some([self.chars().count() as u16, 1]))
}
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
let [x, y, ..] = to.area();
//let [w, h] = self.min_size(to.area().wh())?.unwrap();
Ok(to.blit(&self, x, y, None))
fn render (&self, to: &mut TuiOutput) {
to.blit(self, to.area.x(), to.area.y(), None)
}
}
impl Render<Tui> for String {
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
// TODO: line breaks
Ok(Some([self.chars().count() as u16, 1]))
}
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
let [x, y, ..] = to.area();
//let [w, h] = self.min_size(to.area().wh())?.unwrap();
Ok(to.blit(&self, x, y, None))
fn render (&self, to: &mut TuiOutput) {
to.blit(self, to.area.x(), to.area.y(), None)
}
}