use crate::*; #[macro_export] macro_rules! render { (|$self:ident:$Struct:ident$(<$($L:lifetime),*E$(,$T:ident$(:$U:path)?)*$(,)?>)?|$cb:expr) => { impl Render for $Struct $(<$($L,)* E, $($T),*>)? { fn min_size (&$self, to: ::Size) -> Perhaps<::Size> { $cb.min_size(to) } fn render (&$self, to: &mut ::Output) -> Usually<()> { $cb.render(to) } } }; (<$E:ty>|$self:ident:$Struct:ident$(< $($($L:lifetime),+)? $($($T:ident$(:$U:path)?),+)? >)?|$cb:expr) => { impl $(< $($($L),+)? $($($T$(:$U)?),+)? >)? Render<$E> for $Struct $(< $($($L),+)? $($($T),+)? >)? { fn min_size (&$self, to: <$E as Engine>::Size) -> Perhaps<<$E as Engine>::Size> { $cb.min_size(to) } fn render (&$self, to: &mut <$E as Engine>::Output) -> Usually<()> { $cb.render(to) } } } } /// 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 render_in (&mut self, area: E::Area, widget: &dyn Render) -> Usually<()>; } /// Cast to dynamic pointer pub fn widget > (w: &T) -> &dyn Render { w as &dyn Render } /// A renderable component pub trait Render: Send + Sync { /// Minimum size to use fn min_size (&self, to: E::Size) -> Perhaps { Ok(Some(to)) } /// Draw to output render target fn render (&self, to: &mut E::Output) -> Usually<()>; } impl> Render for &R { fn min_size (&self, to: E::Size) -> Perhaps { (*self).min_size(to) } fn render (&self, to: &mut E::Output) -> Usually<()> { (*self).render(to) } } impl Render for &dyn Render { fn min_size (&self, to: E::Size) -> Perhaps { (*self).min_size(to) } fn render (&self, to: &mut E::Output) -> Usually<()> { (*self).render(to) } } //impl Render for &mut dyn Render { //fn min_size (&self, to: E::Size) -> Perhaps { //(*self).min_size(to) //} //fn render (&self, to: &mut E::Output) -> Usually<()> { //(*self).render(to) //} //} impl Render for Box + '_> { fn min_size (&self, to: E::Size) -> Perhaps { (**self).min_size(to) } fn render (&self, to: &mut E::Output) -> Usually<()> { (**self).render(to) } } impl> Render for Arc { fn min_size (&self, to: E::Size) -> Perhaps { self.as_ref().min_size(to) } fn render (&self, to: &mut E::Output) -> Usually<()> { self.as_ref().render(to) } } impl> Render for Mutex { fn min_size (&self, to: E::Size) -> Perhaps { self.lock().unwrap().min_size(to) } fn render (&self, to: &mut E::Output) -> Usually<()> { self.lock().unwrap().render(to) } } impl> Render for RwLock { fn min_size (&self, to: E::Size) -> Perhaps { self.read().unwrap().min_size(to) } fn render (&self, to: &mut E::Output) -> Usually<()> { self.read().unwrap().render(to) } } impl> Render for Option { fn min_size (&self, to: E::Size) -> Perhaps { 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(())) } } /// A custom [Render] defined by passing layout and render closures in place. pub struct Widget< E: Engine, L: Send + Sync + Fn(E::Size)->Perhaps, R: Send + Sync + Fn(&mut E::Output)->Usually<()> >(L, R, PhantomData); impl< E: Engine, L: Send + Sync + Fn(E::Size)->Perhaps, R: Send + Sync + Fn(&mut E::Output)->Usually<()> > Widget { pub fn new (layout: L, render: R) -> Self { Self(layout, render, Default::default()) } } impl< E: Engine, L: Send + Sync + Fn(E::Size)->Perhaps, R: Send + Sync + Fn(&mut E::Output)->Usually<()> > Render for Widget { fn min_size (&self, to: E::Size) -> Perhaps { self.0(to) } fn render (&self, to: &mut E::Output) -> Usually<()> { self.1(to) } }