1use sequoia_core::{Color, Constraints, Edges, Length, Rect, Size};
2use sequoia_layout::{
3 Align, Axis, ContainerStyle, GridFlow, GridPlacement, GridStyle, Indents, Inset, Justify,
4 LayoutCtx, LayoutStyle, MasonryStyle, Overflow, Position, Track, WrapStyle,
5};
6use sequoia_style::{BoxStyle, TextStyle};
7use sequoia_text::{
8 ElideMode, FontStyle, FontWeight, LetterSpacing, LineHeight, TextVAlign, WrapMode,
9};
10
11use crate::any::AnyView;
12use crate::runtime::{ElementId, Runtime};
13use crate::view::{PaintCtx, View};
14
15pub(crate) fn text_wrap_limit(style: LayoutStyle, available: f32) -> Option<f32> {
16 let outer = match style.width {
17 Length::Px(px) => px,
18 Length::Percent(percent) if available.is_finite() => available * percent / 100.0,
19 Length::Fill(_) | Length::Fit if available.is_finite() => available,
20 _ => f32::INFINITY,
21 };
22 let limit =
23 outer.min(style.max_width).max(style.min_width).max(0.0) - style.padding.horizontal_sum();
24 (limit.is_finite() && limit > 0.0).then_some(limit)
25}
26
27macro_rules! impl_style_extras {
28 ($name:ident) => {
29 impl $name {
30 pub fn margin(mut self, margin: impl Into<Edges>) -> Self {
31 self.style = self.style.margin(margin);
32 self
33 }
34
35 pub fn margin_xy(mut self, x: f32, y: f32) -> Self {
36 self.style = self.style.margin_xy(x, y);
37 self
38 }
39
40 pub fn margin_x(mut self, x: f32) -> Self {
41 self.style = self.style.margin_x(x);
42 self
43 }
44
45 pub fn margin_y(mut self, y: f32) -> Self {
46 self.style = self.style.margin_y(y);
47 self
48 }
49
50 pub fn margin_left(mut self, v: f32) -> Self {
51 self.style = self.style.margin_left(v);
52 self
53 }
54
55 pub fn margin_right(mut self, v: f32) -> Self {
56 self.style = self.style.margin_right(v);
57 self
58 }
59
60 pub fn margin_top(mut self, v: f32) -> Self {
61 self.style = self.style.margin_top(v);
62 self
63 }
64
65 pub fn margin_bottom(mut self, v: f32) -> Self {
66 self.style = self.style.margin_bottom(v);
67 self
68 }
69
70 pub fn indent_top(mut self, v: f32) -> Self {
71 self.style = self.style.indent_top(v);
72 self
73 }
74
75 pub fn indent_bottom(mut self, v: f32) -> Self {
76 self.style = self.style.indent_bottom(v);
77 self
78 }
79
80 pub fn indent_left(mut self, v: f32) -> Self {
81 self.style = self.style.indent_left(v);
82 self
83 }
84
85 pub fn indent_right(mut self, v: f32) -> Self {
86 self.style = self.style.indent_right(v);
87 self
88 }
89
90 pub fn clear_indents(mut self) -> Self {
91 self.style = self.style.clear_indents();
92 self
93 }
94
95 pub fn indent(mut self, indents: Indents) -> Self {
96 self.style = self.style.indent(indents);
97 self
98 }
99
100 pub fn indent_all(mut self, v: f32) -> Self {
101 self.style = self.style.indent_all(v);
102 self
103 }
104
105 pub fn indent_xy(mut self, x: f32, y: f32) -> Self {
106 self.style = self.style.indent_xy(x, y);
107 self
108 }
109
110 pub fn indent_axes(mut self, horizontal: f32, vertical: f32) -> Self {
111 self.style = self.style.indent_axes(horizontal, vertical);
112 self
113 }
114
115 pub fn flex_grow(mut self, weight: f32) -> Self {
116 self.style = self.style.flex_grow(weight);
117 self
118 }
119
120 pub fn flex_shrink(mut self, shrink: f32) -> Self {
121 self.style = self.style.flex_shrink(shrink);
122 self
123 }
124
125 pub fn flex_basis(mut self, basis: Option<Length>) -> Self {
126 self.style = self.style.flex_basis(basis);
127 self
128 }
129
130 pub fn align_self(mut self, align: Option<Align>) -> Self {
131 self.style = self.style.align_self(align);
132 self
133 }
134
135 pub fn align_self_value(mut self, align: Align) -> Self {
136 self.style = self.style.align_self_value(align);
137 self
138 }
139
140 pub fn aspect_ratio(mut self, ratio: Option<f32>) -> Self {
141 self.style = self.style.aspect_ratio(ratio);
142 self
143 }
144
145 pub fn aspect(mut self, ratio: f32) -> Self {
146 self.style = self.style.aspect(ratio);
147 self
148 }
149
150 pub fn position(mut self, position: Position) -> Self {
151 self.style = self.style.position(position);
152 self
153 }
154
155 pub fn absolute(mut self) -> Self {
156 self.style = self.style.absolute();
157 self
158 }
159
160 pub fn absolute_at(mut self, left: f32, top: f32) -> Self {
161 self.style = self.style.absolute_at(left, top);
162 self
163 }
164
165 pub fn absolute_inset(mut self, inset: Inset) -> Self {
166 self.style = self.style.absolute_inset(inset);
167 self
168 }
169
170 pub fn fit(mut self) -> Self {
171 self.style = self.style.fit();
172 self
173 }
174
175 pub fn hit_testable(mut self, on: bool) -> Self {
176 self.style = self.style.hit_testable(on);
177 self
178 }
179 }
180 };
181}
182
183pub trait IntoChildren {
184 fn into_children(self) -> Vec<AnyView>;
185}
186
187impl<V: View + 'static, const N: usize> IntoChildren for [V; N] {
188 fn into_children(self) -> Vec<AnyView> {
189 self.into_iter().map(AnyView::new).collect()
190 }
191}
192
193impl<V: View + 'static> IntoChildren for Vec<V> {
194 fn into_children(self) -> Vec<AnyView> {
195 self.into_iter().map(AnyView::new).collect()
196 }
197}
198
199impl<V: View + 'static> IntoChildren for Option<V> {
200 fn into_children(self) -> Vec<AnyView> {
201 self.into_iter().map(AnyView::new).collect()
202 }
203}
204
205macro_rules! impl_into_children_tuple {
206 ($($T:ident),*) => {
207 #[allow(non_snake_case)]
208 impl<$($T: View + 'static),*> IntoChildren for ($($T,)*) {
209 fn into_children(self) -> Vec<AnyView> {
210 let ($($T,)*) = self;
211 vec![$(AnyView::new($T)),*]
212 }
213 }
214 };
215}
216
217impl_into_children_tuple!(A);
218impl_into_children_tuple!(A, B);
219impl_into_children_tuple!(A, B, C);
220impl_into_children_tuple!(A, B, C, D);
221impl_into_children_tuple!(A, B, C, D, E);
222impl_into_children_tuple!(A, B, C, D, E, F);
223impl_into_children_tuple!(A, B, C, D, E, F, G);
224impl_into_children_tuple!(A, B, C, D, E, F, G, H);
225impl_into_children_tuple!(A, B, C, D, E, F, G, H, I);
226impl_into_children_tuple!(A, B, C, D, E, F, G, H, I, J);
227impl_into_children_tuple!(A, B, C, D, E, F, G, H, I, J, K);
228impl_into_children_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
229
230macro_rules! impl_child_helpers {
231 ($name:ident) => {
232 impl $name {
233 pub fn child_if<V: View + 'static>(self, cond: bool, make: impl FnOnce() -> V) -> Self {
234 if cond { self.child(make()) } else { self }
235 }
236
237 pub fn child_opt<V: View + 'static>(self, child: Option<V>) -> Self {
238 match child {
239 Some(v) => self.child(v),
240 None => self,
241 }
242 }
243 }
244 };
245}
246
247#[derive(Clone, Copy, Default, Debug)]
248pub struct Unit;
249
250impl View for Unit {
251 fn body(&self) -> impl View + 'static {
252 Unit
253 }
254 fn is_leaf(&self) -> bool {
255 true
256 }
257 fn layout_style(&self) -> LayoutStyle {
258 LayoutStyle::default()
259 }
260}
261
262pub struct Text {
263 content: Box<dyn Fn() -> String>,
264 font_size: Option<f32>,
265 color: Option<Color>,
266 weight: Option<FontWeight>,
267 family: Option<String>,
268 font_style: FontStyle,
269 letter_spacing: f32,
270 wrap_width: Option<f32>,
271 wrap_mode: WrapMode,
272 truncate_width: Option<f32>,
273
274 truncate_fill: bool,
275 elide_mode: ElideMode,
276 line_height: LineHeight,
277 align_y: TextVAlign,
278 max_lines: Option<usize>,
279 font_scale: f32,
280 auto_wrap: bool,
281 underline: bool,
282 strikethrough: bool,
283 style: LayoutStyle,
284}
285
286impl Text {
287 pub fn new(content: impl Into<String>) -> Self {
288 let s = content.into();
289 Self {
290 content: Box::new(move || s.clone()),
291 font_size: None,
292 color: None,
293 weight: None,
294 family: None,
295 font_style: FontStyle::Normal,
296 letter_spacing: 0.0,
297 wrap_width: None,
298 wrap_mode: WrapMode::default(),
299 truncate_width: None,
300 truncate_fill: false,
301 elide_mode: ElideMode::default(),
302 line_height: LineHeight::default(),
303 align_y: TextVAlign::Top,
304 max_lines: None,
305 font_scale: 1.0,
306 auto_wrap: false,
307 underline: false,
308 strikethrough: false,
309 style: LayoutStyle {
310 width: Length::Fit,
311 height: Length::Fit,
312 ..LayoutStyle::default()
313 },
314 }
315 }
316
317 pub fn with(content: impl Fn() -> String + 'static) -> Self {
318 Self {
319 content: Box::new(content),
320 font_size: None,
321 color: None,
322 weight: None,
323 family: None,
324 font_style: FontStyle::Normal,
325 letter_spacing: 0.0,
326 wrap_width: None,
327 wrap_mode: WrapMode::default(),
328 truncate_width: None,
329 truncate_fill: false,
330 elide_mode: ElideMode::default(),
331 line_height: LineHeight::default(),
332 align_y: TextVAlign::Top,
333 max_lines: None,
334 font_scale: 1.0,
335 auto_wrap: false,
336 underline: false,
337 strikethrough: false,
338 style: LayoutStyle {
339 width: Length::Fit,
340 height: Length::Fit,
341 ..LayoutStyle::default()
342 },
343 }
344 }
345
346 pub fn underline(mut self, on: bool) -> Self {
347 self.underline = on;
348 self
349 }
350
351 pub fn strikethrough(mut self, on: bool) -> Self {
352 self.strikethrough = on;
353 self
354 }
355
356 pub fn size(mut self, size: f32) -> Self {
357 self.font_size = Some(size);
358 self
359 }
360
361 pub fn color(mut self, color: Color) -> Self {
362 self.color = Some(color);
363 self
364 }
365
366 pub fn weight(mut self, weight: FontWeight) -> Self {
367 self.weight = Some(weight);
368 self
369 }
370
371 pub fn bold(mut self) -> Self {
372 self.weight = Some(FontWeight::BOLD);
373 self
374 }
375
376 pub fn bold_if(mut self, bold: bool) -> Self {
377 self.weight = Some(if bold {
378 FontWeight::BOLD
379 } else {
380 FontWeight::NORMAL
381 });
382 self
383 }
384
385 pub fn semibold(mut self) -> Self {
386 self.weight = Some(FontWeight::SEMIBOLD);
387 self
388 }
389
390 pub fn medium(mut self) -> Self {
391 self.weight = Some(FontWeight::MEDIUM);
392 self
393 }
394
395 pub fn normal(mut self) -> Self {
396 self.weight = Some(FontWeight::NORMAL);
397 self
398 }
399
400 pub fn light(mut self) -> Self {
401 self.weight = Some(FontWeight::LIGHT);
402 self
403 }
404
405 pub fn black(mut self) -> Self {
406 self.weight = Some(FontWeight::BLACK);
407 self
408 }
409
410 pub fn font(mut self, family: impl Into<String>) -> Self {
411 let family = family.into();
412 self.family = if family.is_empty() {
413 None
414 } else {
415 Some(family)
416 };
417 self
418 }
419
420 pub fn family(self, family: impl Into<String>) -> Self {
421 self.font(family)
422 }
423
424 pub fn font_style(mut self, style: FontStyle) -> Self {
425 self.font_style = style;
426 self
427 }
428
429 pub fn italic(mut self) -> Self {
430 self.font_style = FontStyle::Italic;
431 self
432 }
433
434 pub fn oblique(mut self) -> Self {
435 self.font_style = FontStyle::Oblique;
436 self
437 }
438
439 pub fn upright(mut self) -> Self {
440 self.font_style = FontStyle::Normal;
441 self
442 }
443
444 pub fn italic_if(mut self, on: bool) -> Self {
445 self.font_style = if on {
446 FontStyle::Italic
447 } else {
448 FontStyle::Normal
449 };
450 self
451 }
452
453 pub fn letter_spacing(mut self, spacing: LetterSpacing) -> Self {
454 self.letter_spacing = if spacing.is_finite() { spacing } else { 0.0 };
455 self
456 }
457
458 pub fn wrap_width(mut self, width: f32) -> Self {
459 self.wrap_width = if width > 0.0 { Some(width) } else { None };
460 self
461 }
462
463 pub fn wrap_mode(mut self, mode: WrapMode) -> Self {
464 self.wrap_mode = mode;
465 self
466 }
467
468 pub fn wrap(mut self) -> Self {
470 self.auto_wrap = true;
471 self
472 }
473
474 pub fn line_height(mut self, factor: f32) -> Self {
476 if factor.is_finite() && factor > 0.0 {
477 self.line_height = LineHeight::Factor(factor);
478 }
479 self
480 }
481
482 pub fn line_height_px(mut self, px: f32) -> Self {
484 if px.is_finite() && px > 0.0 {
485 self.line_height = LineHeight::Absolute(px);
486 }
487 self
488 }
489
490 pub fn align_y(mut self, align: TextVAlign) -> Self {
492 self.align_y = align;
493 self
494 }
495
496 pub fn max_lines(mut self, lines: usize) -> Self {
498 self.max_lines = if lines == 0 { None } else { Some(lines) };
499 self
500 }
501
502 pub fn font_scale(mut self, scale: f32) -> Self {
504 if scale.is_finite() && scale > 0.0 {
505 self.font_scale = scale;
506 }
507 self
508 }
509
510 pub fn truncate(mut self, max_width: f32) -> Self {
511 self.truncate_width = if max_width > 0.0 {
512 Some(max_width)
513 } else {
514 None
515 };
516 self
517 }
518
519 pub fn truncate_fill(mut self) -> Self {
520 self.truncate_fill = true;
521 self
522 }
523
524 pub fn elide(mut self, mode: ElideMode) -> Self {
525 self.elide_mode = mode;
526 self
527 }
528
529 pub fn style(mut self, style: TextStyle) -> Self {
530 if let Some(size) = style.size {
531 self.font_size = Some(size);
532 }
533 if let Some(color) = style.color {
534 self.color = Some(color);
535 }
536 if let Some(weight) = style.weight {
537 self.weight = Some(FontWeight::new(weight));
538 }
539 if let Some(family) = style.family {
540 self.family = if family.is_empty() {
541 None
542 } else {
543 Some(family)
544 };
545 }
546 if let Some(italic) = style.italic {
547 self.font_style = if italic {
548 FontStyle::Italic
549 } else {
550 FontStyle::Normal
551 };
552 }
553 if let Some(spacing) = style.letter_spacing {
554 self.letter_spacing = if spacing.is_finite() { spacing } else { 0.0 };
555 }
556 if let Some(factor) = style.line_height
557 && factor.is_finite()
558 && factor > 0.0
559 {
560 self.line_height = LineHeight::Factor(factor);
561 }
562 if let Some(on) = style.underline {
563 self.underline = on;
564 }
565 if let Some(on) = style.strikethrough {
566 self.strikethrough = on;
567 }
568 self
569 }
570
571 pub fn width(mut self, width: impl Into<Length>) -> Self {
572 self.style = self.style.width(width.into());
573 self
574 }
575
576 pub fn height(mut self, height: impl Into<Length>) -> Self {
577 self.style = self.style.height(height.into());
578 self
579 }
580
581 pub fn min_width(mut self, v: f32) -> Self {
582 self.style = self.style.min_width(v);
583 self
584 }
585
586 pub fn max_width(mut self, v: f32) -> Self {
587 self.style = self.style.max_width(v);
588 self
589 }
590
591 pub fn min_height(mut self, v: f32) -> Self {
592 self.style = self.style.min_height(v);
593 self
594 }
595
596 pub fn max_height(mut self, v: f32) -> Self {
597 self.style = self.style.max_height(v);
598 self
599 }
600
601 pub fn flex(mut self, weight: f32) -> Self {
602 self.style = self.style.flex(weight);
603 self
604 }
605
606 pub fn expand(self) -> Self {
607 self.flex(1.0)
608 }
609
610 pub fn fill_width(mut self) -> Self {
611 self.style = self.style.width(Length::Fill(1.0));
612 self
613 }
614
615 pub fn fill_height(mut self) -> Self {
616 self.style = self.style.height(Length::Fill(1.0));
617 self
618 }
619
620 pub fn fill_size(self) -> Self {
621 self.fill_width().fill_height()
622 }
623
624 pub fn padding(mut self, padding: impl Into<Edges>) -> Self {
625 self.style = self.style.padding(padding);
626 self
627 }
628
629 pub fn pad(self, padding: impl Into<Edges>) -> Self {
630 self.padding(padding)
631 }
632
633 pub fn padding_xy(mut self, x: f32, y: f32) -> Self {
634 self.style = self.style.padding_xy(x, y);
635 self
636 }
637
638 pub fn padding_x(mut self, x: f32) -> Self {
639 self.style = self.style.padding_x(x);
640 self
641 }
642
643 pub fn padding_y(mut self, y: f32) -> Self {
644 self.style = self.style.padding_y(y);
645 self
646 }
647
648 pub fn padding_left(mut self, v: f32) -> Self {
649 self.style = self.style.padding_left(v);
650 self
651 }
652
653 pub fn padding_right(mut self, v: f32) -> Self {
654 self.style = self.style.padding_right(v);
655 self
656 }
657
658 pub fn padding_top(mut self, v: f32) -> Self {
659 self.style = self.style.padding_top(v);
660 self
661 }
662
663 pub fn padding_bottom(mut self, v: f32) -> Self {
664 self.style = self.style.padding_bottom(v);
665 self
666 }
667
668 pub fn margin(mut self, margin: impl Into<Edges>) -> Self {
669 self.style = self.style.margin(margin);
670 self
671 }
672
673 pub fn margin_xy(mut self, x: f32, y: f32) -> Self {
674 self.style = self.style.margin_xy(x, y);
675 self
676 }
677
678 pub fn margin_x(mut self, x: f32) -> Self {
679 self.style = self.style.margin_x(x);
680 self
681 }
682
683 pub fn margin_y(mut self, y: f32) -> Self {
684 self.style = self.style.margin_y(y);
685 self
686 }
687
688 pub fn margin_left(mut self, v: f32) -> Self {
689 self.style = self.style.margin_left(v);
690 self
691 }
692
693 pub fn margin_right(mut self, v: f32) -> Self {
694 self.style = self.style.margin_right(v);
695 self
696 }
697
698 pub fn margin_top(mut self, v: f32) -> Self {
699 self.style = self.style.margin_top(v);
700 self
701 }
702
703 pub fn margin_bottom(mut self, v: f32) -> Self {
704 self.style = self.style.margin_bottom(v);
705 self
706 }
707
708 pub fn indent_top(mut self, v: f32) -> Self {
709 self.style = self.style.indent_top(v);
710 self
711 }
712
713 pub fn indent_bottom(mut self, v: f32) -> Self {
714 self.style = self.style.indent_bottom(v);
715 self
716 }
717
718 pub fn indent_left(mut self, v: f32) -> Self {
719 self.style = self.style.indent_left(v);
720 self
721 }
722
723 pub fn indent_right(mut self, v: f32) -> Self {
724 self.style = self.style.indent_right(v);
725 self
726 }
727
728 pub fn clear_indents(mut self) -> Self {
729 self.style = self.style.clear_indents();
730 self
731 }
732
733 pub fn indent(mut self, indents: Indents) -> Self {
734 self.style = self.style.indent(indents);
735 self
736 }
737
738 pub fn indent_all(mut self, v: f32) -> Self {
739 self.style = self.style.indent_all(v);
740 self
741 }
742
743 pub fn indent_xy(mut self, x: f32, y: f32) -> Self {
744 self.style = self.style.indent_xy(x, y);
745 self
746 }
747
748 pub fn indent_axes(mut self, horizontal: f32, vertical: f32) -> Self {
749 self.style = self.style.indent_axes(horizontal, vertical);
750 self
751 }
752
753 pub fn hit_testable(mut self, on: bool) -> Self {
754 self.style = self.style.hit_testable(on);
755 self
756 }
757
758 pub fn content(&self) -> String {
759 (self.content)()
760 }
761
762 fn paint_decoration(
763 &self,
764 ctx: &mut PaintCtx,
765 shown: &str,
766 x: f32,
767 baseline: f32,
768 size: f32,
769 weight: FontWeight,
770 color: Color,
771 ) {
772 if !self.underline && !self.strikethrough {
773 return;
774 }
775 let width = ctx.text_width_styled_spaced(
776 shown,
777 size,
778 weight,
779 self.letter_spacing,
780 self.family.as_deref(),
781 self.font_style,
782 );
783 if width <= 0.0 {
784 return;
785 }
786 let thickness = (size * 0.07).max(1.0);
787 if self.underline {
788 let y = (baseline + size * 0.12).round();
789 ctx.quad(Rect::from_xywh(x, y, width, thickness), color, 0.0);
790 }
791 if self.strikethrough {
792 let y = (baseline - size * 0.30).round();
793 ctx.quad(Rect::from_xywh(x, y, width, thickness), color, 0.0);
794 }
795 }
796}
797
798impl View for Text {
799 fn body(&self) -> impl View + 'static {
800 let _ = (self.content)();
801 Unit
802 }
803 fn is_leaf(&self) -> bool {
804 true
805 }
806
807 fn accessibility(&self) -> Option<crate::a11y::Accessible> {
808 Some(crate::a11y::Accessible::new(
809 crate::a11y::AccessibleRole::Text,
810 (self.content)(),
811 ))
812 }
813
814 fn clip_self(&self) -> bool {
815 true
816 }
817 fn layout_style(&self) -> LayoutStyle {
818 self.style
819 }
820 fn intrinsic_size(&self, ctx: &mut LayoutCtx) -> Option<Size> {
821 let size = self.font_size.unwrap_or_else(|| ctx.default_font_size()) * self.font_scale;
822 let weight = self.weight.unwrap_or_default();
823 let family = self.family.as_deref();
824 let fstyle = self.font_style;
825 let content = (self.content)();
826 let pad = self.style.padding;
827 let auto_wrap = if self.auto_wrap {
828 text_wrap_limit(self.style, ctx.available_width())
829 } else {
830 None
831 };
832 let text_size = if let Some(w) = self.truncate_width {
833 if let Some(max_lines) = self.max_lines {
834 let shown = ctx.text_elide_lines_styled_spaced(
835 &content,
836 size,
837 weight,
838 w,
839 self.wrap_mode,
840 self.letter_spacing,
841 family,
842 fstyle,
843 self.line_height,
844 max_lines,
845 );
846 ctx.text_wrapped_size_styled_spaced_lh(
847 &shown,
848 size,
849 weight,
850 w,
851 self.wrap_mode,
852 self.letter_spacing,
853 family,
854 fstyle,
855 self.line_height,
856 )
857 } else {
858 ctx.text_elided_size_styled_spaced_lh(
859 &content,
860 size,
861 weight,
862 w,
863 self.elide_mode,
864 self.letter_spacing,
865 family,
866 fstyle,
867 self.line_height,
868 )
869 }
870 } else if let Some(w) = self.wrap_width.or(auto_wrap) {
871 let shown = match self.max_lines {
872 Some(max_lines) => ctx.text_elide_lines_styled_spaced(
873 &content,
874 size,
875 weight,
876 w,
877 self.wrap_mode,
878 self.letter_spacing,
879 family,
880 fstyle,
881 self.line_height,
882 max_lines,
883 ),
884 None => content.clone(),
885 };
886 ctx.text_wrapped_size_styled_spaced_lh(
887 &shown,
888 size,
889 weight,
890 w,
891 self.wrap_mode,
892 self.letter_spacing,
893 family,
894 fstyle,
895 self.line_height,
896 )
897 } else {
898 let w = ctx.text_width_styled_spaced(
899 &content,
900 size,
901 weight,
902 self.letter_spacing,
903 family,
904 fstyle,
905 );
906 let shaped = ctx.text_wrapped_size_styled_spaced_lh(
907 &content,
908 size,
909 weight,
910 w.max(1.0),
911 self.wrap_mode,
912 self.letter_spacing,
913 family,
914 fstyle,
915 self.line_height,
916 );
917 Size::new(w.max(shaped.width), shaped.height)
918 };
919 Some(Size::new(
920 text_size.width + pad.horizontal_sum(),
921 text_size.height + pad.vertical_sum(),
922 ))
923 }
924
925 fn baseline_offset(&self, ctx: &mut LayoutCtx, width: f32) -> Option<f32> {
926 let size = self.font_size.unwrap_or_else(|| ctx.default_font_size()) * self.font_scale;
927 let weight = self.weight.unwrap_or_default();
928 let family = self.family.as_deref();
929 let content = (self.content)();
930 let pad = self.style.padding;
931 let width = (width - pad.horizontal_sum()).max(0.0);
932 let baseline = ctx.text_first_baseline_styled_spaced_lh(
933 &content,
934 size,
935 weight,
936 width,
937 self.wrap_mode,
938 self.letter_spacing,
939 family,
940 self.font_style,
941 self.line_height,
942 );
943 Some(pad.top + baseline)
944 }
945
946 fn paint_self(&self, ctx: &mut PaintCtx) {
947 let theme = ctx.theme();
948 let size = self.font_size.unwrap_or(theme.font_size) * self.font_scale;
949 let weight = self.weight.unwrap_or_default();
950 let color = self.color.unwrap_or(theme.text);
951 let content = (self.content)();
952 let pad = self.style.padding;
953
954 let content_rect = Rect::from_xywh(
955 ctx.rect.left() + pad.left,
956 ctx.rect.top() + pad.top,
957 (ctx.rect.size.width - pad.horizontal_sum()).max(0.0),
958 (ctx.rect.size.height - pad.vertical_sum()).max(0.0),
959 );
960 let x = content_rect.left();
961
962 let family = self.family.as_deref();
963 let fstyle = self.font_style;
964 let truncate_width = self.truncate_width.or(if self.truncate_fill {
965 Some(content_rect.size.width.max(0.0))
966 } else {
967 None
968 });
969 let auto_wrap = if self.auto_wrap && content_rect.size.width > 0.0 {
970 Some(content_rect.size.width)
971 } else {
972 None
973 };
974 let (shown, wrap_at, shaped) = if let Some(w) = truncate_width {
975 if let Some(max_lines) = self.max_lines {
976 let shown = ctx.elide_lines_styled_spaced(
977 &content,
978 size,
979 weight,
980 w,
981 self.wrap_mode,
982 self.letter_spacing,
983 family,
984 fstyle,
985 self.line_height,
986 max_lines,
987 );
988 let shaped = ctx.shape_wrapped_styled_spaced_lh(
989 &shown,
990 size,
991 weight,
992 w,
993 self.wrap_mode,
994 self.letter_spacing,
995 family,
996 fstyle,
997 self.line_height,
998 );
999 (shown, Some(w), shaped)
1000 } else {
1001 let shown = ctx.elide_styled_spaced(
1002 &content,
1003 size,
1004 weight,
1005 w,
1006 self.elide_mode,
1007 self.letter_spacing,
1008 family,
1009 fstyle,
1010 );
1011 let shaped = ctx.shape_wrapped_styled_spaced_lh(
1012 &shown,
1013 size,
1014 weight,
1015 0.0,
1016 self.wrap_mode,
1017 self.letter_spacing,
1018 family,
1019 fstyle,
1020 self.line_height,
1021 );
1022 (shown, None, shaped)
1023 }
1024 } else if let Some(w) = self.wrap_width.or(auto_wrap) {
1025 let shown = match self.max_lines {
1026 Some(max_lines) => ctx.elide_lines_styled_spaced(
1027 &content,
1028 size,
1029 weight,
1030 w,
1031 self.wrap_mode,
1032 self.letter_spacing,
1033 family,
1034 fstyle,
1035 self.line_height,
1036 max_lines,
1037 ),
1038 None => content.clone(),
1039 };
1040 let shaped = ctx.shape_wrapped_styled_spaced_lh(
1041 &shown,
1042 size,
1043 weight,
1044 w,
1045 self.wrap_mode,
1046 self.letter_spacing,
1047 family,
1048 fstyle,
1049 self.line_height,
1050 );
1051 (shown, Some(w), shaped)
1052 } else {
1053 let full_w = ctx.text_width_styled_spaced(
1054 &content,
1055 size,
1056 weight,
1057 self.letter_spacing,
1058 family,
1059 fstyle,
1060 );
1061 if let Some(max_lines) = self.max_lines {
1062 let shown = ctx.elide_lines_styled_spaced(
1063 &content,
1064 size,
1065 weight,
1066 full_w.max(1.0),
1067 self.wrap_mode,
1068 self.letter_spacing,
1069 family,
1070 fstyle,
1071 self.line_height,
1072 max_lines,
1073 );
1074 let shaped = ctx.shape_wrapped_styled_spaced_lh(
1075 &shown,
1076 size,
1077 weight,
1078 full_w.max(1.0),
1079 self.wrap_mode,
1080 self.letter_spacing,
1081 family,
1082 fstyle,
1083 self.line_height,
1084 );
1085 (shown, None, shaped)
1086 } else {
1087 let shaped = ctx.shape_wrapped_styled_spaced_lh(
1088 &content,
1089 size,
1090 weight,
1091 0.0,
1092 self.wrap_mode,
1093 self.letter_spacing,
1094 family,
1095 fstyle,
1096 self.line_height,
1097 );
1098 (content.clone(), None, shaped)
1099 }
1100 };
1101
1102 #[cfg(debug_assertions)]
1103 {
1104 if wrap_at.is_none()
1105 && !content.is_empty()
1106 && shaped.width() > content_rect.size.width + 1.0
1107 && content_rect.size.width > 0.0
1108 {
1109 use std::sync::Once;
1110 static WARN_ONCE: Once = Once::new();
1111 WARN_ONCE.call_once(|| {
1112 log::warn!(
1113 "sequoia-view: Text `{}` overflows box ({:.1}px > {:.1}px) without truncate — add `.truncate_fill()` or `.truncate(w)`. \
1114 (This warning once per process; subsequent overflows are silent.)",
1115 content.chars().take(24).collect::<String>(),
1116 shaped.width(),
1117 content_rect.size.width,
1118 );
1119 });
1120 }
1121 }
1122
1123 let text_h = shaped.height();
1124 let block_top = match self.align_y {
1125 TextVAlign::Top | TextVAlign::Baseline => content_rect.top(),
1126 TextVAlign::Center => content_rect.top() + (content_rect.size.height - text_h) * 0.5,
1127 TextVAlign::Bottom => content_rect.top() + content_rect.size.height - text_h,
1128 _ => content_rect.top(),
1129 };
1130 let y = if self.align_y == TextVAlign::Baseline {
1131 content_rect.top()
1132 } else {
1133 block_top + shaped.first_baseline()
1134 };
1135 ctx.draw_shaped(&shaped, (x, y), color);
1136 self.paint_decoration(ctx, &shown, x, y, size, weight, color);
1137 }
1138}
1139
1140#[derive(Clone, Default)]
1141pub struct Fragment {
1142 children: Vec<AnyView>,
1143}
1144
1145impl Fragment {
1146 pub fn new() -> Self {
1147 Self::default()
1148 }
1149
1150 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
1151 self.children.push(AnyView::new(child));
1152 self
1153 }
1154
1155 pub fn children(mut self, children: impl IntoChildren) -> Self {
1156 self.children.extend(children.into_children());
1157 self
1158 }
1159}
1160
1161impl View for Fragment {
1162 fn body(&self) -> impl View + 'static {
1163 Unit
1164 }
1165 fn children_override(&self) -> Option<Vec<AnyView>> {
1166 Some(self.children.clone())
1167 }
1168 fn layout_style(&self) -> LayoutStyle {
1169 LayoutStyle::default().hit_testable(false)
1170 }
1171 fn hit_testable(&self) -> bool {
1172 false
1173 }
1174}
1175
1176#[derive(Clone)]
1188pub struct Cached {
1189 child: AnyView,
1190}
1191
1192impl Cached {
1193 pub fn new<V: View + 'static>(child: V) -> Self {
1194 Self {
1195 child: AnyView::new(child),
1196 }
1197 }
1198}
1199
1200impl View for Cached {
1201 fn body(&self) -> impl View + 'static {
1202 Unit
1203 }
1204
1205 fn children_override(&self) -> Option<Vec<AnyView>> {
1206 Some(vec![self.child.clone()])
1207 }
1208
1209 fn layout_style(&self) -> LayoutStyle {
1210 LayoutStyle {
1211 width: Length::Fit,
1212 height: Length::Fit,
1213 ..LayoutStyle::default().hit_testable(false)
1214 }
1215 }
1216
1217 fn hit_testable(&self) -> bool {
1218 false
1219 }
1220
1221 fn cache_layer(&self) -> bool {
1222 true
1223 }
1224}
1225
1226#[derive(Clone)]
1227pub struct Margined {
1228 child: AnyView,
1229 margin: Edges,
1230 indents: Indents,
1231}
1232
1233impl Margined {
1234 pub fn new<V: View + 'static>(child: V, margin: impl Into<Edges>) -> Self {
1235 Self {
1236 child: AnyView::new(child),
1237 margin: margin.into(),
1238 indents: Indents::NONE,
1239 }
1240 }
1241
1242 pub fn with_indents<V: View + 'static>(child: V, indents: Indents) -> Self {
1243 Self {
1244 child: AnyView::new(child),
1245 margin: Edges::ZERO,
1246 indents,
1247 }
1248 }
1249
1250 pub fn margin(mut self, margin: impl Into<Edges>) -> Self {
1251 let m = margin.into();
1252 self.margin = Edges::only(
1253 sanitize_margin_edge(m.left),
1254 sanitize_margin_edge(m.top),
1255 sanitize_margin_edge(m.right),
1256 sanitize_margin_edge(m.bottom),
1257 );
1258 self
1259 }
1260
1261 pub fn margin_xy(self, x: f32, y: f32) -> Self {
1262 self.margin(Edges::xy(x, y))
1263 }
1264
1265 pub fn margin_x(mut self, x: f32) -> Self {
1266 let x = sanitize_margin_edge(x);
1267 self.margin.left = x;
1268 self.margin.right = x;
1269 self
1270 }
1271
1272 pub fn margin_y(mut self, y: f32) -> Self {
1273 let y = sanitize_margin_edge(y);
1274 self.margin.top = y;
1275 self.margin.bottom = y;
1276 self
1277 }
1278
1279 pub fn margin_left(mut self, v: f32) -> Self {
1280 self.margin.left = sanitize_margin_edge(v);
1281 self
1282 }
1283
1284 pub fn margin_right(mut self, v: f32) -> Self {
1285 self.margin.right = sanitize_margin_edge(v);
1286 self
1287 }
1288
1289 pub fn margin_top(mut self, v: f32) -> Self {
1290 self.margin.top = sanitize_margin_edge(v);
1291 self
1292 }
1293
1294 pub fn margin_bottom(mut self, v: f32) -> Self {
1295 self.margin.bottom = sanitize_margin_edge(v);
1296 self
1297 }
1298
1299 pub fn indent_top(mut self, v: f32) -> Self {
1300 self.indents.top = Some(sequoia_layout::sanitize_indent(v));
1301 self
1302 }
1303
1304 pub fn indent_bottom(mut self, v: f32) -> Self {
1305 self.indents.bottom = Some(sequoia_layout::sanitize_indent(v));
1306 self
1307 }
1308
1309 pub fn indent_left(mut self, v: f32) -> Self {
1310 self.indents.left = Some(sequoia_layout::sanitize_indent(v));
1311 self
1312 }
1313
1314 pub fn indent_right(mut self, v: f32) -> Self {
1315 self.indents.right = Some(sequoia_layout::sanitize_indent(v));
1316 self
1317 }
1318
1319 pub fn clear_indents(mut self) -> Self {
1320 self.indents = Indents::NONE;
1321 self
1322 }
1323
1324 pub fn indent(mut self, indents: Indents) -> Self {
1325 if let Some(v) = indents.top {
1326 self.indents.top = Some(sequoia_layout::sanitize_indent(v));
1327 }
1328 if let Some(v) = indents.bottom {
1329 self.indents.bottom = Some(sequoia_layout::sanitize_indent(v));
1330 }
1331 if let Some(v) = indents.left {
1332 self.indents.left = Some(sequoia_layout::sanitize_indent(v));
1333 }
1334 if let Some(v) = indents.right {
1335 self.indents.right = Some(sequoia_layout::sanitize_indent(v));
1336 }
1337 self
1338 }
1339
1340 pub fn indent_all(self, v: f32) -> Self {
1341 self.indent(Indents::all(v))
1342 }
1343
1344 pub fn indent_xy(self, x: f32, y: f32) -> Self {
1345 self.indent(Indents::xy(x, y))
1346 }
1347
1348 pub fn indent_axes(self, horizontal: f32, vertical: f32) -> Self {
1349 self.indent(Indents::axes(horizontal, vertical))
1350 }
1351}
1352
1353fn sanitize_margin_edge(v: f32) -> f32 {
1354 if v.is_finite() { v.max(0.0) } else { 0.0 }
1355}
1356
1357impl View for Margined {
1358 fn body(&self) -> impl View + 'static {
1359 Unit
1360 }
1361 fn children_override(&self) -> Option<Vec<AnyView>> {
1362 Some(vec![self.child.clone()])
1363 }
1364 fn layout_style(&self) -> LayoutStyle {
1365 LayoutStyle {
1366 width: Length::Fit,
1367 height: Length::Fit,
1368 margin: self.margin,
1369 indent_top: self.indents.top,
1370 indent_bottom: self.indents.bottom,
1371 indent_left: self.indents.left,
1372 indent_right: self.indents.right,
1373 ..LayoutStyle::default().hit_testable(false)
1374 }
1375 }
1376 fn hit_testable(&self) -> bool {
1377 false
1378 }
1379}
1380
1381#[derive(Clone, Default)]
1382pub struct FocusScope {
1383 children: Vec<AnyView>,
1384 trap: bool,
1385}
1386
1387impl FocusScope {
1388 pub fn new() -> Self {
1389 Self::default()
1390 }
1391
1392 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
1393 self.children.push(AnyView::new(child));
1394 self
1395 }
1396
1397 pub fn children(mut self, children: impl IntoChildren) -> Self {
1398 self.children.extend(children.into_children());
1399 self
1400 }
1401
1402 pub fn trap(mut self, trap: bool) -> Self {
1403 self.trap = trap;
1404 self
1405 }
1406}
1407
1408impl View for FocusScope {
1409 fn body(&self) -> impl View + 'static {
1410 Unit
1411 }
1412 fn children_override(&self) -> Option<Vec<AnyView>> {
1413 Some(self.children.clone())
1414 }
1415 fn focus_trap(&self) -> bool {
1416 self.trap
1417 }
1418 fn layout_style(&self) -> LayoutStyle {
1419 LayoutStyle::default()
1420 }
1421}
1422
1423struct Flex {
1424 children: Vec<AnyView>,
1425
1426 flex: Vec<f32>,
1427 gap: f32,
1428 cross_gap: f32,
1429 wrap: bool,
1430 align_content: Align,
1431 style: LayoutStyle,
1432 axis: Axis,
1433 align: Align,
1434 justify: Justify,
1435 deco: BoxStyle,
1436}
1437
1438impl Flex {
1439 fn new(axis: Axis) -> Self {
1440 Self {
1441 children: Vec::new(),
1442 flex: Vec::new(),
1443 gap: 0.0,
1444 cross_gap: 0.0,
1445 wrap: false,
1446 align_content: Align::Start,
1447 style: LayoutStyle {
1448 width: Length::Fit,
1449 height: Length::Fit,
1450 ..LayoutStyle::default()
1451 },
1452 axis,
1453 align: Align::Start,
1454 justify: Justify::Start,
1455 deco: BoxStyle::new(),
1456 }
1457 }
1458
1459 fn sanitize_flex(flex: f32) -> f32 {
1460 if flex.is_finite() && flex > 0.0 {
1461 flex
1462 } else {
1463 0.0
1464 }
1465 }
1466}
1467
1468impl View for Flex {
1469 fn body(&self) -> impl View + 'static {
1470 Unit
1471 }
1472 fn children_override(&self) -> Option<Vec<AnyView>> {
1473 Some(self.children.clone())
1474 }
1475 fn layout_style(&self) -> LayoutStyle {
1476 let mut style = self.style;
1477 let edges = self.deco.border_edges();
1478 style.padding.left += edges.left;
1479 style.padding.top += edges.top;
1480 style.padding.right += edges.right;
1481 style.padding.bottom += edges.bottom;
1482 style
1483 }
1484 fn container(&self) -> Option<ContainerStyle> {
1485 Some(ContainerStyle {
1486 axis: self.axis,
1487 gap: self.gap,
1488 cross_gap: self.cross_gap,
1489 align: self.align,
1490 justify: self.justify,
1491 wrap: self.wrap,
1492 align_content: self.align_content,
1493 })
1494 }
1495}
1496
1497macro_rules! impl_flex_container {
1498 ($name:ident, $axis:expr) => {
1499 impl $name {
1500 pub fn gap(mut self, gap: f32) -> Self {
1501 let gap = if gap.is_finite() { gap.max(0.0) } else { 0.0 };
1502 self.0.gap = gap;
1503 self.0.cross_gap = gap;
1504 self
1505 }
1506
1507 pub fn main_gap(mut self, gap: f32) -> Self {
1508 self.0.gap = if gap.is_finite() { gap.max(0.0) } else { 0.0 };
1509 self
1510 }
1511
1512 pub fn cross_gap(mut self, gap: f32) -> Self {
1513 self.0.cross_gap = if gap.is_finite() { gap.max(0.0) } else { 0.0 };
1514 self
1515 }
1516
1517 pub fn gaps(mut self, main: f32, cross: f32) -> Self {
1518 self.0.gap = if main.is_finite() { main.max(0.0) } else { 0.0 };
1519 self.0.cross_gap = if cross.is_finite() {
1520 cross.max(0.0)
1521 } else {
1522 0.0
1523 };
1524 self
1525 }
1526
1527 pub fn wrap(mut self, wrap: bool) -> Self {
1528 self.0.wrap = wrap;
1529 self
1530 }
1531
1532 pub fn wrapped(mut self) -> Self {
1533 self.0.wrap = true;
1534 self
1535 }
1536
1537 pub fn align_content(mut self, align: Align) -> Self {
1538 self.0.align_content = align;
1539 self
1540 }
1541
1542 pub fn margin(mut self, margin: impl Into<Edges>) -> Self {
1543 self.0.style = self.0.style.margin(margin);
1544 self
1545 }
1546
1547 pub fn margin_xy(mut self, x: f32, y: f32) -> Self {
1548 self.0.style = self.0.style.margin_xy(x, y);
1549 self
1550 }
1551
1552 pub fn margin_x(mut self, x: f32) -> Self {
1553 self.0.style = self.0.style.margin_x(x);
1554 self
1555 }
1556
1557 pub fn margin_y(mut self, y: f32) -> Self {
1558 self.0.style = self.0.style.margin_y(y);
1559 self
1560 }
1561
1562 pub fn margin_left(mut self, v: f32) -> Self {
1563 self.0.style = self.0.style.margin_left(v);
1564 self
1565 }
1566
1567 pub fn margin_right(mut self, v: f32) -> Self {
1568 self.0.style = self.0.style.margin_right(v);
1569 self
1570 }
1571
1572 pub fn margin_top(mut self, v: f32) -> Self {
1573 self.0.style = self.0.style.margin_top(v);
1574 self
1575 }
1576
1577 pub fn margin_bottom(mut self, v: f32) -> Self {
1578 self.0.style = self.0.style.margin_bottom(v);
1579 self
1580 }
1581
1582 pub fn indent_top(mut self, v: f32) -> Self {
1583 self.0.style = self.0.style.indent_top(v);
1584 self
1585 }
1586
1587 pub fn indent_bottom(mut self, v: f32) -> Self {
1588 self.0.style = self.0.style.indent_bottom(v);
1589 self
1590 }
1591
1592 pub fn indent_left(mut self, v: f32) -> Self {
1593 self.0.style = self.0.style.indent_left(v);
1594 self
1595 }
1596
1597 pub fn indent_right(mut self, v: f32) -> Self {
1598 self.0.style = self.0.style.indent_right(v);
1599 self
1600 }
1601
1602 pub fn clear_indents(mut self) -> Self {
1603 self.0.style = self.0.style.clear_indents();
1604 self
1605 }
1606
1607 pub fn indent(mut self, indents: Indents) -> Self {
1608 self.0.style = self.0.style.indent(indents);
1609 self
1610 }
1611
1612 pub fn indent_all(mut self, v: f32) -> Self {
1613 self.0.style = self.0.style.indent_all(v);
1614 self
1615 }
1616
1617 pub fn indent_xy(mut self, x: f32, y: f32) -> Self {
1618 self.0.style = self.0.style.indent_xy(x, y);
1619 self
1620 }
1621
1622 pub fn indent_axes(mut self, horizontal: f32, vertical: f32) -> Self {
1623 self.0.style = self.0.style.indent_axes(horizontal, vertical);
1624 self
1625 }
1626
1627 pub fn padding(mut self, padding: impl Into<Edges>) -> Self {
1628 self.0.style = self.0.style.padding(padding);
1629 self
1630 }
1631
1632 pub fn pad(self, padding: impl Into<Edges>) -> Self {
1633 self.padding(padding)
1634 }
1635
1636 pub fn padding_xy(mut self, x: f32, y: f32) -> Self {
1637 self.0.style = self.0.style.padding_xy(x, y);
1638 self
1639 }
1640
1641 pub fn padding_x(mut self, x: f32) -> Self {
1642 self.0.style = self.0.style.padding_x(x);
1643 self
1644 }
1645
1646 pub fn padding_y(mut self, y: f32) -> Self {
1647 self.0.style = self.0.style.padding_y(y);
1648 self
1649 }
1650
1651 pub fn padding_left(mut self, v: f32) -> Self {
1652 self.0.style = self.0.style.padding_left(v);
1653 self
1654 }
1655
1656 pub fn padding_right(mut self, v: f32) -> Self {
1657 self.0.style = self.0.style.padding_right(v);
1658 self
1659 }
1660
1661 pub fn padding_top(mut self, v: f32) -> Self {
1662 self.0.style = self.0.style.padding_top(v);
1663 self
1664 }
1665
1666 pub fn padding_bottom(mut self, v: f32) -> Self {
1667 self.0.style = self.0.style.padding_bottom(v);
1668 self
1669 }
1670
1671 pub fn width(mut self, width: impl Into<Length>) -> Self {
1672 self.0.style = self.0.style.width(width.into());
1673 self
1674 }
1675
1676 pub fn height(mut self, height: impl Into<Length>) -> Self {
1677 self.0.style = self.0.style.height(height.into());
1678 self
1679 }
1680
1681 pub fn size(mut self, width: impl Into<Length>, height: impl Into<Length>) -> Self {
1682 self.0.style = self.0.style.width(width.into()).height(height.into());
1683 self
1684 }
1685
1686 pub fn square(mut self, side: impl Into<Length>) -> Self {
1687 let side = side.into();
1688 self.0.style = self.0.style.width(side).height(side);
1689 self
1690 }
1691
1692 pub fn min_width(mut self, v: f32) -> Self {
1693 self.0.style = self.0.style.min_width(v);
1694 self
1695 }
1696
1697 pub fn max_width(mut self, v: f32) -> Self {
1698 self.0.style = self.0.style.max_width(v);
1699 self
1700 }
1701
1702 pub fn min_height(mut self, v: f32) -> Self {
1703 self.0.style = self.0.style.min_height(v);
1704 self
1705 }
1706
1707 pub fn max_height(mut self, v: f32) -> Self {
1708 self.0.style = self.0.style.max_height(v);
1709 self
1710 }
1711
1712 pub fn overflow(mut self, overflow: Overflow) -> Self {
1713 self.0.style = self.0.style.overflow(overflow);
1714 self
1715 }
1716
1717 pub fn flex(mut self, weight: f32) -> Self {
1718 self.0.style = self.0.style.flex(weight);
1719 self
1720 }
1721
1722 pub fn flex_grow(mut self, weight: f32) -> Self {
1723 self.0.style = self.0.style.flex_grow(weight);
1724 self
1725 }
1726
1727 pub fn flex_shrink(mut self, shrink: f32) -> Self {
1728 self.0.style = self.0.style.flex_shrink(shrink);
1729 self
1730 }
1731
1732 pub fn flex_basis(mut self, basis: Option<Length>) -> Self {
1733 self.0.style = self.0.style.flex_basis(basis);
1734 self
1735 }
1736
1737 pub fn align_self(mut self, align: Option<Align>) -> Self {
1738 self.0.style = self.0.style.align_self(align);
1739 self
1740 }
1741
1742 pub fn align_self_value(mut self, align: Align) -> Self {
1743 self.0.style = self.0.style.align_self_value(align);
1744 self
1745 }
1746
1747 pub fn aspect_ratio(mut self, ratio: Option<f32>) -> Self {
1748 self.0.style = self.0.style.aspect_ratio(ratio);
1749 self
1750 }
1751
1752 pub fn aspect(mut self, ratio: f32) -> Self {
1753 self.0.style = self.0.style.aspect(ratio);
1754 self
1755 }
1756
1757 pub fn position(mut self, position: Position) -> Self {
1758 self.0.style = self.0.style.position(position);
1759 self
1760 }
1761
1762 pub fn absolute(mut self) -> Self {
1763 self.0.style = self.0.style.absolute();
1764 self
1765 }
1766
1767 pub fn absolute_at(mut self, left: f32, top: f32) -> Self {
1768 self.0.style = self.0.style.absolute_at(left, top);
1769 self
1770 }
1771
1772 pub fn absolute_inset(mut self, inset: Inset) -> Self {
1773 self.0.style = self.0.style.absolute_inset(inset);
1774 self
1775 }
1776
1777 pub fn expand(self) -> Self {
1778 self.flex(1.0)
1779 }
1780
1781 pub fn fill_width(mut self) -> Self {
1782 self.0.style = self.0.style.width(Length::Fill(1.0));
1783 self
1784 }
1785
1786 pub fn fill_height(mut self) -> Self {
1787 self.0.style = self.0.style.height(Length::Fill(1.0));
1788 self
1789 }
1790
1791 pub fn fill_size(self) -> Self {
1792 self.fill_width().fill_height()
1793 }
1794
1795 pub fn fit(mut self) -> Self {
1796 self.0.style = self.0.style.fit();
1797 self
1798 }
1799
1800 pub fn hit_testable(mut self, on: bool) -> Self {
1801 self.0.style = self.0.style.hit_testable(on);
1802 self
1803 }
1804
1805 pub fn align_items(mut self, align: Align) -> Self {
1806 self.0.align = align;
1807 self
1808 }
1809
1810 pub fn justify_content(mut self, justify: Justify) -> Self {
1811 self.0.justify = justify;
1812 self
1813 }
1814
1815 pub fn center(mut self) -> Self {
1816 self.0.align = Align::Center;
1817 self.0.justify = Justify::Center;
1818 self
1819 }
1820
1821 pub fn background(mut self, color: Color) -> Self {
1822 self.0.deco = self.0.deco.background(color);
1823 self
1824 }
1825
1826 pub fn border(mut self, width: f32, color: Color) -> Self {
1827 self.0.deco = self.0.deco.border(width, color);
1828 self
1829 }
1830
1831 pub fn border_left(mut self, width: f32, color: Color) -> Self {
1832 self.0.deco = self.0.deco.border_left(width, color);
1833 self
1834 }
1835
1836 pub fn border_right(mut self, width: f32, color: Color) -> Self {
1837 self.0.deco = self.0.deco.border_right(width, color);
1838 self
1839 }
1840
1841 pub fn border_top(mut self, width: f32, color: Color) -> Self {
1842 self.0.deco = self.0.deco.border_top(width, color);
1843 self
1844 }
1845
1846 pub fn border_bottom(mut self, width: f32, color: Color) -> Self {
1847 self.0.deco = self.0.deco.border_bottom(width, color);
1848 self
1849 }
1850
1851 pub fn border_x(mut self, width: f32, color: Color) -> Self {
1852 self.0.deco = self.0.deco.border_x(width, color);
1853 self
1854 }
1855
1856 pub fn border_y(mut self, width: f32, color: Color) -> Self {
1857 self.0.deco = self.0.deco.border_y(width, color);
1858 self
1859 }
1860
1861 pub fn radius(mut self, radius: f32) -> Self {
1862 self.0.deco = self.0.deco.radius(radius);
1863 self
1864 }
1865
1866 pub fn box_style(mut self, style: BoxStyle) -> Self {
1867 self.0.deco = style;
1868 self
1869 }
1870
1871 pub fn style(self, style: BoxStyle) -> Self {
1872 self.box_style(style)
1873 }
1874 }
1875 };
1876}
1877
1878pub struct Row(Flex);
1879
1880impl Row {
1881 pub fn new() -> Self {
1882 Self(Flex::new(Axis::Horizontal))
1883 }
1884
1885 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
1886 self.0.children.push(AnyView::new(child));
1887 self.0.flex.push(0.0);
1888 self
1889 }
1890
1891 pub fn child_flex<V: View + 'static>(mut self, child: V, flex: f32) -> Self {
1892 self.0.children.push(AnyView::new(child));
1893 self.0.flex.push(Flex::sanitize_flex(flex));
1894 self
1895 }
1896
1897 pub fn children(mut self, children: impl IntoChildren) -> Self {
1898 let mut children = children.into_children();
1899 self.0.flex.extend(std::iter::repeat_n(0.0, children.len()));
1900 self.0.children.append(&mut children);
1901 self
1902 }
1903}
1904
1905impl Default for Row {
1906 fn default() -> Self {
1907 Self::new()
1908 }
1909}
1910
1911impl View for Row {
1912 fn body(&self) -> impl View + 'static {
1913 Unit
1914 }
1915 fn children_override(&self) -> Option<Vec<AnyView>> {
1916 self.0.children_override()
1917 }
1918 fn layout_style(&self) -> LayoutStyle {
1919 self.0.layout_style()
1920 }
1921 fn container(&self) -> Option<ContainerStyle> {
1922 self.0.container()
1923 }
1924 fn flex_weights(&self) -> Option<&[f32]> {
1925 Some(&self.0.flex)
1926 }
1927 fn paint_self(&self, ctx: &mut PaintCtx) {
1928 ctx.paint_box(self.0.deco);
1929 }
1930}
1931
1932impl_flex_container!(Row, Axis::Horizontal);
1933
1934pub struct Column(Flex);
1935
1936impl Column {
1937 pub fn new() -> Self {
1938 Self(Flex::new(Axis::Vertical))
1939 }
1940
1941 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
1942 self.0.children.push(AnyView::new(child));
1943 self.0.flex.push(0.0);
1944 self
1945 }
1946
1947 pub fn child_flex<V: View + 'static>(mut self, child: V, flex: f32) -> Self {
1948 self.0.children.push(AnyView::new(child));
1949 self.0.flex.push(Flex::sanitize_flex(flex));
1950 self
1951 }
1952
1953 pub fn children(mut self, children: impl IntoChildren) -> Self {
1954 let mut children = children.into_children();
1955 self.0.flex.extend(std::iter::repeat_n(0.0, children.len()));
1956 self.0.children.append(&mut children);
1957 self
1958 }
1959}
1960
1961impl Default for Column {
1962 fn default() -> Self {
1963 Self::new()
1964 }
1965}
1966
1967impl View for Column {
1968 fn body(&self) -> impl View + 'static {
1969 Unit
1970 }
1971 fn children_override(&self) -> Option<Vec<AnyView>> {
1972 self.0.children_override()
1973 }
1974 fn layout_style(&self) -> LayoutStyle {
1975 self.0.layout_style()
1976 }
1977 fn container(&self) -> Option<ContainerStyle> {
1978 self.0.container()
1979 }
1980 fn flex_weights(&self) -> Option<&[f32]> {
1981 Some(&self.0.flex)
1982 }
1983 fn paint_self(&self, ctx: &mut PaintCtx) {
1984 ctx.paint_box(self.0.deco);
1985 }
1986}
1987
1988impl_flex_container!(Column, Axis::Vertical);
1989
1990#[derive(Clone)]
1991pub struct Stack {
1992 children: Vec<AnyView>,
1993 positions: Vec<StackPos>,
1994 style: LayoutStyle,
1995 deco: BoxStyle,
1996}
1997
1998impl Default for Stack {
1999 fn default() -> Self {
2000 Self {
2001 children: Vec::new(),
2002 positions: Vec::new(),
2003 style: LayoutStyle::default(),
2004 deco: BoxStyle::new(),
2005 }
2006 }
2007}
2008
2009#[derive(Clone, Copy, Debug, Default, PartialEq)]
2010pub struct StackPos {
2011 pub top: Option<f32>,
2012
2013 pub left: Option<f32>,
2014
2015 pub bottom: Option<f32>,
2016
2017 pub right: Option<f32>,
2018
2019 pub dx: f32,
2020
2021 pub dy: f32,
2022
2023 pub z: i32,
2024}
2025
2026impl StackPos {
2027 pub const fn top() -> Self {
2028 Self {
2029 top: Some(0.0),
2030 left: None,
2031 bottom: None,
2032 right: None,
2033 dx: 0.0,
2034 dy: 0.0,
2035 z: 0,
2036 }
2037 }
2038
2039 pub const fn bottom() -> Self {
2040 Self {
2041 top: None,
2042 left: None,
2043 bottom: Some(0.0),
2044 right: None,
2045 dx: 0.0,
2046 dy: 0.0,
2047 z: 0,
2048 }
2049 }
2050
2051 pub const fn left() -> Self {
2052 Self {
2053 top: None,
2054 left: Some(0.0),
2055 bottom: None,
2056 right: None,
2057 dx: 0.0,
2058 dy: 0.0,
2059 z: 0,
2060 }
2061 }
2062
2063 pub const fn right() -> Self {
2064 Self {
2065 top: None,
2066 left: None,
2067 bottom: None,
2068 right: Some(0.0),
2069 dx: 0.0,
2070 dy: 0.0,
2071 z: 0,
2072 }
2073 }
2074
2075 pub const fn top_left() -> Self {
2076 Self {
2077 top: Some(0.0),
2078 left: Some(0.0),
2079 bottom: None,
2080 right: None,
2081 dx: 0.0,
2082 dy: 0.0,
2083 z: 0,
2084 }
2085 }
2086
2087 pub const fn top_right() -> Self {
2088 Self {
2089 top: Some(0.0),
2090 left: None,
2091 bottom: None,
2092 right: Some(0.0),
2093 dx: 0.0,
2094 dy: 0.0,
2095 z: 0,
2096 }
2097 }
2098
2099 pub const fn bottom_left() -> Self {
2100 Self {
2101 top: None,
2102 left: Some(0.0),
2103 bottom: Some(0.0),
2104 right: None,
2105 dx: 0.0,
2106 dy: 0.0,
2107 z: 0,
2108 }
2109 }
2110
2111 pub const fn bottom_right() -> Self {
2112 Self {
2113 top: None,
2114 left: None,
2115 bottom: Some(0.0),
2116 right: Some(0.0),
2117 dx: 0.0,
2118 dy: 0.0,
2119 z: 0,
2120 }
2121 }
2122
2123 pub const fn fill() -> Self {
2124 Self {
2125 top: Some(0.0),
2126 left: Some(0.0),
2127 bottom: Some(0.0),
2128 right: Some(0.0),
2129 dx: 0.0,
2130 dy: 0.0,
2131 z: 0,
2132 }
2133 }
2134
2135 pub const fn offset(mut self, dx: f32, dy: f32) -> Self {
2136 self.dx = dx;
2137 self.dy = dy;
2138 self
2139 }
2140
2141 pub const fn z(mut self, z: i32) -> Self {
2142 self.z = z;
2143 self
2144 }
2145
2146 pub const fn is_pinned(self) -> bool {
2147 self.top.is_some() || self.left.is_some() || self.bottom.is_some() || self.right.is_some()
2148 }
2149}
2150
2151impl Stack {
2152 pub fn new() -> Self {
2153 Self::default()
2154 }
2155
2156 fn stack_axis(len: Length, measured: f32, start: f32, extent: f32) -> (f32, f32) {
2157 if len.is_fill() && extent.is_finite() {
2158 return (extent.max(0.0), start);
2159 }
2160
2161 let size = measured.max(0.0);
2162 let off = if extent.is_finite() {
2163 ((extent - size) * 0.5).max(0.0)
2164 } else {
2165 0.0
2166 };
2167 (size, start + off)
2168 }
2169
2170 fn pinned_axis(
2171 pin_start: Option<f32>,
2172 pin_end: Option<f32>,
2173 delta: f32,
2174 len: Length,
2175 measured: f32,
2176 start: f32,
2177 extent: f32,
2178 ) -> (f32, f32) {
2179 let delta = if delta.is_finite() { delta } else { 0.0 };
2180 if !extent.is_finite() {
2181 return (measured.max(0.0), start + delta);
2182 }
2183 let extent = extent.max(0.0);
2184 match (pin_start, pin_end) {
2185 (Some(a), Some(b)) => {
2186 let x = a.max(0.0);
2187 let w = (extent - a.max(0.0) - b.max(0.0)).max(0.0);
2188 (w, start + x + delta)
2189 }
2190 (Some(a), None) => {
2191 let size = if len.is_fill() {
2192 (extent - a.max(0.0)).max(0.0)
2193 } else {
2194 measured.max(0.0)
2195 };
2196 (size, start + a + delta)
2197 }
2198 (None, Some(b)) => {
2199 let size = if len.is_fill() {
2200 (extent - b.max(0.0)).max(0.0)
2201 } else {
2202 measured.max(0.0)
2203 };
2204 (size, start + extent - b - size + delta)
2205 }
2206 (None, None) => {
2207 let (size, off) = Self::stack_axis(len, measured, start, extent);
2208 (size, off + delta)
2209 }
2210 }
2211 }
2212
2213 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
2214 self.children.push(AnyView::new(child));
2215 self.positions.push(StackPos::default());
2216 self
2217 }
2218
2219 pub fn child_at<V: View + 'static>(mut self, child: V, pos: StackPos) -> Self {
2220 self.children.push(AnyView::new(child));
2221 self.positions.push(pos);
2222 self
2223 }
2224
2225 pub fn child_z<V: View + 'static>(mut self, child: V, z: i32) -> Self {
2226 self.children.push(AnyView::new(child));
2227 self.positions.push(StackPos::default().z(z));
2228 self
2229 }
2230
2231 pub fn fill<V: View + 'static>(mut self, child: V) -> Self {
2232 self.children.push(AnyView::new(child));
2233 self.positions.push(StackPos::fill());
2234 self
2235 }
2236
2237 pub fn overlay<V: View + 'static>(mut self, child: V, dx: f32, dy: f32) -> Self {
2238 self.children.push(AnyView::new(child));
2239 self.positions.push(StackPos::top_left().offset(dx, dy));
2240 self
2241 }
2242
2243 pub fn hud<V: View + 'static>(mut self, child: V, dy: f32) -> Self {
2244 self.children.push(AnyView::new(child));
2245 self.positions.push(StackPos::bottom().offset(0.0, dy));
2246 self
2247 }
2248
2249 fn paint_order(&self) -> Option<Vec<usize>> {
2250 if self.positions.windows(2).all(|w| w[0].z <= w[1].z) {
2251 return None;
2252 }
2253 let mut order: Vec<usize> = (0..self.children.len()).collect();
2254 order.sort_by_key(|&i| self.positions.get(i).map_or(0, |p| p.z));
2255 Some(order)
2256 }
2257
2258 fn pos_at(&self, i: usize, order: Option<&[usize]>) -> StackPos {
2259 match order {
2260 None => self.positions.get(i).copied().unwrap_or_default(),
2261 Some(order) => order
2262 .get(i)
2263 .and_then(|&k| self.positions.get(k))
2264 .copied()
2265 .unwrap_or_default(),
2266 }
2267 }
2268
2269 pub fn children(mut self, children: impl IntoChildren) -> Self {
2270 for c in children.into_children() {
2271 self.children.push(c);
2272 self.positions.push(StackPos::default());
2273 }
2274 self
2275 }
2276
2277 pub fn padding(mut self, padding: impl Into<Edges>) -> Self {
2278 self.style = self.style.padding(padding);
2279 self
2280 }
2281
2282 pub fn pad(self, padding: impl Into<Edges>) -> Self {
2283 self.padding(padding)
2284 }
2285
2286 pub fn padding_xy(mut self, x: f32, y: f32) -> Self {
2287 self.style = self.style.padding_xy(x, y);
2288 self
2289 }
2290
2291 pub fn padding_x(mut self, x: f32) -> Self {
2292 self.style = self.style.padding_x(x);
2293 self
2294 }
2295
2296 pub fn padding_y(mut self, y: f32) -> Self {
2297 self.style = self.style.padding_y(y);
2298 self
2299 }
2300
2301 pub fn padding_left(mut self, v: f32) -> Self {
2302 self.style = self.style.padding_left(v);
2303 self
2304 }
2305
2306 pub fn padding_right(mut self, v: f32) -> Self {
2307 self.style = self.style.padding_right(v);
2308 self
2309 }
2310
2311 pub fn padding_top(mut self, v: f32) -> Self {
2312 self.style = self.style.padding_top(v);
2313 self
2314 }
2315
2316 pub fn padding_bottom(mut self, v: f32) -> Self {
2317 self.style = self.style.padding_bottom(v);
2318 self
2319 }
2320
2321 pub fn width(mut self, width: impl Into<Length>) -> Self {
2322 self.style = self.style.width(width.into());
2323 self
2324 }
2325
2326 pub fn height(mut self, height: impl Into<Length>) -> Self {
2327 self.style = self.style.height(height.into());
2328 self
2329 }
2330
2331 pub fn size(mut self, width: impl Into<Length>, height: impl Into<Length>) -> Self {
2332 self.style = self.style.width(width.into()).height(height.into());
2333 self
2334 }
2335
2336 pub fn square(mut self, side: impl Into<Length>) -> Self {
2337 let side = side.into();
2338 self.style = self.style.width(side).height(side);
2339 self
2340 }
2341
2342 pub fn min_width(mut self, v: f32) -> Self {
2343 self.style = self.style.min_width(v);
2344 self
2345 }
2346
2347 pub fn max_width(mut self, v: f32) -> Self {
2348 self.style = self.style.max_width(v);
2349 self
2350 }
2351
2352 pub fn min_height(mut self, v: f32) -> Self {
2353 self.style = self.style.min_height(v);
2354 self
2355 }
2356
2357 pub fn max_height(mut self, v: f32) -> Self {
2358 self.style = self.style.max_height(v);
2359 self
2360 }
2361
2362 pub fn overflow(mut self, overflow: Overflow) -> Self {
2363 self.style = self.style.overflow(overflow);
2364 self
2365 }
2366
2367 pub fn flex(mut self, weight: f32) -> Self {
2368 self.style = self.style.flex(weight);
2369 self
2370 }
2371
2372 pub fn expand(self) -> Self {
2373 self.flex(1.0)
2374 }
2375
2376 pub fn fill_width(mut self) -> Self {
2377 self.style = self.style.width(Length::Fill(1.0));
2378 self
2379 }
2380
2381 pub fn fill_height(mut self) -> Self {
2382 self.style = self.style.height(Length::Fill(1.0));
2383 self
2384 }
2385
2386 pub fn fill_size(self) -> Self {
2387 self.fill_width().fill_height()
2388 }
2389
2390 pub fn background(mut self, color: Color) -> Self {
2391 self.deco = self.deco.background(color);
2392 self
2393 }
2394
2395 pub fn border(mut self, width: f32, color: Color) -> Self {
2396 self.deco = self.deco.border(width, color);
2397 self
2398 }
2399
2400 pub fn border_left(mut self, width: f32, color: Color) -> Self {
2401 self.deco = self.deco.border_left(width, color);
2402 self
2403 }
2404
2405 pub fn border_right(mut self, width: f32, color: Color) -> Self {
2406 self.deco = self.deco.border_right(width, color);
2407 self
2408 }
2409
2410 pub fn border_top(mut self, width: f32, color: Color) -> Self {
2411 self.deco = self.deco.border_top(width, color);
2412 self
2413 }
2414
2415 pub fn border_bottom(mut self, width: f32, color: Color) -> Self {
2416 self.deco = self.deco.border_bottom(width, color);
2417 self
2418 }
2419
2420 pub fn border_x(mut self, width: f32, color: Color) -> Self {
2421 self.deco = self.deco.border_x(width, color);
2422 self
2423 }
2424
2425 pub fn border_y(mut self, width: f32, color: Color) -> Self {
2426 self.deco = self.deco.border_y(width, color);
2427 self
2428 }
2429
2430 pub fn radius(mut self, radius: f32) -> Self {
2431 self.deco = self.deco.radius(radius);
2432 self
2433 }
2434
2435 pub fn box_style(mut self, style: BoxStyle) -> Self {
2436 self.deco = style;
2437 self
2438 }
2439
2440 pub fn style(self, style: BoxStyle) -> Self {
2441 self.box_style(style)
2442 }
2443}
2444
2445impl_style_extras!(Stack);
2446
2447impl View for Stack {
2448 fn body(&self) -> impl View + 'static {
2449 Unit
2450 }
2451 fn children_override(&self) -> Option<Vec<AnyView>> {
2452 Some(match self.paint_order() {
2453 None => self.children.clone(),
2454 Some(order) => order
2455 .iter()
2456 .filter_map(|&i| self.children.get(i).cloned())
2457 .collect(),
2458 })
2459 }
2460 fn layout_style(&self) -> LayoutStyle {
2461 let mut style = self.style;
2462 let edges = self.deco.border_edges();
2463 style.padding.left += edges.left;
2464 style.padding.top += edges.top;
2465 style.padding.right += edges.right;
2466 style.padding.bottom += edges.bottom;
2467 style
2468 }
2469 fn paint_self(&self, ctx: &mut PaintCtx) {
2470 ctx.paint_box(self.deco);
2471 }
2472 fn arrange_override(
2473 &self,
2474 rt: &Runtime,
2475 el: ElementId,
2476 rect: Rect,
2477 ctx: &mut LayoutCtx,
2478 ) -> bool {
2479 let mut pad = self.style.padding;
2480 let edges = self.deco.border_edges();
2481 pad.left += edges.left;
2482 pad.top += edges.top;
2483 pad.right += edges.right;
2484 pad.bottom += edges.bottom;
2485 let content = Rect::from_xywh(
2486 rect.left() + pad.left,
2487 rect.top() + pad.top,
2488 (rect.size.width - pad.horizontal_sum()).max(0.0),
2489 (rect.size.height - pad.vertical_sum()).max(0.0),
2490 );
2491 let max = Size::new(content.size.width, content.size.height);
2492 let order = self.paint_order();
2493 let kids = rt.children(el);
2494 for (i, child) in kids.iter().enumerate() {
2495 let style = rt.child_layout_style(*child);
2496
2497 if style.is_absolute() {
2498 rt.arrange_absolute(*child, content, ctx);
2499 continue;
2500 }
2501 let pos = self.pos_at(i, order.as_deref());
2502
2503 let m = rt.measure_node(
2504 *child,
2505 Constraints {
2506 min: Size::ZERO,
2507 max,
2508 },
2509 ctx,
2510 );
2511 let (w0, x) = Self::pinned_axis(
2512 pos.left,
2513 pos.right,
2514 pos.dx,
2515 style.width,
2516 m.width,
2517 content.left(),
2518 content.size.width,
2519 );
2520 let (h0, y) = Self::pinned_axis(
2521 pos.top,
2522 pos.bottom,
2523 pos.dy,
2524 style.height,
2525 m.height,
2526 content.top(),
2527 content.size.height,
2528 );
2529
2530 let w = style.clamp_width(w0).max(0.0);
2531 let h = style.clamp_height(h0).max(0.0);
2532 rt.arrange_node(*child, Rect::from_xywh(x, y, w, h), ctx);
2533 }
2534 true
2535 }
2536}
2537
2538pub struct Grid {
2539 children: Vec<AnyView>,
2540 placements: Vec<GridPlacement>,
2541 style: LayoutStyle,
2542 grid: GridStyle,
2543 deco: BoxStyle,
2544}
2545
2546impl Grid {
2547 pub fn new(columns: impl IntoIterator<Item = Track>) -> Self {
2548 Self {
2549 children: Vec::new(),
2550 placements: Vec::new(),
2551 style: LayoutStyle {
2552 width: Length::Fit,
2553 height: Length::Fit,
2554 ..LayoutStyle::default()
2555 },
2556 grid: GridStyle::new(columns),
2557 deco: BoxStyle::new(),
2558 }
2559 }
2560
2561 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
2562 self.children.push(AnyView::new(child));
2563 self.placements.push(GridPlacement::AUTO);
2564 self
2565 }
2566
2567 pub fn child_at<V: View + 'static>(mut self, child: V, placement: GridPlacement) -> Self {
2568 self.children.push(AnyView::new(child));
2569 self.placements.push(placement);
2570 self
2571 }
2572
2573 pub fn child_span<V: View + 'static>(
2574 mut self,
2575 child: V,
2576 column: usize,
2577 row: usize,
2578 col_span: usize,
2579 row_span: usize,
2580 ) -> Self {
2581 self.children.push(AnyView::new(child));
2582 self.placements.push(
2583 GridPlacement::new()
2584 .at(column, row)
2585 .span(col_span, row_span),
2586 );
2587 self
2588 }
2589
2590 pub fn children(mut self, children: impl IntoChildren) -> Self {
2591 let mut children = children.into_children();
2592 self.placements
2593 .extend(std::iter::repeat_n(GridPlacement::AUTO, children.len()));
2594 self.children.append(&mut children);
2595 self
2596 }
2597
2598 pub fn rows(mut self, rows: impl IntoIterator<Item = Track>) -> Self {
2599 self.grid = self.grid.rows(rows);
2600 self
2601 }
2602
2603 pub fn gap(mut self, gap: f32) -> Self {
2604 self.grid = self.grid.gap(gap);
2605 self
2606 }
2607
2608 pub fn column_gap(mut self, gap: f32) -> Self {
2609 self.grid = self.grid.column_gap(gap);
2610 self
2611 }
2612
2613 pub fn row_gap(mut self, gap: f32) -> Self {
2614 self.grid = self.grid.row_gap(gap);
2615 self
2616 }
2617
2618 pub fn auto_flow(mut self, flow: GridFlow) -> Self {
2619 self.grid = self.grid.auto_flow(flow);
2620 self
2621 }
2622
2623 pub fn column_flow(mut self) -> Self {
2624 self.grid = self.grid.column_flow();
2625 self
2626 }
2627
2628 pub fn align_items(mut self, align: Align) -> Self {
2629 self.grid = self.grid.align_items(align);
2630 self
2631 }
2632
2633 pub fn justify_items(mut self, align: Align) -> Self {
2634 self.grid = self.grid.justify_items(align);
2635 self
2636 }
2637
2638 pub fn place_items(mut self, align: Align) -> Self {
2639 self.grid = self.grid.place_items(align);
2640 self
2641 }
2642
2643 pub fn margin(mut self, margin: impl Into<Edges>) -> Self {
2644 self.style = self.style.margin(margin);
2645 self
2646 }
2647
2648 pub fn margin_xy(mut self, x: f32, y: f32) -> Self {
2649 self.style = self.style.margin_xy(x, y);
2650 self
2651 }
2652
2653 pub fn margin_x(mut self, x: f32) -> Self {
2654 self.style = self.style.margin_x(x);
2655 self
2656 }
2657
2658 pub fn margin_y(mut self, y: f32) -> Self {
2659 self.style = self.style.margin_y(y);
2660 self
2661 }
2662
2663 pub fn margin_left(mut self, v: f32) -> Self {
2664 self.style = self.style.margin_left(v);
2665 self
2666 }
2667
2668 pub fn margin_right(mut self, v: f32) -> Self {
2669 self.style = self.style.margin_right(v);
2670 self
2671 }
2672
2673 pub fn margin_top(mut self, v: f32) -> Self {
2674 self.style = self.style.margin_top(v);
2675 self
2676 }
2677
2678 pub fn margin_bottom(mut self, v: f32) -> Self {
2679 self.style = self.style.margin_bottom(v);
2680 self
2681 }
2682
2683 pub fn padding(mut self, padding: impl Into<Edges>) -> Self {
2684 self.style = self.style.padding(padding);
2685 self
2686 }
2687
2688 pub fn pad(self, padding: impl Into<Edges>) -> Self {
2689 self.padding(padding)
2690 }
2691
2692 pub fn padding_xy(mut self, x: f32, y: f32) -> Self {
2693 self.style = self.style.padding_xy(x, y);
2694 self
2695 }
2696
2697 pub fn padding_x(mut self, x: f32) -> Self {
2698 self.style = self.style.padding_x(x);
2699 self
2700 }
2701
2702 pub fn padding_y(mut self, y: f32) -> Self {
2703 self.style = self.style.padding_y(y);
2704 self
2705 }
2706
2707 pub fn padding_left(mut self, v: f32) -> Self {
2708 self.style = self.style.padding_left(v);
2709 self
2710 }
2711
2712 pub fn padding_right(mut self, v: f32) -> Self {
2713 self.style = self.style.padding_right(v);
2714 self
2715 }
2716
2717 pub fn padding_top(mut self, v: f32) -> Self {
2718 self.style = self.style.padding_top(v);
2719 self
2720 }
2721
2722 pub fn padding_bottom(mut self, v: f32) -> Self {
2723 self.style = self.style.padding_bottom(v);
2724 self
2725 }
2726
2727 pub fn width(mut self, width: impl Into<Length>) -> Self {
2728 self.style = self.style.width(width.into());
2729 self
2730 }
2731
2732 pub fn height(mut self, height: impl Into<Length>) -> Self {
2733 self.style = self.style.height(height.into());
2734 self
2735 }
2736
2737 pub fn size(mut self, width: impl Into<Length>, height: impl Into<Length>) -> Self {
2738 self.style = self.style.width(width.into()).height(height.into());
2739 self
2740 }
2741
2742 pub fn square(mut self, side: impl Into<Length>) -> Self {
2743 let side = side.into();
2744 self.style = self.style.width(side).height(side);
2745 self
2746 }
2747
2748 pub fn min_width(mut self, v: f32) -> Self {
2749 self.style = self.style.min_width(v);
2750 self
2751 }
2752
2753 pub fn max_width(mut self, v: f32) -> Self {
2754 self.style = self.style.max_width(v);
2755 self
2756 }
2757
2758 pub fn min_height(mut self, v: f32) -> Self {
2759 self.style = self.style.min_height(v);
2760 self
2761 }
2762
2763 pub fn max_height(mut self, v: f32) -> Self {
2764 self.style = self.style.max_height(v);
2765 self
2766 }
2767
2768 pub fn overflow(mut self, overflow: Overflow) -> Self {
2769 self.style = self.style.overflow(overflow);
2770 self
2771 }
2772
2773 pub fn flex(mut self, weight: f32) -> Self {
2774 self.style = self.style.flex(weight);
2775 self
2776 }
2777
2778 pub fn flex_shrink(mut self, shrink: f32) -> Self {
2779 self.style = self.style.flex_shrink(shrink);
2780 self
2781 }
2782
2783 pub fn flex_basis(mut self, basis: Option<Length>) -> Self {
2784 self.style = self.style.flex_basis(basis);
2785 self
2786 }
2787
2788 pub fn align_self(mut self, align: Option<Align>) -> Self {
2789 self.style = self.style.align_self(align);
2790 self
2791 }
2792
2793 pub fn aspect_ratio(mut self, ratio: Option<f32>) -> Self {
2794 self.style = self.style.aspect_ratio(ratio);
2795 self
2796 }
2797
2798 pub fn aspect(mut self, ratio: f32) -> Self {
2799 self.style = self.style.aspect(ratio);
2800 self
2801 }
2802
2803 pub fn position(mut self, position: Position) -> Self {
2804 self.style = self.style.position(position);
2805 self
2806 }
2807
2808 pub fn absolute(mut self) -> Self {
2809 self.style = self.style.absolute();
2810 self
2811 }
2812
2813 pub fn absolute_at(mut self, left: f32, top: f32) -> Self {
2814 self.style = self.style.absolute_at(left, top);
2815 self
2816 }
2817
2818 pub fn absolute_inset(mut self, inset: Inset) -> Self {
2819 self.style = self.style.absolute_inset(inset);
2820 self
2821 }
2822
2823 pub fn expand(self) -> Self {
2824 self.flex(1.0)
2825 }
2826
2827 pub fn fill_width(mut self) -> Self {
2828 self.style = self.style.width(Length::Fill(1.0));
2829 self
2830 }
2831
2832 pub fn fill_height(mut self) -> Self {
2833 self.style = self.style.height(Length::Fill(1.0));
2834 self
2835 }
2836
2837 pub fn fill_size(self) -> Self {
2838 self.fill_width().fill_height()
2839 }
2840
2841 pub fn background(mut self, color: Color) -> Self {
2842 self.deco = self.deco.background(color);
2843 self
2844 }
2845
2846 pub fn border(mut self, width: f32, color: Color) -> Self {
2847 self.deco = self.deco.border(width, color);
2848 self
2849 }
2850
2851 pub fn border_left(mut self, width: f32, color: Color) -> Self {
2852 self.deco = self.deco.border_left(width, color);
2853 self
2854 }
2855
2856 pub fn border_right(mut self, width: f32, color: Color) -> Self {
2857 self.deco = self.deco.border_right(width, color);
2858 self
2859 }
2860
2861 pub fn border_top(mut self, width: f32, color: Color) -> Self {
2862 self.deco = self.deco.border_top(width, color);
2863 self
2864 }
2865
2866 pub fn border_bottom(mut self, width: f32, color: Color) -> Self {
2867 self.deco = self.deco.border_bottom(width, color);
2868 self
2869 }
2870
2871 pub fn border_x(mut self, width: f32, color: Color) -> Self {
2872 self.deco = self.deco.border_x(width, color);
2873 self
2874 }
2875
2876 pub fn border_y(mut self, width: f32, color: Color) -> Self {
2877 self.deco = self.deco.border_y(width, color);
2878 self
2879 }
2880
2881 pub fn radius(mut self, radius: f32) -> Self {
2882 self.deco = self.deco.radius(radius);
2883 self
2884 }
2885
2886 pub fn box_style(mut self, style: BoxStyle) -> Self {
2887 self.deco = style;
2888 self
2889 }
2890
2891 pub fn style(self, style: BoxStyle) -> Self {
2892 self.box_style(style)
2893 }
2894}
2895
2896impl View for Grid {
2897 fn body(&self) -> impl View + 'static {
2898 Unit
2899 }
2900 fn children_override(&self) -> Option<Vec<AnyView>> {
2901 Some(self.children.clone())
2902 }
2903 fn layout_style(&self) -> LayoutStyle {
2904 self.style
2905 }
2906 fn grid(&self) -> Option<GridStyle> {
2907 Some(self.grid.clone())
2908 }
2909 fn grid_placements(&self) -> Option<Vec<GridPlacement>> {
2910 Some(self.placements.clone())
2911 }
2912 fn paint_self(&self, ctx: &mut PaintCtx) {
2913 ctx.paint_box(self.deco);
2914 }
2915}
2916
2917pub struct Wrap {
2918 children: Vec<AnyView>,
2919 style: LayoutStyle,
2920 wrap: WrapStyle,
2921 deco: BoxStyle,
2922}
2923
2924impl Wrap {
2925 pub fn new() -> Self {
2926 Self {
2927 children: Vec::new(),
2928 style: LayoutStyle {
2929 width: Length::Fill(1.0),
2930 height: Length::Fit,
2931 ..LayoutStyle::default()
2932 },
2933 wrap: WrapStyle::new(Axis::Horizontal),
2934 deco: BoxStyle::new(),
2935 }
2936 }
2937
2938 pub fn vertical() -> Self {
2939 Self {
2940 wrap: WrapStyle::new(Axis::Vertical),
2941 ..Self::new()
2942 }
2943 }
2944
2945 pub fn axis(mut self, axis: Axis) -> Self {
2946 self.wrap = self.wrap.axis(axis);
2947 self
2948 }
2949
2950 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
2951 self.children.push(AnyView::new(child));
2952 self
2953 }
2954
2955 pub fn children(mut self, children: impl IntoChildren) -> Self {
2956 self.children.extend(children.into_children());
2957 self
2958 }
2959
2960 pub fn gap(mut self, gap: f32) -> Self {
2961 self.wrap = self.wrap.gap(gap);
2962 self
2963 }
2964
2965 pub fn column_gap(mut self, gap: f32) -> Self {
2966 self.wrap = self.wrap.column_gap(gap);
2967 self
2968 }
2969
2970 pub fn row_gap(mut self, gap: f32) -> Self {
2971 self.wrap = self.wrap.row_gap(gap);
2972 self
2973 }
2974
2975 pub fn align_items(mut self, align: Align) -> Self {
2976 self.wrap = self.wrap.align(align);
2977 self
2978 }
2979
2980 pub fn columns(mut self, columns: usize) -> Self {
2981 self.wrap = self.wrap.columns(columns);
2982 self
2983 }
2984
2985 pub fn rows(mut self, rows: usize) -> Self {
2986 self.wrap = self.wrap.rows(rows);
2987 self
2988 }
2989
2990 pub fn clear_columns(mut self) -> Self {
2991 self.wrap = self.wrap.clear_columns();
2992 self
2993 }
2994
2995 pub fn clear_rows(mut self) -> Self {
2996 self.wrap = self.wrap.clear_rows();
2997 self
2998 }
2999
3000 pub fn padding(mut self, padding: impl Into<Edges>) -> Self {
3001 self.style = self.style.padding(padding);
3002 self
3003 }
3004
3005 pub fn pad(self, padding: impl Into<Edges>) -> Self {
3006 self.padding(padding)
3007 }
3008
3009 pub fn padding_xy(mut self, x: f32, y: f32) -> Self {
3010 self.style = self.style.padding_xy(x, y);
3011 self
3012 }
3013
3014 pub fn padding_x(mut self, x: f32) -> Self {
3015 self.style = self.style.padding_x(x);
3016 self
3017 }
3018
3019 pub fn padding_y(mut self, y: f32) -> Self {
3020 self.style = self.style.padding_y(y);
3021 self
3022 }
3023
3024 pub fn padding_left(mut self, v: f32) -> Self {
3025 self.style = self.style.padding_left(v);
3026 self
3027 }
3028
3029 pub fn padding_right(mut self, v: f32) -> Self {
3030 self.style = self.style.padding_right(v);
3031 self
3032 }
3033
3034 pub fn padding_top(mut self, v: f32) -> Self {
3035 self.style = self.style.padding_top(v);
3036 self
3037 }
3038
3039 pub fn padding_bottom(mut self, v: f32) -> Self {
3040 self.style = self.style.padding_bottom(v);
3041 self
3042 }
3043
3044 pub fn width(mut self, width: impl Into<Length>) -> Self {
3045 self.style = self.style.width(width.into());
3046 self
3047 }
3048
3049 pub fn height(mut self, height: impl Into<Length>) -> Self {
3050 self.style = self.style.height(height.into());
3051 self
3052 }
3053
3054 pub fn size(mut self, width: impl Into<Length>, height: impl Into<Length>) -> Self {
3055 self.style = self.style.width(width.into()).height(height.into());
3056 self
3057 }
3058
3059 pub fn square(mut self, side: impl Into<Length>) -> Self {
3060 let side = side.into();
3061 self.style = self.style.width(side).height(side);
3062 self
3063 }
3064
3065 pub fn min_width(mut self, v: f32) -> Self {
3066 self.style = self.style.min_width(v);
3067 self
3068 }
3069
3070 pub fn max_width(mut self, v: f32) -> Self {
3071 self.style = self.style.max_width(v);
3072 self
3073 }
3074
3075 pub fn min_height(mut self, v: f32) -> Self {
3076 self.style = self.style.min_height(v);
3077 self
3078 }
3079
3080 pub fn max_height(mut self, v: f32) -> Self {
3081 self.style = self.style.max_height(v);
3082 self
3083 }
3084
3085 pub fn overflow(mut self, overflow: Overflow) -> Self {
3086 self.style = self.style.overflow(overflow);
3087 self
3088 }
3089
3090 pub fn flex(mut self, weight: f32) -> Self {
3091 self.style = self.style.flex(weight);
3092 self
3093 }
3094
3095 pub fn expand(self) -> Self {
3096 self.flex(1.0)
3097 }
3098
3099 pub fn fill_width(mut self) -> Self {
3100 self.style = self.style.width(Length::Fill(1.0));
3101 self
3102 }
3103
3104 pub fn fill_height(mut self) -> Self {
3105 self.style = self.style.height(Length::Fill(1.0));
3106 self
3107 }
3108
3109 pub fn fill_size(self) -> Self {
3110 self.fill_width().fill_height()
3111 }
3112
3113 pub fn background(mut self, color: Color) -> Self {
3114 self.deco = self.deco.background(color);
3115 self
3116 }
3117
3118 pub fn border(mut self, width: f32, color: Color) -> Self {
3119 self.deco = self.deco.border(width, color);
3120 self
3121 }
3122
3123 pub fn border_left(mut self, width: f32, color: Color) -> Self {
3124 self.deco = self.deco.border_left(width, color);
3125 self
3126 }
3127
3128 pub fn border_right(mut self, width: f32, color: Color) -> Self {
3129 self.deco = self.deco.border_right(width, color);
3130 self
3131 }
3132
3133 pub fn border_top(mut self, width: f32, color: Color) -> Self {
3134 self.deco = self.deco.border_top(width, color);
3135 self
3136 }
3137
3138 pub fn border_bottom(mut self, width: f32, color: Color) -> Self {
3139 self.deco = self.deco.border_bottom(width, color);
3140 self
3141 }
3142
3143 pub fn border_x(mut self, width: f32, color: Color) -> Self {
3144 self.deco = self.deco.border_x(width, color);
3145 self
3146 }
3147
3148 pub fn border_y(mut self, width: f32, color: Color) -> Self {
3149 self.deco = self.deco.border_y(width, color);
3150 self
3151 }
3152
3153 pub fn radius(mut self, radius: f32) -> Self {
3154 self.deco = self.deco.radius(radius);
3155 self
3156 }
3157
3158 pub fn box_style(mut self, style: BoxStyle) -> Self {
3159 self.deco = style;
3160 self
3161 }
3162
3163 pub fn style(self, style: BoxStyle) -> Self {
3164 self.box_style(style)
3165 }
3166}
3167
3168impl Default for Wrap {
3169 fn default() -> Self {
3170 Self::new()
3171 }
3172}
3173
3174impl_style_extras!(Wrap);
3175
3176impl View for Wrap {
3177 fn body(&self) -> impl View + 'static {
3178 Unit
3179 }
3180 fn children_override(&self) -> Option<Vec<AnyView>> {
3181 Some(self.children.clone())
3182 }
3183 fn layout_style(&self) -> LayoutStyle {
3184 self.style
3185 }
3186 fn wrap(&self) -> Option<WrapStyle> {
3187 Some(self.wrap)
3188 }
3189 fn paint_self(&self, ctx: &mut PaintCtx) {
3190 ctx.paint_box(self.deco);
3191 }
3192}
3193
3194pub struct Masonry {
3212 children: Vec<AnyView>,
3213 style: LayoutStyle,
3214 masonry: MasonryStyle,
3215 deco: BoxStyle,
3216}
3217
3218impl Masonry {
3219 pub fn new(columns: usize) -> Self {
3221 Self {
3222 children: Vec::new(),
3223 style: LayoutStyle {
3224 width: Length::Fill(1.0),
3225 height: Length::Fit,
3226 ..LayoutStyle::default()
3227 },
3228 masonry: MasonryStyle::new(columns),
3229 deco: BoxStyle::new(),
3230 }
3231 }
3232
3233 pub fn columns(mut self, columns: usize) -> Self {
3234 self.masonry = self.masonry.columns(columns);
3235 self
3236 }
3237
3238 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
3239 self.children.push(AnyView::new(child));
3240 self
3241 }
3242
3243 pub fn children(mut self, children: impl IntoChildren) -> Self {
3244 self.children.extend(children.into_children());
3245 self
3246 }
3247
3248 pub fn gap(mut self, gap: f32) -> Self {
3249 self.masonry = self.masonry.gap(gap);
3250 self
3251 }
3252
3253 pub fn column_gap(mut self, gap: f32) -> Self {
3254 self.masonry = self.masonry.column_gap(gap);
3255 self
3256 }
3257
3258 pub fn row_gap(mut self, gap: f32) -> Self {
3259 self.masonry = self.masonry.row_gap(gap);
3260 self
3261 }
3262
3263 pub fn align_items(mut self, align: Align) -> Self {
3264 self.masonry = self.masonry.align_items(align);
3265 self
3266 }
3267
3268 pub fn padding(mut self, padding: impl Into<Edges>) -> Self {
3269 self.style = self.style.padding(padding);
3270 self
3271 }
3272
3273 pub fn pad(self, padding: impl Into<Edges>) -> Self {
3274 self.padding(padding)
3275 }
3276
3277 pub fn padding_xy(mut self, x: f32, y: f32) -> Self {
3278 self.style = self.style.padding_xy(x, y);
3279 self
3280 }
3281
3282 pub fn padding_x(mut self, x: f32) -> Self {
3283 self.style = self.style.padding_x(x);
3284 self
3285 }
3286
3287 pub fn padding_y(mut self, y: f32) -> Self {
3288 self.style = self.style.padding_y(y);
3289 self
3290 }
3291
3292 pub fn padding_left(mut self, v: f32) -> Self {
3293 self.style = self.style.padding_left(v);
3294 self
3295 }
3296
3297 pub fn padding_right(mut self, v: f32) -> Self {
3298 self.style = self.style.padding_right(v);
3299 self
3300 }
3301
3302 pub fn padding_top(mut self, v: f32) -> Self {
3303 self.style = self.style.padding_top(v);
3304 self
3305 }
3306
3307 pub fn padding_bottom(mut self, v: f32) -> Self {
3308 self.style = self.style.padding_bottom(v);
3309 self
3310 }
3311
3312 pub fn width(mut self, width: impl Into<Length>) -> Self {
3313 self.style = self.style.width(width.into());
3314 self
3315 }
3316
3317 pub fn height(mut self, height: impl Into<Length>) -> Self {
3318 self.style = self.style.height(height.into());
3319 self
3320 }
3321
3322 pub fn size(mut self, width: impl Into<Length>, height: impl Into<Length>) -> Self {
3323 self.style = self.style.width(width.into()).height(height.into());
3324 self
3325 }
3326
3327 pub fn square(mut self, side: impl Into<Length>) -> Self {
3328 let side = side.into();
3329 self.style = self.style.width(side).height(side);
3330 self
3331 }
3332
3333 pub fn min_width(mut self, v: f32) -> Self {
3334 self.style = self.style.min_width(v);
3335 self
3336 }
3337
3338 pub fn max_width(mut self, v: f32) -> Self {
3339 self.style = self.style.max_width(v);
3340 self
3341 }
3342
3343 pub fn min_height(mut self, v: f32) -> Self {
3344 self.style = self.style.min_height(v);
3345 self
3346 }
3347
3348 pub fn max_height(mut self, v: f32) -> Self {
3349 self.style = self.style.max_height(v);
3350 self
3351 }
3352
3353 pub fn overflow(mut self, overflow: Overflow) -> Self {
3354 self.style = self.style.overflow(overflow);
3355 self
3356 }
3357
3358 pub fn flex(mut self, weight: f32) -> Self {
3359 self.style = self.style.flex(weight);
3360 self
3361 }
3362
3363 pub fn expand(self) -> Self {
3364 self.flex(1.0)
3365 }
3366
3367 pub fn fill_width(mut self) -> Self {
3368 self.style = self.style.width(Length::Fill(1.0));
3369 self
3370 }
3371
3372 pub fn fill_height(mut self) -> Self {
3373 self.style = self.style.height(Length::Fill(1.0));
3374 self
3375 }
3376
3377 pub fn fill_size(self) -> Self {
3378 self.fill_width().fill_height()
3379 }
3380
3381 pub fn background(mut self, color: Color) -> Self {
3382 self.deco = self.deco.background(color);
3383 self
3384 }
3385
3386 pub fn border(mut self, width: f32, color: Color) -> Self {
3387 self.deco = self.deco.border(width, color);
3388 self
3389 }
3390
3391 pub fn border_left(mut self, width: f32, color: Color) -> Self {
3392 self.deco = self.deco.border_left(width, color);
3393 self
3394 }
3395
3396 pub fn border_right(mut self, width: f32, color: Color) -> Self {
3397 self.deco = self.deco.border_right(width, color);
3398 self
3399 }
3400
3401 pub fn border_top(mut self, width: f32, color: Color) -> Self {
3402 self.deco = self.deco.border_top(width, color);
3403 self
3404 }
3405
3406 pub fn border_bottom(mut self, width: f32, color: Color) -> Self {
3407 self.deco = self.deco.border_bottom(width, color);
3408 self
3409 }
3410
3411 pub fn border_x(mut self, width: f32, color: Color) -> Self {
3412 self.deco = self.deco.border_x(width, color);
3413 self
3414 }
3415
3416 pub fn border_y(mut self, width: f32, color: Color) -> Self {
3417 self.deco = self.deco.border_y(width, color);
3418 self
3419 }
3420
3421 pub fn radius(mut self, radius: f32) -> Self {
3422 self.deco = self.deco.radius(radius);
3423 self
3424 }
3425
3426 pub fn box_style(mut self, style: BoxStyle) -> Self {
3427 self.deco = style;
3428 self
3429 }
3430
3431 pub fn style(self, style: BoxStyle) -> Self {
3432 self.box_style(style)
3433 }
3434}
3435
3436impl Default for Masonry {
3437 fn default() -> Self {
3438 Self::new(2)
3439 }
3440}
3441
3442impl_style_extras!(Masonry);
3443
3444impl View for Masonry {
3445 fn body(&self) -> impl View + 'static {
3446 Unit
3447 }
3448 fn children_override(&self) -> Option<Vec<AnyView>> {
3449 Some(self.children.clone())
3450 }
3451 fn layout_style(&self) -> LayoutStyle {
3452 self.style
3453 }
3454 fn masonry(&self) -> Option<MasonryStyle> {
3455 Some(self.masonry)
3456 }
3457 fn paint_self(&self, ctx: &mut PaintCtx) {
3458 ctx.paint_box(self.deco);
3459 }
3460}
3461
3462#[derive(Clone, Copy, Debug)]
3463pub struct Panel {
3464 color: Option<Color>,
3465 radius: f32,
3466 style: LayoutStyle,
3467 borders: BoxStyle,
3468}
3469
3470impl Default for Panel {
3471 fn default() -> Self {
3472 Self {
3473 color: None,
3474 radius: 0.0,
3475 style: LayoutStyle::default(),
3476 borders: BoxStyle::new(),
3477 }
3478 }
3479}
3480
3481impl Panel {
3482 pub fn new() -> Self {
3483 Self::default()
3484 }
3485
3486 pub fn background(mut self, color: Color) -> Self {
3487 self.color = Some(color);
3488 self
3489 }
3490
3491 pub fn radius(mut self, radius: f32) -> Self {
3492 self.radius = radius.max(0.0);
3493 self
3494 }
3495
3496 pub fn border(mut self, width: f32, color: Color) -> Self {
3497 self.borders = self.borders.border(width, color);
3498 self
3499 }
3500
3501 pub fn border_left(mut self, width: f32, color: Color) -> Self {
3502 self.borders = self.borders.border_left(width, color);
3503 self
3504 }
3505
3506 pub fn border_right(mut self, width: f32, color: Color) -> Self {
3507 self.borders = self.borders.border_right(width, color);
3508 self
3509 }
3510
3511 pub fn border_top(mut self, width: f32, color: Color) -> Self {
3512 self.borders = self.borders.border_top(width, color);
3513 self
3514 }
3515
3516 pub fn border_bottom(mut self, width: f32, color: Color) -> Self {
3517 self.borders = self.borders.border_bottom(width, color);
3518 self
3519 }
3520
3521 pub fn border_x(mut self, width: f32, color: Color) -> Self {
3522 self.borders = self.borders.border_x(width, color);
3523 self
3524 }
3525
3526 pub fn border_y(mut self, width: f32, color: Color) -> Self {
3527 self.borders = self.borders.border_y(width, color);
3528 self
3529 }
3530
3531 pub fn box_style(mut self, style: BoxStyle) -> Self {
3532 if style.background.a > 0.0 {
3533 self.color = Some(style.background);
3534 } else {
3535 self.color = None;
3536 }
3537 self.radius = style.radius;
3538 let mut borders = style;
3539 borders.background = Color::TRANSPARENT;
3540 borders.radius = 0.0;
3541 self.borders = borders;
3542 self
3543 }
3544
3545 pub fn style(self, style: BoxStyle) -> Self {
3546 self.box_style(style)
3547 }
3548
3549 pub fn padding(mut self, padding: impl Into<Edges>) -> Self {
3550 self.style = self.style.padding(padding);
3551 self
3552 }
3553
3554 pub fn pad(self, padding: impl Into<Edges>) -> Self {
3555 self.padding(padding)
3556 }
3557
3558 pub fn padding_xy(mut self, x: f32, y: f32) -> Self {
3559 self.style = self.style.padding_xy(x, y);
3560 self
3561 }
3562
3563 pub fn padding_x(mut self, x: f32) -> Self {
3564 self.style = self.style.padding_x(x);
3565 self
3566 }
3567
3568 pub fn padding_y(mut self, y: f32) -> Self {
3569 self.style = self.style.padding_y(y);
3570 self
3571 }
3572
3573 pub fn padding_left(mut self, v: f32) -> Self {
3574 self.style = self.style.padding_left(v);
3575 self
3576 }
3577
3578 pub fn padding_right(mut self, v: f32) -> Self {
3579 self.style = self.style.padding_right(v);
3580 self
3581 }
3582
3583 pub fn padding_top(mut self, v: f32) -> Self {
3584 self.style = self.style.padding_top(v);
3585 self
3586 }
3587
3588 pub fn padding_bottom(mut self, v: f32) -> Self {
3589 self.style = self.style.padding_bottom(v);
3590 self
3591 }
3592
3593 pub fn width(mut self, width: impl Into<Length>) -> Self {
3594 self.style = self.style.width(width.into());
3595 self
3596 }
3597
3598 pub fn height(mut self, height: impl Into<Length>) -> Self {
3599 self.style = self.style.height(height.into());
3600 self
3601 }
3602
3603 pub fn size(mut self, width: impl Into<Length>, height: impl Into<Length>) -> Self {
3604 self.style = self.style.width(width.into()).height(height.into());
3605 self
3606 }
3607
3608 pub fn square(mut self, side: impl Into<Length>) -> Self {
3609 let side = side.into();
3610 self.style = self.style.width(side).height(side);
3611 self
3612 }
3613
3614 pub fn min_width(mut self, v: f32) -> Self {
3615 self.style = self.style.min_width(v);
3616 self
3617 }
3618
3619 pub fn max_width(mut self, v: f32) -> Self {
3620 self.style = self.style.max_width(v);
3621 self
3622 }
3623
3624 pub fn min_height(mut self, v: f32) -> Self {
3625 self.style = self.style.min_height(v);
3626 self
3627 }
3628
3629 pub fn max_height(mut self, v: f32) -> Self {
3630 self.style = self.style.max_height(v);
3631 self
3632 }
3633
3634 pub fn overflow(mut self, overflow: Overflow) -> Self {
3635 self.style = self.style.overflow(overflow);
3636 self
3637 }
3638
3639 pub fn flex(mut self, weight: f32) -> Self {
3640 self.style = self.style.flex(weight);
3641 self
3642 }
3643
3644 pub fn expand(self) -> Self {
3645 self.flex(1.0)
3646 }
3647
3648 pub fn fill_width(mut self) -> Self {
3649 self.style = self.style.width(Length::Fill(1.0));
3650 self
3651 }
3652
3653 pub fn fill_height(mut self) -> Self {
3654 self.style = self.style.height(Length::Fill(1.0));
3655 self
3656 }
3657
3658 pub fn fill_size(self) -> Self {
3659 self.fill_width().fill_height()
3660 }
3661}
3662
3663impl_style_extras!(Panel);
3664
3665impl View for Panel {
3666 fn body(&self) -> impl View + 'static {
3667 Unit
3668 }
3669 fn is_leaf(&self) -> bool {
3670 true
3671 }
3672 fn layout_style(&self) -> LayoutStyle {
3673 self.style
3674 }
3675 fn paint_self(&self, ctx: &mut PaintCtx) {
3676 let theme = ctx.theme();
3677 let color = self.color.unwrap_or(theme.surface);
3678 let radius = if self.radius > 0.0 {
3679 self.radius
3680 } else {
3681 theme.radius
3682 };
3683 let p = self.style.padding;
3684 let rect = ctx.rect;
3685 let quad = Rect::from_xywh(
3686 rect.left() + p.left,
3687 rect.top() + p.top,
3688 (rect.size.width - p.horizontal_sum()).max(0.0),
3689 (rect.size.height - p.vertical_sum()).max(0.0),
3690 );
3691
3692 let mut deco = self.borders;
3693 deco.background = color;
3694 deco.radius = radius;
3695 ctx.paint_box_in(deco, quad);
3696 }
3697}
3698
3699#[derive(Clone, Copy, Debug)]
3700pub struct Spacer {
3701 style: LayoutStyle,
3702}
3703
3704impl Spacer {
3705 pub fn flex(weight: f32) -> Self {
3706 let w = if weight.is_finite() {
3707 weight.max(0.0)
3708 } else {
3709 0.0
3710 };
3711 Self {
3712 style: LayoutStyle {
3713 width: Length::Fill(w),
3714 height: Length::Fit,
3715 ..LayoutStyle::default()
3716 },
3717 }
3718 }
3719
3720 pub fn vertical(weight: f32) -> Self {
3721 let w = if weight.is_finite() {
3722 weight.max(0.0)
3723 } else {
3724 0.0
3725 };
3726 Self {
3727 style: LayoutStyle {
3728 width: Length::Fit,
3729 height: Length::Fill(w),
3730 ..LayoutStyle::default()
3731 },
3732 }
3733 }
3734
3735 pub fn fixed(size: f32) -> Self {
3736 let s = if size.is_finite() { size.max(0.0) } else { 0.0 };
3737 Self {
3738 style: LayoutStyle {
3739 width: Length::Px(s),
3740 height: Length::Px(s),
3741 ..LayoutStyle::default()
3742 },
3743 }
3744 }
3745
3746 pub fn fixed_width(w: f32) -> Self {
3747 let w = if w.is_finite() { w.max(0.0) } else { 0.0 };
3748 Self {
3749 style: LayoutStyle {
3750 width: Length::Px(w),
3751 height: Length::Px(0.0),
3752 ..LayoutStyle::default()
3753 },
3754 }
3755 }
3756
3757 pub fn fixed_height(h: f32) -> Self {
3758 let h = if h.is_finite() { h.max(0.0) } else { 0.0 };
3759 Self {
3760 style: LayoutStyle {
3761 width: Length::Px(0.0),
3762 height: Length::Px(h),
3763 ..LayoutStyle::default()
3764 },
3765 }
3766 }
3767
3768 pub fn width(mut self, width: impl Into<Length>) -> Self {
3769 self.style = self.style.width(width.into());
3770 self
3771 }
3772
3773 pub fn height(mut self, height: impl Into<Length>) -> Self {
3774 self.style = self.style.height(height.into());
3775 self
3776 }
3777
3778 pub fn min_width(mut self, v: f32) -> Self {
3779 self.style = self.style.min_width(v);
3780 self
3781 }
3782
3783 pub fn max_width(mut self, v: f32) -> Self {
3784 self.style = self.style.max_width(v);
3785 self
3786 }
3787
3788 pub fn min_height(mut self, v: f32) -> Self {
3789 self.style = self.style.min_height(v);
3790 self
3791 }
3792
3793 pub fn max_height(mut self, v: f32) -> Self {
3794 self.style = self.style.max_height(v);
3795 self
3796 }
3797
3798 pub fn expand(mut self) -> Self {
3799 self.style = self.style.flex(1.0);
3800 self
3801 }
3802}
3803
3804impl Default for Spacer {
3805 fn default() -> Self {
3806 Self::flex(1.0)
3807 }
3808}
3809
3810impl_style_extras!(Spacer);
3811
3812impl_child_helpers!(Fragment);
3813impl_child_helpers!(FocusScope);
3814impl_child_helpers!(Row);
3815impl_child_helpers!(Column);
3816impl_child_helpers!(Stack);
3817impl_child_helpers!(Grid);
3818impl_child_helpers!(Wrap);
3819impl_child_helpers!(Masonry);
3820
3821impl View for Spacer {
3822 fn body(&self) -> impl View + 'static {
3823 Unit
3824 }
3825 fn is_leaf(&self) -> bool {
3826 true
3827 }
3828 fn layout_style(&self) -> LayoutStyle {
3829 self.style
3830 }
3831}
3832
3833fn aspect_contain(content: Size, ratio: f32) -> (Size, f32, f32) {
3834 let (w, h) = (content.width.max(0.0), content.height.max(0.0));
3835 if !(ratio.is_finite() && ratio > 0.0) || w <= 0.0 || h <= 0.0 {
3836 return (Size::new(w, h), 0.0, 0.0);
3837 }
3838 if !w.is_finite() || !h.is_finite() {
3839 return (Size::new(w, h), 0.0, 0.0);
3840 }
3841 let box_w = (h * ratio).min(w);
3842 let box_h = box_w / ratio;
3843 (
3844 Size::new(box_w, box_h),
3845 (w - box_w) * 0.5,
3846 (h - box_h) * 0.5,
3847 )
3848}
3849
3850fn sanitize_aspect_ratio(ratio: f32) -> f32 {
3851 if ratio.is_finite() && ratio > 0.0 {
3852 ratio
3853 } else {
3854 1.0
3855 }
3856}
3857
3858#[derive(Clone)]
3859pub struct AspectRatio {
3860 ratio: f32,
3861 child: Option<AnyView>,
3862 style: LayoutStyle,
3863 deco: BoxStyle,
3864 clip: bool,
3865}
3866
3867impl AspectRatio {
3868 pub fn new(ratio: f32) -> Self {
3869 Self {
3870 ratio: sanitize_aspect_ratio(ratio),
3871 child: None,
3872 style: LayoutStyle {
3873 width: Length::Fit,
3874 height: Length::Fit,
3875 ..LayoutStyle::default()
3876 },
3877 deco: BoxStyle::new(),
3878 clip: false,
3879 }
3880 }
3881
3882 pub fn ratio(mut self, ratio: f32) -> Self {
3883 self.ratio = sanitize_aspect_ratio(ratio);
3884 self
3885 }
3886
3887 pub fn aspect(self, ratio: f32) -> Self {
3888 self.ratio(ratio)
3889 }
3890
3891 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
3892 debug_assert!(
3893 self.child.is_none(),
3894 "AspectRatio takes a single child - a second `.child()` would overwrite the first. Use Row/Column for many."
3895 );
3896 self.child = Some(AnyView::new(child));
3897 self
3898 }
3899
3900 pub fn child_if<V: View + 'static>(mut self, cond: bool, make: impl FnOnce() -> V) -> Self {
3901 if cond {
3902 self.child = Some(AnyView::new(make()));
3903 }
3904 self
3905 }
3906
3907 pub fn child_opt<V: View + 'static>(mut self, child: Option<V>) -> Self {
3908 if let Some(v) = child {
3909 self.child = Some(AnyView::new(v));
3910 }
3911 self
3912 }
3913
3914 pub fn background(mut self, color: Color) -> Self {
3915 self.deco = self.deco.background(color);
3916 self
3917 }
3918
3919 pub fn border(mut self, width: f32, color: Color) -> Self {
3920 self.deco = self.deco.border(width, color);
3921 self
3922 }
3923
3924 pub fn border_left(mut self, width: f32, color: Color) -> Self {
3925 self.deco = self.deco.border_left(width, color);
3926 self
3927 }
3928
3929 pub fn border_right(mut self, width: f32, color: Color) -> Self {
3930 self.deco = self.deco.border_right(width, color);
3931 self
3932 }
3933
3934 pub fn border_top(mut self, width: f32, color: Color) -> Self {
3935 self.deco = self.deco.border_top(width, color);
3936 self
3937 }
3938
3939 pub fn border_bottom(mut self, width: f32, color: Color) -> Self {
3940 self.deco = self.deco.border_bottom(width, color);
3941 self
3942 }
3943
3944 pub fn border_x(mut self, width: f32, color: Color) -> Self {
3945 self.deco = self.deco.border_x(width, color);
3946 self
3947 }
3948
3949 pub fn border_y(mut self, width: f32, color: Color) -> Self {
3950 self.deco = self.deco.border_y(width, color);
3951 self
3952 }
3953
3954 pub fn box_style(mut self, style: BoxStyle) -> Self {
3955 self.deco = style;
3956 self
3957 }
3958
3959 pub fn style(self, style: BoxStyle) -> Self {
3960 self.box_style(style)
3961 }
3962
3963 pub fn radius(mut self, radius: f32) -> Self {
3964 self.deco = self.deco.radius(radius);
3965 self
3966 }
3967
3968 pub fn padding(mut self, padding: impl Into<Edges>) -> Self {
3969 self.style = self.style.padding(padding);
3970 self
3971 }
3972
3973 pub fn pad(self, padding: impl Into<Edges>) -> Self {
3974 self.padding(padding)
3975 }
3976
3977 pub fn padding_xy(mut self, x: f32, y: f32) -> Self {
3978 self.style = self.style.padding_xy(x, y);
3979 self
3980 }
3981
3982 pub fn padding_x(mut self, x: f32) -> Self {
3983 self.style = self.style.padding_x(x);
3984 self
3985 }
3986
3987 pub fn padding_y(mut self, y: f32) -> Self {
3988 self.style = self.style.padding_y(y);
3989 self
3990 }
3991
3992 pub fn padding_left(mut self, v: f32) -> Self {
3993 self.style = self.style.padding_left(v);
3994 self
3995 }
3996
3997 pub fn padding_right(mut self, v: f32) -> Self {
3998 self.style = self.style.padding_right(v);
3999 self
4000 }
4001
4002 pub fn padding_top(mut self, v: f32) -> Self {
4003 self.style = self.style.padding_top(v);
4004 self
4005 }
4006
4007 pub fn padding_bottom(mut self, v: f32) -> Self {
4008 self.style = self.style.padding_bottom(v);
4009 self
4010 }
4011
4012 pub fn width(mut self, width: impl Into<Length>) -> Self {
4013 self.style = self.style.width(width.into());
4014 self
4015 }
4016
4017 pub fn height(mut self, height: impl Into<Length>) -> Self {
4018 self.style = self.style.height(height.into());
4019 self
4020 }
4021
4022 pub fn size(mut self, width: impl Into<Length>, height: impl Into<Length>) -> Self {
4023 self.style = self.style.width(width.into()).height(height.into());
4024 self
4025 }
4026
4027 pub fn square(mut self, side: impl Into<Length>) -> Self {
4028 let side = side.into();
4029 self.style = self.style.width(side).height(side);
4030 self
4031 }
4032
4033 pub fn min_width(mut self, v: f32) -> Self {
4034 self.style = self.style.min_width(v);
4035 self
4036 }
4037
4038 pub fn max_width(mut self, v: f32) -> Self {
4039 self.style = self.style.max_width(v);
4040 self
4041 }
4042
4043 pub fn min_height(mut self, v: f32) -> Self {
4044 self.style = self.style.min_height(v);
4045 self
4046 }
4047
4048 pub fn max_height(mut self, v: f32) -> Self {
4049 self.style = self.style.max_height(v);
4050 self
4051 }
4052
4053 pub fn overflow(mut self, overflow: Overflow) -> Self {
4054 self.style = self.style.overflow(overflow);
4055 self
4056 }
4057
4058 pub fn margin(mut self, margin: impl Into<Edges>) -> Self {
4059 self.style = self.style.margin(margin);
4060 self
4061 }
4062
4063 pub fn margin_xy(mut self, x: f32, y: f32) -> Self {
4064 self.style = self.style.margin_xy(x, y);
4065 self
4066 }
4067
4068 pub fn margin_x(mut self, x: f32) -> Self {
4069 self.style = self.style.margin_x(x);
4070 self
4071 }
4072
4073 pub fn margin_y(mut self, y: f32) -> Self {
4074 self.style = self.style.margin_y(y);
4075 self
4076 }
4077
4078 pub fn margin_left(mut self, v: f32) -> Self {
4079 self.style = self.style.margin_left(v);
4080 self
4081 }
4082
4083 pub fn margin_right(mut self, v: f32) -> Self {
4084 self.style = self.style.margin_right(v);
4085 self
4086 }
4087
4088 pub fn margin_top(mut self, v: f32) -> Self {
4089 self.style = self.style.margin_top(v);
4090 self
4091 }
4092
4093 pub fn margin_bottom(mut self, v: f32) -> Self {
4094 self.style = self.style.margin_bottom(v);
4095 self
4096 }
4097
4098 pub fn flex(mut self, weight: f32) -> Self {
4099 self.style = self.style.flex(weight);
4100 self
4101 }
4102
4103 pub fn flex_shrink(mut self, shrink: f32) -> Self {
4104 self.style = self.style.flex_shrink(shrink);
4105 self
4106 }
4107
4108 pub fn flex_basis(mut self, basis: Option<Length>) -> Self {
4109 self.style = self.style.flex_basis(basis);
4110 self
4111 }
4112
4113 pub fn align_self(mut self, align: Option<Align>) -> Self {
4114 self.style = self.style.align_self(align);
4115 self
4116 }
4117
4118 pub fn position(mut self, position: Position) -> Self {
4119 self.style = self.style.position(position);
4120 self
4121 }
4122
4123 pub fn absolute(mut self) -> Self {
4124 self.style = self.style.absolute();
4125 self
4126 }
4127
4128 pub fn absolute_at(mut self, left: f32, top: f32) -> Self {
4129 self.style = self.style.absolute_at(left, top);
4130 self
4131 }
4132
4133 pub fn absolute_inset(mut self, inset: Inset) -> Self {
4134 self.style = self.style.absolute_inset(inset);
4135 self
4136 }
4137
4138 pub fn expand(self) -> Self {
4139 self.flex(1.0)
4140 }
4141
4142 pub fn fill_width(mut self) -> Self {
4143 self.style = self.style.width(Length::Fill(1.0));
4144 self
4145 }
4146
4147 pub fn fill_height(mut self) -> Self {
4148 self.style = self.style.height(Length::Fill(1.0));
4149 self
4150 }
4151
4152 pub fn fill_size(self) -> Self {
4153 self.fill_width().fill_height()
4154 }
4155
4156 pub fn fit(mut self) -> Self {
4157 self.style = self.style.fit();
4158 self
4159 }
4160
4161 pub fn hit_testable(mut self, on: bool) -> Self {
4162 self.style = self.style.hit_testable(on);
4163 self
4164 }
4165
4166 pub fn clip(mut self, clip: bool) -> Self {
4167 self.clip = clip;
4168 self
4169 }
4170
4171 pub fn clip_children(self) -> Self {
4172 self.clip(true)
4173 }
4174}
4175
4176impl View for AspectRatio {
4177 fn body(&self) -> impl View + 'static {
4178 Unit
4179 }
4180 fn children_override(&self) -> Option<Vec<AnyView>> {
4181 self.child.clone().map(|c| vec![c])
4182 }
4183 fn clip_self(&self) -> bool {
4184 self.clip
4185 }
4186 fn clip_radius(&self) -> f32 {
4187 if self.clip { self.deco.radius } else { 0.0 }
4188 }
4189 fn layout_style(&self) -> LayoutStyle {
4190 let mut style = self.style;
4191 style.aspect_ratio = Some(self.ratio);
4192 style
4193 }
4194 fn arrange_override(
4195 &self,
4196 rt: &Runtime,
4197 el: ElementId,
4198 rect: Rect,
4199 ctx: &mut LayoutCtx,
4200 ) -> bool {
4201 let children = rt.children(el);
4202 let Some(&child) = children.first() else {
4203 return true;
4204 };
4205
4206 if matches!(self.style.width, Length::Fit) || matches!(self.style.height, Length::Fit) {
4207 return false;
4208 }
4209 let pad = self.style.padding;
4210 let content = Rect::from_xywh(
4211 rect.left() + pad.left,
4212 rect.top() + pad.top,
4213 (rect.size.width - pad.horizontal_sum()).max(0.0),
4214 (rect.size.height - pad.vertical_sum()).max(0.0),
4215 );
4216 if !content.size.width.is_finite() || !content.size.height.is_finite() {
4217 return false;
4218 }
4219 let (boxed, dx, dy) = aspect_contain(content.size, self.ratio);
4220 let cs = rt.child_layout_style(child);
4221 rt.arrange_node(
4222 child,
4223 Rect::from_xywh(
4224 content.left() + dx + cs.margin.left,
4225 content.top() + dy + cs.margin.top,
4226 (boxed.width - cs.margin.horizontal_sum()).max(0.0),
4227 (boxed.height - cs.margin.vertical_sum()).max(0.0),
4228 ),
4229 ctx,
4230 );
4231 true
4232 }
4233 fn paint_self(&self, ctx: &mut PaintCtx) {
4234 ctx.paint_box(self.deco);
4235 }
4236}
4237
4238impl crate::styleable::Styleable for AspectRatio {
4239 fn fill_width(mut self) -> Self {
4240 self.style = self.style.width(Length::Fill(1.0));
4241 self
4242 }
4243 fn fill_height(mut self) -> Self {
4244 self.style = self.style.height(Length::Fill(1.0));
4245 self
4246 }
4247 fn fit(mut self) -> Self {
4248 self.style = self.style.fit();
4249 self
4250 }
4251 fn hit_testable(mut self, on: bool) -> Self {
4252 self.style = self.style.hit_testable(on);
4253 self
4254 }
4255 fn padding(mut self, padding: impl Into<Edges>) -> Self {
4256 self.style = self.style.padding(padding);
4257 self
4258 }
4259}
4260
4261impl crate::styleable::Decoratable for AspectRatio {
4262 fn background(mut self, color: Color) -> Self {
4263 self.deco = self.deco.background(color);
4264 self
4265 }
4266 fn border(mut self, width: f32, color: Color) -> Self {
4267 self.deco = self.deco.border(width, color);
4268 self
4269 }
4270 fn radius(mut self, radius: f32) -> Self {
4271 self.deco = self.deco.radius(radius);
4272 self
4273 }
4274 fn box_style(mut self, style: BoxStyle) -> Self {
4275 self.deco = style;
4276 self
4277 }
4278}
4279
4280impl crate::styleable::Styleable for Row {
4281 fn fill_width(mut self) -> Self {
4282 self.0.style = self.0.style.width(Length::Fill(1.0));
4283 self
4284 }
4285 fn fill_height(mut self) -> Self {
4286 self.0.style = self.0.style.height(Length::Fill(1.0));
4287 self
4288 }
4289 fn fit(mut self) -> Self {
4290 self.0.style = self.0.style.fit();
4291 self
4292 }
4293 fn hit_testable(mut self, on: bool) -> Self {
4294 self.0.style = self.0.style.hit_testable(on);
4295 self
4296 }
4297 fn padding(mut self, padding: impl Into<Edges>) -> Self {
4298 self.0.style = self.0.style.padding(padding);
4299 self
4300 }
4301}
4302
4303impl crate::styleable::Decoratable for Row {
4304 fn background(mut self, color: Color) -> Self {
4305 self.0.deco = self.0.deco.background(color);
4306 self
4307 }
4308 fn border(mut self, width: f32, color: Color) -> Self {
4309 self.0.deco = self.0.deco.border(width, color);
4310 self
4311 }
4312 fn radius(mut self, radius: f32) -> Self {
4313 self.0.deco = self.0.deco.radius(radius);
4314 self
4315 }
4316 fn box_style(mut self, style: BoxStyle) -> Self {
4317 self.0.deco = style;
4318 self
4319 }
4320}
4321
4322impl crate::styleable::Styleable for Column {
4323 fn fill_width(mut self) -> Self {
4324 self.0.style = self.0.style.width(Length::Fill(1.0));
4325 self
4326 }
4327 fn fill_height(mut self) -> Self {
4328 self.0.style = self.0.style.height(Length::Fill(1.0));
4329 self
4330 }
4331 fn fit(mut self) -> Self {
4332 self.0.style = self.0.style.fit();
4333 self
4334 }
4335 fn hit_testable(mut self, on: bool) -> Self {
4336 self.0.style = self.0.style.hit_testable(on);
4337 self
4338 }
4339 fn padding(mut self, padding: impl Into<Edges>) -> Self {
4340 self.0.style = self.0.style.padding(padding);
4341 self
4342 }
4343}
4344
4345impl crate::styleable::Decoratable for Column {
4346 fn background(mut self, color: Color) -> Self {
4347 self.0.deco = self.0.deco.background(color);
4348 self
4349 }
4350 fn border(mut self, width: f32, color: Color) -> Self {
4351 self.0.deco = self.0.deco.border(width, color);
4352 self
4353 }
4354 fn radius(mut self, radius: f32) -> Self {
4355 self.0.deco = self.0.deco.radius(radius);
4356 self
4357 }
4358 fn box_style(mut self, style: BoxStyle) -> Self {
4359 self.0.deco = style;
4360 self
4361 }
4362}
4363
4364impl crate::styleable::Styleable for Stack {
4365 fn fill_width(mut self) -> Self {
4366 self.style = self.style.width(Length::Fill(1.0));
4367 self
4368 }
4369 fn fill_height(mut self) -> Self {
4370 self.style = self.style.height(Length::Fill(1.0));
4371 self
4372 }
4373 fn fit(mut self) -> Self {
4374 self.style = self.style.fit();
4375 self
4376 }
4377 fn hit_testable(mut self, on: bool) -> Self {
4378 self.style = self.style.hit_testable(on);
4379 self
4380 }
4381 fn padding(mut self, padding: impl Into<Edges>) -> Self {
4382 self.style = self.style.padding(padding);
4383 self
4384 }
4385}
4386
4387impl crate::styleable::Decoratable for Stack {
4388 fn background(mut self, color: Color) -> Self {
4389 self.deco = self.deco.background(color);
4390 self
4391 }
4392 fn border(mut self, width: f32, color: Color) -> Self {
4393 self.deco = self.deco.border(width, color);
4394 self
4395 }
4396 fn radius(mut self, radius: f32) -> Self {
4397 self.deco = self.deco.radius(radius);
4398 self
4399 }
4400 fn box_style(mut self, style: BoxStyle) -> Self {
4401 self.deco = style;
4402 self
4403 }
4404}
4405
4406#[cfg(test)]
4407mod aspect_ratio_tests {
4408 use super::*;
4409
4410 #[test]
4411 fn invalid_ratio_falls_back_to_square() {
4412 for bad in [0.0, -2.0, f32::NAN, f32::INFINITY, f32::NEG_INFINITY] {
4413 let v = AspectRatio::new(bad);
4414 assert_eq!(v.layout_style().aspect_ratio, Some(1.0), "ratio {bad}");
4415 let v = AspectRatio::new(2.0).ratio(bad);
4416 assert_eq!(v.layout_style().aspect_ratio, Some(1.0), "ratio {bad}");
4417 }
4418 }
4419
4420 #[test]
4421 fn layout_style_carries_ratio() {
4422 let v = AspectRatio::new(16.0 / 9.0).width(320.0);
4423 let style = v.layout_style();
4424 assert_eq!(style.aspect_ratio, Some(16.0 / 9.0));
4425 assert_eq!(style.width, Length::Px(320.0));
4426 }
4427
4428 #[test]
4429 fn contain_fits_wide_content() {
4430 let (boxed, dx, dy) = aspect_contain(Size::new(800.0, 600.0), 16.0 / 9.0);
4431 assert!((boxed.width - 800.0).abs() < 1e-3, "{boxed:?}");
4432 assert!((boxed.height - 450.0).abs() < 1e-3, "{boxed:?}");
4433 assert!(dx.abs() < 1e-3, "{dx}");
4434 assert!((dy - 75.0).abs() < 1e-3, "{dy}");
4435 }
4436
4437 #[test]
4438 fn contain_fits_tall_content() {
4439 let (boxed, dx, dy) = aspect_contain(Size::new(100.0, 200.0), 2.0);
4440 assert!((boxed.width - 100.0).abs() < 1e-3, "{boxed:?}");
4441 assert!((boxed.height - 50.0).abs() < 1e-3, "{boxed:?}");
4442 assert!(dx.abs() < 1e-3, "{dx}");
4443 assert!((dy - 75.0).abs() < 1e-3, "{dy}");
4444 }
4445
4446 #[test]
4447 fn contain_matching_ratio_is_identity() {
4448 let (boxed, dx, dy) = aspect_contain(Size::new(200.0, 100.0), 2.0);
4449 assert!((boxed.width - 200.0).abs() < 1e-3, "{boxed:?}");
4450 assert!((boxed.height - 100.0).abs() < 1e-3, "{boxed:?}");
4451 assert!(dx.abs() < 1e-3);
4452 assert!(dy.abs() < 1e-3);
4453 }
4454
4455 #[test]
4456 fn contain_degenerate_returns_content() {
4457 let (boxed, dx, dy) = aspect_contain(Size::ZERO, 16.0 / 9.0);
4458 assert_eq!(boxed, Size::ZERO);
4459 assert_eq!((dx, dy), (0.0, 0.0));
4460 let (boxed, dx, dy) = aspect_contain(Size::new(100.0, 100.0), 0.0);
4461 assert_eq!(boxed, Size::new(100.0, 100.0));
4462 assert_eq!((dx, dy), (0.0, 0.0));
4463 }
4464}