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,
29 Draw,
31 PointerInput,
33 Semantics,
35 Focus,
37}
38
39pub trait ModifierNodeContext {
41 fn invalidate(&mut self, _kind: InvalidationKind) {}
43
44 fn request_update(&mut self) {}
47
48 fn node_id(&self) -> Option<cranpose_core::NodeId> {
51 None
52 }
53
54 fn push_active_capabilities(&mut self, _capabilities: NodeCapabilities) {}
56
57 fn pop_active_capabilities(&mut self) {}
59
60 fn density(&self) -> f32 {
65 1.0
66 }
67}
68
69#[derive(Default, Debug, Clone)]
78pub struct BasicModifierNodeContext {
79 invalidations: ModifierInvalidations,
80 update_requested: bool,
81 active_capabilities: Vec<NodeCapabilities>,
82 node_id: Option<cranpose_core::NodeId>,
83}
84
85impl BasicModifierNodeContext {
86 pub fn new() -> Self {
88 Self::default()
89 }
90
91 pub fn for_node(
94 node_id: Option<cranpose_core::NodeId>,
95 invalidations: ModifierInvalidations,
96 ) -> Self {
97 Self {
98 invalidations,
99 node_id,
100 ..Self::default()
101 }
102 }
103
104 pub fn invalidations(&self) -> &[ModifierInvalidation] {
108 &self.invalidations
109 }
110
111 pub fn clear_invalidations(&mut self) {
113 self.invalidations.clear();
114 }
115
116 pub fn take_invalidations(&mut self) -> ModifierInvalidations {
118 std::mem::take(&mut self.invalidations)
119 }
120
121 pub fn update_requested(&self) -> bool {
124 self.update_requested
125 }
126
127 pub fn take_update_requested(&mut self) -> bool {
129 std::mem::take(&mut self.update_requested)
130 }
131
132 pub fn set_node_id(&mut self, id: Option<cranpose_core::NodeId>) {
134 self.node_id = id;
135 }
136
137 fn push_invalidation(&mut self, kind: InvalidationKind) {
138 let mut capabilities = self.current_capabilities();
139 capabilities.insert(NodeCapabilities::for_invalidation(kind));
140 if let Some(existing) = self
141 .invalidations
142 .iter_mut()
143 .find(|entry| entry.kind() == kind)
144 {
145 let updated = existing.capabilities() | capabilities;
146 *existing = ModifierInvalidation::new(kind, updated);
147 } else {
148 self.invalidations
149 .push(ModifierInvalidation::new(kind, capabilities));
150 }
151 }
152
153 fn current_capabilities(&self) -> NodeCapabilities {
154 self.active_capabilities
155 .last()
156 .copied()
157 .unwrap_or_else(NodeCapabilities::empty)
158 }
159}
160
161impl ModifierNodeContext for BasicModifierNodeContext {
162 fn invalidate(&mut self, kind: InvalidationKind) {
163 self.push_invalidation(kind);
164 }
165
166 fn request_update(&mut self) {
167 self.update_requested = true;
168 }
169
170 fn push_active_capabilities(&mut self, capabilities: NodeCapabilities) {
171 self.active_capabilities.push(capabilities);
172 }
173
174 fn pop_active_capabilities(&mut self) {
175 self.active_capabilities.pop();
176 }
177
178 fn node_id(&self) -> Option<cranpose_core::NodeId> {
179 self.node_id
180 }
181}
182
183const MAX_DELEGATE_DEPTH: usize = 3;
184
185#[derive(Copy, Clone, Debug, PartialEq, Eq)]
186pub(crate) struct NodePath {
187 entry: u32,
190 delegate_buf: [u8; MAX_DELEGATE_DEPTH],
191 delegate_len: u8,
192}
193
194impl NodePath {
195 #[inline]
196 fn root(entry: usize) -> Self {
197 debug_assert!(entry <= u32::MAX as usize, "chain entry exceeds u32 range");
198 Self {
199 entry: entry as u32,
200 delegate_buf: [0; MAX_DELEGATE_DEPTH],
201 delegate_len: 0,
202 }
203 }
204
205 #[inline]
206 fn from_slice(entry: usize, path: &[usize]) -> Self {
207 debug_assert!(
208 path.len() <= MAX_DELEGATE_DEPTH,
209 "delegate depth {} exceeds MAX_DELEGATE_DEPTH {}",
210 path.len(),
211 MAX_DELEGATE_DEPTH
212 );
213 debug_assert!(
214 path.iter().all(|&i| i <= u8::MAX as usize),
215 "delegate index exceeds u8 range"
216 );
217 let mut delegate_buf = [0u8; MAX_DELEGATE_DEPTH];
218 for (i, &v) in path.iter().enumerate().take(MAX_DELEGATE_DEPTH) {
219 delegate_buf[i] = v as u8;
220 }
221 Self {
222 delegate_buf,
223 delegate_len: path.len().min(MAX_DELEGATE_DEPTH) as u8,
224 ..Self::root(entry)
225 }
226 }
227
228 #[inline]
229 fn entry(&self) -> usize {
230 self.entry as usize
231 }
232
233 #[inline]
234 fn delegates(&self) -> &[u8] {
235 &self.delegate_buf[..self.delegate_len as usize]
236 }
237}
238
239#[derive(Copy, Clone, Debug, PartialEq, Eq)]
240pub(crate) enum NodeLink {
241 Head,
242 Tail,
243 Entry(NodePath),
244}
245
246#[derive(Debug)]
252pub struct NodeState {
253 aggregate_child_capabilities: Cell<NodeCapabilities>,
254 capabilities: Cell<NodeCapabilities>,
255 parent: Cell<Option<NodeLink>>,
256 child: Cell<Option<NodeLink>>,
257 attached: Cell<bool>,
258 is_sentinel: bool,
259}
260
261impl Default for NodeState {
262 fn default() -> Self {
263 Self::new()
264 }
265}
266
267impl NodeState {
268 pub const fn new() -> Self {
270 Self {
271 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
272 capabilities: Cell::new(NodeCapabilities::empty()),
273 parent: Cell::new(None),
274 child: Cell::new(None),
275 attached: Cell::new(false),
276 is_sentinel: false,
277 }
278 }
279
280 pub const fn sentinel() -> Self {
283 Self {
284 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
285 capabilities: Cell::new(NodeCapabilities::empty()),
286 parent: Cell::new(None),
287 child: Cell::new(None),
288 attached: Cell::new(true),
289 is_sentinel: true,
290 }
291 }
292
293 pub fn set_capabilities(&self, capabilities: NodeCapabilities) {
296 self.capabilities.set(capabilities);
297 }
298
299 #[inline]
301 pub fn capabilities(&self) -> NodeCapabilities {
302 self.capabilities.get()
303 }
304
305 pub fn set_aggregate_child_capabilities(&self, capabilities: NodeCapabilities) {
308 self.aggregate_child_capabilities.set(capabilities);
309 }
310
311 #[inline]
314 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
315 self.aggregate_child_capabilities.get()
316 }
317
318 pub(crate) fn set_parent_link(&self, parent: Option<NodeLink>) {
319 self.parent.set(parent);
320 }
321
322 #[inline]
323 pub(crate) fn parent_link(&self) -> Option<NodeLink> {
324 self.parent.get()
325 }
326
327 pub(crate) fn set_child_link(&self, child: Option<NodeLink>) {
328 self.child.set(child);
329 }
330
331 #[inline]
332 pub(crate) fn child_link(&self) -> Option<NodeLink> {
333 self.child.get()
334 }
335
336 pub fn set_attached(&self, attached: bool) {
338 self.attached.set(attached);
339 }
340
341 pub fn is_attached(&self) -> bool {
344 self.attached.get()
345 }
346
347 pub fn is_sentinel(&self) -> bool {
350 self.is_sentinel
351 }
352}
353
354pub trait DelegatableNode {
356 fn node_state(&self) -> &NodeState;
359 fn aggregate_child_capabilities(&self) -> NodeCapabilities {
361 self.node_state().aggregate_child_capabilities()
362 }
363}
364
365pub trait ModifierNode: Any + DelegatableNode {
423 fn on_attach(&mut self, _context: &mut dyn ModifierNodeContext) {}
426
427 fn on_detach(&mut self) {}
430
431 fn on_reset(&mut self) {}
434
435 fn as_draw_node(&self) -> Option<&dyn DrawModifierNode> {
437 None
438 }
439
440 fn as_draw_node_mut(&mut self) -> Option<&mut dyn DrawModifierNode> {
442 None
443 }
444
445 fn as_pointer_input_node(&self) -> Option<&dyn PointerInputNode> {
447 None
448 }
449
450 fn as_pointer_input_node_mut(&mut self) -> Option<&mut dyn PointerInputNode> {
452 None
453 }
454
455 fn as_semantics_node(&self) -> Option<&dyn SemanticsNode> {
457 None
458 }
459
460 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn SemanticsNode> {
462 None
463 }
464
465 fn as_focus_node(&self) -> Option<&dyn FocusNode> {
467 None
468 }
469
470 fn as_focus_node_mut(&mut self) -> Option<&mut dyn FocusNode> {
472 None
473 }
474
475 fn as_layout_node(&self) -> Option<&dyn LayoutModifierNode> {
477 None
478 }
479
480 fn as_layout_node_mut(&mut self) -> Option<&mut dyn LayoutModifierNode> {
482 None
483 }
484
485 fn for_each_delegate<'b>(&'b self, _visitor: &mut dyn FnMut(&'b dyn ModifierNode)) {}
487
488 fn for_each_delegate_mut<'b>(&'b mut self, _visitor: &mut dyn FnMut(&'b mut dyn ModifierNode)) {
490 }
491}
492
493pub trait LayoutModifierNode: ModifierNode {
499 fn measure(
521 &self,
522 _context: &mut dyn ModifierNodeContext,
523 measurable: &dyn Measurable,
524 constraints: Constraints,
525 ) -> cranpose_ui_layout::LayoutModifierMeasureResult {
526 let placeable = measurable.measure(constraints);
527 cranpose_ui_layout::LayoutModifierMeasureResult::with_size(Size {
528 width: placeable.width(),
529 height: placeable.height(),
530 })
531 }
532
533 fn measure_hold(
540 &self,
541 _density: f32,
542 _constraints: Constraints,
543 _size: Size,
544 _wrapped: cranpose_ui_layout::WrappedHold,
545 ) -> Option<cranpose_ui_layout::ConstraintsHold> {
546 None
547 }
548
549 fn min_intrinsic_width(&self, measurable: &dyn Measurable, height: f32, _density: f32) -> f32 {
552 measurable.min_intrinsic_width(height)
553 }
554
555 fn max_intrinsic_width(&self, measurable: &dyn Measurable, height: f32, _density: f32) -> f32 {
558 measurable.max_intrinsic_width(height)
559 }
560
561 fn min_intrinsic_height(&self, measurable: &dyn Measurable, width: f32, _density: f32) -> f32 {
564 measurable.min_intrinsic_height(width)
565 }
566
567 fn max_intrinsic_height(&self, measurable: &dyn Measurable, width: f32, _density: f32) -> f32 {
570 measurable.max_intrinsic_height(width)
571 }
572}
573
574pub trait DrawModifierNode: ModifierNode {
581 fn create_draw_closure(&self) -> Option<NodeDrawClosure> {
592 None
593 }
594
595 fn create_behind_draw_closure(&self) -> Option<NodeDrawClosure> {
600 None
601 }
602}
603
604pub type NodeDrawClosure = Rc<dyn Fn(&mut cranpose_ui_graphics::DrawScopeDefault)>;
609
610pub trait PointerInputNode: ModifierNode {
616 fn on_pointer_event(
619 &mut self,
620 _context: &mut dyn ModifierNodeContext,
621 _event: &PointerEvent,
622 ) -> bool {
623 false
624 }
625
626 fn hit_test(&self, _x: f32, _y: f32) -> bool {
629 true
630 }
631
632 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
634 None
635 }
636
637 fn layout_size_sink(&self) -> Option<Rc<Cell<Size>>> {
650 None
651 }
652}
653
654pub trait SemanticsNode: ModifierNode {
660 fn merge_semantics(&self, _config: &mut SemanticsConfiguration) {}
662
663 fn reach(&self) -> SemanticsReach {
670 SemanticsReach::merged_by(self, true)
671 }
672}
673
674#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
679pub struct SemanticsReach {
680 pub is_modal: bool,
682 pub hidden: bool,
684 pub merges_live_state: bool,
688}
689
690impl SemanticsReach {
691 pub fn merged_by(node: &(impl SemanticsNode + ?Sized), merges_live_state: bool) -> Self {
694 let mut config = SemanticsConfiguration::default();
695 node.merge_semantics(&mut config);
696 Self {
697 is_modal: config.is_modal,
698 hidden: config.hidden,
699 merges_live_state,
700 }
701 }
702
703 pub fn union(self, other: Self) -> Self {
705 Self {
706 is_modal: self.is_modal || other.is_modal,
707 hidden: self.hidden || other.hidden,
708 merges_live_state: self.merges_live_state || other.merges_live_state,
709 }
710 }
711}
712
713#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
717pub enum ToggleableState {
718 On,
720 Off,
722 Indeterminate,
724}
725
726impl From<bool> for ToggleableState {
727 fn from(on: bool) -> Self {
728 if on { Self::On } else { Self::Off }
729 }
730}
731
732#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
737pub enum FocusState {
738 Active,
740 ActiveParent,
742 Captured,
746 #[default]
749 Inactive,
750}
751
752impl FocusState {
753 pub fn is_focused(self) -> bool {
755 matches!(self, FocusState::Active | FocusState::Captured)
756 }
757
758 pub fn has_focus(self) -> bool {
760 matches!(
761 self,
762 FocusState::Active | FocusState::ActiveParent | FocusState::Captured
763 )
764 }
765
766 pub fn is_captured(self) -> bool {
768 matches!(self, FocusState::Captured)
769 }
770}
771
772pub trait FocusNode: ModifierNode {
777 fn focus_state(&self) -> FocusState;
779
780 fn on_focus_changed(&mut self, _context: &mut dyn ModifierNodeContext, _state: FocusState) {}
782}
783
784#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
795pub enum SemanticsWidgetRole {
796 Button,
798 Checkbox,
800 Switch,
802 RadioButton,
804 Tab,
806 Image,
808 DropdownList,
811 ValuePicker,
814 Header,
819 Dialog,
823 Link,
826 SearchField,
829 ProgressBar,
832 ToggleButton,
835 Alert,
838 Toolbar,
841 Menu,
843 MenuItem,
845 TabBar,
848 List,
850 ListItem,
852 RadioGroup,
854}
855
856#[derive(Clone, Copy, Debug, PartialEq)]
864pub struct ProgressBarRangeInfo {
865 pub current: f32,
867 pub start: f32,
869 pub end: f32,
871 pub steps: u32,
874}
875
876impl ProgressBarRangeInfo {
877 pub fn new(current: f32, start: f32, end: f32, steps: u32) -> Self {
880 Self {
881 current,
882 start,
883 end,
884 steps,
885 }
886 }
887
888 pub fn fraction(&self) -> f32 {
890 let span = self.end - self.start;
891 if span.abs() < f32::EPSILON {
892 return 0.0;
893 }
894 ((self.current - self.start) / span).clamp(0.0, 1.0)
895 }
896
897 pub fn step(&self) -> f32 {
900 let span = self.end - self.start;
901 if self.steps == 0 {
902 span / 10.0
903 } else {
904 span / (self.steps as f32 + 1.0)
905 }
906 }
907}
908
909#[derive(Clone, Copy, Debug, PartialEq, Eq)]
912pub struct CollectionInfo {
913 pub rows: usize,
915 pub columns: usize,
917}
918
919#[derive(Clone, Copy, Debug, PartialEq)]
932pub struct ScrollAxisRange {
933 pub value: f32,
936 pub max_value: f32,
938 pub reverse: bool,
941 pub content_padding_start: f32,
943 pub content_padding_end: f32,
945}
946
947impl ScrollAxisRange {
948 pub fn new(value: f32, max_value: f32, reverse: bool) -> Self {
951 Self {
952 value,
953 max_value,
954 reverse,
955 content_padding_start: 0.0,
956 content_padding_end: 0.0,
957 }
958 }
959
960 pub fn with_content_padding(self, start: f32, end: f32) -> Self {
963 Self {
964 content_padding_start: start,
965 content_padding_end: end,
966 ..self
967 }
968 }
969
970 pub fn can_scroll_forward(&self) -> bool {
972 self.value < self.max_value
973 }
974
975 pub fn can_scroll_backward(&self) -> bool {
977 self.value > 0.0
978 }
979}
980
981#[derive(Clone)]
987pub struct SemanticsScrollBy {
988 handler: Rc<dyn Fn(f32, f32) -> bool>,
989}
990
991impl SemanticsScrollBy {
992 pub fn new(handler: impl Fn(f32, f32) -> bool + 'static) -> Self {
995 Self {
996 handler: Rc::new(handler),
997 }
998 }
999
1000 pub fn invoke(&self, dx: f32, dy: f32) -> bool {
1003 (self.handler)(dx, dy)
1004 }
1005}
1006
1007impl fmt::Debug for SemanticsScrollBy {
1008 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1009 f.debug_struct("SemanticsScrollBy").finish_non_exhaustive()
1010 }
1011}
1012
1013impl PartialEq for SemanticsScrollBy {
1014 fn eq(&self, _other: &Self) -> bool {
1015 true
1016 }
1017}
1018
1019impl Eq for SemanticsScrollBy {}
1020
1021#[derive(Clone)]
1027pub struct SemanticsScrollToIndex {
1028 handler: Rc<dyn Fn(usize) -> bool>,
1029}
1030
1031impl SemanticsScrollToIndex {
1032 pub fn new(handler: impl Fn(usize) -> bool + 'static) -> Self {
1035 Self {
1036 handler: Rc::new(handler),
1037 }
1038 }
1039
1040 pub fn invoke(&self, index: usize) -> bool {
1042 (self.handler)(index)
1043 }
1044}
1045
1046impl fmt::Debug for SemanticsScrollToIndex {
1047 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1048 f.debug_struct("SemanticsScrollToIndex")
1049 .finish_non_exhaustive()
1050 }
1051}
1052
1053impl PartialEq for SemanticsScrollToIndex {
1054 fn eq(&self, _other: &Self) -> bool {
1055 true
1056 }
1057}
1058
1059impl Eq for SemanticsScrollToIndex {}
1060
1061#[derive(Clone)]
1067pub struct SemanticsSetProgress {
1068 handler: Rc<dyn Fn(f32) -> bool>,
1069}
1070
1071impl SemanticsSetProgress {
1072 pub fn new(handler: impl Fn(f32) -> bool + 'static) -> Self {
1075 Self {
1076 handler: Rc::new(handler),
1077 }
1078 }
1079
1080 pub fn invoke(&self, value: f32) -> bool {
1083 (self.handler)(value)
1084 }
1085}
1086
1087impl fmt::Debug for SemanticsSetProgress {
1088 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1089 f.debug_struct("SemanticsSetProgress")
1090 .finish_non_exhaustive()
1091 }
1092}
1093
1094#[derive(Clone)]
1098pub struct SemanticsSetText(Rc<dyn Fn(&str) -> bool>);
1099
1100impl SemanticsSetText {
1101 pub fn new(handler: impl Fn(&str) -> bool + 'static) -> Self {
1103 Self(Rc::new(handler))
1104 }
1105
1106 pub fn invoke(&self, text: &str) -> bool {
1108 (self.0)(text)
1109 }
1110}
1111
1112impl fmt::Debug for SemanticsSetText {
1113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1114 f.write_str("SemanticsSetText")
1115 }
1116}
1117
1118#[derive(Clone)]
1124pub struct SemanticsSetSelection(Rc<dyn Fn(usize, usize) -> bool>);
1125
1126impl SemanticsSetSelection {
1127 pub fn new(handler: impl Fn(usize, usize) -> bool + 'static) -> Self {
1130 Self(Rc::new(handler))
1131 }
1132
1133 pub fn invoke(&self, anchor: usize, focus: usize) -> bool {
1136 (self.0)(anchor, focus)
1137 }
1138}
1139
1140impl fmt::Debug for SemanticsSetSelection {
1141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1142 f.write_str("SemanticsSetSelection")
1143 }
1144}
1145
1146#[derive(Clone)]
1149pub struct SemanticsExpand(Rc<dyn Fn() -> bool>);
1150
1151impl SemanticsExpand {
1152 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1154 Self(Rc::new(handler))
1155 }
1156
1157 pub fn invoke(&self) -> bool {
1159 (self.0)()
1160 }
1161}
1162
1163impl fmt::Debug for SemanticsExpand {
1164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1165 f.write_str("SemanticsExpand")
1166 }
1167}
1168
1169#[derive(Clone)]
1173pub struct SemanticsLongClick(Rc<dyn Fn() -> bool>);
1174
1175impl SemanticsLongClick {
1176 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1178 Self(Rc::new(handler))
1179 }
1180
1181 pub fn invoke(&self) -> bool {
1183 (self.0)()
1184 }
1185}
1186
1187impl fmt::Debug for SemanticsLongClick {
1188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1189 f.write_str("SemanticsLongClick")
1190 }
1191}
1192
1193impl PartialEq for SemanticsLongClick {
1194 fn eq(&self, _other: &Self) -> bool {
1195 true
1196 }
1197}
1198
1199impl PartialEq for SemanticsExpand {
1200 fn eq(&self, _other: &Self) -> bool {
1201 true
1202 }
1203}
1204
1205#[derive(Clone)]
1209pub struct SemanticsDismiss(Rc<dyn Fn() -> bool>);
1210
1211impl SemanticsDismiss {
1212 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1214 Self(Rc::new(handler))
1215 }
1216
1217 pub fn invoke(&self) -> bool {
1219 (self.0)()
1220 }
1221}
1222
1223impl fmt::Debug for SemanticsDismiss {
1224 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1225 f.write_str("SemanticsDismiss")
1226 }
1227}
1228
1229impl PartialEq for SemanticsDismiss {
1230 fn eq(&self, _other: &Self) -> bool {
1231 true
1232 }
1233}
1234
1235impl PartialEq for SemanticsSetText {
1236 fn eq(&self, _other: &Self) -> bool {
1237 true
1238 }
1239}
1240
1241impl PartialEq for SemanticsSetSelection {
1242 fn eq(&self, _other: &Self) -> bool {
1243 true
1244 }
1245}
1246
1247#[derive(Clone)]
1253pub struct SemanticsMagicTap(Rc<dyn Fn() -> bool>);
1254
1255impl SemanticsMagicTap {
1256 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1258 Self(Rc::new(handler))
1259 }
1260
1261 pub fn invoke(&self) -> bool {
1263 (self.0)()
1264 }
1265}
1266
1267impl fmt::Debug for SemanticsMagicTap {
1268 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1269 f.write_str("SemanticsMagicTap")
1270 }
1271}
1272
1273impl PartialEq for SemanticsMagicTap {
1274 fn eq(&self, _other: &Self) -> bool {
1275 true
1276 }
1277}
1278
1279impl PartialEq for SemanticsSetProgress {
1280 fn eq(&self, _other: &Self) -> bool {
1281 true
1282 }
1283}
1284
1285impl Eq for SemanticsSetProgress {}
1286
1287#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1294pub enum LiveRegionMode {
1295 Polite,
1297 Assertive,
1300}
1301
1302#[derive(Clone)]
1309pub struct SemanticsCustomAction {
1310 pub label: String,
1312 handler: Rc<dyn Fn()>,
1313}
1314
1315impl SemanticsCustomAction {
1316 pub fn new(label: impl Into<String>, handler: impl Fn() + 'static) -> Self {
1318 Self {
1319 label: label.into(),
1320 handler: Rc::new(handler),
1321 }
1322 }
1323
1324 pub fn invoke(&self) {
1326 (self.handler)();
1327 }
1328}
1329
1330impl fmt::Debug for SemanticsCustomAction {
1331 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1332 f.debug_struct("SemanticsCustomAction")
1333 .field("label", &self.label)
1334 .finish_non_exhaustive()
1335 }
1336}
1337
1338impl PartialEq for SemanticsCustomAction {
1339 fn eq(&self, other: &Self) -> bool {
1340 self.label == other.label
1341 }
1342}
1343
1344impl Eq for SemanticsCustomAction {}
1345
1346#[derive(Clone, Debug, PartialEq)]
1361pub struct CanvasSemanticsNode {
1362 pub key: u64,
1369 pub bounds: cranpose_ui_graphics::Rect,
1371 pub label: String,
1373 pub role: Option<SemanticsWidgetRole>,
1375 pub state_description: Option<String>,
1379 pub on_click_label: Option<String>,
1382 pub clickable: bool,
1384 pub selected: Option<bool>,
1386 pub toggled: Option<ToggleableState>,
1388 pub enabled: bool,
1390 pub custom_actions: Vec<SemanticsCustomAction>,
1392}
1393
1394impl Default for CanvasSemanticsNode {
1395 fn default() -> Self {
1396 Self {
1397 key: 0,
1398 bounds: cranpose_ui_graphics::Rect {
1399 x: 0.0,
1400 y: 0.0,
1401 width: 0.0,
1402 height: 0.0,
1403 },
1404 label: String::new(),
1405 role: None,
1406 state_description: None,
1407 on_click_label: None,
1408 clickable: false,
1409 selected: None,
1410 toggled: None,
1411 enabled: true,
1412 custom_actions: Vec::new(),
1413 }
1414 }
1415}
1416
1417impl CanvasSemanticsNode {
1418 pub fn control(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1420 Self {
1421 key,
1422 bounds,
1423 label: label.into(),
1424 clickable: true,
1425 ..Self::default()
1426 }
1427 }
1428
1429 pub fn text(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1431 Self {
1432 key,
1433 bounds,
1434 label: label.into(),
1435 ..Self::default()
1436 }
1437 }
1438
1439 pub fn with_role(mut self, role: SemanticsWidgetRole) -> Self {
1441 self.role = Some(role);
1442 self
1443 }
1444
1445 pub fn with_state_description(mut self, state: impl Into<String>) -> Self {
1447 self.state_description = Some(state.into());
1448 self
1449 }
1450
1451 pub fn with_click_label(mut self, label: impl Into<String>) -> Self {
1454 self.on_click_label = Some(label.into());
1455 self.clickable = true;
1456 self
1457 }
1458
1459 pub fn with_selected(mut self, selected: bool) -> Self {
1461 self.selected = Some(selected);
1462 self
1463 }
1464
1465 pub fn with_toggled(mut self, toggled: impl Into<ToggleableState>) -> Self {
1467 self.toggled = Some(toggled.into());
1468 self
1469 }
1470
1471 pub fn with_enabled(mut self, enabled: bool) -> Self {
1473 self.enabled = enabled;
1474 self
1475 }
1476
1477 pub fn with_custom_action(mut self, action: SemanticsCustomAction) -> Self {
1479 self.custom_actions.push(action);
1480 self
1481 }
1482}
1483
1484#[derive(Clone, Debug, PartialEq)]
1486pub struct SemanticsConfiguration {
1487 pub content_description: Option<String>,
1489 pub state_description: Option<String>,
1491 pub on_click_label: Option<String>,
1493 pub on_click: Option<SemanticsCustomAction>,
1496 pub on_long_click: Option<SemanticsLongClick>,
1499 pub on_long_click_label: Option<String>,
1502 pub on_magic_tap: Option<SemanticsMagicTap>,
1506 pub on_magic_tap_label: Option<String>,
1509 pub input_labels: Vec<String>,
1513 pub language: Option<String>,
1517 pub role: Option<SemanticsWidgetRole>,
1519 pub selected: Option<bool>,
1521 pub toggled: Option<ToggleableState>,
1524 pub enabled: bool,
1526 pub is_clickable: bool,
1528 pub is_editable_text: bool,
1530 pub multiline: bool,
1532 pub text: Option<String>,
1535 pub text_selection: Option<crate::text::TextRange>,
1537 pub custom_actions: Vec<SemanticsCustomAction>,
1539 pub canvas_children: Vec<CanvasSemanticsNode>,
1542 pub is_modal: bool,
1545 pub hidden: bool,
1549 pub merge_descendants: bool,
1553 pub selectable_group: bool,
1557 pub pane_title: Option<String>,
1560 pub error: Option<String>,
1563 pub password: bool,
1566 pub traversal_index: f32,
1570 pub test_tag: Option<String>,
1573 pub live_region: Option<LiveRegionMode>,
1576 pub progress: Option<ProgressBarRangeInfo>,
1579 pub set_progress: Option<SemanticsSetProgress>,
1582 pub set_text: Option<SemanticsSetText>,
1585 pub set_selection: Option<SemanticsSetSelection>,
1588 pub expand: Option<SemanticsExpand>,
1591 pub dismiss: Option<SemanticsDismiss>,
1595 pub collapse: Option<SemanticsExpand>,
1598 pub vertical_scroll: Option<ScrollAxisRange>,
1601 pub horizontal_scroll: Option<ScrollAxisRange>,
1604 pub scroll_by: Option<SemanticsScrollBy>,
1607 pub scroll_to_index: Option<SemanticsScrollToIndex>,
1611 pub collection: Option<CollectionInfo>,
1613}
1614
1615impl Default for SemanticsConfiguration {
1616 fn default() -> Self {
1617 Self {
1618 content_description: None,
1619 state_description: None,
1620 on_click_label: None,
1621 on_click: None,
1622 on_long_click: None,
1623 on_long_click_label: None,
1624 on_magic_tap: None,
1625 on_magic_tap_label: None,
1626 input_labels: Vec::new(),
1627 language: None,
1628 role: None,
1629 selected: None,
1630 toggled: None,
1631 enabled: true,
1632 is_clickable: false,
1633 is_editable_text: false,
1634 multiline: false,
1635 text: None,
1636 text_selection: None,
1637 custom_actions: Vec::new(),
1638 canvas_children: Vec::new(),
1639 is_modal: false,
1640 hidden: false,
1641 merge_descendants: false,
1642 selectable_group: false,
1643 pane_title: None,
1644 error: None,
1645 password: false,
1646 traversal_index: 0.0,
1647 test_tag: None,
1648 live_region: None,
1649 progress: None,
1650 set_progress: None,
1651 set_text: None,
1652 set_selection: None,
1653 expand: None,
1654 dismiss: None,
1655 collapse: None,
1656 vertical_scroll: None,
1657 horizontal_scroll: None,
1658 scroll_by: None,
1659 scroll_to_index: None,
1660 collection: None,
1661 }
1662 }
1663}
1664
1665pub type SemanticsSpec = SemanticsConfiguration;
1674
1675impl SemanticsConfiguration {
1676 pub fn new() -> Self {
1679 Self::default()
1680 }
1681
1682 pub fn content_description(mut self, name: impl Into<String>) -> Self {
1685 self.content_description = Some(name.into());
1686 self
1687 }
1688
1689 pub fn test_tag(mut self, tag: impl Into<String>) -> Self {
1692 self.test_tag = Some(tag.into());
1693 self
1694 }
1695
1696 pub fn state_description(mut self, state: impl Into<String>) -> Self {
1699 self.state_description = Some(state.into());
1700 self
1701 }
1702
1703 pub fn clickable(mut self) -> Self {
1705 self.is_clickable = true;
1706 self
1707 }
1708
1709 pub fn on_click(mut self, label: impl Into<String>, action: impl Fn() + 'static) -> Self {
1712 self.on_click = Some(SemanticsCustomAction::new(label, action));
1713 self
1714 }
1715
1716 pub fn on_long_click(
1720 mut self,
1721 label: impl Into<String>,
1722 action: impl Fn() -> bool + 'static,
1723 ) -> Self {
1724 self.on_long_click_label = Some(label.into());
1725 self.on_long_click = Some(SemanticsLongClick::new(action));
1726 self
1727 }
1728
1729 pub fn on_magic_tap(
1733 mut self,
1734 label: impl Into<String>,
1735 action: impl Fn() -> bool + 'static,
1736 ) -> Self {
1737 self.on_magic_tap_label = Some(label.into());
1738 self.on_magic_tap = Some(SemanticsMagicTap::new(action));
1739 self
1740 }
1741
1742 pub fn input_labels<S: Into<String>>(mut self, labels: impl IntoIterator<Item = S>) -> Self {
1745 self.input_labels = labels.into_iter().map(Into::into).collect();
1746 self
1747 }
1748
1749 pub fn language(mut self, tag: impl Into<String>) -> Self {
1752 self.language = Some(tag.into());
1753 self
1754 }
1755
1756 pub fn toggled(mut self, toggled: impl Into<ToggleableState>) -> Self {
1759 self.toggled = Some(toggled.into());
1760 self
1761 }
1762
1763 pub fn selected(mut self, selected: bool) -> Self {
1766 self.selected = Some(selected);
1767 self
1768 }
1769
1770 pub fn role(mut self, role: SemanticsWidgetRole) -> Self {
1772 self.role = Some(role);
1773 self
1774 }
1775
1776 pub fn heading(self) -> Self {
1779 self.role(SemanticsWidgetRole::Header)
1780 }
1781
1782 pub fn error(mut self, message: impl Into<String>) -> Self {
1784 self.error = Some(message.into());
1785 self
1786 }
1787
1788 pub fn password(mut self) -> Self {
1790 self.password = true;
1791 self
1792 }
1793
1794 pub fn pane_title(mut self, title: impl Into<String>) -> Self {
1797 self.pane_title = Some(title.into());
1798 self
1799 }
1800
1801 pub fn traversal_index(mut self, index: f32) -> Self {
1804 self.traversal_index = index;
1805 self
1806 }
1807
1808 pub fn hidden(mut self) -> Self {
1811 self.hidden = true;
1812 self
1813 }
1814
1815 pub fn merge_descendants(mut self) -> Self {
1818 self.merge_descendants = true;
1819 self
1820 }
1821
1822 pub fn selectable_group(mut self) -> Self {
1825 self.selectable_group = true;
1826 self
1827 }
1828
1829 pub fn live_region(mut self, mode: LiveRegionMode) -> Self {
1832 self.live_region = Some(mode);
1833 self
1834 }
1835 pub fn merge(&mut self, other: &SemanticsConfiguration) {
1839 if let Some(description) = &other.content_description {
1840 self.content_description = Some(description.clone());
1841 }
1842 if let Some(state) = &other.state_description {
1843 self.state_description = Some(state.clone());
1844 }
1845 if let Some(label) = &other.on_click_label {
1846 self.on_click_label = Some(label.clone());
1847 }
1848 if let Some(label) = &other.on_long_click_label {
1849 self.on_long_click_label = Some(label.clone());
1850 }
1851 if let Some(label) = &other.on_magic_tap_label {
1852 self.on_magic_tap_label = Some(label.clone());
1853 }
1854 if !other.input_labels.is_empty() {
1855 self.input_labels.clone_from(&other.input_labels);
1856 }
1857 if let Some(language) = &other.language {
1858 self.language = Some(language.clone());
1859 }
1860 if let Some(role) = other.role {
1861 self.role = Some(role);
1862 }
1863 if let Some(selected) = other.selected {
1864 self.selected = Some(selected);
1865 }
1866 if let Some(toggled) = other.toggled {
1867 self.toggled = Some(toggled);
1868 }
1869 self.enabled &= other.enabled;
1870 self.is_clickable |= other.is_clickable;
1871 self.is_editable_text |= other.is_editable_text;
1872 self.multiline |= other.multiline;
1873 if let Some(text) = &other.text {
1874 self.text = Some(text.clone());
1875 }
1876 self.is_modal |= other.is_modal;
1877 self.hidden |= other.hidden;
1878 self.merge_descendants |= other.merge_descendants;
1879 self.selectable_group |= other.selectable_group;
1880 self.password |= other.password;
1881 if other.traversal_index != 0.0 {
1882 self.traversal_index = other.traversal_index;
1883 }
1884 if let Some(live_region) = other.live_region {
1885 self.live_region = Some(live_region);
1886 }
1887 self.merge_words(other);
1888 self.merge_actions(other);
1889 self.merge_ranges(other);
1890 }
1891
1892 fn merge_words(&mut self, other: &SemanticsConfiguration) {
1893 if let Some(title) = &other.pane_title {
1894 self.pane_title = Some(title.clone());
1895 }
1896 if let Some(error) = &other.error {
1897 self.error = Some(error.clone());
1898 }
1899 if let Some(tag) = &other.test_tag {
1900 self.test_tag = Some(tag.clone());
1901 }
1902 }
1903
1904 fn merge_actions(&mut self, other: &SemanticsConfiguration) {
1905 if let Some(on_click) = &other.on_click {
1906 self.on_click = Some(on_click.clone());
1907 }
1908 self.custom_actions
1909 .extend(other.custom_actions.iter().cloned());
1910 self.canvas_children
1911 .extend(other.canvas_children.iter().cloned());
1912 if let Some(set_progress) = &other.set_progress {
1913 self.set_progress = Some(set_progress.clone());
1914 }
1915 if let Some(set_text) = &other.set_text {
1916 self.set_text = Some(set_text.clone());
1917 }
1918 if let Some(set_selection) = &other.set_selection {
1919 self.set_selection = Some(set_selection.clone());
1920 }
1921 if let Some(expand) = &other.expand {
1922 self.expand = Some(expand.clone());
1923 }
1924 if let Some(collapse) = &other.collapse {
1925 self.collapse = Some(collapse.clone());
1926 }
1927 if let Some(dismiss) = &other.dismiss {
1928 self.dismiss = Some(dismiss.clone());
1929 }
1930 if let Some(long_click) = &other.on_long_click {
1931 self.on_long_click = Some(long_click.clone());
1932 }
1933 if let Some(magic_tap) = &other.on_magic_tap {
1934 self.on_magic_tap = Some(magic_tap.clone());
1935 }
1936 if let Some(scroll_by) = &other.scroll_by {
1937 self.scroll_by = Some(scroll_by.clone());
1938 }
1939 if let Some(scroll_to_index) = &other.scroll_to_index {
1940 self.scroll_to_index = Some(scroll_to_index.clone());
1941 }
1942 }
1943
1944 fn merge_ranges(&mut self, other: &SemanticsConfiguration) {
1945 if let Some(selection) = other.text_selection {
1946 self.text_selection = Some(selection);
1947 }
1948 if let Some(progress) = other.progress {
1949 self.progress = Some(progress);
1950 }
1951 if let Some(range) = other.vertical_scroll {
1952 self.vertical_scroll = Some(range);
1953 }
1954 if let Some(range) = other.horizontal_scroll {
1955 self.horizontal_scroll = Some(range);
1956 }
1957 if let Some(collection) = other.collection {
1958 self.collection = Some(collection);
1959 }
1960 }
1961
1962 pub fn is_activatable(&self) -> bool {
1965 self.is_clickable || self.on_click_label.is_some() || self.on_click.is_some()
1966 }
1967}
1968
1969impl fmt::Debug for dyn ModifierNode {
1970 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1971 f.debug_struct("ModifierNode").finish_non_exhaustive()
1972 }
1973}
1974
1975impl dyn ModifierNode {
1976 pub fn as_any(&self) -> &dyn Any {
1978 self
1979 }
1980
1981 pub fn as_any_mut(&mut self) -> &mut dyn Any {
1983 self
1984 }
1985}
1986
1987pub trait ModifierNodeElement: fmt::Debug + Hash + PartialEq + 'static {
1990 type Node: ModifierNode;
1992
1993 fn create(&self) -> Self::Node;
1995
1996 fn update(&self, node: &mut Self::Node);
1998
1999 fn key(&self) -> Option<u64> {
2001 None
2002 }
2003
2004 fn inspector_name(&self) -> &'static str {
2006 type_name::<Self>()
2007 }
2008
2009 fn inspector_properties(&self, _inspector: &mut dyn FnMut(&'static str, String)) {}
2011
2012 fn capabilities(&self) -> NodeCapabilities {
2015 NodeCapabilities::default()
2016 }
2017
2018 fn always_update(&self) -> bool {
2024 false
2025 }
2026
2027 fn auto_invalidate_on_update(&self) -> bool {
2030 true
2031 }
2032
2033 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
2040 None
2041 }
2042
2043 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2050 Vec::new()
2051 }
2052}
2053
2054#[derive(Clone, Copy, PartialEq, Eq, Hash)]
2056pub struct NodeCapabilities(u32);
2057
2058impl NodeCapabilities {
2059 pub const NONE: Self = Self(0);
2061 pub const LAYOUT: Self = Self(1 << 0);
2063 pub const DRAW: Self = Self(1 << 1);
2065 pub const POINTER_INPUT: Self = Self(1 << 2);
2067 pub const SEMANTICS: Self = Self(1 << 3);
2069 pub const MODIFIER_LOCALS: Self = Self(1 << 4);
2071 pub const FOCUS: Self = Self(1 << 5);
2073 pub const WINDOW_ROOT: Self = Self(1 << 6);
2077 pub const KEY_INPUT: Self = Self(1 << 7);
2079
2080 pub const fn empty() -> Self {
2082 Self::NONE
2083 }
2084
2085 pub const fn contains(self, other: Self) -> bool {
2087 (self.0 & other.0) == other.0
2088 }
2089
2090 pub const fn intersects(self, other: Self) -> bool {
2092 (self.0 & other.0) != 0
2093 }
2094
2095 pub fn insert(&mut self, other: Self) {
2097 self.0 |= other.0;
2098 }
2099
2100 pub const fn bits(self) -> u32 {
2102 self.0
2103 }
2104
2105 pub const fn is_empty(self) -> bool {
2107 self.0 == 0
2108 }
2109
2110 pub const fn for_invalidation(kind: InvalidationKind) -> Self {
2112 match kind {
2113 InvalidationKind::Layout => Self::LAYOUT,
2114 InvalidationKind::Draw => Self::DRAW,
2115 InvalidationKind::PointerInput => Self::POINTER_INPUT,
2116 InvalidationKind::Semantics => Self::SEMANTICS,
2117 InvalidationKind::Focus => Self::FOCUS,
2118 }
2119 }
2120}
2121
2122impl Default for NodeCapabilities {
2123 fn default() -> Self {
2124 Self::NONE
2125 }
2126}
2127
2128impl fmt::Debug for NodeCapabilities {
2129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2130 f.debug_struct("NodeCapabilities")
2131 .field("layout", &self.contains(Self::LAYOUT))
2132 .field("draw", &self.contains(Self::DRAW))
2133 .field("pointer_input", &self.contains(Self::POINTER_INPUT))
2134 .field("semantics", &self.contains(Self::SEMANTICS))
2135 .field("modifier_locals", &self.contains(Self::MODIFIER_LOCALS))
2136 .field("focus", &self.contains(Self::FOCUS))
2137 .field("window_root", &self.contains(Self::WINDOW_ROOT))
2138 .field("key_input", &self.contains(Self::KEY_INPUT))
2139 .finish()
2140 }
2141}
2142
2143impl BitOr for NodeCapabilities {
2144 type Output = Self;
2145
2146 fn bitor(self, rhs: Self) -> Self::Output {
2147 Self(self.0 | rhs.0)
2148 }
2149}
2150
2151impl BitOrAssign for NodeCapabilities {
2152 fn bitor_assign(&mut self, rhs: Self) {
2153 self.0 |= rhs.0;
2154 }
2155}
2156
2157pub type ModifierInvalidations = smallvec::SmallVec<[ModifierInvalidation; 5]>;
2160
2161#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2163pub struct ModifierInvalidation {
2164 kind: InvalidationKind,
2165 capabilities: NodeCapabilities,
2166}
2167
2168impl ModifierInvalidation {
2169 pub const fn new(kind: InvalidationKind, capabilities: NodeCapabilities) -> Self {
2171 Self { kind, capabilities }
2172 }
2173
2174 pub const fn kind(self) -> InvalidationKind {
2176 self.kind
2177 }
2178
2179 pub const fn capabilities(self) -> NodeCapabilities {
2181 self.capabilities
2182 }
2183}
2184
2185pub trait AnyModifierElement: fmt::Debug {
2187 fn node_type(&self) -> TypeId;
2189
2190 fn element_type(&self) -> TypeId;
2192
2193 fn create_node(&self) -> Rc<RefCell<dyn ModifierNode>>;
2195
2196 fn can_update_node(&self, node: &dyn ModifierNode) -> bool;
2198
2199 fn update_node(&self, node: &mut dyn ModifierNode);
2201
2202 fn key(&self) -> Option<u64>;
2204
2205 fn capabilities(&self) -> NodeCapabilities {
2207 NodeCapabilities::default()
2208 }
2209
2210 fn hash_code(&self) -> u64;
2212
2213 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool;
2215
2216 fn inspector_name(&self) -> &'static str;
2218
2219 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String));
2221
2222 fn requires_update(&self) -> bool;
2224
2225 fn auto_invalidates_on_update(&self) -> bool;
2228
2229 fn update_invalidation_kind(&self) -> Option<InvalidationKind>;
2231
2232 fn provides_composition_locals(&self) -> bool {
2234 false
2235 }
2236
2237 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2239 Vec::new()
2240 }
2241
2242 fn as_any(&self) -> &dyn Any;
2244}
2245
2246struct TypedModifierElement<E: ModifierNodeElement> {
2247 element: E,
2248 cached_hash: u64,
2249 provides_locals: bool,
2250}
2251
2252impl<E: ModifierNodeElement> TypedModifierElement<E> {
2253 fn new(element: E) -> Self {
2254 let mut hasher = default::new();
2255 element.hash(&mut hasher);
2256 let provides_locals = !element.provided_composition_locals().is_empty();
2257 Self {
2258 element,
2259 cached_hash: hasher.finish(),
2260 provides_locals,
2261 }
2262 }
2263}
2264
2265impl<E> fmt::Debug for TypedModifierElement<E>
2266where
2267 E: ModifierNodeElement,
2268{
2269 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2270 f.debug_struct("TypedModifierElement")
2271 .field("type", &type_name::<E>())
2272 .finish()
2273 }
2274}
2275
2276impl<E> AnyModifierElement for TypedModifierElement<E>
2277where
2278 E: ModifierNodeElement,
2279{
2280 fn node_type(&self) -> TypeId {
2281 TypeId::of::<E::Node>()
2282 }
2283
2284 fn element_type(&self) -> TypeId {
2285 TypeId::of::<E>()
2286 }
2287
2288 fn create_node(&self) -> Rc<RefCell<dyn ModifierNode>> {
2289 Rc::new(RefCell::new(self.element.create()))
2290 }
2291
2292 fn can_update_node(&self, node: &dyn ModifierNode) -> bool {
2293 node.as_any().is::<E::Node>()
2294 }
2295
2296 fn update_node(&self, node: &mut dyn ModifierNode) {
2297 if let Some(typed) = node.as_any_mut().downcast_mut::<E::Node>() {
2298 self.element.update(typed);
2299 }
2300 }
2301
2302 fn key(&self) -> Option<u64> {
2303 self.element.key()
2304 }
2305
2306 fn capabilities(&self) -> NodeCapabilities {
2307 self.element.capabilities()
2308 }
2309
2310 fn provides_composition_locals(&self) -> bool {
2311 self.provides_locals
2312 }
2313
2314 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2315 self.element.provided_composition_locals()
2316 }
2317
2318 fn hash_code(&self) -> u64 {
2319 self.cached_hash
2320 }
2321
2322 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool {
2323 other
2324 .as_any()
2325 .downcast_ref::<Self>()
2326 .is_some_and(|typed| typed.element == self.element)
2327 }
2328
2329 fn inspector_name(&self) -> &'static str {
2330 self.element.inspector_name()
2331 }
2332
2333 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String)) {
2334 self.element.inspector_properties(visitor);
2335 }
2336
2337 fn requires_update(&self) -> bool {
2338 self.element.always_update()
2339 }
2340
2341 fn auto_invalidates_on_update(&self) -> bool {
2342 self.element.auto_invalidate_on_update()
2343 }
2344
2345 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
2346 self.element.update_invalidation_kind()
2347 }
2348
2349 fn as_any(&self) -> &dyn Any {
2350 self
2351 }
2352}
2353
2354fn request_update_auto_invalidations(
2355 element: &dyn AnyModifierElement,
2356 context: &mut dyn ModifierNodeContext,
2357 capabilities: NodeCapabilities,
2358) {
2359 if let Some(kind) = element.update_invalidation_kind() {
2360 let capabilities = NodeCapabilities::for_invalidation(kind);
2361 context.push_active_capabilities(capabilities);
2362 context.invalidate(kind);
2363 context.pop_active_capabilities();
2364 } else if element.auto_invalidates_on_update() {
2365 request_auto_invalidations(context, capabilities);
2366 }
2367}
2368
2369pub fn modifier_element<E: ModifierNodeElement>(element: E) -> DynModifierElement {
2372 Rc::new(TypedModifierElement::new(element))
2373}
2374
2375pub type DynModifierElement = Rc<dyn AnyModifierElement>;
2377
2378#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2379enum TraversalDirection {
2380 Forward,
2381 Backward,
2382}
2383
2384pub struct ModifierChainIter<'a> {
2389 chain: &'a ModifierNodeChain,
2390 cursor: usize,
2391 remaining: usize,
2392 direction: TraversalDirection,
2393}
2394
2395impl<'a> ModifierChainIter<'a> {
2396 fn forward(chain: &'a ModifierNodeChain) -> Self {
2397 Self {
2398 chain,
2399 cursor: 0,
2400 remaining: chain.ordered_nodes.len(),
2401 direction: TraversalDirection::Forward,
2402 }
2403 }
2404
2405 fn backward(chain: &'a ModifierNodeChain) -> Self {
2406 let len = chain.ordered_nodes.len();
2407 Self {
2408 chain,
2409 cursor: len.wrapping_sub(1),
2410 remaining: len,
2411 direction: TraversalDirection::Backward,
2412 }
2413 }
2414}
2415
2416impl<'a> Iterator for ModifierChainIter<'a> {
2417 type Item = ModifierChainNodeRef<'a>;
2418
2419 #[inline]
2420 fn next(&mut self) -> Option<Self::Item> {
2421 if self.remaining == 0 {
2422 return None;
2423 }
2424 let (link, caps, agg) = self.chain.ordered_nodes[self.cursor];
2425 let node_ref = self.chain.make_node_ref_with_caps(link, caps, agg);
2426 self.remaining -= 1;
2427 match self.direction {
2428 TraversalDirection::Forward => self.cursor += 1,
2429 TraversalDirection::Backward => self.cursor = self.cursor.wrapping_sub(1),
2430 }
2431 Some(node_ref)
2432 }
2433
2434 #[inline]
2435 fn size_hint(&self) -> (usize, Option<usize>) {
2436 (self.remaining, Some(self.remaining))
2437 }
2438}
2439
2440impl ExactSizeIterator for ModifierChainIter<'_> {}
2441impl std::iter::FusedIterator for ModifierChainIter<'_> {}
2442
2443#[derive(Debug)]
2444struct ModifierNodeEntry {
2445 key: Option<u64>,
2446 hash_code: u64,
2447 element: DynModifierElement,
2448 node: Rc<RefCell<dyn ModifierNode>>,
2449 capabilities: NodeCapabilities,
2450}
2451
2452impl ModifierNodeEntry {
2453 fn new(
2454 key: Option<u64>,
2455 element: DynModifierElement,
2456 node: Rc<RefCell<dyn ModifierNode>>,
2457 hash_code: u64,
2458 capabilities: NodeCapabilities,
2459 ) -> Self {
2460 let entry = Self {
2461 key,
2462 hash_code,
2463 element,
2464 node,
2465 capabilities,
2466 };
2467 entry
2468 .node
2469 .borrow()
2470 .node_state()
2471 .set_capabilities(entry.capabilities);
2472 entry
2473 }
2474}
2475
2476fn visit_node_tree_mut(
2477 node: &mut dyn ModifierNode,
2478 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
2479) {
2480 visitor(node);
2481 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
2482}
2483
2484fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
2485 let mut current = 0usize;
2486 let mut result: Option<&dyn ModifierNode> = None;
2487 node.for_each_delegate(&mut |child| {
2488 if result.is_none() && current == target {
2489 result = Some(child);
2490 }
2491 current += 1;
2492 });
2493 result
2494}
2495
2496fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
2497 let mut current = 0usize;
2498 let mut result: Option<&mut dyn ModifierNode> = None;
2499 node.for_each_delegate_mut(&mut |child| {
2500 if result.is_none() && current == target {
2501 result = Some(child);
2502 }
2503 current += 1;
2504 });
2505 result
2506}
2507
2508fn with_node_context<F, R>(
2509 node: &mut dyn ModifierNode,
2510 context: &mut dyn ModifierNodeContext,
2511 f: F,
2512) -> R
2513where
2514 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
2515{
2516 context.push_active_capabilities(node.node_state().capabilities());
2517 let result = f(node, context);
2518 context.pop_active_capabilities();
2519 result
2520}
2521
2522fn request_auto_invalidations(
2523 context: &mut dyn ModifierNodeContext,
2524 capabilities: NodeCapabilities,
2525) {
2526 if capabilities.is_empty() {
2527 return;
2528 }
2529
2530 context.push_active_capabilities(capabilities);
2531
2532 if capabilities.contains(NodeCapabilities::LAYOUT) {
2533 context.invalidate(InvalidationKind::Layout);
2534 }
2535 if capabilities.contains(NodeCapabilities::DRAW) {
2536 context.invalidate(InvalidationKind::Draw);
2537 }
2538 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
2539 context.invalidate(InvalidationKind::PointerInput);
2540 }
2541 if capabilities.contains(NodeCapabilities::SEMANTICS) {
2542 context.invalidate(InvalidationKind::Semantics);
2543 }
2544 if capabilities.contains(NodeCapabilities::FOCUS) {
2545 context.invalidate(InvalidationKind::Focus);
2546 }
2547
2548 context.pop_active_capabilities();
2549}
2550
2551fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
2552 visit_node_tree_mut(node, &mut |n| {
2553 if !n.node_state().is_attached() {
2554 n.node_state().set_attached(true);
2555 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
2556 }
2557 });
2558}
2559
2560fn reset_node_tree(node: &mut dyn ModifierNode) {
2561 visit_node_tree_mut(node, &mut |n| n.on_reset());
2562}
2563
2564fn detach_node_tree(node: &mut dyn ModifierNode) {
2565 visit_node_tree_mut(node, &mut |n| {
2566 if n.node_state().is_attached() {
2567 n.on_detach();
2568 n.node_state().set_attached(false);
2569 }
2570 n.node_state().set_parent_link(None);
2571 n.node_state().set_child_link(None);
2572 n.node_state()
2573 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2574 });
2575}
2576
2577pub struct ModifierNodeChain {
2584 entries: Vec<ModifierNodeEntry>,
2585 aggregated_capabilities: NodeCapabilities,
2586 head_aggregate_child_capabilities: NodeCapabilities,
2587 head_sentinel: SentinelNode,
2588 tail_sentinel: SentinelNode,
2589 ordered_nodes: Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
2590 attached: bool,
2594 links_cleared: bool,
2597}
2598
2599#[derive(Default)]
2603struct ReconcileScratch {
2604 old_used: Vec<bool>,
2605 match_order: Vec<Option<usize>>,
2606 final_slots: Vec<Option<ModifierNodeEntry>>,
2607 elements: Vec<DynModifierElement>,
2608}
2609
2610thread_local! {
2611 static RECONCILE_SCRATCH: std::cell::RefCell<ReconcileScratch> =
2612 std::cell::RefCell::default();
2613}
2614
2615struct SentinelNode {
2616 state: NodeState,
2617}
2618
2619impl SentinelNode {
2620 fn new() -> Self {
2621 Self {
2622 state: NodeState::sentinel(),
2623 }
2624 }
2625}
2626
2627impl DelegatableNode for SentinelNode {
2628 fn node_state(&self) -> &NodeState {
2629 &self.state
2630 }
2631}
2632
2633impl ModifierNode for SentinelNode {}
2634
2635#[derive(Clone)]
2639pub struct ModifierChainNodeRef<'a> {
2640 chain: &'a ModifierNodeChain,
2641 link: NodeLink,
2642 cached_capabilities: Option<NodeCapabilities>,
2643 cached_aggregate_child: Option<NodeCapabilities>,
2644}
2645
2646impl Default for ModifierNodeChain {
2647 fn default() -> Self {
2648 Self::new()
2649 }
2650}
2651
2652struct EntryIndex {
2653 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2654 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2655 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
2656}
2657
2658struct EntryMatchQuery<'a> {
2659 element_type: TypeId,
2660 node_type: TypeId,
2661 key: Option<u64>,
2662 hash_code: u64,
2663 element: &'a DynModifierElement,
2664}
2665
2666impl EntryIndex {
2667 fn build(entries: &[ModifierNodeEntry]) -> Self {
2668 let mut keyed = HashMap::default();
2669 let mut hashed = HashMap::default();
2670 let mut typed = HashMap::default();
2671
2672 for (i, entry) in entries.iter().enumerate() {
2673 let (element_type, node_type) =
2674 (entry.element.element_type(), entry.element.node_type());
2675 if let Some(key_value) = entry.key {
2676 keyed
2677 .entry((element_type, node_type, key_value))
2678 .or_insert_with(Vec::new)
2679 .push(i);
2680 } else {
2681 hashed
2682 .entry((element_type, node_type, entry.hash_code))
2683 .or_insert_with(Vec::new)
2684 .push(i);
2685 typed
2686 .entry((element_type, node_type))
2687 .or_insert_with(Vec::new)
2688 .push(i);
2689 }
2690 }
2691
2692 Self {
2693 keyed,
2694 hashed,
2695 typed,
2696 }
2697 }
2698
2699 fn find_match(
2700 &self,
2701 entries: &[ModifierNodeEntry],
2702 used: &[bool],
2703 query: EntryMatchQuery<'_>,
2704 ) -> Option<usize> {
2705 if let Some(key_value) = query.key {
2706 if let Some(candidates) =
2707 self.keyed
2708 .get(&(query.element_type, query.node_type, key_value))
2709 {
2710 for &i in candidates {
2711 if !used[i] {
2712 return Some(i);
2713 }
2714 }
2715 }
2716 } else {
2717 if let Some(candidates) =
2718 self.hashed
2719 .get(&(query.element_type, query.node_type, query.hash_code))
2720 {
2721 for &i in candidates {
2722 if !used[i]
2723 && entries[i]
2724 .element
2725 .as_ref()
2726 .equals_element(query.element.as_ref())
2727 {
2728 return Some(i);
2729 }
2730 }
2731 }
2732
2733 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
2734 for &i in candidates {
2735 if !used[i] {
2736 return Some(i);
2737 }
2738 }
2739 }
2740 }
2741
2742 None
2743 }
2744}
2745
2746fn update_entry_in_place(
2751 entry: &mut ModifierNodeEntry,
2752 element: &DynModifierElement,
2753 context: &mut dyn ModifierNodeContext,
2754) -> bool {
2755 if entry.element.element_type() != element.element_type()
2756 || entry.element.node_type() != element.node_type()
2757 || entry.key != element.key()
2758 || !element.can_update_node(&*entry.node.borrow())
2759 {
2760 return false;
2761 }
2762 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2763 let capabilities = element.capabilities();
2764 if !same_element || element.requires_update() {
2765 element.update_node(&mut *entry.node.borrow_mut());
2766 entry.element = element.clone();
2767 entry.hash_code = element.hash_code();
2768 request_update_auto_invalidations(element.as_ref(), context, capabilities);
2769 }
2770 entry.capabilities = capabilities;
2771 entry
2772 .node
2773 .borrow()
2774 .node_state()
2775 .set_capabilities(capabilities);
2776 true
2777}
2778
2779fn fresh_entry(
2782 element: DynModifierElement,
2783 context: &mut dyn ModifierNodeContext,
2784 attach: bool,
2785) -> ModifierNodeEntry {
2786 let capabilities = element.capabilities();
2787 let entry = ModifierNodeEntry::new(
2788 element.key(),
2789 element.clone(),
2790 element.create_node(),
2791 element.hash_code(),
2792 capabilities,
2793 );
2794 if attach {
2795 attach_node_tree(&mut *entry.node.borrow_mut(), context);
2796 }
2797 element.update_node(&mut *entry.node.borrow_mut());
2798 request_auto_invalidations(context, capabilities);
2799 entry
2800}
2801
2802fn reconcile_element(
2807 element: DynModifierElement,
2808 new_pos: usize,
2809 (old_entries, index): (&mut [ModifierNodeEntry], &EntryIndex),
2810 (used, match_order): (&mut [bool], &mut [Option<usize>]),
2811 context: &mut dyn ModifierNodeContext,
2812 attach: bool,
2813) -> Option<ModifierNodeEntry> {
2814 let element_type = element.element_type();
2815 let node_type = element.node_type();
2816 let key = element.key();
2817 let hash_code = element.hash_code();
2818 let capabilities = element.capabilities();
2819 let Some(idx) = index.find_match(
2820 old_entries,
2821 used,
2822 EntryMatchQuery {
2823 element_type,
2824 node_type,
2825 key,
2826 hash_code,
2827 element: &element,
2828 },
2829 ) else {
2830 return Some(fresh_entry(element, context, attach));
2831 };
2832 let entry = &mut old_entries[idx];
2833 if !element.can_update_node(&*entry.node.borrow()) {
2834 return Some(fresh_entry(element, context, attach));
2835 }
2836
2837 used[idx] = true;
2838 match_order[idx] = Some(new_pos);
2839 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2840 if !same_element || element.requires_update() {
2841 element.update_node(&mut *entry.node.borrow_mut());
2842 entry.element = element;
2843 entry.hash_code = hash_code;
2844 request_update_auto_invalidations(entry.element.as_ref(), context, capabilities);
2845 }
2846 if idx != new_pos {
2847 request_auto_invalidations(context, capabilities);
2848 }
2849 entry.key = key;
2850 entry.capabilities = capabilities;
2851 entry
2852 .node
2853 .borrow()
2854 .node_state()
2855 .set_capabilities(capabilities);
2856 None
2857}
2858
2859impl ModifierNodeChain {
2860 pub fn new() -> Self {
2862 let mut chain = Self::detached();
2863 chain.attached = true;
2864 chain
2865 }
2866
2867 pub fn detached() -> Self {
2870 let mut chain = Self {
2871 entries: Vec::new(),
2872 aggregated_capabilities: NodeCapabilities::empty(),
2873 head_aggregate_child_capabilities: NodeCapabilities::empty(),
2874 head_sentinel: SentinelNode::new(),
2875 tail_sentinel: SentinelNode::new(),
2876 ordered_nodes: Vec::new(),
2877 attached: false,
2878 links_cleared: false,
2879 };
2880 chain.sync_chain_links();
2881 chain
2882 }
2883
2884 pub fn detach_nodes(&mut self) {
2886 if !self.attached {
2887 return;
2888 }
2889 self.attached = false;
2890 for entry in &self.entries {
2891 detach_node_tree(&mut *entry.node.borrow_mut());
2892 }
2893 self.links_cleared = !self.entries.is_empty();
2894 }
2895
2896 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
2898 if self.attached {
2899 return;
2900 }
2901 self.attached = true;
2902 for entry in &self.entries {
2903 attach_node_tree(&mut *entry.node.borrow_mut(), context);
2904 }
2905 }
2906
2907 pub fn repair_chain(&mut self) {
2910 if self.links_cleared {
2911 self.sync_chain_links();
2912 }
2913 }
2914
2915 pub fn update_from_slice(
2921 &mut self,
2922 elements: &[DynModifierElement],
2923 context: &mut dyn ModifierNodeContext,
2924 ) {
2925 self.update_from_ref_iter(elements.iter(), context);
2926 }
2927
2928 pub fn update_entries_of_type<'a, I>(
2934 &mut self,
2935 elements: I,
2936 element_count: usize,
2937 element_type: TypeId,
2938 context: &mut dyn ModifierNodeContext,
2939 ) -> bool
2940 where
2941 I: Iterator<Item = &'a DynModifierElement>,
2942 {
2943 if element_count != self.entries.len() {
2944 return false;
2945 }
2946 self.entries
2947 .iter_mut()
2948 .zip(elements)
2949 .filter(|(_, element)| element.element_type() == element_type)
2950 .all(|(entry, element)| update_entry_in_place(entry, element, context))
2951 }
2952
2953 pub fn update_from_ref_iter<'a, I>(
2956 &mut self,
2957 elements: I,
2958 context: &mut dyn ModifierNodeContext,
2959 ) where
2960 I: Iterator<Item = &'a DynModifierElement>,
2961 {
2962 let mut scratch = RECONCILE_SCRATCH
2965 .try_with(|scratch| std::mem::take(&mut *scratch.borrow_mut()))
2966 .unwrap_or_default();
2967 self.reconcile(elements, context, &mut scratch);
2968 scratch.elements.clear();
2969 scratch.final_slots.clear();
2970 let _ = RECONCILE_SCRATCH.try_with(|slot| *slot.borrow_mut() = scratch);
2971 }
2972
2973 fn reconcile<'a, I>(
2974 &mut self,
2975 elements: I,
2976 context: &mut dyn ModifierNodeContext,
2977 scratch: &mut ReconcileScratch,
2978 ) where
2979 I: Iterator<Item = &'a DynModifierElement>,
2980 {
2981 let old_len = self.entries.len();
2982 let mut fast_path_failed_at: Option<usize> = None;
2983 let mut elements_count = 0;
2984
2985 scratch.elements.clear();
2986
2987 for (idx, element) in elements.enumerate() {
2988 elements_count = idx + 1;
2989 if fast_path_failed_at.is_none() && idx < old_len {
2990 if update_entry_in_place(&mut self.entries[idx], element, context) {
2991 continue;
2992 }
2993 fast_path_failed_at = Some(idx);
2994 }
2995 scratch.elements.push(element.clone());
2996 }
2997
2998 if fast_path_failed_at.is_none() && scratch.elements.is_empty() {
2999 if elements_count < self.entries.len() {
3000 for entry in self.entries.drain(elements_count..) {
3001 request_auto_invalidations(context, entry.capabilities);
3002 detach_node_tree(&mut *entry.node.borrow_mut());
3003 }
3004 }
3005 self.sync_chain_links();
3006 return;
3007 }
3008
3009 self.rebuild_tail(fast_path_failed_at.unwrap_or(old_len), context, scratch);
3010 }
3011
3012 fn rebuild_tail(
3016 &mut self,
3017 fail_idx: usize,
3018 context: &mut dyn ModifierNodeContext,
3019 scratch: &mut ReconcileScratch,
3020 ) {
3021 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
3022 let processed_entries_len = self.entries.len();
3023 let old_len = old_entries.len();
3024
3025 scratch.old_used.clear();
3026 scratch.old_used.resize(old_len, false);
3027
3028 scratch.match_order.clear();
3029 scratch.match_order.resize(old_len, None);
3030
3031 let index = EntryIndex::build(&old_entries);
3032
3033 let new_elements_count = scratch.elements.len();
3034 scratch.final_slots.clear();
3035 scratch.final_slots.reserve(new_elements_count);
3036
3037 for (new_pos, element) in scratch.elements.drain(..).enumerate() {
3038 let fresh = reconcile_element(
3039 element,
3040 new_pos,
3041 (&mut old_entries, &index),
3042 (&mut scratch.old_used, &mut scratch.match_order),
3043 context,
3044 self.attached,
3045 );
3046 scratch.final_slots.push(fresh);
3047 }
3048
3049 for (i, entry) in old_entries.into_iter().enumerate() {
3050 match scratch.match_order[i] {
3051 Some(pos) if scratch.old_used[i] => scratch.final_slots[pos] = Some(entry),
3052 _ => {
3053 request_auto_invalidations(context, entry.capabilities);
3054 detach_node_tree(&mut *entry.node.borrow_mut());
3055 }
3056 }
3057 }
3058
3059 self.entries.reserve_exact(scratch.final_slots.len());
3063 for slot in scratch.final_slots.drain(..) {
3064 if let Some(entry) = slot {
3065 self.entries.push(entry);
3066 } else {
3067 log::error!("modifier reconciliation produced an empty final slot");
3068 }
3069 }
3070
3071 debug_assert_eq!(
3072 self.entries.len(),
3073 processed_entries_len + new_elements_count
3074 );
3075 self.sync_chain_links();
3076 }
3077
3078 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
3082 where
3083 I: IntoIterator<Item = DynModifierElement>,
3084 {
3085 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
3086 self.update_from_slice(&collected, context);
3087 }
3088
3089 pub fn reset(&mut self) {
3092 for entry in &mut self.entries {
3093 reset_node_tree(&mut *entry.node.borrow_mut());
3094 }
3095 }
3096
3097 pub fn detach_all(&mut self) {
3099 for entry in std::mem::take(&mut self.entries) {
3100 detach_node_tree(&mut *entry.node.borrow_mut());
3101 {
3102 let node_borrow = entry.node.borrow();
3103 let state = node_borrow.node_state();
3104 state.set_capabilities(NodeCapabilities::empty());
3105 }
3106 }
3107 self.aggregated_capabilities = NodeCapabilities::empty();
3108 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
3109 self.ordered_nodes.clear();
3110 self.sync_chain_links();
3111 }
3112
3113 pub fn len(&self) -> usize {
3115 self.entries.len()
3116 }
3117
3118 pub fn is_empty(&self) -> bool {
3120 self.entries.is_empty()
3121 }
3122
3123 pub fn capabilities(&self) -> NodeCapabilities {
3125 self.aggregated_capabilities
3126 }
3127
3128 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
3130 self.aggregated_capabilities.contains(capability)
3131 }
3132
3133 pub fn head(&self) -> ModifierChainNodeRef<'_> {
3135 self.make_node_ref(NodeLink::Head)
3136 }
3137
3138 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
3140 self.make_node_ref(NodeLink::Tail)
3141 }
3142
3143 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
3145 ModifierChainIter::forward(self)
3146 }
3147
3148 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
3150 ModifierChainIter::backward(self)
3151 }
3152
3153 pub fn for_each_forward<F>(&self, mut f: F)
3155 where
3156 F: FnMut(ModifierChainNodeRef<'_>),
3157 {
3158 for node in self.head_to_tail() {
3159 f(node);
3160 }
3161 }
3162
3163 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
3165 where
3166 F: FnMut(ModifierChainNodeRef<'_>),
3167 {
3168 if mask.is_empty() {
3169 self.for_each_forward(f);
3170 return;
3171 }
3172
3173 if !self.head().aggregate_child_capabilities().intersects(mask) {
3174 return;
3175 }
3176
3177 for node in self.head_to_tail() {
3178 if node.kind_set().intersects(mask) {
3179 f(node);
3180 }
3181 }
3182 }
3183
3184 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
3186 where
3187 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
3188 {
3189 self.for_each_forward_matching(mask, |node_ref| {
3190 node_ref.with_node(|node| f(node_ref.clone(), node));
3191 });
3192 }
3193
3194 pub fn for_each_backward<F>(&self, mut f: F)
3196 where
3197 F: FnMut(ModifierChainNodeRef<'_>),
3198 {
3199 for node in self.tail_to_head() {
3200 f(node);
3201 }
3202 }
3203
3204 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
3206 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
3207 node as *const dyn ModifierNode as *const ()
3208 }
3209
3210 let target = node_data_ptr(node);
3211 for (index, entry) in self.entries.iter().enumerate() {
3212 if node_data_ptr(&*entry.node.borrow()) == target {
3213 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
3214 }
3215 }
3216
3217 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
3218 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
3219 return None;
3220 }
3221 let matches_target = match link {
3222 NodeLink::Head => node_data_ptr(&self.head_sentinel) == target,
3223 NodeLink::Tail => node_data_ptr(&self.tail_sentinel) == target,
3224 NodeLink::Entry(path) => {
3225 let node_borrow = self.entries[path.entry()].node.borrow();
3226 node_data_ptr(&*node_borrow) == target
3227 }
3228 };
3229 if matches_target {
3230 Some(self.make_node_ref(*link))
3231 } else {
3232 None
3233 }
3234 })
3235 }
3236
3237 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
3240 self.entries.get(index).and_then(|entry| {
3241 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
3242 boxed_node.as_any().downcast_ref::<N>()
3243 })
3244 .ok()
3245 })
3246 }
3247
3248 pub fn node_mut<N: ModifierNode + 'static>(
3251 &self,
3252 index: usize,
3253 ) -> Option<std::cell::RefMut<'_, N>> {
3254 self.entries.get(index).and_then(|entry| {
3255 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
3256 boxed_node.as_any_mut().downcast_mut::<N>()
3257 })
3258 .ok()
3259 })
3260 }
3261
3262 pub fn get_node_rc(&self, index: usize) -> Option<&Rc<RefCell<dyn ModifierNode>>> {
3265 self.entries.get(index).map(|entry| &entry.node)
3266 }
3267
3268 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
3270 self.aggregated_capabilities
3271 .contains(NodeCapabilities::for_invalidation(kind))
3272 }
3273
3274 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
3276 where
3277 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
3278 {
3279 for index in 0..self.ordered_nodes.len() {
3280 let (link, cached_caps, _agg) = self.ordered_nodes[index];
3281 match link {
3282 NodeLink::Head => {
3283 f(&mut self.head_sentinel, cached_caps);
3284 }
3285 NodeLink::Tail => {
3286 f(&mut self.tail_sentinel, cached_caps);
3287 }
3288 NodeLink::Entry(path) => {
3289 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
3290 if path.delegates().is_empty() {
3291 f(&mut *node_borrow, cached_caps);
3292 } else {
3293 let mut current: &mut dyn ModifierNode = &mut *node_borrow;
3294 for &delegate_index in path.delegates() {
3295 if let Some(delegate) =
3296 nth_delegate_mut(current, delegate_index as usize)
3297 {
3298 current = delegate;
3299 } else {
3300 return;
3301 }
3302 }
3303 f(current, cached_caps);
3304 }
3305 }
3306 }
3307 }
3308 }
3309
3310 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
3311 ModifierChainNodeRef {
3312 chain: self,
3313 link,
3314 cached_capabilities: None,
3315 cached_aggregate_child: None,
3316 }
3317 }
3318
3319 fn make_node_ref_with_caps(
3320 &self,
3321 link: NodeLink,
3322 caps: NodeCapabilities,
3323 aggregate_child: NodeCapabilities,
3324 ) -> ModifierChainNodeRef<'_> {
3325 ModifierChainNodeRef {
3326 chain: self,
3327 link,
3328 cached_capabilities: Some(caps),
3329 cached_aggregate_child: Some(aggregate_child),
3330 }
3331 }
3332
3333 fn sync_chain_links(&mut self) {
3334 self.links_cleared = false;
3335 self.rebuild_ordered_nodes();
3336
3337 self.head_sentinel.node_state().set_parent_link(None);
3338 self.tail_sentinel.node_state().set_child_link(None);
3339
3340 if self.ordered_nodes.is_empty() {
3341 self.head_sentinel
3342 .node_state()
3343 .set_child_link(Some(NodeLink::Tail));
3344 self.tail_sentinel
3345 .node_state()
3346 .set_parent_link(Some(NodeLink::Head));
3347 self.aggregated_capabilities = NodeCapabilities::empty();
3348 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
3349 self.head_sentinel
3350 .node_state()
3351 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3352 self.tail_sentinel
3353 .node_state()
3354 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3355 return;
3356 }
3357
3358 let mut previous = NodeLink::Head;
3359 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
3360 match &previous {
3361 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
3362 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
3363 NodeLink::Entry(path) => {
3364 let node_borrow = self.entries[path.entry()].node.borrow();
3365 if path.delegates().is_empty() {
3366 node_borrow.node_state().set_child_link(Some(link));
3367 } else {
3368 let mut current: &dyn ModifierNode = &*node_borrow;
3369 for &delegate_index in path.delegates() {
3370 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3371 current = delegate;
3372 }
3373 }
3374 current.node_state().set_child_link(Some(link));
3375 }
3376 }
3377 }
3378 match &link {
3379 NodeLink::Head => self
3380 .head_sentinel
3381 .node_state()
3382 .set_parent_link(Some(previous)),
3383 NodeLink::Tail => self
3384 .tail_sentinel
3385 .node_state()
3386 .set_parent_link(Some(previous)),
3387 NodeLink::Entry(path) => {
3388 let node_borrow = self.entries[path.entry()].node.borrow();
3389 if path.delegates().is_empty() {
3390 node_borrow.node_state().set_parent_link(Some(previous));
3391 } else {
3392 let mut current: &dyn ModifierNode = &*node_borrow;
3393 for &delegate_index in path.delegates() {
3394 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3395 current = delegate;
3396 }
3397 }
3398 current.node_state().set_parent_link(Some(previous));
3399 }
3400 }
3401 }
3402 previous = link;
3403 }
3404
3405 match &previous {
3406 NodeLink::Head => self
3407 .head_sentinel
3408 .node_state()
3409 .set_child_link(Some(NodeLink::Tail)),
3410 NodeLink::Tail => self
3411 .tail_sentinel
3412 .node_state()
3413 .set_child_link(Some(NodeLink::Tail)),
3414 NodeLink::Entry(path) => {
3415 let node_borrow = self.entries[path.entry()].node.borrow();
3416 if path.delegates().is_empty() {
3417 node_borrow
3418 .node_state()
3419 .set_child_link(Some(NodeLink::Tail));
3420 } else {
3421 let mut current: &dyn ModifierNode = &*node_borrow;
3422 for &delegate_index in path.delegates() {
3423 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3424 current = delegate;
3425 }
3426 }
3427 current.node_state().set_child_link(Some(NodeLink::Tail));
3428 }
3429 }
3430 }
3431 self.tail_sentinel
3432 .node_state()
3433 .set_parent_link(Some(previous));
3434 self.tail_sentinel.node_state().set_child_link(None);
3435
3436 let mut aggregate = NodeCapabilities::empty();
3437 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
3438 aggregate |= *cached_caps;
3439 *cached_aggregate = aggregate;
3440 match link {
3441 NodeLink::Head => {
3442 self.head_sentinel
3443 .node_state()
3444 .set_aggregate_child_capabilities(aggregate);
3445 }
3446 NodeLink::Tail => {
3447 self.tail_sentinel
3448 .node_state()
3449 .set_aggregate_child_capabilities(aggregate);
3450 }
3451 NodeLink::Entry(path) => {
3452 let node_borrow = self.entries[path.entry()].node.borrow();
3453 let state = if path.delegates().is_empty() {
3454 node_borrow.node_state()
3455 } else {
3456 let mut current: &dyn ModifierNode = &*node_borrow;
3457 for &delegate_index in path.delegates() {
3458 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3459 current = delegate;
3460 }
3461 }
3462 current.node_state()
3463 };
3464 state.set_aggregate_child_capabilities(aggregate);
3465 }
3466 }
3467 }
3468
3469 self.aggregated_capabilities = aggregate;
3470 self.head_aggregate_child_capabilities = aggregate;
3471 self.head_sentinel
3472 .node_state()
3473 .set_aggregate_child_capabilities(aggregate);
3474 self.tail_sentinel
3475 .node_state()
3476 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3477 }
3478
3479 fn rebuild_ordered_nodes(&mut self) {
3480 self.ordered_nodes.clear();
3481 self.ordered_nodes.reserve_exact(self.entries.len());
3483 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
3484 for (index, entry) in self.entries.iter().enumerate() {
3485 let node_borrow = entry.node.borrow();
3486 Self::enumerate_link_order(
3487 &*node_borrow,
3488 index,
3489 &mut path_buf,
3490 0,
3491 &mut self.ordered_nodes,
3492 );
3493 }
3494 }
3495
3496 fn enumerate_link_order(
3497 node: &dyn ModifierNode,
3498 entry: usize,
3499 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
3500 path_len: usize,
3501 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
3502 ) {
3503 let caps = node.node_state().capabilities();
3504 out.push((
3505 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
3506 caps,
3507 NodeCapabilities::empty(),
3508 ));
3509 let mut delegate_index = 0usize;
3510 node.for_each_delegate(&mut |child| {
3511 if path_len < MAX_DELEGATE_DEPTH {
3512 path_buf[path_len] = delegate_index;
3513 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
3514 }
3515 delegate_index += 1;
3516 });
3517 }
3518}
3519
3520impl<'a> ModifierChainNodeRef<'a> {
3521 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
3522 match &self.link {
3523 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
3524 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
3525 NodeLink::Entry(path) => {
3526 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3527 if path.delegates().is_empty() {
3528 f(node_borrow.node_state())
3529 } else {
3530 let mut current: &dyn ModifierNode = &*node_borrow;
3531 for &delegate_index in path.delegates() {
3532 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3533 current = delegate;
3534 } else {
3535 return f(node_borrow.node_state());
3536 }
3537 }
3538 f(current.node_state())
3539 }
3540 }
3541 }
3542 }
3543
3544 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
3547 match &self.link {
3548 NodeLink::Head => None,
3549 NodeLink::Tail => None,
3550 NodeLink::Entry(path) => {
3551 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3552 if path.delegates().is_empty() {
3553 Some(f(&*node_borrow))
3554 } else {
3555 let mut current: &dyn ModifierNode = &*node_borrow;
3556 for &delegate_index in path.delegates() {
3557 current = nth_delegate(current, delegate_index as usize)?;
3558 }
3559 Some(f(current))
3560 }
3561 }
3562 }
3563 }
3564
3565 #[inline]
3567 pub fn parent(&self) -> Option<Self> {
3568 self.with_state(NodeState::parent_link)
3569 .map(|link| self.chain.make_node_ref(link))
3570 }
3571
3572 #[inline]
3574 pub fn child(&self) -> Option<Self> {
3575 self.with_state(NodeState::child_link)
3576 .map(|link| self.chain.make_node_ref(link))
3577 }
3578
3579 #[inline]
3581 pub fn kind_set(&self) -> NodeCapabilities {
3582 if let Some(caps) = self.cached_capabilities {
3583 return caps;
3584 }
3585 match &self.link {
3586 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
3587 NodeLink::Entry(_) => self.with_state(NodeState::capabilities),
3588 }
3589 }
3590
3591 pub fn entry_index(&self) -> Option<usize> {
3593 match &self.link {
3594 NodeLink::Entry(path) => Some(path.entry()),
3595 _ => None,
3596 }
3597 }
3598
3599 pub fn delegate_depth(&self) -> usize {
3601 match &self.link {
3602 NodeLink::Entry(path) => path.delegates().len(),
3603 _ => 0,
3604 }
3605 }
3606
3607 #[inline]
3609 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
3610 if let Some(agg) = self.cached_aggregate_child {
3611 return agg;
3612 }
3613 if self.is_tail() {
3614 NodeCapabilities::empty()
3615 } else {
3616 self.with_state(NodeState::aggregate_child_capabilities)
3617 }
3618 }
3619
3620 pub fn is_head(&self) -> bool {
3622 matches!(self.link, NodeLink::Head)
3623 }
3624
3625 pub fn is_tail(&self) -> bool {
3627 matches!(self.link, NodeLink::Tail)
3628 }
3629
3630 pub fn is_sentinel(&self) -> bool {
3632 matches!(self.link, NodeLink::Head | NodeLink::Tail)
3633 }
3634
3635 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
3637 !mask.is_empty() && self.kind_set().intersects(mask)
3638 }
3639
3640 pub fn visit_descendants<F>(self, include_self: bool, mut f: F)
3642 where
3643 F: FnMut(ModifierChainNodeRef<'a>),
3644 {
3645 let mut current = if include_self {
3646 Some(self)
3647 } else {
3648 self.child()
3649 };
3650 while let Some(node) = current {
3651 if node.is_tail() {
3652 break;
3653 }
3654 if !node.is_sentinel() {
3655 f(node.clone());
3656 }
3657 current = node.child();
3658 }
3659 }
3660
3661 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3663 where
3664 F: FnMut(ModifierChainNodeRef<'a>),
3665 {
3666 if mask.is_empty() {
3667 self.visit_descendants(include_self, f);
3668 return;
3669 }
3670
3671 if !self.aggregate_child_capabilities().intersects(mask) {
3672 return;
3673 }
3674
3675 self.visit_descendants(include_self, |node| {
3676 if node.kind_set().intersects(mask) {
3677 f(node);
3678 }
3679 });
3680 }
3681
3682 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
3684 where
3685 F: FnMut(ModifierChainNodeRef<'a>),
3686 {
3687 let mut current = if include_self {
3688 Some(self)
3689 } else {
3690 self.parent()
3691 };
3692 while let Some(node) = current {
3693 if node.is_head() {
3694 break;
3695 }
3696 f(node.clone());
3697 current = node.parent();
3698 }
3699 }
3700
3701 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3703 where
3704 F: FnMut(ModifierChainNodeRef<'a>),
3705 {
3706 if mask.is_empty() {
3707 self.visit_ancestors(include_self, f);
3708 return;
3709 }
3710
3711 self.visit_ancestors(include_self, |node| {
3712 if node.kind_set().intersects(mask) {
3713 f(node);
3714 }
3715 });
3716 }
3717}
3718
3719#[cfg(test)]
3720#[path = "tests/modifier_tests.rs"]
3721mod tests;