too/views/
constrain.rs

1use crate::{
2    math::{Size, Space},
3    view::{Builder, Layout, View},
4};
5
6#[derive(Debug, Copy, Clone)]
7#[must_use = "a view does nothing unless `show()` or `show_children()` is called"]
8pub struct Constrain {
9    space: Space,
10}
11
12impl Constrain {
13    pub fn new(space: impl Into<Space>) -> Self {
14        Constrain {
15            space: space.into(),
16        }
17    }
18
19    pub fn with(self, other: Self) -> Self {
20        Self::new(self.space.constrain(other.space))
21    }
22
23    pub fn exact_size(size: impl Into<Size>) -> Self {
24        Self::new(Space::from_size(size.into()))
25    }
26
27    pub fn max_size(size: impl Into<Size>) -> Self {
28        Self::new(Space::new(Size::ZERO, size.into()))
29    }
30
31    pub fn min_size(size: impl Into<Size>) -> Self {
32        Self::new(Space::new(size.into(), Size::FILL))
33    }
34
35    // TODO support floats
36    pub fn exact_height(height: i32) -> Self {
37        let mut space = Space::UNBOUNDED;
38        space.min.height = height as f32;
39        space.max.height = height as f32;
40        Self::new(space)
41    }
42
43    pub fn exact_width(width: i32) -> Self {
44        let mut space = Space::UNBOUNDED;
45        space.min.width = width as f32;
46        space.max.width = width as f32;
47        Self::new(space)
48    }
49
50    pub fn min_width(min_width: i32) -> Self {
51        let mut space = Space::UNBOUNDED;
52        space.min.width = min_width as f32;
53        Self::new(space)
54    }
55
56    pub fn max_width(max_width: i32) -> Self {
57        let mut space = Space::UNBOUNDED;
58        space.max.width = max_width as f32;
59        Self::new(space)
60    }
61
62    pub fn min_height(min_height: i32) -> Self {
63        let mut space = Space::UNBOUNDED;
64        space.min.height = min_height as f32;
65        Self::new(space)
66    }
67
68    pub fn max_height(max_height: i32) -> Self {
69        let mut space = Space::UNBOUNDED;
70        space.max.height = max_height as f32;
71        Self::new(space)
72    }
73}
74
75impl<'v> Builder<'v> for Constrain {
76    type View = Self;
77}
78
79impl View for Constrain {
80    type Args<'v> = Self;
81    type Response = ();
82
83    fn create(this: Self::Args<'_>) -> Self {
84        this
85    }
86
87    fn layout(&mut self, layout: Layout, space: Space) -> Size {
88        let constrained = self.space.constrain(space);
89        self.default_layout(layout, constrained)
90    }
91}
92
93#[derive(Copy, Clone, Default, Debug, PartialEq)]
94pub struct Unconstrained {
95    pub horizontal: bool,
96    pub vertical: bool,
97}
98
99impl Unconstrained {
100    pub const fn new() -> Self {
101        Self {
102            horizontal: false,
103            vertical: false,
104        }
105    }
106
107    pub const fn both() -> Self {
108        Self {
109            horizontal: true,
110            vertical: true,
111        }
112    }
113
114    pub const fn horizontal(mut self, horizontal: bool) -> Self {
115        self.horizontal = horizontal;
116        self
117    }
118
119    pub const fn vertical(mut self, vertical: bool) -> Self {
120        self.vertical = vertical;
121        self
122    }
123}
124
125impl<'v> Builder<'v> for Unconstrained {
126    type View = Self;
127}
128
129impl View for Unconstrained {
130    type Args<'v> = Self;
131    type Response = ();
132
133    fn create(args: Self::Args<'_>) -> Self {
134        args
135    }
136
137    fn layout(&mut self, mut layout: Layout, space: Space) -> Size {
138        let node = layout.nodes.get_current();
139
140        let (min_x, max_x) = if self.horizontal {
141            (0.0, space.max.width)
142        } else {
143            (0.0, f32::INFINITY)
144        };
145
146        let (min_y, max_y) = if self.vertical {
147            (0.0, space.max.height)
148        } else {
149            (0.0, f32::INFINITY)
150        };
151
152        let new = Space::new(Size::new(min_x, min_y), Size::new(max_x, max_y));
153
154        let mut size = Size::ZERO;
155        for &child in &node.children {
156            size = size.max(layout.compute(child, new))
157        }
158
159        new.constrain_min(size)
160    }
161}