frui_widgets 0.0.1

Essential widgets for Frui UI framework
Documentation
use druid_shell::kurbo::Rect;

use frui::prelude::*;

#[derive(SingleChildWidget)]
pub struct Container<W: Widget> {
    child: W,
    width: Option<f64>,
    height: Option<f64>,
    color: Option<Color>,
}

impl Container<()> {
    pub fn builder() -> Container<()> {
        Container {
            child: (),
            width: None,
            height: None,
            color: None,
        }
    }
}

impl<W: Widget> Container<W> {
    pub fn child<C: Widget>(self, child: C) -> Container<C> {
        Container {
            child,
            width: self.width,
            height: self.height,
            color: self.color,
        }
    }

    #[track_caller]
    pub fn width(mut self, width: f64) -> Self {
        assert!(width >= 0.0, "width must be >= 0.0");
        self.width = Some(width);
        self
    }

    #[track_caller]
    pub fn height(mut self, height: f64) -> Self {
        assert!(height >= 0.0, "height must be >= 0.0");
        self.height = Some(height);
        self
    }

    pub fn color(mut self, color: Color) -> Self {
        self.color = Some(color);
        self
    }
}

impl<W: Widget> SingleChildWidget for Container<W> {
    fn build<'w>(&'w self, _: BuildContext<'w, Self>) -> Self::Widget<'w> {
        &self.child
    }

    fn layout(&self, ctx: RenderContext<Self>, constraints: Constraints) -> Size {
        let size = ctx.child().layout(Constraints {
            max_width: self.width.unwrap_or(constraints.max_width),
            max_height: self.height.unwrap_or(constraints.max_height),
            ..constraints
        });

        Size {
            width: self.width.unwrap_or(size.width),
            height: self.height.unwrap_or(size.height),
        }
    }

    fn paint(&self, ctx: RenderContext<Self>, canvas: &mut PaintContext, offset: &Offset) {
        if let Some(color) = &self.color {
            let brush = &canvas.solid_brush(color.clone());

            PietRenderContext::fill(canvas, Rect::from_origin_size(offset, ctx.size()), brush);
        }

        ctx.child().paint(canvas, offset)
    }
}