diff --git a/examples/hello_world_widgets.rs b/examples/hello_world_widgets.rs index 3bf1d24..9dd5e24 100644 --- a/examples/hello_world_widgets.rs +++ b/examples/hello_world_widgets.rs @@ -18,6 +18,8 @@ fn widget() -> impl Widget { .border() .look(BorderLook::LINE_DOUBLE) .style(ContentStyle::default().dark_red()) + .background() + .style(ContentStyle::default().on_dark_yellow()) .float() .all(0.5) } diff --git a/src/widget.rs b/src/widget.rs index ed9053f..ea1d131 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -1,6 +1,6 @@ use async_trait::async_trait; -use crate::widgets::{Border, Float, Padding}; +use crate::widgets::{Background, Border, Float, Padding}; use crate::{Frame, Size}; // TODO Feature-gate these traits @@ -29,6 +29,10 @@ pub trait AsyncWidget { } pub trait WidgetExt: Sized { + fn background(self) -> Background { + Background::new(self) + } + fn border(self) -> Border { Border::new(self) } diff --git a/src/widgets.rs b/src/widgets.rs index 7503859..37f4701 100644 --- a/src/widgets.rs +++ b/src/widgets.rs @@ -1,9 +1,11 @@ +mod background; mod border; mod empty; mod float; mod padding; mod text; +pub use background::*; pub use border::*; pub use empty::*; pub use float::*; diff --git a/src/widgets/background.rs b/src/widgets/background.rs new file mode 100644 index 0000000..5fd91e8 --- /dev/null +++ b/src/widgets/background.rs @@ -0,0 +1,71 @@ +use async_trait::async_trait; +use crossterm::style::ContentStyle; + +use crate::{AsyncWidget, Frame, Pos, Size, Widget}; + +pub struct Background { + inner: I, + style: ContentStyle, +} + +impl Background { + pub fn new(inner: I) -> Self { + Self { + inner, + style: ContentStyle::default(), + } + } + + pub fn style(mut self, style: ContentStyle) -> Self { + self.style = style; + self + } + + fn fill(&self, frame: &mut Frame) { + let size = frame.size(); + for dy in 0..size.height { + for dx in 0..size.width { + frame.write(Pos::new(dx.into(), dy.into()), (" ", self.style)); + } + } + } +} + +impl Widget for Background +where + I: Widget, +{ + fn size( + &self, + frame: &mut Frame, + max_width: Option, + max_height: Option, + ) -> Result { + self.inner.size(frame, max_width, max_height) + } + + fn draw(self, frame: &mut Frame) -> Result<(), E> { + self.fill(frame); + self.inner.draw(frame) + } +} + +#[async_trait] +impl AsyncWidget for Background +where + I: AsyncWidget + Send + Sync, +{ + async fn size( + &self, + frame: &mut Frame, + max_width: Option, + max_height: Option, + ) -> Result { + self.inner.size(frame, max_width, max_height).await + } + + async fn draw(self, frame: &mut Frame) -> Result<(), E> { + self.fill(frame); + self.inner.draw(frame).await + } +}