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