Skip to main content

sequoia_view/
views.rs

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