diff --git a/src/widget.rs b/src/widget.rs index ea1d131..85a5eb9 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -1,6 +1,6 @@ use async_trait::async_trait; -use crate::widgets::{Background, Border, Float, Padding}; +use crate::widgets::{Background, Border, Float, Padding, Layer}; use crate::{Frame, Size}; // TODO Feature-gate these traits @@ -41,6 +41,14 @@ pub trait WidgetExt: Sized { Float::new(self) } + fn below(self, top: W) -> Layer { + Layer::new(self, top) + } + + fn above(self, bottom: W) -> Layer { + Layer::new(bottom, self) + } + fn padding(self) -> Padding { Padding::new(self) } diff --git a/src/widgets.rs b/src/widgets.rs index 81d4dab..fe1346d 100644 --- a/src/widgets.rs +++ b/src/widgets.rs @@ -3,6 +3,7 @@ mod border; mod cursor; mod empty; mod float; +mod layer; mod padding; mod text; @@ -11,5 +12,6 @@ pub use border::*; pub use cursor::*; pub use empty::*; pub use float::*; +pub use layer::*; pub use padding::*; pub use text::*; diff --git a/src/widgets/layer.rs b/src/widgets/layer.rs new file mode 100644 index 0000000..39cd9d7 --- /dev/null +++ b/src/widgets/layer.rs @@ -0,0 +1,65 @@ +use async_trait::async_trait; + +use crate::{AsyncWidget, Frame, Size, Widget}; + +pub struct Layer { + bottom: I1, + top: I2, +} + +impl Layer { + pub fn new(bottom: I1, top: I2) -> Self { + Self { bottom, top } + } + + fn size(bottom: Size, top: Size) -> Size { + Size::new(bottom.width.max(top.width), bottom.height.max(top.height)) + } +} + +impl Widget for Layer +where + I1: Widget, + I2: Widget, +{ + fn size( + &self, + frame: &mut Frame, + max_width: Option, + max_height: Option, + ) -> Result { + let bottom = self.bottom.size(frame, max_width, max_height)?; + let top = self.top.size(frame, max_width, max_height)?; + Ok(Self::size(bottom, top)) + } + + fn draw(self, frame: &mut Frame) -> Result<(), E> { + self.bottom.draw(frame)?; + self.top.draw(frame)?; + Ok(()) + } +} + +#[async_trait] +impl AsyncWidget for Layer +where + I1: AsyncWidget + Send + Sync, + I2: AsyncWidget + Send + Sync, +{ + async fn size( + &self, + frame: &mut Frame, + max_width: Option, + max_height: Option, + ) -> Result { + let bottom = self.bottom.size(frame, max_width, max_height).await?; + let top = self.top.size(frame, max_width, max_height).await?; + Ok(Self::size(bottom, top)) + } + + async fn draw(self, frame: &mut Frame) -> Result<(), E> { + self.bottom.draw(frame).await?; + self.top.draw(frame).await?; + Ok(()) + } +}