1mod limits;
3
4pub mod flex;
5
6pub use limits::Limits;
7
8use crate::widget;
9use crate::{Length, Padding, Point, Rectangle, Size, Vector};
10
11#[derive(Debug, Clone, Copy, PartialEq)]
13pub struct Layout {
14 position: Point,
15 size: Size,
16 parent: Option<Rectangle>,
17}
18
19impl Layout {
20 pub fn new(size: Size) -> Self {
22 Self {
23 position: Point::ORIGIN,
24 size,
25 parent: None,
26 }
27 }
28
29 pub fn position(&self) -> Point {
31 self.position
32 }
33
34 pub fn move_to(self, position: impl Into<Point>) -> Self {
36 Self {
37 position: position.into(),
38 size: self.size,
39 parent: self.parent,
40 }
41 }
42
43 pub fn bounds(&self) -> Rectangle {
48 Rectangle::new(self.position, self.size)
49 }
50
51 pub fn size(&self) -> Size {
53 self.size
54 }
55
56 pub fn parent(&self) -> Option<Rectangle> {
58 self.parent
59 }
60
61 pub fn iter(
63 self,
64 children: &[widget::Tree],
65 ) -> impl DoubleEndedIterator<Item = (Self, &widget::Tree)> + ExactSizeIterator {
66 children.iter().map(move |child| (self.child(child), child))
67 }
68
69 pub fn iter_mut(
71 self,
72 children: &mut [widget::Tree],
73 ) -> impl DoubleEndedIterator<Item = (Self, &mut widget::Tree)> + ExactSizeIterator {
74 children
75 .iter_mut()
76 .map(move |child| (self.child(child), child))
77 }
78
79 fn child(&self, child: &widget::Tree) -> Self {
80 Self {
81 position: self.position + child.translation,
82 size: child.size,
83 parent: Some(self.bounds()),
84 }
85 }
86}
87
88pub fn next_to_each_other(tree: &mut widget::Tree, left: Size, right: Size, spacing: f32) {
97 let (left_y, right_y) = if left.height > right.height {
98 (0.0, (left.height - right.height) / 2.0)
99 } else {
100 ((right.height - left.height) / 2.0, 0.0)
101 };
102
103 tree.size = Size::new(
104 left.width + spacing + right.width,
105 left.height.max(right.height),
106 );
107
108 tree.children[0].size = left;
109 tree.children[0].translation = Vector::new(0.0, left_y);
110
111 tree.children[1].size = right;
112 tree.children[1].translation = Vector::new(left.width + spacing, right_y);
113}
114
115pub fn atomic(limits: &Limits, width: impl Into<Length>, height: impl Into<Length>) -> Size {
118 let width = width.into();
119 let height = height.into();
120
121 limits
122 .width(width)
123 .height(height)
124 .resolve(width, height, Size::ZERO)
125}
126
127pub fn sized(
131 limits: &Limits,
132 width: impl Into<Length>,
133 height: impl Into<Length>,
134 f: impl FnOnce(&Limits) -> Size,
135) -> Size {
136 let width = width.into();
137 let height = height.into();
138
139 let limits = limits.width(width).height(height);
140 let intrinsic_size = f(&limits);
141
142 limits.resolve(width, height, intrinsic_size)
143}
144
145pub fn contained(
149 tree: &mut widget::Tree,
150 limits: &Limits,
151 width: impl Into<Length>,
152 height: impl Into<Length>,
153 f: impl FnOnce(&mut widget::Tree, &Limits) -> Size,
154) {
155 let width = width.into();
156 let height = height.into();
157 let limits = limits.width(width).height(height);
158
159 let child = &mut tree.children[0];
160 let content = f(child, &limits);
161
162 tree.size = limits.resolve(width, height, content);
163 child.translation = Vector::ZERO;
164}
165
166pub fn padded(
170 tree: &mut widget::Tree,
171 limits: &Limits,
172 width: impl Into<Length>,
173 height: impl Into<Length>,
174 padding: impl Into<Padding>,
175 layout: impl FnOnce(&mut widget::Tree, &Limits) -> Size,
176) {
177 positioned(tree, limits, width, height, padding, layout, |_, _| {
178 Vector::ZERO
179 });
180}
181
182pub fn positioned(
184 tree: &mut widget::Tree,
185 limits: &Limits,
186 width: impl Into<Length>,
187 height: impl Into<Length>,
188 padding: impl Into<Padding>,
189 layout: impl FnOnce(&mut widget::Tree, &Limits) -> Size,
190 translate: impl FnOnce(Size, Size) -> Vector,
191) {
192 let width = width.into();
193 let height = height.into();
194 let padding = padding.into();
195 let limits = limits.width(width).height(height);
196
197 let child = &mut tree.children[0];
198 let content = layout(child, &limits.shrink(padding));
199 let padding = padding.fit(content, limits.bounds());
200
201 let container = limits.shrink(padding).resolve(width, height, content);
202
203 tree.size = container.expand(padding);
204 child.translation = Vector::new(padding.left, padding.top) + translate(content, container);
205}