diff --git a/src/widget.rs b/src/widget.rs index dd4859b..1ac044a 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -1,7 +1,7 @@ use async_trait::async_trait; use crate::widgets::{ - Background, Border, Either2, Either3, Float, JoinSegment, Layer, Padding, Resize, + Background, Border, Either2, Either3, Float, JoinSegment, Layer2, Padding, Resize, }; use crate::{Frame, Size, WidthDb}; @@ -67,12 +67,12 @@ pub trait WidgetExt: Sized { JoinSegment::new(self) } - fn below(self, above: W) -> Layer { - Layer::new(self, above) + fn below(self, above: W) -> Layer2 { + Layer2::new(self, above) } - fn above(self, below: W) -> Layer { - Layer::new(below, self) + fn above(self, below: W) -> Layer2 { + Layer2::new(below, self) } fn padding(self) -> Padding { diff --git a/src/widgets/layer.rs b/src/widgets/layer.rs index 366f2b5..b6f4916 100644 --- a/src/widgets/layer.rs +++ b/src/widgets/layer.rs @@ -2,26 +2,19 @@ use async_trait::async_trait; use crate::{AsyncWidget, Frame, Size, Widget, WidthDb}; -#[derive(Debug, Clone, Copy)] -pub struct Layer { - pub below: I1, - pub above: I2, +pub struct Layer { + layers: Vec, } -impl Layer { - pub fn new(below: I1, above: I2) -> Self { - Self { below, above } - } - - fn size(below: Size, above: Size) -> Size { - Size::new(below.width.max(above.width), below.height.max(above.height)) +impl Layer { + pub fn new(layers: Vec) -> Self { + Self { layers } } } -impl Widget for Layer +impl Widget for Layer where - I1: Widget, - I2: Widget, + I: Widget, { fn size( &self, @@ -29,23 +22,27 @@ where max_width: Option, max_height: Option, ) -> Result { - let bottom = self.below.size(widthdb, max_width, max_height)?; - let top = self.above.size(widthdb, max_width, max_height)?; - Ok(Self::size(bottom, top)) + let mut size = Size::ZERO; + for layer in &self.layers { + let lsize = layer.size(widthdb, max_width, max_height)?; + size.width = size.width.max(lsize.width); + size.height = size.height.max(lsize.height); + } + Ok(size) } fn draw(self, frame: &mut Frame) -> Result<(), E> { - self.below.draw(frame)?; - self.above.draw(frame)?; + for layer in self.layers { + layer.draw(frame)?; + } Ok(()) } } #[async_trait] -impl AsyncWidget for Layer +impl AsyncWidget for Layer where - I1: AsyncWidget + Send + Sync, - I2: AsyncWidget + Send + Sync, + I: AsyncWidget + Send + Sync, { async fn size( &self, @@ -53,14 +50,150 @@ where max_width: Option, max_height: Option, ) -> Result { - let bottom = self.below.size(widthdb, max_width, max_height).await?; - let top = self.above.size(widthdb, max_width, max_height).await?; - Ok(Self::size(bottom, top)) + let mut size = Size::ZERO; + for layer in &self.layers { + let lsize = layer.size(widthdb, max_width, max_height).await?; + size.width = size.width.max(lsize.width); + size.height = size.height.max(lsize.height); + } + Ok(size) } async fn draw(self, frame: &mut Frame) -> Result<(), E> { - self.below.draw(frame).await?; - self.above.draw(frame).await?; + for layer in self.layers { + layer.draw(frame).await?; + } Ok(()) } } + +macro_rules! mk_layer { + ( + pub struct $name:ident { + $( pub $arg:ident: $type:ident, )+ + } + ) => { + pub struct $name< $($type),+ >{ + $( pub $arg: $type, )+ + } + + impl< $($type),+ > $name< $($type),+ >{ + pub fn new( $($arg: $type),+ ) -> Self { + Self { $( $arg, )+ } + } + } + + impl Widget for $name< $($type),+ > + where + $( $type: Widget, )+ + { + fn size( + &self, + widthdb: &mut WidthDb, + max_width: Option, + max_height: Option, + ) -> Result { + let mut size = Size::ZERO; + + $({ + let lsize = self.$arg.size(widthdb, max_width, max_height)?; + size.width = size.width.max(lsize.width); + size.height = size.height.max(lsize.height); + })+ + + Ok(size) + } + + fn draw(self, frame: &mut Frame) -> Result<(), E> { + $( self.$arg.draw(frame)?; )+ + Ok(()) + } + } + + #[async_trait] + impl AsyncWidget for $name< $($type),+ > + where + E: Send, + $( $type: AsyncWidget + Send + Sync, )+ + { + async fn size( + &self, + widthdb: &mut WidthDb, + max_width: Option, + max_height: Option, + ) -> Result { + let mut size = Size::ZERO; + + $({ + let lsize = self.$arg.size(widthdb, max_width, max_height).await?; + size.width = size.width.max(lsize.width); + size.height = size.height.max(lsize.height); + })+ + + Ok(size) + } + + async fn draw(self, frame: &mut Frame) -> Result<(), E> { + $( self.$arg.draw(frame).await?; )+ + Ok(()) + } + } + }; +} + +mk_layer!( + pub struct Layer2 { + pub first: I1, + pub second: I2, + } +); + +mk_layer!( + pub struct Layer3 { + pub first: I1, + pub second: I2, + pub third: I3, + } +); + +mk_layer!( + pub struct Layer4 { + pub first: I1, + pub second: I2, + pub third: I3, + pub fourth: I4, + } +); + +mk_layer!( + pub struct Layer5 { + pub first: I1, + pub second: I2, + pub third: I3, + pub fourth: I4, + pub fifth: I5, + } +); + +mk_layer!( + pub struct Layer6 { + pub first: I1, + pub second: I2, + pub third: I3, + pub fourth: I4, + pub fifth: I5, + pub sixth: I6, + } +); + +mk_layer!( + pub struct Layer7 { + pub first: I1, + pub second: I2, + pub third: I3, + pub fourth: I4, + pub fifth: I5, + pub sixth: I6, + pub seventh: I7, + } +);