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