yakui_widgets/widgets/
round_rect.rs

1use yakui_core::geometry::{Color, Constraints, Vec2};
2use yakui_core::widget::{LayoutContext, PaintContext, Widget};
3use yakui_core::Response;
4
5use crate::shapes;
6use crate::util::{widget, widget_children};
7
8/**
9A colored box with rounded corners that can contain children.
10
11Responds with [RoundRectResponse].
12*/
13#[derive(Debug, Clone)]
14#[non_exhaustive]
15#[must_use = "yakui widgets do nothing if you don't `show` them"]
16pub struct RoundRect {
17    pub radius: f32,
18    pub color: Color,
19    pub min_size: Vec2,
20}
21
22impl RoundRect {
23    pub fn new(radius: f32) -> Self {
24        Self {
25            radius,
26            color: Color::WHITE,
27            min_size: Vec2::ZERO,
28        }
29    }
30
31    pub fn show(self) -> Response<RoundRectResponse> {
32        widget::<RoundRectWidget>(self)
33    }
34
35    pub fn show_children<F: FnOnce()>(self, children: F) -> Response<RoundRectResponse> {
36        widget_children::<RoundRectWidget, F>(children, self)
37    }
38}
39
40#[derive(Debug)]
41pub struct RoundRectWidget {
42    props: RoundRect,
43}
44
45pub type RoundRectResponse = ();
46
47impl Widget for RoundRectWidget {
48    type Props<'a> = RoundRect;
49    type Response = RoundRectResponse;
50
51    fn new() -> Self {
52        Self {
53            props: RoundRect::new(0.0),
54        }
55    }
56
57    fn update(&mut self, props: Self::Props<'_>) -> Self::Response {
58        self.props = props;
59    }
60
61    fn layout(&self, mut ctx: LayoutContext<'_>, input: Constraints) -> Vec2 {
62        let node = ctx.dom.get_current();
63        let mut size = self.props.min_size;
64
65        for &child in &node.children {
66            let child_size = ctx.calculate_layout(child, input);
67            size = size.max(child_size);
68        }
69
70        input.constrain_min(size)
71    }
72
73    fn paint(&self, mut ctx: PaintContext<'_>) {
74        let node = ctx.dom.get_current();
75        let layout_node = ctx.layout.get(ctx.dom.current()).unwrap();
76
77        let mut rect = shapes::RoundedRectangle::new(layout_node.rect, self.props.radius);
78        rect.color = self.props.color;
79        rect.add(ctx.paint);
80
81        for &child in &node.children {
82            ctx.paint(child);
83        }
84    }
85}