1use std::{
9 any::{Any, TypeId, type_name},
10 cell::{Cell, RefCell},
11 fmt,
12 hash::{Hash, Hasher},
13 ops::{BitOr, BitOrAssign},
14 rc::Rc,
15};
16
17use cranpose_core::{ProvidedValue, collections::map::HashMap, hash::default};
18pub use cranpose_ui_graphics::{DrawScope, Size};
19pub use cranpose_ui_layout::{Constraints, Measurable};
20
21use crate::nodes::input::types::PointerEvent;
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
26pub enum InvalidationKind {
27 Layout,
28 Draw,
29 PointerInput,
30 Semantics,
31 Focus,
32}
33
34pub trait ModifierNodeContext {
36 fn invalidate(&mut self, _kind: InvalidationKind) {}
38
39 fn request_update(&mut self) {}
42
43 fn node_id(&self) -> Option<cranpose_core::NodeId> {
46 None
47 }
48
49 fn push_active_capabilities(&mut self, _capabilities: NodeCapabilities) {}
51
52 fn pop_active_capabilities(&mut self) {}
54
55 fn density(&self) -> f32 {
60 1.0
61 }
62}
63
64#[derive(Default, Debug, Clone)]
73pub struct BasicModifierNodeContext {
74 invalidations: ModifierInvalidations,
75 update_requested: bool,
76 active_capabilities: Vec<NodeCapabilities>,
77 node_id: Option<cranpose_core::NodeId>,
78}
79
80impl BasicModifierNodeContext {
81 pub fn new() -> Self {
83 Self::default()
84 }
85
86 pub fn invalidations(&self) -> &[ModifierInvalidation] {
90 &self.invalidations
91 }
92
93 pub fn clear_invalidations(&mut self) {
95 self.invalidations.clear();
96 }
97
98 pub fn take_invalidations(&mut self) -> ModifierInvalidations {
100 std::mem::take(&mut self.invalidations)
101 }
102
103 pub fn update_requested(&self) -> bool {
106 self.update_requested
107 }
108
109 pub fn take_update_requested(&mut self) -> bool {
111 std::mem::take(&mut self.update_requested)
112 }
113
114 pub fn set_node_id(&mut self, id: Option<cranpose_core::NodeId>) {
116 self.node_id = id;
117 }
118
119 fn push_invalidation(&mut self, kind: InvalidationKind) {
120 let mut capabilities = self.current_capabilities();
121 capabilities.insert(NodeCapabilities::for_invalidation(kind));
122 if let Some(existing) = self
123 .invalidations
124 .iter_mut()
125 .find(|entry| entry.kind() == kind)
126 {
127 let updated = existing.capabilities() | capabilities;
128 *existing = ModifierInvalidation::new(kind, updated);
129 } else {
130 self.invalidations
131 .push(ModifierInvalidation::new(kind, capabilities));
132 }
133 }
134
135 fn current_capabilities(&self) -> NodeCapabilities {
136 self.active_capabilities
137 .last()
138 .copied()
139 .unwrap_or_else(NodeCapabilities::empty)
140 }
141}
142
143impl ModifierNodeContext for BasicModifierNodeContext {
144 fn invalidate(&mut self, kind: InvalidationKind) {
145 self.push_invalidation(kind);
146 }
147
148 fn request_update(&mut self) {
149 self.update_requested = true;
150 }
151
152 fn push_active_capabilities(&mut self, capabilities: NodeCapabilities) {
153 self.active_capabilities.push(capabilities);
154 }
155
156 fn pop_active_capabilities(&mut self) {
157 self.active_capabilities.pop();
158 }
159
160 fn node_id(&self) -> Option<cranpose_core::NodeId> {
161 self.node_id
162 }
163}
164
165const MAX_DELEGATE_DEPTH: usize = 3;
166
167#[derive(Copy, Clone, Debug, PartialEq, Eq)]
168pub(crate) struct NodePath {
169 entry: u32,
172 delegate_buf: [u8; MAX_DELEGATE_DEPTH],
173 delegate_len: u8,
174}
175
176impl NodePath {
177 #[inline]
178 fn root(entry: usize) -> Self {
179 debug_assert!(entry <= u32::MAX as usize, "chain entry exceeds u32 range");
180 Self {
181 entry: entry as u32,
182 delegate_buf: [0; MAX_DELEGATE_DEPTH],
183 delegate_len: 0,
184 }
185 }
186
187 #[inline]
188 fn from_slice(entry: usize, path: &[usize]) -> Self {
189 debug_assert!(
190 path.len() <= MAX_DELEGATE_DEPTH,
191 "delegate depth {} exceeds MAX_DELEGATE_DEPTH {}",
192 path.len(),
193 MAX_DELEGATE_DEPTH
194 );
195 debug_assert!(
196 path.iter().all(|&i| i <= u8::MAX as usize),
197 "delegate index exceeds u8 range"
198 );
199 let mut delegate_buf = [0u8; MAX_DELEGATE_DEPTH];
200 for (i, &v) in path.iter().enumerate().take(MAX_DELEGATE_DEPTH) {
201 delegate_buf[i] = v as u8;
202 }
203 Self {
204 delegate_buf,
205 delegate_len: path.len().min(MAX_DELEGATE_DEPTH) as u8,
206 ..Self::root(entry)
207 }
208 }
209
210 #[inline]
211 fn entry(&self) -> usize {
212 self.entry as usize
213 }
214
215 #[inline]
216 fn delegates(&self) -> &[u8] {
217 &self.delegate_buf[..self.delegate_len as usize]
218 }
219}
220
221#[derive(Copy, Clone, Debug, PartialEq, Eq)]
222pub(crate) enum NodeLink {
223 Head,
224 Tail,
225 Entry(NodePath),
226}
227
228#[derive(Debug)]
234pub struct NodeState {
235 aggregate_child_capabilities: Cell<NodeCapabilities>,
236 capabilities: Cell<NodeCapabilities>,
237 parent: Cell<Option<NodeLink>>,
238 child: Cell<Option<NodeLink>>,
239 attached: Cell<bool>,
240 is_sentinel: bool,
241}
242
243impl Default for NodeState {
244 fn default() -> Self {
245 Self::new()
246 }
247}
248
249impl NodeState {
250 pub const fn new() -> Self {
251 Self {
252 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
253 capabilities: Cell::new(NodeCapabilities::empty()),
254 parent: Cell::new(None),
255 child: Cell::new(None),
256 attached: Cell::new(false),
257 is_sentinel: false,
258 }
259 }
260
261 pub const fn sentinel() -> Self {
262 Self {
263 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
264 capabilities: Cell::new(NodeCapabilities::empty()),
265 parent: Cell::new(None),
266 child: Cell::new(None),
267 attached: Cell::new(true),
268 is_sentinel: true,
269 }
270 }
271
272 pub fn set_capabilities(&self, capabilities: NodeCapabilities) {
273 self.capabilities.set(capabilities);
274 }
275
276 #[inline]
277 pub fn capabilities(&self) -> NodeCapabilities {
278 self.capabilities.get()
279 }
280
281 pub fn set_aggregate_child_capabilities(&self, capabilities: NodeCapabilities) {
282 self.aggregate_child_capabilities.set(capabilities);
283 }
284
285 #[inline]
286 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
287 self.aggregate_child_capabilities.get()
288 }
289
290 pub(crate) fn set_parent_link(&self, parent: Option<NodeLink>) {
291 self.parent.set(parent);
292 }
293
294 #[inline]
295 pub(crate) fn parent_link(&self) -> Option<NodeLink> {
296 self.parent.get()
297 }
298
299 pub(crate) fn set_child_link(&self, child: Option<NodeLink>) {
300 self.child.set(child);
301 }
302
303 #[inline]
304 pub(crate) fn child_link(&self) -> Option<NodeLink> {
305 self.child.get()
306 }
307
308 pub fn set_attached(&self, attached: bool) {
309 self.attached.set(attached);
310 }
311
312 pub fn is_attached(&self) -> bool {
313 self.attached.get()
314 }
315
316 pub fn is_sentinel(&self) -> bool {
317 self.is_sentinel
318 }
319}
320
321pub trait DelegatableNode {
323 fn node_state(&self) -> &NodeState;
324 fn aggregate_child_capabilities(&self) -> NodeCapabilities {
325 self.node_state().aggregate_child_capabilities()
326 }
327}
328
329pub trait ModifierNode: Any + DelegatableNode {
387 fn on_attach(&mut self, _context: &mut dyn ModifierNodeContext) {}
388
389 fn on_detach(&mut self) {}
390
391 fn on_reset(&mut self) {}
392
393 fn as_draw_node(&self) -> Option<&dyn DrawModifierNode> {
395 None
396 }
397
398 fn as_draw_node_mut(&mut self) -> Option<&mut dyn DrawModifierNode> {
400 None
401 }
402
403 fn as_pointer_input_node(&self) -> Option<&dyn PointerInputNode> {
405 None
406 }
407
408 fn as_pointer_input_node_mut(&mut self) -> Option<&mut dyn PointerInputNode> {
410 None
411 }
412
413 fn as_semantics_node(&self) -> Option<&dyn SemanticsNode> {
415 None
416 }
417
418 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn SemanticsNode> {
420 None
421 }
422
423 fn as_focus_node(&self) -> Option<&dyn FocusNode> {
425 None
426 }
427
428 fn as_focus_node_mut(&mut self) -> Option<&mut dyn FocusNode> {
430 None
431 }
432
433 fn as_layout_node(&self) -> Option<&dyn LayoutModifierNode> {
435 None
436 }
437
438 fn as_layout_node_mut(&mut self) -> Option<&mut dyn LayoutModifierNode> {
440 None
441 }
442
443 fn for_each_delegate<'b>(&'b self, _visitor: &mut dyn FnMut(&'b dyn ModifierNode)) {}
445
446 fn for_each_delegate_mut<'b>(&'b mut self, _visitor: &mut dyn FnMut(&'b mut dyn ModifierNode)) {
448 }
449}
450
451pub trait LayoutModifierNode: ModifierNode {
457 fn measure(
479 &self,
480 _context: &mut dyn ModifierNodeContext,
481 measurable: &dyn Measurable,
482 constraints: Constraints,
483 ) -> cranpose_ui_layout::LayoutModifierMeasureResult {
484 let placeable = measurable.measure(constraints);
485 cranpose_ui_layout::LayoutModifierMeasureResult::with_size(Size {
486 width: placeable.width(),
487 height: placeable.height(),
488 })
489 }
490
491 fn min_intrinsic_width(&self, measurable: &dyn Measurable, height: f32, _density: f32) -> f32 {
494 measurable.min_intrinsic_width(height)
495 }
496
497 fn max_intrinsic_width(&self, measurable: &dyn Measurable, height: f32, _density: f32) -> f32 {
500 measurable.max_intrinsic_width(height)
501 }
502
503 fn min_intrinsic_height(&self, measurable: &dyn Measurable, width: f32, _density: f32) -> f32 {
506 measurable.min_intrinsic_height(width)
507 }
508
509 fn max_intrinsic_height(&self, measurable: &dyn Measurable, width: f32, _density: f32) -> f32 {
512 measurable.max_intrinsic_height(width)
513 }
514}
515
516pub trait DrawModifierNode: ModifierNode {
523 fn create_draw_closure(&self) -> Option<NodeDrawClosure> {
534 None
535 }
536
537 fn create_behind_draw_closure(&self) -> Option<NodeDrawClosure> {
542 None
543 }
544}
545
546pub type NodeDrawClosure = Rc<dyn Fn(&mut cranpose_ui_graphics::DrawScopeDefault)>;
551
552pub trait PointerInputNode: ModifierNode {
558 fn on_pointer_event(
561 &mut self,
562 _context: &mut dyn ModifierNodeContext,
563 _event: &PointerEvent,
564 ) -> bool {
565 false
566 }
567
568 fn hit_test(&self, _x: f32, _y: f32) -> bool {
571 true
572 }
573
574 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
576 None
577 }
578
579 fn layout_size_sink(&self) -> Option<Rc<Cell<Size>>> {
592 None
593 }
594}
595
596pub trait SemanticsNode: ModifierNode {
602 fn merge_semantics(&self, _config: &mut SemanticsConfiguration) {}
604
605 fn reach(&self) -> SemanticsReach {
612 SemanticsReach::merged_by(self, true)
613 }
614}
615
616#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
621pub struct SemanticsReach {
622 pub is_modal: bool,
624 pub hidden: bool,
626 pub merges_live_state: bool,
630}
631
632impl SemanticsReach {
633 pub fn merged_by(node: &(impl SemanticsNode + ?Sized), merges_live_state: bool) -> Self {
636 let mut config = SemanticsConfiguration::default();
637 node.merge_semantics(&mut config);
638 Self {
639 is_modal: config.is_modal,
640 hidden: config.hidden,
641 merges_live_state,
642 }
643 }
644
645 pub fn union(self, other: Self) -> Self {
647 Self {
648 is_modal: self.is_modal || other.is_modal,
649 hidden: self.hidden || other.hidden,
650 merges_live_state: self.merges_live_state || other.merges_live_state,
651 }
652 }
653}
654
655#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
660pub enum FocusState {
661 Active,
663 ActiveParent,
665 Captured,
669 #[default]
672 Inactive,
673}
674
675impl FocusState {
676 pub fn is_focused(self) -> bool {
678 matches!(self, FocusState::Active | FocusState::Captured)
679 }
680
681 pub fn has_focus(self) -> bool {
683 matches!(
684 self,
685 FocusState::Active | FocusState::ActiveParent | FocusState::Captured
686 )
687 }
688
689 pub fn is_captured(self) -> bool {
691 matches!(self, FocusState::Captured)
692 }
693}
694
695pub trait FocusNode: ModifierNode {
700 fn focus_state(&self) -> FocusState;
702
703 fn on_focus_changed(&mut self, _context: &mut dyn ModifierNodeContext, _state: FocusState) {}
705}
706
707#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
718pub enum SemanticsWidgetRole {
719 Button,
720 Checkbox,
721 Switch,
722 RadioButton,
723 Tab,
724 Image,
725 DropdownList,
728 ValuePicker,
731 Header,
736 Dialog,
740 Link,
743 SearchField,
746 ProgressBar,
749 ToggleButton,
752 Alert,
755 Toolbar,
758 Menu,
760 MenuItem,
762 TabBar,
765 List,
767 ListItem,
769 RadioGroup,
771}
772
773#[derive(Clone, Copy, Debug, PartialEq)]
781pub struct ProgressBarRangeInfo {
782 pub current: f32,
783 pub start: f32,
784 pub end: f32,
785 pub steps: u32,
788}
789
790impl ProgressBarRangeInfo {
791 pub fn new(current: f32, start: f32, end: f32, steps: u32) -> Self {
792 Self {
793 current,
794 start,
795 end,
796 steps,
797 }
798 }
799
800 pub fn fraction(&self) -> f32 {
802 let span = self.end - self.start;
803 if span.abs() < f32::EPSILON {
804 return 0.0;
805 }
806 ((self.current - self.start) / span).clamp(0.0, 1.0)
807 }
808
809 pub fn step(&self) -> f32 {
812 let span = self.end - self.start;
813 if self.steps == 0 {
814 span / 10.0
815 } else {
816 span / (self.steps as f32 + 1.0)
817 }
818 }
819}
820
821#[derive(Clone, Copy, Debug, PartialEq, Eq)]
826pub struct CollectionInfo {
827 pub rows: usize,
828 pub columns: usize,
829}
830
831#[derive(Clone, Copy, Debug, PartialEq)]
842pub struct ScrollAxisRange {
843 pub value: f32,
844 pub max_value: f32,
845 pub reverse: bool,
846 pub content_padding_start: f32,
847 pub content_padding_end: f32,
848}
849
850impl ScrollAxisRange {
851 pub fn new(value: f32, max_value: f32, reverse: bool) -> Self {
852 Self {
853 value,
854 max_value,
855 reverse,
856 content_padding_start: 0.0,
857 content_padding_end: 0.0,
858 }
859 }
860
861 pub fn with_content_padding(self, start: f32, end: f32) -> Self {
864 Self {
865 content_padding_start: start,
866 content_padding_end: end,
867 ..self
868 }
869 }
870
871 pub fn can_scroll_forward(&self) -> bool {
872 self.value < self.max_value
873 }
874
875 pub fn can_scroll_backward(&self) -> bool {
876 self.value > 0.0
877 }
878}
879
880#[derive(Clone)]
886pub struct SemanticsScrollBy {
887 handler: Rc<dyn Fn(f32, f32) -> bool>,
888}
889
890impl SemanticsScrollBy {
891 pub fn new(handler: impl Fn(f32, f32) -> bool + 'static) -> Self {
892 Self {
893 handler: Rc::new(handler),
894 }
895 }
896
897 pub fn invoke(&self, dx: f32, dy: f32) -> bool {
898 (self.handler)(dx, dy)
899 }
900}
901
902impl fmt::Debug for SemanticsScrollBy {
903 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
904 f.debug_struct("SemanticsScrollBy").finish_non_exhaustive()
905 }
906}
907
908impl PartialEq for SemanticsScrollBy {
909 fn eq(&self, _other: &Self) -> bool {
910 true
911 }
912}
913
914impl Eq for SemanticsScrollBy {}
915
916#[derive(Clone)]
922pub struct SemanticsScrollToIndex {
923 handler: Rc<dyn Fn(usize) -> bool>,
924}
925
926impl SemanticsScrollToIndex {
927 pub fn new(handler: impl Fn(usize) -> bool + 'static) -> Self {
928 Self {
929 handler: Rc::new(handler),
930 }
931 }
932
933 pub fn invoke(&self, index: usize) -> bool {
934 (self.handler)(index)
935 }
936}
937
938impl fmt::Debug for SemanticsScrollToIndex {
939 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
940 f.debug_struct("SemanticsScrollToIndex")
941 .finish_non_exhaustive()
942 }
943}
944
945impl PartialEq for SemanticsScrollToIndex {
946 fn eq(&self, _other: &Self) -> bool {
947 true
948 }
949}
950
951impl Eq for SemanticsScrollToIndex {}
952
953#[derive(Clone)]
959pub struct SemanticsSetProgress {
960 handler: Rc<dyn Fn(f32) -> bool>,
961}
962
963impl SemanticsSetProgress {
964 pub fn new(handler: impl Fn(f32) -> bool + 'static) -> Self {
965 Self {
966 handler: Rc::new(handler),
967 }
968 }
969
970 pub fn invoke(&self, value: f32) -> bool {
971 (self.handler)(value)
972 }
973}
974
975impl fmt::Debug for SemanticsSetProgress {
976 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
977 f.debug_struct("SemanticsSetProgress")
978 .finish_non_exhaustive()
979 }
980}
981
982#[derive(Clone)]
986pub struct SemanticsSetText(Rc<dyn Fn(&str) -> bool>);
987
988impl SemanticsSetText {
989 pub fn new(handler: impl Fn(&str) -> bool + 'static) -> Self {
990 Self(Rc::new(handler))
991 }
992
993 pub fn invoke(&self, text: &str) -> bool {
994 (self.0)(text)
995 }
996}
997
998impl fmt::Debug for SemanticsSetText {
999 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1000 f.write_str("SemanticsSetText")
1001 }
1002}
1003
1004#[derive(Clone)]
1010pub struct SemanticsSetSelection(Rc<dyn Fn(usize, usize) -> bool>);
1011
1012impl SemanticsSetSelection {
1013 pub fn new(handler: impl Fn(usize, usize) -> bool + 'static) -> Self {
1014 Self(Rc::new(handler))
1015 }
1016
1017 pub fn invoke(&self, anchor: usize, focus: usize) -> bool {
1018 (self.0)(anchor, focus)
1019 }
1020}
1021
1022impl fmt::Debug for SemanticsSetSelection {
1023 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1024 f.write_str("SemanticsSetSelection")
1025 }
1026}
1027
1028#[derive(Clone)]
1031pub struct SemanticsExpand(Rc<dyn Fn() -> bool>);
1032
1033impl SemanticsExpand {
1034 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1035 Self(Rc::new(handler))
1036 }
1037
1038 pub fn invoke(&self) -> bool {
1039 (self.0)()
1040 }
1041}
1042
1043impl fmt::Debug for SemanticsExpand {
1044 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1045 f.write_str("SemanticsExpand")
1046 }
1047}
1048
1049#[derive(Clone)]
1053pub struct SemanticsLongClick(Rc<dyn Fn() -> bool>);
1054
1055impl SemanticsLongClick {
1056 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1057 Self(Rc::new(handler))
1058 }
1059
1060 pub fn invoke(&self) -> bool {
1061 (self.0)()
1062 }
1063}
1064
1065impl fmt::Debug for SemanticsLongClick {
1066 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1067 f.write_str("SemanticsLongClick")
1068 }
1069}
1070
1071impl PartialEq for SemanticsLongClick {
1072 fn eq(&self, _other: &Self) -> bool {
1073 true
1074 }
1075}
1076
1077impl PartialEq for SemanticsExpand {
1078 fn eq(&self, _other: &Self) -> bool {
1079 true
1080 }
1081}
1082
1083#[derive(Clone)]
1087pub struct SemanticsDismiss(Rc<dyn Fn() -> bool>);
1088
1089impl SemanticsDismiss {
1090 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1091 Self(Rc::new(handler))
1092 }
1093
1094 pub fn invoke(&self) -> bool {
1095 (self.0)()
1096 }
1097}
1098
1099impl fmt::Debug for SemanticsDismiss {
1100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1101 f.write_str("SemanticsDismiss")
1102 }
1103}
1104
1105impl PartialEq for SemanticsDismiss {
1106 fn eq(&self, _other: &Self) -> bool {
1107 true
1108 }
1109}
1110
1111impl PartialEq for SemanticsSetText {
1112 fn eq(&self, _other: &Self) -> bool {
1113 true
1114 }
1115}
1116
1117impl PartialEq for SemanticsSetSelection {
1118 fn eq(&self, _other: &Self) -> bool {
1119 true
1120 }
1121}
1122
1123#[derive(Clone)]
1129pub struct SemanticsMagicTap(Rc<dyn Fn() -> bool>);
1130
1131impl SemanticsMagicTap {
1132 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1133 Self(Rc::new(handler))
1134 }
1135
1136 pub fn invoke(&self) -> bool {
1137 (self.0)()
1138 }
1139}
1140
1141impl fmt::Debug for SemanticsMagicTap {
1142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1143 f.write_str("SemanticsMagicTap")
1144 }
1145}
1146
1147impl PartialEq for SemanticsMagicTap {
1148 fn eq(&self, _other: &Self) -> bool {
1149 true
1150 }
1151}
1152
1153impl PartialEq for SemanticsSetProgress {
1154 fn eq(&self, _other: &Self) -> bool {
1155 true
1156 }
1157}
1158
1159impl Eq for SemanticsSetProgress {}
1160
1161#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1168pub enum LiveRegionMode {
1169 Polite,
1171 Assertive,
1174}
1175
1176#[derive(Clone)]
1183pub struct SemanticsCustomAction {
1184 pub label: String,
1186 handler: Rc<dyn Fn()>,
1187}
1188
1189impl SemanticsCustomAction {
1190 pub fn new(label: impl Into<String>, handler: impl Fn() + 'static) -> Self {
1191 Self {
1192 label: label.into(),
1193 handler: Rc::new(handler),
1194 }
1195 }
1196
1197 pub fn invoke(&self) {
1198 (self.handler)();
1199 }
1200}
1201
1202impl fmt::Debug for SemanticsCustomAction {
1203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1204 f.debug_struct("SemanticsCustomAction")
1205 .field("label", &self.label)
1206 .finish_non_exhaustive()
1207 }
1208}
1209
1210impl PartialEq for SemanticsCustomAction {
1211 fn eq(&self, other: &Self) -> bool {
1212 self.label == other.label
1213 }
1214}
1215
1216impl Eq for SemanticsCustomAction {}
1217
1218#[derive(Clone, Debug, PartialEq)]
1233pub struct CanvasSemanticsNode {
1234 pub key: u64,
1241 pub bounds: cranpose_ui_graphics::Rect,
1243 pub label: String,
1244 pub role: Option<SemanticsWidgetRole>,
1245 pub state_description: Option<String>,
1249 pub on_click_label: Option<String>,
1252 pub clickable: bool,
1253 pub selected: Option<bool>,
1255 pub toggled: Option<bool>,
1257 pub enabled: bool,
1258 pub custom_actions: Vec<SemanticsCustomAction>,
1259}
1260
1261impl Default for CanvasSemanticsNode {
1262 fn default() -> Self {
1263 Self {
1264 key: 0,
1265 bounds: cranpose_ui_graphics::Rect {
1266 x: 0.0,
1267 y: 0.0,
1268 width: 0.0,
1269 height: 0.0,
1270 },
1271 label: String::new(),
1272 role: None,
1273 state_description: None,
1274 on_click_label: None,
1275 clickable: false,
1276 selected: None,
1277 toggled: None,
1278 enabled: true,
1279 custom_actions: Vec::new(),
1280 }
1281 }
1282}
1283
1284impl CanvasSemanticsNode {
1285 pub fn control(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1287 Self {
1288 key,
1289 bounds,
1290 label: label.into(),
1291 clickable: true,
1292 ..Self::default()
1293 }
1294 }
1295
1296 pub fn text(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1298 Self {
1299 key,
1300 bounds,
1301 label: label.into(),
1302 ..Self::default()
1303 }
1304 }
1305
1306 pub fn with_role(mut self, role: SemanticsWidgetRole) -> Self {
1307 self.role = Some(role);
1308 self
1309 }
1310
1311 pub fn with_state_description(mut self, state: impl Into<String>) -> Self {
1312 self.state_description = Some(state.into());
1313 self
1314 }
1315
1316 pub fn with_click_label(mut self, label: impl Into<String>) -> Self {
1317 self.on_click_label = Some(label.into());
1318 self.clickable = true;
1319 self
1320 }
1321
1322 pub fn with_selected(mut self, selected: bool) -> Self {
1323 self.selected = Some(selected);
1324 self
1325 }
1326
1327 pub fn with_toggled(mut self, toggled: bool) -> Self {
1328 self.toggled = Some(toggled);
1329 self
1330 }
1331
1332 pub fn with_enabled(mut self, enabled: bool) -> Self {
1333 self.enabled = enabled;
1334 self
1335 }
1336
1337 pub fn with_custom_action(mut self, action: SemanticsCustomAction) -> Self {
1338 self.custom_actions.push(action);
1339 self
1340 }
1341}
1342
1343#[derive(Clone, Debug, PartialEq)]
1345pub struct SemanticsConfiguration {
1346 pub content_description: Option<String>,
1347 pub state_description: Option<String>,
1349 pub on_click_label: Option<String>,
1351 pub on_click: Option<SemanticsCustomAction>,
1354 pub on_long_click: Option<SemanticsLongClick>,
1357 pub on_long_click_label: Option<String>,
1360 pub on_magic_tap: Option<SemanticsMagicTap>,
1364 pub on_magic_tap_label: Option<String>,
1367 pub input_labels: Vec<String>,
1371 pub language: Option<String>,
1375 pub role: Option<SemanticsWidgetRole>,
1377 pub selected: Option<bool>,
1378 pub toggled: Option<bool>,
1379 pub enabled: bool,
1380 pub is_clickable: bool,
1381 pub is_editable_text: bool,
1382 pub multiline: bool,
1384 pub text: Option<String>,
1387 pub text_selection: Option<crate::text::TextRange>,
1388 pub custom_actions: Vec<SemanticsCustomAction>,
1389 pub canvas_children: Vec<CanvasSemanticsNode>,
1392 pub is_modal: bool,
1395 pub hidden: bool,
1399 pub merge_descendants: bool,
1403 pub selectable_group: bool,
1407 pub pane_title: Option<String>,
1410 pub error: Option<String>,
1413 pub password: bool,
1416 pub traversal_index: f32,
1420 pub live_region: Option<LiveRegionMode>,
1423 pub progress: Option<ProgressBarRangeInfo>,
1426 pub set_progress: Option<SemanticsSetProgress>,
1429 pub set_text: Option<SemanticsSetText>,
1432 pub set_selection: Option<SemanticsSetSelection>,
1435 pub expand: Option<SemanticsExpand>,
1438 pub dismiss: Option<SemanticsDismiss>,
1442 pub collapse: Option<SemanticsExpand>,
1445 pub vertical_scroll: Option<ScrollAxisRange>,
1448 pub horizontal_scroll: Option<ScrollAxisRange>,
1451 pub scroll_by: Option<SemanticsScrollBy>,
1454 pub scroll_to_index: Option<SemanticsScrollToIndex>,
1458 pub collection: Option<CollectionInfo>,
1460}
1461
1462impl Default for SemanticsConfiguration {
1463 fn default() -> Self {
1464 Self {
1465 content_description: None,
1466 state_description: None,
1467 on_click_label: None,
1468 on_click: None,
1469 on_long_click: None,
1470 on_long_click_label: None,
1471 on_magic_tap: None,
1472 on_magic_tap_label: None,
1473 input_labels: Vec::new(),
1474 language: None,
1475 role: None,
1476 selected: None,
1477 toggled: None,
1478 enabled: true,
1479 is_clickable: false,
1480 is_editable_text: false,
1481 multiline: false,
1482 text: None,
1483 text_selection: None,
1484 custom_actions: Vec::new(),
1485 canvas_children: Vec::new(),
1486 is_modal: false,
1487 hidden: false,
1488 merge_descendants: false,
1489 selectable_group: false,
1490 pane_title: None,
1491 error: None,
1492 password: false,
1493 traversal_index: 0.0,
1494 live_region: None,
1495 progress: None,
1496 set_progress: None,
1497 set_text: None,
1498 set_selection: None,
1499 expand: None,
1500 dismiss: None,
1501 collapse: None,
1502 vertical_scroll: None,
1503 horizontal_scroll: None,
1504 scroll_by: None,
1505 scroll_to_index: None,
1506 collection: None,
1507 }
1508 }
1509}
1510
1511pub type SemanticsSpec = SemanticsConfiguration;
1520
1521impl SemanticsConfiguration {
1522 pub fn new() -> Self {
1525 Self::default()
1526 }
1527
1528 pub fn content_description(mut self, name: impl Into<String>) -> Self {
1531 self.content_description = Some(name.into());
1532 self
1533 }
1534
1535 pub fn state_description(mut self, state: impl Into<String>) -> Self {
1538 self.state_description = Some(state.into());
1539 self
1540 }
1541
1542 pub fn clickable(mut self) -> Self {
1544 self.is_clickable = true;
1545 self
1546 }
1547
1548 pub fn on_click(mut self, label: impl Into<String>, action: impl Fn() + 'static) -> Self {
1551 self.on_click = Some(SemanticsCustomAction::new(label, action));
1552 self
1553 }
1554
1555 pub fn on_long_click(
1559 mut self,
1560 label: impl Into<String>,
1561 action: impl Fn() -> bool + 'static,
1562 ) -> Self {
1563 self.on_long_click_label = Some(label.into());
1564 self.on_long_click = Some(SemanticsLongClick::new(action));
1565 self
1566 }
1567
1568 pub fn on_magic_tap(
1572 mut self,
1573 label: impl Into<String>,
1574 action: impl Fn() -> bool + 'static,
1575 ) -> Self {
1576 self.on_magic_tap_label = Some(label.into());
1577 self.on_magic_tap = Some(SemanticsMagicTap::new(action));
1578 self
1579 }
1580
1581 pub fn input_labels<S: Into<String>>(mut self, labels: impl IntoIterator<Item = S>) -> Self {
1584 self.input_labels = labels.into_iter().map(Into::into).collect();
1585 self
1586 }
1587
1588 pub fn language(mut self, tag: impl Into<String>) -> Self {
1591 self.language = Some(tag.into());
1592 self
1593 }
1594
1595 pub fn toggled(mut self, toggled: bool) -> Self {
1597 self.toggled = Some(toggled);
1598 self
1599 }
1600
1601 pub fn selected(mut self, selected: bool) -> Self {
1604 self.selected = Some(selected);
1605 self
1606 }
1607
1608 pub fn role(mut self, role: SemanticsWidgetRole) -> Self {
1610 self.role = Some(role);
1611 self
1612 }
1613
1614 pub fn heading(self) -> Self {
1617 self.role(SemanticsWidgetRole::Header)
1618 }
1619
1620 pub fn error(mut self, message: impl Into<String>) -> Self {
1622 self.error = Some(message.into());
1623 self
1624 }
1625
1626 pub fn password(mut self) -> Self {
1628 self.password = true;
1629 self
1630 }
1631
1632 pub fn pane_title(mut self, title: impl Into<String>) -> Self {
1635 self.pane_title = Some(title.into());
1636 self
1637 }
1638
1639 pub fn traversal_index(mut self, index: f32) -> Self {
1642 self.traversal_index = index;
1643 self
1644 }
1645
1646 pub fn hidden(mut self) -> Self {
1649 self.hidden = true;
1650 self
1651 }
1652
1653 pub fn merge_descendants(mut self) -> Self {
1656 self.merge_descendants = true;
1657 self
1658 }
1659
1660 pub fn selectable_group(mut self) -> Self {
1663 self.selectable_group = true;
1664 self
1665 }
1666
1667 pub fn live_region(mut self, mode: LiveRegionMode) -> Self {
1670 self.live_region = Some(mode);
1671 self
1672 }
1673 pub fn merge(&mut self, other: &SemanticsConfiguration) {
1674 if let Some(description) = &other.content_description {
1675 self.content_description = Some(description.clone());
1676 }
1677 if let Some(state) = &other.state_description {
1678 self.state_description = Some(state.clone());
1679 }
1680 if let Some(label) = &other.on_click_label {
1681 self.on_click_label = Some(label.clone());
1682 }
1683 if let Some(label) = &other.on_long_click_label {
1684 self.on_long_click_label = Some(label.clone());
1685 }
1686 if let Some(label) = &other.on_magic_tap_label {
1687 self.on_magic_tap_label = Some(label.clone());
1688 }
1689 if !other.input_labels.is_empty() {
1690 self.input_labels.clone_from(&other.input_labels);
1691 }
1692 if let Some(language) = &other.language {
1693 self.language = Some(language.clone());
1694 }
1695 if let Some(role) = other.role {
1696 self.role = Some(role);
1697 }
1698 if let Some(selected) = other.selected {
1699 self.selected = Some(selected);
1700 }
1701 if let Some(toggled) = other.toggled {
1702 self.toggled = Some(toggled);
1703 }
1704 self.enabled &= other.enabled;
1705 self.is_clickable |= other.is_clickable;
1706 self.is_editable_text |= other.is_editable_text;
1707 self.multiline |= other.multiline;
1708 if let Some(text) = &other.text {
1709 self.text = Some(text.clone());
1710 }
1711 self.is_modal |= other.is_modal;
1712 self.hidden |= other.hidden;
1713 self.merge_descendants |= other.merge_descendants;
1714 self.selectable_group |= other.selectable_group;
1715 self.password |= other.password;
1716 if other.traversal_index != 0.0 {
1717 self.traversal_index = other.traversal_index;
1718 }
1719 if let Some(live_region) = other.live_region {
1720 self.live_region = Some(live_region);
1721 }
1722 self.merge_words(other);
1723 self.merge_actions(other);
1724 self.merge_ranges(other);
1725 }
1726
1727 fn merge_words(&mut self, other: &SemanticsConfiguration) {
1728 if let Some(title) = &other.pane_title {
1729 self.pane_title = Some(title.clone());
1730 }
1731 if let Some(error) = &other.error {
1732 self.error = Some(error.clone());
1733 }
1734 }
1735
1736 fn merge_actions(&mut self, other: &SemanticsConfiguration) {
1737 if let Some(on_click) = &other.on_click {
1738 self.on_click = Some(on_click.clone());
1739 }
1740 self.custom_actions
1741 .extend(other.custom_actions.iter().cloned());
1742 self.canvas_children
1743 .extend(other.canvas_children.iter().cloned());
1744 if let Some(set_progress) = &other.set_progress {
1745 self.set_progress = Some(set_progress.clone());
1746 }
1747 if let Some(set_text) = &other.set_text {
1748 self.set_text = Some(set_text.clone());
1749 }
1750 if let Some(set_selection) = &other.set_selection {
1751 self.set_selection = Some(set_selection.clone());
1752 }
1753 if let Some(expand) = &other.expand {
1754 self.expand = Some(expand.clone());
1755 }
1756 if let Some(collapse) = &other.collapse {
1757 self.collapse = Some(collapse.clone());
1758 }
1759 if let Some(dismiss) = &other.dismiss {
1760 self.dismiss = Some(dismiss.clone());
1761 }
1762 if let Some(long_click) = &other.on_long_click {
1763 self.on_long_click = Some(long_click.clone());
1764 }
1765 if let Some(magic_tap) = &other.on_magic_tap {
1766 self.on_magic_tap = Some(magic_tap.clone());
1767 }
1768 if let Some(scroll_by) = &other.scroll_by {
1769 self.scroll_by = Some(scroll_by.clone());
1770 }
1771 if let Some(scroll_to_index) = &other.scroll_to_index {
1772 self.scroll_to_index = Some(scroll_to_index.clone());
1773 }
1774 }
1775
1776 fn merge_ranges(&mut self, other: &SemanticsConfiguration) {
1777 if let Some(selection) = other.text_selection {
1778 self.text_selection = Some(selection);
1779 }
1780 if let Some(progress) = other.progress {
1781 self.progress = Some(progress);
1782 }
1783 if let Some(range) = other.vertical_scroll {
1784 self.vertical_scroll = Some(range);
1785 }
1786 if let Some(range) = other.horizontal_scroll {
1787 self.horizontal_scroll = Some(range);
1788 }
1789 if let Some(collection) = other.collection {
1790 self.collection = Some(collection);
1791 }
1792 }
1793
1794 pub fn is_activatable(&self) -> bool {
1797 self.is_clickable || self.on_click_label.is_some() || self.on_click.is_some()
1798 }
1799}
1800
1801impl fmt::Debug for dyn ModifierNode {
1802 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1803 f.debug_struct("ModifierNode").finish_non_exhaustive()
1804 }
1805}
1806
1807impl dyn ModifierNode {
1808 pub fn as_any(&self) -> &dyn Any {
1809 self
1810 }
1811
1812 pub fn as_any_mut(&mut self) -> &mut dyn Any {
1813 self
1814 }
1815}
1816
1817pub trait ModifierNodeElement: fmt::Debug + Hash + PartialEq + 'static {
1820 type Node: ModifierNode;
1821
1822 fn create(&self) -> Self::Node;
1824
1825 fn update(&self, node: &mut Self::Node);
1827
1828 fn key(&self) -> Option<u64> {
1830 None
1831 }
1832
1833 fn inspector_name(&self) -> &'static str {
1835 type_name::<Self>()
1836 }
1837
1838 fn inspector_properties(&self, _inspector: &mut dyn FnMut(&'static str, String)) {}
1840
1841 fn capabilities(&self) -> NodeCapabilities {
1844 NodeCapabilities::default()
1845 }
1846
1847 fn always_update(&self) -> bool {
1853 false
1854 }
1855
1856 fn auto_invalidate_on_update(&self) -> bool {
1859 true
1860 }
1861
1862 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
1869 None
1870 }
1871
1872 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
1879 Vec::new()
1880 }
1881}
1882
1883#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1885pub struct NodeCapabilities(u32);
1886
1887impl NodeCapabilities {
1888 pub const NONE: Self = Self(0);
1890 pub const LAYOUT: Self = Self(1 << 0);
1892 pub const DRAW: Self = Self(1 << 1);
1894 pub const POINTER_INPUT: Self = Self(1 << 2);
1896 pub const SEMANTICS: Self = Self(1 << 3);
1898 pub const MODIFIER_LOCALS: Self = Self(1 << 4);
1900 pub const FOCUS: Self = Self(1 << 5);
1902 pub const WINDOW_ROOT: Self = Self(1 << 6);
1906 pub const KEY_INPUT: Self = Self(1 << 7);
1908
1909 pub const fn empty() -> Self {
1911 Self::NONE
1912 }
1913
1914 pub const fn contains(self, other: Self) -> bool {
1916 (self.0 & other.0) == other.0
1917 }
1918
1919 pub const fn intersects(self, other: Self) -> bool {
1921 (self.0 & other.0) != 0
1922 }
1923
1924 pub fn insert(&mut self, other: Self) {
1926 self.0 |= other.0;
1927 }
1928
1929 pub const fn bits(self) -> u32 {
1931 self.0
1932 }
1933
1934 pub const fn is_empty(self) -> bool {
1936 self.0 == 0
1937 }
1938
1939 pub const fn for_invalidation(kind: InvalidationKind) -> Self {
1941 match kind {
1942 InvalidationKind::Layout => Self::LAYOUT,
1943 InvalidationKind::Draw => Self::DRAW,
1944 InvalidationKind::PointerInput => Self::POINTER_INPUT,
1945 InvalidationKind::Semantics => Self::SEMANTICS,
1946 InvalidationKind::Focus => Self::FOCUS,
1947 }
1948 }
1949}
1950
1951impl Default for NodeCapabilities {
1952 fn default() -> Self {
1953 Self::NONE
1954 }
1955}
1956
1957impl fmt::Debug for NodeCapabilities {
1958 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1959 f.debug_struct("NodeCapabilities")
1960 .field("layout", &self.contains(Self::LAYOUT))
1961 .field("draw", &self.contains(Self::DRAW))
1962 .field("pointer_input", &self.contains(Self::POINTER_INPUT))
1963 .field("semantics", &self.contains(Self::SEMANTICS))
1964 .field("modifier_locals", &self.contains(Self::MODIFIER_LOCALS))
1965 .field("focus", &self.contains(Self::FOCUS))
1966 .field("window_root", &self.contains(Self::WINDOW_ROOT))
1967 .field("key_input", &self.contains(Self::KEY_INPUT))
1968 .finish()
1969 }
1970}
1971
1972impl BitOr for NodeCapabilities {
1973 type Output = Self;
1974
1975 fn bitor(self, rhs: Self) -> Self::Output {
1976 Self(self.0 | rhs.0)
1977 }
1978}
1979
1980impl BitOrAssign for NodeCapabilities {
1981 fn bitor_assign(&mut self, rhs: Self) {
1982 self.0 |= rhs.0;
1983 }
1984}
1985
1986pub type ModifierInvalidations = smallvec::SmallVec<[ModifierInvalidation; 5]>;
1989
1990#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1992pub struct ModifierInvalidation {
1993 kind: InvalidationKind,
1994 capabilities: NodeCapabilities,
1995}
1996
1997impl ModifierInvalidation {
1998 pub const fn new(kind: InvalidationKind, capabilities: NodeCapabilities) -> Self {
2000 Self { kind, capabilities }
2001 }
2002
2003 pub const fn kind(self) -> InvalidationKind {
2005 self.kind
2006 }
2007
2008 pub const fn capabilities(self) -> NodeCapabilities {
2010 self.capabilities
2011 }
2012}
2013
2014pub trait AnyModifierElement: fmt::Debug {
2016 fn node_type(&self) -> TypeId;
2017
2018 fn element_type(&self) -> TypeId;
2019
2020 fn create_node(&self) -> Rc<RefCell<dyn ModifierNode>>;
2022
2023 fn can_update_node(&self, node: &dyn ModifierNode) -> bool;
2024
2025 fn update_node(&self, node: &mut dyn ModifierNode);
2026
2027 fn key(&self) -> Option<u64>;
2028
2029 fn capabilities(&self) -> NodeCapabilities {
2030 NodeCapabilities::default()
2031 }
2032
2033 fn hash_code(&self) -> u64;
2034
2035 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool;
2036
2037 fn inspector_name(&self) -> &'static str;
2038
2039 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String));
2040
2041 fn requires_update(&self) -> bool;
2042
2043 fn auto_invalidates_on_update(&self) -> bool;
2044
2045 fn update_invalidation_kind(&self) -> Option<InvalidationKind>;
2046
2047 fn provides_composition_locals(&self) -> bool {
2049 false
2050 }
2051
2052 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2054 Vec::new()
2055 }
2056
2057 fn as_any(&self) -> &dyn Any;
2058}
2059
2060struct TypedModifierElement<E: ModifierNodeElement> {
2061 element: E,
2062 cached_hash: u64,
2063 provides_locals: bool,
2064}
2065
2066impl<E: ModifierNodeElement> TypedModifierElement<E> {
2067 fn new(element: E) -> Self {
2068 let mut hasher = default::new();
2069 element.hash(&mut hasher);
2070 let provides_locals = !element.provided_composition_locals().is_empty();
2071 Self {
2072 element,
2073 cached_hash: hasher.finish(),
2074 provides_locals,
2075 }
2076 }
2077}
2078
2079impl<E> fmt::Debug for TypedModifierElement<E>
2080where
2081 E: ModifierNodeElement,
2082{
2083 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2084 f.debug_struct("TypedModifierElement")
2085 .field("type", &type_name::<E>())
2086 .finish()
2087 }
2088}
2089
2090impl<E> AnyModifierElement for TypedModifierElement<E>
2091where
2092 E: ModifierNodeElement,
2093{
2094 fn node_type(&self) -> TypeId {
2095 TypeId::of::<E::Node>()
2096 }
2097
2098 fn element_type(&self) -> TypeId {
2099 TypeId::of::<E>()
2100 }
2101
2102 fn create_node(&self) -> Rc<RefCell<dyn ModifierNode>> {
2103 Rc::new(RefCell::new(self.element.create()))
2104 }
2105
2106 fn can_update_node(&self, node: &dyn ModifierNode) -> bool {
2107 node.as_any().is::<E::Node>()
2108 }
2109
2110 fn update_node(&self, node: &mut dyn ModifierNode) {
2111 if let Some(typed) = node.as_any_mut().downcast_mut::<E::Node>() {
2112 self.element.update(typed);
2113 }
2114 }
2115
2116 fn key(&self) -> Option<u64> {
2117 self.element.key()
2118 }
2119
2120 fn capabilities(&self) -> NodeCapabilities {
2121 self.element.capabilities()
2122 }
2123
2124 fn provides_composition_locals(&self) -> bool {
2125 self.provides_locals
2126 }
2127
2128 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2129 self.element.provided_composition_locals()
2130 }
2131
2132 fn hash_code(&self) -> u64 {
2133 self.cached_hash
2134 }
2135
2136 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool {
2137 other
2138 .as_any()
2139 .downcast_ref::<Self>()
2140 .is_some_and(|typed| typed.element == self.element)
2141 }
2142
2143 fn inspector_name(&self) -> &'static str {
2144 self.element.inspector_name()
2145 }
2146
2147 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String)) {
2148 self.element.inspector_properties(visitor);
2149 }
2150
2151 fn requires_update(&self) -> bool {
2152 self.element.always_update()
2153 }
2154
2155 fn auto_invalidates_on_update(&self) -> bool {
2156 self.element.auto_invalidate_on_update()
2157 }
2158
2159 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
2160 self.element.update_invalidation_kind()
2161 }
2162
2163 fn as_any(&self) -> &dyn Any {
2164 self
2165 }
2166}
2167
2168fn request_update_auto_invalidations(
2169 element: &dyn AnyModifierElement,
2170 context: &mut dyn ModifierNodeContext,
2171 capabilities: NodeCapabilities,
2172) {
2173 if let Some(kind) = element.update_invalidation_kind() {
2174 let capabilities = NodeCapabilities::for_invalidation(kind);
2175 context.push_active_capabilities(capabilities);
2176 context.invalidate(kind);
2177 context.pop_active_capabilities();
2178 } else if element.auto_invalidates_on_update() {
2179 request_auto_invalidations(context, capabilities);
2180 }
2181}
2182
2183pub fn modifier_element<E: ModifierNodeElement>(element: E) -> DynModifierElement {
2186 Rc::new(TypedModifierElement::new(element))
2187}
2188
2189pub type DynModifierElement = Rc<dyn AnyModifierElement>;
2191
2192#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2193enum TraversalDirection {
2194 Forward,
2195 Backward,
2196}
2197
2198pub struct ModifierChainIter<'a> {
2203 chain: &'a ModifierNodeChain,
2204 cursor: usize,
2205 remaining: usize,
2206 direction: TraversalDirection,
2207}
2208
2209impl<'a> ModifierChainIter<'a> {
2210 fn forward(chain: &'a ModifierNodeChain) -> Self {
2211 Self {
2212 chain,
2213 cursor: 0,
2214 remaining: chain.ordered_nodes.len(),
2215 direction: TraversalDirection::Forward,
2216 }
2217 }
2218
2219 fn backward(chain: &'a ModifierNodeChain) -> Self {
2220 let len = chain.ordered_nodes.len();
2221 Self {
2222 chain,
2223 cursor: len.wrapping_sub(1),
2224 remaining: len,
2225 direction: TraversalDirection::Backward,
2226 }
2227 }
2228}
2229
2230impl<'a> Iterator for ModifierChainIter<'a> {
2231 type Item = ModifierChainNodeRef<'a>;
2232
2233 #[inline]
2234 fn next(&mut self) -> Option<Self::Item> {
2235 if self.remaining == 0 {
2236 return None;
2237 }
2238 let (link, caps, agg) = self.chain.ordered_nodes[self.cursor];
2239 let node_ref = self.chain.make_node_ref_with_caps(link, caps, agg);
2240 self.remaining -= 1;
2241 match self.direction {
2242 TraversalDirection::Forward => self.cursor += 1,
2243 TraversalDirection::Backward => self.cursor = self.cursor.wrapping_sub(1),
2244 }
2245 Some(node_ref)
2246 }
2247
2248 #[inline]
2249 fn size_hint(&self) -> (usize, Option<usize>) {
2250 (self.remaining, Some(self.remaining))
2251 }
2252}
2253
2254impl ExactSizeIterator for ModifierChainIter<'_> {}
2255impl std::iter::FusedIterator for ModifierChainIter<'_> {}
2256
2257#[derive(Debug)]
2258struct ModifierNodeEntry {
2259 key: Option<u64>,
2260 hash_code: u64,
2261 element: DynModifierElement,
2262 node: Rc<RefCell<dyn ModifierNode>>,
2263 capabilities: NodeCapabilities,
2264}
2265
2266impl ModifierNodeEntry {
2267 fn new(
2268 key: Option<u64>,
2269 element: DynModifierElement,
2270 node: Rc<RefCell<dyn ModifierNode>>,
2271 hash_code: u64,
2272 capabilities: NodeCapabilities,
2273 ) -> Self {
2274 let entry = Self {
2275 key,
2276 hash_code,
2277 element,
2278 node,
2279 capabilities,
2280 };
2281 entry
2282 .node
2283 .borrow()
2284 .node_state()
2285 .set_capabilities(entry.capabilities);
2286 entry
2287 }
2288}
2289
2290fn visit_node_tree_mut(
2291 node: &mut dyn ModifierNode,
2292 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
2293) {
2294 visitor(node);
2295 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
2296}
2297
2298fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
2299 let mut current = 0usize;
2300 let mut result: Option<&dyn ModifierNode> = None;
2301 node.for_each_delegate(&mut |child| {
2302 if result.is_none() && current == target {
2303 result = Some(child);
2304 }
2305 current += 1;
2306 });
2307 result
2308}
2309
2310fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
2311 let mut current = 0usize;
2312 let mut result: Option<&mut dyn ModifierNode> = None;
2313 node.for_each_delegate_mut(&mut |child| {
2314 if result.is_none() && current == target {
2315 result = Some(child);
2316 }
2317 current += 1;
2318 });
2319 result
2320}
2321
2322fn with_node_context<F, R>(
2323 node: &mut dyn ModifierNode,
2324 context: &mut dyn ModifierNodeContext,
2325 f: F,
2326) -> R
2327where
2328 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
2329{
2330 context.push_active_capabilities(node.node_state().capabilities());
2331 let result = f(node, context);
2332 context.pop_active_capabilities();
2333 result
2334}
2335
2336fn request_auto_invalidations(
2337 context: &mut dyn ModifierNodeContext,
2338 capabilities: NodeCapabilities,
2339) {
2340 if capabilities.is_empty() {
2341 return;
2342 }
2343
2344 context.push_active_capabilities(capabilities);
2345
2346 if capabilities.contains(NodeCapabilities::LAYOUT) {
2347 context.invalidate(InvalidationKind::Layout);
2348 }
2349 if capabilities.contains(NodeCapabilities::DRAW) {
2350 context.invalidate(InvalidationKind::Draw);
2351 }
2352 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
2353 context.invalidate(InvalidationKind::PointerInput);
2354 }
2355 if capabilities.contains(NodeCapabilities::SEMANTICS) {
2356 context.invalidate(InvalidationKind::Semantics);
2357 }
2358 if capabilities.contains(NodeCapabilities::FOCUS) {
2359 context.invalidate(InvalidationKind::Focus);
2360 }
2361
2362 context.pop_active_capabilities();
2363}
2364
2365fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
2366 visit_node_tree_mut(node, &mut |n| {
2367 if !n.node_state().is_attached() {
2368 n.node_state().set_attached(true);
2369 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
2370 }
2371 });
2372}
2373
2374fn reset_node_tree(node: &mut dyn ModifierNode) {
2375 visit_node_tree_mut(node, &mut |n| n.on_reset());
2376}
2377
2378fn detach_node_tree(node: &mut dyn ModifierNode) {
2379 visit_node_tree_mut(node, &mut |n| {
2380 if n.node_state().is_attached() {
2381 n.on_detach();
2382 n.node_state().set_attached(false);
2383 }
2384 n.node_state().set_parent_link(None);
2385 n.node_state().set_child_link(None);
2386 n.node_state()
2387 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2388 });
2389}
2390
2391pub struct ModifierNodeChain {
2398 entries: Vec<ModifierNodeEntry>,
2399 aggregated_capabilities: NodeCapabilities,
2400 head_aggregate_child_capabilities: NodeCapabilities,
2401 head_sentinel: SentinelNode,
2402 tail_sentinel: SentinelNode,
2403 ordered_nodes: Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
2404}
2405
2406#[derive(Default)]
2410struct ReconcileScratch {
2411 old_used: Vec<bool>,
2412 match_order: Vec<Option<usize>>,
2413 final_slots: Vec<Option<ModifierNodeEntry>>,
2414 elements: Vec<DynModifierElement>,
2415}
2416
2417thread_local! {
2418 static RECONCILE_SCRATCH: std::cell::RefCell<ReconcileScratch> =
2419 std::cell::RefCell::default();
2420}
2421
2422struct SentinelNode {
2423 state: NodeState,
2424}
2425
2426impl SentinelNode {
2427 fn new() -> Self {
2428 Self {
2429 state: NodeState::sentinel(),
2430 }
2431 }
2432}
2433
2434impl DelegatableNode for SentinelNode {
2435 fn node_state(&self) -> &NodeState {
2436 &self.state
2437 }
2438}
2439
2440impl ModifierNode for SentinelNode {}
2441
2442#[derive(Clone)]
2443pub struct ModifierChainNodeRef<'a> {
2444 chain: &'a ModifierNodeChain,
2445 link: NodeLink,
2446 cached_capabilities: Option<NodeCapabilities>,
2447 cached_aggregate_child: Option<NodeCapabilities>,
2448}
2449
2450impl Default for ModifierNodeChain {
2451 fn default() -> Self {
2452 Self::new()
2453 }
2454}
2455
2456struct EntryIndex {
2457 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2458 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2459 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
2460}
2461
2462struct EntryMatchQuery<'a> {
2463 element_type: TypeId,
2464 node_type: TypeId,
2465 key: Option<u64>,
2466 hash_code: u64,
2467 element: &'a DynModifierElement,
2468}
2469
2470impl EntryIndex {
2471 fn build(entries: &[ModifierNodeEntry]) -> Self {
2472 let mut keyed = HashMap::default();
2473 let mut hashed = HashMap::default();
2474 let mut typed = HashMap::default();
2475
2476 for (i, entry) in entries.iter().enumerate() {
2477 let (element_type, node_type) =
2478 (entry.element.element_type(), entry.element.node_type());
2479 if let Some(key_value) = entry.key {
2480 keyed
2481 .entry((element_type, node_type, key_value))
2482 .or_insert_with(Vec::new)
2483 .push(i);
2484 } else {
2485 hashed
2486 .entry((element_type, node_type, entry.hash_code))
2487 .or_insert_with(Vec::new)
2488 .push(i);
2489 typed
2490 .entry((element_type, node_type))
2491 .or_insert_with(Vec::new)
2492 .push(i);
2493 }
2494 }
2495
2496 Self {
2497 keyed,
2498 hashed,
2499 typed,
2500 }
2501 }
2502
2503 fn find_match(
2504 &self,
2505 entries: &[ModifierNodeEntry],
2506 used: &[bool],
2507 query: EntryMatchQuery<'_>,
2508 ) -> Option<usize> {
2509 if let Some(key_value) = query.key {
2510 if let Some(candidates) =
2511 self.keyed
2512 .get(&(query.element_type, query.node_type, key_value))
2513 {
2514 for &i in candidates {
2515 if !used[i] {
2516 return Some(i);
2517 }
2518 }
2519 }
2520 } else {
2521 if let Some(candidates) =
2522 self.hashed
2523 .get(&(query.element_type, query.node_type, query.hash_code))
2524 {
2525 for &i in candidates {
2526 if !used[i]
2527 && entries[i]
2528 .element
2529 .as_ref()
2530 .equals_element(query.element.as_ref())
2531 {
2532 return Some(i);
2533 }
2534 }
2535 }
2536
2537 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
2538 for &i in candidates {
2539 if !used[i] {
2540 return Some(i);
2541 }
2542 }
2543 }
2544 }
2545
2546 None
2547 }
2548}
2549
2550fn update_entry_in_place(
2555 entry: &mut ModifierNodeEntry,
2556 element: &DynModifierElement,
2557 context: &mut dyn ModifierNodeContext,
2558) -> bool {
2559 if entry.element.element_type() != element.element_type()
2560 || entry.element.node_type() != element.node_type()
2561 || entry.key != element.key()
2562 || !element.can_update_node(&*entry.node.borrow())
2563 {
2564 return false;
2565 }
2566 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2567 let capabilities = element.capabilities();
2568 attach_if_detached(entry, context);
2569 if !same_element || element.requires_update() {
2570 element.update_node(&mut *entry.node.borrow_mut());
2571 entry.element = element.clone();
2572 entry.hash_code = element.hash_code();
2573 request_update_auto_invalidations(element.as_ref(), context, capabilities);
2574 }
2575 entry.capabilities = capabilities;
2576 entry
2577 .node
2578 .borrow()
2579 .node_state()
2580 .set_capabilities(capabilities);
2581 true
2582}
2583
2584fn attach_if_detached(entry: &ModifierNodeEntry, context: &mut dyn ModifierNodeContext) {
2585 let attached = entry.node.borrow().node_state().is_attached();
2586 if !attached {
2587 attach_node_tree(&mut *entry.node.borrow_mut(), context);
2588 }
2589}
2590
2591fn fresh_entry(
2593 element: DynModifierElement,
2594 context: &mut dyn ModifierNodeContext,
2595) -> ModifierNodeEntry {
2596 let capabilities = element.capabilities();
2597 let entry = ModifierNodeEntry::new(
2598 element.key(),
2599 element.clone(),
2600 element.create_node(),
2601 element.hash_code(),
2602 capabilities,
2603 );
2604 attach_node_tree(&mut *entry.node.borrow_mut(), context);
2605 element.update_node(&mut *entry.node.borrow_mut());
2606 request_auto_invalidations(context, capabilities);
2607 entry
2608}
2609
2610fn reconcile_element(
2615 element: DynModifierElement,
2616 new_pos: usize,
2617 (old_entries, index): (&mut [ModifierNodeEntry], &EntryIndex),
2618 (used, match_order): (&mut [bool], &mut [Option<usize>]),
2619 context: &mut dyn ModifierNodeContext,
2620) -> Option<ModifierNodeEntry> {
2621 let element_type = element.element_type();
2622 let node_type = element.node_type();
2623 let key = element.key();
2624 let hash_code = element.hash_code();
2625 let capabilities = element.capabilities();
2626 let Some(idx) = index.find_match(
2627 old_entries,
2628 used,
2629 EntryMatchQuery {
2630 element_type,
2631 node_type,
2632 key,
2633 hash_code,
2634 element: &element,
2635 },
2636 ) else {
2637 return Some(fresh_entry(element, context));
2638 };
2639 let entry = &mut old_entries[idx];
2640 if !element.can_update_node(&*entry.node.borrow()) {
2641 return Some(fresh_entry(element, context));
2642 }
2643
2644 used[idx] = true;
2645 match_order[idx] = Some(new_pos);
2646 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2647 attach_if_detached(entry, context);
2648 if !same_element || element.requires_update() {
2649 element.update_node(&mut *entry.node.borrow_mut());
2650 entry.element = element;
2651 entry.hash_code = hash_code;
2652 request_update_auto_invalidations(entry.element.as_ref(), context, capabilities);
2653 }
2654 if idx != new_pos {
2655 request_auto_invalidations(context, capabilities);
2656 }
2657 entry.key = key;
2658 entry.capabilities = capabilities;
2659 entry
2660 .node
2661 .borrow()
2662 .node_state()
2663 .set_capabilities(capabilities);
2664 None
2665}
2666
2667impl ModifierNodeChain {
2668 pub fn new() -> Self {
2669 let mut chain = Self {
2670 entries: Vec::new(),
2671 aggregated_capabilities: NodeCapabilities::empty(),
2672 head_aggregate_child_capabilities: NodeCapabilities::empty(),
2673 head_sentinel: SentinelNode::new(),
2674 tail_sentinel: SentinelNode::new(),
2675 ordered_nodes: Vec::new(),
2676 };
2677 chain.sync_chain_links();
2678 chain
2679 }
2680
2681 pub fn detach_nodes(&mut self) {
2683 for entry in &self.entries {
2684 detach_node_tree(&mut *entry.node.borrow_mut());
2685 }
2686 }
2687
2688 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
2690 for entry in &self.entries {
2691 attach_node_tree(&mut *entry.node.borrow_mut(), context);
2692 }
2693 }
2694
2695 pub fn repair_chain(&mut self) {
2698 self.sync_chain_links();
2699 }
2700
2701 pub fn update_from_slice(
2707 &mut self,
2708 elements: &[DynModifierElement],
2709 context: &mut dyn ModifierNodeContext,
2710 ) {
2711 self.update_from_ref_iter(elements.iter(), context);
2712 }
2713
2714 pub fn update_entries_of_type<'a, I>(
2724 &mut self,
2725 elements: I,
2726 element_count: usize,
2727 element_type: TypeId,
2728 context: &mut dyn ModifierNodeContext,
2729 ) -> bool
2730 where
2731 I: Iterator<Item = &'a DynModifierElement>,
2732 {
2733 if element_count != self.entries.len() {
2734 return false;
2735 }
2736 self.entries
2737 .iter_mut()
2738 .zip(elements)
2739 .filter(|(_, element)| element.element_type() == element_type)
2740 .all(|(entry, element)| update_entry_in_place(entry, element, context))
2741 }
2742
2743 pub fn update_from_ref_iter<'a, I>(
2744 &mut self,
2745 elements: I,
2746 context: &mut dyn ModifierNodeContext,
2747 ) where
2748 I: Iterator<Item = &'a DynModifierElement>,
2749 {
2750 let mut scratch = RECONCILE_SCRATCH
2753 .try_with(|scratch| std::mem::take(&mut *scratch.borrow_mut()))
2754 .unwrap_or_default();
2755 self.reconcile(elements, context, &mut scratch);
2756 scratch.elements.clear();
2757 scratch.final_slots.clear();
2758 let _ = RECONCILE_SCRATCH.try_with(|slot| *slot.borrow_mut() = scratch);
2759 }
2760
2761 fn reconcile<'a, I>(
2762 &mut self,
2763 elements: I,
2764 context: &mut dyn ModifierNodeContext,
2765 scratch: &mut ReconcileScratch,
2766 ) where
2767 I: Iterator<Item = &'a DynModifierElement>,
2768 {
2769 let old_len = self.entries.len();
2770 let mut fast_path_failed_at: Option<usize> = None;
2771 let mut elements_count = 0;
2772
2773 scratch.elements.clear();
2774
2775 for (idx, element) in elements.enumerate() {
2776 elements_count = idx + 1;
2777 if fast_path_failed_at.is_none() && idx < old_len {
2778 if update_entry_in_place(&mut self.entries[idx], element, context) {
2779 continue;
2780 }
2781 fast_path_failed_at = Some(idx);
2782 }
2783 scratch.elements.push(element.clone());
2784 }
2785
2786 if fast_path_failed_at.is_none() && scratch.elements.is_empty() {
2787 if elements_count < self.entries.len() {
2788 for entry in self.entries.drain(elements_count..) {
2789 request_auto_invalidations(context, entry.capabilities);
2790 detach_node_tree(&mut *entry.node.borrow_mut());
2791 }
2792 }
2793 self.sync_chain_links();
2794 return;
2795 }
2796
2797 self.rebuild_tail(fast_path_failed_at.unwrap_or(old_len), context, scratch);
2798 }
2799
2800 fn rebuild_tail(
2804 &mut self,
2805 fail_idx: usize,
2806 context: &mut dyn ModifierNodeContext,
2807 scratch: &mut ReconcileScratch,
2808 ) {
2809 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
2810 let processed_entries_len = self.entries.len();
2811 let old_len = old_entries.len();
2812
2813 scratch.old_used.clear();
2814 scratch.old_used.resize(old_len, false);
2815
2816 scratch.match_order.clear();
2817 scratch.match_order.resize(old_len, None);
2818
2819 let index = EntryIndex::build(&old_entries);
2820
2821 let new_elements_count = scratch.elements.len();
2822 scratch.final_slots.clear();
2823 scratch.final_slots.reserve(new_elements_count);
2824
2825 for (new_pos, element) in scratch.elements.drain(..).enumerate() {
2826 let fresh = reconcile_element(
2827 element,
2828 new_pos,
2829 (&mut old_entries, &index),
2830 (&mut scratch.old_used, &mut scratch.match_order),
2831 context,
2832 );
2833 scratch.final_slots.push(fresh);
2834 }
2835
2836 for (i, entry) in old_entries.into_iter().enumerate() {
2837 match scratch.match_order[i] {
2838 Some(pos) if scratch.old_used[i] => scratch.final_slots[pos] = Some(entry),
2839 _ => {
2840 request_auto_invalidations(context, entry.capabilities);
2841 detach_node_tree(&mut *entry.node.borrow_mut());
2842 }
2843 }
2844 }
2845
2846 self.entries.reserve(scratch.final_slots.len());
2847 for slot in scratch.final_slots.drain(..) {
2848 if let Some(entry) = slot {
2849 self.entries.push(entry);
2850 } else {
2851 log::error!("modifier reconciliation produced an empty final slot");
2852 }
2853 }
2854
2855 debug_assert_eq!(
2856 self.entries.len(),
2857 processed_entries_len + new_elements_count
2858 );
2859 self.sync_chain_links();
2860 }
2861
2862 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
2866 where
2867 I: IntoIterator<Item = DynModifierElement>,
2868 {
2869 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
2870 self.update_from_slice(&collected, context);
2871 }
2872
2873 pub fn reset(&mut self) {
2876 for entry in &mut self.entries {
2877 reset_node_tree(&mut *entry.node.borrow_mut());
2878 }
2879 }
2880
2881 pub fn detach_all(&mut self) {
2883 for entry in std::mem::take(&mut self.entries) {
2884 detach_node_tree(&mut *entry.node.borrow_mut());
2885 {
2886 let node_borrow = entry.node.borrow();
2887 let state = node_borrow.node_state();
2888 state.set_capabilities(NodeCapabilities::empty());
2889 }
2890 }
2891 self.aggregated_capabilities = NodeCapabilities::empty();
2892 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2893 self.ordered_nodes.clear();
2894 self.sync_chain_links();
2895 }
2896
2897 pub fn len(&self) -> usize {
2898 self.entries.len()
2899 }
2900
2901 pub fn is_empty(&self) -> bool {
2902 self.entries.is_empty()
2903 }
2904
2905 pub fn capabilities(&self) -> NodeCapabilities {
2907 self.aggregated_capabilities
2908 }
2909
2910 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
2912 self.aggregated_capabilities.contains(capability)
2913 }
2914
2915 pub fn head(&self) -> ModifierChainNodeRef<'_> {
2917 self.make_node_ref(NodeLink::Head)
2918 }
2919
2920 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
2922 self.make_node_ref(NodeLink::Tail)
2923 }
2924
2925 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
2927 ModifierChainIter::forward(self)
2928 }
2929
2930 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
2932 ModifierChainIter::backward(self)
2933 }
2934
2935 pub fn for_each_forward<F>(&self, mut f: F)
2937 where
2938 F: FnMut(ModifierChainNodeRef<'_>),
2939 {
2940 for node in self.head_to_tail() {
2941 f(node);
2942 }
2943 }
2944
2945 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
2947 where
2948 F: FnMut(ModifierChainNodeRef<'_>),
2949 {
2950 if mask.is_empty() {
2951 self.for_each_forward(f);
2952 return;
2953 }
2954
2955 if !self.head().aggregate_child_capabilities().intersects(mask) {
2956 return;
2957 }
2958
2959 for node in self.head_to_tail() {
2960 if node.kind_set().intersects(mask) {
2961 f(node);
2962 }
2963 }
2964 }
2965
2966 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
2968 where
2969 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
2970 {
2971 self.for_each_forward_matching(mask, |node_ref| {
2972 node_ref.with_node(|node| f(node_ref.clone(), node));
2973 });
2974 }
2975
2976 pub fn for_each_backward<F>(&self, mut f: F)
2978 where
2979 F: FnMut(ModifierChainNodeRef<'_>),
2980 {
2981 for node in self.tail_to_head() {
2982 f(node);
2983 }
2984 }
2985
2986 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
2988 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
2989 node as *const dyn ModifierNode as *const ()
2990 }
2991
2992 let target = node_data_ptr(node);
2993 for (index, entry) in self.entries.iter().enumerate() {
2994 if node_data_ptr(&*entry.node.borrow()) == target {
2995 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
2996 }
2997 }
2998
2999 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
3000 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
3001 return None;
3002 }
3003 let matches_target = match link {
3004 NodeLink::Head => node_data_ptr(&self.head_sentinel) == target,
3005 NodeLink::Tail => node_data_ptr(&self.tail_sentinel) == target,
3006 NodeLink::Entry(path) => {
3007 let node_borrow = self.entries[path.entry()].node.borrow();
3008 node_data_ptr(&*node_borrow) == target
3009 }
3010 };
3011 if matches_target {
3012 Some(self.make_node_ref(*link))
3013 } else {
3014 None
3015 }
3016 })
3017 }
3018
3019 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
3022 self.entries.get(index).and_then(|entry| {
3023 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
3024 boxed_node.as_any().downcast_ref::<N>()
3025 })
3026 .ok()
3027 })
3028 }
3029
3030 pub fn node_mut<N: ModifierNode + 'static>(
3033 &self,
3034 index: usize,
3035 ) -> Option<std::cell::RefMut<'_, N>> {
3036 self.entries.get(index).and_then(|entry| {
3037 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
3038 boxed_node.as_any_mut().downcast_mut::<N>()
3039 })
3040 .ok()
3041 })
3042 }
3043
3044 pub fn get_node_rc(&self, index: usize) -> Option<&Rc<RefCell<dyn ModifierNode>>> {
3047 self.entries.get(index).map(|entry| &entry.node)
3048 }
3049
3050 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
3052 self.aggregated_capabilities
3053 .contains(NodeCapabilities::for_invalidation(kind))
3054 }
3055
3056 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
3058 where
3059 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
3060 {
3061 for index in 0..self.ordered_nodes.len() {
3062 let (link, cached_caps, _agg) = self.ordered_nodes[index];
3063 match link {
3064 NodeLink::Head => {
3065 f(&mut self.head_sentinel, cached_caps);
3066 }
3067 NodeLink::Tail => {
3068 f(&mut self.tail_sentinel, cached_caps);
3069 }
3070 NodeLink::Entry(path) => {
3071 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
3072 if path.delegates().is_empty() {
3073 f(&mut *node_borrow, cached_caps);
3074 } else {
3075 let mut current: &mut dyn ModifierNode = &mut *node_borrow;
3076 for &delegate_index in path.delegates() {
3077 if let Some(delegate) =
3078 nth_delegate_mut(current, delegate_index as usize)
3079 {
3080 current = delegate;
3081 } else {
3082 return;
3083 }
3084 }
3085 f(current, cached_caps);
3086 }
3087 }
3088 }
3089 }
3090 }
3091
3092 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
3093 ModifierChainNodeRef {
3094 chain: self,
3095 link,
3096 cached_capabilities: None,
3097 cached_aggregate_child: None,
3098 }
3099 }
3100
3101 fn make_node_ref_with_caps(
3102 &self,
3103 link: NodeLink,
3104 caps: NodeCapabilities,
3105 aggregate_child: NodeCapabilities,
3106 ) -> ModifierChainNodeRef<'_> {
3107 ModifierChainNodeRef {
3108 chain: self,
3109 link,
3110 cached_capabilities: Some(caps),
3111 cached_aggregate_child: Some(aggregate_child),
3112 }
3113 }
3114
3115 fn sync_chain_links(&mut self) {
3116 self.rebuild_ordered_nodes();
3117
3118 self.head_sentinel.node_state().set_parent_link(None);
3119 self.tail_sentinel.node_state().set_child_link(None);
3120
3121 if self.ordered_nodes.is_empty() {
3122 self.head_sentinel
3123 .node_state()
3124 .set_child_link(Some(NodeLink::Tail));
3125 self.tail_sentinel
3126 .node_state()
3127 .set_parent_link(Some(NodeLink::Head));
3128 self.aggregated_capabilities = NodeCapabilities::empty();
3129 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
3130 self.head_sentinel
3131 .node_state()
3132 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3133 self.tail_sentinel
3134 .node_state()
3135 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3136 return;
3137 }
3138
3139 let mut previous = NodeLink::Head;
3140 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
3141 match &previous {
3142 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
3143 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
3144 NodeLink::Entry(path) => {
3145 let node_borrow = self.entries[path.entry()].node.borrow();
3146 if path.delegates().is_empty() {
3147 node_borrow.node_state().set_child_link(Some(link));
3148 } else {
3149 let mut current: &dyn ModifierNode = &*node_borrow;
3150 for &delegate_index in path.delegates() {
3151 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3152 current = delegate;
3153 }
3154 }
3155 current.node_state().set_child_link(Some(link));
3156 }
3157 }
3158 }
3159 match &link {
3160 NodeLink::Head => self
3161 .head_sentinel
3162 .node_state()
3163 .set_parent_link(Some(previous)),
3164 NodeLink::Tail => self
3165 .tail_sentinel
3166 .node_state()
3167 .set_parent_link(Some(previous)),
3168 NodeLink::Entry(path) => {
3169 let node_borrow = self.entries[path.entry()].node.borrow();
3170 if path.delegates().is_empty() {
3171 node_borrow.node_state().set_parent_link(Some(previous));
3172 } else {
3173 let mut current: &dyn ModifierNode = &*node_borrow;
3174 for &delegate_index in path.delegates() {
3175 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3176 current = delegate;
3177 }
3178 }
3179 current.node_state().set_parent_link(Some(previous));
3180 }
3181 }
3182 }
3183 previous = link;
3184 }
3185
3186 match &previous {
3187 NodeLink::Head => self
3188 .head_sentinel
3189 .node_state()
3190 .set_child_link(Some(NodeLink::Tail)),
3191 NodeLink::Tail => self
3192 .tail_sentinel
3193 .node_state()
3194 .set_child_link(Some(NodeLink::Tail)),
3195 NodeLink::Entry(path) => {
3196 let node_borrow = self.entries[path.entry()].node.borrow();
3197 if path.delegates().is_empty() {
3198 node_borrow
3199 .node_state()
3200 .set_child_link(Some(NodeLink::Tail));
3201 } else {
3202 let mut current: &dyn ModifierNode = &*node_borrow;
3203 for &delegate_index in path.delegates() {
3204 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3205 current = delegate;
3206 }
3207 }
3208 current.node_state().set_child_link(Some(NodeLink::Tail));
3209 }
3210 }
3211 }
3212 self.tail_sentinel
3213 .node_state()
3214 .set_parent_link(Some(previous));
3215 self.tail_sentinel.node_state().set_child_link(None);
3216
3217 let mut aggregate = NodeCapabilities::empty();
3218 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
3219 aggregate |= *cached_caps;
3220 *cached_aggregate = aggregate;
3221 match link {
3222 NodeLink::Head => {
3223 self.head_sentinel
3224 .node_state()
3225 .set_aggregate_child_capabilities(aggregate);
3226 }
3227 NodeLink::Tail => {
3228 self.tail_sentinel
3229 .node_state()
3230 .set_aggregate_child_capabilities(aggregate);
3231 }
3232 NodeLink::Entry(path) => {
3233 let node_borrow = self.entries[path.entry()].node.borrow();
3234 let state = if path.delegates().is_empty() {
3235 node_borrow.node_state()
3236 } else {
3237 let mut current: &dyn ModifierNode = &*node_borrow;
3238 for &delegate_index in path.delegates() {
3239 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3240 current = delegate;
3241 }
3242 }
3243 current.node_state()
3244 };
3245 state.set_aggregate_child_capabilities(aggregate);
3246 }
3247 }
3248 }
3249
3250 self.aggregated_capabilities = aggregate;
3251 self.head_aggregate_child_capabilities = aggregate;
3252 self.head_sentinel
3253 .node_state()
3254 .set_aggregate_child_capabilities(aggregate);
3255 self.tail_sentinel
3256 .node_state()
3257 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3258 }
3259
3260 fn rebuild_ordered_nodes(&mut self) {
3261 self.ordered_nodes.clear();
3262 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
3263 for (index, entry) in self.entries.iter().enumerate() {
3264 let node_borrow = entry.node.borrow();
3265 Self::enumerate_link_order(
3266 &*node_borrow,
3267 index,
3268 &mut path_buf,
3269 0,
3270 &mut self.ordered_nodes,
3271 );
3272 }
3273 }
3274
3275 fn enumerate_link_order(
3276 node: &dyn ModifierNode,
3277 entry: usize,
3278 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
3279 path_len: usize,
3280 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
3281 ) {
3282 let caps = node.node_state().capabilities();
3283 out.push((
3284 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
3285 caps,
3286 NodeCapabilities::empty(),
3287 ));
3288 let mut delegate_index = 0usize;
3289 node.for_each_delegate(&mut |child| {
3290 if path_len < MAX_DELEGATE_DEPTH {
3291 path_buf[path_len] = delegate_index;
3292 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
3293 }
3294 delegate_index += 1;
3295 });
3296 }
3297}
3298
3299impl<'a> ModifierChainNodeRef<'a> {
3300 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
3301 match &self.link {
3302 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
3303 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
3304 NodeLink::Entry(path) => {
3305 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3306 if path.delegates().is_empty() {
3307 f(node_borrow.node_state())
3308 } else {
3309 let mut current: &dyn ModifierNode = &*node_borrow;
3310 for &delegate_index in path.delegates() {
3311 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3312 current = delegate;
3313 } else {
3314 return f(node_borrow.node_state());
3315 }
3316 }
3317 f(current.node_state())
3318 }
3319 }
3320 }
3321 }
3322
3323 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
3326 match &self.link {
3327 NodeLink::Head => None,
3328 NodeLink::Tail => None,
3329 NodeLink::Entry(path) => {
3330 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3331 if path.delegates().is_empty() {
3332 Some(f(&*node_borrow))
3333 } else {
3334 let mut current: &dyn ModifierNode = &*node_borrow;
3335 for &delegate_index in path.delegates() {
3336 current = nth_delegate(current, delegate_index as usize)?;
3337 }
3338 Some(f(current))
3339 }
3340 }
3341 }
3342 }
3343
3344 #[inline]
3346 pub fn parent(&self) -> Option<Self> {
3347 self.with_state(NodeState::parent_link)
3348 .map(|link| self.chain.make_node_ref(link))
3349 }
3350
3351 #[inline]
3353 pub fn child(&self) -> Option<Self> {
3354 self.with_state(NodeState::child_link)
3355 .map(|link| self.chain.make_node_ref(link))
3356 }
3357
3358 #[inline]
3360 pub fn kind_set(&self) -> NodeCapabilities {
3361 if let Some(caps) = self.cached_capabilities {
3362 return caps;
3363 }
3364 match &self.link {
3365 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
3366 NodeLink::Entry(_) => self.with_state(NodeState::capabilities),
3367 }
3368 }
3369
3370 pub fn entry_index(&self) -> Option<usize> {
3372 match &self.link {
3373 NodeLink::Entry(path) => Some(path.entry()),
3374 _ => None,
3375 }
3376 }
3377
3378 pub fn delegate_depth(&self) -> usize {
3380 match &self.link {
3381 NodeLink::Entry(path) => path.delegates().len(),
3382 _ => 0,
3383 }
3384 }
3385
3386 #[inline]
3388 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
3389 if let Some(agg) = self.cached_aggregate_child {
3390 return agg;
3391 }
3392 if self.is_tail() {
3393 NodeCapabilities::empty()
3394 } else {
3395 self.with_state(NodeState::aggregate_child_capabilities)
3396 }
3397 }
3398
3399 pub fn is_head(&self) -> bool {
3401 matches!(self.link, NodeLink::Head)
3402 }
3403
3404 pub fn is_tail(&self) -> bool {
3406 matches!(self.link, NodeLink::Tail)
3407 }
3408
3409 pub fn is_sentinel(&self) -> bool {
3411 matches!(self.link, NodeLink::Head | NodeLink::Tail)
3412 }
3413
3414 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
3416 !mask.is_empty() && self.kind_set().intersects(mask)
3417 }
3418
3419 pub fn visit_descendants<F>(self, include_self: bool, mut f: F)
3421 where
3422 F: FnMut(ModifierChainNodeRef<'a>),
3423 {
3424 let mut current = if include_self {
3425 Some(self)
3426 } else {
3427 self.child()
3428 };
3429 while let Some(node) = current {
3430 if node.is_tail() {
3431 break;
3432 }
3433 if !node.is_sentinel() {
3434 f(node.clone());
3435 }
3436 current = node.child();
3437 }
3438 }
3439
3440 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3442 where
3443 F: FnMut(ModifierChainNodeRef<'a>),
3444 {
3445 if mask.is_empty() {
3446 self.visit_descendants(include_self, f);
3447 return;
3448 }
3449
3450 if !self.aggregate_child_capabilities().intersects(mask) {
3451 return;
3452 }
3453
3454 self.visit_descendants(include_self, |node| {
3455 if node.kind_set().intersects(mask) {
3456 f(node);
3457 }
3458 });
3459 }
3460
3461 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
3463 where
3464 F: FnMut(ModifierChainNodeRef<'a>),
3465 {
3466 let mut current = if include_self {
3467 Some(self)
3468 } else {
3469 self.parent()
3470 };
3471 while let Some(node) = current {
3472 if node.is_head() {
3473 break;
3474 }
3475 f(node.clone());
3476 current = node.parent();
3477 }
3478 }
3479
3480 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3482 where
3483 F: FnMut(ModifierChainNodeRef<'a>),
3484 {
3485 if mask.is_empty() {
3486 self.visit_ancestors(include_self, f);
3487 return;
3488 }
3489
3490 self.visit_ancestors(include_self, |node| {
3491 if node.kind_set().intersects(mask) {
3492 f(node);
3493 }
3494 });
3495 }
3496}
3497
3498#[cfg(test)]
3499#[path = "tests/modifier_tests.rs"]
3500mod tests;