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 Default for TextInputConfig {
295 fn default() -> Self {
296 Self {
297 hint: String::new(),
298 multiline: false,
299 on_change: None,
300 on_submit: None,
301 focus_tracker: None,
302 value: String::new(),
303 visual_transformation: None,
304 keyboard_type: crate::text::KeyboardType::default(),
305 capitalization: crate::text::KeyboardCapitalization::default(),
306 ime_action: crate::text::ImeAction::default(),
307 auto_correct_enabled: None,
308 enabled: true,
309 read_only: false,
310 max_lines: None,
311 min_lines: 1,
312 cursor_color: None,
313 on_text_layout: None,
314 text_style: None,
315 keyboard_actions: None,
316 interaction_source: None,
317 line_limits: None,
318 }
319 }
320}
321
322impl std::fmt::Debug for TextInputConfig {
323 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
324 let mut s = f.debug_struct("TextInputConfig");
325 s.field("hint", &self.hint);
326 s.field("multiline", &self.multiline);
327 if self.on_change.is_some() {
328 s.field("on_change", &"…");
329 }
330 if self.on_submit.is_some() {
331 s.field("on_submit", &"…");
332 }
333 if self.focus_tracker.is_some() {
334 s.field("focus_tracker", &"…");
335 }
336 s.field("value", &self.value);
337 if self.visual_transformation.is_some() {
338 s.field("visual_transformation", &"…");
339 }
340 s.field("keyboard_type", &self.keyboard_type);
341 s.field("capitalization", &self.capitalization);
342 s.field("ime_action", &self.ime_action);
343 s.field("auto_correct_enabled", &self.auto_correct_enabled);
344 s.field("enabled", &self.enabled);
345 s.field("read_only", &self.read_only);
346 s.field("max_lines", &self.max_lines);
347 s.field("min_lines", &self.min_lines);
348 s.field("cursor_color", &self.cursor_color);
349 if self.on_text_layout.is_some() {
350 s.field("on_text_layout", &"…");
351 }
352 s.finish()
353 }
354}
355
356#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
359pub enum IntrinsicSize {
360 Min,
361 Max,
362}
363
364static PRESS_COUNTER: AtomicU64 = AtomicU64::new(1);
365
366pub type PressId = u64;
368
369#[derive(Clone, Copy, Debug, PartialEq)]
377pub enum Interaction {
378 Press(PressId, Vec2),
381 Release(PressId),
383 Cancel(PressId),
386 HoverEnter,
387 HoverLeave,
388 Focus,
389 Unfocus,
390 DragStart,
391 DragStop,
392 DragCancel,
393}
394
395impl Interaction {
396 #[inline]
398 pub fn new_press(position: Vec2) -> Self {
399 Interaction::Press(PRESS_COUNTER.fetch_add(1, Ordering::Relaxed), position)
400 }
401}
402
403#[derive(Clone)]
410pub struct InteractionSource {
411 pub(crate) state: Rc<RefCell<InteractionState>>,
412}
413
414impl InteractionSource {
415 pub fn collect_is_pressed(&self) -> bool {
416 !self.state.borrow().active_presses.is_empty()
417 }
418 pub fn collect_is_hovered(&self) -> bool {
419 self.state.borrow().hovered
420 }
421 pub fn collect_is_focused(&self) -> bool {
422 self.state.borrow().focused
423 }
424 pub fn collect_is_dragged(&self) -> bool {
425 self.state.borrow().dragged > 0
426 }
427 pub fn collect_last_press_position(&self) -> Option<Vec2> {
428 self.state.borrow().last_press_position
429 }
430 pub fn collect_last_press_id(&self) -> Option<PressId> {
431 self.state.borrow().last_press_id
432 }
433 pub fn stable_id(&self) -> *const () {
435 Rc::as_ptr(&self.state) as *const ()
436 }
437 pub fn to_mutable(&self) -> MutableInteractionSource {
441 MutableInteractionSource {
442 state: self.state.clone(),
443 }
444 }
445
446 pub fn reset(&self) {
448 self.to_mutable().reset();
449 }
450
451 pub fn reset_hover(&self) {
453 self.to_mutable().reset_hover();
454 }
455}
456
457#[derive(Clone)]
467pub struct MutableInteractionSource {
468 pub(crate) state: Rc<RefCell<InteractionState>>,
469}
470
471impl std::fmt::Debug for MutableInteractionSource {
472 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
473 f.debug_struct("MutableInteractionSource")
474 .finish_non_exhaustive()
475 }
476}
477
478impl MutableInteractionSource {
479 pub fn new() -> Self {
480 Self {
481 state: Rc::new(RefCell::new(InteractionState::default())),
482 }
483 }
484
485 pub fn emit(&self, interaction: Interaction) {
487 let changed = {
488 let mut s = self.state.borrow_mut();
489 match interaction {
490 Interaction::Press(id, pos) => {
491 let inserted = s.active_presses.insert(id);
492 s.last_press_id = Some(id);
493 s.last_press_position = Some(pos);
494 inserted
495 }
496 Interaction::Release(id) | Interaction::Cancel(id) => {
497 if s.active_presses.remove(&id) {
498 true
499 } else if id == 0 {
500 if let Some(any) = s.active_presses.iter().next().copied() {
501 s.active_presses.remove(&any);
502 true
503 } else {
504 false
505 }
506 } else {
507 false
508 }
509 }
510 Interaction::HoverEnter => {
511 let changed = !s.hovered;
512 s.hovered = true;
513 changed
514 }
515 Interaction::HoverLeave => {
516 let changed = s.hovered;
517 s.hovered = false;
518 if !s.active_presses.is_empty() {
520 s.active_presses.clear();
521 true
522 } else {
523 changed
524 }
525 }
526 Interaction::Focus => {
527 let changed = !s.focused;
528 s.focused = true;
529 changed
530 }
531 Interaction::Unfocus => {
532 let changed = s.focused;
533 s.focused = false;
534 changed
535 }
536 Interaction::DragStart => {
537 let changed = s.dragged == 0;
538 s.dragged = s.dragged.saturating_add(1);
539 changed
540 }
541 Interaction::DragStop | Interaction::DragCancel => {
542 let was = s.dragged;
543 s.dragged = s.dragged.saturating_sub(1);
544 was != s.dragged
545 }
546 }
547 };
548 if changed {
549 crate::frame_clock::request_frame();
551 }
552 }
553
554 pub fn source(&self) -> InteractionSource {
556 InteractionSource {
557 state: self.state.clone(),
558 }
559 }
560
561 pub fn reset(&self) {
563 let mut s = self.state.borrow_mut();
564 *s = InteractionState::default();
565 crate::frame_clock::request_frame();
566 }
567
568 pub fn reset_hover(&self) {
570 let mut s = self.state.borrow_mut();
571 if s.hovered {
572 s.hovered = false;
573 crate::frame_clock::request_frame();
574 }
575 }
576}
577
578impl Default for MutableInteractionSource {
579 fn default() -> Self {
580 Self::new()
581 }
582}
583
584#[derive(Clone, Default)]
585pub(crate) struct InteractionState {
586 active_presses: HashSet<PressId>,
588 hovered: bool,
589 focused: bool,
590 dragged: u32,
591 pub(crate) last_press_position: Option<Vec2>,
593 pub(crate) last_press_id: Option<PressId>,
595}
596
597#[derive(Clone, Default)]
598pub struct Modifier {
599 pub key: Option<u64>,
605
606 pub size: Option<Size>,
607 pub width: Option<f32>,
608 pub height: Option<f32>,
609 pub required_size: Option<Size>,
610 pub fill_max: Option<f32>,
611 pub fill_max_w: Option<f32>,
612 pub fill_max_h: Option<f32>,
613 pub padding: Option<f32>,
614 pub padding_values: Option<PaddingValues>,
615 pub min_width: Option<f32>,
616 pub min_height: Option<f32>,
617 pub max_width: Option<f32>,
618 pub max_height: Option<f32>,
619 pub required_min_width: Option<f32>,
621 pub required_max_width: Option<f32>,
623 pub required_min_height: Option<f32>,
625 pub required_max_height: Option<f32>,
627 pub default_min_width: Option<f32>,
630 pub default_min_height: Option<f32>,
631 pub background: Option<Brush>,
632 pub state_colors: Option<StateColors>,
633 pub state_elevation: Option<StateElevation>,
634
635 pub border: Option<Border>,
636 pub flex_grow: Option<f32>,
637 pub flex_shrink: Option<f32>,
638 pub flex_basis: Option<f32>,
639 pub flex_wrap: Option<FlexWrap>,
640 pub flex_dir: Option<FlexDirection>,
641 pub gap: Option<f32>,
642 pub row_gap: Option<f32>,
643 pub column_gap: Option<f32>,
644 pub align_self: Option<AlignSelf>,
645 pub justify_content: Option<JustifyContent>,
646 pub align_items_container: Option<AlignItems>,
647 pub align_content: Option<AlignContent>,
648 pub clip_rounded: Option<[f32; 4]>,
649 pub clip_rect: Option<ClipRect>,
652 pub overflow: Option<Overflow>,
657 pub z_index: f32,
659 pub render_z_index: Option<f32>,
661 pub hit_passthrough: bool,
663 pub input_blocker: bool,
665 pub repaint_boundary: bool,
666 pub click: bool,
667 pub disabled: bool,
669 pub focusable: Option<bool>,
673 pub propagate_min: bool,
675 pub focus_group: bool,
678 pub on_scroll: Option<Rc<dyn Fn(Vec2) -> Vec2>>,
679 pub scroll: Option<crate::scroll::ScrollBinding>,
685 pub nested_scroll_connection: Option<crate::nested_scroll::NestedScrollConnection>,
694 pub on_pointer_down: Option<Rc<dyn Fn(PointerEvent)>>,
695 pub on_pointer_move: Option<Rc<dyn Fn(PointerEvent)>>,
696 pub on_pointer_up: Option<Rc<dyn Fn(PointerEvent)>>,
697 pub on_pointer_cancel: Option<Rc<dyn Fn(PointerEvent)>>,
698 pub on_pointer_enter: Option<Rc<dyn Fn(PointerEvent)>>,
699 pub on_pointer_leave: Option<Rc<dyn Fn(PointerEvent)>>,
700 pub on_click: Option<Rc<dyn Fn()>>,
702 pub on_double_click: Option<Rc<dyn Fn()>>,
704 pub on_long_click: Option<Rc<dyn Fn()>>,
706 pub on_globally_positioned: Option<Rc<dyn Fn(crate::Rect)>>,
709 pub on_size_changed: Option<Rc<dyn Fn(crate::Vec2)>>,
712 pub on_key_event: Option<Rc<dyn Fn(crate::input::KeyEvent) -> bool>>,
715 pub on_preview_key_event: Option<Rc<dyn Fn(crate::input::KeyEvent) -> bool>>,
718 pub blur: Option<BlurStyle>,
723 pub layout: Option<Rc<dyn Fn(LayoutConstraints) -> (f32, f32)>>,
728 pub semantics: Option<crate::Semantics>,
729 pub alpha: Option<f32>,
730 pub graphics_layer: Option<f32>,
731 pub shadow: Option<ShadowSpec>,
732 pub transform: Option<Transform>,
733 pub grid: Option<GridConfig>,
734 pub grid_col_span: Option<u16>,
735 pub grid_row_span: Option<u16>,
736 pub position_type: Option<PositionType>,
737 pub offset_left: Option<f32>,
738 pub offset_right: Option<f32>,
739 pub offset_top: Option<f32>,
740 pub offset_bottom: Option<f32>,
741
742 pub margin_left: Option<f32>,
743 pub margin_right: Option<f32>,
744 pub margin_top: Option<f32>,
745 pub margin_bottom: Option<f32>,
746 pub aspect_ratio: Option<f32>,
747 pub intrinsic_width: Option<IntrinsicSize>,
749 pub intrinsic_height: Option<IntrinsicSize>,
751 pub painter: Option<Rc<dyn Fn(&mut crate::Scene, crate::Rect, f32)>>,
752
753 pub on_drag_start: Option<Rc<dyn Fn(crate::dnd::DragStart) -> Option<crate::dnd::DragPayload>>>,
755 pub on_drag_end: Option<Rc<dyn Fn(crate::dnd::DragEnd)>>,
756 pub on_drag_enter: Option<Rc<dyn Fn(crate::dnd::DragOver)>>,
757 pub on_drag_over: Option<Rc<dyn Fn(crate::dnd::DragOver)>>,
758 pub on_drag_leave: Option<Rc<dyn Fn(crate::dnd::DragOver)>>,
759 pub on_drop: Option<Rc<dyn Fn(crate::dnd::DropEvent) -> bool>>,
760 pub drag_preview: Option<crate::dnd::DragPreview>,
762
763 pub on_action: Option<Rc<dyn Fn(crate::shortcuts::Action) -> bool>>,
764
765 pub cursor: Option<crate::CursorIcon>,
767
768 pub animate_content_size: Option<AnimationSpec>,
771
772 pub focus_requester: Option<crate::runtime::FocusRequester>,
776
777 pub on_focus_changed: Option<Rc<dyn Fn(bool)>>,
780
781 pub interaction_source: Option<InteractionSource>,
788
789 pub text_input: Option<TextInputConfig>,
791
792 pub indication: Option<Rc<dyn IndicationNodeFactory>>,
794}
795
796impl std::fmt::Debug for Modifier {
797 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
798 let mut s = f.debug_struct("Modifier");
799
800 macro_rules! opt_val {
801 ($($name:ident),+ $(,)?) => {
802 $( if self.$name.is_some() { s.field(stringify!($name), &self.$name); } )+
803 };
804 }
805 if self.indication.is_some() {
806 s.field("indication", &"…");
807 }
808
809 opt_val!(
810 key,
811 size,
812 width,
813 height,
814 required_size,
815 padding,
816 padding_values,
817 min_width,
818 min_height,
819 max_width,
820 max_height,
821 required_min_width,
822 required_max_width,
823 required_min_height,
824 required_max_height,
825 default_min_width,
826 default_min_height,
827 fill_max,
828 fill_max_w,
829 fill_max_h,
830 background,
831 state_colors,
832 state_elevation,
833 border,
834 flex_grow,
835 flex_shrink,
836 flex_basis,
837 flex_wrap,
838 flex_dir,
839 gap,
840 row_gap,
841 column_gap,
842 align_self,
843 justify_content,
844 align_items_container,
845 align_content,
846 clip_rounded,
847 clip_rect,
848 render_z_index,
849 semantics,
850 alpha,
851 transform,
852 grid,
853 grid_col_span,
854 grid_row_span,
855 position_type,
856 offset_left,
857 offset_right,
858 offset_top,
859 offset_bottom,
860 margin_left,
861 margin_right,
862 margin_top,
863 margin_bottom,
864 aspect_ratio,
865 intrinsic_width,
866 intrinsic_height,
867 cursor,
868 animate_content_size,
869 blur,
870 );
871
872 macro_rules! opt_cb {
873 ($($name:ident),+ $(,)?) => {
874 $( if self.$name.is_some() { s.field(stringify!($name), &"…"); } )+
875 };
876 }
877 opt_cb!(
878 on_scroll,
879 scroll,
880 nested_scroll_connection,
881 on_pointer_down,
882 on_pointer_move,
883 on_pointer_up,
884 on_pointer_cancel,
885 on_pointer_enter,
886 on_pointer_leave,
887 on_click,
888 on_double_click,
889 on_long_click,
890 on_globally_positioned,
891 on_size_changed,
892 on_key_event,
893 on_preview_key_event,
894 painter,
895 on_drag_start,
896 on_drag_end,
897 on_drag_enter,
898 on_drag_over,
899 on_drag_leave,
900 on_drop,
901 drag_preview,
902 on_action,
903 on_focus_changed,
904 interaction_source,
905 text_input,
906 layout,
907 );
908
909 macro_rules! flag {
910 ($($name:ident),+ $(,)?) => {
911 $( if self.$name { s.field(stringify!($name), &true); } )+
912 };
913 }
914 flag!(
915 hit_passthrough,
916 input_blocker,
917 repaint_boundary,
918 click,
919 disabled,
920 propagate_min,
921 focus_group,
922 );
923
924 if let Some(f) = self.focusable {
925 s.field("focusable", &f);
926 }
927 if self.z_index != 0.0 {
928 s.field("z_index", &self.z_index);
929 }
930
931 s.finish()
932 }
933}
934
935impl_option_fields!(Modifier);
936
937#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
941pub enum Alignment {
942 TopStart,
943 TopCenter,
944 TopEnd,
945 CenterStart,
946 #[default]
947 Center,
948 CenterEnd,
949 BottomStart,
950 BottomCenter,
951 BottomEnd,
952}
953
954impl Alignment {
955 pub fn to_flex(self) -> (AlignItems, JustifyContent) {
957 use AlignItems as AI;
958 use JustifyContent as JC;
959 match self {
960 Self::TopStart => (AI::START, JC::START),
961 Self::TopCenter => (AI::START, JC::CENTER),
962 Self::TopEnd => (AI::START, JC::END),
963 Self::CenterStart => (AI::CENTER, JC::START),
964 Self::Center => (AI::CENTER, JC::CENTER),
965 Self::CenterEnd => (AI::CENTER, JC::END),
966 Self::BottomStart => (AI::END, JC::START),
967 Self::BottomCenter => (AI::END, JC::CENTER),
968 Self::BottomEnd => (AI::END, JC::END),
969 }
970 }
971}
972
973impl Modifier {
974 pub fn new() -> Self {
975 Self::default()
976 }
977
978 pub fn key(mut self, key: u64) -> Self {
981 self.key = Some(key);
982 self
983 }
984
985 pub fn size(mut self, w: f32, h: f32) -> Self {
986 self.size = Some(Size {
987 width: w,
988 height: h,
989 });
990 self
991 }
992 pub fn width(mut self, w: f32) -> Self {
993 self.width = Some(w);
994 self
995 }
996 pub fn height(mut self, h: f32) -> Self {
997 self.height = Some(h);
998 self
999 }
1000 pub fn required_size(mut self, w: f32, h: f32) -> Self {
1005 self.required_size = Some(Size {
1006 width: w,
1007 height: h,
1008 });
1009 self
1010 }
1011 pub fn required_width_in(mut self, min: f32, max: f32) -> Self {
1012 self.required_min_width = Some(min.max(0.0));
1013 self.required_max_width = Some(max.max(0.0));
1014 self
1015 }
1016 pub fn required_height_in(mut self, min: f32, max: f32) -> Self {
1017 self.required_min_height = Some(min.max(0.0));
1018 self.required_max_height = Some(max.max(0.0));
1019 self
1020 }
1021 pub fn required_min_width(mut self, w: f32) -> Self {
1022 self.required_min_width = Some(w.max(0.0));
1023 self
1024 }
1025 pub fn required_max_width(mut self, w: f32) -> Self {
1026 self.required_max_width = Some(w.max(0.0));
1027 self
1028 }
1029 pub fn required_min_height(mut self, h: f32) -> Self {
1030 self.required_min_height = Some(h.max(0.0));
1031 self
1032 }
1033 pub fn required_max_height(mut self, h: f32) -> Self {
1034 self.required_max_height = Some(h.max(0.0));
1035 self
1036 }
1037 pub fn default_min_size(mut self, w: f32, h: f32) -> Self {
1039 self.default_min_width = Some(w.max(0.0));
1040 self.default_min_height = Some(h.max(0.0));
1041 self
1042 }
1043 pub fn fill_max_size(mut self) -> Self {
1046 self.fill_max = Some(1.0);
1047 self
1048 }
1049 pub fn fill_max_size_frac(mut self, fraction: f32) -> Self {
1050 self.fill_max = Some(fraction.clamp(0.0, 1.0));
1051 self
1052 }
1053 pub fn fill_max_width(mut self) -> Self {
1055 self.fill_max_w = Some(1.0);
1056 self
1057 }
1058 pub fn fill_max_width_frac(mut self, fraction: f32) -> Self {
1059 self.fill_max_w = Some(fraction.clamp(0.0, 1.0));
1060 self
1061 }
1062 pub fn fill_max_height(mut self) -> Self {
1064 self.fill_max_h = Some(1.0);
1065 self
1066 }
1067 pub fn fill_max_height_frac(mut self, fraction: f32) -> Self {
1068 self.fill_max_h = Some(fraction.clamp(0.0, 1.0));
1069 self
1070 }
1071 pub fn padding(mut self, v: f32) -> Self {
1072 self.padding = Some(v);
1073 self
1074 }
1075 pub fn padding_values(mut self, padding: PaddingValues) -> Self {
1076 self.padding_values = Some(padding);
1077 self
1078 }
1079 pub fn ime_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.ime_bottom / scale;
1086 self.padding_values = Some(p);
1087 self
1088 }
1089 pub fn system_bars_padding(mut self) -> Self {
1091 let insets = crate::locals::window_insets();
1092 let scale = crate::locals::density().scale * crate::locals::ui_scale().0;
1093 let mut p = self.padding_values.unwrap_or_default();
1094 p.top += insets.top / scale;
1095 p.bottom += insets.bottom / scale;
1096 self.padding_values = Some(p);
1097 self
1098 }
1099 pub fn status_bars_padding(mut self) -> Self {
1101 let insets = crate::locals::window_insets();
1102 let scale = crate::locals::density().scale * crate::locals::ui_scale().0;
1103 let mut p = self.padding_values.unwrap_or_default();
1104 p.top += insets.top / scale;
1105 self.padding_values = Some(p);
1106 self
1107 }
1108 pub fn navigation_bars_padding(mut self) -> Self {
1110 let insets = crate::locals::window_insets();
1111 let scale = crate::locals::density().scale * crate::locals::ui_scale().0;
1112 let mut p = self.padding_values.unwrap_or_default();
1113 p.bottom += insets.bottom / scale;
1114 self.padding_values = Some(p);
1115 self
1116 }
1117 pub fn min_size(mut self, w: f32, h: f32) -> Self {
1118 self.min_width = Some(w);
1119 self.min_height = Some(h);
1120 self
1121 }
1122 pub fn max_size(mut self, w: f32, h: f32) -> Self {
1123 self.max_width = Some(w);
1124 self.max_height = Some(h);
1125 self
1126 }
1127 pub fn min_width(mut self, w: f32) -> Self {
1128 self.min_width = Some(w);
1129 self
1130 }
1131 pub fn min_height(mut self, h: f32) -> Self {
1132 self.min_height = Some(h);
1133 self
1134 }
1135 pub fn max_width(mut self, w: f32) -> Self {
1136 self.max_width = Some(w);
1137 self
1138 }
1139 pub fn max_height(mut self, h: f32) -> Self {
1140 self.max_height = Some(h);
1141 self
1142 }
1143 pub fn background(mut self, color: Color) -> Self {
1145 self.background = Some(Brush::Solid(color));
1146 self
1147 }
1148 pub fn background_brush(mut self, brush: Brush) -> Self {
1150 self.background = Some(brush);
1151 self
1152 }
1153 pub fn border(mut self, width: f32, color: Color, radius: f32) -> Self {
1154 self.border = Some(Border {
1155 width,
1156 color,
1157 radius: [radius; 4],
1158 });
1159 self
1160 }
1161 pub fn border_radii(mut self, width: f32, color: Color, radii: [f32; 4]) -> Self {
1162 self.border = Some(Border {
1163 width,
1164 color,
1165 radius: radii,
1166 });
1167 self
1168 }
1169 pub fn flex_grow(mut self, v: f32) -> Self {
1170 self.flex_grow = Some(v);
1171 self
1172 }
1173 pub fn flex_shrink(mut self, v: f32) -> Self {
1174 self.flex_shrink = Some(v);
1175 self
1176 }
1177 pub fn flex_basis(mut self, v: f32) -> Self {
1178 self.flex_basis = Some(v);
1179 self
1180 }
1181 pub fn flex_wrap(mut self, w: FlexWrap) -> Self {
1182 self.flex_wrap = Some(w);
1183 self
1184 }
1185 pub fn flex_dir(mut self, d: FlexDirection) -> Self {
1186 self.flex_dir = Some(d);
1187 self
1188 }
1189 pub fn gap(mut self, v: f32) -> Self {
1190 let v = v.max(0.0);
1191 self.gap = Some(v);
1192 self.row_gap = Some(v);
1193 self.column_gap = Some(v);
1194 self
1195 }
1196 pub fn row_gap(mut self, v: f32) -> Self {
1197 self.row_gap = Some(v.max(0.0));
1198 self
1199 }
1200 pub fn column_gap(mut self, v: f32) -> Self {
1201 self.column_gap = Some(v.max(0.0));
1202 self
1203 }
1204 pub fn align_self(mut self, a: AlignSelf) -> Self {
1205 self.align_self = Some(a);
1206 self
1207 }
1208 pub fn align_self_center(mut self) -> Self {
1209 self.align_self = Some(AlignSelf::CENTER);
1210 self
1211 }
1212 pub fn justify_content(mut self, j: JustifyContent) -> Self {
1213 self.justify_content = Some(j);
1214 self
1215 }
1216 pub fn align_items(mut self, a: AlignItems) -> Self {
1217 self.align_items_container = Some(a);
1218 self
1219 }
1220 pub fn content_alignment(self, alignment: Alignment) -> Self {
1223 let (ai, jc) = alignment.to_flex();
1224 self.align_items(ai).justify_content(jc)
1225 }
1226 pub fn align_content(mut self, a: AlignContent) -> Self {
1227 self.align_content = Some(a);
1228 self
1229 }
1230 pub fn clip_rounded(mut self, radius: f32) -> Self {
1231 self.clip_rounded = Some([radius; 4]);
1232 self
1233 }
1234 pub fn clip_rounded_radii(mut self, radii: [f32; 4]) -> Self {
1235 self.clip_rounded = Some(radii);
1236 self
1237 }
1238 pub fn clip_rect(mut self, left: f32, top: f32, right: f32, bottom: f32, op: ClipOp) -> Self {
1241 self.clip_rect = Some(ClipRect {
1242 left,
1243 top,
1244 right,
1245 bottom,
1246 op,
1247 });
1248 self
1249 }
1250 pub fn overflow(mut self, overflow: Overflow) -> Self {
1251 self.overflow = Some(overflow);
1252 self
1253 }
1254 pub fn z_index(mut self, z: f32) -> Self {
1255 self.z_index = z;
1256 self
1257 }
1258
1259 pub fn render_z_index(mut self, z: f32) -> Self {
1262 self.render_z_index = Some(z);
1263 self
1264 }
1265
1266 pub fn input_blocker(mut self) -> Self {
1268 self.input_blocker = true;
1269 self
1270 }
1271
1272 pub fn hit_passthrough(mut self) -> Self {
1273 self.hit_passthrough = true;
1274 self
1275 }
1276 pub fn clickable(mut self) -> Self {
1277 self.click = true;
1278 if self.indication.is_none() {
1279 self.indication = crate::locals::local_indication();
1280 }
1281 self
1282 }
1283 pub fn clickable_with_source(mut self, source: &MutableInteractionSource) -> Self {
1286 self.click = true;
1287 self.interaction_source = Some(source.source());
1288 if self.indication.is_none() {
1289 self.indication = crate::locals::local_indication();
1290 }
1291 self
1292 }
1293 pub fn state_colors(mut self, colors: StateColors) -> Self {
1296 self.state_colors = Some(colors);
1297 self
1298 }
1299 pub fn state_elevation(mut self, elev: StateElevation) -> Self {
1301 self.state_elevation = Some(elev);
1302 self
1303 }
1304 pub fn disabled(mut self) -> Self {
1306 self.disabled = true;
1307 self
1308 }
1309 pub fn enabled(mut self, enabled: bool) -> Self {
1311 self.disabled = !enabled;
1312 self
1313 }
1314 pub fn focusable(mut self, focusable: bool) -> Self {
1319 self.focusable = Some(focusable);
1320 self
1321 }
1322 pub fn focus_group(mut self) -> Self {
1325 self.focus_group = true;
1326 self
1327 }
1328 pub fn interaction_source(mut self, source: &MutableInteractionSource) -> Self {
1339 self.interaction_source = Some(source.source());
1340 self
1341 }
1342 pub fn hoverable(
1345 mut self,
1346 on_enter: impl Fn() + 'static,
1347 on_leave: impl Fn() + 'static,
1348 ) -> Self {
1349 self.on_pointer_enter = Some(Rc::new(move |_| on_enter()));
1350 self.on_pointer_leave = Some(Rc::new(move |_| on_leave()));
1351 self
1352 }
1353 pub fn hoverable_with_source(mut self, source: &MutableInteractionSource) -> Self {
1357 self.interaction_source = Some(source.source());
1358 self
1359 }
1360 pub fn propagate_min_constraints(mut self, propagate: bool) -> Self {
1363 self.propagate_min = propagate;
1364 self
1365 }
1366 pub fn on_scroll(mut self, f: impl Fn(Vec2) -> Vec2 + 'static) -> Self {
1367 self.on_scroll = Some(Rc::new(f));
1368 self
1369 }
1370 pub fn vertical_scroll(mut self, binding: crate::scroll::ScrollAxisBinding) -> Self {
1374 self.scroll = Some(crate::scroll::ScrollBinding::Vertical(binding));
1375 self
1376 }
1377 pub fn horizontal_scroll(mut self, binding: crate::scroll::ScrollAxisBinding) -> Self {
1379 self.scroll = Some(crate::scroll::ScrollBinding::Horizontal(binding));
1380 self
1381 }
1382 pub fn scrollable(mut self, binding: crate::scroll::ScrollBothBinding) -> Self {
1384 self.scroll = Some(crate::scroll::ScrollBinding::Both(binding));
1385 self
1386 }
1387 pub fn nested_scroll(mut self, conn: crate::nested_scroll::NestedScrollConnection) -> Self {
1394 self.nested_scroll_connection = Some(conn);
1395 self
1396 }
1397 pub fn on_pointer_down(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
1398 self.on_pointer_down = Some(Rc::new(f));
1399 self
1400 }
1401 pub fn on_pointer_move(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
1402 self.on_pointer_move = Some(Rc::new(f));
1403 self
1404 }
1405 pub fn on_pointer_up(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
1406 self.on_pointer_up = Some(Rc::new(f));
1407 self
1408 }
1409 pub fn on_pointer_cancel(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
1410 self.on_pointer_cancel = Some(Rc::new(f));
1411 self
1412 }
1413 pub fn on_pointer_enter(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
1414 self.on_pointer_enter = Some(Rc::new(f));
1415 self
1416 }
1417 pub fn on_pointer_leave(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
1418 self.on_pointer_leave = Some(Rc::new(f));
1419 self
1420 }
1421 pub fn on_click(mut self, f: impl Fn() + 'static) -> Self {
1422 self.on_click = Some(Rc::new(f));
1423 self.click = true;
1424 if self.semantics.is_none() {
1425 self.semantics = Some(crate::Semantics::new(crate::Role::Button));
1426 }
1427 self
1428 }
1429 pub fn on_double_click(mut self, f: impl Fn() + 'static) -> Self {
1430 self.on_double_click = Some(Rc::new(f));
1431 self.click = true;
1432 self
1433 }
1434 pub fn on_long_click(mut self, f: impl Fn() + 'static) -> Self {
1435 self.on_long_click = Some(Rc::new(f));
1436 self.click = true;
1437 self
1438 }
1439 pub fn clickable_ext(
1440 mut self,
1441 enabled: bool,
1442 on_click_label: Option<String>,
1443 role: Option<crate::semantics::Role>,
1444 on_click: impl Fn() + 'static,
1445 ) -> Self {
1446 if !enabled {
1447 let mut s = self.semantics.clone().unwrap_or_else(|| {
1448 crate::semantics::Semantics::new(role.unwrap_or(crate::semantics::Role::Button))
1449 });
1450 s.enabled = false;
1451 if let Some(r) = role {
1452 s.role = r;
1453 }
1454 if let Some(l) = on_click_label {
1455 s.label = Some(l);
1456 }
1457 return self
1458 .clickable()
1459 .enabled(false)
1460 .default_min_size(48.0, 48.0)
1461 .semantics(s);
1462 }
1463 self = self.clickable().on_click(on_click);
1464 if role.is_some() || on_click_label.is_some() {
1465 let mut s = self.semantics.clone().unwrap_or_else(|| {
1466 crate::semantics::Semantics::new(role.unwrap_or(crate::semantics::Role::Button))
1467 });
1468 s.enabled = true;
1469 if let Some(r) = role {
1470 s.role = r;
1471 }
1472 if let Some(l) = on_click_label {
1473 s.label = Some(l);
1474 }
1475 self = self.semantics(s);
1476 }
1477 self.default_min_size(48.0, 48.0)
1478 }
1479 pub fn combined_clickable(
1480 mut self,
1481 enabled: bool,
1482 on_click_label: Option<String>,
1483 role: Option<crate::semantics::Role>,
1484 on_long_click_label: Option<String>,
1485 on_click: impl Fn() + 'static,
1486 on_long_click: Option<impl Fn() + 'static>,
1487 on_double_click: Option<impl Fn() + 'static>,
1488 ) -> Self {
1489 let _ = on_long_click_label;
1490 if !enabled {
1491 return self.clickable_ext(false, on_click_label, role, || {});
1492 }
1493 self = self.clickable_ext(true, on_click_label, role, on_click);
1494 if let Some(f) = on_long_click {
1495 self = self.on_long_click(f);
1496 }
1497 if let Some(f) = on_double_click {
1498 self = self.on_double_click(f);
1499 }
1500 self.default_min_size(48.0, 48.0)
1501 }
1502 pub fn semantics(mut self, s: crate::Semantics) -> Self {
1503 self.semantics = Some(s);
1504 self
1505 }
1506 pub fn alpha(mut self, a: f32) -> Self {
1507 self.alpha = Some(a);
1508 self
1509 }
1510 pub fn graphics_layer(mut self, alpha: f32) -> Self {
1515 self.graphics_layer = Some(alpha.clamp(0.0, 1.0));
1516 self
1517 }
1518 pub fn shadow(mut self, blur_radius: f32, offset_y: f32) -> Self {
1522 self.shadow = Some(ShadowSpec {
1523 blur_radius: blur_radius.max(0.0),
1524 offset_y,
1525 color: Color(0, 0, 0, 64),
1526 });
1527 self
1528 }
1529 pub fn shadow_with_color(mut self, blur_radius: f32, offset_y: f32, color: Color) -> Self {
1531 self.shadow = Some(ShadowSpec {
1532 blur_radius: blur_radius.max(0.0),
1533 offset_y,
1534 color,
1535 });
1536 self
1537 }
1538 pub fn elevation(mut self, level: f32) -> Self {
1542 if level <= 0.0 {
1543 self.shadow = None;
1544 return self;
1545 }
1546 self.shadow = Some(ShadowSpec {
1547 blur_radius: level * 2.0,
1548 offset_y: level * 0.5,
1549 color: Color(0, 0, 0, (level * 8.0).clamp(8.0, 80.0) as u8),
1550 });
1551 self
1552 }
1553 pub fn transform(mut self, t: Transform) -> Self {
1554 self.transform = Some(t);
1555 self
1556 }
1557 pub fn grid(mut self, columns: usize, row_gap: f32, column_gap: f32) -> Self {
1558 self.grid = Some(GridConfig {
1559 columns,
1560 row_gap,
1561 column_gap,
1562 });
1563 self
1564 }
1565 pub fn grid_span(mut self, col_span: u16, row_span: u16) -> Self {
1566 self.grid_col_span = Some(col_span);
1567 self.grid_row_span = Some(row_span);
1568 self
1569 }
1570 pub fn absolute(mut self) -> Self {
1571 self.position_type = Some(PositionType::Absolute);
1572 self
1573 }
1574 pub fn offset(
1575 mut self,
1576 left: Option<f32>,
1577 top: Option<f32>,
1578 right: Option<f32>,
1579 bottom: Option<f32>,
1580 ) -> Self {
1581 self.offset_left = left;
1582 self.offset_top = top;
1583 self.offset_right = right;
1584 self.offset_bottom = bottom;
1585 self
1586 }
1587 pub fn offset_left(mut self, v: f32) -> Self {
1588 self.offset_left = Some(v);
1589 self
1590 }
1591 pub fn offset_right(mut self, v: f32) -> Self {
1592 self.offset_right = Some(v);
1593 self
1594 }
1595 pub fn offset_top(mut self, v: f32) -> Self {
1596 self.offset_top = Some(v);
1597 self
1598 }
1599 pub fn offset_bottom(mut self, v: f32) -> Self {
1600 self.offset_bottom = Some(v);
1601 self
1602 }
1603 pub fn margin(mut self, v: f32) -> Self {
1604 self.margin_left = Some(v);
1605 self.margin_right = Some(v);
1606 self.margin_top = Some(v);
1607 self.margin_bottom = Some(v);
1608 self
1609 }
1610
1611 pub fn margin_horizontal(mut self, v: f32) -> Self {
1612 self.margin_left = Some(v);
1613 self.margin_right = Some(v);
1614 self
1615 }
1616
1617 pub fn margin_vertical(mut self, v: f32) -> Self {
1618 self.margin_top = Some(v);
1619 self.margin_bottom = Some(v);
1620 self
1621 }
1622 pub fn aspect_ratio(mut self, ratio: f32) -> Self {
1623 self.aspect_ratio = Some(ratio);
1624 self
1625 }
1626 pub fn intrinsic_width(mut self, mode: IntrinsicSize) -> Self {
1628 self.intrinsic_width = Some(mode);
1629 self
1630 }
1631 pub fn intrinsic_height(mut self, mode: IntrinsicSize) -> Self {
1633 self.intrinsic_height = Some(mode);
1634 self
1635 }
1636 pub fn painter(mut self, f: impl Fn(&mut crate::Scene, crate::Rect, f32) + 'static) -> Self {
1637 self.painter = Some(Rc::new(f));
1638 self
1639 }
1640 pub fn scale(self, s: f32) -> Self {
1641 self.scale2(s, s)
1642 }
1643 pub fn scale2(mut self, sx: f32, sy: f32) -> Self {
1644 let mut t = self.transform.unwrap_or_else(Transform::identity);
1645 t.scale_x *= sx;
1646 t.scale_y *= sy;
1647 self.transform = Some(t);
1648 self
1649 }
1650 pub fn translate(mut self, x: f32, y: f32) -> Self {
1651 let t = self.transform.unwrap_or_else(Transform::identity);
1652 self.transform = Some(t.combine(&Transform::translate(x, y)));
1653 self
1654 }
1655 pub fn translate_vec2(self, v: Vec2) -> Self {
1656 self.translate(v.x, v.y)
1657 }
1658 pub fn rotate(mut self, radians: f32) -> Self {
1659 let mut t = self.transform.unwrap_or_else(Transform::identity);
1660 t.rotate += radians;
1661 self.transform = Some(t);
1662 self
1663 }
1664 pub fn transform_origin(mut self, x: f32, y: f32) -> Self {
1665 let mut t = self.transform.unwrap_or_else(Transform::identity);
1666 t.origin_x = x;
1667 t.origin_y = y;
1668 self.transform = Some(t);
1669 self
1670 }
1671 pub fn weight(mut self, w: f32) -> Self {
1672 let w = w.max(0.0);
1673 self.flex_grow = Some(w);
1674 self.flex_shrink = Some(1.0);
1675 self.flex_basis = Some(0.0);
1677 self
1678 }
1679 pub fn repaint_boundary(mut self) -> Self {
1683 self.repaint_boundary = true;
1684 self
1685 }
1686 pub fn on_action(mut self, f: impl Fn(crate::shortcuts::Action) -> bool + 'static) -> Self {
1687 self.on_action = Some(Rc::new(f));
1688 self
1689 }
1690
1691 pub fn on_drag_start(
1693 mut self,
1694 f: impl Fn(crate::dnd::DragStart) -> Option<crate::dnd::DragPayload> + 'static,
1695 ) -> Self {
1696 self.on_drag_start = Some(Rc::new(f));
1697 self
1698 }
1699
1700 pub fn on_drag_end(mut self, f: impl Fn(crate::dnd::DragEnd) + 'static) -> Self {
1702 self.on_drag_end = Some(Rc::new(f));
1703 self
1704 }
1705
1706 pub fn on_drag_enter(mut self, f: impl Fn(crate::dnd::DragOver) + 'static) -> Self {
1708 self.on_drag_enter = Some(Rc::new(f));
1709 self
1710 }
1711
1712 pub fn on_drag_over(mut self, f: impl Fn(crate::dnd::DragOver) + 'static) -> Self {
1714 self.on_drag_over = Some(Rc::new(f));
1715 self
1716 }
1717
1718 pub fn on_drag_leave(mut self, f: impl Fn(crate::dnd::DragOver) + 'static) -> Self {
1720 self.on_drag_leave = Some(Rc::new(f));
1721 self
1722 }
1723
1724 pub fn on_drop(mut self, f: impl Fn(crate::dnd::DropEvent) -> bool + 'static) -> Self {
1727 self.on_drop = Some(Rc::new(f));
1728 self
1729 }
1730
1731 pub fn draw_drag_decoration(
1736 mut self,
1737 f: impl Fn(&mut crate::Scene, &crate::dnd::DragPreviewCtx) + 'static,
1738 ) -> Self {
1739 self.drag_preview = Some(Rc::new(f));
1740 self
1741 }
1742
1743 pub fn draw_drag_decoration_rc(mut self, preview: crate::dnd::DragPreview) -> Self {
1745 self.drag_preview = Some(preview);
1746 self
1747 }
1748
1749 pub fn drag_preview_label(self, label: impl Into<String>, accent: crate::Color) -> Self {
1751 self.draw_drag_decoration_rc(crate::dnd::drag_preview_label(label, accent))
1752 }
1753
1754 pub fn drag_preview_chip(self, label: impl Into<String>, accent: crate::Color) -> Self {
1756 self.draw_drag_decoration_rc(crate::dnd::drag_preview_chip(label, accent))
1757 }
1758
1759 pub fn cursor(mut self, c: crate::CursorIcon) -> Self {
1761 self.cursor = Some(c);
1762 self
1763 }
1764
1765 pub fn animate_content_size(mut self, spec: AnimationSpec) -> Self {
1769 self.animate_content_size = Some(spec);
1770 self
1771 }
1772
1773 pub fn focus_requester(mut self, fr: crate::runtime::FocusRequester) -> Self {
1776 self.focus_requester = Some(fr);
1777 self
1778 }
1779
1780 pub fn focus_target(mut self) -> Self {
1783 self.focusable = Some(true);
1784 self
1785 }
1786
1787 pub fn on_focus_changed(mut self, f: impl Fn(bool) + 'static) -> Self {
1790 self.on_focus_changed = Some(Rc::new(f));
1791 self
1792 }
1793
1794 pub fn on_globally_positioned(mut self, f: impl Fn(crate::Rect) + 'static) -> Self {
1798 self.on_globally_positioned = Some(Rc::new(f));
1799 self
1800 }
1801
1802 pub fn on_size_changed(mut self, f: impl Fn(crate::Vec2) + 'static) -> Self {
1805 self.on_size_changed = Some(Rc::new(f));
1806 self
1807 }
1808
1809 pub fn on_key_event(mut self, f: impl Fn(crate::input::KeyEvent) -> bool + 'static) -> Self {
1813 self.on_key_event = Some(Rc::new(f));
1814 self
1815 }
1816
1817 pub fn on_preview_key_event(
1821 mut self,
1822 f: impl Fn(crate::input::KeyEvent) -> bool + 'static,
1823 ) -> Self {
1824 self.on_preview_key_event = Some(Rc::new(f));
1825 self
1826 }
1827
1828 pub fn blur(mut self, radius_dp: f32) -> Self {
1835 self.blur = Some(BlurStyle {
1836 radius_x: radius_dp.max(0.0),
1837 radius_y: radius_dp.max(0.0),
1838 edge_treatment: BlurredEdgeTreatment::Rectangle,
1839 });
1840 self
1841 }
1842
1843 pub fn blur_with_edge(
1848 mut self,
1849 radius_x: f32,
1850 radius_y: f32,
1851 edge_treatment: BlurredEdgeTreatment,
1852 ) -> Self {
1853 self.blur = Some(BlurStyle {
1854 radius_x: radius_x.max(0.0),
1855 radius_y: radius_y.max(0.0),
1856 edge_treatment,
1857 });
1858 self
1859 }
1860
1861 pub fn layout(mut self, f: impl Fn(LayoutConstraints) -> (f32, f32) + 'static) -> Self {
1869 self.layout = Some(Rc::new(f));
1870 self
1871 }
1872
1873 pub fn text_input(mut self, config: TextInputConfig) -> Self {
1875 self.text_input = Some(config);
1876 self
1877 }
1878
1879 pub fn indication(mut self, factory: Rc<dyn IndicationNodeFactory>) -> Self {
1883 self.indication = Some(factory);
1884 self
1885 }
1886}