1use std::cell::{Cell, RefCell};
2use std::collections::HashSet;
3use std::rc::Rc;
4use std::sync::atomic::{AtomicU64, Ordering};
5
6use taffy::{AlignContent, AlignItems, AlignSelf, FlexDirection, FlexWrap, JustifyContent};
7
8use crate::animation::AnimationSpec;
9use crate::indication::IndicationNodeFactory;
10use crate::{Brush, Color, PointerEvent, Size, Transform, Vec2};
11
12#[derive(Clone, Copy, Debug)]
18pub struct StateColors {
19 pub default: Color,
20 pub hovered: Color,
21 pub focused: Color,
23 pub pressed: Color,
24 pub disabled: Color,
25 pub dragged: Color,
27}
28
29#[derive(Clone, Copy, Debug)]
32pub struct StateElevation {
33 pub default: f32,
34 pub hovered: f32,
35 pub focused: f32,
37 pub pressed: f32,
38 pub disabled: f32,
39 pub dragged: f32,
41}
42
43impl StateColors {
44 pub const fn transparent() -> Self {
46 Self {
47 default: Color::TRANSPARENT,
48 hovered: Color::TRANSPARENT,
49 focused: Color::TRANSPARENT,
50 pressed: Color::TRANSPARENT,
51 disabled: Color::TRANSPARENT,
52 dragged: Color::TRANSPARENT,
53 }
54 }
55}
56
57impl StateElevation {
58 pub const fn zero() -> Self {
60 Self {
61 default: 0.0,
62 hovered: 0.0,
63 focused: 0.0,
64 pressed: 0.0,
65 disabled: 0.0,
66 dragged: 0.0,
67 }
68 }
69}
70
71macro_rules! merge_opts {
72 ($dst:ident, $src:ident; $($f:ident),+ $(,)?) => {
73 $( $dst.$f = $src.$f.or($dst.$f); )+
74 };
75}
76macro_rules! merge_flags {
77 ($dst:ident, $src:ident; $($f:ident),+ $(,)?) => {
78 $( $dst.$f |= $src.$f; )+
79 };
80}
81
82macro_rules! impl_option_fields {
83 ($ty:ty, $fn:ident) => {
84 impl $ty {
85 $fn!(replace);
86 }
87 };
88 ($ty:ident) => {
89 impl $ty {
90 pub fn then(mut self, other: Self) -> Self {
93 merge_opts!(self, other;
94 key, size, width, height, required_size,
95 padding, padding_values,
96 min_width, min_height, max_width, max_height,
97 required_min_width, required_max_width,
98 required_min_height, required_max_height,
99 default_min_width, default_min_height,
100 fill_max, fill_max_w, fill_max_h,
101 background, state_colors, state_elevation, border,
102 flex_grow, flex_shrink, flex_basis, flex_wrap, flex_dir,
103 gap, row_gap, column_gap,
104 align_self, justify_content, align_items_container, align_content,
105 clip_rounded, clip_rect, overflow, render_z_index,
106 on_scroll,
107 nested_scroll_connection,
108 scroll,
109 on_pointer_down, on_pointer_move, on_pointer_up,
110 on_pointer_enter, on_pointer_leave,
111 on_click, on_double_click, on_long_click,
112 semantics, alpha, transform,
113 grid, grid_col_span, grid_row_span,
114 position_type,
115 offset_left, offset_right, offset_top, offset_bottom,
116 margin_left, margin_right, margin_top, margin_bottom,
117 aspect_ratio, intrinsic_width, intrinsic_height,
118 painter,
119 on_drag_start, on_drag_end, on_drag_enter, on_drag_over, on_drag_leave, on_drop,
120 drag_preview,
121 on_action, cursor, animate_content_size, focus_requester, on_focus_changed,
122 interaction_source, text_input,
123 );
124 merge_flags!(self, other;
125 hit_passthrough, input_blocker, repaint_boundary, click, disabled,
126 propagate_min, focus_group,
127 );
128
129 if let Some(f) = other.focusable {
130 self.focusable = Some(f);
131 }
132 if other.indication.is_some() {
133 self.indication = other.indication;
134 }
135 if other.z_index != 0.0 {
136 self.z_index = other.z_index;
137 }
138 self
139 }
140 }
141 };
142}
143
144#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
145pub enum ClipOp {
146 #[default]
148 Intersect,
149 Difference,
151}
152
153#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
159pub enum Overflow {
160 #[default]
161 Clip,
162 Visible,
163}
164
165#[derive(Clone, Copy, Debug)]
168pub struct ClipRect {
169 pub left: f32,
170 pub top: f32,
171 pub right: f32,
172 pub bottom: f32,
173 pub op: ClipOp,
174}
175
176#[derive(Clone, Debug)]
177pub struct Border {
178 pub width: f32,
179 pub color: Color,
180 pub radius: [f32; 4],
181}
182
183#[derive(Clone, Copy, Debug, Default)]
184pub struct PaddingValues {
185 pub left: f32,
186 pub right: f32,
187 pub top: f32,
188 pub bottom: f32,
189}
190
191#[derive(Clone, Debug)]
192pub struct GridConfig {
193 pub columns: usize,
194 pub row_gap: f32,
195 pub column_gap: f32,
196}
197
198#[derive(Clone, Copy, Debug, PartialEq)]
201pub enum BlurredEdgeTreatment {
202 Rectangle,
205 Unbounded,
208}
209
210#[derive(Clone, Copy, Debug)]
212pub struct BlurStyle {
213 pub radius_x: f32,
215 pub radius_y: f32,
217 pub edge_treatment: BlurredEdgeTreatment,
219}
220
221#[derive(Clone, Copy, Debug)]
226pub struct LayoutConstraints {
227 pub min_width: f32,
228 pub max_width: f32,
229 pub min_height: f32,
230 pub max_height: f32,
231}
232
233#[derive(Clone, Copy, Debug)]
240pub struct ShadowSpec {
241 pub blur_radius: f32,
242 pub offset_y: f32,
243 pub color: Color,
244}
245
246#[derive(Clone, Copy, Debug)]
247#[non_exhaustive]
248pub enum PositionType {
249 Relative,
250 Absolute,
251}
252
253#[derive(Clone)]
255pub struct TextInputConfig {
256 pub hint: String,
257 pub multiline: bool,
258 pub on_change: Option<Rc<dyn Fn(String)>>,
259 pub on_submit: Option<Rc<dyn Fn(String)>>,
260 pub focus_tracker: Option<Rc<Cell<bool>>>,
261 pub value: String,
262 pub visual_transformation: Option<Rc<dyn crate::text::VisualTransformation>>,
263 pub keyboard_type: crate::text::KeyboardType,
264 pub capitalization: crate::text::KeyboardCapitalization,
265 pub ime_action: crate::text::ImeAction,
266 pub auto_correct_enabled: Option<bool>,
269 pub enabled: bool,
271 pub read_only: bool,
273 pub max_lines: Option<usize>,
275 pub min_lines: usize,
277 pub cursor_color: Option<Color>,
279 pub on_text_layout: Option<Rc<dyn Fn(&crate::text::TextLayoutResult)>>,
282 pub text_style: Option<crate::text::TextStyle>,
285 pub keyboard_actions: Option<crate::text::KeyboardActions>,
288 pub interaction_source: Option<InteractionSource>,
290 pub line_limits: Option<crate::text::TextFieldLineLimits>,
292}
293
294impl std::fmt::Debug for TextInputConfig {
295 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
296 let mut s = f.debug_struct("TextInputConfig");
297 s.field("hint", &self.hint);
298 s.field("multiline", &self.multiline);
299 if self.on_change.is_some() {
300 s.field("on_change", &"…");
301 }
302 if self.on_submit.is_some() {
303 s.field("on_submit", &"…");
304 }
305 if self.focus_tracker.is_some() {
306 s.field("focus_tracker", &"…");
307 }
308 s.field("value", &self.value);
309 if self.visual_transformation.is_some() {
310 s.field("visual_transformation", &"…");
311 }
312 s.field("keyboard_type", &self.keyboard_type);
313 s.field("capitalization", &self.capitalization);
314 s.field("ime_action", &self.ime_action);
315 s.field("auto_correct_enabled", &self.auto_correct_enabled);
316 s.field("enabled", &self.enabled);
317 s.field("read_only", &self.read_only);
318 s.field("max_lines", &self.max_lines);
319 s.field("min_lines", &self.min_lines);
320 s.field("cursor_color", &self.cursor_color);
321 if self.on_text_layout.is_some() {
322 s.field("on_text_layout", &"…");
323 }
324 s.finish()
325 }
326}
327
328#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
331pub enum IntrinsicSize {
332 Min,
333 Max,
334}
335
336static PRESS_COUNTER: AtomicU64 = AtomicU64::new(1);
337
338pub type PressId = u64;
340
341#[derive(Clone, Copy, Debug, PartialEq)]
349pub enum Interaction {
350 Press(PressId, Vec2),
353 Release(PressId),
355 Cancel(PressId),
358 HoverEnter,
359 HoverLeave,
360 Focus,
361 Unfocus,
362 DragStart,
363 DragStop,
364 DragCancel,
365}
366
367impl Interaction {
368 #[inline]
370 pub fn new_press(position: Vec2) -> Self {
371 Interaction::Press(PRESS_COUNTER.fetch_add(1, Ordering::Relaxed), position)
372 }
373}
374
375#[derive(Clone)]
382pub struct InteractionSource {
383 pub(crate) state: Rc<RefCell<InteractionState>>,
384}
385
386impl InteractionSource {
387 pub fn collect_is_pressed(&self) -> bool {
388 !self.state.borrow().active_presses.is_empty()
389 }
390 pub fn collect_is_hovered(&self) -> bool {
391 self.state.borrow().hovered
392 }
393 pub fn collect_is_focused(&self) -> bool {
394 self.state.borrow().focused
395 }
396 pub fn collect_is_dragged(&self) -> bool {
397 self.state.borrow().dragged > 0
398 }
399 pub fn collect_last_press_position(&self) -> Option<Vec2> {
400 self.state.borrow().last_press_position
401 }
402 pub fn collect_last_press_id(&self) -> Option<PressId> {
403 self.state.borrow().last_press_id
404 }
405 pub fn stable_id(&self) -> *const () {
407 Rc::as_ptr(&self.state) as *const ()
408 }
409 pub fn to_mutable(&self) -> MutableInteractionSource {
413 MutableInteractionSource {
414 state: self.state.clone(),
415 }
416 }
417
418 pub fn reset(&self) {
420 self.to_mutable().reset();
421 }
422
423 pub fn reset_hover(&self) {
425 self.to_mutable().reset_hover();
426 }
427}
428
429#[derive(Clone)]
439pub struct MutableInteractionSource {
440 pub(crate) state: Rc<RefCell<InteractionState>>,
441}
442
443impl std::fmt::Debug for MutableInteractionSource {
444 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
445 f.debug_struct("MutableInteractionSource")
446 .finish_non_exhaustive()
447 }
448}
449
450impl MutableInteractionSource {
451 pub fn new() -> Self {
452 Self {
453 state: Rc::new(RefCell::new(InteractionState::default())),
454 }
455 }
456
457 pub fn emit(&self, interaction: Interaction) {
459 let changed = {
460 let mut s = self.state.borrow_mut();
461 match interaction {
462 Interaction::Press(id, pos) => {
463 let inserted = s.active_presses.insert(id);
464 s.last_press_id = Some(id);
465 s.last_press_position = Some(pos);
466 inserted
467 }
468 Interaction::Release(id) | Interaction::Cancel(id) => {
469 if s.active_presses.remove(&id) {
470 true
471 } else if id == 0 {
472 if let Some(any) = s.active_presses.iter().next().copied() {
473 s.active_presses.remove(&any);
474 true
475 } else {
476 false
477 }
478 } else {
479 false
480 }
481 }
482 Interaction::HoverEnter => {
483 let changed = !s.hovered;
484 s.hovered = true;
485 changed
486 }
487 Interaction::HoverLeave => {
488 let changed = s.hovered;
489 s.hovered = false;
490 if !s.active_presses.is_empty() {
492 s.active_presses.clear();
493 true
494 } else {
495 changed
496 }
497 }
498 Interaction::Focus => {
499 let changed = !s.focused;
500 s.focused = true;
501 changed
502 }
503 Interaction::Unfocus => {
504 let changed = s.focused;
505 s.focused = false;
506 changed
507 }
508 Interaction::DragStart => {
509 let changed = s.dragged == 0;
510 s.dragged = s.dragged.saturating_add(1);
511 changed
512 }
513 Interaction::DragStop | Interaction::DragCancel => {
514 let was = s.dragged;
515 s.dragged = s.dragged.saturating_sub(1);
516 was != s.dragged
517 }
518 }
519 };
520 if changed {
521 crate::frame_clock::request_frame();
523 }
524 }
525
526 pub fn source(&self) -> InteractionSource {
528 InteractionSource {
529 state: self.state.clone(),
530 }
531 }
532
533 pub fn reset(&self) {
535 let mut s = self.state.borrow_mut();
536 *s = InteractionState::default();
537 crate::frame_clock::request_frame();
538 }
539
540 pub fn reset_hover(&self) {
542 let mut s = self.state.borrow_mut();
543 if s.hovered {
544 s.hovered = false;
545 crate::frame_clock::request_frame();
546 }
547 }
548}
549
550impl Default for MutableInteractionSource {
551 fn default() -> Self {
552 Self::new()
553 }
554}
555
556#[derive(Clone, Default)]
557pub(crate) struct InteractionState {
558 active_presses: HashSet<PressId>,
560 hovered: bool,
561 focused: bool,
562 dragged: u32,
563 pub(crate) last_press_position: Option<Vec2>,
565 pub(crate) last_press_id: Option<PressId>,
567}
568
569#[derive(Clone, Default)]
570pub struct Modifier {
571 pub key: Option<u64>,
577
578 pub size: Option<Size>,
579 pub width: Option<f32>,
580 pub height: Option<f32>,
581 pub required_size: Option<Size>,
582 pub fill_max: Option<f32>,
583 pub fill_max_w: Option<f32>,
584 pub fill_max_h: Option<f32>,
585 pub padding: Option<f32>,
586 pub padding_values: Option<PaddingValues>,
587 pub min_width: Option<f32>,
588 pub min_height: Option<f32>,
589 pub max_width: Option<f32>,
590 pub max_height: Option<f32>,
591 pub required_min_width: Option<f32>,
593 pub required_max_width: Option<f32>,
595 pub required_min_height: Option<f32>,
597 pub required_max_height: Option<f32>,
599 pub default_min_width: Option<f32>,
602 pub default_min_height: Option<f32>,
603 pub background: Option<Brush>,
604 pub state_colors: Option<StateColors>,
605 pub state_elevation: Option<StateElevation>,
606
607 pub border: Option<Border>,
608 pub flex_grow: Option<f32>,
609 pub flex_shrink: Option<f32>,
610 pub flex_basis: Option<f32>,
611 pub flex_wrap: Option<FlexWrap>,
612 pub flex_dir: Option<FlexDirection>,
613 pub gap: Option<f32>,
614 pub row_gap: Option<f32>,
615 pub column_gap: Option<f32>,
616 pub align_self: Option<AlignSelf>,
617 pub justify_content: Option<JustifyContent>,
618 pub align_items_container: Option<AlignItems>,
619 pub align_content: Option<AlignContent>,
620 pub clip_rounded: Option<[f32; 4]>,
621 pub clip_rect: Option<ClipRect>,
624 pub overflow: Option<Overflow>,
629 pub z_index: f32,
631 pub render_z_index: Option<f32>,
633 pub hit_passthrough: bool,
635 pub input_blocker: bool,
637 pub repaint_boundary: bool,
638 pub click: bool,
639 pub disabled: bool,
641 pub focusable: Option<bool>,
645 pub propagate_min: bool,
647 pub focus_group: bool,
650 pub on_scroll: Option<Rc<dyn Fn(Vec2) -> Vec2>>,
651 pub scroll: Option<crate::scroll::ScrollBinding>,
657 pub nested_scroll_connection: Option<crate::nested_scroll::NestedScrollConnection>,
666 pub on_pointer_down: Option<Rc<dyn Fn(PointerEvent)>>,
667 pub on_pointer_move: Option<Rc<dyn Fn(PointerEvent)>>,
668 pub on_pointer_up: Option<Rc<dyn Fn(PointerEvent)>>,
669 pub on_pointer_cancel: Option<Rc<dyn Fn(PointerEvent)>>,
670 pub on_pointer_enter: Option<Rc<dyn Fn(PointerEvent)>>,
671 pub on_pointer_leave: Option<Rc<dyn Fn(PointerEvent)>>,
672 pub on_click: Option<Rc<dyn Fn()>>,
674 pub on_double_click: Option<Rc<dyn Fn()>>,
676 pub on_long_click: Option<Rc<dyn Fn()>>,
678 pub on_globally_positioned: Option<Rc<dyn Fn(crate::Rect)>>,
681 pub on_size_changed: Option<Rc<dyn Fn(crate::Vec2)>>,
684 pub on_key_event: Option<Rc<dyn Fn(crate::input::KeyEvent) -> bool>>,
687 pub on_preview_key_event: Option<Rc<dyn Fn(crate::input::KeyEvent) -> bool>>,
690 pub blur: Option<BlurStyle>,
695 pub layout: Option<Rc<dyn Fn(LayoutConstraints) -> (f32, f32)>>,
700 pub semantics: Option<crate::Semantics>,
701 pub alpha: Option<f32>,
702 pub graphics_layer: Option<f32>,
703 pub shadow: Option<ShadowSpec>,
704 pub transform: Option<Transform>,
705 pub grid: Option<GridConfig>,
706 pub grid_col_span: Option<u16>,
707 pub grid_row_span: Option<u16>,
708 pub position_type: Option<PositionType>,
709 pub offset_left: Option<f32>,
710 pub offset_right: Option<f32>,
711 pub offset_top: Option<f32>,
712 pub offset_bottom: Option<f32>,
713
714 pub margin_left: Option<f32>,
715 pub margin_right: Option<f32>,
716 pub margin_top: Option<f32>,
717 pub margin_bottom: Option<f32>,
718 pub aspect_ratio: Option<f32>,
719 pub intrinsic_width: Option<IntrinsicSize>,
721 pub intrinsic_height: Option<IntrinsicSize>,
723 pub painter: Option<Rc<dyn Fn(&mut crate::Scene, crate::Rect, f32)>>,
724
725 pub on_drag_start: Option<Rc<dyn Fn(crate::dnd::DragStart) -> Option<crate::dnd::DragPayload>>>,
727 pub on_drag_end: Option<Rc<dyn Fn(crate::dnd::DragEnd)>>,
728 pub on_drag_enter: Option<Rc<dyn Fn(crate::dnd::DragOver)>>,
729 pub on_drag_over: Option<Rc<dyn Fn(crate::dnd::DragOver)>>,
730 pub on_drag_leave: Option<Rc<dyn Fn(crate::dnd::DragOver)>>,
731 pub on_drop: Option<Rc<dyn Fn(crate::dnd::DropEvent) -> bool>>,
732 pub drag_preview: Option<crate::dnd::DragPreview>,
734
735 pub on_action: Option<Rc<dyn Fn(crate::shortcuts::Action) -> bool>>,
736
737 pub cursor: Option<crate::CursorIcon>,
739
740 pub animate_content_size: Option<AnimationSpec>,
743
744 pub focus_requester: Option<crate::runtime::FocusRequester>,
748
749 pub on_focus_changed: Option<Rc<dyn Fn(bool)>>,
752
753 pub interaction_source: Option<InteractionSource>,
760
761 pub text_input: Option<TextInputConfig>,
763
764 pub indication: Option<Rc<dyn IndicationNodeFactory>>,
766}
767
768impl std::fmt::Debug for Modifier {
769 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
770 let mut s = f.debug_struct("Modifier");
771
772 macro_rules! opt_val {
773 ($($name:ident),+ $(,)?) => {
774 $( if self.$name.is_some() { s.field(stringify!($name), &self.$name); } )+
775 };
776 }
777 if self.indication.is_some() {
778 s.field("indication", &"…");
779 }
780
781 opt_val!(
782 key,
783 size,
784 width,
785 height,
786 required_size,
787 padding,
788 padding_values,
789 min_width,
790 min_height,
791 max_width,
792 max_height,
793 required_min_width,
794 required_max_width,
795 required_min_height,
796 required_max_height,
797 default_min_width,
798 default_min_height,
799 fill_max,
800 fill_max_w,
801 fill_max_h,
802 background,
803 state_colors,
804 state_elevation,
805 border,
806 flex_grow,
807 flex_shrink,
808 flex_basis,
809 flex_wrap,
810 flex_dir,
811 gap,
812 row_gap,
813 column_gap,
814 align_self,
815 justify_content,
816 align_items_container,
817 align_content,
818 clip_rounded,
819 clip_rect,
820 render_z_index,
821 semantics,
822 alpha,
823 transform,
824 grid,
825 grid_col_span,
826 grid_row_span,
827 position_type,
828 offset_left,
829 offset_right,
830 offset_top,
831 offset_bottom,
832 margin_left,
833 margin_right,
834 margin_top,
835 margin_bottom,
836 aspect_ratio,
837 intrinsic_width,
838 intrinsic_height,
839 cursor,
840 animate_content_size,
841 blur,
842 );
843
844 macro_rules! opt_cb {
845 ($($name:ident),+ $(,)?) => {
846 $( if self.$name.is_some() { s.field(stringify!($name), &"…"); } )+
847 };
848 }
849 opt_cb!(
850 on_scroll,
851 scroll,
852 nested_scroll_connection,
853 on_pointer_down,
854 on_pointer_move,
855 on_pointer_up,
856 on_pointer_cancel,
857 on_pointer_enter,
858 on_pointer_leave,
859 on_click,
860 on_double_click,
861 on_long_click,
862 on_globally_positioned,
863 on_size_changed,
864 on_key_event,
865 on_preview_key_event,
866 painter,
867 on_drag_start,
868 on_drag_end,
869 on_drag_enter,
870 on_drag_over,
871 on_drag_leave,
872 on_drop,
873 drag_preview,
874 on_action,
875 on_focus_changed,
876 interaction_source,
877 text_input,
878 layout,
879 );
880
881 macro_rules! flag {
882 ($($name:ident),+ $(,)?) => {
883 $( if self.$name { s.field(stringify!($name), &true); } )+
884 };
885 }
886 flag!(
887 hit_passthrough,
888 input_blocker,
889 repaint_boundary,
890 click,
891 disabled,
892 propagate_min,
893 focus_group,
894 );
895
896 if let Some(f) = self.focusable {
897 s.field("focusable", &f);
898 }
899 if self.z_index != 0.0 {
900 s.field("z_index", &self.z_index);
901 }
902
903 s.finish()
904 }
905}
906
907impl_option_fields!(Modifier);
908
909#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
913pub enum Alignment {
914 TopStart,
915 TopCenter,
916 TopEnd,
917 CenterStart,
918 #[default]
919 Center,
920 CenterEnd,
921 BottomStart,
922 BottomCenter,
923 BottomEnd,
924}
925
926impl Alignment {
927 pub fn to_flex(self) -> (AlignItems, JustifyContent) {
929 use AlignItems as AI;
930 use JustifyContent as JC;
931 match self {
932 Self::TopStart => (AI::START, JC::START),
933 Self::TopCenter => (AI::START, JC::CENTER),
934 Self::TopEnd => (AI::START, JC::END),
935 Self::CenterStart => (AI::CENTER, JC::START),
936 Self::Center => (AI::CENTER, JC::CENTER),
937 Self::CenterEnd => (AI::CENTER, JC::END),
938 Self::BottomStart => (AI::END, JC::START),
939 Self::BottomCenter => (AI::END, JC::CENTER),
940 Self::BottomEnd => (AI::END, JC::END),
941 }
942 }
943}
944
945impl Modifier {
946 pub fn new() -> Self {
947 Self::default()
948 }
949
950 pub fn key(mut self, key: u64) -> Self {
953 self.key = Some(key);
954 self
955 }
956
957 pub fn size(mut self, w: f32, h: f32) -> Self {
958 self.size = Some(Size {
959 width: w,
960 height: h,
961 });
962 self
963 }
964 pub fn width(mut self, w: f32) -> Self {
965 self.width = Some(w);
966 self
967 }
968 pub fn height(mut self, h: f32) -> Self {
969 self.height = Some(h);
970 self
971 }
972 pub fn required_size(mut self, w: f32, h: f32) -> Self {
977 self.required_size = Some(Size {
978 width: w,
979 height: h,
980 });
981 self
982 }
983 pub fn required_width_in(mut self, min: f32, max: f32) -> Self {
984 self.required_min_width = Some(min.max(0.0));
985 self.required_max_width = Some(max.max(0.0));
986 self
987 }
988 pub fn required_height_in(mut self, min: f32, max: f32) -> Self {
989 self.required_min_height = Some(min.max(0.0));
990 self.required_max_height = Some(max.max(0.0));
991 self
992 }
993 pub fn required_min_width(mut self, w: f32) -> Self {
994 self.required_min_width = Some(w.max(0.0));
995 self
996 }
997 pub fn required_max_width(mut self, w: f32) -> Self {
998 self.required_max_width = Some(w.max(0.0));
999 self
1000 }
1001 pub fn required_min_height(mut self, h: f32) -> Self {
1002 self.required_min_height = Some(h.max(0.0));
1003 self
1004 }
1005 pub fn required_max_height(mut self, h: f32) -> Self {
1006 self.required_max_height = Some(h.max(0.0));
1007 self
1008 }
1009 pub fn default_min_size(mut self, w: f32, h: f32) -> Self {
1011 self.default_min_width = Some(w.max(0.0));
1012 self.default_min_height = Some(h.max(0.0));
1013 self
1014 }
1015 pub fn fill_max_size(mut self) -> Self {
1018 self.fill_max = Some(1.0);
1019 self
1020 }
1021 pub fn fill_max_size_frac(mut self, fraction: f32) -> Self {
1022 self.fill_max = Some(fraction.clamp(0.0, 1.0));
1023 self
1024 }
1025 pub fn fill_max_width(mut self) -> Self {
1027 self.fill_max_w = Some(1.0);
1028 self
1029 }
1030 pub fn fill_max_width_frac(mut self, fraction: f32) -> Self {
1031 self.fill_max_w = Some(fraction.clamp(0.0, 1.0));
1032 self
1033 }
1034 pub fn fill_max_height(mut self) -> Self {
1036 self.fill_max_h = Some(1.0);
1037 self
1038 }
1039 pub fn fill_max_height_frac(mut self, fraction: f32) -> Self {
1040 self.fill_max_h = Some(fraction.clamp(0.0, 1.0));
1041 self
1042 }
1043 pub fn padding(mut self, v: f32) -> Self {
1044 self.padding = Some(v);
1045 self
1046 }
1047 pub fn padding_values(mut self, padding: PaddingValues) -> Self {
1048 self.padding_values = Some(padding);
1049 self
1050 }
1051 pub fn ime_padding(mut self) -> Self {
1054 let insets = crate::locals::window_insets();
1055 let scale = crate::locals::density().scale * crate::locals::ui_scale().0;
1056 let mut p = self.padding_values.unwrap_or_default();
1057 p.bottom += insets.ime_bottom / scale;
1058 self.padding_values = Some(p);
1059 self
1060 }
1061 pub fn system_bars_padding(mut self) -> Self {
1063 let insets = crate::locals::window_insets();
1064 let scale = crate::locals::density().scale * crate::locals::ui_scale().0;
1065 let mut p = self.padding_values.unwrap_or_default();
1066 p.top += insets.top / scale;
1067 p.bottom += insets.bottom / scale;
1068 self.padding_values = Some(p);
1069 self
1070 }
1071 pub fn status_bars_padding(mut self) -> Self {
1073 let insets = crate::locals::window_insets();
1074 let scale = crate::locals::density().scale * crate::locals::ui_scale().0;
1075 let mut p = self.padding_values.unwrap_or_default();
1076 p.top += insets.top / scale;
1077 self.padding_values = Some(p);
1078 self
1079 }
1080 pub fn navigation_bars_padding(mut self) -> Self {
1082 let insets = crate::locals::window_insets();
1083 let scale = crate::locals::density().scale * crate::locals::ui_scale().0;
1084 let mut p = self.padding_values.unwrap_or_default();
1085 p.bottom += insets.bottom / scale;
1086 self.padding_values = Some(p);
1087 self
1088 }
1089 pub fn min_size(mut self, w: f32, h: f32) -> Self {
1090 self.min_width = Some(w);
1091 self.min_height = Some(h);
1092 self
1093 }
1094 pub fn max_size(mut self, w: f32, h: f32) -> Self {
1095 self.max_width = Some(w);
1096 self.max_height = Some(h);
1097 self
1098 }
1099 pub fn min_width(mut self, w: f32) -> Self {
1100 self.min_width = Some(w);
1101 self
1102 }
1103 pub fn min_height(mut self, h: f32) -> Self {
1104 self.min_height = Some(h);
1105 self
1106 }
1107 pub fn max_width(mut self, w: f32) -> Self {
1108 self.max_width = Some(w);
1109 self
1110 }
1111 pub fn max_height(mut self, h: f32) -> Self {
1112 self.max_height = Some(h);
1113 self
1114 }
1115 pub fn background(mut self, color: Color) -> Self {
1117 self.background = Some(Brush::Solid(color));
1118 self
1119 }
1120 pub fn background_brush(mut self, brush: Brush) -> Self {
1122 self.background = Some(brush);
1123 self
1124 }
1125 pub fn border(mut self, width: f32, color: Color, radius: f32) -> Self {
1126 self.border = Some(Border {
1127 width,
1128 color,
1129 radius: [radius; 4],
1130 });
1131 self
1132 }
1133 pub fn border_radii(mut self, width: f32, color: Color, radii: [f32; 4]) -> Self {
1134 self.border = Some(Border {
1135 width,
1136 color,
1137 radius: radii,
1138 });
1139 self
1140 }
1141 pub fn flex_grow(mut self, v: f32) -> Self {
1142 self.flex_grow = Some(v);
1143 self
1144 }
1145 pub fn flex_shrink(mut self, v: f32) -> Self {
1146 self.flex_shrink = Some(v);
1147 self
1148 }
1149 pub fn flex_basis(mut self, v: f32) -> Self {
1150 self.flex_basis = Some(v);
1151 self
1152 }
1153 pub fn flex_wrap(mut self, w: FlexWrap) -> Self {
1154 self.flex_wrap = Some(w);
1155 self
1156 }
1157 pub fn flex_dir(mut self, d: FlexDirection) -> Self {
1158 self.flex_dir = Some(d);
1159 self
1160 }
1161 pub fn gap(mut self, v: f32) -> Self {
1162 let v = v.max(0.0);
1163 self.gap = Some(v);
1164 self.row_gap = Some(v);
1165 self.column_gap = Some(v);
1166 self
1167 }
1168 pub fn row_gap(mut self, v: f32) -> Self {
1169 self.row_gap = Some(v.max(0.0));
1170 self
1171 }
1172 pub fn column_gap(mut self, v: f32) -> Self {
1173 self.column_gap = Some(v.max(0.0));
1174 self
1175 }
1176 pub fn align_self(mut self, a: AlignSelf) -> Self {
1177 self.align_self = Some(a);
1178 self
1179 }
1180 pub fn align_self_center(mut self) -> Self {
1181 self.align_self = Some(AlignSelf::CENTER);
1182 self
1183 }
1184 pub fn justify_content(mut self, j: JustifyContent) -> Self {
1185 self.justify_content = Some(j);
1186 self
1187 }
1188 pub fn align_items(mut self, a: AlignItems) -> Self {
1189 self.align_items_container = Some(a);
1190 self
1191 }
1192 pub fn content_alignment(self, alignment: Alignment) -> Self {
1195 let (ai, jc) = alignment.to_flex();
1196 self.align_items(ai).justify_content(jc)
1197 }
1198 pub fn align_content(mut self, a: AlignContent) -> Self {
1199 self.align_content = Some(a);
1200 self
1201 }
1202 pub fn clip_rounded(mut self, radius: f32) -> Self {
1203 self.clip_rounded = Some([radius; 4]);
1204 self
1205 }
1206 pub fn clip_rounded_radii(mut self, radii: [f32; 4]) -> Self {
1207 self.clip_rounded = Some(radii);
1208 self
1209 }
1210 pub fn clip_rect(mut self, left: f32, top: f32, right: f32, bottom: f32, op: ClipOp) -> Self {
1213 self.clip_rect = Some(ClipRect {
1214 left,
1215 top,
1216 right,
1217 bottom,
1218 op,
1219 });
1220 self
1221 }
1222 pub fn overflow(mut self, overflow: Overflow) -> Self {
1223 self.overflow = Some(overflow);
1224 self
1225 }
1226 pub fn z_index(mut self, z: f32) -> Self {
1227 self.z_index = z;
1228 self
1229 }
1230
1231 pub fn render_z_index(mut self, z: f32) -> Self {
1234 self.render_z_index = Some(z);
1235 self
1236 }
1237
1238 pub fn input_blocker(mut self) -> Self {
1240 self.input_blocker = true;
1241 self
1242 }
1243
1244 pub fn hit_passthrough(mut self) -> Self {
1245 self.hit_passthrough = true;
1246 self
1247 }
1248 pub fn clickable(mut self) -> Self {
1249 self.click = true;
1250 if self.indication.is_none() {
1251 self.indication = crate::locals::local_indication();
1252 }
1253 self
1254 }
1255 pub fn clickable_with_source(mut self, source: &MutableInteractionSource) -> Self {
1258 self.click = true;
1259 self.interaction_source = Some(source.source());
1260 if self.indication.is_none() {
1261 self.indication = crate::locals::local_indication();
1262 }
1263 self
1264 }
1265 pub fn state_colors(mut self, colors: StateColors) -> Self {
1268 self.state_colors = Some(colors);
1269 self
1270 }
1271 pub fn state_elevation(mut self, elev: StateElevation) -> Self {
1273 self.state_elevation = Some(elev);
1274 self
1275 }
1276 pub fn disabled(mut self) -> Self {
1278 self.disabled = true;
1279 self
1280 }
1281 pub fn enabled(mut self, enabled: bool) -> Self {
1283 self.disabled = !enabled;
1284 self
1285 }
1286 pub fn focusable(mut self, focusable: bool) -> Self {
1291 self.focusable = Some(focusable);
1292 self
1293 }
1294 pub fn focus_group(mut self) -> Self {
1297 self.focus_group = true;
1298 self
1299 }
1300 pub fn interaction_source(mut self, source: &MutableInteractionSource) -> Self {
1311 self.interaction_source = Some(source.source());
1312 self
1313 }
1314 pub fn hoverable(
1317 mut self,
1318 on_enter: impl Fn() + 'static,
1319 on_leave: impl Fn() + 'static,
1320 ) -> Self {
1321 self.on_pointer_enter = Some(Rc::new(move |_| on_enter()));
1322 self.on_pointer_leave = Some(Rc::new(move |_| on_leave()));
1323 self
1324 }
1325 pub fn hoverable_with_source(mut self, source: &MutableInteractionSource) -> Self {
1329 self.interaction_source = Some(source.source());
1330 self
1331 }
1332 pub fn propagate_min_constraints(mut self, propagate: bool) -> Self {
1335 self.propagate_min = propagate;
1336 self
1337 }
1338 pub fn on_scroll(mut self, f: impl Fn(Vec2) -> Vec2 + 'static) -> Self {
1339 self.on_scroll = Some(Rc::new(f));
1340 self
1341 }
1342 pub fn vertical_scroll(mut self, binding: crate::scroll::ScrollAxisBinding) -> Self {
1346 self.scroll = Some(crate::scroll::ScrollBinding::Vertical(binding));
1347 self
1348 }
1349 pub fn horizontal_scroll(mut self, binding: crate::scroll::ScrollAxisBinding) -> Self {
1351 self.scroll = Some(crate::scroll::ScrollBinding::Horizontal(binding));
1352 self
1353 }
1354 pub fn scrollable(mut self, binding: crate::scroll::ScrollBothBinding) -> Self {
1356 self.scroll = Some(crate::scroll::ScrollBinding::Both(binding));
1357 self
1358 }
1359 pub fn nested_scroll(mut self, conn: crate::nested_scroll::NestedScrollConnection) -> Self {
1366 self.nested_scroll_connection = Some(conn);
1367 self
1368 }
1369 pub fn on_pointer_down(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
1370 self.on_pointer_down = Some(Rc::new(f));
1371 self
1372 }
1373 pub fn on_pointer_move(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
1374 self.on_pointer_move = Some(Rc::new(f));
1375 self
1376 }
1377 pub fn on_pointer_up(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
1378 self.on_pointer_up = Some(Rc::new(f));
1379 self
1380 }
1381 pub fn on_pointer_cancel(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
1382 self.on_pointer_cancel = Some(Rc::new(f));
1383 self
1384 }
1385 pub fn on_pointer_enter(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
1386 self.on_pointer_enter = Some(Rc::new(f));
1387 self
1388 }
1389 pub fn on_pointer_leave(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
1390 self.on_pointer_leave = Some(Rc::new(f));
1391 self
1392 }
1393 pub fn on_click(mut self, f: impl Fn() + 'static) -> Self {
1394 self.on_click = Some(Rc::new(f));
1395 self.click = true;
1396 self
1397 }
1398 pub fn on_double_click(mut self, f: impl Fn() + 'static) -> Self {
1399 self.on_double_click = Some(Rc::new(f));
1400 self
1401 }
1402 pub fn on_long_click(mut self, f: impl Fn() + 'static) -> Self {
1403 self.on_long_click = Some(Rc::new(f));
1404 self
1405 }
1406 pub fn semantics(mut self, s: crate::Semantics) -> Self {
1407 self.semantics = Some(s);
1408 self
1409 }
1410 pub fn alpha(mut self, a: f32) -> Self {
1411 self.alpha = Some(a);
1412 self
1413 }
1414 pub fn graphics_layer(mut self, alpha: f32) -> Self {
1419 self.graphics_layer = Some(alpha.clamp(0.0, 1.0));
1420 self
1421 }
1422 pub fn shadow(mut self, blur_radius: f32, offset_y: f32) -> Self {
1426 self.shadow = Some(ShadowSpec {
1427 blur_radius: blur_radius.max(0.0),
1428 offset_y,
1429 color: Color(0, 0, 0, 64),
1430 });
1431 self
1432 }
1433 pub fn shadow_with_color(mut self, blur_radius: f32, offset_y: f32, color: Color) -> Self {
1435 self.shadow = Some(ShadowSpec {
1436 blur_radius: blur_radius.max(0.0),
1437 offset_y,
1438 color,
1439 });
1440 self
1441 }
1442 pub fn elevation(mut self, level: f32) -> Self {
1446 if level <= 0.0 {
1447 self.shadow = None;
1448 return self;
1449 }
1450 self.shadow = Some(ShadowSpec {
1451 blur_radius: level * 2.0,
1452 offset_y: level * 0.5,
1453 color: Color(0, 0, 0, (level * 8.0).clamp(8.0, 80.0) as u8),
1454 });
1455 self
1456 }
1457 pub fn transform(mut self, t: Transform) -> Self {
1458 self.transform = Some(t);
1459 self
1460 }
1461 pub fn grid(mut self, columns: usize, row_gap: f32, column_gap: f32) -> Self {
1462 self.grid = Some(GridConfig {
1463 columns,
1464 row_gap,
1465 column_gap,
1466 });
1467 self
1468 }
1469 pub fn grid_span(mut self, col_span: u16, row_span: u16) -> Self {
1470 self.grid_col_span = Some(col_span);
1471 self.grid_row_span = Some(row_span);
1472 self
1473 }
1474 pub fn absolute(mut self) -> Self {
1475 self.position_type = Some(PositionType::Absolute);
1476 self
1477 }
1478 pub fn offset(
1479 mut self,
1480 left: Option<f32>,
1481 top: Option<f32>,
1482 right: Option<f32>,
1483 bottom: Option<f32>,
1484 ) -> Self {
1485 self.offset_left = left;
1486 self.offset_top = top;
1487 self.offset_right = right;
1488 self.offset_bottom = bottom;
1489 self
1490 }
1491 pub fn offset_left(mut self, v: f32) -> Self {
1492 self.offset_left = Some(v);
1493 self
1494 }
1495 pub fn offset_right(mut self, v: f32) -> Self {
1496 self.offset_right = Some(v);
1497 self
1498 }
1499 pub fn offset_top(mut self, v: f32) -> Self {
1500 self.offset_top = Some(v);
1501 self
1502 }
1503 pub fn offset_bottom(mut self, v: f32) -> Self {
1504 self.offset_bottom = Some(v);
1505 self
1506 }
1507 pub fn margin(mut self, v: f32) -> Self {
1508 self.margin_left = Some(v);
1509 self.margin_right = Some(v);
1510 self.margin_top = Some(v);
1511 self.margin_bottom = Some(v);
1512 self
1513 }
1514
1515 pub fn margin_horizontal(mut self, v: f32) -> Self {
1516 self.margin_left = Some(v);
1517 self.margin_right = Some(v);
1518 self
1519 }
1520
1521 pub fn margin_vertical(mut self, v: f32) -> Self {
1522 self.margin_top = Some(v);
1523 self.margin_bottom = Some(v);
1524 self
1525 }
1526 pub fn aspect_ratio(mut self, ratio: f32) -> Self {
1527 self.aspect_ratio = Some(ratio);
1528 self
1529 }
1530 pub fn intrinsic_width(mut self, mode: IntrinsicSize) -> Self {
1532 self.intrinsic_width = Some(mode);
1533 self
1534 }
1535 pub fn intrinsic_height(mut self, mode: IntrinsicSize) -> Self {
1537 self.intrinsic_height = Some(mode);
1538 self
1539 }
1540 pub fn painter(mut self, f: impl Fn(&mut crate::Scene, crate::Rect, f32) + 'static) -> Self {
1541 self.painter = Some(Rc::new(f));
1542 self
1543 }
1544 pub fn scale(self, s: f32) -> Self {
1545 self.scale2(s, s)
1546 }
1547 pub fn scale2(mut self, sx: f32, sy: f32) -> Self {
1548 let mut t = self.transform.unwrap_or_else(Transform::identity);
1549 t.scale_x *= sx;
1550 t.scale_y *= sy;
1551 self.transform = Some(t);
1552 self
1553 }
1554 pub fn translate(mut self, x: f32, y: f32) -> Self {
1555 let t = self.transform.unwrap_or_else(Transform::identity);
1556 self.transform = Some(t.combine(&Transform::translate(x, y)));
1557 self
1558 }
1559 pub fn translate_vec2(self, v: Vec2) -> Self {
1560 self.translate(v.x, v.y)
1561 }
1562 pub fn rotate(mut self, radians: f32) -> Self {
1563 let mut t = self.transform.unwrap_or_else(Transform::identity);
1564 t.rotate += radians;
1565 self.transform = Some(t);
1566 self
1567 }
1568 pub fn transform_origin(mut self, x: f32, y: f32) -> Self {
1569 let mut t = self.transform.unwrap_or_else(Transform::identity);
1570 t.origin_x = x;
1571 t.origin_y = y;
1572 self.transform = Some(t);
1573 self
1574 }
1575 pub fn weight(mut self, w: f32) -> Self {
1576 let w = w.max(0.0);
1577 self.flex_grow = Some(w);
1578 self.flex_shrink = Some(1.0);
1579 self.flex_basis = Some(0.0);
1581 self
1582 }
1583 pub fn repaint_boundary(mut self) -> Self {
1587 self.repaint_boundary = true;
1588 self
1589 }
1590 pub fn on_action(mut self, f: impl Fn(crate::shortcuts::Action) -> bool + 'static) -> Self {
1591 self.on_action = Some(Rc::new(f));
1592 self
1593 }
1594
1595 pub fn on_drag_start(
1597 mut self,
1598 f: impl Fn(crate::dnd::DragStart) -> Option<crate::dnd::DragPayload> + 'static,
1599 ) -> Self {
1600 self.on_drag_start = Some(Rc::new(f));
1601 self
1602 }
1603
1604 pub fn on_drag_end(mut self, f: impl Fn(crate::dnd::DragEnd) + 'static) -> Self {
1606 self.on_drag_end = Some(Rc::new(f));
1607 self
1608 }
1609
1610 pub fn on_drag_enter(mut self, f: impl Fn(crate::dnd::DragOver) + 'static) -> Self {
1612 self.on_drag_enter = Some(Rc::new(f));
1613 self
1614 }
1615
1616 pub fn on_drag_over(mut self, f: impl Fn(crate::dnd::DragOver) + 'static) -> Self {
1618 self.on_drag_over = Some(Rc::new(f));
1619 self
1620 }
1621
1622 pub fn on_drag_leave(mut self, f: impl Fn(crate::dnd::DragOver) + 'static) -> Self {
1624 self.on_drag_leave = Some(Rc::new(f));
1625 self
1626 }
1627
1628 pub fn on_drop(mut self, f: impl Fn(crate::dnd::DropEvent) -> bool + 'static) -> Self {
1631 self.on_drop = Some(Rc::new(f));
1632 self
1633 }
1634
1635 pub fn draw_drag_decoration(
1640 mut self,
1641 f: impl Fn(&mut crate::Scene, &crate::dnd::DragPreviewCtx) + 'static,
1642 ) -> Self {
1643 self.drag_preview = Some(Rc::new(f));
1644 self
1645 }
1646
1647 pub fn draw_drag_decoration_rc(mut self, preview: crate::dnd::DragPreview) -> Self {
1649 self.drag_preview = Some(preview);
1650 self
1651 }
1652
1653 pub fn drag_preview_label(self, label: impl Into<String>, accent: crate::Color) -> Self {
1655 self.draw_drag_decoration_rc(crate::dnd::drag_preview_label(label, accent))
1656 }
1657
1658 pub fn drag_preview_chip(self, label: impl Into<String>, accent: crate::Color) -> Self {
1660 self.draw_drag_decoration_rc(crate::dnd::drag_preview_chip(label, accent))
1661 }
1662
1663 pub fn cursor(mut self, c: crate::CursorIcon) -> Self {
1665 self.cursor = Some(c);
1666 self
1667 }
1668
1669 pub fn animate_content_size(mut self, spec: AnimationSpec) -> Self {
1673 self.animate_content_size = Some(spec);
1674 self
1675 }
1676
1677 pub fn focus_requester(mut self, fr: crate::runtime::FocusRequester) -> Self {
1680 self.focus_requester = Some(fr);
1681 self
1682 }
1683
1684 pub fn focus_target(mut self) -> Self {
1687 self.focusable = Some(true);
1688 self
1689 }
1690
1691 pub fn on_focus_changed(mut self, f: impl Fn(bool) + 'static) -> Self {
1694 self.on_focus_changed = Some(Rc::new(f));
1695 self
1696 }
1697
1698 pub fn on_globally_positioned(mut self, f: impl Fn(crate::Rect) + 'static) -> Self {
1702 self.on_globally_positioned = Some(Rc::new(f));
1703 self
1704 }
1705
1706 pub fn on_size_changed(mut self, f: impl Fn(crate::Vec2) + 'static) -> Self {
1709 self.on_size_changed = Some(Rc::new(f));
1710 self
1711 }
1712
1713 pub fn on_key_event(mut self, f: impl Fn(crate::input::KeyEvent) -> bool + 'static) -> Self {
1717 self.on_key_event = Some(Rc::new(f));
1718 self
1719 }
1720
1721 pub fn on_preview_key_event(
1725 mut self,
1726 f: impl Fn(crate::input::KeyEvent) -> bool + 'static,
1727 ) -> Self {
1728 self.on_preview_key_event = Some(Rc::new(f));
1729 self
1730 }
1731
1732 pub fn blur(mut self, radius_dp: f32) -> Self {
1739 self.blur = Some(BlurStyle {
1740 radius_x: radius_dp.max(0.0),
1741 radius_y: radius_dp.max(0.0),
1742 edge_treatment: BlurredEdgeTreatment::Rectangle,
1743 });
1744 self
1745 }
1746
1747 pub fn blur_with_edge(
1752 mut self,
1753 radius_x: f32,
1754 radius_y: f32,
1755 edge_treatment: BlurredEdgeTreatment,
1756 ) -> Self {
1757 self.blur = Some(BlurStyle {
1758 radius_x: radius_x.max(0.0),
1759 radius_y: radius_y.max(0.0),
1760 edge_treatment,
1761 });
1762 self
1763 }
1764
1765 pub fn layout(mut self, f: impl Fn(LayoutConstraints) -> (f32, f32) + 'static) -> Self {
1773 self.layout = Some(Rc::new(f));
1774 self
1775 }
1776
1777 pub fn text_input(mut self, config: TextInputConfig) -> Self {
1779 self.text_input = Some(config);
1780 self
1781 }
1782
1783 pub fn indication(mut self, factory: Rc<dyn IndicationNodeFactory>) -> Self {
1787 self.indication = Some(factory);
1788 self
1789 }
1790}