1use std::cell::Cell;
2use std::rc::Rc;
3
4use taffy::{AlignContent, AlignItems, AlignSelf, FlexDirection, FlexWrap, JustifyContent};
5
6use crate::animation::AnimationSpec;
7use crate::{Brush, Color, PointerEvent, Size, Transform, Vec2};
8
9#[derive(Clone, Copy, Debug)]
13pub struct StateColors {
14 pub default: Color,
15 pub hovered: Color,
16 pub pressed: Color,
17 pub disabled: Color,
18}
19
20#[derive(Clone, Copy, Debug)]
22pub struct StateElevation {
23 pub default: f32,
24 pub hovered: f32,
25 pub pressed: f32,
26 pub disabled: f32,
27}
28
29macro_rules! merge_opts {
30 ($dst:ident, $src:ident; $($f:ident),+ $(,)?) => {
31 $( $dst.$f = $src.$f.or($dst.$f); )+
32 };
33}
34macro_rules! merge_flags {
35 ($dst:ident, $src:ident; $($f:ident),+ $(,)?) => {
36 $( $dst.$f |= $src.$f; )+
37 };
38}
39
40macro_rules! impl_option_fields {
41 ($ty:ty, $fn:ident) => {
42 impl $ty {
43 $fn!(replace);
44 }
45 };
46 ($ty:ident) => {
47 impl $ty {
48 pub fn then(mut self, other: Self) -> Self {
51 merge_opts!(self, other;
52 key, size, width, height,
53 padding, padding_values,
54 min_width, min_height, max_width, max_height,
55 background, state_colors, state_elevation, border,
56 flex_grow, flex_shrink, flex_basis, flex_wrap, flex_dir,
57 gap, row_gap, column_gap,
58 align_self, justify_content, align_items_container, align_content,
59 clip_rounded, render_z_index,
60 on_scroll,
61 on_pointer_down, on_pointer_move, on_pointer_up,
62 on_pointer_enter, on_pointer_leave,
63 semantics, alpha, transform,
64 grid, grid_col_span, grid_row_span,
65 position_type,
66 offset_left, offset_right, offset_top, offset_bottom,
67 margin_left, margin_right, margin_top, margin_bottom,
68 aspect_ratio, painter,
69 on_drag_start, on_drag_end, on_drag_enter, on_drag_over, on_drag_leave, on_drop,
70 on_action, cursor, animate_content_size, focus_requester, on_focus_changed,
71 text_input,
72 );
73 merge_flags!(self, other;
74 fill_max, fill_max_w, fill_max_h,
75 hit_passthrough, input_blocker, repaint_boundary, click, disabled,
76 );
77 if other.z_index != 0.0 {
78 self.z_index = other.z_index;
79 }
80 self
81 }
82 }
83 };
84}
85
86#[derive(Clone, Debug)]
87pub struct Border {
88 pub width: f32,
89 pub color: Color,
90 pub radius: f32,
91}
92
93#[derive(Clone, Copy, Debug, Default)]
94pub struct PaddingValues {
95 pub left: f32,
96 pub right: f32,
97 pub top: f32,
98 pub bottom: f32,
99}
100
101#[derive(Clone, Debug)]
102pub struct GridConfig {
103 pub columns: usize,
104 pub row_gap: f32,
105 pub column_gap: f32,
106}
107
108#[derive(Clone, Copy, Debug)]
115pub struct ShadowSpec {
116 pub blur_radius: f32,
117 pub offset_y: f32,
118 pub color: Color,
119}
120
121#[derive(Clone, Copy, Debug)]
122#[non_exhaustive]
123pub enum PositionType {
124 Relative,
125 Absolute,
126}
127
128#[derive(Clone)]
130pub struct TextInputConfig {
131 pub hint: String,
132 pub multiline: bool,
133 pub on_change: Option<Rc<dyn Fn(String)>>,
134 pub on_submit: Option<Rc<dyn Fn(String)>>,
135 pub focus_tracker: Option<Rc<Cell<bool>>>,
136 pub value: String,
137 pub visual_transformation: Option<Rc<dyn crate::text::VisualTransformation>>,
138 pub keyboard_type: Option<crate::text::KeyboardType>,
139 pub ime_action: Option<crate::text::ImeAction>,
140}
141
142impl std::fmt::Debug for TextInputConfig {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144 let mut s = f.debug_struct("TextInputConfig");
145 s.field("hint", &self.hint);
146 s.field("multiline", &self.multiline);
147 if self.on_change.is_some() {
148 s.field("on_change", &"…");
149 }
150 if self.on_submit.is_some() {
151 s.field("on_submit", &"…");
152 }
153 if self.focus_tracker.is_some() {
154 s.field("focus_tracker", &"…");
155 }
156 s.field("value", &self.value);
157 if self.visual_transformation.is_some() {
158 s.field("visual_transformation", &"…");
159 }
160 s.field("keyboard_type", &self.keyboard_type);
161 s.field("ime_action", &self.ime_action);
162 s.finish()
163 }
164}
165
166#[derive(Clone, Default)]
167pub struct Modifier {
168 pub key: Option<u64>,
174
175 pub size: Option<Size>,
176 pub width: Option<f32>,
177 pub height: Option<f32>,
178 pub fill_max: bool,
179 pub fill_max_w: bool,
180 pub fill_max_h: bool,
181 pub padding: Option<f32>,
182 pub padding_values: Option<PaddingValues>,
183 pub min_width: Option<f32>,
184 pub min_height: Option<f32>,
185 pub max_width: Option<f32>,
186 pub max_height: Option<f32>,
187 pub background: Option<Brush>,
188 pub state_colors: Option<StateColors>,
189 pub state_elevation: Option<StateElevation>,
190
191 pub border: Option<Border>,
192 pub flex_grow: Option<f32>,
193 pub flex_shrink: Option<f32>,
194 pub flex_basis: Option<f32>,
195 pub flex_wrap: Option<FlexWrap>,
196 pub flex_dir: Option<FlexDirection>,
197 pub gap: Option<f32>,
198 pub row_gap: Option<f32>,
199 pub column_gap: Option<f32>,
200 pub align_self: Option<AlignSelf>,
201 pub justify_content: Option<JustifyContent>,
202 pub align_items_container: Option<AlignItems>,
203 pub align_content: Option<AlignContent>,
204 pub clip_rounded: Option<f32>,
205 pub z_index: f32,
207 pub render_z_index: Option<f32>,
209 pub hit_passthrough: bool,
211 pub input_blocker: bool,
213 pub repaint_boundary: bool,
214 pub click: bool,
215 pub disabled: bool,
217 pub on_scroll: Option<Rc<dyn Fn(Vec2) -> Vec2>>,
218 pub on_pointer_down: Option<Rc<dyn Fn(PointerEvent)>>,
219 pub on_pointer_move: Option<Rc<dyn Fn(PointerEvent)>>,
220 pub on_pointer_up: Option<Rc<dyn Fn(PointerEvent)>>,
221 pub on_pointer_enter: Option<Rc<dyn Fn(PointerEvent)>>,
222 pub on_pointer_leave: Option<Rc<dyn Fn(PointerEvent)>>,
223 pub semantics: Option<crate::Semantics>,
224 pub alpha: Option<f32>,
225 pub graphics_layer: Option<f32>,
226 pub shadow: Option<ShadowSpec>,
227 pub transform: Option<Transform>,
228 pub grid: Option<GridConfig>,
229 pub grid_col_span: Option<u16>,
230 pub grid_row_span: Option<u16>,
231 pub position_type: Option<PositionType>,
232 pub offset_left: Option<f32>,
233 pub offset_right: Option<f32>,
234 pub offset_top: Option<f32>,
235 pub offset_bottom: Option<f32>,
236 pub margin_left: Option<f32>,
237 pub margin_right: Option<f32>,
238 pub margin_top: Option<f32>,
239 pub margin_bottom: Option<f32>,
240 pub aspect_ratio: Option<f32>,
241 pub painter: Option<Rc<dyn Fn(&mut crate::Scene, crate::Rect, f32)>>,
242
243 pub on_drag_start: Option<Rc<dyn Fn(crate::dnd::DragStart) -> Option<crate::dnd::DragPayload>>>,
245 pub on_drag_end: Option<Rc<dyn Fn(crate::dnd::DragEnd)>>,
246 pub on_drag_enter: Option<Rc<dyn Fn(crate::dnd::DragOver)>>,
247 pub on_drag_over: Option<Rc<dyn Fn(crate::dnd::DragOver)>>,
248 pub on_drag_leave: Option<Rc<dyn Fn(crate::dnd::DragOver)>>,
249 pub on_drop: Option<Rc<dyn Fn(crate::dnd::DropEvent) -> bool>>,
250
251 pub on_action: Option<Rc<dyn Fn(crate::shortcuts::Action) -> bool>>,
252
253 pub cursor: Option<crate::CursorIcon>,
255
256 pub animate_content_size: Option<AnimationSpec>,
259
260 pub focus_requester: Option<crate::runtime::FocusRequester>,
264
265 pub on_focus_changed: Option<Rc<dyn Fn(bool)>>,
268
269 pub text_input: Option<TextInputConfig>,
271}
272
273impl std::fmt::Debug for Modifier {
274 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275 let mut s = f.debug_struct("Modifier");
276
277 macro_rules! opt_val {
278 ($($name:ident),+ $(,)?) => {
279 $( if self.$name.is_some() { s.field(stringify!($name), &self.$name); } )+
280 };
281 }
282 opt_val!(
283 key,
284 size,
285 width,
286 height,
287 padding,
288 padding_values,
289 min_width,
290 min_height,
291 max_width,
292 max_height,
293 background,
294 state_colors,
295 state_elevation,
296 border,
297 flex_grow,
298 flex_shrink,
299 flex_basis,
300 flex_wrap,
301 flex_dir,
302 gap,
303 row_gap,
304 column_gap,
305 align_self,
306 justify_content,
307 align_items_container,
308 align_content,
309 clip_rounded,
310 render_z_index,
311 semantics,
312 alpha,
313 transform,
314 grid,
315 grid_col_span,
316 grid_row_span,
317 position_type,
318 offset_left,
319 offset_right,
320 offset_top,
321 offset_bottom,
322 margin_left,
323 margin_right,
324 margin_top,
325 margin_bottom,
326 aspect_ratio,
327 cursor,
328 animate_content_size,
329 );
330
331 macro_rules! opt_cb {
332 ($($name:ident),+ $(,)?) => {
333 $( if self.$name.is_some() { s.field(stringify!($name), &"…"); } )+
334 };
335 }
336 opt_cb!(
337 on_scroll,
338 on_pointer_down,
339 on_pointer_move,
340 on_pointer_up,
341 on_pointer_enter,
342 on_pointer_leave,
343 painter,
344 on_drag_start,
345 on_drag_end,
346 on_drag_enter,
347 on_drag_over,
348 on_drag_leave,
349 on_drop,
350 on_action,
351 on_focus_changed,
352 text_input,
353 );
354
355 macro_rules! flag {
356 ($($name:ident),+ $(,)?) => {
357 $( if self.$name { s.field(stringify!($name), &true); } )+
358 };
359 }
360 flag!(
361 fill_max,
362 fill_max_w,
363 fill_max_h,
364 hit_passthrough,
365 input_blocker,
366 repaint_boundary,
367 click,
368 disabled,
369 );
370
371 if self.z_index != 0.0 {
372 s.field("z_index", &self.z_index);
373 }
374
375 s.finish()
376 }
377}
378
379impl_option_fields!(Modifier);
380
381impl Modifier {
382 pub fn new() -> Self {
383 Self::default()
384 }
385
386 pub fn key(mut self, key: u64) -> Self {
389 self.key = Some(key);
390 self
391 }
392
393 pub fn size(mut self, w: f32, h: f32) -> Self {
394 self.size = Some(Size {
395 width: w,
396 height: h,
397 });
398 self
399 }
400 pub fn width(mut self, w: f32) -> Self {
401 self.width = Some(w);
402 self
403 }
404 pub fn height(mut self, h: f32) -> Self {
405 self.height = Some(h);
406 self
407 }
408 pub fn fill_max_size(mut self) -> Self {
409 self.fill_max = true;
410 self
411 }
412 pub fn fill_max_width(mut self) -> Self {
413 self.fill_max_w = true;
414 self
415 }
416 pub fn fill_max_height(mut self) -> Self {
417 self.fill_max_h = true;
418 self
419 }
420 pub fn padding(mut self, v: f32) -> Self {
421 self.padding = Some(v);
422 self
423 }
424 pub fn padding_values(mut self, padding: PaddingValues) -> Self {
425 self.padding_values = Some(padding);
426 self
427 }
428 pub fn ime_padding(mut self) -> Self {
431 let insets = crate::locals::window_insets();
432 let scale = crate::locals::density().scale * crate::locals::ui_scale().0;
433 let mut p = self.padding_values.unwrap_or_default();
434 p.bottom += insets.ime_bottom / scale;
435 self.padding_values = Some(p);
436 self
437 }
438 pub fn system_bars_padding(mut self) -> Self {
440 let insets = crate::locals::window_insets();
441 let scale = crate::locals::density().scale * crate::locals::ui_scale().0;
442 let mut p = self.padding_values.unwrap_or_default();
443 p.top += insets.top / scale;
444 p.bottom += insets.bottom / scale;
445 self.padding_values = Some(p);
446 self
447 }
448 pub fn status_bars_padding(mut self) -> Self {
450 let insets = crate::locals::window_insets();
451 let scale = crate::locals::density().scale * crate::locals::ui_scale().0;
452 let mut p = self.padding_values.unwrap_or_default();
453 p.top += insets.top / scale;
454 self.padding_values = Some(p);
455 self
456 }
457 pub fn navigation_bars_padding(mut self) -> Self {
459 let insets = crate::locals::window_insets();
460 let scale = crate::locals::density().scale * crate::locals::ui_scale().0;
461 let mut p = self.padding_values.unwrap_or_default();
462 p.bottom += insets.bottom / scale;
463 self.padding_values = Some(p);
464 self
465 }
466 pub fn min_size(mut self, w: f32, h: f32) -> Self {
467 self.min_width = Some(w);
468 self.min_height = Some(h);
469 self
470 }
471 pub fn max_size(mut self, w: f32, h: f32) -> Self {
472 self.max_width = Some(w);
473 self.max_height = Some(h);
474 self
475 }
476 pub fn min_width(mut self, w: f32) -> Self {
477 self.min_width = Some(w);
478 self
479 }
480 pub fn min_height(mut self, h: f32) -> Self {
481 self.min_height = Some(h);
482 self
483 }
484 pub fn max_width(mut self, w: f32) -> Self {
485 self.max_width = Some(w);
486 self
487 }
488 pub fn max_height(mut self, h: f32) -> Self {
489 self.max_height = Some(h);
490 self
491 }
492 pub fn background(mut self, color: Color) -> Self {
494 self.background = Some(Brush::Solid(color));
495 self
496 }
497 pub fn background_brush(mut self, brush: Brush) -> Self {
499 self.background = Some(brush);
500 self
501 }
502 pub fn border(mut self, width: f32, color: Color, radius: f32) -> Self {
503 self.border = Some(Border {
504 width,
505 color,
506 radius,
507 });
508 self
509 }
510 pub fn flex_grow(mut self, v: f32) -> Self {
511 self.flex_grow = Some(v);
512 self
513 }
514 pub fn flex_shrink(mut self, v: f32) -> Self {
515 self.flex_shrink = Some(v);
516 self
517 }
518 pub fn flex_basis(mut self, v: f32) -> Self {
519 self.flex_basis = Some(v);
520 self
521 }
522 pub fn flex_wrap(mut self, w: FlexWrap) -> Self {
523 self.flex_wrap = Some(w);
524 self
525 }
526 pub fn flex_dir(mut self, d: FlexDirection) -> Self {
527 self.flex_dir = Some(d);
528 self
529 }
530 pub fn gap(mut self, v: f32) -> Self {
531 let v = v.max(0.0);
532 self.gap = Some(v);
533 self.row_gap = Some(v);
534 self.column_gap = Some(v);
535 self
536 }
537 pub fn row_gap(mut self, v: f32) -> Self {
538 self.row_gap = Some(v.max(0.0));
539 self
540 }
541 pub fn column_gap(mut self, v: f32) -> Self {
542 self.column_gap = Some(v.max(0.0));
543 self
544 }
545 pub fn align_self(mut self, a: AlignSelf) -> Self {
546 self.align_self = Some(a);
547 self
548 }
549 pub fn align_self_center(mut self) -> Self {
550 self.align_self = Some(AlignSelf::Center);
551 self
552 }
553 pub fn justify_content(mut self, j: JustifyContent) -> Self {
554 self.justify_content = Some(j);
555 self
556 }
557 pub fn align_items(mut self, a: AlignItems) -> Self {
558 self.align_items_container = Some(a);
559 self
560 }
561 pub fn align_content(mut self, a: AlignContent) -> Self {
562 self.align_content = Some(a);
563 self
564 }
565 pub fn clip_rounded(mut self, radius: f32) -> Self {
566 self.clip_rounded = Some(radius);
567 self
568 }
569 pub fn z_index(mut self, z: f32) -> Self {
570 self.z_index = z;
571 self
572 }
573
574 pub fn render_z_index(mut self, z: f32) -> Self {
577 self.render_z_index = Some(z);
578 self
579 }
580
581 pub fn input_blocker(mut self) -> Self {
583 self.input_blocker = true;
584 self
585 }
586
587 pub fn hit_passthrough(mut self) -> Self {
588 self.hit_passthrough = true;
589 self
590 }
591 pub fn clickable(mut self) -> Self {
592 self.click = true;
593 self
594 }
595 pub fn state_colors(mut self, colors: StateColors) -> Self {
598 self.state_colors = Some(colors);
599 self
600 }
601 pub fn state_elevation(mut self, elev: StateElevation) -> Self {
603 self.state_elevation = Some(elev);
604 self
605 }
606 pub fn disabled(mut self) -> Self {
608 self.disabled = true;
609 self
610 }
611 pub fn enabled(mut self, enabled: bool) -> Self {
613 self.disabled = !enabled;
614 self
615 }
616 pub fn on_scroll(mut self, f: impl Fn(Vec2) -> Vec2 + 'static) -> Self {
617 self.on_scroll = Some(Rc::new(f));
618 self
619 }
620 pub fn on_pointer_down(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
621 self.on_pointer_down = Some(Rc::new(f));
622 self
623 }
624 pub fn on_pointer_move(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
625 self.on_pointer_move = Some(Rc::new(f));
626 self
627 }
628 pub fn on_pointer_up(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
629 self.on_pointer_up = Some(Rc::new(f));
630 self
631 }
632 pub fn on_pointer_enter(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
633 self.on_pointer_enter = Some(Rc::new(f));
634 self
635 }
636 pub fn on_pointer_leave(mut self, f: impl Fn(PointerEvent) + 'static) -> Self {
637 self.on_pointer_leave = Some(Rc::new(f));
638 self
639 }
640 pub fn semantics(mut self, s: crate::Semantics) -> Self {
641 self.semantics = Some(s);
642 self
643 }
644 pub fn alpha(mut self, a: f32) -> Self {
645 self.alpha = Some(a);
646 self
647 }
648 pub fn graphics_layer(mut self, alpha: f32) -> Self {
653 self.graphics_layer = Some(alpha.clamp(0.0, 1.0));
654 self
655 }
656 pub fn shadow(mut self, blur_radius: f32, offset_y: f32) -> Self {
660 self.shadow = Some(ShadowSpec {
661 blur_radius: blur_radius.max(0.0),
662 offset_y,
663 color: Color(0, 0, 0, 64),
664 });
665 self
666 }
667 pub fn shadow_with_color(mut self, blur_radius: f32, offset_y: f32, color: Color) -> Self {
669 self.shadow = Some(ShadowSpec {
670 blur_radius: blur_radius.max(0.0),
671 offset_y,
672 color,
673 });
674 self
675 }
676 pub fn elevation(mut self, level: f32) -> Self {
680 if level <= 0.0 {
681 self.shadow = None;
682 return self;
683 }
684 self.shadow = Some(ShadowSpec {
685 blur_radius: level * 2.0,
686 offset_y: level * 0.5,
687 color: Color(0, 0, 0, (level * 8.0).clamp(8.0, 80.0) as u8),
688 });
689 self
690 }
691 pub fn transform(mut self, t: Transform) -> Self {
692 self.transform = Some(t);
693 self
694 }
695 pub fn grid(mut self, columns: usize, row_gap: f32, column_gap: f32) -> Self {
696 self.grid = Some(GridConfig {
697 columns,
698 row_gap,
699 column_gap,
700 });
701 self
702 }
703 pub fn grid_span(mut self, col_span: u16, row_span: u16) -> Self {
704 self.grid_col_span = Some(col_span);
705 self.grid_row_span = Some(row_span);
706 self
707 }
708 pub fn absolute(mut self) -> Self {
709 self.position_type = Some(PositionType::Absolute);
710 self
711 }
712 pub fn offset(
713 mut self,
714 left: Option<f32>,
715 top: Option<f32>,
716 right: Option<f32>,
717 bottom: Option<f32>,
718 ) -> Self {
719 self.offset_left = left;
720 self.offset_top = top;
721 self.offset_right = right;
722 self.offset_bottom = bottom;
723 self
724 }
725 pub fn offset_left(mut self, v: f32) -> Self {
726 self.offset_left = Some(v);
727 self
728 }
729 pub fn offset_right(mut self, v: f32) -> Self {
730 self.offset_right = Some(v);
731 self
732 }
733 pub fn offset_top(mut self, v: f32) -> Self {
734 self.offset_top = Some(v);
735 self
736 }
737 pub fn offset_bottom(mut self, v: f32) -> Self {
738 self.offset_bottom = Some(v);
739 self
740 }
741
742 pub fn margin(mut self, v: f32) -> Self {
743 self.margin_left = Some(v);
744 self.margin_right = Some(v);
745 self.margin_top = Some(v);
746 self.margin_bottom = Some(v);
747 self
748 }
749
750 pub fn margin_horizontal(mut self, v: f32) -> Self {
751 self.margin_left = Some(v);
752 self.margin_right = Some(v);
753 self
754 }
755
756 pub fn margin_vertical(mut self, v: f32) -> Self {
757 self.margin_top = Some(v);
758 self.margin_bottom = Some(v);
759 self
760 }
761 pub fn aspect_ratio(mut self, ratio: f32) -> Self {
762 self.aspect_ratio = Some(ratio);
763 self
764 }
765 pub fn painter(mut self, f: impl Fn(&mut crate::Scene, crate::Rect, f32) + 'static) -> Self {
766 self.painter = Some(Rc::new(f));
767 self
768 }
769 pub fn scale(self, s: f32) -> Self {
770 self.scale2(s, s)
771 }
772 pub fn scale2(mut self, sx: f32, sy: f32) -> Self {
773 let mut t = self.transform.unwrap_or_else(Transform::identity);
774 t.scale_x *= sx;
775 t.scale_y *= sy;
776 self.transform = Some(t);
777 self
778 }
779 pub fn translate(mut self, x: f32, y: f32) -> Self {
780 let t = self.transform.unwrap_or_else(Transform::identity);
781 self.transform = Some(t.combine(&Transform::translate(x, y)));
782 self
783 }
784 pub fn translate_vec2(self, v: Vec2) -> Self {
785 self.translate(v.x, v.y)
786 }
787 pub fn rotate(mut self, radians: f32) -> Self {
788 let mut t = self.transform.unwrap_or_else(Transform::identity);
789 t.rotate += radians;
790 self.transform = Some(t);
791 self
792 }
793 pub fn weight(mut self, w: f32) -> Self {
794 let w = w.max(0.0);
795 self.flex_grow = Some(w);
796 self.flex_shrink = Some(1.0);
797 self.flex_basis = Some(0.0);
799 self
800 }
801 pub fn repaint_boundary(mut self) -> Self {
805 self.repaint_boundary = true;
806 self
807 }
808 pub fn on_action(mut self, f: impl Fn(crate::shortcuts::Action) -> bool + 'static) -> Self {
809 self.on_action = Some(Rc::new(f));
810 self
811 }
812
813 pub fn on_drag_start(
815 mut self,
816 f: impl Fn(crate::dnd::DragStart) -> Option<crate::dnd::DragPayload> + 'static,
817 ) -> Self {
818 self.on_drag_start = Some(Rc::new(f));
819 self
820 }
821
822 pub fn on_drag_end(mut self, f: impl Fn(crate::dnd::DragEnd) + 'static) -> Self {
824 self.on_drag_end = Some(Rc::new(f));
825 self
826 }
827
828 pub fn on_drag_enter(mut self, f: impl Fn(crate::dnd::DragOver) + 'static) -> Self {
830 self.on_drag_enter = Some(Rc::new(f));
831 self
832 }
833
834 pub fn on_drag_over(mut self, f: impl Fn(crate::dnd::DragOver) + 'static) -> Self {
836 self.on_drag_over = Some(Rc::new(f));
837 self
838 }
839
840 pub fn on_drag_leave(mut self, f: impl Fn(crate::dnd::DragOver) + 'static) -> Self {
842 self.on_drag_leave = Some(Rc::new(f));
843 self
844 }
845
846 pub fn on_drop(mut self, f: impl Fn(crate::dnd::DropEvent) -> bool + 'static) -> Self {
849 self.on_drop = Some(Rc::new(f));
850 self
851 }
852
853 pub fn cursor(mut self, c: crate::CursorIcon) -> Self {
855 self.cursor = Some(c);
856 self
857 }
858
859 pub fn animate_content_size(mut self, spec: AnimationSpec) -> Self {
863 self.animate_content_size = Some(spec);
864 self
865 }
866
867 pub fn focus_requester(mut self, fr: crate::runtime::FocusRequester) -> Self {
870 self.focus_requester = Some(fr);
871 self
872 }
873
874 pub fn on_focus_changed(mut self, f: impl Fn(bool) + 'static) -> Self {
877 self.on_focus_changed = Some(Rc::new(f));
878 self
879 }
880
881 pub fn text_input(mut self, config: TextInputConfig) -> Self {
883 self.text_input = Some(config);
884 self
885 }
886}