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