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