use crate::*; /// Output target. /// /// ``` /// use tengri::*; /// struct TestOut { w: u16, h: u16 }; /// impl Wide for TestOut {} /// impl Tall for TestOut {} /// impl Xy for TestOut { fn x (&self) -> u16 { 0 } fn y (&self) -> u16 { 0 } } /// impl Screen for TestOut { /// type Unit = u16; /// fn show > (&mut self, _: D) -> Drawn { /// println!("placed"); /// Ok(None) /// } /// } /// /// impl_draw!(|self: String, to: TestOut|{ /// to.w = self.len() as u16; /// Ok(None) /// }); /// ``` pub trait Screen: Xy + Wh + Send + Sync + Sized { type Unit: Coord; /// Render drawable in subarea specified by `area` fn show (&mut self, content: impl Draw) -> Perhaps>; /// Get current clipping area fn area (&self) -> XYWH; /// Set clipping area fn clip ( &mut self, area: impl Into>>, draw: impl FnOnce(&mut Self)->T ) -> T; } /// Implement the [Draw] trait for a particular drawable and [Screen]. /// /// ``` /// use tengri::*; /// struct MyDrawable; /// impl_draw!(|self: MyDrawable, to: Tui|{ /// todo!("your draw logic") /// }); /// ``` #[macro_export] macro_rules! impl_draw ( ($(<$($T:ident: $Trait:path,)+>)?| $self:ident:$Self:path, $to:ident:$To:ty |$draw:block)=>{ impl$(<$($T:$Trait),+>)? Draw<$To> for $Self { fn draw ($self, $to: &mut $To) -> Perhaps::Unit>> $draw } }; ($(<$($T:ident: $Trait:path,)+>)?| $self:ident:$Self:ty, $to:ident:$To:ty |$draw:block)=>{ impl$(<$($T:$Trait),+>)? Draw<$To> for $Self { fn draw ($self, $to: &mut $To) -> Perhaps::Unit>> $draw } } ); /// Drawable that supports dynamic dispatch. /// /// Drawables are composable, e.g. the [when] and [either] conditionals /// or the layout constraints. /// /// Drawables are consumable, i.e. the [Draw::draw] method receives an /// owned `self` and does not return it, consuming the drawable. /// /// To draw a thing multiple times, instead of explicitly constructing it /// every time, implement the [View] trait instead, which will construct /// a [Draw]able. /// /// ``` /// use tengri::*; /// struct MyWidget(bool); /// impl Draw for MyWidget { /// fn draw (self, to: &mut Tui) -> Perhaps> { /// todo!("your draw logic") /// } /// } /// ``` pub trait Draw { fn draw (self, to: &mut S) -> Drawn; fn layout (&self, area: XYWH) -> Drawn { Ok(Some(area)) } } pub type Drawn = Perhaps>; impl Draw for () { fn draw (self, _: &mut S) -> Drawn { Ok(None) } } impl_draw!(,>|self: Option, to: S|{ self.map(|it|it.draw(to)).transpose().map(Option::unwrap_or_default) }); //impl> Draw for RwLock { //fn draw (self, __: &mut S) -> Drawn { //todo!() //} //} //impl> Draw for Arc { //fn draw (self, __: &mut T) -> Perhaps> { //todo!() //} //} /// Emit a [Draw]able. /// /// Speculative. How to avoid conflicts with [Draw] proper? pub trait View { fn view (&self) -> impl Draw; } impl View for () { fn view (&self) -> impl Draw { () } } impl> Draw for &V { fn draw (self, to: &mut T) -> Perhaps> { self.view().draw(to) } } features! { "draw": [ color, coord, iter, layout, lrtb, sizer, space, split, thunk, xywh ] }