1use iced_core::{Widget, widget::Tree};
4use iced_widget::core::{
5 Alignment, Element, Padding, Point, Size,
6 layout::{Limits, Node},
7 renderer,
8};
9
10use crate::widget::RcElementWrapper;
11
12#[derive(Debug)]
14pub enum Axis {
15 Horizontal,
17
18 #[allow(dead_code)]
20 Vertical,
21}
22
23impl Axis {
24 fn main(&self, size: Size) -> f32 {
26 match self {
27 Self::Horizontal => size.width,
28 Self::Vertical => size.height,
29 }
30 }
31
32 fn cross(&self, size: Size) -> f32 {
34 match self {
35 Self::Horizontal => size.height,
36 Self::Vertical => size.width,
37 }
38 }
39
40 fn pack(&self, main: f32, cross: f32) -> (f32, f32) {
42 match self {
43 Self::Horizontal => (main, cross),
44 Self::Vertical => (cross, main),
45 }
46 }
47}
48
49pub fn resolve<'a, E, Message, Renderer>(
54 axis: &Axis,
55 renderer: &Renderer,
56 limits: &Limits,
57 padding: Padding,
58 spacing: f32,
59 align_items: Alignment,
60 items: &mut [E],
61 tree: &mut [&mut Tree],
62) -> Node
63where
64 E: std::borrow::BorrowMut<Element<'a, Message, crate::Theme, Renderer>>,
65 Renderer: renderer::Renderer,
66{
67 let limits = limits.shrink(padding);
68 let total_spacing = spacing * items.len().saturating_sub(1) as f32;
69 let max_cross = axis.cross(limits.max());
70
71 let mut fill_sum = 0;
72 let mut cross = axis.cross(limits.min()).max(axis.cross(Size::INFINITE));
73 let mut available = axis.main(limits.max()) - total_spacing;
74
75 let mut nodes: Vec<Node> = Vec::with_capacity(items.len());
76 nodes.resize(items.len(), Node::default());
77
78 if align_items == Alignment::Center {
79 let mut fill_cross = axis.cross(limits.min());
80
81 for (child, tree) in items.iter_mut().zip(tree.iter_mut()) {
82 let child = child.borrow_mut();
83 let c_size = child.as_widget().size();
84 let cross_fill_factor = match axis {
85 Axis::Horizontal => c_size.height,
86 Axis::Vertical => c_size.width,
87 }
88 .fill_factor();
89
90 if cross_fill_factor == 0 {
91 let (max_width, max_height) = axis.pack(available, max_cross);
92
93 let child_limits = Limits::new(Size::ZERO, Size::new(max_width, max_height));
94
95 let layout = child.as_widget_mut().layout(tree, renderer, &child_limits);
96 let size = layout.size();
97
98 fill_cross = fill_cross.max(axis.cross(size));
99 }
100 }
101
102 cross = fill_cross;
103 }
104
105 for (i, (child, tree)) in items.iter_mut().zip(tree.iter_mut()).enumerate() {
106 let child = child.borrow_mut();
107 let c_size = child.as_widget().size();
108 let fill_factor = match axis {
109 Axis::Horizontal => c_size.width,
110 Axis::Vertical => c_size.height,
111 }
112 .fill_factor();
113
114 if fill_factor == 0 {
115 let (min_width, min_height) = if align_items == Alignment::Center {
116 axis.pack(0.0, cross)
117 } else {
118 axis.pack(0.0, 0.0)
119 };
120
121 let (max_width, max_height) = if align_items == Alignment::Center {
122 axis.pack(available, cross)
123 } else {
124 axis.pack(available, max_cross)
125 };
126
127 let child_limits = Limits::new(
128 Size::new(min_width, min_height),
129 Size::new(max_width, max_height),
130 );
131
132 let layout = child.as_widget_mut().layout(tree, renderer, &child_limits);
133 let size = layout.size();
134
135 available -= axis.main(size);
136
137 if align_items != Alignment::Center {
138 cross = cross.max(axis.cross(size));
139 }
140
141 nodes[i] = layout;
142 } else {
143 fill_sum += fill_factor;
144 }
145 }
146
147 let remaining = available.max(0.0);
148
149 for (i, (child, tree)) in items.iter_mut().zip(tree.iter_mut()).enumerate() {
150 let child = child.borrow_mut();
151 let c_size = child.as_widget().size();
152 let fill_factor = match axis {
153 Axis::Horizontal => c_size.width,
154 Axis::Vertical => c_size.height,
155 }
156 .fill_factor();
157
158 if fill_factor != 0 {
159 let max_main = remaining * f32::from(fill_factor) / f32::from(fill_sum);
160 let min_main = if max_main.is_infinite() {
161 0.0
162 } else {
163 max_main
164 };
165
166 let (min_width, min_height) = if align_items == Alignment::Center {
167 axis.pack(min_main, cross)
168 } else {
169 axis.pack(min_main, axis.cross(limits.min()))
170 };
171
172 let (max_width, max_height) = if align_items == Alignment::Center {
173 axis.pack(max_main, cross)
174 } else {
175 axis.pack(max_main, max_cross)
176 };
177
178 let child_limits = Limits::new(
179 Size::new(min_width, min_height),
180 Size::new(max_width, max_height),
181 );
182
183 let layout = child.as_widget_mut().layout(tree, renderer, &child_limits);
184
185 if align_items != Alignment::Center {
186 cross = cross.max(axis.cross(layout.size()));
187 }
188
189 nodes[i] = layout;
190 }
191 }
192
193 let pad = axis.pack(padding.left, padding.top);
194 let mut main = pad.0;
195
196 for (i, node) in nodes.iter_mut().enumerate() {
197 if i > 0 {
198 main += spacing;
199 }
200
201 let (x, y) = axis.pack(main, pad.1);
202
203 node.move_to_mut(Point::new(x, y));
204
205 match axis {
206 Axis::Horizontal => {
207 node.align_mut(Alignment::Start, align_items, Size::new(0.0, cross))
208 }
209 Axis::Vertical => node.align_mut(align_items, Alignment::Start, Size::new(cross, 0.0)),
210 };
211
212 let size = node.bounds().size();
213
214 main += axis.main(size);
215 }
216
217 let (width, height) = axis.pack(main - pad.0, cross);
218 let size = limits.resolve(width, height, Size::new(width, height));
219
220 Node::with_children(size.expand(padding), nodes)
221}
222
223pub fn resolve_wrapper<'a, Message>(
228 axis: &Axis,
229 renderer: &crate::Renderer,
230 limits: &Limits,
231 padding: Padding,
232 spacing: f32,
233 align_items: Alignment,
234 items: &mut [&mut RcElementWrapper<Message>],
235 tree: &mut [&mut Tree],
236) -> Node {
237 let limits = limits.shrink(padding);
238 let total_spacing = spacing * items.len().saturating_sub(1) as f32;
239 let max_cross = axis.cross(limits.max());
240
241 let mut fill_sum = 0;
242 let mut cross = axis.cross(limits.min()).max(axis.cross(Size::INFINITE));
243 let mut available = axis.main(limits.max()) - total_spacing;
244
245 let mut nodes: Vec<Node> = Vec::with_capacity(items.len());
246 nodes.resize(items.len(), Node::default());
247
248 if align_items == Alignment::Center {
249 let mut fill_cross = axis.cross(limits.min());
250
251 for (child, tree) in items.into_iter().zip(tree.iter_mut()) {
252 let c_size = child.size();
253 let cross_fill_factor = match axis {
254 Axis::Horizontal => c_size.height,
255 Axis::Vertical => c_size.width,
256 }
257 .fill_factor();
258
259 if cross_fill_factor == 0 {
260 let (max_width, max_height) = axis.pack(available, max_cross);
261
262 let child_limits = Limits::new(Size::ZERO, Size::new(max_width, max_height));
263
264 let layout = child.layout(tree, renderer, &child_limits);
265 let size = layout.size();
266
267 fill_cross = fill_cross.max(axis.cross(size));
268 }
269 }
270
271 cross = fill_cross;
272 }
273
274 for (i, (child, tree)) in items.into_iter().zip(tree.iter_mut()).enumerate() {
275 let c_size = child.size();
276 let fill_factor = match axis {
277 Axis::Horizontal => c_size.width,
278 Axis::Vertical => c_size.height,
279 }
280 .fill_factor();
281
282 if fill_factor == 0 {
283 let (min_width, min_height) = if align_items == Alignment::Center {
284 axis.pack(0.0, cross)
285 } else {
286 axis.pack(0.0, 0.0)
287 };
288
289 let (max_width, max_height) = if align_items == Alignment::Center {
290 axis.pack(available, cross)
291 } else {
292 axis.pack(available, max_cross)
293 };
294
295 let child_limits = Limits::new(
296 Size::new(min_width, min_height),
297 Size::new(max_width, max_height),
298 );
299
300 let layout = child.layout(tree, renderer, &child_limits);
301 let size = layout.size();
302
303 available -= axis.main(size);
304
305 if align_items != Alignment::Center {
306 cross = cross.max(axis.cross(size));
307 }
308
309 nodes[i] = layout;
310 } else {
311 fill_sum += fill_factor;
312 }
313 }
314
315 let remaining = available.max(0.0);
316
317 for (i, (child, tree)) in items.into_iter().zip(tree.iter_mut()).enumerate() {
318 let c_size = child.size();
319 let fill_factor = match axis {
320 Axis::Horizontal => c_size.width,
321 Axis::Vertical => c_size.height,
322 }
323 .fill_factor();
324
325 if fill_factor != 0 {
326 let max_main = remaining * f32::from(fill_factor) / f32::from(fill_sum);
327 let min_main = if max_main.is_infinite() {
328 0.0
329 } else {
330 max_main
331 };
332
333 let (min_width, min_height) = if align_items == Alignment::Center {
334 axis.pack(min_main, cross)
335 } else {
336 axis.pack(min_main, axis.cross(limits.min()))
337 };
338
339 let (max_width, max_height) = if align_items == Alignment::Center {
340 axis.pack(max_main, cross)
341 } else {
342 axis.pack(max_main, max_cross)
343 };
344
345 let child_limits = Limits::new(
346 Size::new(min_width, min_height),
347 Size::new(max_width, max_height),
348 );
349
350 let layout = child.layout(tree, renderer, &child_limits);
351
352 if align_items != Alignment::Center {
353 cross = cross.max(axis.cross(layout.size()));
354 }
355
356 nodes[i] = layout;
357 }
358 }
359
360 let pad = axis.pack(padding.left, padding.top);
361 let mut main = pad.0;
362
363 for (i, node) in nodes.iter_mut().enumerate() {
364 if i > 0 {
365 main += spacing;
366 }
367
368 let (x, y) = axis.pack(main, pad.1);
369
370 node.move_to_mut(Point::new(x, y));
371
372 match axis {
373 Axis::Horizontal => {
374 node.align_mut(Alignment::Start, align_items, Size::new(0.0, cross))
375 }
376 Axis::Vertical => node.align_mut(align_items, Alignment::Start, Size::new(cross, 0.0)),
377 };
378
379 let size = node.bounds().size();
380
381 main += axis.main(size);
382 }
383
384 let (width, height) = axis.pack(main - pad.0, cross);
385 let size = limits.resolve(width, height, Size::new(width, height));
386
387 Node::with_children(size.expand(padding), nodes)
388}