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