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 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}