Add Background widget

This commit is contained in:
Joscha 2024-03-04 00:26:20 +01:00
parent 1000de5bcf
commit fd1b337cd1
4 changed files with 70 additions and 17 deletions

View file

@ -22,16 +22,11 @@ impl<'a, C> View<'a, C> {
} }
} }
pub fn with_area(mut self, area: Rect) -> Self { pub fn zoom(mut self, area: Rect) -> Self {
self.area = area; self.area = area + self.area.corner_nw();
self self
} }
pub fn translated(self, delta: Vec2) -> Self {
let area = self.area + delta;
self.with_area(area)
}
pub fn size(&self) -> Vec2 { pub fn size(&self) -> Vec2 {
self.area.size() self.area.size()
} }

View file

@ -1,4 +1,4 @@
use crate::{Rect, Vec2, View}; use crate::{widgets::Background, Rect, Vec2, View};
pub trait Widget<C> { pub trait Widget<C> {
/// Size that the widget wants to be, given the width and height /// Size that the widget wants to be, given the width and height
@ -26,6 +26,20 @@ pub trait Widget<C> {
fn draw(self, view: &mut View<'_, C>); fn draw(self, view: &mut View<'_, C>);
} }
/// Extension trait for [`Widget`]s.
pub trait WidgetExt<C> {
fn boxed(self) -> BoxedWidget<C>;
}
impl<C, W> WidgetExt<C> for W
where
W: Widget<C> + 'static,
{
fn boxed(self) -> BoxedWidget<C> {
BoxedWidget::new(self)
}
}
/// Wrapper trait around [`Widget`] that turns `Box<Self>` into a `Self` to get /// Wrapper trait around [`Widget`] that turns `Box<Self>` into a `Self` to get
/// around the "size cannot be statically determined" error with the naïve /// around the "size cannot be statically determined" error with the naïve
/// approach of `Box<Widget>`. /// approach of `Box<Widget>`.
@ -77,22 +91,30 @@ impl<C> BoxedWidget<C> {
pub fn area(&self) -> Rect { pub fn area(&self) -> Rect {
self.area self.area
} }
}
impl<C> Widget<C> for BoxedWidget<C> { // Widget-like functions
fn size(&self, max_width: Option<i32>, max_height: Option<i32>) -> Vec2 {
pub fn size(&self, max_width: Option<i32>, max_height: Option<i32>) -> Vec2 {
self.widget.size(max_width, max_height) 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); self.widget.resize(area);
} }
fn update(&mut self, area: Rect) -> anyhow::Result<()> { pub fn update(&mut self) -> anyhow::Result<()> {
self.widget.update(area) self.widget.update(self.area)
} }
fn draw(self, view: &mut View<'_, C>) { pub fn draw(self, view: &mut View<'_, C>) {
self.widget.draw(view); let mut view = view.dup().zoom(self.area);
self.widget.draw(&mut view);
}
// Widget constructors
pub fn background(self, color: C) -> Background<C> {
Background::new(self, color)
} }
} }

View file

@ -1,3 +1,5 @@
pub use empty::Empty; pub use background::*;
pub use empty::*;
mod background;
mod empty; mod empty;

View file

@ -0,0 +1,34 @@
use crate::{BoxedWidget, Vec2, Widget};
pub struct Background<C> {
inner: BoxedWidget<C>,
color: C,
}
impl<C> Background<C> {
pub fn new(inner: BoxedWidget<C>, color: C) -> Self {
Self { inner, color }
}
}
impl<C: Copy> Widget<C> for Background<C> {
fn size(&self, max_width: Option<i32>, max_height: Option<i32>) -> 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);
}
}
}
}