yakui_widgets/widgets/
constrained_box.rs

1use yakui_core::geometry::{Constraints, Vec2};
2use yakui_core::widget::{LayoutContext, Widget};
3use yakui_core::Response;
4
5use crate::util::widget_children;
6
7/**
8A box that forces specific constraints onto its child.
9
10Responds with [ConstrainedBoxResponse].
11*/
12#[derive(Debug, Clone)]
13#[non_exhaustive]
14#[must_use = "yakui widgets do nothing if you don't `show` them"]
15pub struct ConstrainedBox {
16    pub constraints: Constraints,
17}
18
19impl ConstrainedBox {
20    pub fn new(constraints: Constraints) -> Self {
21        Self { constraints }
22    }
23
24    pub fn show<F: FnOnce()>(self, children: F) -> Response<ConstrainedBoxResponse> {
25        widget_children::<ConstrainedBoxWidget, F>(children, self)
26    }
27}
28
29#[derive(Debug)]
30pub struct ConstrainedBoxWidget {
31    props: ConstrainedBox,
32}
33
34pub type ConstrainedBoxResponse = ();
35
36impl Widget for ConstrainedBoxWidget {
37    type Props<'a> = ConstrainedBox;
38    type Response = ConstrainedBoxResponse;
39
40    fn new() -> Self {
41        Self {
42            props: ConstrainedBox::new(Constraints {
43                min: Vec2::ZERO,
44                max: Vec2::ZERO,
45            }),
46        }
47    }
48
49    fn update(&mut self, props: Self::Props<'_>) -> Self::Response {
50        self.props = props;
51    }
52
53    fn layout(&self, mut ctx: LayoutContext<'_>, input: Constraints) -> Vec2 {
54        let node = ctx.dom.get_current();
55        let mut size = Vec2::ZERO;
56        let constraints = Constraints {
57            min: Vec2::max(input.min, self.props.constraints.min),
58            max: Vec2::min(input.max, self.props.constraints.max),
59        };
60
61        for &child in &node.children {
62            let child_size = ctx.calculate_layout(child, constraints);
63            size = size.max(child_size);
64        }
65
66        input.constrain(constraints.constrain(size))
67    }
68}