1use crate::core::alignment::{self, Alignment};
3use crate::core::layout;
4use crate::core::mouse;
5use crate::core::overlay;
6use crate::core::renderer;
7use crate::core::widget::{Meta, Operation, Tree, tree};
8use crate::core::{Event, Layout, Length, Padding, Pixels, Rectangle, Shell, Size, Vector, Widget};
9
10pub struct Column<W> {
33 spacing: f32,
34 padding: Padding,
35 width: Length,
36 height: Length,
37 align: Alignment,
38 clip: bool,
39 children: Vec<W>,
40}
41
42impl<W> Column<W> {
43 pub fn new() -> Self {
45 Self::from_vec(Vec::new())
46 }
47
48 pub fn with_capacity(capacity: usize) -> Self {
50 Self::from_vec(Vec::with_capacity(capacity))
51 }
52
53 pub fn with_children(children: impl IntoIterator<Item = W>) -> Self
55 where
56 W: Meta,
57 {
58 let iterator = children.into_iter();
59
60 Self::with_capacity(iterator.size_hint().0).extend(iterator)
61 }
62
63 pub fn from_vec(children: Vec<W>) -> Self {
65 Self {
66 spacing: 0.0,
67 padding: Padding::ZERO,
68 width: Length::Fit,
69 height: Length::Fit,
70 align: Alignment::Start,
71 clip: false,
72 children,
73 }
74 }
75
76 pub fn spacing(mut self, amount: impl Into<Pixels>) -> Self {
82 self.spacing = amount.into().0;
83 self
84 }
85
86 pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
88 self.padding = padding.into();
89 self
90 }
91
92 pub fn width(mut self, width: impl Into<Length>) -> Self {
94 self.width = width.into();
95 self
96 }
97
98 pub fn height(mut self, height: impl Into<Length>) -> Self {
100 self.height = height.into();
101 self
102 }
103
104 pub fn align_x(mut self, align: impl Into<alignment::Horizontal>) -> Self {
106 self.align = Alignment::from(align.into());
107 self
108 }
109
110 pub fn clip(mut self, clip: bool) -> Self {
113 self.clip = clip;
114 self
115 }
116
117 pub fn push(mut self, child: W) -> Self
119 where
120 W: Meta,
121 {
122 if !child.is_void() {
123 self.children.push(child);
124 }
125
126 self
127 }
128
129 pub fn extend(self, children: impl IntoIterator<Item = W>) -> Self
131 where
132 W: Meta,
133 {
134 children.into_iter().fold(self, Self::push)
135 }
136
137 pub fn wrap(self) -> Wrapping<W> {
141 Wrapping {
142 column: self,
143 horizontal_spacing: None,
144 align_y: alignment::Vertical::Top,
145 }
146 }
147}
148
149impl<W> Default for Column<W> {
150 fn default() -> Self {
151 Self::new()
152 }
153}
154
155impl<W> FromIterator<W> for Column<W>
156where
157 W: Meta,
158{
159 fn from_iter<T: IntoIterator<Item = W>>(iter: T) -> Self {
160 Self::with_children(iter)
161 }
162}
163
164impl<W> Meta for Column<W> {}
165
166impl<W, Message, Theme, Renderer> Widget<Message, Theme, Renderer> for Column<W>
167where
168 W: Widget<Message, Theme, Renderer>,
169 Renderer: crate::core::Renderer,
170{
171 fn tag(&self) -> tree::Tag {
172 tree::Tag::of::<layout::flex::Cache>()
173 }
174
175 fn state(&self) -> tree::State {
176 tree::State::new(layout::flex::Cache::default())
177 }
178
179 fn diff(&mut self, tree: &mut Tree) {
180 tree.diff_children(&mut self.children);
181
182 if self.width.is_fit() || self.height.is_fit() {
183 for child in &self.children {
184 let size = child.size();
185
186 self.width = self.width.cross(size.width);
187 self.height = self.height.stack(size.height);
188 }
189 }
190 }
191
192 fn size(&self) -> Size<Length> {
193 Size {
194 width: self.width,
195 height: self.height,
196 }
197 }
198
199 fn layout(&mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits) {
200 let cache = tree.state.downcast_mut::<layout::flex::Cache>();
201
202 tree.size = layout::flex::resolve(
203 layout::flex::Axis::Vertical,
204 renderer,
205 limits,
206 self.width,
207 self.height,
208 self.padding,
209 self.spacing,
210 self.align,
211 &mut tree.children,
212 &mut self.children,
213 cache,
214 );
215 }
216
217 fn operate(
218 &mut self,
219 tree: &mut Tree,
220 layout: Layout,
221 viewport: &Rectangle,
222 renderer: &Renderer,
223 operation: &mut dyn Operation,
224 ) {
225 operation.container(None, layout.bounds(), viewport);
226 operation.traverse(&mut |operation| {
227 self.children
228 .iter_mut()
229 .zip(layout.iter_mut(&mut tree.children))
230 .for_each(|(child, (layout, state))| {
231 child.operate(state, layout, viewport, renderer, operation);
232 });
233 });
234 }
235
236 fn update(
237 &mut self,
238 tree: &mut Tree,
239 event: &Event,
240 layout: Layout,
241 cursor: mouse::Cursor,
242 renderer: &Renderer,
243 shell: &mut Shell<'_, Message>,
244 viewport: &Rectangle,
245 ) {
246 for (child, (layout, tree)) in self
247 .children
248 .iter_mut()
249 .zip(layout.iter_mut(&mut tree.children))
250 {
251 child.update(tree, event, layout, cursor, renderer, shell, viewport);
252 }
253 }
254
255 fn mouse_interaction(
256 &self,
257 tree: &Tree,
258 layout: Layout,
259 cursor: mouse::Cursor,
260 viewport: &Rectangle,
261 renderer: &Renderer,
262 ) -> mouse::Interaction {
263 self.children
264 .iter()
265 .zip(layout.iter(&tree.children))
266 .map(|(child, (layout, tree))| {
267 child.mouse_interaction(tree, layout, cursor, viewport, renderer)
268 })
269 .max()
270 .unwrap_or_default()
271 }
272
273 fn draw(
274 &self,
275 tree: &Tree,
276 renderer: &mut Renderer,
277 theme: &Theme,
278 style: &renderer::Style,
279 layout: Layout,
280 cursor: mouse::Cursor,
281 viewport: &Rectangle,
282 ) {
283 if let Some(clipped_viewport) = layout.bounds().intersection(viewport) {
284 let viewport = if self.clip {
285 &clipped_viewport
286 } else {
287 viewport
288 };
289
290 for (child, (layout, tree)) in self
291 .children
292 .iter()
293 .zip(layout.iter(&tree.children))
294 .filter(|(_, (layout, _))| layout.bounds().intersects(viewport))
295 {
296 child.draw(tree, renderer, theme, style, layout, cursor, viewport);
297 }
298 }
299 }
300
301 fn overlay<'b>(
302 &'b mut self,
303 tree: &'b mut Tree,
304 layout: Layout,
305 renderer: &Renderer,
306 viewport: &Rectangle,
307 translation: Vector,
308 window: Size,
309 ) -> Vec<overlay::Element<'b, Message, Theme, Renderer>> {
310 overlay::from_children(
311 &mut self.children,
312 tree,
313 layout,
314 renderer,
315 viewport,
316 translation,
317 window,
318 )
319 }
320}
321
322#[allow(missing_debug_implementations)]
329pub struct Wrapping<W> {
330 column: Column<W>,
331 horizontal_spacing: Option<f32>,
332 align_y: alignment::Vertical,
333}
334
335impl<W> Wrapping<W> {
336 pub fn horizontal_spacing(mut self, amount: impl Into<Pixels>) -> Self {
338 self.horizontal_spacing = Some(amount.into().0);
339 self
340 }
341
342 pub fn align_y(mut self, align_y: impl Into<alignment::Vertical>) -> Self {
344 self.align_y = align_y.into();
345 self
346 }
347}
348
349impl<W> Meta for Wrapping<W> {}
350
351impl<W, Message, Theme, Renderer> Widget<Message, Theme, Renderer> for Wrapping<W>
352where
353 W: Widget<Message, Theme, Renderer>,
354 Renderer: crate::core::Renderer,
355{
356 fn diff(&mut self, tree: &mut Tree) {
357 self.column.diff(tree);
358 }
359
360 fn size(&self) -> Size<Length> {
361 self.column.size()
362 }
363
364 fn layout(&mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits) {
365 let limits = limits
366 .width(self.column.width)
367 .height(self.column.height)
368 .shrink(self.column.padding);
369
370 let child_limits = limits.loose();
371 let spacing = self.column.spacing;
372 let horizontal_spacing = self.horizontal_spacing.unwrap_or(spacing);
373 let max_height = limits.bounds().height;
374
375 let mut intrinsic_size = Size::ZERO;
376 let mut column_start = 0;
377 let mut column_width = 0.0;
378 let mut x = 0.0;
379 let mut y = 0.0;
380
381 let align_factor = match self.column.align {
382 Alignment::Start => 0.0,
383 Alignment::Center => 2.0,
384 Alignment::End => 1.0,
385 };
386
387 let align_x =
388 |column_start: std::ops::Range<usize>, column_width: f32, children: &mut [Tree]| {
389 if align_factor != 0.0 {
390 for child in &mut children[column_start] {
391 let width = child.size.width;
392
393 child.translation.x += (column_width - width) / align_factor;
394 }
395 }
396 };
397
398 for (i, child) in self.column.children.iter_mut().enumerate() {
399 child.layout(&mut tree.children[i], renderer, &child_limits);
400
401 let child_size = tree.children[i].size;
402
403 if y != 0.0 && y + child_size.height > max_height {
404 intrinsic_size.height = intrinsic_size.height.max(y - spacing);
405
406 align_x(column_start..i, column_width, &mut tree.children);
407
408 x += column_width + horizontal_spacing;
409 y = 0.0;
410 column_start = i;
411 column_width = 0.0;
412 }
413
414 column_width = column_width.max(child_size.width);
415
416 tree.children[i].translation =
417 Vector::new(x + self.column.padding.left, y + self.column.padding.top);
418
419 y += child_size.height + spacing;
420 }
421
422 if y != 0.0 {
423 intrinsic_size.height = intrinsic_size.height.max(y - spacing);
424 }
425
426 intrinsic_size.width = x + column_width;
427 align_x(
428 column_start..tree.children.len(),
429 column_width,
430 &mut tree.children,
431 );
432
433 let align_factor = match self.align_y {
434 alignment::Vertical::Top => 0.0,
435 alignment::Vertical::Center => 2.0,
436 alignment::Vertical::Bottom => 1.0,
437 };
438
439 if align_factor != 0.0 {
440 let total_height = intrinsic_size.height;
441
442 let mut column_start = 0;
443
444 for i in 0..tree.children.len() {
445 let column_height = tree.children[i].translation.y + tree.children[i].size.height;
446
447 let next_y = tree
448 .children
449 .get(i + 1)
450 .map(|child| child.translation.y)
451 .unwrap_or_default();
452
453 if next_y == 0.0 {
454 let translation =
455 Vector::new(0.0, (total_height - column_height) / align_factor);
456
457 for child in &mut tree.children[column_start..=i] {
458 child.translation += translation;
459 }
460
461 column_start = i + 1;
462 }
463 }
464 }
465
466 let size = limits.resolve(self.column.width, self.column.height, intrinsic_size);
467
468 tree.size = size.expand(self.column.padding);
469 }
470
471 fn operate(
472 &mut self,
473 tree: &mut Tree,
474 layout: Layout,
475 viewport: &Rectangle,
476 renderer: &Renderer,
477 operation: &mut dyn Operation,
478 ) {
479 self.column
480 .operate(tree, layout, viewport, renderer, operation);
481 }
482
483 fn update(
484 &mut self,
485 tree: &mut Tree,
486 event: &Event,
487 layout: Layout,
488 cursor: mouse::Cursor,
489 renderer: &Renderer,
490 shell: &mut Shell<'_, Message>,
491 viewport: &Rectangle,
492 ) {
493 self.column
494 .update(tree, event, layout, cursor, renderer, shell, viewport);
495 }
496
497 fn mouse_interaction(
498 &self,
499 tree: &Tree,
500 layout: Layout,
501 cursor: mouse::Cursor,
502 viewport: &Rectangle,
503 renderer: &Renderer,
504 ) -> mouse::Interaction {
505 self.column
506 .mouse_interaction(tree, layout, cursor, viewport, renderer)
507 }
508
509 fn draw(
510 &self,
511 tree: &Tree,
512 renderer: &mut Renderer,
513 theme: &Theme,
514 style: &renderer::Style,
515 layout: Layout,
516 cursor: mouse::Cursor,
517 viewport: &Rectangle,
518 ) {
519 self.column
520 .draw(tree, renderer, theme, style, layout, cursor, viewport);
521 }
522
523 fn overlay<'b>(
524 &'b mut self,
525 tree: &'b mut Tree,
526 layout: Layout,
527 renderer: &Renderer,
528 viewport: &Rectangle,
529 translation: Vector,
530 window: Size,
531 ) -> Vec<overlay::Element<'b, Message, Theme, Renderer>> {
532 self.column
533 .overlay(tree, layout, renderer, viewport, translation, window)
534 }
535}