1use teksilo_canvas::Point;
21
22use crate::event::{ButtonMask, EventResponse, WidgetEvent};
23use crate::event_handlers::EventHandlers;
24use crate::gesture::{DragPhase, PinchPhase, SwipeDirection, TapEvent};
25use crate::signal::Prop;
26use crate::widget::{CursorIcon, EventContext, Widget};
27use crate::widget_id::WidgetId;
28
29#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
39pub enum AccessSubtreeMode {
40 #[default]
42 Inherit,
43 Exclude,
46 Merge,
52}
53
54#[derive(Default)]
75pub struct AccessibilityOverrides {
76 pub label: Option<Prop<String>>,
78 pub description: Option<Prop<String>>,
79 pub value: Option<Prop<String>>,
80 pub role: Option<accesskit::Role>,
81 pub hidden: Option<Prop<bool>>,
87 pub disabled: Option<bool>,
88
89 pub identifier: Option<String>,
91 pub controls: Vec<WidgetId>,
92 pub described_by: Vec<WidgetId>,
93 pub labelled_by: Vec<WidgetId>,
94 pub live: Option<accesskit::Live>,
95 pub aria_current: Option<accesskit::AriaCurrent>,
96 pub shortcut: Option<String>,
101 pub shortcut_id: Option<String>,
108 pub has_popup: Option<accesskit::HasPopup>,
109 pub orientation: Option<accesskit::Orientation>,
110
111 pub numeric_value: Option<f64>,
113 pub min_numeric_value: Option<f64>,
114 pub max_numeric_value: Option<f64>,
115 pub numeric_step: Option<f64>,
116
117 pub actions: Vec<(accesskit::Action, Box<dyn FnMut(&mut EventContext)>)>,
123
124 pub removed_actions: Vec<accesskit::Action>,
128
129 pub custom_actions: Vec<(Prop<String>, Box<dyn FnMut(&mut EventContext)>)>,
134
135 pub customize: Option<Box<dyn Fn(&mut crate::accessibility::AccessNodeBuilder)>>,
140}
141
142impl std::fmt::Debug for AccessibilityOverrides {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144 f.debug_struct("AccessibilityOverrides")
145 .field("label", &self.label)
146 .field("description", &self.description)
147 .field("value", &self.value)
148 .field("role", &self.role)
149 .field("hidden", &self.hidden)
150 .field("disabled", &self.disabled)
151 .field("identifier", &self.identifier)
152 .field("shortcut", &self.shortcut)
153 .field("shortcut_id", &self.shortcut_id)
154 .field("controls_len", &self.controls.len())
155 .field("described_by_len", &self.described_by.len())
156 .field("labelled_by_len", &self.labelled_by.len())
157 .field("actions_len", &self.actions.len())
158 .field("removed_actions", &self.removed_actions)
159 .field("custom_actions_len", &self.custom_actions.len())
160 .finish()
161 }
162}
163
164impl AccessibilityOverrides {
165 pub(crate) fn apply(&self, b: &mut crate::accessibility::AccessNodeBuilder) {
170 use crate::accessibility::widget_id_to_node_id;
171
172 if let Some(ref p) = self.label {
173 b.set_name(p.get());
174 }
175 if let Some(ref p) = self.description {
176 b.set_description(p.get());
177 }
178 if let Some(ref p) = self.value {
179 b.set_value(p.get());
180 }
181 if let Some(role) = self.role {
182 b.set_role(role);
183 }
184 match self.hidden.as_ref().map(|p| p.get()) {
185 Some(true) => b.set_hidden(),
186 Some(false) => b.clear_hidden(),
187 None => {}
188 }
189 match self.disabled {
190 Some(true) => b.set_disabled(),
191 Some(false) => b.clear_disabled(),
192 None => {}
193 }
194 if let Some(ref s) = self.identifier {
195 b.set_author_id(s.clone());
196 }
197 for &id in &self.controls {
198 b.push_controlled(widget_id_to_node_id(id));
199 }
200 for &id in &self.described_by {
201 b.push_described_by(widget_id_to_node_id(id));
202 }
203 for &id in &self.labelled_by {
204 b.push_labelled_by(widget_id_to_node_id(id));
205 }
206 if let Some(live) = self.live {
207 b.set_live(live);
208 }
209 if let Some(c) = self.aria_current {
210 b.set_aria_current(c);
211 }
212 if let Some(ref s) = self.shortcut {
213 b.set_keyboard_shortcut(s.clone());
214 }
215 if let Some(p) = self.has_popup {
219 b.set_has_popup(p);
220 }
221 if let Some(o) = self.orientation {
222 b.set_orientation(o);
223 }
224 if let Some(v) = self.numeric_value {
225 b.set_numeric_value(v);
226 }
227 if let Some(v) = self.min_numeric_value {
228 b.set_min_numeric_value(v);
229 }
230 if let Some(v) = self.max_numeric_value {
231 b.set_max_numeric_value(v);
232 }
233 if let Some(v) = self.numeric_step {
234 b.set_numeric_value_step(v);
235 }
236 for &a in &self.removed_actions {
241 b.remove_action(a);
242 }
243 for (action, _) in &self.actions {
244 b.add_action(*action);
245 }
246 if !self.custom_actions.is_empty() {
247 let custom: Vec<accesskit::CustomAction> = self
248 .custom_actions
249 .iter()
250 .enumerate()
251 .map(|(i, (label, _))| accesskit::CustomAction {
252 id: i as i32,
253 description: label.get(),
254 })
255 .collect();
256 b.set_custom_actions(custom);
257 }
258 if let Some(ref f) = self.customize {
259 f(b);
260 }
261 }
262}
263
264pub type ContextMenuFactory = Box<dyn Fn(Point, &mut EventContext) -> Option<Box<dyn Widget>>>;
291
292pub struct HandlerSet {
295 pub(crate) handlers: EventHandlers,
296 pub(crate) focusable: Option<bool>,
297 pub(crate) tab_index: Option<i32>,
298 pub(crate) cursor: Option<CursorIcon>,
299 pub(crate) clips_children: Option<bool>,
300 pub(crate) ime: Option<crate::ime::ImeContext>,
305 pub(crate) event_pass_through: Option<bool>,
309 pub(crate) gesture_dead_zone: Option<bool>,
313 pub(crate) keyboard_capture: Option<bool>,
318 pub(crate) hit_transparent: Option<bool>,
322 pub(crate) context_menu_factory: Option<ContextMenuFactory>,
323 pub(crate) focus_within: Option<crate::signal::Signal<bool>>,
327 pub(crate) hover_within: Option<crate::signal::Signal<bool>>,
331 pub(crate) visible_when: Option<Prop<bool>>,
336 pub(crate) access: Option<Box<AccessibilityOverrides>>,
344 pub(crate) access_subtree: Option<AccessSubtreeMode>,
347}
348
349impl HandlerSet {
350 pub fn new() -> Self {
352 Self {
353 handlers: EventHandlers::new(),
354 focusable: None,
355 tab_index: None,
356 cursor: None,
357 clips_children: None,
358 ime: None,
359 event_pass_through: None,
360 gesture_dead_zone: None,
361 keyboard_capture: None,
362 hit_transparent: None,
363 context_menu_factory: None,
364 focus_within: None,
365 hover_within: None,
366 visible_when: None,
367 access: None,
368 access_subtree: None,
369 }
370 }
371
372 pub(crate) fn access_mut(&mut self) -> &mut AccessibilityOverrides {
375 self.access
376 .get_or_insert_with(|| Box::new(AccessibilityOverrides::default()))
377 }
378
379 pub fn on_tap(mut self, f: impl FnMut(&TapEvent, &mut EventContext) + 'static) -> Self {
391 self.handlers.on_tap = Some(Box::new(f));
392 self
393 }
394
395 pub fn on_double_tap(mut self, f: impl FnMut(&TapEvent, &mut EventContext) + 'static) -> Self {
398 self.handlers.on_double_tap = Some(Box::new(f));
399 self
400 }
401
402 pub fn on_triple_tap(mut self, f: impl FnMut(&TapEvent, &mut EventContext) + 'static) -> Self {
407 self.handlers.on_triple_tap = Some(Box::new(f));
408 self
409 }
410
411 pub fn on_long_press(mut self, f: impl FnMut(&TapEvent, &mut EventContext) + 'static) -> Self {
416 self.handlers.on_long_press = Some(Box::new(f));
417 self
418 }
419
420 pub fn accept_tap_buttons(mut self, mask: impl Into<ButtonMask>) -> Self {
425 self.handlers.tap_buttons = Some(mask.into());
426 self
427 }
428
429 pub fn accept_double_tap_buttons(mut self, mask: impl Into<ButtonMask>) -> Self {
433 self.handlers.double_tap_buttons = Some(mask.into());
434 self
435 }
436
437 pub fn accept_triple_tap_buttons(mut self, mask: impl Into<ButtonMask>) -> Self {
441 self.handlers.triple_tap_buttons = Some(mask.into());
442 self
443 }
444
445 pub fn accept_long_press_buttons(mut self, mask: impl Into<ButtonMask>) -> Self {
449 self.handlers.long_press_buttons = Some(mask.into());
450 self
451 }
452
453 pub fn on_hover(mut self, f: impl FnMut(bool, &mut EventContext) + 'static) -> Self {
455 self.handlers.on_hover = Some(Box::new(f));
456 self
457 }
458
459 pub fn on_key(
461 mut self,
462 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
463 ) -> Self {
464 self.handlers.on_key = Some(Box::new(f));
465 self
466 }
467
468 pub fn on_key_preview(
473 mut self,
474 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
475 ) -> Self {
476 self.handlers.on_key_preview = Some(Box::new(f));
477 self
478 }
479
480 pub fn on_drag(mut self, f: impl FnMut(DragPhase, &mut EventContext) + 'static) -> Self {
484 self.handlers.on_drag = Some(Box::new(f));
485 self
486 }
487
488 pub fn on_swipe(
491 mut self,
492 f: impl FnMut(SwipeDirection, f32, &mut EventContext) + 'static,
493 ) -> Self {
494 self.handlers.on_swipe = Some(Box::new(f));
495 self
496 }
497
498 pub fn on_pinch(mut self, f: impl FnMut(PinchPhase, &mut EventContext) + 'static) -> Self {
501 self.handlers.on_pinch = Some(Box::new(f));
502 self
503 }
504
505 pub fn on_focus(mut self, f: impl FnMut(bool, &mut EventContext) + 'static) -> Self {
516 self.handlers.on_focus = Some(Box::new(f));
517 self
518 }
519
520 pub fn on_pointer_event(
522 mut self,
523 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
524 ) -> Self {
525 self.handlers.on_pointer_event = Some(Box::new(f));
526 self
527 }
528
529 pub fn on_scroll(
531 mut self,
532 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
533 ) -> Self {
534 self.handlers.on_scroll = Some(Box::new(f));
535 self
536 }
537
538 pub fn on_access_action(
540 mut self,
541 f: impl FnMut(accesskit::Action, &mut EventContext) -> EventResponse + 'static,
542 ) -> Self {
543 self.handlers.on_access_action = Some(Box::new(f));
544 self
545 }
546
547 pub fn on_access_action_request(
556 mut self,
557 f: impl FnMut(
558 accesskit::Action,
559 accesskit::NodeId,
560 Option<accesskit::ActionData>,
561 &mut EventContext,
562 ) -> EventResponse
563 + 'static,
564 ) -> Self {
565 self.handlers.on_access_action_request = Some(Box::new(f));
566 self
567 }
568
569 pub fn focusable(mut self, focusable: bool) -> Self {
571 self.focusable = Some(focusable);
572 self
573 }
574
575 pub fn cursor(mut self, cursor: CursorIcon) -> Self {
577 self.cursor = Some(cursor);
578 self
579 }
580
581 pub fn clips_children(mut self, clips: bool) -> Self {
583 self.clips_children = Some(clips);
584 self
585 }
586
587 pub fn ime_input(mut self, ctx: crate::ime::ImeContext) -> Self {
592 self.ime = Some(ctx);
593 self
594 }
595
596 pub fn event_pass_through(mut self, pass_through: bool) -> Self {
602 self.event_pass_through = Some(pass_through);
603 self
604 }
605
606 pub fn gesture_dead_zone(mut self, dead_zone: bool) -> Self {
614 self.gesture_dead_zone = Some(dead_zone);
615 self
616 }
617
618 pub fn keyboard_capture(mut self, capture: bool) -> Self {
638 self.keyboard_capture = Some(capture);
639 self
640 }
641
642 pub fn hit_transparent(mut self, transparent: bool) -> Self {
649 self.hit_transparent = Some(transparent);
650 self
651 }
652
653 pub fn focus_within(mut self, signal: crate::signal::Signal<bool>) -> Self {
664 self.focus_within = Some(signal);
665 self
666 }
667
668 pub fn hover_within(mut self, signal: crate::signal::Signal<bool>) -> Self {
672 self.hover_within = Some(signal);
673 self
674 }
675
676 pub fn visible_when(mut self, state: impl Into<Prop<bool>>) -> Self {
681 self.visible_when = Some(state.into());
682 self
683 }
684
685 pub fn context_menu(
691 mut self,
692 factory: impl Fn(Point, &mut EventContext) -> Option<Box<dyn Widget>> + 'static,
693 ) -> Self {
694 self.context_menu_factory = Some(Box::new(factory));
695 self
696 }
697
698 pub fn on_drag_hover(
701 mut self,
702 f: impl FnMut(
703 &crate::drag_payload::DragPayload,
704 teksilo_canvas::Point,
705 &mut EventContext,
706 ) -> crate::drag_state::DropFeedback
707 + 'static,
708 ) -> Self {
709 self.handlers.on_drag_hover = Some(Box::new(f));
710 self
711 }
712
713 pub fn on_drag_leave(mut self, f: impl FnMut(&mut EventContext) + 'static) -> Self {
718 self.handlers.on_drag_leave = Some(Box::new(f));
719 self
720 }
721
722 pub fn on_drag_tick(
729 mut self,
730 f: impl FnMut(teksilo_canvas::Point, &mut EventContext) + 'static,
731 ) -> Self {
732 self.handlers.on_drag_tick = Some(Box::new(f));
733 self
734 }
735
736 pub fn on_drop(
739 mut self,
740 f: impl FnMut(
741 crate::drag_payload::DragPayload,
742 teksilo_canvas::Point,
743 &mut EventContext,
744 ) -> bool
745 + 'static,
746 ) -> Self {
747 self.handlers.on_drop = Some(Box::new(f));
748 self
749 }
750
751 pub fn on_drag_ended(
757 mut self,
758 f: impl FnMut(crate::drag_payload::DropOutcome, &mut EventContext) + 'static,
759 ) -> Self {
760 self.handlers.on_drag_ended = Some(Box::new(f));
761 self
762 }
763}
764
765impl Default for HandlerSet {
766 fn default() -> Self {
767 Self::new()
768 }
769}
770
771impl std::fmt::Debug for HandlerSet {
772 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
773 f.debug_struct("HandlerSet")
774 .field("handlers", &self.handlers)
775 .field("focusable", &self.focusable)
776 .field("tab_index", &self.tab_index)
777 .field("cursor", &self.cursor)
778 .finish()
779 }
780}
781
782pub struct WidgetWithHandlers<W: Widget> {
789 pub(crate) widget: W,
790 pub(crate) handler_set: HandlerSet,
791}
792
793impl<W: Widget> WidgetWithHandlers<W> {
794 fn new(widget: W) -> Self {
795 Self {
796 widget,
797 handler_set: HandlerSet::new(),
798 }
799 }
800
801 pub(crate) fn take_handler_set(&mut self) -> HandlerSet {
803 std::mem::take(&mut self.handler_set)
804 }
805
806 pub fn on_tap(mut self, f: impl FnMut(&TapEvent, &mut EventContext) + 'static) -> Self {
809 self.handler_set.handlers.on_tap = Some(Box::new(f));
810 self
811 }
812
813 pub fn on_double_tap(mut self, f: impl FnMut(&TapEvent, &mut EventContext) + 'static) -> Self {
814 self.handler_set.handlers.on_double_tap = Some(Box::new(f));
815 self
816 }
817
818 pub fn on_triple_tap(mut self, f: impl FnMut(&TapEvent, &mut EventContext) + 'static) -> Self {
819 self.handler_set.handlers.on_triple_tap = Some(Box::new(f));
820 self
821 }
822
823 pub fn on_long_press(mut self, f: impl FnMut(&TapEvent, &mut EventContext) + 'static) -> Self {
824 self.handler_set.handlers.on_long_press = Some(Box::new(f));
825 self
826 }
827
828 pub fn accept_tap_buttons(mut self, mask: impl Into<ButtonMask>) -> Self {
831 self.handler_set.handlers.tap_buttons = Some(mask.into());
832 self
833 }
834
835 pub fn accept_double_tap_buttons(mut self, mask: impl Into<ButtonMask>) -> Self {
838 self.handler_set.handlers.double_tap_buttons = Some(mask.into());
839 self
840 }
841
842 pub fn accept_triple_tap_buttons(mut self, mask: impl Into<ButtonMask>) -> Self {
845 self.handler_set.handlers.triple_tap_buttons = Some(mask.into());
846 self
847 }
848
849 pub fn accept_long_press_buttons(mut self, mask: impl Into<ButtonMask>) -> Self {
852 self.handler_set.handlers.long_press_buttons = Some(mask.into());
853 self
854 }
855
856 pub fn on_drag(mut self, f: impl FnMut(DragPhase, &mut EventContext) + 'static) -> Self {
857 self.handler_set.handlers.on_drag = Some(Box::new(f));
858 self
859 }
860
861 pub fn on_swipe(
862 mut self,
863 f: impl FnMut(SwipeDirection, f32, &mut EventContext) + 'static,
864 ) -> Self {
865 self.handler_set.handlers.on_swipe = Some(Box::new(f));
866 self
867 }
868
869 pub fn on_pinch(mut self, f: impl FnMut(PinchPhase, &mut EventContext) + 'static) -> Self {
870 self.handler_set.handlers.on_pinch = Some(Box::new(f));
871 self
872 }
873
874 pub fn on_focus(mut self, f: impl FnMut(bool, &mut EventContext) + 'static) -> Self {
877 self.handler_set.handlers.on_focus = Some(Box::new(f));
878 self
879 }
880
881 pub fn on_key(
882 mut self,
883 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
884 ) -> Self {
885 self.handler_set.handlers.on_key = Some(Box::new(f));
886 self
887 }
888
889 pub fn on_key_preview(
892 mut self,
893 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
894 ) -> Self {
895 self.handler_set.handlers.on_key_preview = Some(Box::new(f));
896 self
897 }
898
899 pub fn focusable(mut self, focusable: bool) -> Self {
900 self.handler_set.focusable = Some(focusable);
901 self
902 }
903
904 pub fn tab_index(mut self, index: i32) -> Self {
905 self.handler_set.tab_index = Some(index);
906 self
907 }
908
909 pub fn on_pointer_event(
912 mut self,
913 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
914 ) -> Self {
915 self.handler_set.handlers.on_pointer_event = Some(Box::new(f));
916 self
917 }
918
919 pub fn on_hover(mut self, f: impl FnMut(bool, &mut EventContext) + 'static) -> Self {
920 self.handler_set.handlers.on_hover = Some(Box::new(f));
921 self
922 }
923
924 pub fn cursor(mut self, cursor: CursorIcon) -> Self {
925 self.handler_set.cursor = Some(cursor);
926 self
927 }
928
929 pub fn on_scroll(
932 mut self,
933 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
934 ) -> Self {
935 self.handler_set.handlers.on_scroll = Some(Box::new(f));
936 self
937 }
938
939 pub fn on_access_action(
942 mut self,
943 f: impl FnMut(accesskit::Action, &mut EventContext) -> EventResponse + 'static,
944 ) -> Self {
945 self.handler_set.handlers.on_access_action = Some(Box::new(f));
946 self
947 }
948
949 pub fn on_access_action_request(
950 mut self,
951 f: impl FnMut(
952 accesskit::Action,
953 accesskit::NodeId,
954 Option<accesskit::ActionData>,
955 &mut EventContext,
956 ) -> EventResponse
957 + 'static,
958 ) -> Self {
959 self.handler_set.handlers.on_access_action_request = Some(Box::new(f));
960 self
961 }
962
963 pub fn clips_children(mut self, clips: bool) -> Self {
966 self.handler_set.clips_children = Some(clips);
967 self
968 }
969
970 pub fn ime_input(mut self, ctx: crate::ime::ImeContext) -> Self {
973 self.handler_set.ime = Some(ctx);
974 self
975 }
976
977 pub fn event_pass_through(mut self, pass_through: bool) -> Self {
980 self.handler_set.event_pass_through = Some(pass_through);
981 self
982 }
983
984 pub fn gesture_dead_zone(mut self, dead_zone: bool) -> Self {
987 self.handler_set.gesture_dead_zone = Some(dead_zone);
988 self
989 }
990
991 pub fn keyboard_capture(mut self, capture: bool) -> Self {
996 self.handler_set.keyboard_capture = Some(capture);
997 self
998 }
999
1000 pub fn hit_transparent(mut self, transparent: bool) -> Self {
1003 self.handler_set.hit_transparent = Some(transparent);
1004 self
1005 }
1006
1007 pub fn context_menu(
1010 mut self,
1011 factory: impl Fn(Point, &mut EventContext) -> Option<Box<dyn Widget>> + 'static,
1012 ) -> Self {
1013 self.handler_set.context_menu_factory = Some(Box::new(factory));
1014 self
1015 }
1016
1017 pub fn focus_within(mut self, signal: crate::signal::Signal<bool>) -> Self {
1020 self.handler_set.focus_within = Some(signal);
1021 self
1022 }
1023
1024 pub fn hover_within(mut self, signal: crate::signal::Signal<bool>) -> Self {
1027 self.handler_set.hover_within = Some(signal);
1028 self
1029 }
1030
1031 pub fn visible_when(mut self, state: impl Into<Prop<bool>>) -> Self {
1033 self.handler_set.visible_when = Some(state.into());
1034 self
1035 }
1036
1037 pub fn on_drag_hover(
1039 mut self,
1040 f: impl FnMut(
1041 &crate::drag_payload::DragPayload,
1042 teksilo_canvas::Point,
1043 &mut EventContext,
1044 ) -> crate::drag_state::DropFeedback
1045 + 'static,
1046 ) -> Self {
1047 self.handler_set.handlers.on_drag_hover = Some(Box::new(f));
1048 self
1049 }
1050
1051 pub fn on_drag_leave(mut self, f: impl FnMut(&mut EventContext) + 'static) -> Self {
1053 self.handler_set.handlers.on_drag_leave = Some(Box::new(f));
1054 self
1055 }
1056
1057 pub fn on_drag_tick(
1059 mut self,
1060 f: impl FnMut(teksilo_canvas::Point, &mut EventContext) + 'static,
1061 ) -> Self {
1062 self.handler_set.handlers.on_drag_tick = Some(Box::new(f));
1063 self
1064 }
1065
1066 pub fn on_drop(
1068 mut self,
1069 f: impl FnMut(
1070 crate::drag_payload::DragPayload,
1071 teksilo_canvas::Point,
1072 &mut EventContext,
1073 ) -> bool
1074 + 'static,
1075 ) -> Self {
1076 self.handler_set.handlers.on_drop = Some(Box::new(f));
1077 self
1078 }
1079
1080 pub fn on_drag_ended(
1083 mut self,
1084 f: impl FnMut(crate::drag_payload::DropOutcome, &mut EventContext) + 'static,
1085 ) -> Self {
1086 self.handler_set.handlers.on_drag_ended = Some(Box::new(f));
1087 self
1088 }
1089
1090 pub fn access_label(mut self, label: impl Into<Prop<String>>) -> Self {
1112 self.handler_set.access_mut().label = Some(label.into());
1113 self
1114 }
1115
1116 #[doc(hidden)]
1122 pub fn access_label_literal(self, label: impl Into<String>) -> Self {
1123 self.access_label(Prop::Static(label.into()))
1124 }
1125
1126 pub fn access_description(mut self, description: impl Into<Prop<String>>) -> Self {
1129 self.handler_set.access_mut().description = Some(description.into());
1130 self
1131 }
1132
1133 #[doc(hidden)]
1134 pub fn access_description_literal(self, description: impl Into<String>) -> Self {
1135 self.access_description(Prop::Static(description.into()))
1136 }
1137
1138 pub fn access_hint(self, hint: impl Into<Prop<String>>) -> Self {
1142 self.access_description(hint)
1143 }
1144
1145 #[doc(hidden)]
1146 pub fn access_hint_literal(self, hint: impl Into<String>) -> Self {
1147 self.access_description(Prop::Static(hint.into()))
1148 }
1149
1150 pub fn access_value(mut self, value: impl Into<Prop<String>>) -> Self {
1153 self.handler_set.access_mut().value = Some(value.into());
1154 self
1155 }
1156
1157 #[doc(hidden)]
1158 pub fn access_value_literal(self, value: impl Into<String>) -> Self {
1159 self.access_value(Prop::Static(value.into()))
1160 }
1161
1162 pub fn access_role(mut self, role: accesskit::Role) -> Self {
1164 self.handler_set.access_mut().role = Some(role);
1165 self
1166 }
1167
1168 pub fn access_hidden(mut self, hidden: impl Into<Prop<bool>>) -> Self {
1175 self.handler_set.access_mut().hidden = Some(hidden.into());
1176 self
1177 }
1178
1179 pub fn access_disabled(mut self, disabled: bool) -> Self {
1184 self.handler_set.access_mut().disabled = Some(disabled);
1185 self
1186 }
1187
1188 pub fn access_identifier(mut self, id: impl Into<String>) -> Self {
1191 self.handler_set.access_mut().identifier = Some(id.into());
1192 self
1193 }
1194
1195 pub fn access_controls(mut self, target: WidgetId) -> Self {
1198 self.handler_set.access_mut().controls.push(target);
1199 self
1200 }
1201
1202 pub fn access_described_by(mut self, target: WidgetId) -> Self {
1204 self.handler_set.access_mut().described_by.push(target);
1205 self
1206 }
1207
1208 pub fn access_labelled_by(mut self, target: WidgetId) -> Self {
1210 self.handler_set.access_mut().labelled_by.push(target);
1211 self
1212 }
1213
1214 pub fn access_live(mut self, mode: accesskit::Live) -> Self {
1216 self.handler_set.access_mut().live = Some(mode);
1217 self
1218 }
1219
1220 pub fn access_current(mut self, current: accesskit::AriaCurrent) -> Self {
1223 self.handler_set.access_mut().aria_current = Some(current);
1224 self
1225 }
1226
1227 pub fn access_shortcut_literal(mut self, shortcut: impl Into<String>) -> Self {
1234 self.handler_set.access_mut().shortcut = Some(shortcut.into());
1235 self
1236 }
1237
1238 pub fn access_shortcut_id(mut self, id: impl Into<String>) -> Self {
1249 self.handler_set.access_mut().shortcut_id = Some(id.into());
1250 self
1251 }
1252
1253 pub fn access_has_popup(mut self, kind: accesskit::HasPopup) -> Self {
1256 self.handler_set.access_mut().has_popup = Some(kind);
1257 self
1258 }
1259
1260 pub fn access_orientation(mut self, orientation: accesskit::Orientation) -> Self {
1263 self.handler_set.access_mut().orientation = Some(orientation);
1264 self
1265 }
1266
1267 pub fn access_exclude_subtree(mut self) -> Self {
1271 self.handler_set.access_subtree = Some(AccessSubtreeMode::Exclude);
1272 self
1273 }
1274
1275 pub fn access_merge_subtree(mut self) -> Self {
1281 self.handler_set.access_subtree = Some(AccessSubtreeMode::Merge);
1282 self
1283 }
1284
1285 pub fn access_subtree(mut self, mode: AccessSubtreeMode) -> Self {
1287 self.handler_set.access_subtree = Some(mode);
1288 self
1289 }
1290
1291 pub fn access_numeric_value(mut self, value: f64) -> Self {
1293 self.handler_set.access_mut().numeric_value = Some(value);
1294 self
1295 }
1296
1297 pub fn access_numeric_range(mut self, min: f64, max: f64) -> Self {
1299 let access = self.handler_set.access_mut();
1300 access.min_numeric_value = Some(min);
1301 access.max_numeric_value = Some(max);
1302 self
1303 }
1304
1305 pub fn access_numeric_step(mut self, step: f64) -> Self {
1307 self.handler_set.access_mut().numeric_step = Some(step);
1308 self
1309 }
1310
1311 pub fn access_action<F>(mut self, action: accesskit::Action, handler: F) -> Self
1316 where
1317 F: FnMut(&mut EventContext) + 'static,
1318 {
1319 self.handler_set
1320 .access_mut()
1321 .actions
1322 .push((action, Box::new(handler)));
1323 self
1324 }
1325
1326 pub fn access_remove_action(mut self, action: accesskit::Action) -> Self {
1333 self.handler_set.access_mut().removed_actions.push(action);
1334 self
1335 }
1336
1337 pub fn access_custom_action<F>(mut self, label: impl Into<Prop<String>>, handler: F) -> Self
1343 where
1344 F: FnMut(&mut EventContext) + 'static,
1345 {
1346 self.handler_set
1347 .access_mut()
1348 .custom_actions
1349 .push((label.into(), Box::new(handler)));
1350 self
1351 }
1352
1353 #[doc(hidden)]
1354 pub fn access_custom_action_literal<F>(self, label: impl Into<String>, handler: F) -> Self
1355 where
1356 F: FnMut(&mut EventContext) + 'static,
1357 {
1358 self.access_custom_action(Prop::Static(label.into()), handler)
1359 }
1360
1361 pub fn access_customize<F>(mut self, f: F) -> Self
1367 where
1368 F: Fn(&mut crate::accessibility::AccessNodeBuilder) + 'static,
1369 {
1370 self.handler_set.access_mut().customize = Some(Box::new(f));
1371 self
1372 }
1373}
1374
1375impl<W: Widget> std::fmt::Debug for WidgetWithHandlers<W> {
1377 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1378 f.debug_struct("WidgetWithHandlers")
1379 .field("widget", &self.widget)
1380 .field("handler_set", &self.handler_set)
1381 .finish()
1382 }
1383}
1384
1385impl<W: Widget + 'static> Widget for WidgetWithHandlers<W> {
1386 fn build(
1387 &mut self,
1388 ctx: &mut crate::build_context::BuildContext,
1389 ) -> Vec<crate::widget_id::WidgetId> {
1390 self.widget.build(ctx)
1391 }
1392
1393 fn layout_response(
1394 &self,
1395 proposal: teksilo_canvas::SizeProposal,
1396 ctx: &crate::widget::LayoutContext,
1397 ) -> crate::widget::LayoutResponse {
1398 self.widget.layout_response(proposal, ctx)
1399 }
1400
1401 fn place_children(
1402 &self,
1403 bounds: teksilo_canvas::Rect,
1404 proposal: teksilo_canvas::SizeProposal,
1405 children: &mut [crate::widget::WidgetPlacement],
1406 ctx: &crate::widget::LayoutContext,
1407 ) {
1408 self.widget.place_children(bounds, proposal, children, ctx)
1409 }
1410
1411 fn paint(
1412 &self,
1413 bounds: teksilo_canvas::Rect,
1414 canvas: &mut teksilo_canvas::Canvas,
1415 ctx: &crate::widget::PaintContext,
1416 ) {
1417 self.widget.paint(bounds, canvas, ctx)
1418 }
1419
1420 fn accessibility(&self, builder: &mut crate::accessibility::AccessNodeBuilder) {
1421 self.widget.accessibility(builder)
1422 }
1423
1424 fn children(&self) -> Vec<crate::widget_id::WidgetId> {
1425 self.widget.children()
1426 }
1427
1428 fn as_any(&self) -> Option<&dyn std::any::Any> {
1429 self.widget.as_any()
1430 }
1431
1432 fn as_any_mut(&mut self) -> Option<&mut dyn std::any::Any> {
1442 self.widget.as_any_mut()
1443 }
1444
1445 fn clips_children(&self) -> bool {
1446 self.handler_set
1447 .clips_children
1448 .unwrap_or_else(|| self.widget.clips_children())
1449 }
1450
1451 fn take_handler_set(&mut self) -> Option<HandlerSet> {
1452 Some(self.take_handler_set())
1453 }
1454}
1455
1456pub trait WidgetBuilder: Widget + Sized + 'static {
1463 fn on_tap(
1464 self,
1465 f: impl FnMut(&TapEvent, &mut EventContext) + 'static,
1466 ) -> WidgetWithHandlers<Self> {
1467 WidgetWithHandlers::new(self).on_tap(f)
1468 }
1469
1470 fn on_double_tap(
1471 self,
1472 f: impl FnMut(&TapEvent, &mut EventContext) + 'static,
1473 ) -> WidgetWithHandlers<Self> {
1474 WidgetWithHandlers::new(self).on_double_tap(f)
1475 }
1476
1477 fn on_triple_tap(
1478 self,
1479 f: impl FnMut(&TapEvent, &mut EventContext) + 'static,
1480 ) -> WidgetWithHandlers<Self> {
1481 WidgetWithHandlers::new(self).on_triple_tap(f)
1482 }
1483
1484 fn on_long_press(
1485 self,
1486 f: impl FnMut(&TapEvent, &mut EventContext) + 'static,
1487 ) -> WidgetWithHandlers<Self> {
1488 WidgetWithHandlers::new(self).on_long_press(f)
1489 }
1490
1491 fn accept_tap_buttons(self, mask: impl Into<ButtonMask>) -> WidgetWithHandlers<Self> {
1494 WidgetWithHandlers::new(self).accept_tap_buttons(mask)
1495 }
1496
1497 fn accept_double_tap_buttons(self, mask: impl Into<ButtonMask>) -> WidgetWithHandlers<Self> {
1500 WidgetWithHandlers::new(self).accept_double_tap_buttons(mask)
1501 }
1502
1503 fn accept_triple_tap_buttons(self, mask: impl Into<ButtonMask>) -> WidgetWithHandlers<Self> {
1506 WidgetWithHandlers::new(self).accept_triple_tap_buttons(mask)
1507 }
1508
1509 fn accept_long_press_buttons(self, mask: impl Into<ButtonMask>) -> WidgetWithHandlers<Self> {
1512 WidgetWithHandlers::new(self).accept_long_press_buttons(mask)
1513 }
1514
1515 fn dim_when_inactive(self, factor: f32) -> crate::dim_when_inactive::DimWhenInactive {
1525 crate::dim_when_inactive::DimWhenInactive::new()
1526 .child(self)
1527 .factor(factor)
1528 }
1529
1530 fn dim_when_inactive_default(self) -> crate::dim_when_inactive::DimWhenInactive {
1533 crate::dim_when_inactive::DimWhenInactive::new().child(self)
1534 }
1535
1536 fn on_drag(
1537 self,
1538 f: impl FnMut(DragPhase, &mut EventContext) + 'static,
1539 ) -> WidgetWithHandlers<Self> {
1540 WidgetWithHandlers::new(self).on_drag(f)
1541 }
1542
1543 fn on_swipe(
1544 self,
1545 f: impl FnMut(SwipeDirection, f32, &mut EventContext) + 'static,
1546 ) -> WidgetWithHandlers<Self> {
1547 WidgetWithHandlers::new(self).on_swipe(f)
1548 }
1549
1550 fn on_pinch(
1551 self,
1552 f: impl FnMut(PinchPhase, &mut EventContext) + 'static,
1553 ) -> WidgetWithHandlers<Self> {
1554 WidgetWithHandlers::new(self).on_pinch(f)
1555 }
1556
1557 fn on_focus(
1558 self,
1559 f: impl FnMut(bool, &mut EventContext) + 'static,
1560 ) -> WidgetWithHandlers<Self> {
1561 WidgetWithHandlers::new(self).on_focus(f)
1562 }
1563
1564 fn on_key(
1565 self,
1566 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
1567 ) -> WidgetWithHandlers<Self> {
1568 WidgetWithHandlers::new(self).on_key(f)
1569 }
1570
1571 fn on_key_preview(
1573 self,
1574 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
1575 ) -> WidgetWithHandlers<Self> {
1576 WidgetWithHandlers::new(self).on_key_preview(f)
1577 }
1578
1579 fn on_pointer_event(
1580 self,
1581 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
1582 ) -> WidgetWithHandlers<Self> {
1583 WidgetWithHandlers::new(self).on_pointer_event(f)
1584 }
1585
1586 fn on_hover(
1587 self,
1588 f: impl FnMut(bool, &mut EventContext) + 'static,
1589 ) -> WidgetWithHandlers<Self> {
1590 WidgetWithHandlers::new(self).on_hover(f)
1591 }
1592
1593 fn on_scroll(
1594 self,
1595 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
1596 ) -> WidgetWithHandlers<Self> {
1597 WidgetWithHandlers::new(self).on_scroll(f)
1598 }
1599
1600 fn on_access_action(
1601 self,
1602 f: impl FnMut(accesskit::Action, &mut EventContext) -> EventResponse + 'static,
1603 ) -> WidgetWithHandlers<Self> {
1604 WidgetWithHandlers::new(self).on_access_action(f)
1605 }
1606
1607 fn focusable(self, focusable: bool) -> WidgetWithHandlers<Self> {
1608 WidgetWithHandlers::new(self).focusable(focusable)
1609 }
1610
1611 fn tab_index(self, index: i32) -> WidgetWithHandlers<Self> {
1612 WidgetWithHandlers::new(self).tab_index(index)
1613 }
1614
1615 fn cursor(self, cursor: CursorIcon) -> WidgetWithHandlers<Self> {
1616 WidgetWithHandlers::new(self).cursor(cursor)
1617 }
1618
1619 fn clips_children_on(self, clips: bool) -> WidgetWithHandlers<Self> {
1620 WidgetWithHandlers::new(self).clips_children(clips)
1621 }
1622
1623 fn ime_input(self, ctx: crate::ime::ImeContext) -> WidgetWithHandlers<Self> {
1626 WidgetWithHandlers::new(self).ime_input(ctx)
1627 }
1628
1629 fn event_pass_through(self, pass_through: bool) -> WidgetWithHandlers<Self> {
1632 WidgetWithHandlers::new(self).event_pass_through(pass_through)
1633 }
1634
1635 fn gesture_dead_zone(self, dead_zone: bool) -> WidgetWithHandlers<Self> {
1638 WidgetWithHandlers::new(self).gesture_dead_zone(dead_zone)
1639 }
1640
1641 fn keyboard_capture(self, capture: bool) -> WidgetWithHandlers<Self> {
1645 WidgetWithHandlers::new(self).keyboard_capture(capture)
1646 }
1647
1648 fn hit_transparent(self, transparent: bool) -> WidgetWithHandlers<Self> {
1652 WidgetWithHandlers::new(self).hit_transparent(transparent)
1653 }
1654
1655 fn context_menu(
1658 self,
1659 factory: impl Fn(Point, &mut EventContext) -> Option<Box<dyn Widget>> + 'static,
1660 ) -> WidgetWithHandlers<Self> {
1661 WidgetWithHandlers::new(self).context_menu(factory)
1662 }
1663
1664 fn focus_within(self, signal: crate::signal::Signal<bool>) -> WidgetWithHandlers<Self> {
1667 WidgetWithHandlers::new(self).focus_within(signal)
1668 }
1669
1670 fn hover_within(self, signal: crate::signal::Signal<bool>) -> WidgetWithHandlers<Self> {
1673 WidgetWithHandlers::new(self).hover_within(signal)
1674 }
1675
1676 fn visible_when(self, state: impl Into<Prop<bool>>) -> WidgetWithHandlers<Self> {
1680 WidgetWithHandlers::new(self).visible_when(state)
1681 }
1682
1683 fn on_drag_hover(
1684 self,
1685 f: impl FnMut(
1686 &crate::drag_payload::DragPayload,
1687 teksilo_canvas::Point,
1688 &mut EventContext,
1689 ) -> crate::drag_state::DropFeedback
1690 + 'static,
1691 ) -> WidgetWithHandlers<Self> {
1692 WidgetWithHandlers::new(self).on_drag_hover(f)
1693 }
1694
1695 fn on_drag_leave(self, f: impl FnMut(&mut EventContext) + 'static) -> WidgetWithHandlers<Self> {
1696 WidgetWithHandlers::new(self).on_drag_leave(f)
1697 }
1698
1699 fn on_drag_tick(
1700 self,
1701 f: impl FnMut(teksilo_canvas::Point, &mut EventContext) + 'static,
1702 ) -> WidgetWithHandlers<Self> {
1703 WidgetWithHandlers::new(self).on_drag_tick(f)
1704 }
1705
1706 fn on_drop(
1707 self,
1708 f: impl FnMut(
1709 crate::drag_payload::DragPayload,
1710 teksilo_canvas::Point,
1711 &mut EventContext,
1712 ) -> bool
1713 + 'static,
1714 ) -> WidgetWithHandlers<Self> {
1715 WidgetWithHandlers::new(self).on_drop(f)
1716 }
1717
1718 fn on_drag_ended(
1721 self,
1722 f: impl FnMut(crate::drag_payload::DropOutcome, &mut EventContext) + 'static,
1723 ) -> WidgetWithHandlers<Self> {
1724 WidgetWithHandlers::new(self).on_drag_ended(f)
1725 }
1726
1727 fn access_label(self, label: impl Into<Prop<String>>) -> WidgetWithHandlers<Self> {
1738 WidgetWithHandlers::new(self).access_label(label)
1739 }
1740
1741 #[doc(hidden)]
1742 fn access_label_literal(self, label: impl Into<String>) -> WidgetWithHandlers<Self> {
1743 WidgetWithHandlers::new(self).access_label_literal(label)
1744 }
1745
1746 fn access_description(self, description: impl Into<Prop<String>>) -> WidgetWithHandlers<Self> {
1747 WidgetWithHandlers::new(self).access_description(description)
1748 }
1749
1750 #[doc(hidden)]
1751 fn access_description_literal(
1752 self,
1753 description: impl Into<String>,
1754 ) -> WidgetWithHandlers<Self> {
1755 WidgetWithHandlers::new(self).access_description_literal(description)
1756 }
1757
1758 fn access_hint(self, hint: impl Into<Prop<String>>) -> WidgetWithHandlers<Self> {
1759 WidgetWithHandlers::new(self).access_hint(hint)
1760 }
1761
1762 #[doc(hidden)]
1763 fn access_hint_literal(self, hint: impl Into<String>) -> WidgetWithHandlers<Self> {
1764 WidgetWithHandlers::new(self).access_hint_literal(hint)
1765 }
1766
1767 fn access_value(self, value: impl Into<Prop<String>>) -> WidgetWithHandlers<Self> {
1768 WidgetWithHandlers::new(self).access_value(value)
1769 }
1770
1771 #[doc(hidden)]
1772 fn access_value_literal(self, value: impl Into<String>) -> WidgetWithHandlers<Self> {
1773 WidgetWithHandlers::new(self).access_value_literal(value)
1774 }
1775
1776 fn access_role(self, role: accesskit::Role) -> WidgetWithHandlers<Self> {
1777 WidgetWithHandlers::new(self).access_role(role)
1778 }
1779
1780 fn access_hidden(self, hidden: impl Into<Prop<bool>>) -> WidgetWithHandlers<Self> {
1781 WidgetWithHandlers::new(self).access_hidden(hidden)
1782 }
1783
1784 fn access_disabled(self, disabled: bool) -> WidgetWithHandlers<Self> {
1785 WidgetWithHandlers::new(self).access_disabled(disabled)
1786 }
1787
1788 fn access_identifier(self, id: impl Into<String>) -> WidgetWithHandlers<Self> {
1789 WidgetWithHandlers::new(self).access_identifier(id)
1790 }
1791
1792 fn access_controls(self, target: WidgetId) -> WidgetWithHandlers<Self> {
1793 WidgetWithHandlers::new(self).access_controls(target)
1794 }
1795
1796 fn access_described_by(self, target: WidgetId) -> WidgetWithHandlers<Self> {
1797 WidgetWithHandlers::new(self).access_described_by(target)
1798 }
1799
1800 fn access_labelled_by(self, target: WidgetId) -> WidgetWithHandlers<Self> {
1801 WidgetWithHandlers::new(self).access_labelled_by(target)
1802 }
1803
1804 fn access_live(self, mode: accesskit::Live) -> WidgetWithHandlers<Self> {
1805 WidgetWithHandlers::new(self).access_live(mode)
1806 }
1807
1808 fn access_current(self, current: accesskit::AriaCurrent) -> WidgetWithHandlers<Self> {
1809 WidgetWithHandlers::new(self).access_current(current)
1810 }
1811
1812 fn access_shortcut_literal(self, shortcut: impl Into<String>) -> WidgetWithHandlers<Self> {
1813 WidgetWithHandlers::new(self).access_shortcut_literal(shortcut)
1814 }
1815
1816 fn access_shortcut_id(self, id: impl Into<String>) -> WidgetWithHandlers<Self> {
1817 WidgetWithHandlers::new(self).access_shortcut_id(id)
1818 }
1819
1820 fn access_has_popup(self, kind: accesskit::HasPopup) -> WidgetWithHandlers<Self> {
1821 WidgetWithHandlers::new(self).access_has_popup(kind)
1822 }
1823
1824 fn access_orientation(self, orientation: accesskit::Orientation) -> WidgetWithHandlers<Self> {
1825 WidgetWithHandlers::new(self).access_orientation(orientation)
1826 }
1827
1828 fn access_exclude_subtree(self) -> WidgetWithHandlers<Self> {
1829 WidgetWithHandlers::new(self).access_exclude_subtree()
1830 }
1831
1832 fn access_merge_subtree(self) -> WidgetWithHandlers<Self> {
1833 WidgetWithHandlers::new(self).access_merge_subtree()
1834 }
1835
1836 fn access_subtree(self, mode: AccessSubtreeMode) -> WidgetWithHandlers<Self> {
1837 WidgetWithHandlers::new(self).access_subtree(mode)
1838 }
1839
1840 fn access_numeric_value(self, value: f64) -> WidgetWithHandlers<Self> {
1841 WidgetWithHandlers::new(self).access_numeric_value(value)
1842 }
1843
1844 fn access_numeric_range(self, min: f64, max: f64) -> WidgetWithHandlers<Self> {
1845 WidgetWithHandlers::new(self).access_numeric_range(min, max)
1846 }
1847
1848 fn access_numeric_step(self, step: f64) -> WidgetWithHandlers<Self> {
1849 WidgetWithHandlers::new(self).access_numeric_step(step)
1850 }
1851
1852 fn access_action<F>(self, action: accesskit::Action, handler: F) -> WidgetWithHandlers<Self>
1853 where
1854 F: FnMut(&mut EventContext) + 'static,
1855 {
1856 WidgetWithHandlers::new(self).access_action(action, handler)
1857 }
1858
1859 fn access_remove_action(self, action: accesskit::Action) -> WidgetWithHandlers<Self> {
1860 WidgetWithHandlers::new(self).access_remove_action(action)
1861 }
1862
1863 fn access_custom_action<F>(
1864 self,
1865 label: impl Into<Prop<String>>,
1866 handler: F,
1867 ) -> WidgetWithHandlers<Self>
1868 where
1869 F: FnMut(&mut EventContext) + 'static,
1870 {
1871 WidgetWithHandlers::new(self).access_custom_action(label, handler)
1872 }
1873
1874 #[doc(hidden)]
1875 fn access_custom_action_literal<F>(
1876 self,
1877 label: impl Into<String>,
1878 handler: F,
1879 ) -> WidgetWithHandlers<Self>
1880 where
1881 F: FnMut(&mut EventContext) + 'static,
1882 {
1883 WidgetWithHandlers::new(self).access_custom_action_literal(label, handler)
1884 }
1885
1886 fn access_customize<F>(self, f: F) -> WidgetWithHandlers<Self>
1887 where
1888 F: Fn(&mut crate::accessibility::AccessNodeBuilder) + 'static,
1889 {
1890 WidgetWithHandlers::new(self).access_customize(f)
1891 }
1892}
1893
1894impl<W: Widget + Sized + 'static> WidgetBuilder for W {}
1896
1897#[cfg(test)]
1898mod tests {
1899 use super::*;
1900 use crate::widget::WidgetPlacement;
1901 use crate::widget_id::WidgetId;
1902 use crate::widget_tree::WidgetTree;
1903
1904 #[derive(Debug)]
1905 struct CompositeLeaf {
1906 child_id: Option<WidgetId>,
1907 }
1908
1909 impl CompositeLeaf {
1910 fn new() -> Self {
1911 Self { child_id: None }
1912 }
1913 }
1914
1915 impl Widget for CompositeLeaf {
1916 fn build(&mut self, ctx: &mut crate::build_context::BuildContext) -> Vec<WidgetId> {
1917 let child = ctx.add(crate::test_widgets::FillWidget::new());
1918 self.child_id = Some(child);
1919 vec![child]
1920 }
1921
1922 fn layout_response(
1923 &self,
1924 proposal: teksilo_canvas::SizeProposal,
1925 _ctx: &crate::widget::LayoutContext,
1926 ) -> crate::widget::LayoutResponse {
1927 proposal.resolve(120.0, 40.0).into()
1928 }
1929
1930 fn place_children(
1931 &self,
1932 bounds: teksilo_canvas::Rect,
1933 _proposal: teksilo_canvas::SizeProposal,
1934 children: &mut [WidgetPlacement],
1935 _ctx: &crate::widget::LayoutContext,
1936 ) {
1937 for child in children.iter_mut() {
1938 child.origin = bounds.origin();
1939 child.size = bounds.size();
1940 }
1941 }
1942
1943 fn children(&self) -> Vec<WidgetId> {
1944 self.child_id.into_iter().collect()
1945 }
1946 }
1947
1948 #[test]
1949 fn external_handlers_survive_rebuild() {
1950 use std::cell::Cell;
1958 use std::rc::Rc;
1959
1960 let tap_count = Rc::new(Cell::new(0_u32));
1961 let tc = tap_count.clone();
1962
1963 let mut tree = WidgetTree::new();
1964 let id = tree.add(CompositeLeaf::new().on_tap(move |_pos, _ctx| {
1965 tc.set(tc.get() + 1);
1966 }));
1967 tree.layout(teksilo_canvas::SizeProposal::exact(200.0, 100.0));
1968
1969 tree.arena_mark_needs_rebuild_for_testing(id);
1972 tree.layout(teksilo_canvas::SizeProposal::exact(200.0, 100.0));
1973
1974 tree.click(id);
1977 assert_eq!(
1978 tap_count.get(),
1979 1,
1980 "externally-attached on_tap must survive a rebuild"
1981 );
1982 }
1983
1984 #[test]
1985 fn wrapped_composite_widget_still_builds_children() {
1986 let mut tree = WidgetTree::new();
1987 let root = tree.add(CompositeLeaf::new().on_tap(|_pos, _ctx| {}));
1988 tree.layout(teksilo_canvas::SizeProposal::exact(200.0, 100.0));
1989
1990 assert_eq!(tree.children(root).len(), 1);
1991 }
1992
1993 #[derive(Debug)]
1996 struct Reflective {
1997 marker: u32,
1998 }
1999
2000 impl Widget for Reflective {
2001 fn layout_response(
2002 &self,
2003 proposal: teksilo_canvas::SizeProposal,
2004 _ctx: &crate::widget::LayoutContext,
2005 ) -> crate::widget::LayoutResponse {
2006 proposal.resolve(0.0, 0.0).into()
2007 }
2008
2009 fn as_any(&self) -> Option<&dyn std::any::Any> {
2010 Some(self)
2011 }
2012
2013 fn as_any_mut(&mut self) -> Option<&mut dyn std::any::Any> {
2014 Some(self)
2015 }
2016 }
2017
2018 #[test]
2024 fn both_downcast_hooks_see_through_the_handler_wrapper() {
2025 let mut wrapped = Reflective { marker: 7 }.focusable(true);
2026
2027 let seen = wrapped
2028 .as_any()
2029 .and_then(|a| a.downcast_ref::<Reflective>())
2030 .map(|r| r.marker);
2031 assert_eq!(seen, Some(7), "as_any must forward through the wrapper");
2032
2033 let seen_mut = wrapped
2034 .as_any_mut()
2035 .and_then(|a| a.downcast_mut::<Reflective>())
2036 .map(|r| r.marker);
2037 assert_eq!(
2038 seen_mut,
2039 Some(7),
2040 "as_any_mut must forward through the wrapper too"
2041 );
2042 }
2043}