Skip to main content

sequoia_view/
views.rs

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    /// Enables wrapping at the width available from the parent container.
469    pub fn wrap(mut self) -> Self {
470        self.auto_wrap = true;
471        self
472    }
473
474    /// Sets the line height as a multiple of the font size.
475    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    /// Sets an absolute line height in logical pixels.
483    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    /// Sets vertical alignment within the text box.
491    pub fn align_y(mut self, align: TextVAlign) -> Self {
492        self.align_y = align;
493        self
494    }
495
496    /// Limits visible wrapped text to `lines`, appending an ellipsis.
497    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    /// Scales the resolved font size without changing layout styles.
503    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/// Opts a subtree into the runtime layer cache.
1177///
1178/// The runtime replays the child's painted output while the child's element
1179/// revision and absolute paint context are unchanged. Mutating a signal read
1180/// during build/paint bumps the revision and forces a repaint. Backdrop,
1181/// filter, and opacity spans are captured and rebased with the layer; embedded
1182/// surfaces and paint-time callbacks still bypass the cache.
1183///
1184/// Paint-time side effects are not replayed. Do not wrap views that register
1185/// shapes, sample the clock or pointer position, or rely on `paint_self` being
1186/// called on every frame.
1187#[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
3194/// A waterfall layout with equal-width columns and variable item heights.
3195///
3196/// Items are appended to the shortest column, keeping their natural height.
3197/// This is useful for card feeds and galleries where rows should not share a
3198/// common height. Absolute children are excluded from the flow.
3199///
3200/// ```
3201/// use sequoia_view::prelude::*;
3202///
3203/// let feed = Masonry::new(2)
3204///     .gap(12.0)
3205///     .padding(16.0)
3206///     .child(Panel::new().height(120.0))
3207///     .child(Panel::new().height(80.0))
3208///     .child(Panel::new().height(160.0));
3209/// # let _ = feed;
3210/// ```
3211pub struct Masonry {
3212    children: Vec<AnyView>,
3213    style: LayoutStyle,
3214    masonry: MasonryStyle,
3215    deco: BoxStyle,
3216}
3217
3218impl Masonry {
3219    /// Creates a masonry container with the given number of columns.
3220    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}