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, 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(14.0);
709 let weight = self.weight.unwrap_or_default();
710 let family = self.family.as_deref();
711 let fstyle = self.font_style;
712 let content = (self.content)();
713 let pad = self.style.padding;
714 let text_size = if let Some(w) = self.truncate_width {
715 ctx.text_elided_size_styled_spaced(
716 &content,
717 size,
718 weight,
719 w,
720 self.elide_mode,
721 self.letter_spacing,
722 family,
723 fstyle,
724 )
725 } else {
726 match self.wrap_width {
727 Some(w) => ctx.text_wrapped_size_styled_spaced(
728 &content,
729 size,
730 weight,
731 w,
732 self.wrap_mode,
733 self.letter_spacing,
734 family,
735 fstyle,
736 ),
737 None => {
738 let w = ctx.text_width_styled_spaced(
739 &content,
740 size,
741 weight,
742 self.letter_spacing,
743 family,
744 fstyle,
745 );
746 Size::new(w, LayoutCtx::text_line_height(size))
747 }
748 }
749 };
750 Some(Size::new(
751 text_size.width + pad.horizontal_sum(),
752 text_size.height + pad.vertical_sum(),
753 ))
754 }
755 fn paint_self(&self, ctx: &mut PaintCtx) {
756 let theme = ctx.theme();
757 let size = self.font_size.unwrap_or(theme.font_size);
758 let weight = self.weight.unwrap_or_default();
759 let color = self.color.unwrap_or(theme.text);
760 let content = (self.content)();
761 let pad = self.style.padding;
762
763 let content_rect = Rect::from_xywh(
764 ctx.rect.left() + pad.left,
765 ctx.rect.top() + pad.top,
766 (ctx.rect.size.width - pad.horizontal_sum()).max(0.0),
767 (ctx.rect.size.height - pad.vertical_sum()).max(0.0),
768 );
769 let x = content_rect.left();
770
771 let family = self.family.as_deref();
772 let fstyle = self.font_style;
773 let (shown, y, wrapped) = if let Some(w) = self.truncate_width.or(if self.truncate_fill {
774 Some(content_rect.size.width.max(0.0))
775 } else {
776 None
777 }) {
778 let shown = ctx.elide_styled_spaced(
779 &content,
780 size,
781 weight,
782 w,
783 self.elide_mode,
784 self.letter_spacing,
785 family,
786 fstyle,
787 );
788 let y = content_rect.top() + content_rect.size.height * 0.5 + size * 0.35;
789 (shown, y, None)
790 } else {
791 let y = match self.wrap_width {
792 Some(_) => {
793 content_rect.top() + LayoutCtx::text_line_height(size) * 0.5 + size * 0.35
794 }
795 None => content_rect.top() + content_rect.size.height * 0.5 + size * 0.35,
796 };
797
798 #[cfg(debug_assertions)]
799 {
800 if self.wrap_width.is_none() && !content.is_empty() {
801 let full_w = ctx.text_width_styled_spaced(
802 &content,
803 size,
804 weight,
805 self.letter_spacing,
806 family,
807 fstyle,
808 );
809 if full_w > content_rect.size.width + 1.0 && content_rect.size.width > 0.0 {
810 use std::sync::Once;
811 static WARN_ONCE: Once = Once::new();
812 WARN_ONCE.call_once(|| {
813 log::warn!(
814 "sequoia-view: Text `{}` overflows box ({full_w:.1}px > {:.1}px) without truncate — add `.truncate_fill()` or `.truncate(w)`. \
815 (This warning once per process; subsequent overflows are silent.)",
816 content.chars().take(24).collect::<String>(),
817 content_rect.size.width,
818 );
819 });
820 }
821 }
822 }
823 (content.clone(), y, self.wrap_width)
824 };
825 match wrapped {
826 Some(w) => ctx.draw_text_wrapped_styled_spaced(
827 &shown,
828 (x, y),
829 size,
830 weight,
831 w,
832 self.wrap_mode,
833 self.letter_spacing,
834 family,
835 fstyle,
836 color,
837 ),
838 None => ctx.draw_text_styled_spaced(
839 &shown,
840 (x, y),
841 size,
842 weight,
843 self.letter_spacing,
844 family,
845 fstyle,
846 color,
847 ),
848 }
849 self.paint_decoration(ctx, &shown, x, y, size, weight, color);
850 }
851}
852
853#[derive(Clone, Default)]
854pub struct Fragment {
855 children: Vec<AnyView>,
856}
857
858impl Fragment {
859 pub fn new() -> Self {
860 Self::default()
861 }
862
863 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
864 self.children.push(AnyView::new(child));
865 self
866 }
867
868 pub fn children(mut self, children: impl IntoChildren) -> Self {
869 self.children.extend(children.into_children());
870 self
871 }
872}
873
874impl View for Fragment {
875 fn body(&self) -> impl View + 'static {
876 Unit
877 }
878 fn children_override(&self) -> Option<Vec<AnyView>> {
879 Some(self.children.clone())
880 }
881 fn layout_style(&self) -> LayoutStyle {
882 LayoutStyle::default().hit_testable(false)
883 }
884 fn hit_testable(&self) -> bool {
885 false
886 }
887}
888
889#[derive(Clone)]
890pub struct Margined {
891 child: AnyView,
892 margin: Edges,
893 indents: Indents,
894}
895
896impl Margined {
897 pub fn new<V: View + 'static>(child: V, margin: impl Into<Edges>) -> Self {
898 Self {
899 child: AnyView::new(child),
900 margin: margin.into(),
901 indents: Indents::NONE,
902 }
903 }
904
905 pub fn with_indents<V: View + 'static>(child: V, indents: Indents) -> Self {
906 Self {
907 child: AnyView::new(child),
908 margin: Edges::ZERO,
909 indents,
910 }
911 }
912
913 pub fn margin(mut self, margin: impl Into<Edges>) -> Self {
914 let m = margin.into();
915 self.margin = Edges::only(
916 sanitize_margin_edge(m.left),
917 sanitize_margin_edge(m.top),
918 sanitize_margin_edge(m.right),
919 sanitize_margin_edge(m.bottom),
920 );
921 self
922 }
923
924 pub fn margin_xy(self, x: f32, y: f32) -> Self {
925 self.margin(Edges::xy(x, y))
926 }
927
928 pub fn margin_x(mut self, x: f32) -> Self {
929 let x = sanitize_margin_edge(x);
930 self.margin.left = x;
931 self.margin.right = x;
932 self
933 }
934
935 pub fn margin_y(mut self, y: f32) -> Self {
936 let y = sanitize_margin_edge(y);
937 self.margin.top = y;
938 self.margin.bottom = y;
939 self
940 }
941
942 pub fn margin_left(mut self, v: f32) -> Self {
943 self.margin.left = sanitize_margin_edge(v);
944 self
945 }
946
947 pub fn margin_right(mut self, v: f32) -> Self {
948 self.margin.right = sanitize_margin_edge(v);
949 self
950 }
951
952 pub fn margin_top(mut self, v: f32) -> Self {
953 self.margin.top = sanitize_margin_edge(v);
954 self
955 }
956
957 pub fn margin_bottom(mut self, v: f32) -> Self {
958 self.margin.bottom = sanitize_margin_edge(v);
959 self
960 }
961
962 pub fn indent_top(mut self, v: f32) -> Self {
963 self.indents.top = Some(sequoia_layout::sanitize_indent(v));
964 self
965 }
966
967 pub fn indent_bottom(mut self, v: f32) -> Self {
968 self.indents.bottom = Some(sequoia_layout::sanitize_indent(v));
969 self
970 }
971
972 pub fn indent_left(mut self, v: f32) -> Self {
973 self.indents.left = Some(sequoia_layout::sanitize_indent(v));
974 self
975 }
976
977 pub fn indent_right(mut self, v: f32) -> Self {
978 self.indents.right = Some(sequoia_layout::sanitize_indent(v));
979 self
980 }
981
982 pub fn clear_indents(mut self) -> Self {
983 self.indents = Indents::NONE;
984 self
985 }
986
987 pub fn indent(mut self, indents: Indents) -> Self {
988 if let Some(v) = indents.top {
989 self.indents.top = Some(sequoia_layout::sanitize_indent(v));
990 }
991 if let Some(v) = indents.bottom {
992 self.indents.bottom = Some(sequoia_layout::sanitize_indent(v));
993 }
994 if let Some(v) = indents.left {
995 self.indents.left = Some(sequoia_layout::sanitize_indent(v));
996 }
997 if let Some(v) = indents.right {
998 self.indents.right = Some(sequoia_layout::sanitize_indent(v));
999 }
1000 self
1001 }
1002
1003 pub fn indent_all(self, v: f32) -> Self {
1004 self.indent(Indents::all(v))
1005 }
1006
1007 pub fn indent_xy(self, x: f32, y: f32) -> Self {
1008 self.indent(Indents::xy(x, y))
1009 }
1010
1011 pub fn indent_axes(self, horizontal: f32, vertical: f32) -> Self {
1012 self.indent(Indents::axes(horizontal, vertical))
1013 }
1014}
1015
1016fn sanitize_margin_edge(v: f32) -> f32 {
1017 if v.is_finite() { v.max(0.0) } else { 0.0 }
1018}
1019
1020impl View for Margined {
1021 fn body(&self) -> impl View + 'static {
1022 Unit
1023 }
1024 fn children_override(&self) -> Option<Vec<AnyView>> {
1025 Some(vec![self.child.clone()])
1026 }
1027 fn layout_style(&self) -> LayoutStyle {
1028 LayoutStyle {
1029 width: Length::Fit,
1030 height: Length::Fit,
1031 margin: self.margin,
1032 indent_top: self.indents.top,
1033 indent_bottom: self.indents.bottom,
1034 indent_left: self.indents.left,
1035 indent_right: self.indents.right,
1036 ..LayoutStyle::default().hit_testable(false)
1037 }
1038 }
1039 fn hit_testable(&self) -> bool {
1040 false
1041 }
1042}
1043
1044#[derive(Clone, Default)]
1045pub struct FocusScope {
1046 children: Vec<AnyView>,
1047 trap: bool,
1048}
1049
1050impl FocusScope {
1051 pub fn new() -> Self {
1052 Self::default()
1053 }
1054
1055 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
1056 self.children.push(AnyView::new(child));
1057 self
1058 }
1059
1060 pub fn children(mut self, children: impl IntoChildren) -> Self {
1061 self.children.extend(children.into_children());
1062 self
1063 }
1064
1065 pub fn trap(mut self, trap: bool) -> Self {
1066 self.trap = trap;
1067 self
1068 }
1069}
1070
1071impl View for FocusScope {
1072 fn body(&self) -> impl View + 'static {
1073 Unit
1074 }
1075 fn children_override(&self) -> Option<Vec<AnyView>> {
1076 Some(self.children.clone())
1077 }
1078 fn focus_trap(&self) -> bool {
1079 self.trap
1080 }
1081 fn layout_style(&self) -> LayoutStyle {
1082 LayoutStyle::default()
1083 }
1084}
1085
1086struct Flex {
1087 children: Vec<AnyView>,
1088
1089 flex: Vec<f32>,
1090 gap: f32,
1091 cross_gap: f32,
1092 wrap: bool,
1093 align_content: Align,
1094 style: LayoutStyle,
1095 axis: Axis,
1096 align: Align,
1097 justify: Justify,
1098 deco: BoxStyle,
1099}
1100
1101impl Flex {
1102 fn new(axis: Axis) -> Self {
1103 Self {
1104 children: Vec::new(),
1105 flex: Vec::new(),
1106 gap: 0.0,
1107 cross_gap: 0.0,
1108 wrap: false,
1109 align_content: Align::Start,
1110 style: LayoutStyle {
1111 width: Length::Fit,
1112 height: Length::Fit,
1113 ..LayoutStyle::default()
1114 },
1115 axis,
1116 align: Align::Start,
1117 justify: Justify::Start,
1118 deco: BoxStyle::new(),
1119 }
1120 }
1121
1122 fn sanitize_flex(flex: f32) -> f32 {
1123 if flex.is_finite() && flex > 0.0 {
1124 flex
1125 } else {
1126 0.0
1127 }
1128 }
1129}
1130
1131impl View for Flex {
1132 fn body(&self) -> impl View + 'static {
1133 Unit
1134 }
1135 fn children_override(&self) -> Option<Vec<AnyView>> {
1136 Some(self.children.clone())
1137 }
1138 fn layout_style(&self) -> LayoutStyle {
1139 let mut style = self.style;
1140 let edges = self.deco.border_edges();
1141 style.padding.left += edges.left;
1142 style.padding.top += edges.top;
1143 style.padding.right += edges.right;
1144 style.padding.bottom += edges.bottom;
1145 style
1146 }
1147 fn container(&self) -> Option<ContainerStyle> {
1148 Some(ContainerStyle {
1149 axis: self.axis,
1150 gap: self.gap,
1151 cross_gap: self.cross_gap,
1152 align: self.align,
1153 justify: self.justify,
1154 wrap: self.wrap,
1155 align_content: self.align_content,
1156 })
1157 }
1158}
1159
1160macro_rules! impl_flex_container {
1161 ($name:ident, $axis:expr) => {
1162 impl $name {
1163 pub fn gap(mut self, gap: f32) -> Self {
1164 let gap = if gap.is_finite() { gap.max(0.0) } else { 0.0 };
1165 self.0.gap = gap;
1166 self.0.cross_gap = gap;
1167 self
1168 }
1169
1170 pub fn main_gap(mut self, gap: f32) -> Self {
1171 self.0.gap = if gap.is_finite() { gap.max(0.0) } else { 0.0 };
1172 self
1173 }
1174
1175 pub fn cross_gap(mut self, gap: f32) -> Self {
1176 self.0.cross_gap = if gap.is_finite() { gap.max(0.0) } else { 0.0 };
1177 self
1178 }
1179
1180 pub fn gaps(mut self, main: f32, cross: f32) -> Self {
1181 self.0.gap = if main.is_finite() { main.max(0.0) } else { 0.0 };
1182 self.0.cross_gap = if cross.is_finite() {
1183 cross.max(0.0)
1184 } else {
1185 0.0
1186 };
1187 self
1188 }
1189
1190 pub fn wrap(mut self, wrap: bool) -> Self {
1191 self.0.wrap = wrap;
1192 self
1193 }
1194
1195 pub fn wrapped(mut self) -> Self {
1196 self.0.wrap = true;
1197 self
1198 }
1199
1200 pub fn align_content(mut self, align: Align) -> Self {
1201 self.0.align_content = align;
1202 self
1203 }
1204
1205 pub fn margin(mut self, margin: impl Into<Edges>) -> Self {
1206 self.0.style = self.0.style.margin(margin);
1207 self
1208 }
1209
1210 pub fn margin_xy(mut self, x: f32, y: f32) -> Self {
1211 self.0.style = self.0.style.margin_xy(x, y);
1212 self
1213 }
1214
1215 pub fn margin_x(mut self, x: f32) -> Self {
1216 self.0.style = self.0.style.margin_x(x);
1217 self
1218 }
1219
1220 pub fn margin_y(mut self, y: f32) -> Self {
1221 self.0.style = self.0.style.margin_y(y);
1222 self
1223 }
1224
1225 pub fn margin_left(mut self, v: f32) -> Self {
1226 self.0.style = self.0.style.margin_left(v);
1227 self
1228 }
1229
1230 pub fn margin_right(mut self, v: f32) -> Self {
1231 self.0.style = self.0.style.margin_right(v);
1232 self
1233 }
1234
1235 pub fn margin_top(mut self, v: f32) -> Self {
1236 self.0.style = self.0.style.margin_top(v);
1237 self
1238 }
1239
1240 pub fn margin_bottom(mut self, v: f32) -> Self {
1241 self.0.style = self.0.style.margin_bottom(v);
1242 self
1243 }
1244
1245 pub fn indent_top(mut self, v: f32) -> Self {
1246 self.0.style = self.0.style.indent_top(v);
1247 self
1248 }
1249
1250 pub fn indent_bottom(mut self, v: f32) -> Self {
1251 self.0.style = self.0.style.indent_bottom(v);
1252 self
1253 }
1254
1255 pub fn indent_left(mut self, v: f32) -> Self {
1256 self.0.style = self.0.style.indent_left(v);
1257 self
1258 }
1259
1260 pub fn indent_right(mut self, v: f32) -> Self {
1261 self.0.style = self.0.style.indent_right(v);
1262 self
1263 }
1264
1265 pub fn clear_indents(mut self) -> Self {
1266 self.0.style = self.0.style.clear_indents();
1267 self
1268 }
1269
1270 pub fn indent(mut self, indents: Indents) -> Self {
1271 self.0.style = self.0.style.indent(indents);
1272 self
1273 }
1274
1275 pub fn indent_all(mut self, v: f32) -> Self {
1276 self.0.style = self.0.style.indent_all(v);
1277 self
1278 }
1279
1280 pub fn indent_xy(mut self, x: f32, y: f32) -> Self {
1281 self.0.style = self.0.style.indent_xy(x, y);
1282 self
1283 }
1284
1285 pub fn indent_axes(mut self, horizontal: f32, vertical: f32) -> Self {
1286 self.0.style = self.0.style.indent_axes(horizontal, vertical);
1287 self
1288 }
1289
1290 pub fn padding(mut self, padding: impl Into<Edges>) -> Self {
1291 self.0.style = self.0.style.padding(padding);
1292 self
1293 }
1294
1295 pub fn pad(self, padding: impl Into<Edges>) -> Self {
1296 self.padding(padding)
1297 }
1298
1299 pub fn padding_xy(mut self, x: f32, y: f32) -> Self {
1300 self.0.style = self.0.style.padding_xy(x, y);
1301 self
1302 }
1303
1304 pub fn padding_x(mut self, x: f32) -> Self {
1305 self.0.style = self.0.style.padding_x(x);
1306 self
1307 }
1308
1309 pub fn padding_y(mut self, y: f32) -> Self {
1310 self.0.style = self.0.style.padding_y(y);
1311 self
1312 }
1313
1314 pub fn padding_left(mut self, v: f32) -> Self {
1315 self.0.style = self.0.style.padding_left(v);
1316 self
1317 }
1318
1319 pub fn padding_right(mut self, v: f32) -> Self {
1320 self.0.style = self.0.style.padding_right(v);
1321 self
1322 }
1323
1324 pub fn padding_top(mut self, v: f32) -> Self {
1325 self.0.style = self.0.style.padding_top(v);
1326 self
1327 }
1328
1329 pub fn padding_bottom(mut self, v: f32) -> Self {
1330 self.0.style = self.0.style.padding_bottom(v);
1331 self
1332 }
1333
1334 pub fn width(mut self, width: impl Into<Length>) -> Self {
1335 self.0.style = self.0.style.width(width.into());
1336 self
1337 }
1338
1339 pub fn height(mut self, height: impl Into<Length>) -> Self {
1340 self.0.style = self.0.style.height(height.into());
1341 self
1342 }
1343
1344 pub fn size(mut self, width: impl Into<Length>, height: impl Into<Length>) -> Self {
1345 self.0.style = self.0.style.width(width.into()).height(height.into());
1346 self
1347 }
1348
1349 pub fn square(mut self, side: impl Into<Length>) -> Self {
1350 let side = side.into();
1351 self.0.style = self.0.style.width(side).height(side);
1352 self
1353 }
1354
1355 pub fn min_width(mut self, v: f32) -> Self {
1356 self.0.style = self.0.style.min_width(v);
1357 self
1358 }
1359
1360 pub fn max_width(mut self, v: f32) -> Self {
1361 self.0.style = self.0.style.max_width(v);
1362 self
1363 }
1364
1365 pub fn min_height(mut self, v: f32) -> Self {
1366 self.0.style = self.0.style.min_height(v);
1367 self
1368 }
1369
1370 pub fn max_height(mut self, v: f32) -> Self {
1371 self.0.style = self.0.style.max_height(v);
1372 self
1373 }
1374
1375 pub fn overflow(mut self, overflow: Overflow) -> Self {
1376 self.0.style = self.0.style.overflow(overflow);
1377 self
1378 }
1379
1380 pub fn flex(mut self, weight: f32) -> Self {
1381 self.0.style = self.0.style.flex(weight);
1382 self
1383 }
1384
1385 pub fn flex_grow(mut self, weight: f32) -> Self {
1386 self.0.style = self.0.style.flex_grow(weight);
1387 self
1388 }
1389
1390 pub fn flex_shrink(mut self, shrink: f32) -> Self {
1391 self.0.style = self.0.style.flex_shrink(shrink);
1392 self
1393 }
1394
1395 pub fn flex_basis(mut self, basis: Option<Length>) -> Self {
1396 self.0.style = self.0.style.flex_basis(basis);
1397 self
1398 }
1399
1400 pub fn align_self(mut self, align: Option<Align>) -> Self {
1401 self.0.style = self.0.style.align_self(align);
1402 self
1403 }
1404
1405 pub fn align_self_value(mut self, align: Align) -> Self {
1406 self.0.style = self.0.style.align_self_value(align);
1407 self
1408 }
1409
1410 pub fn aspect_ratio(mut self, ratio: Option<f32>) -> Self {
1411 self.0.style = self.0.style.aspect_ratio(ratio);
1412 self
1413 }
1414
1415 pub fn aspect(mut self, ratio: f32) -> Self {
1416 self.0.style = self.0.style.aspect(ratio);
1417 self
1418 }
1419
1420 pub fn position(mut self, position: Position) -> Self {
1421 self.0.style = self.0.style.position(position);
1422 self
1423 }
1424
1425 pub fn absolute(mut self) -> Self {
1426 self.0.style = self.0.style.absolute();
1427 self
1428 }
1429
1430 pub fn absolute_at(mut self, left: f32, top: f32) -> Self {
1431 self.0.style = self.0.style.absolute_at(left, top);
1432 self
1433 }
1434
1435 pub fn absolute_inset(mut self, inset: Inset) -> Self {
1436 self.0.style = self.0.style.absolute_inset(inset);
1437 self
1438 }
1439
1440 pub fn expand(self) -> Self {
1441 self.flex(1.0)
1442 }
1443
1444 pub fn fill_width(mut self) -> Self {
1445 self.0.style = self.0.style.width(Length::Fill(1.0));
1446 self
1447 }
1448
1449 pub fn fill_height(mut self) -> Self {
1450 self.0.style = self.0.style.height(Length::Fill(1.0));
1451 self
1452 }
1453
1454 pub fn fill_size(self) -> Self {
1455 self.fill_width().fill_height()
1456 }
1457
1458 pub fn fit(mut self) -> Self {
1459 self.0.style = self.0.style.fit();
1460 self
1461 }
1462
1463 pub fn hit_testable(mut self, on: bool) -> Self {
1464 self.0.style = self.0.style.hit_testable(on);
1465 self
1466 }
1467
1468 pub fn align_items(mut self, align: Align) -> Self {
1469 self.0.align = align;
1470 self
1471 }
1472
1473 pub fn justify_content(mut self, justify: Justify) -> Self {
1474 self.0.justify = justify;
1475 self
1476 }
1477
1478 pub fn center(mut self) -> Self {
1479 self.0.align = Align::Center;
1480 self.0.justify = Justify::Center;
1481 self
1482 }
1483
1484 pub fn background(mut self, color: Color) -> Self {
1485 self.0.deco = self.0.deco.background(color);
1486 self
1487 }
1488
1489 pub fn border(mut self, width: f32, color: Color) -> Self {
1490 self.0.deco = self.0.deco.border(width, color);
1491 self
1492 }
1493
1494 pub fn border_left(mut self, width: f32, color: Color) -> Self {
1495 self.0.deco = self.0.deco.border_left(width, color);
1496 self
1497 }
1498
1499 pub fn border_right(mut self, width: f32, color: Color) -> Self {
1500 self.0.deco = self.0.deco.border_right(width, color);
1501 self
1502 }
1503
1504 pub fn border_top(mut self, width: f32, color: Color) -> Self {
1505 self.0.deco = self.0.deco.border_top(width, color);
1506 self
1507 }
1508
1509 pub fn border_bottom(mut self, width: f32, color: Color) -> Self {
1510 self.0.deco = self.0.deco.border_bottom(width, color);
1511 self
1512 }
1513
1514 pub fn border_x(mut self, width: f32, color: Color) -> Self {
1515 self.0.deco = self.0.deco.border_x(width, color);
1516 self
1517 }
1518
1519 pub fn border_y(mut self, width: f32, color: Color) -> Self {
1520 self.0.deco = self.0.deco.border_y(width, color);
1521 self
1522 }
1523
1524 pub fn radius(mut self, radius: f32) -> Self {
1525 self.0.deco = self.0.deco.radius(radius);
1526 self
1527 }
1528
1529 pub fn box_style(mut self, style: BoxStyle) -> Self {
1530 self.0.deco = style;
1531 self
1532 }
1533
1534 pub fn style(self, style: BoxStyle) -> Self {
1535 self.box_style(style)
1536 }
1537 }
1538 };
1539}
1540
1541pub struct Row(Flex);
1542
1543impl Row {
1544 pub fn new() -> Self {
1545 Self(Flex::new(Axis::Horizontal))
1546 }
1547
1548 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
1549 self.0.children.push(AnyView::new(child));
1550 self.0.flex.push(0.0);
1551 self
1552 }
1553
1554 pub fn child_flex<V: View + 'static>(mut self, child: V, flex: f32) -> Self {
1555 self.0.children.push(AnyView::new(child));
1556 self.0.flex.push(Flex::sanitize_flex(flex));
1557 self
1558 }
1559
1560 pub fn children(mut self, children: impl IntoChildren) -> Self {
1561 let mut children = children.into_children();
1562 self.0.flex.extend(std::iter::repeat_n(0.0, children.len()));
1563 self.0.children.append(&mut children);
1564 self
1565 }
1566}
1567
1568impl Default for Row {
1569 fn default() -> Self {
1570 Self::new()
1571 }
1572}
1573
1574impl View for Row {
1575 fn body(&self) -> impl View + 'static {
1576 Unit
1577 }
1578 fn children_override(&self) -> Option<Vec<AnyView>> {
1579 self.0.children_override()
1580 }
1581 fn layout_style(&self) -> LayoutStyle {
1582 self.0.layout_style()
1583 }
1584 fn container(&self) -> Option<ContainerStyle> {
1585 self.0.container()
1586 }
1587 fn flex_weights(&self) -> Option<&[f32]> {
1588 Some(&self.0.flex)
1589 }
1590 fn paint_self(&self, ctx: &mut PaintCtx) {
1591 ctx.paint_box(self.0.deco);
1592 }
1593}
1594
1595impl_flex_container!(Row, Axis::Horizontal);
1596
1597pub struct Column(Flex);
1598
1599impl Column {
1600 pub fn new() -> Self {
1601 Self(Flex::new(Axis::Vertical))
1602 }
1603
1604 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
1605 self.0.children.push(AnyView::new(child));
1606 self.0.flex.push(0.0);
1607 self
1608 }
1609
1610 pub fn child_flex<V: View + 'static>(mut self, child: V, flex: f32) -> Self {
1611 self.0.children.push(AnyView::new(child));
1612 self.0.flex.push(Flex::sanitize_flex(flex));
1613 self
1614 }
1615
1616 pub fn children(mut self, children: impl IntoChildren) -> Self {
1617 let mut children = children.into_children();
1618 self.0.flex.extend(std::iter::repeat_n(0.0, children.len()));
1619 self.0.children.append(&mut children);
1620 self
1621 }
1622}
1623
1624impl Default for Column {
1625 fn default() -> Self {
1626 Self::new()
1627 }
1628}
1629
1630impl View for Column {
1631 fn body(&self) -> impl View + 'static {
1632 Unit
1633 }
1634 fn children_override(&self) -> Option<Vec<AnyView>> {
1635 self.0.children_override()
1636 }
1637 fn layout_style(&self) -> LayoutStyle {
1638 self.0.layout_style()
1639 }
1640 fn container(&self) -> Option<ContainerStyle> {
1641 self.0.container()
1642 }
1643 fn flex_weights(&self) -> Option<&[f32]> {
1644 Some(&self.0.flex)
1645 }
1646 fn paint_self(&self, ctx: &mut PaintCtx) {
1647 ctx.paint_box(self.0.deco);
1648 }
1649}
1650
1651impl_flex_container!(Column, Axis::Vertical);
1652
1653#[derive(Clone)]
1654pub struct Stack {
1655 children: Vec<AnyView>,
1656 positions: Vec<StackPos>,
1657 style: LayoutStyle,
1658 deco: BoxStyle,
1659}
1660
1661impl Default for Stack {
1662 fn default() -> Self {
1663 Self {
1664 children: Vec::new(),
1665 positions: Vec::new(),
1666 style: LayoutStyle::default(),
1667 deco: BoxStyle::new(),
1668 }
1669 }
1670}
1671
1672#[derive(Clone, Copy, Debug, Default, PartialEq)]
1673pub struct StackPos {
1674 pub top: Option<f32>,
1675
1676 pub left: Option<f32>,
1677
1678 pub bottom: Option<f32>,
1679
1680 pub right: Option<f32>,
1681
1682 pub dx: f32,
1683
1684 pub dy: f32,
1685
1686 pub z: i32,
1687}
1688
1689impl StackPos {
1690 pub const fn top() -> Self {
1691 Self {
1692 top: Some(0.0),
1693 left: None,
1694 bottom: None,
1695 right: None,
1696 dx: 0.0,
1697 dy: 0.0,
1698 z: 0,
1699 }
1700 }
1701
1702 pub const fn bottom() -> Self {
1703 Self {
1704 top: None,
1705 left: None,
1706 bottom: Some(0.0),
1707 right: None,
1708 dx: 0.0,
1709 dy: 0.0,
1710 z: 0,
1711 }
1712 }
1713
1714 pub const fn left() -> Self {
1715 Self {
1716 top: None,
1717 left: Some(0.0),
1718 bottom: None,
1719 right: None,
1720 dx: 0.0,
1721 dy: 0.0,
1722 z: 0,
1723 }
1724 }
1725
1726 pub const fn right() -> Self {
1727 Self {
1728 top: None,
1729 left: None,
1730 bottom: None,
1731 right: Some(0.0),
1732 dx: 0.0,
1733 dy: 0.0,
1734 z: 0,
1735 }
1736 }
1737
1738 pub const fn top_left() -> Self {
1739 Self {
1740 top: Some(0.0),
1741 left: Some(0.0),
1742 bottom: None,
1743 right: None,
1744 dx: 0.0,
1745 dy: 0.0,
1746 z: 0,
1747 }
1748 }
1749
1750 pub const fn top_right() -> Self {
1751 Self {
1752 top: Some(0.0),
1753 left: None,
1754 bottom: None,
1755 right: Some(0.0),
1756 dx: 0.0,
1757 dy: 0.0,
1758 z: 0,
1759 }
1760 }
1761
1762 pub const fn bottom_left() -> Self {
1763 Self {
1764 top: None,
1765 left: Some(0.0),
1766 bottom: Some(0.0),
1767 right: None,
1768 dx: 0.0,
1769 dy: 0.0,
1770 z: 0,
1771 }
1772 }
1773
1774 pub const fn bottom_right() -> Self {
1775 Self {
1776 top: None,
1777 left: None,
1778 bottom: Some(0.0),
1779 right: Some(0.0),
1780 dx: 0.0,
1781 dy: 0.0,
1782 z: 0,
1783 }
1784 }
1785
1786 pub const fn fill() -> Self {
1787 Self {
1788 top: Some(0.0),
1789 left: Some(0.0),
1790 bottom: Some(0.0),
1791 right: Some(0.0),
1792 dx: 0.0,
1793 dy: 0.0,
1794 z: 0,
1795 }
1796 }
1797
1798 pub const fn offset(mut self, dx: f32, dy: f32) -> Self {
1799 self.dx = dx;
1800 self.dy = dy;
1801 self
1802 }
1803
1804 pub const fn z(mut self, z: i32) -> Self {
1805 self.z = z;
1806 self
1807 }
1808
1809 pub const fn is_pinned(self) -> bool {
1810 self.top.is_some() || self.left.is_some() || self.bottom.is_some() || self.right.is_some()
1811 }
1812}
1813
1814impl Stack {
1815 pub fn new() -> Self {
1816 Self::default()
1817 }
1818
1819 fn stack_axis(len: Length, measured: f32, start: f32, extent: f32) -> (f32, f32) {
1820 if len.is_fill() && extent.is_finite() {
1821 return (extent.max(0.0), start);
1822 }
1823
1824 let size = measured.max(0.0);
1825 let off = if extent.is_finite() {
1826 ((extent - size) * 0.5).max(0.0)
1827 } else {
1828 0.0
1829 };
1830 (size, start + off)
1831 }
1832
1833 fn pinned_axis(
1834 pin_start: Option<f32>,
1835 pin_end: Option<f32>,
1836 delta: f32,
1837 len: Length,
1838 measured: f32,
1839 start: f32,
1840 extent: f32,
1841 ) -> (f32, f32) {
1842 let delta = if delta.is_finite() { delta } else { 0.0 };
1843 if !extent.is_finite() {
1844 return (measured.max(0.0), start + delta);
1845 }
1846 let extent = extent.max(0.0);
1847 match (pin_start, pin_end) {
1848 (Some(a), Some(b)) => {
1849 let x = a.max(0.0);
1850 let w = (extent - a.max(0.0) - b.max(0.0)).max(0.0);
1851 (w, start + x + delta)
1852 }
1853 (Some(a), None) => {
1854 let size = if len.is_fill() {
1855 (extent - a.max(0.0)).max(0.0)
1856 } else {
1857 measured.max(0.0)
1858 };
1859 (size, start + a + delta)
1860 }
1861 (None, Some(b)) => {
1862 let size = if len.is_fill() {
1863 (extent - b.max(0.0)).max(0.0)
1864 } else {
1865 measured.max(0.0)
1866 };
1867 (size, start + extent - b - size + delta)
1868 }
1869 (None, None) => {
1870 let (size, off) = Self::stack_axis(len, measured, start, extent);
1871 (size, off + delta)
1872 }
1873 }
1874 }
1875
1876 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
1877 self.children.push(AnyView::new(child));
1878 self.positions.push(StackPos::default());
1879 self
1880 }
1881
1882 pub fn child_at<V: View + 'static>(mut self, child: V, pos: StackPos) -> Self {
1883 self.children.push(AnyView::new(child));
1884 self.positions.push(pos);
1885 self
1886 }
1887
1888 pub fn child_z<V: View + 'static>(mut self, child: V, z: i32) -> Self {
1889 self.children.push(AnyView::new(child));
1890 self.positions.push(StackPos::default().z(z));
1891 self
1892 }
1893
1894 pub fn fill<V: View + 'static>(mut self, child: V) -> Self {
1895 self.children.push(AnyView::new(child));
1896 self.positions.push(StackPos::fill());
1897 self
1898 }
1899
1900 pub fn overlay<V: View + 'static>(mut self, child: V, dx: f32, dy: f32) -> Self {
1901 self.children.push(AnyView::new(child));
1902 self.positions.push(StackPos::top_left().offset(dx, dy));
1903 self
1904 }
1905
1906 pub fn hud<V: View + 'static>(mut self, child: V, dy: f32) -> Self {
1907 self.children.push(AnyView::new(child));
1908 self.positions.push(StackPos::bottom().offset(0.0, dy));
1909 self
1910 }
1911
1912 fn paint_order(&self) -> Option<Vec<usize>> {
1913 if self.positions.windows(2).all(|w| w[0].z <= w[1].z) {
1914 return None;
1915 }
1916 let mut order: Vec<usize> = (0..self.children.len()).collect();
1917 order.sort_by_key(|&i| self.positions.get(i).map_or(0, |p| p.z));
1918 Some(order)
1919 }
1920
1921 fn pos_at(&self, i: usize, order: Option<&[usize]>) -> StackPos {
1922 match order {
1923 None => self.positions.get(i).copied().unwrap_or_default(),
1924 Some(order) => order
1925 .get(i)
1926 .and_then(|&k| self.positions.get(k))
1927 .copied()
1928 .unwrap_or_default(),
1929 }
1930 }
1931
1932 pub fn children(mut self, children: impl IntoChildren) -> Self {
1933 for c in children.into_children() {
1934 self.children.push(c);
1935 self.positions.push(StackPos::default());
1936 }
1937 self
1938 }
1939
1940 pub fn padding(mut self, padding: impl Into<Edges>) -> Self {
1941 self.style = self.style.padding(padding);
1942 self
1943 }
1944
1945 pub fn pad(self, padding: impl Into<Edges>) -> Self {
1946 self.padding(padding)
1947 }
1948
1949 pub fn padding_xy(mut self, x: f32, y: f32) -> Self {
1950 self.style = self.style.padding_xy(x, y);
1951 self
1952 }
1953
1954 pub fn padding_x(mut self, x: f32) -> Self {
1955 self.style = self.style.padding_x(x);
1956 self
1957 }
1958
1959 pub fn padding_y(mut self, y: f32) -> Self {
1960 self.style = self.style.padding_y(y);
1961 self
1962 }
1963
1964 pub fn padding_left(mut self, v: f32) -> Self {
1965 self.style = self.style.padding_left(v);
1966 self
1967 }
1968
1969 pub fn padding_right(mut self, v: f32) -> Self {
1970 self.style = self.style.padding_right(v);
1971 self
1972 }
1973
1974 pub fn padding_top(mut self, v: f32) -> Self {
1975 self.style = self.style.padding_top(v);
1976 self
1977 }
1978
1979 pub fn padding_bottom(mut self, v: f32) -> Self {
1980 self.style = self.style.padding_bottom(v);
1981 self
1982 }
1983
1984 pub fn width(mut self, width: impl Into<Length>) -> Self {
1985 self.style = self.style.width(width.into());
1986 self
1987 }
1988
1989 pub fn height(mut self, height: impl Into<Length>) -> Self {
1990 self.style = self.style.height(height.into());
1991 self
1992 }
1993
1994 pub fn size(mut self, width: impl Into<Length>, height: impl Into<Length>) -> Self {
1995 self.style = self.style.width(width.into()).height(height.into());
1996 self
1997 }
1998
1999 pub fn square(mut self, side: impl Into<Length>) -> Self {
2000 let side = side.into();
2001 self.style = self.style.width(side).height(side);
2002 self
2003 }
2004
2005 pub fn min_width(mut self, v: f32) -> Self {
2006 self.style = self.style.min_width(v);
2007 self
2008 }
2009
2010 pub fn max_width(mut self, v: f32) -> Self {
2011 self.style = self.style.max_width(v);
2012 self
2013 }
2014
2015 pub fn min_height(mut self, v: f32) -> Self {
2016 self.style = self.style.min_height(v);
2017 self
2018 }
2019
2020 pub fn max_height(mut self, v: f32) -> Self {
2021 self.style = self.style.max_height(v);
2022 self
2023 }
2024
2025 pub fn overflow(mut self, overflow: Overflow) -> Self {
2026 self.style = self.style.overflow(overflow);
2027 self
2028 }
2029
2030 pub fn flex(mut self, weight: f32) -> Self {
2031 self.style = self.style.flex(weight);
2032 self
2033 }
2034
2035 pub fn expand(self) -> Self {
2036 self.flex(1.0)
2037 }
2038
2039 pub fn fill_width(mut self) -> Self {
2040 self.style = self.style.width(Length::Fill(1.0));
2041 self
2042 }
2043
2044 pub fn fill_height(mut self) -> Self {
2045 self.style = self.style.height(Length::Fill(1.0));
2046 self
2047 }
2048
2049 pub fn fill_size(self) -> Self {
2050 self.fill_width().fill_height()
2051 }
2052
2053 pub fn background(mut self, color: Color) -> Self {
2054 self.deco = self.deco.background(color);
2055 self
2056 }
2057
2058 pub fn border(mut self, width: f32, color: Color) -> Self {
2059 self.deco = self.deco.border(width, color);
2060 self
2061 }
2062
2063 pub fn border_left(mut self, width: f32, color: Color) -> Self {
2064 self.deco = self.deco.border_left(width, color);
2065 self
2066 }
2067
2068 pub fn border_right(mut self, width: f32, color: Color) -> Self {
2069 self.deco = self.deco.border_right(width, color);
2070 self
2071 }
2072
2073 pub fn border_top(mut self, width: f32, color: Color) -> Self {
2074 self.deco = self.deco.border_top(width, color);
2075 self
2076 }
2077
2078 pub fn border_bottom(mut self, width: f32, color: Color) -> Self {
2079 self.deco = self.deco.border_bottom(width, color);
2080 self
2081 }
2082
2083 pub fn border_x(mut self, width: f32, color: Color) -> Self {
2084 self.deco = self.deco.border_x(width, color);
2085 self
2086 }
2087
2088 pub fn border_y(mut self, width: f32, color: Color) -> Self {
2089 self.deco = self.deco.border_y(width, color);
2090 self
2091 }
2092
2093 pub fn radius(mut self, radius: f32) -> Self {
2094 self.deco = self.deco.radius(radius);
2095 self
2096 }
2097
2098 pub fn box_style(mut self, style: BoxStyle) -> Self {
2099 self.deco = style;
2100 self
2101 }
2102
2103 pub fn style(self, style: BoxStyle) -> Self {
2104 self.box_style(style)
2105 }
2106}
2107
2108impl_style_extras!(Stack);
2109
2110impl View for Stack {
2111 fn body(&self) -> impl View + 'static {
2112 Unit
2113 }
2114 fn children_override(&self) -> Option<Vec<AnyView>> {
2115 Some(match self.paint_order() {
2116 None => self.children.clone(),
2117 Some(order) => order
2118 .iter()
2119 .filter_map(|&i| self.children.get(i).cloned())
2120 .collect(),
2121 })
2122 }
2123 fn layout_style(&self) -> LayoutStyle {
2124 let mut style = self.style;
2125 let edges = self.deco.border_edges();
2126 style.padding.left += edges.left;
2127 style.padding.top += edges.top;
2128 style.padding.right += edges.right;
2129 style.padding.bottom += edges.bottom;
2130 style
2131 }
2132 fn paint_self(&self, ctx: &mut PaintCtx) {
2133 ctx.paint_box(self.deco);
2134 }
2135 fn arrange_override(
2136 &self,
2137 rt: &Runtime,
2138 el: ElementId,
2139 rect: Rect,
2140 ctx: &mut LayoutCtx,
2141 ) -> bool {
2142 let mut pad = self.style.padding;
2143 let edges = self.deco.border_edges();
2144 pad.left += edges.left;
2145 pad.top += edges.top;
2146 pad.right += edges.right;
2147 pad.bottom += edges.bottom;
2148 let content = Rect::from_xywh(
2149 rect.left() + pad.left,
2150 rect.top() + pad.top,
2151 (rect.size.width - pad.horizontal_sum()).max(0.0),
2152 (rect.size.height - pad.vertical_sum()).max(0.0),
2153 );
2154 let max = Size::new(content.size.width, content.size.height);
2155 let order = self.paint_order();
2156 let kids = rt.children(el);
2157 for (i, child) in kids.iter().enumerate() {
2158 let style = rt.child_layout_style(*child);
2159
2160 if style.is_absolute() {
2161 rt.arrange_absolute(*child, content, ctx);
2162 continue;
2163 }
2164 let pos = self.pos_at(i, order.as_deref());
2165
2166 let m = rt.measure_node(
2167 *child,
2168 Constraints {
2169 min: Size::ZERO,
2170 max,
2171 },
2172 ctx,
2173 );
2174 let (w0, x) = Self::pinned_axis(
2175 pos.left,
2176 pos.right,
2177 pos.dx,
2178 style.width,
2179 m.width,
2180 content.left(),
2181 content.size.width,
2182 );
2183 let (h0, y) = Self::pinned_axis(
2184 pos.top,
2185 pos.bottom,
2186 pos.dy,
2187 style.height,
2188 m.height,
2189 content.top(),
2190 content.size.height,
2191 );
2192
2193 let w = style.clamp_width(w0).max(0.0);
2194 let h = style.clamp_height(h0).max(0.0);
2195 rt.arrange_node(*child, Rect::from_xywh(x, y, w, h), ctx);
2196 }
2197 true
2198 }
2199}
2200
2201pub struct Grid {
2202 children: Vec<AnyView>,
2203 placements: Vec<GridPlacement>,
2204 style: LayoutStyle,
2205 grid: GridStyle,
2206 deco: BoxStyle,
2207}
2208
2209impl Grid {
2210 pub fn new(columns: impl IntoIterator<Item = Track>) -> Self {
2211 Self {
2212 children: Vec::new(),
2213 placements: Vec::new(),
2214 style: LayoutStyle {
2215 width: Length::Fit,
2216 height: Length::Fit,
2217 ..LayoutStyle::default()
2218 },
2219 grid: GridStyle::new(columns),
2220 deco: BoxStyle::new(),
2221 }
2222 }
2223
2224 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
2225 self.children.push(AnyView::new(child));
2226 self.placements.push(GridPlacement::AUTO);
2227 self
2228 }
2229
2230 pub fn child_at<V: View + 'static>(mut self, child: V, placement: GridPlacement) -> Self {
2231 self.children.push(AnyView::new(child));
2232 self.placements.push(placement);
2233 self
2234 }
2235
2236 pub fn child_span<V: View + 'static>(
2237 mut self,
2238 child: V,
2239 column: usize,
2240 row: usize,
2241 col_span: usize,
2242 row_span: usize,
2243 ) -> Self {
2244 self.children.push(AnyView::new(child));
2245 self.placements.push(
2246 GridPlacement::new()
2247 .at(column, row)
2248 .span(col_span, row_span),
2249 );
2250 self
2251 }
2252
2253 pub fn children(mut self, children: impl IntoChildren) -> Self {
2254 let mut children = children.into_children();
2255 self.placements
2256 .extend(std::iter::repeat_n(GridPlacement::AUTO, children.len()));
2257 self.children.append(&mut children);
2258 self
2259 }
2260
2261 pub fn rows(mut self, rows: impl IntoIterator<Item = Track>) -> Self {
2262 self.grid = self.grid.rows(rows);
2263 self
2264 }
2265
2266 pub fn gap(mut self, gap: f32) -> Self {
2267 self.grid = self.grid.gap(gap);
2268 self
2269 }
2270
2271 pub fn column_gap(mut self, gap: f32) -> Self {
2272 self.grid = self.grid.column_gap(gap);
2273 self
2274 }
2275
2276 pub fn row_gap(mut self, gap: f32) -> Self {
2277 self.grid = self.grid.row_gap(gap);
2278 self
2279 }
2280
2281 pub fn auto_flow(mut self, flow: GridFlow) -> Self {
2282 self.grid = self.grid.auto_flow(flow);
2283 self
2284 }
2285
2286 pub fn column_flow(mut self) -> Self {
2287 self.grid = self.grid.column_flow();
2288 self
2289 }
2290
2291 pub fn align_items(mut self, align: Align) -> Self {
2292 self.grid = self.grid.align_items(align);
2293 self
2294 }
2295
2296 pub fn justify_items(mut self, align: Align) -> Self {
2297 self.grid = self.grid.justify_items(align);
2298 self
2299 }
2300
2301 pub fn place_items(mut self, align: Align) -> Self {
2302 self.grid = self.grid.place_items(align);
2303 self
2304 }
2305
2306 pub fn margin(mut self, margin: impl Into<Edges>) -> Self {
2307 self.style = self.style.margin(margin);
2308 self
2309 }
2310
2311 pub fn margin_xy(mut self, x: f32, y: f32) -> Self {
2312 self.style = self.style.margin_xy(x, y);
2313 self
2314 }
2315
2316 pub fn margin_x(mut self, x: f32) -> Self {
2317 self.style = self.style.margin_x(x);
2318 self
2319 }
2320
2321 pub fn margin_y(mut self, y: f32) -> Self {
2322 self.style = self.style.margin_y(y);
2323 self
2324 }
2325
2326 pub fn margin_left(mut self, v: f32) -> Self {
2327 self.style = self.style.margin_left(v);
2328 self
2329 }
2330
2331 pub fn margin_right(mut self, v: f32) -> Self {
2332 self.style = self.style.margin_right(v);
2333 self
2334 }
2335
2336 pub fn margin_top(mut self, v: f32) -> Self {
2337 self.style = self.style.margin_top(v);
2338 self
2339 }
2340
2341 pub fn margin_bottom(mut self, v: f32) -> Self {
2342 self.style = self.style.margin_bottom(v);
2343 self
2344 }
2345
2346 pub fn padding(mut self, padding: impl Into<Edges>) -> Self {
2347 self.style = self.style.padding(padding);
2348 self
2349 }
2350
2351 pub fn pad(self, padding: impl Into<Edges>) -> Self {
2352 self.padding(padding)
2353 }
2354
2355 pub fn padding_xy(mut self, x: f32, y: f32) -> Self {
2356 self.style = self.style.padding_xy(x, y);
2357 self
2358 }
2359
2360 pub fn padding_x(mut self, x: f32) -> Self {
2361 self.style = self.style.padding_x(x);
2362 self
2363 }
2364
2365 pub fn padding_y(mut self, y: f32) -> Self {
2366 self.style = self.style.padding_y(y);
2367 self
2368 }
2369
2370 pub fn padding_left(mut self, v: f32) -> Self {
2371 self.style = self.style.padding_left(v);
2372 self
2373 }
2374
2375 pub fn padding_right(mut self, v: f32) -> Self {
2376 self.style = self.style.padding_right(v);
2377 self
2378 }
2379
2380 pub fn padding_top(mut self, v: f32) -> Self {
2381 self.style = self.style.padding_top(v);
2382 self
2383 }
2384
2385 pub fn padding_bottom(mut self, v: f32) -> Self {
2386 self.style = self.style.padding_bottom(v);
2387 self
2388 }
2389
2390 pub fn width(mut self, width: impl Into<Length>) -> Self {
2391 self.style = self.style.width(width.into());
2392 self
2393 }
2394
2395 pub fn height(mut self, height: impl Into<Length>) -> Self {
2396 self.style = self.style.height(height.into());
2397 self
2398 }
2399
2400 pub fn size(mut self, width: impl Into<Length>, height: impl Into<Length>) -> Self {
2401 self.style = self.style.width(width.into()).height(height.into());
2402 self
2403 }
2404
2405 pub fn square(mut self, side: impl Into<Length>) -> Self {
2406 let side = side.into();
2407 self.style = self.style.width(side).height(side);
2408 self
2409 }
2410
2411 pub fn min_width(mut self, v: f32) -> Self {
2412 self.style = self.style.min_width(v);
2413 self
2414 }
2415
2416 pub fn max_width(mut self, v: f32) -> Self {
2417 self.style = self.style.max_width(v);
2418 self
2419 }
2420
2421 pub fn min_height(mut self, v: f32) -> Self {
2422 self.style = self.style.min_height(v);
2423 self
2424 }
2425
2426 pub fn max_height(mut self, v: f32) -> Self {
2427 self.style = self.style.max_height(v);
2428 self
2429 }
2430
2431 pub fn overflow(mut self, overflow: Overflow) -> Self {
2432 self.style = self.style.overflow(overflow);
2433 self
2434 }
2435
2436 pub fn flex(mut self, weight: f32) -> Self {
2437 self.style = self.style.flex(weight);
2438 self
2439 }
2440
2441 pub fn flex_shrink(mut self, shrink: f32) -> Self {
2442 self.style = self.style.flex_shrink(shrink);
2443 self
2444 }
2445
2446 pub fn flex_basis(mut self, basis: Option<Length>) -> Self {
2447 self.style = self.style.flex_basis(basis);
2448 self
2449 }
2450
2451 pub fn align_self(mut self, align: Option<Align>) -> Self {
2452 self.style = self.style.align_self(align);
2453 self
2454 }
2455
2456 pub fn aspect_ratio(mut self, ratio: Option<f32>) -> Self {
2457 self.style = self.style.aspect_ratio(ratio);
2458 self
2459 }
2460
2461 pub fn aspect(mut self, ratio: f32) -> Self {
2462 self.style = self.style.aspect(ratio);
2463 self
2464 }
2465
2466 pub fn position(mut self, position: Position) -> Self {
2467 self.style = self.style.position(position);
2468 self
2469 }
2470
2471 pub fn absolute(mut self) -> Self {
2472 self.style = self.style.absolute();
2473 self
2474 }
2475
2476 pub fn absolute_at(mut self, left: f32, top: f32) -> Self {
2477 self.style = self.style.absolute_at(left, top);
2478 self
2479 }
2480
2481 pub fn absolute_inset(mut self, inset: Inset) -> Self {
2482 self.style = self.style.absolute_inset(inset);
2483 self
2484 }
2485
2486 pub fn expand(self) -> Self {
2487 self.flex(1.0)
2488 }
2489
2490 pub fn fill_width(mut self) -> Self {
2491 self.style = self.style.width(Length::Fill(1.0));
2492 self
2493 }
2494
2495 pub fn fill_height(mut self) -> Self {
2496 self.style = self.style.height(Length::Fill(1.0));
2497 self
2498 }
2499
2500 pub fn fill_size(self) -> Self {
2501 self.fill_width().fill_height()
2502 }
2503
2504 pub fn background(mut self, color: Color) -> Self {
2505 self.deco = self.deco.background(color);
2506 self
2507 }
2508
2509 pub fn border(mut self, width: f32, color: Color) -> Self {
2510 self.deco = self.deco.border(width, color);
2511 self
2512 }
2513
2514 pub fn border_left(mut self, width: f32, color: Color) -> Self {
2515 self.deco = self.deco.border_left(width, color);
2516 self
2517 }
2518
2519 pub fn border_right(mut self, width: f32, color: Color) -> Self {
2520 self.deco = self.deco.border_right(width, color);
2521 self
2522 }
2523
2524 pub fn border_top(mut self, width: f32, color: Color) -> Self {
2525 self.deco = self.deco.border_top(width, color);
2526 self
2527 }
2528
2529 pub fn border_bottom(mut self, width: f32, color: Color) -> Self {
2530 self.deco = self.deco.border_bottom(width, color);
2531 self
2532 }
2533
2534 pub fn border_x(mut self, width: f32, color: Color) -> Self {
2535 self.deco = self.deco.border_x(width, color);
2536 self
2537 }
2538
2539 pub fn border_y(mut self, width: f32, color: Color) -> Self {
2540 self.deco = self.deco.border_y(width, color);
2541 self
2542 }
2543
2544 pub fn radius(mut self, radius: f32) -> Self {
2545 self.deco = self.deco.radius(radius);
2546 self
2547 }
2548
2549 pub fn box_style(mut self, style: BoxStyle) -> Self {
2550 self.deco = style;
2551 self
2552 }
2553
2554 pub fn style(self, style: BoxStyle) -> Self {
2555 self.box_style(style)
2556 }
2557}
2558
2559impl View for Grid {
2560 fn body(&self) -> impl View + 'static {
2561 Unit
2562 }
2563 fn children_override(&self) -> Option<Vec<AnyView>> {
2564 Some(self.children.clone())
2565 }
2566 fn layout_style(&self) -> LayoutStyle {
2567 self.style
2568 }
2569 fn grid(&self) -> Option<GridStyle> {
2570 Some(self.grid.clone())
2571 }
2572 fn grid_placements(&self) -> Option<Vec<GridPlacement>> {
2573 Some(self.placements.clone())
2574 }
2575 fn paint_self(&self, ctx: &mut PaintCtx) {
2576 ctx.paint_box(self.deco);
2577 }
2578}
2579
2580pub struct Wrap {
2581 children: Vec<AnyView>,
2582 style: LayoutStyle,
2583 wrap: WrapStyle,
2584 deco: BoxStyle,
2585}
2586
2587impl Wrap {
2588 pub fn new() -> Self {
2589 Self {
2590 children: Vec::new(),
2591 style: LayoutStyle {
2592 width: Length::Fill(1.0),
2593 height: Length::Fit,
2594 ..LayoutStyle::default()
2595 },
2596 wrap: WrapStyle::new(Axis::Horizontal),
2597 deco: BoxStyle::new(),
2598 }
2599 }
2600
2601 pub fn vertical() -> Self {
2602 Self {
2603 wrap: WrapStyle::new(Axis::Vertical),
2604 ..Self::new()
2605 }
2606 }
2607
2608 pub fn axis(mut self, axis: Axis) -> Self {
2609 self.wrap = self.wrap.axis(axis);
2610 self
2611 }
2612
2613 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
2614 self.children.push(AnyView::new(child));
2615 self
2616 }
2617
2618 pub fn children(mut self, children: impl IntoChildren) -> Self {
2619 self.children.extend(children.into_children());
2620 self
2621 }
2622
2623 pub fn gap(mut self, gap: f32) -> Self {
2624 self.wrap = self.wrap.gap(gap);
2625 self
2626 }
2627
2628 pub fn column_gap(mut self, gap: f32) -> Self {
2629 self.wrap = self.wrap.column_gap(gap);
2630 self
2631 }
2632
2633 pub fn row_gap(mut self, gap: f32) -> Self {
2634 self.wrap = self.wrap.row_gap(gap);
2635 self
2636 }
2637
2638 pub fn align_items(mut self, align: Align) -> Self {
2639 self.wrap = self.wrap.align(align);
2640 self
2641 }
2642
2643 pub fn padding(mut self, padding: impl Into<Edges>) -> Self {
2644 self.style = self.style.padding(padding);
2645 self
2646 }
2647
2648 pub fn pad(self, padding: impl Into<Edges>) -> Self {
2649 self.padding(padding)
2650 }
2651
2652 pub fn padding_xy(mut self, x: f32, y: f32) -> Self {
2653 self.style = self.style.padding_xy(x, y);
2654 self
2655 }
2656
2657 pub fn padding_x(mut self, x: f32) -> Self {
2658 self.style = self.style.padding_x(x);
2659 self
2660 }
2661
2662 pub fn padding_y(mut self, y: f32) -> Self {
2663 self.style = self.style.padding_y(y);
2664 self
2665 }
2666
2667 pub fn padding_left(mut self, v: f32) -> Self {
2668 self.style = self.style.padding_left(v);
2669 self
2670 }
2671
2672 pub fn padding_right(mut self, v: f32) -> Self {
2673 self.style = self.style.padding_right(v);
2674 self
2675 }
2676
2677 pub fn padding_top(mut self, v: f32) -> Self {
2678 self.style = self.style.padding_top(v);
2679 self
2680 }
2681
2682 pub fn padding_bottom(mut self, v: f32) -> Self {
2683 self.style = self.style.padding_bottom(v);
2684 self
2685 }
2686
2687 pub fn width(mut self, width: impl Into<Length>) -> Self {
2688 self.style = self.style.width(width.into());
2689 self
2690 }
2691
2692 pub fn height(mut self, height: impl Into<Length>) -> Self {
2693 self.style = self.style.height(height.into());
2694 self
2695 }
2696
2697 pub fn size(mut self, width: impl Into<Length>, height: impl Into<Length>) -> Self {
2698 self.style = self.style.width(width.into()).height(height.into());
2699 self
2700 }
2701
2702 pub fn square(mut self, side: impl Into<Length>) -> Self {
2703 let side = side.into();
2704 self.style = self.style.width(side).height(side);
2705 self
2706 }
2707
2708 pub fn min_width(mut self, v: f32) -> Self {
2709 self.style = self.style.min_width(v);
2710 self
2711 }
2712
2713 pub fn max_width(mut self, v: f32) -> Self {
2714 self.style = self.style.max_width(v);
2715 self
2716 }
2717
2718 pub fn min_height(mut self, v: f32) -> Self {
2719 self.style = self.style.min_height(v);
2720 self
2721 }
2722
2723 pub fn max_height(mut self, v: f32) -> Self {
2724 self.style = self.style.max_height(v);
2725 self
2726 }
2727
2728 pub fn overflow(mut self, overflow: Overflow) -> Self {
2729 self.style = self.style.overflow(overflow);
2730 self
2731 }
2732
2733 pub fn flex(mut self, weight: f32) -> Self {
2734 self.style = self.style.flex(weight);
2735 self
2736 }
2737
2738 pub fn expand(self) -> Self {
2739 self.flex(1.0)
2740 }
2741
2742 pub fn fill_width(mut self) -> Self {
2743 self.style = self.style.width(Length::Fill(1.0));
2744 self
2745 }
2746
2747 pub fn fill_height(mut self) -> Self {
2748 self.style = self.style.height(Length::Fill(1.0));
2749 self
2750 }
2751
2752 pub fn fill_size(self) -> Self {
2753 self.fill_width().fill_height()
2754 }
2755
2756 pub fn background(mut self, color: Color) -> Self {
2757 self.deco = self.deco.background(color);
2758 self
2759 }
2760
2761 pub fn border(mut self, width: f32, color: Color) -> Self {
2762 self.deco = self.deco.border(width, color);
2763 self
2764 }
2765
2766 pub fn border_left(mut self, width: f32, color: Color) -> Self {
2767 self.deco = self.deco.border_left(width, color);
2768 self
2769 }
2770
2771 pub fn border_right(mut self, width: f32, color: Color) -> Self {
2772 self.deco = self.deco.border_right(width, color);
2773 self
2774 }
2775
2776 pub fn border_top(mut self, width: f32, color: Color) -> Self {
2777 self.deco = self.deco.border_top(width, color);
2778 self
2779 }
2780
2781 pub fn border_bottom(mut self, width: f32, color: Color) -> Self {
2782 self.deco = self.deco.border_bottom(width, color);
2783 self
2784 }
2785
2786 pub fn border_x(mut self, width: f32, color: Color) -> Self {
2787 self.deco = self.deco.border_x(width, color);
2788 self
2789 }
2790
2791 pub fn border_y(mut self, width: f32, color: Color) -> Self {
2792 self.deco = self.deco.border_y(width, color);
2793 self
2794 }
2795
2796 pub fn radius(mut self, radius: f32) -> Self {
2797 self.deco = self.deco.radius(radius);
2798 self
2799 }
2800
2801 pub fn box_style(mut self, style: BoxStyle) -> Self {
2802 self.deco = style;
2803 self
2804 }
2805
2806 pub fn style(self, style: BoxStyle) -> Self {
2807 self.box_style(style)
2808 }
2809}
2810
2811impl Default for Wrap {
2812 fn default() -> Self {
2813 Self::new()
2814 }
2815}
2816
2817impl_style_extras!(Wrap);
2818
2819impl View for Wrap {
2820 fn body(&self) -> impl View + 'static {
2821 Unit
2822 }
2823 fn children_override(&self) -> Option<Vec<AnyView>> {
2824 Some(self.children.clone())
2825 }
2826 fn layout_style(&self) -> LayoutStyle {
2827 self.style
2828 }
2829 fn wrap(&self) -> Option<WrapStyle> {
2830 Some(self.wrap)
2831 }
2832 fn paint_self(&self, ctx: &mut PaintCtx) {
2833 ctx.paint_box(self.deco);
2834 }
2835}
2836
2837#[derive(Clone, Copy, Debug)]
2838pub struct Panel {
2839 color: Option<Color>,
2840 radius: f32,
2841 style: LayoutStyle,
2842 borders: BoxStyle,
2843}
2844
2845impl Default for Panel {
2846 fn default() -> Self {
2847 Self {
2848 color: None,
2849 radius: 0.0,
2850 style: LayoutStyle::default(),
2851 borders: BoxStyle::new(),
2852 }
2853 }
2854}
2855
2856impl Panel {
2857 pub fn new() -> Self {
2858 Self::default()
2859 }
2860
2861 pub fn background(mut self, color: Color) -> Self {
2862 self.color = Some(color);
2863 self
2864 }
2865
2866 pub fn radius(mut self, radius: f32) -> Self {
2867 self.radius = radius.max(0.0);
2868 self
2869 }
2870
2871 pub fn border(mut self, width: f32, color: Color) -> Self {
2872 self.borders = self.borders.border(width, color);
2873 self
2874 }
2875
2876 pub fn border_left(mut self, width: f32, color: Color) -> Self {
2877 self.borders = self.borders.border_left(width, color);
2878 self
2879 }
2880
2881 pub fn border_right(mut self, width: f32, color: Color) -> Self {
2882 self.borders = self.borders.border_right(width, color);
2883 self
2884 }
2885
2886 pub fn border_top(mut self, width: f32, color: Color) -> Self {
2887 self.borders = self.borders.border_top(width, color);
2888 self
2889 }
2890
2891 pub fn border_bottom(mut self, width: f32, color: Color) -> Self {
2892 self.borders = self.borders.border_bottom(width, color);
2893 self
2894 }
2895
2896 pub fn border_x(mut self, width: f32, color: Color) -> Self {
2897 self.borders = self.borders.border_x(width, color);
2898 self
2899 }
2900
2901 pub fn border_y(mut self, width: f32, color: Color) -> Self {
2902 self.borders = self.borders.border_y(width, color);
2903 self
2904 }
2905
2906 pub fn box_style(mut self, style: BoxStyle) -> Self {
2907 if style.background.a > 0.0 {
2908 self.color = Some(style.background);
2909 } else {
2910 self.color = None;
2911 }
2912 self.radius = style.radius;
2913 let mut borders = style;
2914 borders.background = Color::TRANSPARENT;
2915 borders.radius = 0.0;
2916 self.borders = borders;
2917 self
2918 }
2919
2920 pub fn style(self, style: BoxStyle) -> Self {
2921 self.box_style(style)
2922 }
2923
2924 pub fn padding(mut self, padding: impl Into<Edges>) -> Self {
2925 self.style = self.style.padding(padding);
2926 self
2927 }
2928
2929 pub fn pad(self, padding: impl Into<Edges>) -> Self {
2930 self.padding(padding)
2931 }
2932
2933 pub fn padding_xy(mut self, x: f32, y: f32) -> Self {
2934 self.style = self.style.padding_xy(x, y);
2935 self
2936 }
2937
2938 pub fn padding_x(mut self, x: f32) -> Self {
2939 self.style = self.style.padding_x(x);
2940 self
2941 }
2942
2943 pub fn padding_y(mut self, y: f32) -> Self {
2944 self.style = self.style.padding_y(y);
2945 self
2946 }
2947
2948 pub fn padding_left(mut self, v: f32) -> Self {
2949 self.style = self.style.padding_left(v);
2950 self
2951 }
2952
2953 pub fn padding_right(mut self, v: f32) -> Self {
2954 self.style = self.style.padding_right(v);
2955 self
2956 }
2957
2958 pub fn padding_top(mut self, v: f32) -> Self {
2959 self.style = self.style.padding_top(v);
2960 self
2961 }
2962
2963 pub fn padding_bottom(mut self, v: f32) -> Self {
2964 self.style = self.style.padding_bottom(v);
2965 self
2966 }
2967
2968 pub fn width(mut self, width: impl Into<Length>) -> Self {
2969 self.style = self.style.width(width.into());
2970 self
2971 }
2972
2973 pub fn height(mut self, height: impl Into<Length>) -> Self {
2974 self.style = self.style.height(height.into());
2975 self
2976 }
2977
2978 pub fn size(mut self, width: impl Into<Length>, height: impl Into<Length>) -> Self {
2979 self.style = self.style.width(width.into()).height(height.into());
2980 self
2981 }
2982
2983 pub fn square(mut self, side: impl Into<Length>) -> Self {
2984 let side = side.into();
2985 self.style = self.style.width(side).height(side);
2986 self
2987 }
2988
2989 pub fn min_width(mut self, v: f32) -> Self {
2990 self.style = self.style.min_width(v);
2991 self
2992 }
2993
2994 pub fn max_width(mut self, v: f32) -> Self {
2995 self.style = self.style.max_width(v);
2996 self
2997 }
2998
2999 pub fn min_height(mut self, v: f32) -> Self {
3000 self.style = self.style.min_height(v);
3001 self
3002 }
3003
3004 pub fn max_height(mut self, v: f32) -> Self {
3005 self.style = self.style.max_height(v);
3006 self
3007 }
3008
3009 pub fn overflow(mut self, overflow: Overflow) -> Self {
3010 self.style = self.style.overflow(overflow);
3011 self
3012 }
3013
3014 pub fn flex(mut self, weight: f32) -> Self {
3015 self.style = self.style.flex(weight);
3016 self
3017 }
3018
3019 pub fn expand(self) -> Self {
3020 self.flex(1.0)
3021 }
3022
3023 pub fn fill_width(mut self) -> Self {
3024 self.style = self.style.width(Length::Fill(1.0));
3025 self
3026 }
3027
3028 pub fn fill_height(mut self) -> Self {
3029 self.style = self.style.height(Length::Fill(1.0));
3030 self
3031 }
3032
3033 pub fn fill_size(self) -> Self {
3034 self.fill_width().fill_height()
3035 }
3036}
3037
3038impl_style_extras!(Panel);
3039
3040impl View for Panel {
3041 fn body(&self) -> impl View + 'static {
3042 Unit
3043 }
3044 fn is_leaf(&self) -> bool {
3045 true
3046 }
3047 fn layout_style(&self) -> LayoutStyle {
3048 self.style
3049 }
3050 fn paint_self(&self, ctx: &mut PaintCtx) {
3051 let theme = ctx.theme();
3052 let color = self.color.unwrap_or(theme.surface);
3053 let radius = if self.radius > 0.0 {
3054 self.radius
3055 } else {
3056 theme.radius
3057 };
3058 let p = self.style.padding;
3059 let rect = ctx.rect;
3060 let quad = Rect::from_xywh(
3061 rect.left() + p.left,
3062 rect.top() + p.top,
3063 (rect.size.width - p.horizontal_sum()).max(0.0),
3064 (rect.size.height - p.vertical_sum()).max(0.0),
3065 );
3066
3067 let mut deco = self.borders;
3068 deco.background = color;
3069 deco.radius = radius;
3070 ctx.paint_box_in(deco, quad);
3071 }
3072}
3073
3074#[derive(Clone, Copy, Debug)]
3075pub struct Spacer {
3076 style: LayoutStyle,
3077}
3078
3079impl Spacer {
3080 pub fn flex(weight: f32) -> Self {
3081 let w = if weight.is_finite() {
3082 weight.max(0.0)
3083 } else {
3084 0.0
3085 };
3086 Self {
3087 style: LayoutStyle {
3088 width: Length::Fill(w),
3089 height: Length::Fit,
3090 ..LayoutStyle::default()
3091 },
3092 }
3093 }
3094
3095 pub fn vertical(weight: f32) -> Self {
3096 let w = if weight.is_finite() {
3097 weight.max(0.0)
3098 } else {
3099 0.0
3100 };
3101 Self {
3102 style: LayoutStyle {
3103 width: Length::Fit,
3104 height: Length::Fill(w),
3105 ..LayoutStyle::default()
3106 },
3107 }
3108 }
3109
3110 pub fn fixed(size: f32) -> Self {
3111 let s = if size.is_finite() { size.max(0.0) } else { 0.0 };
3112 Self {
3113 style: LayoutStyle {
3114 width: Length::Px(s),
3115 height: Length::Px(s),
3116 ..LayoutStyle::default()
3117 },
3118 }
3119 }
3120
3121 pub fn fixed_width(w: f32) -> Self {
3122 let w = if w.is_finite() { w.max(0.0) } else { 0.0 };
3123 Self {
3124 style: LayoutStyle {
3125 width: Length::Px(w),
3126 height: Length::Px(0.0),
3127 ..LayoutStyle::default()
3128 },
3129 }
3130 }
3131
3132 pub fn fixed_height(h: f32) -> Self {
3133 let h = if h.is_finite() { h.max(0.0) } else { 0.0 };
3134 Self {
3135 style: LayoutStyle {
3136 width: Length::Px(0.0),
3137 height: Length::Px(h),
3138 ..LayoutStyle::default()
3139 },
3140 }
3141 }
3142
3143 pub fn width(mut self, width: impl Into<Length>) -> Self {
3144 self.style = self.style.width(width.into());
3145 self
3146 }
3147
3148 pub fn height(mut self, height: impl Into<Length>) -> Self {
3149 self.style = self.style.height(height.into());
3150 self
3151 }
3152
3153 pub fn min_width(mut self, v: f32) -> Self {
3154 self.style = self.style.min_width(v);
3155 self
3156 }
3157
3158 pub fn max_width(mut self, v: f32) -> Self {
3159 self.style = self.style.max_width(v);
3160 self
3161 }
3162
3163 pub fn min_height(mut self, v: f32) -> Self {
3164 self.style = self.style.min_height(v);
3165 self
3166 }
3167
3168 pub fn max_height(mut self, v: f32) -> Self {
3169 self.style = self.style.max_height(v);
3170 self
3171 }
3172
3173 pub fn expand(mut self) -> Self {
3174 self.style = self.style.flex(1.0);
3175 self
3176 }
3177}
3178
3179impl Default for Spacer {
3180 fn default() -> Self {
3181 Self::flex(1.0)
3182 }
3183}
3184
3185impl_style_extras!(Spacer);
3186
3187impl_child_helpers!(Fragment);
3188impl_child_helpers!(FocusScope);
3189impl_child_helpers!(Row);
3190impl_child_helpers!(Column);
3191impl_child_helpers!(Stack);
3192impl_child_helpers!(Grid);
3193impl_child_helpers!(Wrap);
3194
3195impl View for Spacer {
3196 fn body(&self) -> impl View + 'static {
3197 Unit
3198 }
3199 fn is_leaf(&self) -> bool {
3200 true
3201 }
3202 fn layout_style(&self) -> LayoutStyle {
3203 self.style
3204 }
3205}
3206
3207fn aspect_contain(content: Size, ratio: f32) -> (Size, f32, f32) {
3208 let (w, h) = (content.width.max(0.0), content.height.max(0.0));
3209 if !(ratio.is_finite() && ratio > 0.0) || w <= 0.0 || h <= 0.0 {
3210 return (Size::new(w, h), 0.0, 0.0);
3211 }
3212 if !w.is_finite() || !h.is_finite() {
3213 return (Size::new(w, h), 0.0, 0.0);
3214 }
3215 let box_w = (h * ratio).min(w);
3216 let box_h = box_w / ratio;
3217 (
3218 Size::new(box_w, box_h),
3219 (w - box_w) * 0.5,
3220 (h - box_h) * 0.5,
3221 )
3222}
3223
3224fn sanitize_aspect_ratio(ratio: f32) -> f32 {
3225 if ratio.is_finite() && ratio > 0.0 {
3226 ratio
3227 } else {
3228 1.0
3229 }
3230}
3231
3232#[derive(Clone)]
3233pub struct AspectRatio {
3234 ratio: f32,
3235 child: Option<AnyView>,
3236 style: LayoutStyle,
3237 deco: BoxStyle,
3238 clip: bool,
3239}
3240
3241impl AspectRatio {
3242 pub fn new(ratio: f32) -> Self {
3243 Self {
3244 ratio: sanitize_aspect_ratio(ratio),
3245 child: None,
3246 style: LayoutStyle {
3247 width: Length::Fit,
3248 height: Length::Fit,
3249 ..LayoutStyle::default()
3250 },
3251 deco: BoxStyle::new(),
3252 clip: false,
3253 }
3254 }
3255
3256 pub fn ratio(mut self, ratio: f32) -> Self {
3257 self.ratio = sanitize_aspect_ratio(ratio);
3258 self
3259 }
3260
3261 pub fn aspect(self, ratio: f32) -> Self {
3262 self.ratio(ratio)
3263 }
3264
3265 pub fn child<V: View + 'static>(mut self, child: V) -> Self {
3266 debug_assert!(
3267 self.child.is_none(),
3268 "AspectRatio takes a single child - a second `.child()` would overwrite the first. Use Row/Column for many."
3269 );
3270 self.child = Some(AnyView::new(child));
3271 self
3272 }
3273
3274 pub fn child_if<V: View + 'static>(mut self, cond: bool, make: impl FnOnce() -> V) -> Self {
3275 if cond {
3276 self.child = Some(AnyView::new(make()));
3277 }
3278 self
3279 }
3280
3281 pub fn child_opt<V: View + 'static>(mut self, child: Option<V>) -> Self {
3282 if let Some(v) = child {
3283 self.child = Some(AnyView::new(v));
3284 }
3285 self
3286 }
3287
3288 pub fn background(mut self, color: Color) -> Self {
3289 self.deco = self.deco.background(color);
3290 self
3291 }
3292
3293 pub fn border(mut self, width: f32, color: Color) -> Self {
3294 self.deco = self.deco.border(width, color);
3295 self
3296 }
3297
3298 pub fn border_left(mut self, width: f32, color: Color) -> Self {
3299 self.deco = self.deco.border_left(width, color);
3300 self
3301 }
3302
3303 pub fn border_right(mut self, width: f32, color: Color) -> Self {
3304 self.deco = self.deco.border_right(width, color);
3305 self
3306 }
3307
3308 pub fn border_top(mut self, width: f32, color: Color) -> Self {
3309 self.deco = self.deco.border_top(width, color);
3310 self
3311 }
3312
3313 pub fn border_bottom(mut self, width: f32, color: Color) -> Self {
3314 self.deco = self.deco.border_bottom(width, color);
3315 self
3316 }
3317
3318 pub fn border_x(mut self, width: f32, color: Color) -> Self {
3319 self.deco = self.deco.border_x(width, color);
3320 self
3321 }
3322
3323 pub fn border_y(mut self, width: f32, color: Color) -> Self {
3324 self.deco = self.deco.border_y(width, color);
3325 self
3326 }
3327
3328 pub fn box_style(mut self, style: BoxStyle) -> Self {
3329 self.deco = style;
3330 self
3331 }
3332
3333 pub fn style(self, style: BoxStyle) -> Self {
3334 self.box_style(style)
3335 }
3336
3337 pub fn radius(mut self, radius: f32) -> Self {
3338 self.deco = self.deco.radius(radius);
3339 self
3340 }
3341
3342 pub fn padding(mut self, padding: impl Into<Edges>) -> Self {
3343 self.style = self.style.padding(padding);
3344 self
3345 }
3346
3347 pub fn pad(self, padding: impl Into<Edges>) -> Self {
3348 self.padding(padding)
3349 }
3350
3351 pub fn padding_xy(mut self, x: f32, y: f32) -> Self {
3352 self.style = self.style.padding_xy(x, y);
3353 self
3354 }
3355
3356 pub fn padding_x(mut self, x: f32) -> Self {
3357 self.style = self.style.padding_x(x);
3358 self
3359 }
3360
3361 pub fn padding_y(mut self, y: f32) -> Self {
3362 self.style = self.style.padding_y(y);
3363 self
3364 }
3365
3366 pub fn padding_left(mut self, v: f32) -> Self {
3367 self.style = self.style.padding_left(v);
3368 self
3369 }
3370
3371 pub fn padding_right(mut self, v: f32) -> Self {
3372 self.style = self.style.padding_right(v);
3373 self
3374 }
3375
3376 pub fn padding_top(mut self, v: f32) -> Self {
3377 self.style = self.style.padding_top(v);
3378 self
3379 }
3380
3381 pub fn padding_bottom(mut self, v: f32) -> Self {
3382 self.style = self.style.padding_bottom(v);
3383 self
3384 }
3385
3386 pub fn width(mut self, width: impl Into<Length>) -> Self {
3387 self.style = self.style.width(width.into());
3388 self
3389 }
3390
3391 pub fn height(mut self, height: impl Into<Length>) -> Self {
3392 self.style = self.style.height(height.into());
3393 self
3394 }
3395
3396 pub fn size(mut self, width: impl Into<Length>, height: impl Into<Length>) -> Self {
3397 self.style = self.style.width(width.into()).height(height.into());
3398 self
3399 }
3400
3401 pub fn square(mut self, side: impl Into<Length>) -> Self {
3402 let side = side.into();
3403 self.style = self.style.width(side).height(side);
3404 self
3405 }
3406
3407 pub fn min_width(mut self, v: f32) -> Self {
3408 self.style = self.style.min_width(v);
3409 self
3410 }
3411
3412 pub fn max_width(mut self, v: f32) -> Self {
3413 self.style = self.style.max_width(v);
3414 self
3415 }
3416
3417 pub fn min_height(mut self, v: f32) -> Self {
3418 self.style = self.style.min_height(v);
3419 self
3420 }
3421
3422 pub fn max_height(mut self, v: f32) -> Self {
3423 self.style = self.style.max_height(v);
3424 self
3425 }
3426
3427 pub fn overflow(mut self, overflow: Overflow) -> Self {
3428 self.style = self.style.overflow(overflow);
3429 self
3430 }
3431
3432 pub fn margin(mut self, margin: impl Into<Edges>) -> Self {
3433 self.style = self.style.margin(margin);
3434 self
3435 }
3436
3437 pub fn margin_xy(mut self, x: f32, y: f32) -> Self {
3438 self.style = self.style.margin_xy(x, y);
3439 self
3440 }
3441
3442 pub fn margin_x(mut self, x: f32) -> Self {
3443 self.style = self.style.margin_x(x);
3444 self
3445 }
3446
3447 pub fn margin_y(mut self, y: f32) -> Self {
3448 self.style = self.style.margin_y(y);
3449 self
3450 }
3451
3452 pub fn margin_left(mut self, v: f32) -> Self {
3453 self.style = self.style.margin_left(v);
3454 self
3455 }
3456
3457 pub fn margin_right(mut self, v: f32) -> Self {
3458 self.style = self.style.margin_right(v);
3459 self
3460 }
3461
3462 pub fn margin_top(mut self, v: f32) -> Self {
3463 self.style = self.style.margin_top(v);
3464 self
3465 }
3466
3467 pub fn margin_bottom(mut self, v: f32) -> Self {
3468 self.style = self.style.margin_bottom(v);
3469 self
3470 }
3471
3472 pub fn flex(mut self, weight: f32) -> Self {
3473 self.style = self.style.flex(weight);
3474 self
3475 }
3476
3477 pub fn flex_shrink(mut self, shrink: f32) -> Self {
3478 self.style = self.style.flex_shrink(shrink);
3479 self
3480 }
3481
3482 pub fn flex_basis(mut self, basis: Option<Length>) -> Self {
3483 self.style = self.style.flex_basis(basis);
3484 self
3485 }
3486
3487 pub fn align_self(mut self, align: Option<Align>) -> Self {
3488 self.style = self.style.align_self(align);
3489 self
3490 }
3491
3492 pub fn position(mut self, position: Position) -> Self {
3493 self.style = self.style.position(position);
3494 self
3495 }
3496
3497 pub fn absolute(mut self) -> Self {
3498 self.style = self.style.absolute();
3499 self
3500 }
3501
3502 pub fn absolute_at(mut self, left: f32, top: f32) -> Self {
3503 self.style = self.style.absolute_at(left, top);
3504 self
3505 }
3506
3507 pub fn absolute_inset(mut self, inset: Inset) -> Self {
3508 self.style = self.style.absolute_inset(inset);
3509 self
3510 }
3511
3512 pub fn expand(self) -> Self {
3513 self.flex(1.0)
3514 }
3515
3516 pub fn fill_width(mut self) -> Self {
3517 self.style = self.style.width(Length::Fill(1.0));
3518 self
3519 }
3520
3521 pub fn fill_height(mut self) -> Self {
3522 self.style = self.style.height(Length::Fill(1.0));
3523 self
3524 }
3525
3526 pub fn fill_size(self) -> Self {
3527 self.fill_width().fill_height()
3528 }
3529
3530 pub fn fit(mut self) -> Self {
3531 self.style = self.style.fit();
3532 self
3533 }
3534
3535 pub fn hit_testable(mut self, on: bool) -> Self {
3536 self.style = self.style.hit_testable(on);
3537 self
3538 }
3539
3540 pub fn clip(mut self, clip: bool) -> Self {
3541 self.clip = clip;
3542 self
3543 }
3544
3545 pub fn clip_children(self) -> Self {
3546 self.clip(true)
3547 }
3548}
3549
3550impl View for AspectRatio {
3551 fn body(&self) -> impl View + 'static {
3552 Unit
3553 }
3554 fn children_override(&self) -> Option<Vec<AnyView>> {
3555 self.child.clone().map(|c| vec![c])
3556 }
3557 fn clip_self(&self) -> bool {
3558 self.clip
3559 }
3560 fn clip_radius(&self) -> f32 {
3561 if self.clip { self.deco.radius } else { 0.0 }
3562 }
3563 fn layout_style(&self) -> LayoutStyle {
3564 let mut style = self.style;
3565 style.aspect_ratio = Some(self.ratio);
3566 style
3567 }
3568 fn arrange_override(
3569 &self,
3570 rt: &Runtime,
3571 el: ElementId,
3572 rect: Rect,
3573 ctx: &mut LayoutCtx,
3574 ) -> bool {
3575 let children = rt.children(el);
3576 let Some(&child) = children.first() else {
3577 return true;
3578 };
3579
3580 if matches!(self.style.width, Length::Fit) || matches!(self.style.height, Length::Fit) {
3581 return false;
3582 }
3583 let pad = self.style.padding;
3584 let content = Rect::from_xywh(
3585 rect.left() + pad.left,
3586 rect.top() + pad.top,
3587 (rect.size.width - pad.horizontal_sum()).max(0.0),
3588 (rect.size.height - pad.vertical_sum()).max(0.0),
3589 );
3590 if !content.size.width.is_finite() || !content.size.height.is_finite() {
3591 return false;
3592 }
3593 let (boxed, dx, dy) = aspect_contain(content.size, self.ratio);
3594 let cs = rt.child_layout_style(child);
3595 rt.arrange_node(
3596 child,
3597 Rect::from_xywh(
3598 content.left() + dx + cs.margin.left,
3599 content.top() + dy + cs.margin.top,
3600 (boxed.width - cs.margin.horizontal_sum()).max(0.0),
3601 (boxed.height - cs.margin.vertical_sum()).max(0.0),
3602 ),
3603 ctx,
3604 );
3605 true
3606 }
3607 fn paint_self(&self, ctx: &mut PaintCtx) {
3608 ctx.paint_box(self.deco);
3609 }
3610}
3611
3612impl crate::styleable::Styleable for AspectRatio {
3613 fn fill_width(mut self) -> Self {
3614 self.style = self.style.width(Length::Fill(1.0));
3615 self
3616 }
3617 fn fill_height(mut self) -> Self {
3618 self.style = self.style.height(Length::Fill(1.0));
3619 self
3620 }
3621 fn fit(mut self) -> Self {
3622 self.style = self.style.fit();
3623 self
3624 }
3625 fn hit_testable(mut self, on: bool) -> Self {
3626 self.style = self.style.hit_testable(on);
3627 self
3628 }
3629 fn padding(mut self, padding: impl Into<Edges>) -> Self {
3630 self.style = self.style.padding(padding);
3631 self
3632 }
3633}
3634
3635impl crate::styleable::Decoratable for AspectRatio {
3636 fn background(mut self, color: Color) -> Self {
3637 self.deco = self.deco.background(color);
3638 self
3639 }
3640 fn border(mut self, width: f32, color: Color) -> Self {
3641 self.deco = self.deco.border(width, color);
3642 self
3643 }
3644 fn radius(mut self, radius: f32) -> Self {
3645 self.deco = self.deco.radius(radius);
3646 self
3647 }
3648 fn box_style(mut self, style: BoxStyle) -> Self {
3649 self.deco = style;
3650 self
3651 }
3652}
3653
3654impl crate::styleable::Styleable for Row {
3655 fn fill_width(mut self) -> Self {
3656 self.0.style = self.0.style.width(Length::Fill(1.0));
3657 self
3658 }
3659 fn fill_height(mut self) -> Self {
3660 self.0.style = self.0.style.height(Length::Fill(1.0));
3661 self
3662 }
3663 fn fit(mut self) -> Self {
3664 self.0.style = self.0.style.fit();
3665 self
3666 }
3667 fn hit_testable(mut self, on: bool) -> Self {
3668 self.0.style = self.0.style.hit_testable(on);
3669 self
3670 }
3671 fn padding(mut self, padding: impl Into<Edges>) -> Self {
3672 self.0.style = self.0.style.padding(padding);
3673 self
3674 }
3675}
3676
3677impl crate::styleable::Decoratable for Row {
3678 fn background(mut self, color: Color) -> Self {
3679 self.0.deco = self.0.deco.background(color);
3680 self
3681 }
3682 fn border(mut self, width: f32, color: Color) -> Self {
3683 self.0.deco = self.0.deco.border(width, color);
3684 self
3685 }
3686 fn radius(mut self, radius: f32) -> Self {
3687 self.0.deco = self.0.deco.radius(radius);
3688 self
3689 }
3690 fn box_style(mut self, style: BoxStyle) -> Self {
3691 self.0.deco = style;
3692 self
3693 }
3694}
3695
3696impl crate::styleable::Styleable for Column {
3697 fn fill_width(mut self) -> Self {
3698 self.0.style = self.0.style.width(Length::Fill(1.0));
3699 self
3700 }
3701 fn fill_height(mut self) -> Self {
3702 self.0.style = self.0.style.height(Length::Fill(1.0));
3703 self
3704 }
3705 fn fit(mut self) -> Self {
3706 self.0.style = self.0.style.fit();
3707 self
3708 }
3709 fn hit_testable(mut self, on: bool) -> Self {
3710 self.0.style = self.0.style.hit_testable(on);
3711 self
3712 }
3713 fn padding(mut self, padding: impl Into<Edges>) -> Self {
3714 self.0.style = self.0.style.padding(padding);
3715 self
3716 }
3717}
3718
3719impl crate::styleable::Decoratable for Column {
3720 fn background(mut self, color: Color) -> Self {
3721 self.0.deco = self.0.deco.background(color);
3722 self
3723 }
3724 fn border(mut self, width: f32, color: Color) -> Self {
3725 self.0.deco = self.0.deco.border(width, color);
3726 self
3727 }
3728 fn radius(mut self, radius: f32) -> Self {
3729 self.0.deco = self.0.deco.radius(radius);
3730 self
3731 }
3732 fn box_style(mut self, style: BoxStyle) -> Self {
3733 self.0.deco = style;
3734 self
3735 }
3736}
3737
3738impl crate::styleable::Styleable for Stack {
3739 fn fill_width(mut self) -> Self {
3740 self.style = self.style.width(Length::Fill(1.0));
3741 self
3742 }
3743 fn fill_height(mut self) -> Self {
3744 self.style = self.style.height(Length::Fill(1.0));
3745 self
3746 }
3747 fn fit(mut self) -> Self {
3748 self.style = self.style.fit();
3749 self
3750 }
3751 fn hit_testable(mut self, on: bool) -> Self {
3752 self.style = self.style.hit_testable(on);
3753 self
3754 }
3755 fn padding(mut self, padding: impl Into<Edges>) -> Self {
3756 self.style = self.style.padding(padding);
3757 self
3758 }
3759}
3760
3761impl crate::styleable::Decoratable for Stack {
3762 fn background(mut self, color: Color) -> Self {
3763 self.deco = self.deco.background(color);
3764 self
3765 }
3766 fn border(mut self, width: f32, color: Color) -> Self {
3767 self.deco = self.deco.border(width, color);
3768 self
3769 }
3770 fn radius(mut self, radius: f32) -> Self {
3771 self.deco = self.deco.radius(radius);
3772 self
3773 }
3774 fn box_style(mut self, style: BoxStyle) -> Self {
3775 self.deco = style;
3776 self
3777 }
3778}
3779
3780#[cfg(test)]
3781mod aspect_ratio_tests {
3782 use super::*;
3783
3784 #[test]
3785 fn invalid_ratio_falls_back_to_square() {
3786 for bad in [0.0, -2.0, f32::NAN, f32::INFINITY, f32::NEG_INFINITY] {
3787 let v = AspectRatio::new(bad);
3788 assert_eq!(v.layout_style().aspect_ratio, Some(1.0), "ratio {bad}");
3789 let v = AspectRatio::new(2.0).ratio(bad);
3790 assert_eq!(v.layout_style().aspect_ratio, Some(1.0), "ratio {bad}");
3791 }
3792 }
3793
3794 #[test]
3795 fn layout_style_carries_ratio() {
3796 let v = AspectRatio::new(16.0 / 9.0).width(320.0);
3797 let style = v.layout_style();
3798 assert_eq!(style.aspect_ratio, Some(16.0 / 9.0));
3799 assert_eq!(style.width, Length::Px(320.0));
3800 }
3801
3802 #[test]
3803 fn contain_fits_wide_content() {
3804 let (boxed, dx, dy) = aspect_contain(Size::new(800.0, 600.0), 16.0 / 9.0);
3805 assert!((boxed.width - 800.0).abs() < 1e-3, "{boxed:?}");
3806 assert!((boxed.height - 450.0).abs() < 1e-3, "{boxed:?}");
3807 assert!(dx.abs() < 1e-3, "{dx}");
3808 assert!((dy - 75.0).abs() < 1e-3, "{dy}");
3809 }
3810
3811 #[test]
3812 fn contain_fits_tall_content() {
3813 let (boxed, dx, dy) = aspect_contain(Size::new(100.0, 200.0), 2.0);
3814 assert!((boxed.width - 100.0).abs() < 1e-3, "{boxed:?}");
3815 assert!((boxed.height - 50.0).abs() < 1e-3, "{boxed:?}");
3816 assert!(dx.abs() < 1e-3, "{dx}");
3817 assert!((dy - 75.0).abs() < 1e-3, "{dy}");
3818 }
3819
3820 #[test]
3821 fn contain_matching_ratio_is_identity() {
3822 let (boxed, dx, dy) = aspect_contain(Size::new(200.0, 100.0), 2.0);
3823 assert!((boxed.width - 200.0).abs() < 1e-3, "{boxed:?}");
3824 assert!((boxed.height - 100.0).abs() < 1e-3, "{boxed:?}");
3825 assert!(dx.abs() < 1e-3);
3826 assert!(dy.abs() < 1e-3);
3827 }
3828
3829 #[test]
3830 fn contain_degenerate_returns_content() {
3831 let (boxed, dx, dy) = aspect_contain(Size::ZERO, 16.0 / 9.0);
3832 assert_eq!(boxed, Size::ZERO);
3833 assert_eq!((dx, dy), (0.0, 0.0));
3834 let (boxed, dx, dy) = aspect_contain(Size::new(100.0, 100.0), 0.0);
3835 assert_eq!(boxed, Size::new(100.0, 100.0));
3836 assert_eq!((dx, dy), (0.0, 0.0));
3837 }
3838}