diff --git a/showbits-common/src/view.rs b/showbits-common/src/view.rs index 7836918..d659d32 100644 --- a/showbits-common/src/view.rs +++ b/showbits-common/src/view.rs @@ -22,16 +22,11 @@ impl<'a, C> View<'a, C> { } } - pub fn with_area(mut self, area: Rect) -> Self { - self.area = area; + pub fn zoom(mut self, area: Rect) -> Self { + self.area = area + self.area.corner_nw(); self } - pub fn translated(self, delta: Vec2) -> Self { - let area = self.area + delta; - self.with_area(area) - } - pub fn size(&self) -> Vec2 { self.area.size() } diff --git a/showbits-common/src/widget.rs b/showbits-common/src/widget.rs index 942754b..3430653 100644 --- a/showbits-common/src/widget.rs +++ b/showbits-common/src/widget.rs @@ -1,4 +1,4 @@ -use crate::{Rect, Vec2, View}; +use crate::{widgets::Background, Rect, Vec2, View}; pub trait Widget { /// Size that the widget wants to be, given the width and height @@ -26,6 +26,20 @@ pub trait Widget { fn draw(self, view: &mut View<'_, C>); } +/// Extension trait for [`Widget`]s. +pub trait WidgetExt { + fn boxed(self) -> BoxedWidget; +} + +impl WidgetExt for W +where + W: Widget + 'static, +{ + fn boxed(self) -> BoxedWidget { + BoxedWidget::new(self) + } +} + /// Wrapper trait around [`Widget`] that turns `Box` into a `Self` to get /// around the "size cannot be statically determined" error with the naïve /// approach of `Box`. @@ -77,22 +91,30 @@ impl BoxedWidget { pub fn area(&self) -> Rect { self.area } -} -impl Widget for BoxedWidget { - fn size(&self, max_width: Option, max_height: Option) -> Vec2 { + // Widget-like functions + + pub fn size(&self, max_width: Option, max_height: Option) -> Vec2 { self.widget.size(max_width, max_height) } - fn resize(&mut self, area: Rect) { + pub fn resize(&mut self, area: Rect) { + self.area = area; self.widget.resize(area); } - fn update(&mut self, area: Rect) -> anyhow::Result<()> { - self.widget.update(area) + pub fn update(&mut self) -> anyhow::Result<()> { + self.widget.update(self.area) } - fn draw(self, view: &mut View<'_, C>) { - self.widget.draw(view); + pub fn draw(self, view: &mut View<'_, C>) { + let mut view = view.dup().zoom(self.area); + self.widget.draw(&mut view); + } + + // Widget constructors + + pub fn background(self, color: C) -> Background { + Background::new(self, color) } } diff --git a/showbits-common/src/widgets.rs b/showbits-common/src/widgets.rs index 43725cc..be2843c 100644 --- a/showbits-common/src/widgets.rs +++ b/showbits-common/src/widgets.rs @@ -1,3 +1,5 @@ -pub use empty::Empty; +pub use background::*; +pub use empty::*; +mod background; mod empty; diff --git a/showbits-common/src/widgets/background.rs b/showbits-common/src/widgets/background.rs new file mode 100644 index 0000000..c3f49b3 --- /dev/null +++ b/showbits-common/src/widgets/background.rs @@ -0,0 +1,34 @@ +use crate::{BoxedWidget, Vec2, Widget}; + +pub struct Background { + inner: BoxedWidget, + color: C, +} + +impl Background { + pub fn new(inner: BoxedWidget, color: C) -> Self { + Self { inner, color } + } +} + +impl Widget for Background { + fn size(&self, max_width: Option, max_height: Option) -> crate::Vec2 { + self.inner.size(max_width, max_height) + } + + fn resize(&mut self, area: crate::Rect) { + self.inner.resize(area); + } + + fn update(&mut self, _area: crate::Rect) -> anyhow::Result<()> { + Ok(()) + } + + fn draw(self, view: &mut crate::View<'_, C>) { + for y in 0..view.size().y { + for x in 0..view.size().x { + view.set(Vec2::new(x, y), self.color); + } + } + } +}