1use iced_core::{
5 Alignment, Clipboard, Element, Event, Layout, Length, Padding, Pixels, Point, Rectangle, Shell,
6 Size, Vector, Widget,
7 layout::{Limits, Node},
8 mouse::{self, Cursor},
9 overlay, renderer,
10 widget::{Operation, Tree},
11};
12use std::marker::PhantomData;
13
14#[allow(missing_debug_implementations)]
16pub struct Wrap<
17 'a,
18 Message,
19 Direction,
20 Theme = iced_widget::Theme,
21 Renderer = iced_widget::Renderer,
22> {
23 pub elements: Vec<Element<'a, Message, Theme, Renderer>>,
25 pub alignment: Alignment,
27 pub width: Length,
29 pub height: Length,
31 pub max_width: f32,
33 pub max_height: f32,
35 pub padding: Padding,
37 pub spacing: Pixels,
39 pub line_spacing: Pixels,
41 pub line_minimal_length: f32,
43 #[allow(clippy::missing_docs_in_private_items)]
44 _direction: PhantomData<Direction>,
45}
46
47impl<'a, Message, Theme, Renderer> Wrap<'a, Message, direction::Horizontal, Theme, Renderer> {
48 #[must_use]
50 pub fn new() -> Self {
51 Self::with_elements(Vec::new())
52 }
53
54 #[must_use]
59 pub fn with_elements(elements: Vec<Element<'a, Message, Theme, Renderer>>) -> Self {
60 Self {
61 elements,
62 ..Wrap::default()
63 }
64 }
65}
66
67impl<'a, Message, Theme, Renderer> Wrap<'a, Message, direction::Vertical, Theme, Renderer> {
68 #[must_use]
70 pub fn new_vertical() -> Self {
71 Self::with_elements_vertical(Vec::new())
72 }
73
74 #[must_use]
79 pub fn with_elements_vertical(elements: Vec<Element<'a, Message, Theme, Renderer>>) -> Self {
80 Self {
81 elements,
82 ..Wrap::default()
83 }
84 }
85}
86
87impl<'a, Message, Renderer, Direction, Theme> Wrap<'a, Message, Direction, Theme, Renderer> {
88 #[must_use]
90 pub fn spacing(mut self, spacing: impl Into<Pixels>) -> Self {
91 self.spacing = spacing.into();
92 self
93 }
94
95 #[must_use]
97 pub fn line_spacing(mut self, spacing: impl Into<Pixels>) -> Self {
98 self.line_spacing = spacing.into();
99 self
100 }
101
102 #[must_use]
104 pub const fn line_minimal_length(mut self, units: f32) -> Self {
105 self.line_minimal_length = units;
106 self
107 }
108
109 #[must_use]
111 pub fn padding(mut self, padding: impl Into<Padding>) -> Self {
112 self.padding = padding.into();
113 self
114 }
115
116 #[must_use]
118 pub const fn width_items(mut self, width: Length) -> Self {
119 self.width = width;
120 self
121 }
122
123 #[must_use]
125 pub const fn height_items(mut self, height: Length) -> Self {
126 self.height = height;
127 self
128 }
129
130 #[must_use]
132 pub const fn max_width(mut self, max_width: f32) -> Self {
133 self.max_width = max_width;
134 self
135 }
136
137 #[must_use]
139 pub const fn max_height(mut self, max_height: f32) -> Self {
140 self.max_height = max_height;
141 self
142 }
143
144 #[must_use]
146 pub const fn align_items(mut self, align: Alignment) -> Self {
147 self.alignment = align;
148 self
149 }
150
151 #[must_use]
153 pub fn push<E>(mut self, element: E) -> Self
154 where
155 E: Into<Element<'a, Message, Theme, Renderer>>,
156 {
157 self.elements.push(element.into());
158 self
159 }
160}
161
162impl<Message, Renderer, Direction, Theme> Widget<Message, Theme, Renderer>
163 for Wrap<'_, Message, Direction, Theme, Renderer>
164where
165 Self: WrapLayout<Renderer>,
166 Renderer: renderer::Renderer,
167{
168 fn children(&self) -> Vec<Tree> {
169 self.elements.iter().map(Tree::new).collect()
170 }
171
172 fn diff(&self, tree: &mut Tree) {
173 tree.diff_children(&self.elements);
174 }
175
176 fn size(&self) -> Size<Length> {
177 Size::new(self.width, self.height)
178 }
179
180 fn layout(&mut self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node {
181 self.inner_layout(tree, renderer, limits)
182 }
183
184 fn update(
185 &mut self,
186 state: &mut Tree,
187 event: &Event,
188 layout: Layout<'_>,
189 cursor: Cursor,
190 renderer: &Renderer,
191 clipboard: &mut dyn Clipboard,
192 shell: &mut Shell<Message>,
193 viewport: &Rectangle,
194 ) {
195 self.elements
196 .iter_mut()
197 .zip(&mut state.children)
198 .zip(layout.children())
199 .for_each(|((child, state), layout)| {
200 child.as_widget_mut().update(
201 state, event, layout, cursor, renderer, clipboard, shell, viewport,
202 );
203 });
204 }
205
206 fn overlay<'b>(
207 &'b mut self,
208 tree: &'b mut Tree,
209 layout: Layout<'b>,
210 renderer: &Renderer,
211 viewport: &Rectangle,
212 translation: Vector,
213 ) -> Option<overlay::Element<'b, Message, Theme, Renderer>> {
214 self.elements
215 .iter_mut()
216 .zip(&mut tree.children)
217 .zip(layout.children())
218 .find_map(|((child, state), layout)| {
219 child
220 .as_widget_mut()
221 .overlay(state, layout, renderer, viewport, translation)
222 })
223 }
224
225 fn mouse_interaction(
226 &self,
227 state: &Tree,
228 layout: Layout<'_>,
229 cursor: Cursor,
230 viewport: &Rectangle,
231 renderer: &Renderer,
232 ) -> mouse::Interaction {
233 self.elements
234 .iter()
235 .zip(&state.children)
236 .zip(layout.children())
237 .map(|((child, state), layout)| {
238 child
239 .as_widget()
240 .mouse_interaction(state, layout, cursor, viewport, renderer)
241 })
242 .max()
243 .unwrap_or_default()
244 }
245
246 fn draw(
247 &self,
248 state: &Tree,
249 renderer: &mut Renderer,
250 theme: &Theme,
251 style: &renderer::Style,
252 layout: Layout<'_>,
253 cursor: Cursor,
254 viewport: &Rectangle,
255 ) {
256 for ((child, state), layout) in self
257 .elements
258 .iter()
259 .zip(&state.children)
260 .zip(layout.children())
261 {
262 child
263 .as_widget()
264 .draw(state, renderer, theme, style, layout, cursor, viewport);
265 }
266 }
267
268 fn operate(
269 &mut self,
270 state: &mut Tree,
271 layout: Layout<'_>,
272 renderer: &Renderer,
273 operation: &mut dyn Operation<()>,
274 ) {
275 for ((element, state), layout) in self
276 .elements
277 .iter_mut()
278 .zip(&mut state.children)
279 .zip(layout.children())
280 {
281 element
282 .as_widget_mut()
283 .operate(state, layout, renderer, operation);
284 }
285 }
286}
287
288impl<'a, Message, Theme, Renderer> From<Wrap<'a, Message, direction::Vertical, Theme, Renderer>>
289 for Element<'a, Message, Theme, Renderer>
290where
291 Renderer: 'a + renderer::Renderer,
292 Message: 'a,
293 Theme: 'a,
294{
295 fn from(wrap: Wrap<'a, Message, direction::Vertical, Theme, Renderer>) -> Self {
296 Element::new(wrap)
297 }
298}
299
300impl<'a, Message, Theme, Renderer> From<Wrap<'a, Message, direction::Horizontal, Theme, Renderer>>
301 for Element<'a, Message, Theme, Renderer>
302where
303 Renderer: 'a + renderer::Renderer,
304 Message: 'a,
305 Theme: 'a,
306{
307 fn from(wrap: Wrap<'a, Message, direction::Horizontal, Theme, Renderer>) -> Self {
308 Element::new(wrap)
309 }
310}
311
312impl<Message, Renderer, Direction, Theme> Default
313 for Wrap<'_, Message, Direction, Theme, Renderer>
314{
315 fn default() -> Self {
316 Self {
317 elements: vec![],
318 alignment: Alignment::Start,
319 width: Length::Shrink,
320 height: Length::Shrink,
321 max_width: 4_294_967_295.0,
322 max_height: 4_294_967_295.0,
323 padding: Padding::ZERO,
324 spacing: Pixels::ZERO,
325 line_spacing: Pixels::ZERO,
326 line_minimal_length: 10.0,
327 _direction: PhantomData,
328 }
329 }
330}
331pub trait WrapLayout<Renderer>
333where
334 Renderer: renderer::Renderer,
335{
336 fn inner_layout(&mut self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node;
338}
339
340impl<'a, Message, Theme, Renderer> WrapLayout<Renderer>
341 for Wrap<'a, Message, direction::Horizontal, Theme, Renderer>
342where
343 Renderer: renderer::Renderer + 'a,
344{
345 #[allow(clippy::inline_always)]
346 #[inline(always)]
347 fn inner_layout(&mut self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node {
348 let padding = self.padding;
349 let spacing = self.spacing;
350 let line_spacing = self.line_spacing;
351 #[allow(clippy::cast_precision_loss)] let line_minimal_length = self.line_minimal_length;
353 let limits = limits
354 .shrink(padding)
355 .width(self.width)
356 .height(self.height)
357 .max_width(self.max_width)
358 .max_height(self.max_height);
359 let max_width = limits.max().width;
360
361 let mut children = tree.children.iter_mut();
362 let mut curse = padding.left;
363 let mut deep_curse = padding.left;
364 let mut current_line_height = line_minimal_length;
365 let mut max_main = curse;
366 let mut align = vec![];
367 let mut start = 0;
368 let mut end = 0;
369 let mut nodes: Vec<Node> = self
370 .elements
371 .iter_mut()
372 .map(|elem| {
373 let node_limit = Limits::new(
374 Size::new(limits.min().width, line_minimal_length),
375 limits.max(),
376 );
377 let mut node = elem.as_widget_mut().layout(
378 children.next().expect("wrap missing expected child"),
379 renderer,
380 &node_limit,
381 );
382
383 let size = node.size();
384
385 let offset_init = size.width + spacing.0;
386 let offset = curse + offset_init;
387
388 if offset > max_width {
389 deep_curse += current_line_height + line_spacing.0;
390 align.push((start..end, current_line_height));
391 start = end;
392 end += 1;
393 current_line_height = line_minimal_length;
394 node.move_to_mut(Point::new(padding.left, deep_curse));
395 curse = offset_init + padding.left;
396 } else {
397 node.move_to_mut(Point::new(curse, deep_curse));
398 curse = offset;
399 end += 1;
400 }
401 current_line_height = current_line_height.max(size.height);
402 max_main = max_main.max(curse);
403
404 node
405 })
406 .collect();
407 if end != start {
408 align.push((start..end, current_line_height));
409 }
410 for (range, max_length) in align {
411 nodes[range].iter_mut().for_each(|node| {
412 let size = node.size();
413 let space = Size::new(size.width, max_length);
414 node.align_mut(Alignment::Start, self.alignment, space);
415 });
416 }
417 let (width, height) = (
418 max_main - padding.left,
419 deep_curse - padding.left + current_line_height,
420 );
421 let size = limits.resolve(self.width, self.height, Size::new(width, height));
422
423 Node::with_children(size.expand(padding), nodes)
424 }
425}
426
427impl<'a, Message, Theme, Renderer> WrapLayout<Renderer>
428 for Wrap<'a, Message, direction::Vertical, Theme, Renderer>
429where
430 Renderer: renderer::Renderer + 'a,
431{
432 #[allow(clippy::inline_always)]
433 #[inline(always)]
434 fn inner_layout(&mut self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node {
435 let padding = self.padding;
436 let spacing = self.spacing;
437 let line_spacing = self.line_spacing;
438 #[allow(clippy::cast_precision_loss)] let line_minimal_length = self.line_minimal_length;
440 let limits = limits
441 .shrink(padding)
442 .width(self.width)
443 .height(self.height)
444 .max_width(self.max_width)
445 .max_height(self.max_height);
446 let max_height = limits.max().height;
447
448 let mut children = tree.children.iter_mut();
449 let mut curse = padding.left;
450 let mut wide_curse = padding.left;
451 let mut current_line_width = line_minimal_length;
452 let mut max_main = curse;
453 let mut align = vec![];
454 let mut start = 0;
455 let mut end = 0;
456 let mut nodes: Vec<Node> = self
457 .elements
458 .iter_mut()
459 .map(|elem| {
460 let node_limit = Limits::new(
461 Size::new(line_minimal_length, limits.min().height),
462 limits.max(),
463 );
464 let mut node = elem.as_widget_mut().layout(
465 children.next().expect("wrap missing expected child"),
466 renderer,
467 &node_limit,
468 );
469
470 let size = node.size();
471
472 let offset_init = size.height + spacing.0;
473 let offset = curse + offset_init;
474
475 if offset > max_height {
476 wide_curse += current_line_width + line_spacing.0;
477 align.push((start..end, current_line_width));
478 start = end;
479 end += 1;
480 current_line_width = line_minimal_length;
481 node = node.move_to(Point::new(wide_curse, padding.left));
482 curse = offset_init + padding.left;
483 } else {
484 node = node.move_to(Point::new(wide_curse, curse));
485 end += 1;
486 curse = offset;
487 }
488 current_line_width = current_line_width.max(size.width);
489 max_main = max_main.max(curse);
490
491 node
492 })
493 .collect();
494 if end != start {
495 align.push((start..end, current_line_width));
496 }
497
498 for (range, max_length) in align {
499 nodes[range].iter_mut().for_each(|node| {
500 let size = node.size();
501 let space = Size::new(max_length, size.height);
502 node.align_mut(self.alignment, Alignment::Start, space);
503 });
504 }
505
506 let (width, height) = (
507 wide_curse - padding.left + current_line_width,
508 max_main - padding.left,
509 );
510 let size = limits.resolve(self.width, self.height, Size::new(width, height));
511
512 Node::with_children(size.expand(padding), nodes)
513 }
514}
515
516pub mod direction {
518 #[derive(Debug)]
520 pub struct Vertical;
521 #[derive(Debug)]
523 pub struct Horizontal;
524}
525
526#[cfg(test)]
527#[allow(clippy::float_cmp)]
528mod tests {
529 use super::*;
530
531 #[derive(Clone)]
532 enum TestMessage {}
533
534 type TestWrapHorizontal<'a> =
535 Wrap<'a, TestMessage, direction::Horizontal, iced_widget::Theme, iced_widget::Renderer>;
536 type TestWrapVertical<'a> =
537 Wrap<'a, TestMessage, direction::Vertical, iced_widget::Theme, iced_widget::Renderer>;
538
539 #[test]
544 fn wrap_horizontal_new_creates_empty_wrap() {
545 let wrap = TestWrapHorizontal::new();
546 assert_eq!(wrap.elements.len(), 0);
547 }
548
549 #[test]
550 fn wrap_horizontal_new_has_default_values() {
551 let wrap = TestWrapHorizontal::new();
552
553 assert_eq!(wrap.elements.len(), 0);
554 assert_eq!(wrap.alignment, Alignment::Start);
555 assert_eq!(wrap.width, Length::Shrink);
556 assert_eq!(wrap.height, Length::Shrink);
557 assert_eq!(wrap.max_width, 4_294_967_295.0);
558 assert_eq!(wrap.max_height, 4_294_967_295.0);
559 assert_eq!(wrap.padding, Padding::ZERO);
560 assert_eq!(wrap.spacing, Pixels::ZERO);
561 assert_eq!(wrap.line_spacing, Pixels::ZERO);
562 assert_eq!(wrap.line_minimal_length, 10.0);
563 }
564
565 #[test]
566 fn wrap_horizontal_with_elements_creates_wrap_with_elements() {
567 let elements: Vec<Element<TestMessage, iced_widget::Theme, iced_widget::Renderer>> =
568 vec![iced_widget::text::Text::new("Test").into()];
569 let wrap = TestWrapHorizontal::with_elements(elements);
570 assert_eq!(wrap.elements.len(), 1);
571 }
572
573 #[test]
574 fn wrap_horizontal_with_elements_empty_vec() {
575 let elements: Vec<Element<TestMessage, iced_widget::Theme, iced_widget::Renderer>> = vec![];
576 let wrap = TestWrapHorizontal::with_elements(elements);
577 assert_eq!(wrap.elements.len(), 0);
578 }
579
580 #[test]
585 fn wrap_vertical_new_creates_empty_wrap() {
586 let wrap = TestWrapVertical::new_vertical();
587 assert_eq!(wrap.elements.len(), 0);
588 }
589
590 #[test]
591 fn wrap_vertical_new_has_default_values() {
592 let wrap = TestWrapVertical::new_vertical();
593
594 assert_eq!(wrap.elements.len(), 0);
595 assert_eq!(wrap.alignment, Alignment::Start);
596 assert_eq!(wrap.width, Length::Shrink);
597 assert_eq!(wrap.height, Length::Shrink);
598 assert_eq!(wrap.max_width, 4_294_967_295.0);
599 assert_eq!(wrap.max_height, 4_294_967_295.0);
600 assert_eq!(wrap.padding, Padding::ZERO);
601 assert_eq!(wrap.spacing, Pixels::ZERO);
602 assert_eq!(wrap.line_spacing, Pixels::ZERO);
603 assert_eq!(wrap.line_minimal_length, 10.0);
604 }
605
606 #[test]
607 fn wrap_vertical_with_elements_creates_wrap_with_elements() {
608 let elements: Vec<Element<TestMessage, iced_widget::Theme, iced_widget::Renderer>> =
609 vec![iced_widget::text::Text::new("Test").into()];
610 let wrap = TestWrapVertical::with_elements_vertical(elements);
611 assert_eq!(wrap.elements.len(), 1);
612 }
613
614 #[test]
615 fn wrap_vertical_with_elements_empty_vec() {
616 let elements: Vec<Element<TestMessage, iced_widget::Theme, iced_widget::Renderer>> = vec![];
617 let wrap = TestWrapVertical::with_elements_vertical(elements);
618 assert_eq!(wrap.elements.len(), 0);
619 }
620
621 #[test]
626 fn wrap_horizontal_push_adds_element() {
627 let wrap = TestWrapHorizontal::new().push(iced_widget::text::Text::new("Test"));
628 assert_eq!(wrap.elements.len(), 1);
629 }
630
631 #[test]
632 fn wrap_horizontal_push_multiple_elements() {
633 let wrap = TestWrapHorizontal::new()
634 .push(iced_widget::text::Text::new("First"))
635 .push(iced_widget::text::Text::new("Second"))
636 .push(iced_widget::text::Text::new("Third"));
637 assert_eq!(wrap.elements.len(), 3);
638 }
639
640 #[test]
641 fn wrap_vertical_push_adds_element() {
642 let wrap = TestWrapVertical::new_vertical().push(iced_widget::text::Text::new("Test"));
643 assert_eq!(wrap.elements.len(), 1);
644 }
645
646 #[test]
647 fn wrap_vertical_push_multiple_elements() {
648 let wrap = TestWrapVertical::new_vertical()
649 .push(iced_widget::text::Text::new("First"))
650 .push(iced_widget::text::Text::new("Second"))
651 .push(iced_widget::text::Text::new("Third"));
652 assert_eq!(wrap.elements.len(), 3);
653 }
654
655 #[test]
660 fn wrap_horizontal_spacing_sets_value() {
661 let wrap = TestWrapHorizontal::new().spacing(10.0);
662 assert_eq!(wrap.spacing, Pixels(10.0));
663 }
664
665 #[test]
666 fn wrap_horizontal_spacing_zero_sets_value() {
667 let wrap = TestWrapHorizontal::new().spacing(0.0);
668 assert_eq!(wrap.spacing, Pixels::ZERO);
669 }
670
671 #[test]
672 fn wrap_vertical_spacing_sets_value() {
673 let wrap = TestWrapVertical::new_vertical().spacing(15.0);
674 assert_eq!(wrap.spacing, Pixels(15.0));
675 }
676
677 #[test]
682 fn wrap_horizontal_line_spacing_sets_value() {
683 let wrap = TestWrapHorizontal::new().line_spacing(20.0);
684 assert_eq!(wrap.line_spacing, Pixels(20.0));
685 }
686
687 #[test]
688 fn wrap_horizontal_line_spacing_zero_sets_value() {
689 let wrap = TestWrapHorizontal::new().line_spacing(0.0);
690 assert_eq!(wrap.line_spacing, Pixels::ZERO);
691 }
692
693 #[test]
694 fn wrap_vertical_line_spacing_sets_value() {
695 let wrap = TestWrapVertical::new_vertical().line_spacing(25.0);
696 assert_eq!(wrap.line_spacing, Pixels(25.0));
697 }
698
699 #[test]
704 fn wrap_horizontal_line_minimal_length_sets_value() {
705 let wrap = TestWrapHorizontal::new().line_minimal_length(50.0);
706 assert_eq!(wrap.line_minimal_length, 50.0);
707 }
708
709 #[test]
710 fn wrap_horizontal_line_minimal_length_default_is_10() {
711 let wrap = TestWrapHorizontal::new();
712 assert_eq!(wrap.line_minimal_length, 10.0);
713 }
714
715 #[test]
716 fn wrap_vertical_line_minimal_length_sets_value() {
717 let wrap = TestWrapVertical::new_vertical().line_minimal_length(100.0);
718 assert_eq!(wrap.line_minimal_length, 100.0);
719 }
720
721 #[test]
726 fn wrap_horizontal_padding_sets_value() {
727 let wrap = TestWrapHorizontal::new().padding(10);
728 assert_eq!(wrap.padding, Padding::new(10.0));
729 }
730
731 #[test]
732 fn wrap_horizontal_padding_default_is_zero() {
733 let wrap = TestWrapHorizontal::new();
734 assert_eq!(wrap.padding, Padding::ZERO);
735 }
736
737 #[test]
738 fn wrap_horizontal_padding_with_padding_struct() {
739 let padding = Padding {
740 top: 5.0,
741 right: 10.0,
742 bottom: 15.0,
743 left: 20.0,
744 };
745 let wrap = TestWrapHorizontal::new().padding(padding);
746 assert_eq!(wrap.padding, padding);
747 }
748
749 #[test]
750 fn wrap_vertical_padding_sets_value() {
751 let wrap = TestWrapVertical::new_vertical().padding(12);
752 assert_eq!(wrap.padding, Padding::new(12.0));
753 }
754
755 #[test]
760 fn wrap_horizontal_width_items_sets_value() {
761 let wrap = TestWrapHorizontal::new().width_items(Length::Fill);
762 assert_eq!(wrap.width, Length::Fill);
763 }
764
765 #[test]
766 fn wrap_horizontal_width_items_default_is_shrink() {
767 let wrap = TestWrapHorizontal::new();
768 assert_eq!(wrap.width, Length::Shrink);
769 }
770
771 #[test]
772 fn wrap_horizontal_width_items_fixed() {
773 let wrap = TestWrapHorizontal::new().width_items(Length::Fixed(200.0));
774 assert_eq!(wrap.width, Length::Fixed(200.0));
775 }
776
777 #[test]
778 fn wrap_vertical_width_items_sets_value() {
779 let wrap = TestWrapVertical::new_vertical().width_items(Length::Fill);
780 assert_eq!(wrap.width, Length::Fill);
781 }
782
783 #[test]
788 fn wrap_horizontal_height_items_sets_value() {
789 let wrap = TestWrapHorizontal::new().height_items(Length::Fill);
790 assert_eq!(wrap.height, Length::Fill);
791 }
792
793 #[test]
794 fn wrap_horizontal_height_items_default_is_shrink() {
795 let wrap = TestWrapHorizontal::new();
796 assert_eq!(wrap.height, Length::Shrink);
797 }
798
799 #[test]
800 fn wrap_horizontal_height_items_fixed() {
801 let wrap = TestWrapHorizontal::new().height_items(Length::Fixed(150.0));
802 assert_eq!(wrap.height, Length::Fixed(150.0));
803 }
804
805 #[test]
806 fn wrap_vertical_height_items_sets_value() {
807 let wrap = TestWrapVertical::new_vertical().height_items(Length::Fill);
808 assert_eq!(wrap.height, Length::Fill);
809 }
810
811 #[test]
816 fn wrap_horizontal_max_width_sets_value() {
817 let wrap = TestWrapHorizontal::new().max_width(500.0);
818 assert_eq!(wrap.max_width, 500.0);
819 }
820
821 #[test]
822 fn wrap_horizontal_max_width_default() {
823 let wrap = TestWrapHorizontal::new();
824 assert_eq!(wrap.max_width, 4_294_967_295.0);
825 }
826
827 #[test]
828 fn wrap_vertical_max_width_sets_value() {
829 let wrap = TestWrapVertical::new_vertical().max_width(600.0);
830 assert_eq!(wrap.max_width, 600.0);
831 }
832
833 #[test]
838 fn wrap_horizontal_max_height_sets_value() {
839 let wrap = TestWrapHorizontal::new().max_height(400.0);
840 assert_eq!(wrap.max_height, 400.0);
841 }
842
843 #[test]
844 fn wrap_horizontal_max_height_default() {
845 let wrap = TestWrapHorizontal::new();
846 assert_eq!(wrap.max_height, 4_294_967_295.0);
847 }
848
849 #[test]
850 fn wrap_vertical_max_height_sets_value() {
851 let wrap = TestWrapVertical::new_vertical().max_height(300.0);
852 assert_eq!(wrap.max_height, 300.0);
853 }
854
855 #[test]
860 fn wrap_horizontal_align_items_start() {
861 let wrap = TestWrapHorizontal::new().align_items(Alignment::Start);
862 assert_eq!(wrap.alignment, Alignment::Start);
863 }
864
865 #[test]
866 fn wrap_horizontal_align_items_center() {
867 let wrap = TestWrapHorizontal::new().align_items(Alignment::Center);
868 assert_eq!(wrap.alignment, Alignment::Center);
869 }
870
871 #[test]
872 fn wrap_horizontal_align_items_end() {
873 let wrap = TestWrapHorizontal::new().align_items(Alignment::End);
874 assert_eq!(wrap.alignment, Alignment::End);
875 }
876
877 #[test]
878 fn wrap_horizontal_align_items_default_is_start() {
879 let wrap = TestWrapHorizontal::new();
880 assert_eq!(wrap.alignment, Alignment::Start);
881 }
882
883 #[test]
884 fn wrap_vertical_align_items_center() {
885 let wrap = TestWrapVertical::new_vertical().align_items(Alignment::Center);
886 assert_eq!(wrap.alignment, Alignment::Center);
887 }
888
889 #[test]
894 fn wrap_horizontal_chaining_all_methods() {
895 let wrap = TestWrapHorizontal::new()
896 .push(iced_widget::text::Text::new("Test"))
897 .spacing(5.0)
898 .line_spacing(10.0)
899 .line_minimal_length(20.0)
900 .padding(15)
901 .width_items(Length::Fill)
902 .height_items(Length::Shrink)
903 .max_width(800.0)
904 .max_height(600.0)
905 .align_items(Alignment::Center);
906
907 assert_eq!(wrap.elements.len(), 1);
908 assert_eq!(wrap.spacing, Pixels(5.0));
909 assert_eq!(wrap.line_spacing, Pixels(10.0));
910 assert_eq!(wrap.line_minimal_length, 20.0);
911 assert_eq!(wrap.padding, Padding::new(15.0));
912 assert_eq!(wrap.width, Length::Fill);
913 assert_eq!(wrap.height, Length::Shrink);
914 assert_eq!(wrap.max_width, 800.0);
915 assert_eq!(wrap.max_height, 600.0);
916 assert_eq!(wrap.alignment, Alignment::Center);
917 }
918
919 #[test]
920 fn wrap_vertical_chaining_all_methods() {
921 let wrap = TestWrapVertical::new_vertical()
922 .push(iced_widget::text::Text::new("Test"))
923 .spacing(8.0)
924 .line_spacing(12.0)
925 .line_minimal_length(25.0)
926 .padding(20)
927 .width_items(Length::Shrink)
928 .height_items(Length::Fill)
929 .max_width(700.0)
930 .max_height(500.0)
931 .align_items(Alignment::End);
932
933 assert_eq!(wrap.elements.len(), 1);
934 assert_eq!(wrap.spacing, Pixels(8.0));
935 assert_eq!(wrap.line_spacing, Pixels(12.0));
936 assert_eq!(wrap.line_minimal_length, 25.0);
937 assert_eq!(wrap.padding, Padding::new(20.0));
938 assert_eq!(wrap.width, Length::Shrink);
939 assert_eq!(wrap.height, Length::Fill);
940 assert_eq!(wrap.max_width, 700.0);
941 assert_eq!(wrap.max_height, 500.0);
942 assert_eq!(wrap.alignment, Alignment::End);
943 }
944
945 #[test]
950 fn wrap_horizontal_size_method_returns_correct_size() {
951 let wrap = TestWrapHorizontal::new()
952 .width_items(Length::Fixed(100.0))
953 .height_items(Length::Fixed(50.0));
954
955 let size = Widget::<TestMessage, iced_widget::Theme, iced_widget::Renderer>::size(&wrap);
956 assert_eq!(size.width, Length::Fixed(100.0));
957 assert_eq!(size.height, Length::Fixed(50.0));
958 }
959
960 #[test]
961 fn wrap_vertical_size_method_returns_correct_size() {
962 let wrap = TestWrapVertical::new_vertical()
963 .width_items(Length::Fill)
964 .height_items(Length::Shrink);
965
966 let size = Widget::<TestMessage, iced_widget::Theme, iced_widget::Renderer>::size(&wrap);
967 assert_eq!(size.width, Length::Fill);
968 assert_eq!(size.height, Length::Shrink);
969 }
970
971 #[test]
976 fn wrap_horizontal_default_creates_empty_wrap_with_defaults() {
977 let wrap: TestWrapHorizontal = Wrap::default();
978
979 assert_eq!(wrap.elements.len(), 0);
980 assert_eq!(wrap.alignment, Alignment::Start);
981 assert_eq!(wrap.width, Length::Shrink);
982 assert_eq!(wrap.height, Length::Shrink);
983 assert_eq!(wrap.max_width, 4_294_967_295.0);
984 assert_eq!(wrap.max_height, 4_294_967_295.0);
985 assert_eq!(wrap.padding, Padding::ZERO);
986 assert_eq!(wrap.spacing, Pixels::ZERO);
987 assert_eq!(wrap.line_spacing, Pixels::ZERO);
988 assert_eq!(wrap.line_minimal_length, 10.0);
989 }
990
991 #[test]
992 fn wrap_vertical_default_creates_empty_wrap_with_defaults() {
993 let wrap: TestWrapVertical = Wrap::default();
994
995 assert_eq!(wrap.elements.len(), 0);
996 assert_eq!(wrap.alignment, Alignment::Start);
997 assert_eq!(wrap.width, Length::Shrink);
998 assert_eq!(wrap.height, Length::Shrink);
999 assert_eq!(wrap.max_width, 4_294_967_295.0);
1000 assert_eq!(wrap.max_height, 4_294_967_295.0);
1001 assert_eq!(wrap.padding, Padding::ZERO);
1002 assert_eq!(wrap.spacing, Pixels::ZERO);
1003 assert_eq!(wrap.line_spacing, Pixels::ZERO);
1004 assert_eq!(wrap.line_minimal_length, 10.0);
1005 }
1006}