yakui_widgets/widgets/
round_rect.rs1use 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#[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}