use crate::*; use std::marker::PhantomData; //use std::sync::{Arc, Mutex, RwLock}; /// Rendering target pub trait Output { /// Current output area fn area (&self) -> E::Area; /// Mutable pointer to area fn area_mut (&mut self) -> &mut E::Area; /// Render widget in area fn place (&mut self, area: E::Area, content: &impl Content); #[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() } #[inline] fn wh (&self) -> E::Size { self.area().wh().into() } } pub trait Content: Send + Sync { fn content (&self) -> impl Content { () } fn layout (&self, area: E::Area) -> E::Area { self.content().layout(area) } fn render (&self, output: &mut E::Output) { output.place(self.layout(output.area()), &self.content()) } } /// The platonic ideal unit of [Content]: total emptiness at dead center. impl Content for () { fn layout (&self, area: E::Area) -> E::Area { let [x, y] = area.center(); [x, y, 0.into(), 0.into()].into() } fn render (&self, _: &mut E::Output) {} } impl> Content for &T { fn content (&self) -> impl Content { (*self).content() } fn layout (&self, area: E::Area) -> E::Area { (*self).layout(area) } fn render (&self, output: &mut E::Output) { (*self).render(output) } } impl> Content for Option { fn content (&self) -> impl Content { self.as_ref() .map(|content|content.content()) } fn layout (&self, area: E::Area) -> E::Area { self.as_ref() .map(|content|content.layout(area)) .unwrap_or([0.into(), 0.into(), 0.into(), 0.into(),].into()) } fn render (&self, output: &mut E::Output) { self.as_ref() .map(|content|content.render(output)); } } pub struct Thunk, F: Fn()->T + Send + Sync>(F, PhantomData); impl, F: Fn()->T + Send + Sync> Thunk { pub fn new (thunk: F) -> Self { Self(thunk, Default::default()) } } impl, F: Fn()->T + Send + Sync> Content for Thunk { fn content (&self) -> impl Content { (self.0)() } } #[macro_export] macro_rules! render { (($self:ident:$Struct:ty) => $content:expr) => { impl Content for $Struct { fn content (&$self) -> impl Content { Some($content) } } }; (|$self:ident:$Struct:ident $(< $($L:lifetime),* $($T:ident $(:$Trait:path)?),* >)?, $to:ident | $render:expr) => { impl <$($($L),*)? E: Engine, $($T$(:$Trait)?),*> Content for $Struct $(<$($L),* $($T),*>>)? { fn render (&$self, $to: &mut E::Output) { $render } } }; ($Engine:ty: ($self:ident:$Struct:ident $(<$( $($L:lifetime)? $($T:ident)? $(:$Trait:path)? ),+>)?) => $content:expr ) => { impl $(<$($($L)? $($T)? $(:$Trait)?),+>)? Content<$Engine> for $Struct $(<$($($L)? $($T)?),+>)? { fn content (&$self) -> impl Content<$Engine> { $content } } }; ($Engine:ty: |$self:ident : $Struct:ident $(<$( $($L:lifetime)? $($T:ident)? $(:$Trait:path)? ),+>)?, $to:ident| $render:expr ) => { impl $(<$($($L)? $($T)? $(:$Trait)?),+>)? Content<$Engine> for $Struct $(<$($($L)? $($T)?),+>)? { fn render (&$self, $to: &mut <$Engine as Engine>::Output) { $render } } }; }