1use crate::UiHost;
2use crate::elements::{ElementContext, GlobalElementId};
3use crate::overlay_placement::{Align, AnchoredPanelLayout, AnchoredPanelOptions, Side};
4use fret_core::scene::{BlendMode, CustomEffectPyramidRequestV1, Mask, Paint};
5use fret_core::{
6 AttributedText, CaretAffinity, Color, Corners, Edges, EffectChain, EffectMode, EffectQuality,
7 ImageId, KeyCode, NodeId, Px, Rect, RenderTargetId, SemanticsLive, SemanticsOrientation,
8 SemanticsRole, Size, SvgFit, TextAlign, TextOverflow, TextStyle, TextStyleRefinement, TextWrap,
9 UvRect, ViewportFit,
10};
11use fret_runtime::{CommandId, Model};
12use std::sync::Arc;
13
14use crate::{ResizablePanelGroupStyle, SvgSource, TextAreaStyle, TextInputStyle};
15
16#[derive(Debug)]
24pub struct AnyElement {
25 pub id: GlobalElementId,
26 pub kind: ElementKind,
27 pub children: Vec<AnyElement>,
28 pub inherited_foreground: Option<Color>,
34 pub inherited_text_style: Option<TextStyleRefinement>,
39 pub semantics_decoration: Option<SemanticsDecoration>,
41 pub key_context: Option<Arc<str>>,
43}
44
45impl AnyElement {
46 pub fn new(id: GlobalElementId, kind: ElementKind, children: Vec<AnyElement>) -> Self {
47 Self {
48 id,
49 kind,
50 children,
51 inherited_foreground: None,
52 inherited_text_style: None,
53 semantics_decoration: None,
54 key_context: None,
55 }
56 }
57
58 pub fn inherit_foreground(mut self, foreground: Color) -> Self {
63 self.inherited_foreground = Some(foreground);
64 self
65 }
66
67 pub fn inherit_text_style(mut self, refinement: TextStyleRefinement) -> Self {
72 match self.inherited_text_style.as_mut() {
73 Some(existing) => existing.merge(&refinement),
74 None => self.inherited_text_style = Some(refinement),
75 }
76 self
77 }
78
79 pub fn attach_semantics(mut self, decoration: SemanticsDecoration) -> Self {
98 self.semantics_decoration = Some(match self.semantics_decoration.take() {
99 Some(existing) => existing.merge(decoration),
100 None => decoration,
101 });
102 self
103 }
104
105 pub fn a11y(self, decoration: SemanticsDecoration) -> Self {
109 self.attach_semantics(decoration)
110 }
111
112 pub fn a11y_role(self, role: SemanticsRole) -> Self {
114 self.a11y(SemanticsDecoration::default().role(role))
115 }
116
117 pub fn a11y_label(self, label: impl Into<Arc<str>>) -> Self {
119 self.a11y(SemanticsDecoration::default().label(label))
120 }
121
122 pub fn test_id(self, test_id: impl Into<Arc<str>>) -> Self {
130 self.a11y(SemanticsDecoration::default().test_id(test_id))
131 }
132
133 pub fn a11y_value(self, value: impl Into<Arc<str>>) -> Self {
135 self.a11y(SemanticsDecoration::default().value(value))
136 }
137
138 pub fn a11y_disabled(self, disabled: bool) -> Self {
140 self.a11y(SemanticsDecoration::default().disabled(disabled))
141 }
142
143 pub fn a11y_selected(self, selected: bool) -> Self {
145 self.a11y(SemanticsDecoration::default().selected(selected))
146 }
147
148 pub fn a11y_expanded(self, expanded: bool) -> Self {
150 self.a11y(SemanticsDecoration::default().expanded(expanded))
151 }
152
153 pub fn a11y_checked(self, checked: Option<bool>) -> Self {
155 self.a11y(SemanticsDecoration::default().checked(checked))
156 }
157
158 pub fn key_context(mut self, key_context: impl Into<Arc<str>>) -> Self {
162 self.key_context = Some(key_context.into());
163 self
164 }
165}
166
167#[allow(clippy::large_enum_variant)]
168#[derive(Debug, Clone)]
169pub enum ElementKind {
170 Container(ContainerProps),
171 Semantics(SemanticsProps),
172 SemanticFlex(SemanticFlexProps),
178 FocusScope(FocusScopeProps),
179 LayoutQueryRegion(LayoutQueryRegionProps),
185 InteractivityGate(InteractivityGateProps),
192 HitTestGate(HitTestGateProps),
202 FocusTraversalGate(FocusTraversalGateProps),
211 ForegroundScope(ForegroundScopeProps),
220 Opacity(OpacityProps),
221 EffectLayer(EffectLayerProps),
223 BackdropSourceGroup(BackdropSourceGroupProps),
225 MaskLayer(MaskLayerProps),
230 CompositeGroup(CompositeGroupProps),
235 ViewCache(ViewCacheProps),
240 VisualTransform(VisualTransformProps),
241 RenderTransform(RenderTransformProps),
242 FractionalRenderTransform(FractionalRenderTransformProps),
243 Anchored(AnchoredProps),
244 Pressable(PressableProps),
245 PointerRegion(PointerRegionProps),
246 TextInputRegion(TextInputRegionProps),
253 InternalDragRegion(InternalDragRegionProps),
258 ExternalDragRegion(ExternalDragRegionProps),
263 RovingFlex(RovingFlexProps),
264 Stack(StackProps),
265 Column(ColumnProps),
266 Row(RowProps),
267 Spacer(SpacerProps),
268 Text(TextProps),
269 StyledText(StyledTextProps),
270 SelectableText(SelectableTextProps),
271 TextInput(TextInputProps),
272 TextArea(TextAreaProps),
273 ResizablePanelGroup(ResizablePanelGroupProps),
274 VirtualList(VirtualListProps),
275 Flex(FlexProps),
276 Grid(GridProps),
277 Image(ImageProps),
278 Canvas(CanvasProps),
280 #[cfg(feature = "unstable-retained-bridge")]
282 RetainedSubtree(crate::retained_bridge::RetainedSubtreeProps),
283 ViewportSurface(ViewportSurfaceProps),
285 SvgIcon(SvgIconProps),
286 Spinner(SpinnerProps),
287 HoverRegion(HoverRegionProps),
288 WheelRegion(WheelRegionProps),
293 Scroll(ScrollProps),
294 Scrollbar(ScrollbarProps),
295}
296
297#[derive(Debug, Clone, Copy)]
298pub struct SemanticFlexProps {
299 pub role: SemanticsRole,
300 pub flex: FlexProps,
301}
302
303#[derive(Debug, Default, Clone)]
305pub struct PointerRegionState {
306 pub last_down: Option<crate::action::PointerDownCx>,
307}
308
309#[derive(Debug, Clone, Copy)]
313pub struct PointerRegionProps {
314 pub layout: LayoutStyle,
315 pub enabled: bool,
316 pub capture_phase_pointer_moves: bool,
326}
327
328#[derive(Debug, Clone)]
330pub struct TextInputRegionProps {
331 pub layout: LayoutStyle,
332 pub enabled: bool,
333 pub text_boundary_mode_override: Option<fret_runtime::TextBoundaryMode>,
334 pub ime_cursor_area: Option<fret_core::Rect>,
340 pub a11y_label: Option<Arc<str>>,
342 pub a11y_value: Option<Arc<str>>,
347 pub a11y_required: bool,
348 pub a11y_invalid: Option<fret_core::SemanticsInvalid>,
349 pub a11y_text_selection: Option<(u32, u32)>,
351 pub a11y_text_composition: Option<(u32, u32)>,
353 pub ime_surrounding_text: Option<fret_runtime::WindowImeSurroundingText>,
358}
359
360#[derive(Debug, Clone, Copy)]
364pub struct InternalDragRegionProps {
365 pub layout: LayoutStyle,
366 pub enabled: bool,
367}
368
369#[derive(Debug, Clone, Copy)]
373pub struct ExternalDragRegionProps {
374 pub layout: LayoutStyle,
375 pub enabled: bool,
376}
377
378impl Default for InternalDragRegionProps {
379 fn default() -> Self {
380 Self {
381 layout: LayoutStyle::default(),
382 enabled: true,
383 }
384 }
385}
386
387impl Default for ExternalDragRegionProps {
388 fn default() -> Self {
389 Self {
390 layout: LayoutStyle::default(),
391 enabled: true,
392 }
393 }
394}
395
396impl Default for PointerRegionProps {
397 fn default() -> Self {
398 Self {
399 layout: LayoutStyle::default(),
400 enabled: true,
401 capture_phase_pointer_moves: false,
402 }
403 }
404}
405
406impl Default for TextInputRegionProps {
407 fn default() -> Self {
408 Self {
409 layout: LayoutStyle::default(),
410 enabled: true,
411 text_boundary_mode_override: None,
412 ime_cursor_area: None,
413 a11y_label: None,
414 a11y_value: None,
415 a11y_required: false,
416 a11y_invalid: None,
417 a11y_text_selection: None,
418 a11y_text_composition: None,
419 ime_surrounding_text: None,
420 }
421 }
422}
423
424#[derive(Debug, Clone, Copy, Default, PartialEq)]
425pub struct LayoutStyle {
426 pub size: SizeStyle,
427 pub flex: FlexItemStyle,
428 pub overflow: Overflow,
429 pub margin: MarginEdges,
430 pub position: PositionStyle,
431 pub inset: InsetStyle,
432 pub aspect_ratio: Option<f32>,
433 pub grid: GridItemStyle,
434}
435
436#[derive(Debug, Clone, Copy, PartialEq)]
437pub enum MarginEdge {
438 Px(Px),
439 Fill,
440 Fraction(f32),
441 Auto,
442}
443
444impl Default for MarginEdge {
445 fn default() -> Self {
446 Self::Px(Px(0.0))
447 }
448}
449
450impl From<Px> for MarginEdge {
451 fn from(px: Px) -> Self {
452 Self::Px(px)
453 }
454}
455
456impl From<Option<Px>> for MarginEdge {
457 fn from(px: Option<Px>) -> Self {
458 match px {
459 Some(px) => Self::Px(px),
460 None => Self::Auto,
461 }
462 }
463}
464
465#[derive(Debug, Clone, Copy, Default, PartialEq)]
466pub struct MarginEdges {
467 pub top: MarginEdge,
468 pub right: MarginEdge,
469 pub bottom: MarginEdge,
470 pub left: MarginEdge,
471}
472
473impl MarginEdges {
474 pub fn all(edge: MarginEdge) -> Self {
475 Self {
476 top: edge,
477 right: edge,
478 bottom: edge,
479 left: edge,
480 }
481 }
482}
483
484#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
485pub enum Overflow {
486 #[default]
487 Visible,
488 Clip,
489}
490
491#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
492pub enum PositionStyle {
493 #[default]
495 Static,
496 Relative,
498 Absolute,
500}
501
502#[derive(Debug, Clone, Copy, Default, PartialEq)]
503pub struct InsetStyle {
504 pub top: InsetEdge,
505 pub right: InsetEdge,
506 pub bottom: InsetEdge,
507 pub left: InsetEdge,
508}
509
510#[derive(Debug, Clone, Copy, Default, PartialEq)]
511pub enum InsetEdge {
512 Px(Px),
513 Fill,
514 Fraction(f32),
515 #[default]
516 Auto,
517}
518
519impl From<Px> for InsetEdge {
520 fn from(px: Px) -> Self {
521 Self::Px(px)
522 }
523}
524
525impl From<Option<Px>> for InsetEdge {
526 fn from(px: Option<Px>) -> Self {
527 match px {
528 Some(px) => Self::Px(px),
529 None => Self::Auto,
530 }
531 }
532}
533
534#[derive(Debug, Clone, Copy, Default, PartialEq)]
535pub struct GridItemStyle {
536 pub column: GridLine,
537 pub row: GridLine,
538 pub align_self: Option<CrossAlign>,
539 pub justify_self: Option<CrossAlign>,
540}
541
542#[derive(Debug, Clone, Copy, Default, PartialEq)]
543pub struct GridLine {
544 pub start: Option<i16>,
545 pub span: Option<u16>,
546}
547
548#[derive(Debug, Clone, Copy, PartialEq)]
549pub struct SizeStyle {
550 pub width: Length,
551 pub height: Length,
552 pub min_width: Option<Length>,
557 pub min_height: Option<Length>,
559 pub max_width: Option<Length>,
561 pub max_height: Option<Length>,
563}
564
565impl Default for SizeStyle {
566 fn default() -> Self {
567 Self {
568 width: Length::Auto,
569 height: Length::Auto,
570 min_width: None,
571 min_height: None,
572 max_width: None,
573 max_height: None,
574 }
575 }
576}
577
578#[derive(Debug, Clone, Copy, PartialEq)]
579pub struct FlexItemStyle {
580 pub order: i32,
585 pub grow: f32,
586 pub shrink: f32,
587 pub basis: Length,
588 pub align_self: Option<CrossAlign>,
589}
590
591impl Default for FlexItemStyle {
592 fn default() -> Self {
593 Self {
594 order: 0,
595 grow: 0.0,
596 shrink: 1.0,
599 basis: Length::Auto,
600 align_self: None,
601 }
602 }
603}
604
605#[derive(Debug, Clone, Copy, Default, PartialEq)]
606pub enum Length {
607 #[default]
608 Auto,
609 Px(Px),
610 Fraction(f32),
615 Fill,
616}
617
618#[derive(Debug, Clone, Copy, PartialEq)]
625pub enum SpacingLength {
626 Px(Px),
627 Fraction(f32),
631 Fill,
633}
634
635impl Default for SpacingLength {
636 fn default() -> Self {
637 Self::Px(Px(0.0))
638 }
639}
640
641impl SpacingLength {
642 pub const fn px(px: Px) -> Self {
643 Self::Px(px)
644 }
645
646 pub const fn fraction(fraction: f32) -> Self {
647 Self::Fraction(fraction)
648 }
649
650 pub const fn fill() -> Self {
651 Self::Fill
652 }
653}
654
655impl From<Px> for SpacingLength {
656 fn from(value: Px) -> Self {
657 Self::Px(value)
658 }
659}
660
661#[derive(Debug, Clone, Copy, PartialEq)]
662pub struct SpacingEdges {
663 pub top: SpacingLength,
664 pub right: SpacingLength,
665 pub bottom: SpacingLength,
666 pub left: SpacingLength,
667}
668
669impl Default for SpacingEdges {
670 fn default() -> Self {
671 Self::all(SpacingLength::Px(Px(0.0)))
672 }
673}
674
675impl SpacingEdges {
676 pub const fn all(value: SpacingLength) -> Self {
677 Self {
678 top: value,
679 right: value,
680 bottom: value,
681 left: value,
682 }
683 }
684
685 pub const fn symmetric(horizontal: SpacingLength, vertical: SpacingLength) -> Self {
686 Self {
687 top: vertical,
688 right: horizontal,
689 bottom: vertical,
690 left: horizontal,
691 }
692 }
693}
694
695impl From<Edges> for SpacingEdges {
696 fn from(value: Edges) -> Self {
697 Self {
698 top: SpacingLength::Px(value.top),
699 right: SpacingLength::Px(value.right),
700 bottom: SpacingLength::Px(value.bottom),
701 left: SpacingLength::Px(value.left),
702 }
703 }
704}
705
706#[derive(Debug, Clone, Copy)]
712pub struct ContainerProps {
713 pub layout: LayoutStyle,
714 pub padding: SpacingEdges,
715 pub background: Option<Color>,
716 pub background_paint: Option<Paint>,
721 pub shadow: Option<ShadowStyle>,
722 pub border: Edges,
723 pub border_color: Option<Color>,
724 pub border_paint: Option<Paint>,
728 pub border_dash: Option<fret_core::scene::DashPatternV1>,
730 pub focus_ring: Option<RingStyle>,
732 pub focus_ring_always_paint: bool,
740 pub focus_border_color: Option<Color>,
745 pub focus_within: bool,
747 pub corner_radii: Corners,
748 pub snap_to_device_pixels: bool,
750}
751
752impl Default for ContainerProps {
753 fn default() -> Self {
754 Self {
755 layout: LayoutStyle::default(),
756 padding: SpacingEdges::all(SpacingLength::Px(Px(0.0))),
757 background: None,
758 background_paint: None,
759 shadow: None,
760 border: Edges::all(Px(0.0)),
761 border_color: None,
762 border_paint: None,
763 border_dash: None,
764 focus_ring: None,
765 focus_ring_always_paint: false,
766 focus_border_color: None,
767 focus_within: false,
768 corner_radii: Corners::all(Px(0.0)),
769 snap_to_device_pixels: false,
770 }
771 }
772}
773
774#[derive(Debug, Default, Clone)]
792pub struct SemanticsDecoration {
793 pub role: Option<SemanticsRole>,
794 pub label: Option<Arc<str>>,
795 pub role_description: Option<Arc<str>>,
797 pub test_id: Option<Arc<str>>,
801 pub value: Option<Arc<str>>,
802 pub disabled: Option<bool>,
803 pub read_only: Option<bool>,
804 pub required: Option<bool>,
805 pub invalid: Option<fret_core::SemanticsInvalid>,
806 pub hidden: Option<bool>,
807 pub visited: Option<bool>,
808 pub multiselectable: Option<bool>,
809 pub busy: Option<bool>,
810 pub live: Option<Option<SemanticsLive>>,
814 pub live_atomic: Option<bool>,
815 pub selected: Option<bool>,
816 pub expanded: Option<bool>,
817 pub checked: Option<Option<bool>>,
819 pub placeholder: Option<Arc<str>>,
820 pub url: Option<Arc<str>>,
821 pub level: Option<u32>,
823 pub orientation: Option<SemanticsOrientation>,
824 pub numeric_value: Option<f64>,
825 pub min_numeric_value: Option<f64>,
826 pub max_numeric_value: Option<f64>,
827 pub numeric_value_step: Option<f64>,
828 pub numeric_value_jump: Option<f64>,
829 pub scroll_x: Option<f64>,
830 pub scroll_x_min: Option<f64>,
831 pub scroll_x_max: Option<f64>,
832 pub scroll_y: Option<f64>,
833 pub scroll_y_min: Option<f64>,
834 pub scroll_y_max: Option<f64>,
835 pub active_descendant_element: Option<u64>,
837 pub labelled_by_element: Option<u64>,
839 pub described_by_element: Option<u64>,
841 pub controls_element: Option<u64>,
843 pub invokable: Option<bool>,
848}
849
850impl SemanticsDecoration {
851 pub fn merge(self, other: Self) -> Self {
853 Self {
854 role: other.role.or(self.role),
855 label: other.label.or(self.label),
856 role_description: other.role_description.or(self.role_description),
857 test_id: other.test_id.or(self.test_id),
858 value: other.value.or(self.value),
859 disabled: other.disabled.or(self.disabled),
860 read_only: other.read_only.or(self.read_only),
861 required: other.required.or(self.required),
862 invalid: other.invalid.or(self.invalid),
863 hidden: other.hidden.or(self.hidden),
864 visited: other.visited.or(self.visited),
865 multiselectable: other.multiselectable.or(self.multiselectable),
866 busy: other.busy.or(self.busy),
867 live: other.live.or(self.live),
868 live_atomic: other.live_atomic.or(self.live_atomic),
869 selected: other.selected.or(self.selected),
870 expanded: other.expanded.or(self.expanded),
871 checked: other.checked.or(self.checked),
872 placeholder: other.placeholder.or(self.placeholder),
873 url: other.url.or(self.url),
874 level: other.level.or(self.level),
875 orientation: other.orientation.or(self.orientation),
876 numeric_value: other.numeric_value.or(self.numeric_value),
877 min_numeric_value: other.min_numeric_value.or(self.min_numeric_value),
878 max_numeric_value: other.max_numeric_value.or(self.max_numeric_value),
879 numeric_value_step: other.numeric_value_step.or(self.numeric_value_step),
880 numeric_value_jump: other.numeric_value_jump.or(self.numeric_value_jump),
881 scroll_x: other.scroll_x.or(self.scroll_x),
882 scroll_x_min: other.scroll_x_min.or(self.scroll_x_min),
883 scroll_x_max: other.scroll_x_max.or(self.scroll_x_max),
884 scroll_y: other.scroll_y.or(self.scroll_y),
885 scroll_y_min: other.scroll_y_min.or(self.scroll_y_min),
886 scroll_y_max: other.scroll_y_max.or(self.scroll_y_max),
887 active_descendant_element: other
888 .active_descendant_element
889 .or(self.active_descendant_element),
890 labelled_by_element: other.labelled_by_element.or(self.labelled_by_element),
891 described_by_element: other.described_by_element.or(self.described_by_element),
892 controls_element: other.controls_element.or(self.controls_element),
893 invokable: other.invokable.or(self.invokable),
894 }
895 }
896
897 pub fn role(mut self, role: SemanticsRole) -> Self {
898 self.role = Some(role);
899 self
900 }
901
902 pub fn label(mut self, label: impl Into<Arc<str>>) -> Self {
903 self.label = Some(label.into());
904 self
905 }
906
907 pub fn role_description(mut self, role_description: impl Into<Arc<str>>) -> Self {
908 self.role_description = Some(role_description.into());
909 self
910 }
911
912 pub fn test_id(mut self, test_id: impl Into<Arc<str>>) -> Self {
913 self.test_id = Some(test_id.into());
914 self
915 }
916
917 pub fn value(mut self, value: impl Into<Arc<str>>) -> Self {
918 self.value = Some(value.into());
919 self
920 }
921
922 pub fn disabled(mut self, disabled: bool) -> Self {
923 self.disabled = Some(disabled);
924 self
925 }
926
927 pub fn read_only(mut self, read_only: bool) -> Self {
928 self.read_only = Some(read_only);
929 self
930 }
931
932 pub fn required(mut self, required: bool) -> Self {
933 self.required = Some(required);
934 self
935 }
936
937 pub fn invalid(mut self, invalid: fret_core::SemanticsInvalid) -> Self {
938 self.invalid = Some(invalid);
939 self
940 }
941
942 pub fn hidden(mut self, hidden: bool) -> Self {
943 self.hidden = Some(hidden);
944 self
945 }
946
947 pub fn visited(mut self, visited: bool) -> Self {
948 self.visited = Some(visited);
949 self
950 }
951
952 pub fn multiselectable(mut self, multiselectable: bool) -> Self {
953 self.multiselectable = Some(multiselectable);
954 self
955 }
956
957 pub fn busy(mut self, busy: bool) -> Self {
958 self.busy = Some(busy);
959 self
960 }
961
962 pub fn live(mut self, live: Option<SemanticsLive>) -> Self {
963 self.live = Some(live);
964 self
965 }
966
967 pub fn live_atomic(mut self, live_atomic: bool) -> Self {
968 self.live_atomic = Some(live_atomic);
969 self
970 }
971
972 pub fn selected(mut self, selected: bool) -> Self {
973 self.selected = Some(selected);
974 self
975 }
976
977 pub fn expanded(mut self, expanded: bool) -> Self {
978 self.expanded = Some(expanded);
979 self
980 }
981
982 pub fn checked(mut self, checked: Option<bool>) -> Self {
983 self.checked = Some(checked);
984 self
985 }
986
987 pub fn placeholder(mut self, placeholder: impl Into<Arc<str>>) -> Self {
988 self.placeholder = Some(placeholder.into());
989 self
990 }
991
992 pub fn url(mut self, url: impl Into<Arc<str>>) -> Self {
993 self.url = Some(url.into());
994 self
995 }
996
997 pub fn level(mut self, level: u32) -> Self {
998 self.level = Some(level);
999 self
1000 }
1001
1002 pub fn orientation(mut self, orientation: SemanticsOrientation) -> Self {
1003 self.orientation = Some(orientation);
1004 self
1005 }
1006
1007 pub fn numeric_value(mut self, value: f64) -> Self {
1008 self.numeric_value = Some(value);
1009 self
1010 }
1011
1012 pub fn numeric_range(mut self, min: f64, max: f64) -> Self {
1013 self.min_numeric_value = Some(min);
1014 self.max_numeric_value = Some(max);
1015 self
1016 }
1017
1018 pub fn numeric_step(mut self, step: f64) -> Self {
1019 self.numeric_value_step = Some(step);
1020 self
1021 }
1022
1023 pub fn numeric_jump(mut self, jump: f64) -> Self {
1024 self.numeric_value_jump = Some(jump);
1025 self
1026 }
1027
1028 pub fn scroll_x(mut self, x: f64, min: f64, max: f64) -> Self {
1029 self.scroll_x = Some(x);
1030 self.scroll_x_min = Some(min);
1031 self.scroll_x_max = Some(max);
1032 self
1033 }
1034
1035 pub fn scroll_y(mut self, y: f64, min: f64, max: f64) -> Self {
1036 self.scroll_y = Some(y);
1037 self.scroll_y_min = Some(min);
1038 self.scroll_y_max = Some(max);
1039 self
1040 }
1041
1042 pub fn active_descendant_element(mut self, element: u64) -> Self {
1043 self.active_descendant_element = Some(element);
1044 self
1045 }
1046
1047 pub fn labelled_by_element(mut self, element: u64) -> Self {
1048 self.labelled_by_element = Some(element);
1049 self
1050 }
1051
1052 pub fn described_by_element(mut self, element: u64) -> Self {
1053 self.described_by_element = Some(element);
1054 self
1055 }
1056
1057 pub fn controls_element(mut self, element: u64) -> Self {
1058 self.controls_element = Some(element);
1059 self
1060 }
1061
1062 pub fn invokable(mut self, invokable: bool) -> Self {
1063 self.invokable = Some(invokable);
1064 self
1065 }
1066}
1067
1068#[derive(Debug, Clone)]
1077pub struct SemanticsProps {
1078 pub layout: LayoutStyle,
1079 pub role: SemanticsRole,
1080 pub label: Option<Arc<str>>,
1081 pub test_id: Option<Arc<str>>,
1085 pub value: Option<Arc<str>>,
1086 pub placeholder: Option<Arc<str>>,
1087 pub url: Option<Arc<str>>,
1088 pub level: Option<u32>,
1090 pub orientation: Option<SemanticsOrientation>,
1091 pub numeric_value: Option<f64>,
1092 pub min_numeric_value: Option<f64>,
1093 pub max_numeric_value: Option<f64>,
1094 pub numeric_value_step: Option<f64>,
1095 pub numeric_value_jump: Option<f64>,
1096 pub scroll_x: Option<f64>,
1097 pub scroll_x_min: Option<f64>,
1098 pub scroll_x_max: Option<f64>,
1099 pub scroll_y: Option<f64>,
1100 pub scroll_y_min: Option<f64>,
1101 pub scroll_y_max: Option<f64>,
1102 pub focusable: bool,
1107 pub value_editable: Option<bool>,
1115 pub disabled: bool,
1116 pub read_only: bool,
1117 pub required: bool,
1118 pub invalid: Option<fret_core::SemanticsInvalid>,
1119 pub hidden: bool,
1120 pub visited: bool,
1121 pub multiselectable: bool,
1122 pub busy: bool,
1123 pub live: Option<SemanticsLive>,
1124 pub live_atomic: bool,
1125 pub selected: bool,
1126 pub expanded: Option<bool>,
1127 pub checked: Option<bool>,
1128 pub active_descendant: Option<NodeId>,
1129 pub labelled_by_element: Option<u64>,
1135 pub described_by_element: Option<u64>,
1141 pub controls_element: Option<u64>,
1147}
1148
1149impl Default for SemanticsProps {
1150 fn default() -> Self {
1151 Self {
1152 layout: LayoutStyle::default(),
1153 role: SemanticsRole::Generic,
1154 label: None,
1155 test_id: None,
1156 value: None,
1157 placeholder: None,
1158 url: None,
1159 level: None,
1160 orientation: None,
1161 numeric_value: None,
1162 min_numeric_value: None,
1163 max_numeric_value: None,
1164 numeric_value_step: None,
1165 numeric_value_jump: None,
1166 scroll_x: None,
1167 scroll_x_min: None,
1168 scroll_x_max: None,
1169 scroll_y: None,
1170 scroll_y_min: None,
1171 scroll_y_max: None,
1172 focusable: false,
1173 value_editable: None,
1174 disabled: false,
1175 read_only: false,
1176 required: false,
1177 invalid: None,
1178 hidden: false,
1179 visited: false,
1180 multiselectable: false,
1181 busy: false,
1182 live: None,
1183 live_atomic: false,
1184 selected: false,
1185 expanded: None,
1186 checked: None,
1187 active_descendant: None,
1188 labelled_by_element: None,
1189 described_by_element: None,
1190 controls_element: None,
1191 }
1192 }
1193}
1194
1195#[derive(Debug, Default, Clone)]
1200pub struct LayoutQueryRegionProps {
1201 pub layout: LayoutStyle,
1202 pub name: Option<Arc<str>>,
1206}
1207
1208#[derive(Debug, Default, Clone, Copy)]
1214pub struct FocusScopeProps {
1215 pub layout: LayoutStyle,
1216 pub trap_focus: bool,
1217}
1218
1219#[derive(Debug, Clone, Copy)]
1227pub struct InteractivityGateProps {
1228 pub layout: LayoutStyle,
1229 pub present: bool,
1230 pub interactive: bool,
1231}
1232
1233impl Default for InteractivityGateProps {
1234 fn default() -> Self {
1235 Self {
1236 layout: LayoutStyle::default(),
1237 present: true,
1238 interactive: true,
1239 }
1240 }
1241}
1242
1243#[derive(Debug, Clone, Copy)]
1248pub struct HitTestGateProps {
1249 pub layout: LayoutStyle,
1250 pub hit_test: bool,
1251}
1252
1253impl Default for HitTestGateProps {
1254 fn default() -> Self {
1255 Self {
1256 layout: LayoutStyle::default(),
1257 hit_test: true,
1258 }
1259 }
1260}
1261
1262#[derive(Debug, Clone, Copy)]
1267pub struct FocusTraversalGateProps {
1268 pub layout: LayoutStyle,
1269 pub traverse: bool,
1270}
1271
1272impl Default for FocusTraversalGateProps {
1273 fn default() -> Self {
1274 Self {
1275 layout: LayoutStyle::default(),
1276 traverse: true,
1277 }
1278 }
1279}
1280
1281#[derive(Debug, Clone, Copy)]
1286pub struct OpacityProps {
1287 pub layout: LayoutStyle,
1288 pub opacity: f32,
1289}
1290
1291impl Default for OpacityProps {
1292 fn default() -> Self {
1293 Self {
1294 layout: LayoutStyle::default(),
1295 opacity: 1.0,
1296 }
1297 }
1298}
1299
1300#[derive(Debug, Clone, Copy, Default)]
1305pub struct ForegroundScopeProps {
1306 pub layout: LayoutStyle,
1307 pub foreground: Option<Color>,
1308}
1309
1310#[derive(Debug, Clone, Copy)]
1315pub struct EffectLayerProps {
1316 pub layout: LayoutStyle,
1317 pub mode: EffectMode,
1318 pub chain: EffectChain,
1319 pub quality: EffectQuality,
1320}
1321
1322impl Default for EffectLayerProps {
1323 fn default() -> Self {
1324 Self {
1325 layout: LayoutStyle::default(),
1326 mode: EffectMode::FilterContent,
1327 chain: EffectChain::EMPTY,
1328 quality: EffectQuality::Auto,
1329 }
1330 }
1331}
1332
1333#[derive(Debug, Clone, Copy)]
1338pub struct BackdropSourceGroupProps {
1339 pub layout: LayoutStyle,
1340 pub pyramid: Option<CustomEffectPyramidRequestV1>,
1341 pub quality: EffectQuality,
1342}
1343
1344impl Default for BackdropSourceGroupProps {
1345 fn default() -> Self {
1346 Self {
1347 layout: LayoutStyle::default(),
1348 pyramid: None,
1349 quality: EffectQuality::Auto,
1350 }
1351 }
1352}
1353
1354#[derive(Debug, Clone, Copy, PartialEq)]
1359pub struct MaskLayerProps {
1360 pub layout: LayoutStyle,
1361 pub mask: Mask,
1362}
1363
1364#[derive(Debug, Clone, Copy, PartialEq)]
1369pub struct CompositeGroupProps {
1370 pub layout: LayoutStyle,
1371 pub mode: BlendMode,
1372 pub quality: EffectQuality,
1373}
1374
1375impl Default for CompositeGroupProps {
1376 fn default() -> Self {
1377 Self {
1378 layout: LayoutStyle::default(),
1379 mode: BlendMode::Over,
1380 quality: EffectQuality::Auto,
1381 }
1382 }
1383}
1384
1385#[derive(Debug, Clone, Copy, Default)]
1390pub struct ViewCacheProps {
1391 pub layout: LayoutStyle,
1392 pub contained_layout: bool,
1394 pub cache_key: u64,
1399}
1400
1401#[derive(Debug, Clone, Copy, Default)]
1410pub struct VisualTransformProps {
1411 pub layout: LayoutStyle,
1412 pub transform: fret_core::Transform2D,
1417}
1418
1419#[derive(Debug, Clone, Copy, Default)]
1429pub struct RenderTransformProps {
1430 pub layout: LayoutStyle,
1431 pub transform: fret_core::Transform2D,
1432}
1433
1434#[derive(Debug, Clone, Copy, Default)]
1441pub struct FractionalRenderTransformProps {
1442 pub layout: LayoutStyle,
1443 pub translate_x_fraction: f32,
1445 pub translate_y_fraction: f32,
1447}
1448
1449#[derive(Debug, Clone)]
1456pub struct AnchoredProps {
1457 pub layout: LayoutStyle,
1458 pub outer_margin: Edges,
1460 pub anchor: fret_core::Rect,
1462 pub anchor_element: Option<u64>,
1471 pub side: Side,
1472 pub align: Align,
1473 pub side_offset: Px,
1475 pub options: AnchoredPanelOptions,
1476 pub layout_out: Option<Model<AnchoredPanelLayout>>,
1478}
1479
1480impl Default for AnchoredProps {
1481 fn default() -> Self {
1482 let mut layout = LayoutStyle::default();
1483 layout.size.width = Length::Fill;
1484 layout.size.height = Length::Fill;
1485
1486 Self {
1487 layout,
1488 outer_margin: Edges::all(Px(0.0)),
1489 anchor: fret_core::Rect::default(),
1490 anchor_element: None,
1491 side: Side::Bottom,
1492 align: Align::Start,
1493 side_offset: Px(0.0),
1494 options: AnchoredPanelOptions::default(),
1495 layout_out: None,
1496 }
1497 }
1498}
1499
1500#[derive(Debug, Clone, Copy, PartialEq)]
1505pub struct ShadowLayerStyle {
1506 pub color: Color,
1507 pub offset_x: Px,
1508 pub offset_y: Px,
1509 pub blur: Px,
1511 pub spread: Px,
1513}
1514
1515#[derive(Debug, Clone, Copy, PartialEq)]
1520pub struct ShadowStyle {
1521 pub primary: ShadowLayerStyle,
1522 pub secondary: Option<ShadowLayerStyle>,
1523 pub corner_radii: Corners,
1524}
1525
1526#[derive(Clone)]
1527pub struct PressableProps {
1528 pub layout: LayoutStyle,
1529 pub enabled: bool,
1530 pub focusable: bool,
1535 pub focus_ring: Option<RingStyle>,
1536 pub focus_ring_always_paint: bool,
1544 pub focus_ring_bounds: Option<Rect>,
1552 pub key_activation: PressableKeyActivation,
1553 pub a11y: PressableA11y,
1554}
1555
1556impl std::fmt::Debug for PressableProps {
1557 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1558 let mut out = f.debug_struct("PressableProps");
1559 out.field("layout", &self.layout)
1560 .field("enabled", &self.enabled)
1561 .field("focusable", &self.focusable);
1562
1563 out.field("focus_ring", &self.focus_ring)
1564 .field("focus_ring_always_paint", &self.focus_ring_always_paint)
1565 .field("focus_ring_bounds", &self.focus_ring_bounds)
1566 .field("key_activation", &self.key_activation)
1567 .field("a11y", &self.a11y)
1568 .finish()
1569 }
1570}
1571
1572impl Default for PressableProps {
1573 fn default() -> Self {
1574 Self {
1575 layout: LayoutStyle::default(),
1576 enabled: true,
1577 focusable: true,
1578 focus_ring: None,
1579 focus_ring_always_paint: false,
1580 focus_ring_bounds: None,
1581 key_activation: PressableKeyActivation::default(),
1582 a11y: PressableA11y::default(),
1583 }
1584 }
1585}
1586
1587#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
1588pub enum PressableKeyActivation {
1589 #[default]
1591 EnterAndSpace,
1592 EnterOnly,
1594}
1595
1596impl PressableKeyActivation {
1597 pub fn allows(self, key: KeyCode) -> bool {
1598 match self {
1599 Self::EnterAndSpace => {
1600 matches!(key, KeyCode::Enter | KeyCode::NumpadEnter | KeyCode::Space)
1601 }
1602 Self::EnterOnly => matches!(key, KeyCode::Enter | KeyCode::NumpadEnter),
1603 }
1604 }
1605}
1606
1607#[derive(Clone, Default)]
1608pub struct RovingFlexProps {
1609 pub flex: FlexProps,
1610 pub roving: RovingFocusProps,
1611}
1612
1613impl std::fmt::Debug for RovingFlexProps {
1614 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1615 f.debug_struct("RovingFlexProps")
1616 .field("flex", &self.flex)
1617 .field("roving", &self.roving)
1618 .finish()
1619 }
1620}
1621
1622#[derive(Debug, Clone)]
1623pub struct RovingFocusProps {
1624 pub enabled: bool,
1625 pub wrap: bool,
1626 pub disabled: Arc<[bool]>,
1627}
1628
1629impl Default for RovingFocusProps {
1630 fn default() -> Self {
1631 Self {
1632 enabled: true,
1633 wrap: true,
1634 disabled: Arc::from([]),
1635 }
1636 }
1637}
1638
1639#[derive(Debug, Default, Clone)]
1640pub struct PressableA11y {
1641 pub role: Option<SemanticsRole>,
1642 pub label: Option<Arc<str>>,
1643 pub level: Option<u32>,
1645 pub test_id: Option<Arc<str>>,
1649 pub hidden: bool,
1655 pub visited: bool,
1659 pub multiselectable: bool,
1663 pub required: bool,
1664 pub invalid: Option<fret_core::SemanticsInvalid>,
1665 pub selected: bool,
1666 pub expanded: Option<bool>,
1667 pub checked: Option<bool>,
1668 pub checked_state: Option<fret_core::SemanticsCheckedState>,
1669 pub pressed_state: Option<fret_core::SemanticsPressedState>,
1670 pub active_descendant: Option<NodeId>,
1671 pub labelled_by_element: Option<u64>,
1677 pub described_by_element: Option<u64>,
1683 pub controls_element: Option<u64>,
1689 pub pos_in_set: Option<u32>,
1690 pub set_size: Option<u32>,
1691}
1692
1693#[derive(Debug, Clone, Copy, Default)]
1694pub struct PressableState {
1695 pub hovered: bool,
1696 pub hovered_raw: bool,
1697 pub hovered_raw_below_barrier: bool,
1704 pub pressed: bool,
1705 pub focused: bool,
1706}
1707
1708#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
1709pub enum RingPlacement {
1710 Inset,
1712 #[default]
1714 Outset,
1715}
1716
1717#[derive(Debug, Clone, Copy, PartialEq)]
1723pub struct RingStyle {
1724 pub placement: RingPlacement,
1725 pub width: Px,
1726 pub offset: Px,
1727 pub color: Color,
1728 pub offset_color: Option<Color>,
1729 pub corner_radii: Corners,
1730}
1731
1732#[derive(Debug, Default, Clone, Copy)]
1733pub struct StackProps {
1734 pub layout: LayoutStyle,
1735}
1736
1737#[derive(Debug, Clone, Copy)]
1738pub struct ColumnProps {
1739 pub layout: LayoutStyle,
1740 pub gap: SpacingLength,
1741 pub padding: SpacingEdges,
1742 pub justify: MainAlign,
1743 pub align: CrossAlign,
1744}
1745
1746impl Default for ColumnProps {
1747 fn default() -> Self {
1748 Self {
1749 layout: LayoutStyle::default(),
1750 gap: SpacingLength::Px(Px(0.0)),
1751 padding: SpacingEdges::all(SpacingLength::Px(Px(0.0))),
1752 justify: MainAlign::Start,
1753 align: CrossAlign::Stretch,
1754 }
1755 }
1756}
1757
1758#[derive(Debug, Clone, Copy)]
1759pub struct RowProps {
1760 pub layout: LayoutStyle,
1761 pub gap: SpacingLength,
1762 pub padding: SpacingEdges,
1763 pub justify: MainAlign,
1764 pub align: CrossAlign,
1765}
1766
1767impl Default for RowProps {
1768 fn default() -> Self {
1769 Self {
1770 layout: LayoutStyle::default(),
1771 gap: SpacingLength::Px(Px(0.0)),
1772 padding: SpacingEdges::all(SpacingLength::Px(Px(0.0))),
1773 justify: MainAlign::Start,
1774 align: CrossAlign::Stretch,
1775 }
1776 }
1777}
1778
1779#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
1780pub enum MainAlign {
1781 #[default]
1782 Start,
1783 Center,
1784 End,
1785 SpaceBetween,
1786 SpaceAround,
1787 SpaceEvenly,
1788}
1789
1790#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
1791pub enum CrossAlign {
1792 Start,
1793 #[default]
1794 Center,
1795 End,
1796 Stretch,
1797}
1798
1799#[derive(Debug, Clone, Copy)]
1800pub struct SpacerProps {
1801 pub layout: LayoutStyle,
1802 pub min: Px,
1803}
1804
1805impl Default for SpacerProps {
1806 fn default() -> Self {
1807 let mut layout = LayoutStyle::default();
1808 layout.flex.grow = 1.0;
1809 layout.flex.shrink = 1.0;
1810 layout.flex.basis = Length::Px(Px(0.0));
1811 Self {
1812 layout,
1813 min: Px(0.0),
1814 }
1815 }
1816}
1817
1818#[derive(Debug, Clone)]
1819pub struct TextProps {
1820 pub layout: LayoutStyle,
1821 pub text: std::sync::Arc<str>,
1822 pub style: Option<TextStyle>,
1823 pub color: Option<Color>,
1824 pub wrap: TextWrap,
1825 pub overflow: TextOverflow,
1826 pub align: TextAlign,
1827 pub ink_overflow: TextInkOverflow,
1833}
1834
1835#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
1836pub enum TextInkOverflow {
1837 #[default]
1839 None,
1840 AutoPad,
1846}
1847
1848#[derive(Debug, Clone)]
1849pub struct StyledTextProps {
1850 pub layout: LayoutStyle,
1851 pub rich: AttributedText,
1852 pub style: Option<TextStyle>,
1853 pub color: Option<Color>,
1855 pub wrap: TextWrap,
1856 pub overflow: TextOverflow,
1857 pub align: TextAlign,
1858 pub ink_overflow: TextInkOverflow,
1859}
1860
1861#[derive(Debug, Clone)]
1862pub struct SelectableTextProps {
1863 pub layout: LayoutStyle,
1864 pub rich: AttributedText,
1865 pub style: Option<TextStyle>,
1866 pub color: Option<Color>,
1868 pub wrap: TextWrap,
1869 pub overflow: TextOverflow,
1870 pub align: TextAlign,
1871 pub ink_overflow: TextInkOverflow,
1872 pub interactive_spans: std::sync::Arc<[SelectableTextInteractiveSpan]>,
1877}
1878
1879#[derive(Debug, Clone, PartialEq, Eq)]
1880pub struct SelectableTextInteractiveSpan {
1881 pub range: std::ops::Range<usize>,
1882 pub tag: std::sync::Arc<str>,
1884}
1885
1886#[derive(Debug, Clone, PartialEq)]
1887pub struct SelectableTextInteractiveSpanBounds {
1888 pub range: std::ops::Range<usize>,
1889 pub tag: std::sync::Arc<str>,
1890 pub bounds_local: fret_core::Rect,
1892}
1893
1894#[derive(Debug, Clone)]
1895pub struct SelectableTextState {
1896 pub selection_anchor: usize,
1897 pub caret: usize,
1898 pub affinity: CaretAffinity,
1899 pub preferred_x: Option<Px>,
1900 pub dragging: bool,
1901 pub last_pointer_pos: Option<fret_core::Point>,
1902 pub pointer_down_pos: Option<fret_core::Point>,
1903 pub pending_span_activation: Option<crate::action::SelectableTextSpanActivation>,
1904 pub pending_span_click_count: u8,
1905 pub interactive_span_bounds: Vec<SelectableTextInteractiveSpanBounds>,
1906}
1907
1908impl Default for SelectableTextState {
1909 fn default() -> Self {
1910 Self {
1911 selection_anchor: 0,
1912 caret: 0,
1913 affinity: CaretAffinity::Downstream,
1914 preferred_x: None,
1915 dragging: false,
1916 last_pointer_pos: None,
1917 pointer_down_pos: None,
1918 pending_span_activation: None,
1919 pending_span_click_count: 0,
1920 interactive_span_bounds: Vec::new(),
1921 }
1922 }
1923}
1924
1925#[derive(Clone)]
1926pub struct TextInputProps {
1927 pub layout: LayoutStyle,
1928 pub enabled: bool,
1929 pub focusable: bool,
1930 pub model: Model<String>,
1931 pub a11y_label: Option<std::sync::Arc<str>>,
1932 pub a11y_role: Option<SemanticsRole>,
1933 pub test_id: Option<std::sync::Arc<str>>,
1934 pub placeholder: Option<std::sync::Arc<str>>,
1935 pub obscure_text: bool,
1938 pub a11y_required: bool,
1939 pub a11y_invalid: Option<fret_core::SemanticsInvalid>,
1940 pub active_descendant: Option<NodeId>,
1941 pub active_descendant_element: Option<u64>,
1947 pub controls_element: Option<u64>,
1953 pub expanded: Option<bool>,
1954 pub chrome: TextInputStyle,
1955 pub focus_ring_always_paint: bool,
1961 pub text_style: TextStyle,
1962 pub submit_command: Option<CommandId>,
1963 pub cancel_command: Option<CommandId>,
1964}
1965
1966impl TextInputProps {
1967 pub fn new(model: Model<String>) -> Self {
1968 Self {
1969 layout: LayoutStyle::default(),
1970 enabled: true,
1971 focusable: true,
1972 model,
1973 a11y_label: None,
1974 a11y_role: None,
1975 test_id: None,
1976 placeholder: None,
1977 obscure_text: false,
1978 a11y_required: false,
1979 a11y_invalid: None,
1980 active_descendant: None,
1981 active_descendant_element: None,
1982 controls_element: None,
1983 expanded: None,
1984 chrome: TextInputStyle::default(),
1985 focus_ring_always_paint: false,
1986 text_style: TextStyle::default(),
1987 submit_command: None,
1988 cancel_command: None,
1989 }
1990 }
1991}
1992
1993impl std::fmt::Debug for TextInputProps {
1994 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1995 f.debug_struct("TextInputProps")
1996 .field("layout", &self.layout)
1997 .field("enabled", &self.enabled)
1998 .field("focusable", &self.focusable)
1999 .field("model", &"<model>")
2000 .field("a11y_label", &self.a11y_label.as_ref().map(|s| s.as_ref()))
2001 .field("a11y_role", &self.a11y_role)
2002 .field("test_id", &self.test_id.as_ref().map(|s| s.as_ref()))
2003 .field(
2004 "placeholder",
2005 &self.placeholder.as_ref().map(|s| s.as_ref()),
2006 )
2007 .field("obscure_text", &self.obscure_text)
2008 .field("active_descendant_element", &self.active_descendant_element)
2009 .field("controls_element", &self.controls_element)
2010 .field("expanded", &self.expanded)
2011 .field("chrome", &self.chrome)
2012 .field("focus_ring_always_paint", &self.focus_ring_always_paint)
2013 .field("text_style", &self.text_style)
2014 .field("submit_command", &self.submit_command)
2015 .field("cancel_command", &self.cancel_command)
2016 .finish()
2017 }
2018}
2019
2020#[derive(Clone)]
2021pub struct TextAreaProps {
2022 pub layout: LayoutStyle,
2023 pub enabled: bool,
2024 pub focusable: bool,
2025 pub model: Model<String>,
2026 pub placeholder: Option<std::sync::Arc<str>>,
2027 pub a11y_required: bool,
2028 pub a11y_invalid: Option<fret_core::SemanticsInvalid>,
2029 pub a11y_label: Option<std::sync::Arc<str>>,
2030 pub test_id: Option<std::sync::Arc<str>>,
2031 pub chrome: TextAreaStyle,
2032 pub focus_ring_always_paint: bool,
2038 pub text_style: TextStyle,
2039 pub min_height: Px,
2040}
2041
2042impl TextAreaProps {
2043 pub fn new(model: Model<String>) -> Self {
2044 Self {
2045 layout: LayoutStyle::default(),
2046 enabled: true,
2047 focusable: true,
2048 model,
2049 placeholder: None,
2050 a11y_required: false,
2051 a11y_invalid: None,
2052 a11y_label: None,
2053 test_id: None,
2054 chrome: TextAreaStyle::default(),
2055 focus_ring_always_paint: false,
2056 text_style: TextStyle::default(),
2057 min_height: Px(80.0),
2058 }
2059 }
2060}
2061
2062impl std::fmt::Debug for TextAreaProps {
2063 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2064 f.debug_struct("TextAreaProps")
2065 .field("layout", &self.layout)
2066 .field("enabled", &self.enabled)
2067 .field("focusable", &self.focusable)
2068 .field("model", &"<model>")
2069 .field(
2070 "placeholder",
2071 &self.placeholder.as_ref().map(|s| s.as_ref()),
2072 )
2073 .field("a11y_label", &self.a11y_label.as_ref().map(|s| s.as_ref()))
2074 .field("test_id", &self.test_id.as_ref().map(|s| s.as_ref()))
2075 .field("chrome", &self.chrome)
2076 .field("focus_ring_always_paint", &self.focus_ring_always_paint)
2077 .field("text_style", &self.text_style)
2078 .field("min_height", &self.min_height)
2079 .finish()
2080 }
2081}
2082
2083#[derive(Clone)]
2084pub struct ResizablePanelGroupProps {
2085 pub layout: LayoutStyle,
2086 pub axis: fret_core::Axis,
2087 pub model: Model<Vec<f32>>,
2088 pub min_px: Vec<Px>,
2089 pub enabled: bool,
2090 pub chrome: ResizablePanelGroupStyle,
2091}
2092
2093impl ResizablePanelGroupProps {
2094 pub fn new(axis: fret_core::Axis, model: Model<Vec<f32>>) -> Self {
2095 let mut layout = LayoutStyle::default();
2096 layout.size.width = Length::Fill;
2097 layout.size.height = Length::Fill;
2098
2099 Self {
2100 layout,
2101 axis,
2102 model,
2103 min_px: Vec::new(),
2104 enabled: true,
2105 chrome: ResizablePanelGroupStyle::default(),
2106 }
2107 }
2108}
2109
2110impl std::fmt::Debug for ResizablePanelGroupProps {
2111 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2112 f.debug_struct("ResizablePanelGroupProps")
2113 .field("layout", &self.layout)
2114 .field("axis", &self.axis)
2115 .field("model", &"<model>")
2116 .field("min_px_len", &self.min_px.len())
2117 .field("enabled", &self.enabled)
2118 .field("chrome", &self.chrome)
2119 .finish()
2120 }
2121}
2122
2123#[derive(Debug, Clone, Copy)]
2124pub struct ImageProps {
2125 pub layout: LayoutStyle,
2126 pub image: ImageId,
2127 pub fit: ViewportFit,
2128 pub sampling: fret_core::scene::ImageSamplingHint,
2129 pub opacity: f32,
2130 pub uv: Option<UvRect>,
2131}
2132
2133impl ImageProps {
2134 pub fn new(image: ImageId) -> Self {
2135 Self {
2136 layout: LayoutStyle::default(),
2137 image,
2138 fit: ViewportFit::Stretch,
2139 sampling: fret_core::scene::ImageSamplingHint::Default,
2140 opacity: 1.0,
2141 uv: None,
2142 }
2143 }
2144
2145 pub fn sampling(mut self, sampling: fret_core::scene::ImageSamplingHint) -> Self {
2146 self.sampling = sampling;
2147 self
2148 }
2149}
2150
2151#[derive(Debug, Clone, Copy)]
2152pub struct ViewportSurfaceProps {
2153 pub layout: LayoutStyle,
2154 pub target: RenderTargetId,
2155 pub target_px_size: (u32, u32),
2156 pub fit: ViewportFit,
2157 pub opacity: f32,
2158}
2159
2160impl ViewportSurfaceProps {
2161 pub fn new(target: RenderTargetId) -> Self {
2162 Self {
2163 layout: LayoutStyle::default(),
2164 target,
2165 target_px_size: (1, 1),
2166 fit: ViewportFit::Stretch,
2167 opacity: 1.0,
2168 }
2169 }
2170}
2171
2172#[derive(Debug, Clone, Copy)]
2177pub struct CanvasProps {
2178 pub layout: LayoutStyle,
2179 pub cache_policy: CanvasCachePolicy,
2180}
2181
2182#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2184pub struct CanvasCacheTuning {
2185 pub keep_frames: u64,
2187 pub max_entries: usize,
2189}
2190
2191impl CanvasCacheTuning {
2192 pub const fn transient() -> Self {
2193 Self {
2194 keep_frames: 0,
2195 max_entries: 0,
2196 }
2197 }
2198}
2199
2200#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2205pub struct CanvasCachePolicy {
2206 pub text: CanvasCacheTuning,
2207 pub shared_text: CanvasCacheTuning,
2208 pub path: CanvasCacheTuning,
2209 pub svg: CanvasCacheTuning,
2210}
2211
2212impl CanvasCachePolicy {
2213 pub const fn smooth_default() -> Self {
2214 Self {
2215 text: CanvasCacheTuning {
2217 keep_frames: 60,
2218 max_entries: 4096,
2219 },
2220 shared_text: CanvasCacheTuning {
2225 keep_frames: 120,
2226 max_entries: 4096,
2227 },
2228 path: CanvasCacheTuning {
2229 keep_frames: 60,
2230 max_entries: 2048,
2231 },
2232 svg: CanvasCacheTuning {
2233 keep_frames: 60,
2234 max_entries: 256,
2235 },
2236 }
2237 }
2238}
2239
2240impl Default for CanvasCachePolicy {
2241 fn default() -> Self {
2242 Self::smooth_default()
2243 }
2244}
2245
2246impl Default for CanvasProps {
2247 fn default() -> Self {
2248 let mut layout = LayoutStyle::default();
2249 layout.size.width = Length::Fill;
2250 layout.size.height = Length::Fill;
2251 Self {
2252 layout,
2253 cache_policy: CanvasCachePolicy::default(),
2254 }
2255 }
2256}
2257
2258#[derive(Debug, Clone)]
2259pub struct SvgIconProps {
2260 pub layout: LayoutStyle,
2261 pub svg: SvgSource,
2262 pub fit: SvgFit,
2263 pub color: Color,
2264 pub inherit_color: bool,
2268 pub opacity: f32,
2269}
2270
2271impl SvgIconProps {
2272 pub fn new(svg: SvgSource) -> Self {
2273 Self {
2274 layout: LayoutStyle::default(),
2275 svg,
2276 fit: SvgFit::Contain,
2277 color: Color {
2278 r: 1.0,
2279 g: 1.0,
2280 b: 1.0,
2281 a: 1.0,
2282 },
2283 inherit_color: false,
2284 opacity: 1.0,
2285 }
2286 }
2287}
2288
2289#[derive(Debug, Clone, Copy)]
2294pub struct SpinnerProps {
2295 pub layout: LayoutStyle,
2296 pub color: Option<Color>,
2297 pub dot_count: u8,
2298 pub speed: f32,
2300}
2301
2302impl Default for SpinnerProps {
2303 fn default() -> Self {
2304 let mut layout = LayoutStyle::default();
2305 layout.size.width = Length::Px(Px(16.0));
2306 layout.size.height = Length::Px(Px(16.0));
2307
2308 Self {
2309 layout,
2310 color: None,
2311 dot_count: 12,
2312 speed: 0.2,
2313 }
2314 }
2315}
2316
2317#[derive(Debug, Clone, Copy, Default)]
2322pub struct HoverRegionProps {
2323 pub layout: LayoutStyle,
2324}
2325
2326#[derive(Debug, Clone)]
2328pub struct WheelRegionProps {
2329 pub layout: LayoutStyle,
2330 pub axis: ScrollAxis,
2331 pub scroll_target: Option<GlobalElementId>,
2333 pub scroll_handle: crate::scroll::ScrollHandle,
2334}
2335
2336impl Default for WheelRegionProps {
2337 fn default() -> Self {
2338 Self {
2339 layout: LayoutStyle::default(),
2340 axis: ScrollAxis::Y,
2341 scroll_target: None,
2342 scroll_handle: crate::scroll::ScrollHandle::default(),
2343 }
2344 }
2345}
2346
2347impl TextProps {
2348 pub fn new(text: impl Into<std::sync::Arc<str>>) -> Self {
2349 Self {
2350 layout: LayoutStyle::default(),
2351 text: text.into(),
2352 style: None,
2353 color: None,
2354 wrap: TextWrap::Word,
2355 overflow: TextOverflow::Clip,
2356 align: TextAlign::Start,
2357 ink_overflow: TextInkOverflow::None,
2358 }
2359 }
2360
2361 pub(crate) fn resolved_text_style_with_inherited(
2362 &self,
2363 theme: crate::ThemeSnapshot,
2364 inherited: Option<&fret_core::TextStyleRefinement>,
2365 ) -> TextStyle {
2366 crate::text_props::resolve_text_style(theme, self.style.clone(), inherited)
2367 }
2368
2369 pub(crate) fn build_text_input_with_style(&self, style: TextStyle) -> fret_core::TextInput {
2370 crate::text_props::build_text_input_plain(self.text.clone(), style)
2371 }
2372}
2373
2374impl StyledTextProps {
2375 pub fn new(rich: AttributedText) -> Self {
2376 Self {
2377 layout: LayoutStyle::default(),
2378 rich,
2379 style: None,
2380 color: None,
2381 wrap: TextWrap::Word,
2382 overflow: TextOverflow::Clip,
2383 align: TextAlign::Start,
2384 ink_overflow: TextInkOverflow::None,
2385 }
2386 }
2387
2388 pub(crate) fn resolved_text_style_with_inherited(
2389 &self,
2390 theme: crate::ThemeSnapshot,
2391 inherited: Option<&fret_core::TextStyleRefinement>,
2392 ) -> TextStyle {
2393 crate::text_props::resolve_text_style(theme, self.style.clone(), inherited)
2394 }
2395
2396 pub(crate) fn build_text_input_with_style(&self, style: TextStyle) -> fret_core::TextInput {
2397 crate::text_props::build_text_input_attributed(&self.rich, style)
2398 }
2399}
2400
2401impl SelectableTextProps {
2402 pub fn new(rich: AttributedText) -> Self {
2403 Self {
2404 layout: LayoutStyle::default(),
2405 rich,
2406 style: None,
2407 color: None,
2408 wrap: TextWrap::Word,
2409 overflow: TextOverflow::Clip,
2410 align: TextAlign::Start,
2411 ink_overflow: TextInkOverflow::None,
2412 interactive_spans: std::sync::Arc::from([]),
2413 }
2414 }
2415
2416 pub(crate) fn resolved_text_style_with_inherited(
2417 &self,
2418 theme: crate::ThemeSnapshot,
2419 inherited: Option<&fret_core::TextStyleRefinement>,
2420 ) -> TextStyle {
2421 crate::text_props::resolve_text_style(theme, self.style.clone(), inherited)
2422 }
2423
2424 pub(crate) fn build_text_input_with_style(&self, style: TextStyle) -> fret_core::TextInput {
2425 crate::text_props::build_text_input_attributed(&self.rich, style)
2426 }
2427}
2428
2429#[derive(Debug, Clone, Copy)]
2430pub struct FlexProps {
2431 pub layout: LayoutStyle,
2432 pub direction: fret_core::Axis,
2433 pub gap: SpacingLength,
2434 pub padding: SpacingEdges,
2435 pub justify: MainAlign,
2436 pub align: CrossAlign,
2437 pub wrap: bool,
2438}
2439
2440impl Default for FlexProps {
2441 fn default() -> Self {
2442 Self {
2443 layout: LayoutStyle::default(),
2444 direction: fret_core::Axis::Horizontal,
2445 gap: SpacingLength::Px(Px(0.0)),
2446 padding: SpacingEdges::all(SpacingLength::Px(Px(0.0))),
2447 justify: MainAlign::Start,
2448 align: CrossAlign::Stretch,
2449 wrap: false,
2450 }
2451 }
2452}
2453
2454#[derive(Debug, Clone, Copy, PartialEq)]
2455pub enum GridTrackSizing {
2456 Auto,
2457 MinContent,
2458 MaxContent,
2459 Px(Px),
2460 Fr(f32),
2461 Flex(f32),
2463}
2464
2465#[derive(Debug, Clone, PartialEq)]
2466pub struct GridProps {
2467 pub layout: LayoutStyle,
2468 pub cols: u16,
2469 pub rows: Option<u16>,
2470 pub template_columns: Option<Vec<GridTrackSizing>>,
2474 pub template_rows: Option<Vec<GridTrackSizing>>,
2478 pub gap: SpacingLength,
2479 pub column_gap: Option<SpacingLength>,
2483 pub row_gap: Option<SpacingLength>,
2487 pub padding: SpacingEdges,
2488 pub justify: MainAlign,
2489 pub align: CrossAlign,
2490 pub justify_items: Option<CrossAlign>,
2494}
2495
2496impl Default for GridProps {
2497 fn default() -> Self {
2498 Self {
2499 layout: LayoutStyle::default(),
2500 cols: 1,
2501 rows: None,
2502 template_columns: None,
2503 template_rows: None,
2504 gap: SpacingLength::Px(Px(0.0)),
2505 column_gap: None,
2506 row_gap: None,
2507 padding: SpacingEdges::all(SpacingLength::Px(Px(0.0))),
2508 justify: MainAlign::Start,
2509 align: CrossAlign::Stretch,
2510 justify_items: None,
2511 }
2512 }
2513}
2514
2515impl GridProps {
2516 pub fn resolved_column_gap(&self) -> SpacingLength {
2517 self.column_gap.unwrap_or(self.gap)
2518 }
2519
2520 pub fn resolved_row_gap(&self) -> SpacingLength {
2521 self.row_gap.unwrap_or(self.gap)
2522 }
2523}
2524
2525#[derive(Debug, Clone)]
2526pub struct VirtualListProps {
2527 pub layout: LayoutStyle,
2528 pub axis: fret_core::Axis,
2529 pub len: usize,
2530 pub items_revision: u64,
2531 pub estimate_row_height: Px,
2532 pub measure_mode: VirtualListMeasureMode,
2533 pub key_cache: VirtualListKeyCacheMode,
2534 pub overscan: usize,
2535 pub keep_alive: usize,
2541 pub scroll_margin: Px,
2542 pub gap: Px,
2543 pub scroll_handle: crate::scroll::VirtualListScrollHandle,
2544 pub visible_items: Vec<crate::virtual_list::VirtualItem>,
2545}
2546
2547#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2548pub enum VirtualListMeasureMode {
2549 Measured,
2552 Fixed,
2555 Known,
2563}
2564
2565#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
2566pub enum VirtualListKeyCacheMode {
2567 #[default]
2571 AllKeys,
2572 VisibleOnly,
2577}
2578
2579#[derive(Clone)]
2580pub struct VirtualListOptions {
2581 pub axis: fret_core::Axis,
2582 pub items_revision: u64,
2583 pub estimate_row_height: Px,
2584 pub measure_mode: VirtualListMeasureMode,
2585 pub key_cache: VirtualListKeyCacheMode,
2586 pub overscan: usize,
2587 pub keep_alive: usize,
2588 pub scroll_margin: Px,
2589 pub gap: Px,
2590 pub known_row_height_at: Option<Arc<dyn Fn(usize) -> Px + Send + Sync>>,
2591}
2592
2593impl VirtualListOptions {
2594 pub fn new(estimate_row_height: Px, overscan: usize) -> Self {
2595 Self {
2596 axis: fret_core::Axis::Vertical,
2597 items_revision: 0,
2598 estimate_row_height,
2599 measure_mode: VirtualListMeasureMode::Measured,
2600 key_cache: VirtualListKeyCacheMode::AllKeys,
2601 overscan,
2602 keep_alive: 0,
2603 scroll_margin: Px(0.0),
2604 gap: Px(0.0),
2605 known_row_height_at: None,
2606 }
2607 }
2608
2609 pub fn keep_alive(mut self, keep_alive: usize) -> Self {
2610 self.keep_alive = keep_alive;
2611 self
2612 }
2613
2614 pub fn fixed(estimate_row_height: Px, overscan: usize) -> Self {
2615 Self {
2616 measure_mode: VirtualListMeasureMode::Fixed,
2617 ..Self::new(estimate_row_height, overscan)
2618 }
2619 }
2620
2621 pub fn known(
2622 estimate_row_height: Px,
2623 overscan: usize,
2624 height_at: impl Fn(usize) -> Px + Send + Sync + 'static,
2625 ) -> Self {
2626 let mut options = Self::new(estimate_row_height, overscan);
2627 options.measure_mode = VirtualListMeasureMode::Known;
2628 options.known_row_height_at = Some(Arc::new(height_at));
2629 options
2630 }
2631}
2632
2633impl std::fmt::Debug for VirtualListOptions {
2634 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2635 f.debug_struct("VirtualListOptions")
2636 .field("axis", &self.axis)
2637 .field("items_revision", &self.items_revision)
2638 .field("estimate_row_height", &self.estimate_row_height)
2639 .field("measure_mode", &self.measure_mode)
2640 .field("key_cache", &self.key_cache)
2641 .field("overscan", &self.overscan)
2642 .field("keep_alive", &self.keep_alive)
2643 .field("scroll_margin", &self.scroll_margin)
2644 .field("gap", &self.gap)
2645 .field("known_row_height_at", &self.known_row_height_at.is_some())
2646 .finish()
2647 }
2648}
2649
2650#[derive(Debug, Default, Clone)]
2652pub struct VirtualListState {
2653 pub offset_x: Px,
2654 pub offset_y: Px,
2655 pub viewport_w: Px,
2656 pub viewport_h: Px,
2657 pub(crate) window_range: Option<crate::virtual_list::VirtualRange>,
2658 pub(crate) render_window_range: Option<crate::virtual_list::VirtualRange>,
2659 pub(crate) last_scroll_direction_forward: Option<bool>,
2660 pub(crate) has_final_viewport: bool,
2661 pub(crate) deferred_scroll_offset_hint: Option<Px>,
2662 pub(crate) metrics: crate::virtual_list::VirtualListMetrics,
2663 pub(crate) items_revision: u64,
2664 pub(crate) items_len: usize,
2665 pub(crate) key_cache: VirtualListKeyCacheMode,
2666 pub(crate) keys: Vec<crate::ItemKey>,
2667 pub(crate) layout_scratch: VirtualListLayoutScratch,
2668}
2669
2670#[derive(Debug, Default, Clone)]
2671pub(crate) struct VirtualListLayoutScratch {
2672 pub(crate) measured_updates: Vec<(NodeId, usize, Px)>,
2673 pub(crate) barrier_roots: Vec<(NodeId, Rect)>,
2674}
2675
2676#[derive(Debug, Clone)]
2677pub struct ScrollProps {
2678 pub layout: LayoutStyle,
2679 pub axis: ScrollAxis,
2680 pub scroll_handle: Option<crate::scroll::ScrollHandle>,
2681 pub intrinsic_measure_mode: ScrollIntrinsicMeasureMode,
2682 pub windowed_paint: bool,
2690 pub probe_unbounded: bool,
2696}
2697
2698impl Default for ScrollProps {
2699 fn default() -> Self {
2700 let layout = LayoutStyle {
2701 overflow: Overflow::Clip,
2702 ..Default::default()
2703 };
2704 Self {
2705 layout,
2706 axis: ScrollAxis::Y,
2707 scroll_handle: None,
2708 intrinsic_measure_mode: ScrollIntrinsicMeasureMode::Content,
2709 windowed_paint: false,
2710 probe_unbounded: true,
2711 }
2712 }
2713}
2714
2715#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2716pub enum ScrollIntrinsicMeasureMode {
2717 Content,
2720 Viewport,
2728}
2729
2730#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2731pub enum ScrollAxis {
2732 X,
2733 Y,
2734 Both,
2735}
2736
2737impl ScrollAxis {
2738 pub fn scroll_x(self) -> bool {
2739 matches!(self, Self::X | Self::Both)
2740 }
2741
2742 pub fn scroll_y(self) -> bool {
2743 matches!(self, Self::Y | Self::Both)
2744 }
2745}
2746
2747#[derive(Debug, Default, Clone)]
2749pub struct ScrollState {
2750 pub scroll_handle: crate::scroll::ScrollHandle,
2751 pub(crate) intrinsic_measure_cache: Option<ScrollIntrinsicMeasureCache>,
2752 pub(crate) pending_extent_probe: bool,
2753}
2754
2755#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2756pub(crate) struct ScrollIntrinsicMeasureCacheKey {
2757 pub avail_w: u64,
2758 pub avail_h: u64,
2759 pub axis: u8,
2760 pub probe_unbounded: bool,
2761 pub scale_bits: u32,
2762}
2763
2764#[derive(Debug, Clone, Copy)]
2765pub(crate) struct ScrollIntrinsicMeasureCache {
2766 pub key: ScrollIntrinsicMeasureCacheKey,
2767 pub max_child: Size,
2768}
2769
2770#[derive(Debug, Clone, Copy)]
2771pub struct ScrollbarStyle {
2772 pub thumb: Color,
2773 pub thumb_hover: Color,
2774 pub thumb_idle_alpha: f32,
2775 pub track_padding: Px,
2781}
2782
2783impl Default for ScrollbarStyle {
2784 fn default() -> Self {
2785 Self {
2786 thumb: Color {
2787 r: 0.35,
2788 g: 0.38,
2789 b: 0.45,
2790 a: 1.0,
2791 },
2792 thumb_hover: Color {
2793 r: 0.45,
2794 g: 0.50,
2795 b: 0.60,
2796 a: 1.0,
2797 },
2798 thumb_idle_alpha: 0.65,
2799 track_padding: Px(1.0),
2800 }
2801 }
2802}
2803
2804#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
2805pub enum ScrollbarAxis {
2806 #[default]
2807 Vertical,
2808 Horizontal,
2809}
2810
2811#[derive(Debug, Clone, Default)]
2817pub struct ScrollbarProps {
2818 pub layout: LayoutStyle,
2819 pub axis: ScrollbarAxis,
2820 pub scroll_target: Option<GlobalElementId>,
2825 pub scroll_handle: crate::scroll::ScrollHandle,
2826 pub style: ScrollbarStyle,
2827}
2828
2829#[derive(Debug, Default, Clone)]
2831pub struct ScrollbarState {
2832 pub dragging_thumb: bool,
2833 pub drag_start_pointer: Px,
2834 pub drag_start_offset: Px,
2835 pub drag_baseline_viewport: Option<Px>,
2836 pub drag_baseline_content: Option<Px>,
2837 pub hovered: bool,
2838}
2839
2840pub trait IntoElement {
2845 fn into_element(self, id: GlobalElementId) -> AnyElement;
2846}
2847
2848#[derive(Debug, Default)]
2855pub struct Elements(pub Vec<AnyElement>);
2856
2857impl Elements {
2858 pub fn new(children: impl IntoIterator<Item = AnyElement>) -> Self {
2859 Self(children.into_iter().collect())
2860 }
2861
2862 pub fn into_vec(self) -> Vec<AnyElement> {
2863 self.0
2864 }
2865}
2866
2867impl From<Vec<AnyElement>> for Elements {
2868 fn from(value: Vec<AnyElement>) -> Self {
2869 Self(value)
2870 }
2871}
2872
2873impl From<AnyElement> for Elements {
2874 fn from(value: AnyElement) -> Self {
2875 Self::new([value])
2876 }
2877}
2878
2879impl<const N: usize> From<[AnyElement; N]> for Elements {
2880 fn from(value: [AnyElement; N]) -> Self {
2881 Self::new(value)
2882 }
2883}
2884
2885impl std::iter::FromIterator<AnyElement> for Elements {
2886 fn from_iter<T: IntoIterator<Item = AnyElement>>(iter: T) -> Self {
2887 Self::new(iter)
2888 }
2889}
2890
2891impl std::ops::Deref for Elements {
2892 type Target = Vec<AnyElement>;
2893
2894 fn deref(&self) -> &Self::Target {
2895 &self.0
2896 }
2897}
2898
2899impl std::ops::DerefMut for Elements {
2900 fn deref_mut(&mut self) -> &mut Self::Target {
2901 &mut self.0
2902 }
2903}
2904
2905impl IntoIterator for Elements {
2906 type Item = AnyElement;
2907 type IntoIter = std::vec::IntoIter<AnyElement>;
2908
2909 fn into_iter(self) -> Self::IntoIter {
2910 self.0.into_iter()
2911 }
2912}
2913
2914impl<'a> IntoIterator for &'a Elements {
2915 type Item = &'a AnyElement;
2916 type IntoIter = std::slice::Iter<'a, AnyElement>;
2917
2918 fn into_iter(self) -> Self::IntoIter {
2919 self.0.iter()
2920 }
2921}
2922
2923impl<'a> IntoIterator for &'a mut Elements {
2924 type Item = &'a mut AnyElement;
2925 type IntoIter = std::slice::IterMut<'a, AnyElement>;
2926
2927 fn into_iter(self) -> Self::IntoIter {
2928 self.0.iter_mut()
2929 }
2930}
2931
2932pub trait AnyElementIterExt: Iterator<Item = AnyElement> + Sized {
2941 fn elements(self) -> Vec<AnyElement> {
2942 self.collect()
2943 }
2944
2945 fn elements_owned(self) -> Elements {
2946 self.collect::<Elements>()
2947 }
2948}
2949
2950impl<T> AnyElementIterExt for T where T: Iterator<Item = AnyElement> + Sized {}
2951
2952impl IntoElement for AnyElement {
2953 fn into_element(self, _id: GlobalElementId) -> AnyElement {
2954 self
2955 }
2956}
2957
2958impl IntoElement for TextProps {
2959 fn into_element(self, id: GlobalElementId) -> AnyElement {
2960 AnyElement::new(id, ElementKind::Text(self), Vec::new())
2961 }
2962}
2963
2964impl IntoElement for StyledTextProps {
2965 fn into_element(self, id: GlobalElementId) -> AnyElement {
2966 AnyElement::new(id, ElementKind::StyledText(self), Vec::new())
2967 }
2968}
2969
2970impl IntoElement for SelectableTextProps {
2971 fn into_element(self, id: GlobalElementId) -> AnyElement {
2972 AnyElement::new(id, ElementKind::SelectableText(self), Vec::new())
2973 }
2974}
2975
2976impl IntoElement for ImageProps {
2977 fn into_element(self, id: GlobalElementId) -> AnyElement {
2978 AnyElement::new(id, ElementKind::Image(self), Vec::new())
2979 }
2980}
2981
2982impl IntoElement for ViewportSurfaceProps {
2983 fn into_element(self, id: GlobalElementId) -> AnyElement {
2984 AnyElement::new(id, ElementKind::ViewportSurface(self), Vec::new())
2985 }
2986}
2987
2988impl IntoElement for SvgIconProps {
2989 fn into_element(self, id: GlobalElementId) -> AnyElement {
2990 AnyElement::new(id, ElementKind::SvgIcon(self), Vec::new())
2991 }
2992}
2993
2994impl IntoElement for ScrollProps {
2995 fn into_element(self, id: GlobalElementId) -> AnyElement {
2996 AnyElement::new(id, ElementKind::Scroll(self), Vec::new())
2997 }
2998}
2999
3000impl IntoElement for std::sync::Arc<str> {
3001 fn into_element(self, id: GlobalElementId) -> AnyElement {
3002 TextProps::new(self).into_element(id)
3003 }
3004}
3005
3006impl IntoElement for &'static str {
3007 fn into_element(self, id: GlobalElementId) -> AnyElement {
3008 TextProps::new(self).into_element(id)
3009 }
3010}
3011
3012pub trait Render {
3014 fn render<H: UiHost>(&mut self, cx: &mut ElementContext<'_, H>) -> AnyElement;
3015}
3016
3017pub trait RenderOnce {
3019 fn render_once<H: UiHost>(self, cx: &mut ElementContext<'_, H>) -> AnyElement;
3020}
3021
3022#[cfg(test)]
3023mod default_semantics_tests {
3024 use super::*;
3025
3026 #[test]
3027 fn flex_props_default_width_is_auto() {
3028 assert_eq!(FlexProps::default().layout.size.width, Length::Auto);
3029 }
3030
3031 #[test]
3032 fn length_default_is_auto() {
3033 assert_eq!(Length::default(), Length::Auto);
3034 }
3035
3036 #[test]
3037 fn scroll_props_default_probe_unbounded_is_true() {
3038 assert!(ScrollProps::default().probe_unbounded);
3039 }
3040}