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(
554 mut self,
555 f: impl FnMut(
556 accesskit::Action,
557 accesskit::NodeId,
558 Option<accesskit::ActionData>,
559 &mut EventContext,
560 ) -> EventResponse
561 + 'static,
562 ) -> Self {
563 self.handlers.on_access_action_request = Some(Box::new(f));
564 self
565 }
566
567 pub fn focusable(mut self, focusable: bool) -> Self {
569 self.focusable = Some(focusable);
570 self
571 }
572
573 pub fn cursor(mut self, cursor: CursorIcon) -> Self {
575 self.cursor = Some(cursor);
576 self
577 }
578
579 pub fn clips_children(mut self, clips: bool) -> Self {
581 self.clips_children = Some(clips);
582 self
583 }
584
585 pub fn ime_input(mut self, ctx: crate::ime::ImeContext) -> Self {
590 self.ime = Some(ctx);
591 self
592 }
593
594 pub fn event_pass_through(mut self, pass_through: bool) -> Self {
600 self.event_pass_through = Some(pass_through);
601 self
602 }
603
604 pub fn gesture_dead_zone(mut self, dead_zone: bool) -> Self {
612 self.gesture_dead_zone = Some(dead_zone);
613 self
614 }
615
616 pub fn keyboard_capture(mut self, capture: bool) -> Self {
636 self.keyboard_capture = Some(capture);
637 self
638 }
639
640 pub fn hit_transparent(mut self, transparent: bool) -> Self {
647 self.hit_transparent = Some(transparent);
648 self
649 }
650
651 pub fn focus_within(mut self, signal: crate::signal::Signal<bool>) -> Self {
662 self.focus_within = Some(signal);
663 self
664 }
665
666 pub fn hover_within(mut self, signal: crate::signal::Signal<bool>) -> Self {
670 self.hover_within = Some(signal);
671 self
672 }
673
674 pub fn visible_when(mut self, state: impl Into<Prop<bool>>) -> Self {
679 self.visible_when = Some(state.into());
680 self
681 }
682
683 pub fn context_menu(
689 mut self,
690 factory: impl Fn(Point, &mut EventContext) -> Option<Box<dyn Widget>> + 'static,
691 ) -> Self {
692 self.context_menu_factory = Some(Box::new(factory));
693 self
694 }
695
696 pub fn on_drag_hover(
699 mut self,
700 f: impl FnMut(
701 &crate::drag_payload::DragPayload,
702 teksilo_canvas::Point,
703 &mut EventContext,
704 ) -> crate::drag_state::DropFeedback
705 + 'static,
706 ) -> Self {
707 self.handlers.on_drag_hover = Some(Box::new(f));
708 self
709 }
710
711 pub fn on_drag_leave(mut self, f: impl FnMut(&mut EventContext) + 'static) -> Self {
716 self.handlers.on_drag_leave = Some(Box::new(f));
717 self
718 }
719
720 pub fn on_drag_tick(
727 mut self,
728 f: impl FnMut(teksilo_canvas::Point, &mut EventContext) + 'static,
729 ) -> Self {
730 self.handlers.on_drag_tick = Some(Box::new(f));
731 self
732 }
733
734 pub fn on_drop(
737 mut self,
738 f: impl FnMut(
739 crate::drag_payload::DragPayload,
740 teksilo_canvas::Point,
741 &mut EventContext,
742 ) -> bool
743 + 'static,
744 ) -> Self {
745 self.handlers.on_drop = Some(Box::new(f));
746 self
747 }
748
749 pub fn on_drag_ended(
755 mut self,
756 f: impl FnMut(crate::drag_payload::DropOutcome, &mut EventContext) + 'static,
757 ) -> Self {
758 self.handlers.on_drag_ended = Some(Box::new(f));
759 self
760 }
761}
762
763impl Default for HandlerSet {
764 fn default() -> Self {
765 Self::new()
766 }
767}
768
769impl std::fmt::Debug for HandlerSet {
770 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
771 f.debug_struct("HandlerSet")
772 .field("handlers", &self.handlers)
773 .field("focusable", &self.focusable)
774 .field("tab_index", &self.tab_index)
775 .field("cursor", &self.cursor)
776 .finish()
777 }
778}
779
780pub struct WidgetWithHandlers<W: Widget> {
787 pub(crate) widget: W,
788 pub(crate) handler_set: HandlerSet,
789}
790
791impl<W: Widget> WidgetWithHandlers<W> {
792 fn new(widget: W) -> Self {
793 Self {
794 widget,
795 handler_set: HandlerSet::new(),
796 }
797 }
798
799 pub(crate) fn take_handler_set(&mut self) -> HandlerSet {
801 std::mem::take(&mut self.handler_set)
802 }
803
804 pub fn on_tap(mut self, f: impl FnMut(&TapEvent, &mut EventContext) + 'static) -> Self {
807 self.handler_set.handlers.on_tap = Some(Box::new(f));
808 self
809 }
810
811 pub fn on_double_tap(mut self, f: impl FnMut(&TapEvent, &mut EventContext) + 'static) -> Self {
812 self.handler_set.handlers.on_double_tap = Some(Box::new(f));
813 self
814 }
815
816 pub fn on_triple_tap(mut self, f: impl FnMut(&TapEvent, &mut EventContext) + 'static) -> Self {
817 self.handler_set.handlers.on_triple_tap = Some(Box::new(f));
818 self
819 }
820
821 pub fn on_long_press(mut self, f: impl FnMut(&TapEvent, &mut EventContext) + 'static) -> Self {
822 self.handler_set.handlers.on_long_press = Some(Box::new(f));
823 self
824 }
825
826 pub fn accept_tap_buttons(mut self, mask: impl Into<ButtonMask>) -> Self {
829 self.handler_set.handlers.tap_buttons = Some(mask.into());
830 self
831 }
832
833 pub fn accept_double_tap_buttons(mut self, mask: impl Into<ButtonMask>) -> Self {
836 self.handler_set.handlers.double_tap_buttons = Some(mask.into());
837 self
838 }
839
840 pub fn accept_triple_tap_buttons(mut self, mask: impl Into<ButtonMask>) -> Self {
843 self.handler_set.handlers.triple_tap_buttons = Some(mask.into());
844 self
845 }
846
847 pub fn accept_long_press_buttons(mut self, mask: impl Into<ButtonMask>) -> Self {
850 self.handler_set.handlers.long_press_buttons = Some(mask.into());
851 self
852 }
853
854 pub fn on_drag(mut self, f: impl FnMut(DragPhase, &mut EventContext) + 'static) -> Self {
855 self.handler_set.handlers.on_drag = Some(Box::new(f));
856 self
857 }
858
859 pub fn on_swipe(
860 mut self,
861 f: impl FnMut(SwipeDirection, f32, &mut EventContext) + 'static,
862 ) -> Self {
863 self.handler_set.handlers.on_swipe = Some(Box::new(f));
864 self
865 }
866
867 pub fn on_pinch(mut self, f: impl FnMut(PinchPhase, &mut EventContext) + 'static) -> Self {
868 self.handler_set.handlers.on_pinch = Some(Box::new(f));
869 self
870 }
871
872 pub fn on_focus(mut self, f: impl FnMut(bool, &mut EventContext) + 'static) -> Self {
875 self.handler_set.handlers.on_focus = Some(Box::new(f));
876 self
877 }
878
879 pub fn on_key(
880 mut self,
881 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
882 ) -> Self {
883 self.handler_set.handlers.on_key = Some(Box::new(f));
884 self
885 }
886
887 pub fn on_key_preview(
890 mut self,
891 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
892 ) -> Self {
893 self.handler_set.handlers.on_key_preview = Some(Box::new(f));
894 self
895 }
896
897 pub fn focusable(mut self, focusable: bool) -> Self {
898 self.handler_set.focusable = Some(focusable);
899 self
900 }
901
902 pub fn tab_index(mut self, index: i32) -> Self {
903 self.handler_set.tab_index = Some(index);
904 self
905 }
906
907 pub fn on_pointer_event(
910 mut self,
911 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
912 ) -> Self {
913 self.handler_set.handlers.on_pointer_event = Some(Box::new(f));
914 self
915 }
916
917 pub fn on_hover(mut self, f: impl FnMut(bool, &mut EventContext) + 'static) -> Self {
918 self.handler_set.handlers.on_hover = Some(Box::new(f));
919 self
920 }
921
922 pub fn cursor(mut self, cursor: CursorIcon) -> Self {
923 self.handler_set.cursor = Some(cursor);
924 self
925 }
926
927 pub fn on_scroll(
930 mut self,
931 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
932 ) -> Self {
933 self.handler_set.handlers.on_scroll = Some(Box::new(f));
934 self
935 }
936
937 pub fn on_access_action(
940 mut self,
941 f: impl FnMut(accesskit::Action, &mut EventContext) -> EventResponse + 'static,
942 ) -> Self {
943 self.handler_set.handlers.on_access_action = Some(Box::new(f));
944 self
945 }
946
947 pub fn on_access_action_request(
948 mut self,
949 f: impl FnMut(
950 accesskit::Action,
951 accesskit::NodeId,
952 Option<accesskit::ActionData>,
953 &mut EventContext,
954 ) -> EventResponse
955 + 'static,
956 ) -> Self {
957 self.handler_set.handlers.on_access_action_request = Some(Box::new(f));
958 self
959 }
960
961 pub fn clips_children(mut self, clips: bool) -> Self {
964 self.handler_set.clips_children = Some(clips);
965 self
966 }
967
968 pub fn ime_input(mut self, ctx: crate::ime::ImeContext) -> Self {
971 self.handler_set.ime = Some(ctx);
972 self
973 }
974
975 pub fn event_pass_through(mut self, pass_through: bool) -> Self {
978 self.handler_set.event_pass_through = Some(pass_through);
979 self
980 }
981
982 pub fn gesture_dead_zone(mut self, dead_zone: bool) -> Self {
985 self.handler_set.gesture_dead_zone = Some(dead_zone);
986 self
987 }
988
989 pub fn keyboard_capture(mut self, capture: bool) -> Self {
994 self.handler_set.keyboard_capture = Some(capture);
995 self
996 }
997
998 pub fn hit_transparent(mut self, transparent: bool) -> Self {
1001 self.handler_set.hit_transparent = Some(transparent);
1002 self
1003 }
1004
1005 pub fn context_menu(
1008 mut self,
1009 factory: impl Fn(Point, &mut EventContext) -> Option<Box<dyn Widget>> + 'static,
1010 ) -> Self {
1011 self.handler_set.context_menu_factory = Some(Box::new(factory));
1012 self
1013 }
1014
1015 pub fn focus_within(mut self, signal: crate::signal::Signal<bool>) -> Self {
1018 self.handler_set.focus_within = Some(signal);
1019 self
1020 }
1021
1022 pub fn hover_within(mut self, signal: crate::signal::Signal<bool>) -> Self {
1025 self.handler_set.hover_within = Some(signal);
1026 self
1027 }
1028
1029 pub fn visible_when(mut self, state: impl Into<Prop<bool>>) -> Self {
1031 self.handler_set.visible_when = Some(state.into());
1032 self
1033 }
1034
1035 pub fn on_drag_hover(
1037 mut self,
1038 f: impl FnMut(
1039 &crate::drag_payload::DragPayload,
1040 teksilo_canvas::Point,
1041 &mut EventContext,
1042 ) -> crate::drag_state::DropFeedback
1043 + 'static,
1044 ) -> Self {
1045 self.handler_set.handlers.on_drag_hover = Some(Box::new(f));
1046 self
1047 }
1048
1049 pub fn on_drag_leave(mut self, f: impl FnMut(&mut EventContext) + 'static) -> Self {
1051 self.handler_set.handlers.on_drag_leave = Some(Box::new(f));
1052 self
1053 }
1054
1055 pub fn on_drag_tick(
1057 mut self,
1058 f: impl FnMut(teksilo_canvas::Point, &mut EventContext) + 'static,
1059 ) -> Self {
1060 self.handler_set.handlers.on_drag_tick = Some(Box::new(f));
1061 self
1062 }
1063
1064 pub fn on_drop(
1066 mut self,
1067 f: impl FnMut(
1068 crate::drag_payload::DragPayload,
1069 teksilo_canvas::Point,
1070 &mut EventContext,
1071 ) -> bool
1072 + 'static,
1073 ) -> Self {
1074 self.handler_set.handlers.on_drop = Some(Box::new(f));
1075 self
1076 }
1077
1078 pub fn on_drag_ended(
1081 mut self,
1082 f: impl FnMut(crate::drag_payload::DropOutcome, &mut EventContext) + 'static,
1083 ) -> Self {
1084 self.handler_set.handlers.on_drag_ended = Some(Box::new(f));
1085 self
1086 }
1087
1088 pub fn access_label(mut self, label: impl Into<Prop<String>>) -> Self {
1110 self.handler_set.access_mut().label = Some(label.into());
1111 self
1112 }
1113
1114 #[doc(hidden)]
1120 pub fn access_label_literal(self, label: impl Into<String>) -> Self {
1121 self.access_label(Prop::Static(label.into()))
1122 }
1123
1124 pub fn access_description(mut self, description: impl Into<Prop<String>>) -> Self {
1127 self.handler_set.access_mut().description = Some(description.into());
1128 self
1129 }
1130
1131 #[doc(hidden)]
1132 pub fn access_description_literal(self, description: impl Into<String>) -> Self {
1133 self.access_description(Prop::Static(description.into()))
1134 }
1135
1136 pub fn access_hint(self, hint: impl Into<Prop<String>>) -> Self {
1140 self.access_description(hint)
1141 }
1142
1143 #[doc(hidden)]
1144 pub fn access_hint_literal(self, hint: impl Into<String>) -> Self {
1145 self.access_description(Prop::Static(hint.into()))
1146 }
1147
1148 pub fn access_value(mut self, value: impl Into<Prop<String>>) -> Self {
1151 self.handler_set.access_mut().value = Some(value.into());
1152 self
1153 }
1154
1155 #[doc(hidden)]
1156 pub fn access_value_literal(self, value: impl Into<String>) -> Self {
1157 self.access_value(Prop::Static(value.into()))
1158 }
1159
1160 pub fn access_role(mut self, role: accesskit::Role) -> Self {
1162 self.handler_set.access_mut().role = Some(role);
1163 self
1164 }
1165
1166 pub fn access_hidden(mut self, hidden: impl Into<Prop<bool>>) -> Self {
1173 self.handler_set.access_mut().hidden = Some(hidden.into());
1174 self
1175 }
1176
1177 pub fn access_disabled(mut self, disabled: bool) -> Self {
1182 self.handler_set.access_mut().disabled = Some(disabled);
1183 self
1184 }
1185
1186 pub fn access_identifier(mut self, id: impl Into<String>) -> Self {
1189 self.handler_set.access_mut().identifier = Some(id.into());
1190 self
1191 }
1192
1193 pub fn access_controls(mut self, target: WidgetId) -> Self {
1196 self.handler_set.access_mut().controls.push(target);
1197 self
1198 }
1199
1200 pub fn access_described_by(mut self, target: WidgetId) -> Self {
1202 self.handler_set.access_mut().described_by.push(target);
1203 self
1204 }
1205
1206 pub fn access_labelled_by(mut self, target: WidgetId) -> Self {
1208 self.handler_set.access_mut().labelled_by.push(target);
1209 self
1210 }
1211
1212 pub fn access_live(mut self, mode: accesskit::Live) -> Self {
1214 self.handler_set.access_mut().live = Some(mode);
1215 self
1216 }
1217
1218 pub fn access_current(mut self, current: accesskit::AriaCurrent) -> Self {
1221 self.handler_set.access_mut().aria_current = Some(current);
1222 self
1223 }
1224
1225 pub fn access_shortcut_literal(mut self, shortcut: impl Into<String>) -> Self {
1232 self.handler_set.access_mut().shortcut = Some(shortcut.into());
1233 self
1234 }
1235
1236 pub fn access_shortcut_id(mut self, id: impl Into<String>) -> Self {
1247 self.handler_set.access_mut().shortcut_id = Some(id.into());
1248 self
1249 }
1250
1251 pub fn access_has_popup(mut self, kind: accesskit::HasPopup) -> Self {
1254 self.handler_set.access_mut().has_popup = Some(kind);
1255 self
1256 }
1257
1258 pub fn access_orientation(mut self, orientation: accesskit::Orientation) -> Self {
1261 self.handler_set.access_mut().orientation = Some(orientation);
1262 self
1263 }
1264
1265 pub fn access_exclude_subtree(mut self) -> Self {
1269 self.handler_set.access_subtree = Some(AccessSubtreeMode::Exclude);
1270 self
1271 }
1272
1273 pub fn access_merge_subtree(mut self) -> Self {
1279 self.handler_set.access_subtree = Some(AccessSubtreeMode::Merge);
1280 self
1281 }
1282
1283 pub fn access_subtree(mut self, mode: AccessSubtreeMode) -> Self {
1285 self.handler_set.access_subtree = Some(mode);
1286 self
1287 }
1288
1289 pub fn access_numeric_value(mut self, value: f64) -> Self {
1291 self.handler_set.access_mut().numeric_value = Some(value);
1292 self
1293 }
1294
1295 pub fn access_numeric_range(mut self, min: f64, max: f64) -> Self {
1297 let access = self.handler_set.access_mut();
1298 access.min_numeric_value = Some(min);
1299 access.max_numeric_value = Some(max);
1300 self
1301 }
1302
1303 pub fn access_numeric_step(mut self, step: f64) -> Self {
1305 self.handler_set.access_mut().numeric_step = Some(step);
1306 self
1307 }
1308
1309 pub fn access_action<F>(mut self, action: accesskit::Action, handler: F) -> Self
1314 where
1315 F: FnMut(&mut EventContext) + 'static,
1316 {
1317 self.handler_set
1318 .access_mut()
1319 .actions
1320 .push((action, Box::new(handler)));
1321 self
1322 }
1323
1324 pub fn access_remove_action(mut self, action: accesskit::Action) -> Self {
1331 self.handler_set.access_mut().removed_actions.push(action);
1332 self
1333 }
1334
1335 pub fn access_custom_action<F>(mut self, label: impl Into<Prop<String>>, handler: F) -> Self
1341 where
1342 F: FnMut(&mut EventContext) + 'static,
1343 {
1344 self.handler_set
1345 .access_mut()
1346 .custom_actions
1347 .push((label.into(), Box::new(handler)));
1348 self
1349 }
1350
1351 #[doc(hidden)]
1352 pub fn access_custom_action_literal<F>(self, label: impl Into<String>, handler: F) -> Self
1353 where
1354 F: FnMut(&mut EventContext) + 'static,
1355 {
1356 self.access_custom_action(Prop::Static(label.into()), handler)
1357 }
1358
1359 pub fn access_customize<F>(mut self, f: F) -> Self
1365 where
1366 F: Fn(&mut crate::accessibility::AccessNodeBuilder) + 'static,
1367 {
1368 self.handler_set.access_mut().customize = Some(Box::new(f));
1369 self
1370 }
1371}
1372
1373impl<W: Widget> std::fmt::Debug for WidgetWithHandlers<W> {
1375 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1376 f.debug_struct("WidgetWithHandlers")
1377 .field("widget", &self.widget)
1378 .field("handler_set", &self.handler_set)
1379 .finish()
1380 }
1381}
1382
1383impl<W: Widget + 'static> Widget for WidgetWithHandlers<W> {
1384 fn build(
1385 &mut self,
1386 ctx: &mut crate::build_context::BuildContext,
1387 ) -> Vec<crate::widget_id::WidgetId> {
1388 self.widget.build(ctx)
1389 }
1390
1391 fn layout_response(
1392 &self,
1393 proposal: teksilo_canvas::SizeProposal,
1394 ctx: &crate::widget::LayoutContext,
1395 ) -> crate::widget::LayoutResponse {
1396 self.widget.layout_response(proposal, ctx)
1397 }
1398
1399 fn place_children(
1400 &self,
1401 bounds: teksilo_canvas::Rect,
1402 proposal: teksilo_canvas::SizeProposal,
1403 children: &mut [crate::widget::WidgetPlacement],
1404 ctx: &crate::widget::LayoutContext,
1405 ) {
1406 self.widget.place_children(bounds, proposal, children, ctx)
1407 }
1408
1409 fn paint(
1410 &self,
1411 bounds: teksilo_canvas::Rect,
1412 canvas: &mut teksilo_canvas::Canvas,
1413 ctx: &crate::widget::PaintContext,
1414 ) {
1415 self.widget.paint(bounds, canvas, ctx)
1416 }
1417
1418 fn accessibility(&self, builder: &mut crate::accessibility::AccessNodeBuilder) {
1419 self.widget.accessibility(builder)
1420 }
1421
1422 fn children(&self) -> Vec<crate::widget_id::WidgetId> {
1423 self.widget.children()
1424 }
1425
1426 fn as_any(&self) -> Option<&dyn std::any::Any> {
1427 self.widget.as_any()
1428 }
1429
1430 fn as_any_mut(&mut self) -> Option<&mut dyn std::any::Any> {
1440 self.widget.as_any_mut()
1441 }
1442
1443 fn clips_children(&self) -> bool {
1444 self.handler_set
1445 .clips_children
1446 .unwrap_or_else(|| self.widget.clips_children())
1447 }
1448
1449 fn take_handler_set(&mut self) -> Option<HandlerSet> {
1450 Some(self.take_handler_set())
1451 }
1452}
1453
1454pub trait WidgetBuilder: Widget + Sized + 'static {
1461 fn on_tap(
1462 self,
1463 f: impl FnMut(&TapEvent, &mut EventContext) + 'static,
1464 ) -> WidgetWithHandlers<Self> {
1465 WidgetWithHandlers::new(self).on_tap(f)
1466 }
1467
1468 fn on_double_tap(
1469 self,
1470 f: impl FnMut(&TapEvent, &mut EventContext) + 'static,
1471 ) -> WidgetWithHandlers<Self> {
1472 WidgetWithHandlers::new(self).on_double_tap(f)
1473 }
1474
1475 fn on_triple_tap(
1476 self,
1477 f: impl FnMut(&TapEvent, &mut EventContext) + 'static,
1478 ) -> WidgetWithHandlers<Self> {
1479 WidgetWithHandlers::new(self).on_triple_tap(f)
1480 }
1481
1482 fn on_long_press(
1483 self,
1484 f: impl FnMut(&TapEvent, &mut EventContext) + 'static,
1485 ) -> WidgetWithHandlers<Self> {
1486 WidgetWithHandlers::new(self).on_long_press(f)
1487 }
1488
1489 fn accept_tap_buttons(self, mask: impl Into<ButtonMask>) -> WidgetWithHandlers<Self> {
1492 WidgetWithHandlers::new(self).accept_tap_buttons(mask)
1493 }
1494
1495 fn accept_double_tap_buttons(self, mask: impl Into<ButtonMask>) -> WidgetWithHandlers<Self> {
1498 WidgetWithHandlers::new(self).accept_double_tap_buttons(mask)
1499 }
1500
1501 fn accept_triple_tap_buttons(self, mask: impl Into<ButtonMask>) -> WidgetWithHandlers<Self> {
1504 WidgetWithHandlers::new(self).accept_triple_tap_buttons(mask)
1505 }
1506
1507 fn accept_long_press_buttons(self, mask: impl Into<ButtonMask>) -> WidgetWithHandlers<Self> {
1510 WidgetWithHandlers::new(self).accept_long_press_buttons(mask)
1511 }
1512
1513 fn dim_when_inactive(self, factor: f32) -> crate::dim_when_inactive::DimWhenInactive {
1523 crate::dim_when_inactive::DimWhenInactive::new()
1524 .child(self)
1525 .factor(factor)
1526 }
1527
1528 fn dim_when_inactive_default(self) -> crate::dim_when_inactive::DimWhenInactive {
1531 crate::dim_when_inactive::DimWhenInactive::new().child(self)
1532 }
1533
1534 fn on_drag(
1535 self,
1536 f: impl FnMut(DragPhase, &mut EventContext) + 'static,
1537 ) -> WidgetWithHandlers<Self> {
1538 WidgetWithHandlers::new(self).on_drag(f)
1539 }
1540
1541 fn on_swipe(
1542 self,
1543 f: impl FnMut(SwipeDirection, f32, &mut EventContext) + 'static,
1544 ) -> WidgetWithHandlers<Self> {
1545 WidgetWithHandlers::new(self).on_swipe(f)
1546 }
1547
1548 fn on_pinch(
1549 self,
1550 f: impl FnMut(PinchPhase, &mut EventContext) + 'static,
1551 ) -> WidgetWithHandlers<Self> {
1552 WidgetWithHandlers::new(self).on_pinch(f)
1553 }
1554
1555 fn on_focus(
1556 self,
1557 f: impl FnMut(bool, &mut EventContext) + 'static,
1558 ) -> WidgetWithHandlers<Self> {
1559 WidgetWithHandlers::new(self).on_focus(f)
1560 }
1561
1562 fn on_key(
1563 self,
1564 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
1565 ) -> WidgetWithHandlers<Self> {
1566 WidgetWithHandlers::new(self).on_key(f)
1567 }
1568
1569 fn on_key_preview(
1571 self,
1572 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
1573 ) -> WidgetWithHandlers<Self> {
1574 WidgetWithHandlers::new(self).on_key_preview(f)
1575 }
1576
1577 fn on_pointer_event(
1578 self,
1579 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
1580 ) -> WidgetWithHandlers<Self> {
1581 WidgetWithHandlers::new(self).on_pointer_event(f)
1582 }
1583
1584 fn on_hover(
1585 self,
1586 f: impl FnMut(bool, &mut EventContext) + 'static,
1587 ) -> WidgetWithHandlers<Self> {
1588 WidgetWithHandlers::new(self).on_hover(f)
1589 }
1590
1591 fn on_scroll(
1592 self,
1593 f: impl FnMut(&WidgetEvent, &mut EventContext) -> EventResponse + 'static,
1594 ) -> WidgetWithHandlers<Self> {
1595 WidgetWithHandlers::new(self).on_scroll(f)
1596 }
1597
1598 fn on_access_action(
1599 self,
1600 f: impl FnMut(accesskit::Action, &mut EventContext) -> EventResponse + 'static,
1601 ) -> WidgetWithHandlers<Self> {
1602 WidgetWithHandlers::new(self).on_access_action(f)
1603 }
1604
1605 fn focusable(self, focusable: bool) -> WidgetWithHandlers<Self> {
1606 WidgetWithHandlers::new(self).focusable(focusable)
1607 }
1608
1609 fn tab_index(self, index: i32) -> WidgetWithHandlers<Self> {
1610 WidgetWithHandlers::new(self).tab_index(index)
1611 }
1612
1613 fn cursor(self, cursor: CursorIcon) -> WidgetWithHandlers<Self> {
1614 WidgetWithHandlers::new(self).cursor(cursor)
1615 }
1616
1617 fn clips_children_on(self, clips: bool) -> WidgetWithHandlers<Self> {
1618 WidgetWithHandlers::new(self).clips_children(clips)
1619 }
1620
1621 fn ime_input(self, ctx: crate::ime::ImeContext) -> WidgetWithHandlers<Self> {
1624 WidgetWithHandlers::new(self).ime_input(ctx)
1625 }
1626
1627 fn event_pass_through(self, pass_through: bool) -> WidgetWithHandlers<Self> {
1630 WidgetWithHandlers::new(self).event_pass_through(pass_through)
1631 }
1632
1633 fn gesture_dead_zone(self, dead_zone: bool) -> WidgetWithHandlers<Self> {
1636 WidgetWithHandlers::new(self).gesture_dead_zone(dead_zone)
1637 }
1638
1639 fn keyboard_capture(self, capture: bool) -> WidgetWithHandlers<Self> {
1643 WidgetWithHandlers::new(self).keyboard_capture(capture)
1644 }
1645
1646 fn hit_transparent(self, transparent: bool) -> WidgetWithHandlers<Self> {
1650 WidgetWithHandlers::new(self).hit_transparent(transparent)
1651 }
1652
1653 fn context_menu(
1656 self,
1657 factory: impl Fn(Point, &mut EventContext) -> Option<Box<dyn Widget>> + 'static,
1658 ) -> WidgetWithHandlers<Self> {
1659 WidgetWithHandlers::new(self).context_menu(factory)
1660 }
1661
1662 fn focus_within(self, signal: crate::signal::Signal<bool>) -> WidgetWithHandlers<Self> {
1665 WidgetWithHandlers::new(self).focus_within(signal)
1666 }
1667
1668 fn hover_within(self, signal: crate::signal::Signal<bool>) -> WidgetWithHandlers<Self> {
1671 WidgetWithHandlers::new(self).hover_within(signal)
1672 }
1673
1674 fn visible_when(self, state: impl Into<Prop<bool>>) -> WidgetWithHandlers<Self> {
1678 WidgetWithHandlers::new(self).visible_when(state)
1679 }
1680
1681 fn on_drag_hover(
1682 self,
1683 f: impl FnMut(
1684 &crate::drag_payload::DragPayload,
1685 teksilo_canvas::Point,
1686 &mut EventContext,
1687 ) -> crate::drag_state::DropFeedback
1688 + 'static,
1689 ) -> WidgetWithHandlers<Self> {
1690 WidgetWithHandlers::new(self).on_drag_hover(f)
1691 }
1692
1693 fn on_drag_leave(self, f: impl FnMut(&mut EventContext) + 'static) -> WidgetWithHandlers<Self> {
1694 WidgetWithHandlers::new(self).on_drag_leave(f)
1695 }
1696
1697 fn on_drag_tick(
1698 self,
1699 f: impl FnMut(teksilo_canvas::Point, &mut EventContext) + 'static,
1700 ) -> WidgetWithHandlers<Self> {
1701 WidgetWithHandlers::new(self).on_drag_tick(f)
1702 }
1703
1704 fn on_drop(
1705 self,
1706 f: impl FnMut(
1707 crate::drag_payload::DragPayload,
1708 teksilo_canvas::Point,
1709 &mut EventContext,
1710 ) -> bool
1711 + 'static,
1712 ) -> WidgetWithHandlers<Self> {
1713 WidgetWithHandlers::new(self).on_drop(f)
1714 }
1715
1716 fn on_drag_ended(
1719 self,
1720 f: impl FnMut(crate::drag_payload::DropOutcome, &mut EventContext) + 'static,
1721 ) -> WidgetWithHandlers<Self> {
1722 WidgetWithHandlers::new(self).on_drag_ended(f)
1723 }
1724
1725 fn access_label(self, label: impl Into<Prop<String>>) -> WidgetWithHandlers<Self> {
1736 WidgetWithHandlers::new(self).access_label(label)
1737 }
1738
1739 #[doc(hidden)]
1740 fn access_label_literal(self, label: impl Into<String>) -> WidgetWithHandlers<Self> {
1741 WidgetWithHandlers::new(self).access_label_literal(label)
1742 }
1743
1744 fn access_description(self, description: impl Into<Prop<String>>) -> WidgetWithHandlers<Self> {
1745 WidgetWithHandlers::new(self).access_description(description)
1746 }
1747
1748 #[doc(hidden)]
1749 fn access_description_literal(
1750 self,
1751 description: impl Into<String>,
1752 ) -> WidgetWithHandlers<Self> {
1753 WidgetWithHandlers::new(self).access_description_literal(description)
1754 }
1755
1756 fn access_hint(self, hint: impl Into<Prop<String>>) -> WidgetWithHandlers<Self> {
1757 WidgetWithHandlers::new(self).access_hint(hint)
1758 }
1759
1760 #[doc(hidden)]
1761 fn access_hint_literal(self, hint: impl Into<String>) -> WidgetWithHandlers<Self> {
1762 WidgetWithHandlers::new(self).access_hint_literal(hint)
1763 }
1764
1765 fn access_value(self, value: impl Into<Prop<String>>) -> WidgetWithHandlers<Self> {
1766 WidgetWithHandlers::new(self).access_value(value)
1767 }
1768
1769 #[doc(hidden)]
1770 fn access_value_literal(self, value: impl Into<String>) -> WidgetWithHandlers<Self> {
1771 WidgetWithHandlers::new(self).access_value_literal(value)
1772 }
1773
1774 fn access_role(self, role: accesskit::Role) -> WidgetWithHandlers<Self> {
1775 WidgetWithHandlers::new(self).access_role(role)
1776 }
1777
1778 fn access_hidden(self, hidden: impl Into<Prop<bool>>) -> WidgetWithHandlers<Self> {
1779 WidgetWithHandlers::new(self).access_hidden(hidden)
1780 }
1781
1782 fn access_disabled(self, disabled: bool) -> WidgetWithHandlers<Self> {
1783 WidgetWithHandlers::new(self).access_disabled(disabled)
1784 }
1785
1786 fn access_identifier(self, id: impl Into<String>) -> WidgetWithHandlers<Self> {
1787 WidgetWithHandlers::new(self).access_identifier(id)
1788 }
1789
1790 fn access_controls(self, target: WidgetId) -> WidgetWithHandlers<Self> {
1791 WidgetWithHandlers::new(self).access_controls(target)
1792 }
1793
1794 fn access_described_by(self, target: WidgetId) -> WidgetWithHandlers<Self> {
1795 WidgetWithHandlers::new(self).access_described_by(target)
1796 }
1797
1798 fn access_labelled_by(self, target: WidgetId) -> WidgetWithHandlers<Self> {
1799 WidgetWithHandlers::new(self).access_labelled_by(target)
1800 }
1801
1802 fn access_live(self, mode: accesskit::Live) -> WidgetWithHandlers<Self> {
1803 WidgetWithHandlers::new(self).access_live(mode)
1804 }
1805
1806 fn access_current(self, current: accesskit::AriaCurrent) -> WidgetWithHandlers<Self> {
1807 WidgetWithHandlers::new(self).access_current(current)
1808 }
1809
1810 fn access_shortcut_literal(self, shortcut: impl Into<String>) -> WidgetWithHandlers<Self> {
1811 WidgetWithHandlers::new(self).access_shortcut_literal(shortcut)
1812 }
1813
1814 fn access_shortcut_id(self, id: impl Into<String>) -> WidgetWithHandlers<Self> {
1815 WidgetWithHandlers::new(self).access_shortcut_id(id)
1816 }
1817
1818 fn access_has_popup(self, kind: accesskit::HasPopup) -> WidgetWithHandlers<Self> {
1819 WidgetWithHandlers::new(self).access_has_popup(kind)
1820 }
1821
1822 fn access_orientation(self, orientation: accesskit::Orientation) -> WidgetWithHandlers<Self> {
1823 WidgetWithHandlers::new(self).access_orientation(orientation)
1824 }
1825
1826 fn access_exclude_subtree(self) -> WidgetWithHandlers<Self> {
1827 WidgetWithHandlers::new(self).access_exclude_subtree()
1828 }
1829
1830 fn access_merge_subtree(self) -> WidgetWithHandlers<Self> {
1831 WidgetWithHandlers::new(self).access_merge_subtree()
1832 }
1833
1834 fn access_subtree(self, mode: AccessSubtreeMode) -> WidgetWithHandlers<Self> {
1835 WidgetWithHandlers::new(self).access_subtree(mode)
1836 }
1837
1838 fn access_numeric_value(self, value: f64) -> WidgetWithHandlers<Self> {
1839 WidgetWithHandlers::new(self).access_numeric_value(value)
1840 }
1841
1842 fn access_numeric_range(self, min: f64, max: f64) -> WidgetWithHandlers<Self> {
1843 WidgetWithHandlers::new(self).access_numeric_range(min, max)
1844 }
1845
1846 fn access_numeric_step(self, step: f64) -> WidgetWithHandlers<Self> {
1847 WidgetWithHandlers::new(self).access_numeric_step(step)
1848 }
1849
1850 fn access_action<F>(self, action: accesskit::Action, handler: F) -> WidgetWithHandlers<Self>
1851 where
1852 F: FnMut(&mut EventContext) + 'static,
1853 {
1854 WidgetWithHandlers::new(self).access_action(action, handler)
1855 }
1856
1857 fn access_remove_action(self, action: accesskit::Action) -> WidgetWithHandlers<Self> {
1858 WidgetWithHandlers::new(self).access_remove_action(action)
1859 }
1860
1861 fn access_custom_action<F>(
1862 self,
1863 label: impl Into<Prop<String>>,
1864 handler: F,
1865 ) -> WidgetWithHandlers<Self>
1866 where
1867 F: FnMut(&mut EventContext) + 'static,
1868 {
1869 WidgetWithHandlers::new(self).access_custom_action(label, handler)
1870 }
1871
1872 #[doc(hidden)]
1873 fn access_custom_action_literal<F>(
1874 self,
1875 label: impl Into<String>,
1876 handler: F,
1877 ) -> WidgetWithHandlers<Self>
1878 where
1879 F: FnMut(&mut EventContext) + 'static,
1880 {
1881 WidgetWithHandlers::new(self).access_custom_action_literal(label, handler)
1882 }
1883
1884 fn access_customize<F>(self, f: F) -> WidgetWithHandlers<Self>
1885 where
1886 F: Fn(&mut crate::accessibility::AccessNodeBuilder) + 'static,
1887 {
1888 WidgetWithHandlers::new(self).access_customize(f)
1889 }
1890}
1891
1892impl<W: Widget + Sized + 'static> WidgetBuilder for W {}
1894
1895#[cfg(test)]
1896mod tests {
1897 use super::*;
1898 use crate::widget::WidgetPlacement;
1899 use crate::widget_id::WidgetId;
1900 use crate::widget_tree::WidgetTree;
1901
1902 #[derive(Debug)]
1903 struct CompositeLeaf {
1904 child_id: Option<WidgetId>,
1905 }
1906
1907 impl CompositeLeaf {
1908 fn new() -> Self {
1909 Self { child_id: None }
1910 }
1911 }
1912
1913 impl Widget for CompositeLeaf {
1914 fn build(&mut self, ctx: &mut crate::build_context::BuildContext) -> Vec<WidgetId> {
1915 let child = ctx.add(crate::test_widgets::FillWidget::new());
1916 self.child_id = Some(child);
1917 vec![child]
1918 }
1919
1920 fn layout_response(
1921 &self,
1922 proposal: teksilo_canvas::SizeProposal,
1923 _ctx: &crate::widget::LayoutContext,
1924 ) -> crate::widget::LayoutResponse {
1925 proposal.resolve(120.0, 40.0).into()
1926 }
1927
1928 fn place_children(
1929 &self,
1930 bounds: teksilo_canvas::Rect,
1931 _proposal: teksilo_canvas::SizeProposal,
1932 children: &mut [WidgetPlacement],
1933 _ctx: &crate::widget::LayoutContext,
1934 ) {
1935 for child in children.iter_mut() {
1936 child.origin = bounds.origin();
1937 child.size = bounds.size();
1938 }
1939 }
1940
1941 fn children(&self) -> Vec<WidgetId> {
1942 self.child_id.into_iter().collect()
1943 }
1944 }
1945
1946 #[test]
1947 fn external_handlers_survive_rebuild() {
1948 use std::cell::Cell;
1956 use std::rc::Rc;
1957
1958 let tap_count = Rc::new(Cell::new(0_u32));
1959 let tc = tap_count.clone();
1960
1961 let mut tree = WidgetTree::new();
1962 let id = tree.add(CompositeLeaf::new().on_tap(move |_pos, _ctx| {
1963 tc.set(tc.get() + 1);
1964 }));
1965 tree.layout(teksilo_canvas::SizeProposal::exact(200.0, 100.0));
1966
1967 tree.arena_mark_needs_rebuild_for_testing(id);
1970 tree.layout(teksilo_canvas::SizeProposal::exact(200.0, 100.0));
1971
1972 tree.click(id);
1975 assert_eq!(
1976 tap_count.get(),
1977 1,
1978 "externally-attached on_tap must survive a rebuild"
1979 );
1980 }
1981
1982 #[test]
1983 fn wrapped_composite_widget_still_builds_children() {
1984 let mut tree = WidgetTree::new();
1985 let root = tree.add(CompositeLeaf::new().on_tap(|_pos, _ctx| {}));
1986 tree.layout(teksilo_canvas::SizeProposal::exact(200.0, 100.0));
1987
1988 assert_eq!(tree.children(root).len(), 1);
1989 }
1990
1991 #[derive(Debug)]
1994 struct Reflective {
1995 marker: u32,
1996 }
1997
1998 impl Widget for Reflective {
1999 fn layout_response(
2000 &self,
2001 proposal: teksilo_canvas::SizeProposal,
2002 _ctx: &crate::widget::LayoutContext,
2003 ) -> crate::widget::LayoutResponse {
2004 proposal.resolve(0.0, 0.0).into()
2005 }
2006
2007 fn as_any(&self) -> Option<&dyn std::any::Any> {
2008 Some(self)
2009 }
2010
2011 fn as_any_mut(&mut self) -> Option<&mut dyn std::any::Any> {
2012 Some(self)
2013 }
2014 }
2015
2016 #[test]
2022 fn both_downcast_hooks_see_through_the_handler_wrapper() {
2023 let mut wrapped = Reflective { marker: 7 }.focusable(true);
2024
2025 let seen = wrapped
2026 .as_any()
2027 .and_then(|a| a.downcast_ref::<Reflective>())
2028 .map(|r| r.marker);
2029 assert_eq!(seen, Some(7), "as_any must forward through the wrapper");
2030
2031 let seen_mut = wrapped
2032 .as_any_mut()
2033 .and_then(|a| a.downcast_mut::<Reflective>())
2034 .map(|r| r.marker);
2035 assert_eq!(
2036 seen_mut,
2037 Some(7),
2038 "as_any_mut must forward through the wrapper too"
2039 );
2040 }
2041}