Rip out buffer and widgets

I've decided to use the "taffy" crate for layouting. To make the API
somewhat bearable to use, I've decided to perform all rendering in a
good ol' rgb image buffer (in this case, an ImageBuffer from the "image"
crate). The pixels will be converted to their final representation just
before being sent to whatever device will be displaying them.

I've removed the buffer and the color traits because they're no longer
necessary. I've also removed the existing widgets because the widget
system will have to be redesigned to work well with taffy.
This commit is contained in:
Joscha 2024-03-06 00:36:18 +01:00
parent 04ed092c4f
commit eb04b3fb50
13 changed files with 38 additions and 300 deletions

View file

@ -1,122 +0,0 @@
use crate::{widgets::Background, Rect, Vec2, View};
pub trait Widget<C> {
/// Size that the widget wants to be, given the width and height
/// constraints.
fn size(&self, max_width: Option<i32>, max_height: Option<i32>) -> Vec2;
/// Recalculate the area (size and position) of all inner widgets given the
/// widget's own area.
///
/// # Implement if...
///
/// - There are inner widgets
fn set_area(&mut self, _area: Rect) {}
/// Perform any updates (e.g. fetching map tiles) that require the widget's
/// area and may fail.
///
/// # Implement if...
///
/// - There are inner widgets
/// - This widget needs to perform updates
fn update(&mut self, _area: Rect) -> anyhow::Result<()> {
Ok(())
}
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
/// around the "size cannot be statically determined" error with the naïve
/// approach of `Box<Widget>`.
trait WidgetWrapper<C> {
fn size(&self, max_width: Option<i32>, max_height: Option<i32>) -> Vec2;
fn set_area(&mut self, _area: Rect);
fn update(&mut self, _area: Rect) -> anyhow::Result<()>;
fn draw(self: Box<Self>, view: &mut View<'_, C>);
}
impl<C, W: Widget<C>> WidgetWrapper<C> for W {
// These implementations explicitly use `Widget::*` to call the widget
// methods even though they have priority over the `WidgetWrapper::*`
// methods for some reason. Just a bit of rustc magic, I guess.
fn size(&self, max_width: Option<i32>, max_height: Option<i32>) -> Vec2 {
Widget::size(self, max_width, max_height)
}
fn set_area(&mut self, area: Rect) {
// Widget::set_area(self, area);
self.set_area(area);
}
fn update(&mut self, area: Rect) -> anyhow::Result<()> {
Widget::update(self, area)
}
fn draw(self: Box<Self>, view: &mut View<'_, C>) {
Widget::draw(*self, view);
}
}
pub struct BoxedWidget<C> {
area: Rect,
widget: Box<dyn WidgetWrapper<C>>,
}
impl<C> BoxedWidget<C> {
pub fn new<W>(widget: W) -> Self
where
W: Widget<C> + 'static,
{
Self {
area: Rect::ZERO,
widget: Box::new(widget),
}
}
pub fn area(&self) -> Rect {
self.area
}
// Widget-like functions
pub fn size(&self, max_width: Option<i32>, max_height: Option<i32>) -> Vec2 {
self.widget.size(max_width, max_height)
}
pub fn set_area(&mut self, area: Rect) {
self.area = area;
self.widget.set_area(area);
}
pub fn update(&mut self) -> anyhow::Result<()> {
self.widget.update(self.area)
}
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<C> {
Background::new(self, color)
}
}