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 for_node(
89 node_id: Option<cranpose_core::NodeId>,
90 invalidations: ModifierInvalidations,
91 ) -> Self {
92 Self {
93 invalidations,
94 node_id,
95 ..Self::default()
96 }
97 }
98
99 pub fn invalidations(&self) -> &[ModifierInvalidation] {
103 &self.invalidations
104 }
105
106 pub fn clear_invalidations(&mut self) {
108 self.invalidations.clear();
109 }
110
111 pub fn take_invalidations(&mut self) -> ModifierInvalidations {
113 std::mem::take(&mut self.invalidations)
114 }
115
116 pub fn update_requested(&self) -> bool {
119 self.update_requested
120 }
121
122 pub fn take_update_requested(&mut self) -> bool {
124 std::mem::take(&mut self.update_requested)
125 }
126
127 pub fn set_node_id(&mut self, id: Option<cranpose_core::NodeId>) {
129 self.node_id = id;
130 }
131
132 fn push_invalidation(&mut self, kind: InvalidationKind) {
133 let mut capabilities = self.current_capabilities();
134 capabilities.insert(NodeCapabilities::for_invalidation(kind));
135 if let Some(existing) = self
136 .invalidations
137 .iter_mut()
138 .find(|entry| entry.kind() == kind)
139 {
140 let updated = existing.capabilities() | capabilities;
141 *existing = ModifierInvalidation::new(kind, updated);
142 } else {
143 self.invalidations
144 .push(ModifierInvalidation::new(kind, capabilities));
145 }
146 }
147
148 fn current_capabilities(&self) -> NodeCapabilities {
149 self.active_capabilities
150 .last()
151 .copied()
152 .unwrap_or_else(NodeCapabilities::empty)
153 }
154}
155
156impl ModifierNodeContext for BasicModifierNodeContext {
157 fn invalidate(&mut self, kind: InvalidationKind) {
158 self.push_invalidation(kind);
159 }
160
161 fn request_update(&mut self) {
162 self.update_requested = true;
163 }
164
165 fn push_active_capabilities(&mut self, capabilities: NodeCapabilities) {
166 self.active_capabilities.push(capabilities);
167 }
168
169 fn pop_active_capabilities(&mut self) {
170 self.active_capabilities.pop();
171 }
172
173 fn node_id(&self) -> Option<cranpose_core::NodeId> {
174 self.node_id
175 }
176}
177
178const MAX_DELEGATE_DEPTH: usize = 3;
179
180#[derive(Copy, Clone, Debug, PartialEq, Eq)]
181pub(crate) struct NodePath {
182 entry: u32,
185 delegate_buf: [u8; MAX_DELEGATE_DEPTH],
186 delegate_len: u8,
187}
188
189impl NodePath {
190 #[inline]
191 fn root(entry: usize) -> Self {
192 debug_assert!(entry <= u32::MAX as usize, "chain entry exceeds u32 range");
193 Self {
194 entry: entry as u32,
195 delegate_buf: [0; MAX_DELEGATE_DEPTH],
196 delegate_len: 0,
197 }
198 }
199
200 #[inline]
201 fn from_slice(entry: usize, path: &[usize]) -> Self {
202 debug_assert!(
203 path.len() <= MAX_DELEGATE_DEPTH,
204 "delegate depth {} exceeds MAX_DELEGATE_DEPTH {}",
205 path.len(),
206 MAX_DELEGATE_DEPTH
207 );
208 debug_assert!(
209 path.iter().all(|&i| i <= u8::MAX as usize),
210 "delegate index exceeds u8 range"
211 );
212 let mut delegate_buf = [0u8; MAX_DELEGATE_DEPTH];
213 for (i, &v) in path.iter().enumerate().take(MAX_DELEGATE_DEPTH) {
214 delegate_buf[i] = v as u8;
215 }
216 Self {
217 delegate_buf,
218 delegate_len: path.len().min(MAX_DELEGATE_DEPTH) as u8,
219 ..Self::root(entry)
220 }
221 }
222
223 #[inline]
224 fn entry(&self) -> usize {
225 self.entry as usize
226 }
227
228 #[inline]
229 fn delegates(&self) -> &[u8] {
230 &self.delegate_buf[..self.delegate_len as usize]
231 }
232}
233
234#[derive(Copy, Clone, Debug, PartialEq, Eq)]
235pub(crate) enum NodeLink {
236 Head,
237 Tail,
238 Entry(NodePath),
239}
240
241#[derive(Debug)]
247pub struct NodeState {
248 aggregate_child_capabilities: Cell<NodeCapabilities>,
249 capabilities: Cell<NodeCapabilities>,
250 parent: Cell<Option<NodeLink>>,
251 child: Cell<Option<NodeLink>>,
252 attached: Cell<bool>,
253 is_sentinel: bool,
254}
255
256impl Default for NodeState {
257 fn default() -> Self {
258 Self::new()
259 }
260}
261
262impl NodeState {
263 pub const fn new() -> Self {
264 Self {
265 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
266 capabilities: Cell::new(NodeCapabilities::empty()),
267 parent: Cell::new(None),
268 child: Cell::new(None),
269 attached: Cell::new(false),
270 is_sentinel: false,
271 }
272 }
273
274 pub const fn sentinel() -> Self {
275 Self {
276 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
277 capabilities: Cell::new(NodeCapabilities::empty()),
278 parent: Cell::new(None),
279 child: Cell::new(None),
280 attached: Cell::new(true),
281 is_sentinel: true,
282 }
283 }
284
285 pub fn set_capabilities(&self, capabilities: NodeCapabilities) {
286 self.capabilities.set(capabilities);
287 }
288
289 #[inline]
290 pub fn capabilities(&self) -> NodeCapabilities {
291 self.capabilities.get()
292 }
293
294 pub fn set_aggregate_child_capabilities(&self, capabilities: NodeCapabilities) {
295 self.aggregate_child_capabilities.set(capabilities);
296 }
297
298 #[inline]
299 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
300 self.aggregate_child_capabilities.get()
301 }
302
303 pub(crate) fn set_parent_link(&self, parent: Option<NodeLink>) {
304 self.parent.set(parent);
305 }
306
307 #[inline]
308 pub(crate) fn parent_link(&self) -> Option<NodeLink> {
309 self.parent.get()
310 }
311
312 pub(crate) fn set_child_link(&self, child: Option<NodeLink>) {
313 self.child.set(child);
314 }
315
316 #[inline]
317 pub(crate) fn child_link(&self) -> Option<NodeLink> {
318 self.child.get()
319 }
320
321 pub fn set_attached(&self, attached: bool) {
322 self.attached.set(attached);
323 }
324
325 pub fn is_attached(&self) -> bool {
326 self.attached.get()
327 }
328
329 pub fn is_sentinel(&self) -> bool {
330 self.is_sentinel
331 }
332}
333
334pub trait DelegatableNode {
336 fn node_state(&self) -> &NodeState;
337 fn aggregate_child_capabilities(&self) -> NodeCapabilities {
338 self.node_state().aggregate_child_capabilities()
339 }
340}
341
342pub trait ModifierNode: Any + DelegatableNode {
400 fn on_attach(&mut self, _context: &mut dyn ModifierNodeContext) {}
401
402 fn on_detach(&mut self) {}
403
404 fn on_reset(&mut self) {}
405
406 fn as_draw_node(&self) -> Option<&dyn DrawModifierNode> {
408 None
409 }
410
411 fn as_draw_node_mut(&mut self) -> Option<&mut dyn DrawModifierNode> {
413 None
414 }
415
416 fn as_pointer_input_node(&self) -> Option<&dyn PointerInputNode> {
418 None
419 }
420
421 fn as_pointer_input_node_mut(&mut self) -> Option<&mut dyn PointerInputNode> {
423 None
424 }
425
426 fn as_semantics_node(&self) -> Option<&dyn SemanticsNode> {
428 None
429 }
430
431 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn SemanticsNode> {
433 None
434 }
435
436 fn as_focus_node(&self) -> Option<&dyn FocusNode> {
438 None
439 }
440
441 fn as_focus_node_mut(&mut self) -> Option<&mut dyn FocusNode> {
443 None
444 }
445
446 fn as_layout_node(&self) -> Option<&dyn LayoutModifierNode> {
448 None
449 }
450
451 fn as_layout_node_mut(&mut self) -> Option<&mut dyn LayoutModifierNode> {
453 None
454 }
455
456 fn for_each_delegate<'b>(&'b self, _visitor: &mut dyn FnMut(&'b dyn ModifierNode)) {}
458
459 fn for_each_delegate_mut<'b>(&'b mut self, _visitor: &mut dyn FnMut(&'b mut dyn ModifierNode)) {
461 }
462}
463
464pub trait LayoutModifierNode: ModifierNode {
470 fn measure(
492 &self,
493 _context: &mut dyn ModifierNodeContext,
494 measurable: &dyn Measurable,
495 constraints: Constraints,
496 ) -> cranpose_ui_layout::LayoutModifierMeasureResult {
497 let placeable = measurable.measure(constraints);
498 cranpose_ui_layout::LayoutModifierMeasureResult::with_size(Size {
499 width: placeable.width(),
500 height: placeable.height(),
501 })
502 }
503
504 fn measure_hold(
511 &self,
512 _density: f32,
513 _constraints: Constraints,
514 _size: Size,
515 _wrapped: cranpose_ui_layout::WrappedHold,
516 ) -> Option<cranpose_ui_layout::ConstraintsHold> {
517 None
518 }
519
520 fn min_intrinsic_width(&self, measurable: &dyn Measurable, height: f32, _density: f32) -> f32 {
523 measurable.min_intrinsic_width(height)
524 }
525
526 fn max_intrinsic_width(&self, measurable: &dyn Measurable, height: f32, _density: f32) -> f32 {
529 measurable.max_intrinsic_width(height)
530 }
531
532 fn min_intrinsic_height(&self, measurable: &dyn Measurable, width: f32, _density: f32) -> f32 {
535 measurable.min_intrinsic_height(width)
536 }
537
538 fn max_intrinsic_height(&self, measurable: &dyn Measurable, width: f32, _density: f32) -> f32 {
541 measurable.max_intrinsic_height(width)
542 }
543}
544
545pub trait DrawModifierNode: ModifierNode {
552 fn create_draw_closure(&self) -> Option<NodeDrawClosure> {
563 None
564 }
565
566 fn create_behind_draw_closure(&self) -> Option<NodeDrawClosure> {
571 None
572 }
573}
574
575pub type NodeDrawClosure = Rc<dyn Fn(&mut cranpose_ui_graphics::DrawScopeDefault)>;
580
581pub trait PointerInputNode: ModifierNode {
587 fn on_pointer_event(
590 &mut self,
591 _context: &mut dyn ModifierNodeContext,
592 _event: &PointerEvent,
593 ) -> bool {
594 false
595 }
596
597 fn hit_test(&self, _x: f32, _y: f32) -> bool {
600 true
601 }
602
603 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
605 None
606 }
607
608 fn layout_size_sink(&self) -> Option<Rc<Cell<Size>>> {
621 None
622 }
623}
624
625pub trait SemanticsNode: ModifierNode {
631 fn merge_semantics(&self, _config: &mut SemanticsConfiguration) {}
633
634 fn reach(&self) -> SemanticsReach {
641 SemanticsReach::merged_by(self, true)
642 }
643}
644
645#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
650pub struct SemanticsReach {
651 pub is_modal: bool,
653 pub hidden: bool,
655 pub merges_live_state: bool,
659}
660
661impl SemanticsReach {
662 pub fn merged_by(node: &(impl SemanticsNode + ?Sized), merges_live_state: bool) -> Self {
665 let mut config = SemanticsConfiguration::default();
666 node.merge_semantics(&mut config);
667 Self {
668 is_modal: config.is_modal,
669 hidden: config.hidden,
670 merges_live_state,
671 }
672 }
673
674 pub fn union(self, other: Self) -> Self {
676 Self {
677 is_modal: self.is_modal || other.is_modal,
678 hidden: self.hidden || other.hidden,
679 merges_live_state: self.merges_live_state || other.merges_live_state,
680 }
681 }
682}
683
684#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
689pub enum FocusState {
690 Active,
692 ActiveParent,
694 Captured,
698 #[default]
701 Inactive,
702}
703
704impl FocusState {
705 pub fn is_focused(self) -> bool {
707 matches!(self, FocusState::Active | FocusState::Captured)
708 }
709
710 pub fn has_focus(self) -> bool {
712 matches!(
713 self,
714 FocusState::Active | FocusState::ActiveParent | FocusState::Captured
715 )
716 }
717
718 pub fn is_captured(self) -> bool {
720 matches!(self, FocusState::Captured)
721 }
722}
723
724pub trait FocusNode: ModifierNode {
729 fn focus_state(&self) -> FocusState;
731
732 fn on_focus_changed(&mut self, _context: &mut dyn ModifierNodeContext, _state: FocusState) {}
734}
735
736#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
747pub enum SemanticsWidgetRole {
748 Button,
749 Checkbox,
750 Switch,
751 RadioButton,
752 Tab,
753 Image,
754 DropdownList,
757 ValuePicker,
760 Header,
765 Dialog,
769 Link,
772 SearchField,
775 ProgressBar,
778 ToggleButton,
781 Alert,
784 Toolbar,
787 Menu,
789 MenuItem,
791 TabBar,
794 List,
796 ListItem,
798 RadioGroup,
800}
801
802#[derive(Clone, Copy, Debug, PartialEq)]
810pub struct ProgressBarRangeInfo {
811 pub current: f32,
812 pub start: f32,
813 pub end: f32,
814 pub steps: u32,
817}
818
819impl ProgressBarRangeInfo {
820 pub fn new(current: f32, start: f32, end: f32, steps: u32) -> Self {
821 Self {
822 current,
823 start,
824 end,
825 steps,
826 }
827 }
828
829 pub fn fraction(&self) -> f32 {
831 let span = self.end - self.start;
832 if span.abs() < f32::EPSILON {
833 return 0.0;
834 }
835 ((self.current - self.start) / span).clamp(0.0, 1.0)
836 }
837
838 pub fn step(&self) -> f32 {
841 let span = self.end - self.start;
842 if self.steps == 0 {
843 span / 10.0
844 } else {
845 span / (self.steps as f32 + 1.0)
846 }
847 }
848}
849
850#[derive(Clone, Copy, Debug, PartialEq, Eq)]
855pub struct CollectionInfo {
856 pub rows: usize,
857 pub columns: usize,
858}
859
860#[derive(Clone, Copy, Debug, PartialEq)]
871pub struct ScrollAxisRange {
872 pub value: f32,
873 pub max_value: f32,
874 pub reverse: bool,
875 pub content_padding_start: f32,
876 pub content_padding_end: f32,
877}
878
879impl ScrollAxisRange {
880 pub fn new(value: f32, max_value: f32, reverse: bool) -> Self {
881 Self {
882 value,
883 max_value,
884 reverse,
885 content_padding_start: 0.0,
886 content_padding_end: 0.0,
887 }
888 }
889
890 pub fn with_content_padding(self, start: f32, end: f32) -> Self {
893 Self {
894 content_padding_start: start,
895 content_padding_end: end,
896 ..self
897 }
898 }
899
900 pub fn can_scroll_forward(&self) -> bool {
901 self.value < self.max_value
902 }
903
904 pub fn can_scroll_backward(&self) -> bool {
905 self.value > 0.0
906 }
907}
908
909#[derive(Clone)]
915pub struct SemanticsScrollBy {
916 handler: Rc<dyn Fn(f32, f32) -> bool>,
917}
918
919impl SemanticsScrollBy {
920 pub fn new(handler: impl Fn(f32, f32) -> bool + 'static) -> Self {
921 Self {
922 handler: Rc::new(handler),
923 }
924 }
925
926 pub fn invoke(&self, dx: f32, dy: f32) -> bool {
927 (self.handler)(dx, dy)
928 }
929}
930
931impl fmt::Debug for SemanticsScrollBy {
932 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
933 f.debug_struct("SemanticsScrollBy").finish_non_exhaustive()
934 }
935}
936
937impl PartialEq for SemanticsScrollBy {
938 fn eq(&self, _other: &Self) -> bool {
939 true
940 }
941}
942
943impl Eq for SemanticsScrollBy {}
944
945#[derive(Clone)]
951pub struct SemanticsScrollToIndex {
952 handler: Rc<dyn Fn(usize) -> bool>,
953}
954
955impl SemanticsScrollToIndex {
956 pub fn new(handler: impl Fn(usize) -> bool + 'static) -> Self {
957 Self {
958 handler: Rc::new(handler),
959 }
960 }
961
962 pub fn invoke(&self, index: usize) -> bool {
963 (self.handler)(index)
964 }
965}
966
967impl fmt::Debug for SemanticsScrollToIndex {
968 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
969 f.debug_struct("SemanticsScrollToIndex")
970 .finish_non_exhaustive()
971 }
972}
973
974impl PartialEq for SemanticsScrollToIndex {
975 fn eq(&self, _other: &Self) -> bool {
976 true
977 }
978}
979
980impl Eq for SemanticsScrollToIndex {}
981
982#[derive(Clone)]
988pub struct SemanticsSetProgress {
989 handler: Rc<dyn Fn(f32) -> bool>,
990}
991
992impl SemanticsSetProgress {
993 pub fn new(handler: impl Fn(f32) -> bool + 'static) -> Self {
994 Self {
995 handler: Rc::new(handler),
996 }
997 }
998
999 pub fn invoke(&self, value: f32) -> bool {
1000 (self.handler)(value)
1001 }
1002}
1003
1004impl fmt::Debug for SemanticsSetProgress {
1005 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1006 f.debug_struct("SemanticsSetProgress")
1007 .finish_non_exhaustive()
1008 }
1009}
1010
1011#[derive(Clone)]
1015pub struct SemanticsSetText(Rc<dyn Fn(&str) -> bool>);
1016
1017impl SemanticsSetText {
1018 pub fn new(handler: impl Fn(&str) -> bool + 'static) -> Self {
1019 Self(Rc::new(handler))
1020 }
1021
1022 pub fn invoke(&self, text: &str) -> bool {
1023 (self.0)(text)
1024 }
1025}
1026
1027impl fmt::Debug for SemanticsSetText {
1028 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1029 f.write_str("SemanticsSetText")
1030 }
1031}
1032
1033#[derive(Clone)]
1039pub struct SemanticsSetSelection(Rc<dyn Fn(usize, usize) -> bool>);
1040
1041impl SemanticsSetSelection {
1042 pub fn new(handler: impl Fn(usize, usize) -> bool + 'static) -> Self {
1043 Self(Rc::new(handler))
1044 }
1045
1046 pub fn invoke(&self, anchor: usize, focus: usize) -> bool {
1047 (self.0)(anchor, focus)
1048 }
1049}
1050
1051impl fmt::Debug for SemanticsSetSelection {
1052 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1053 f.write_str("SemanticsSetSelection")
1054 }
1055}
1056
1057#[derive(Clone)]
1060pub struct SemanticsExpand(Rc<dyn Fn() -> bool>);
1061
1062impl SemanticsExpand {
1063 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1064 Self(Rc::new(handler))
1065 }
1066
1067 pub fn invoke(&self) -> bool {
1068 (self.0)()
1069 }
1070}
1071
1072impl fmt::Debug for SemanticsExpand {
1073 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1074 f.write_str("SemanticsExpand")
1075 }
1076}
1077
1078#[derive(Clone)]
1082pub struct SemanticsLongClick(Rc<dyn Fn() -> bool>);
1083
1084impl SemanticsLongClick {
1085 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1086 Self(Rc::new(handler))
1087 }
1088
1089 pub fn invoke(&self) -> bool {
1090 (self.0)()
1091 }
1092}
1093
1094impl fmt::Debug for SemanticsLongClick {
1095 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1096 f.write_str("SemanticsLongClick")
1097 }
1098}
1099
1100impl PartialEq for SemanticsLongClick {
1101 fn eq(&self, _other: &Self) -> bool {
1102 true
1103 }
1104}
1105
1106impl PartialEq for SemanticsExpand {
1107 fn eq(&self, _other: &Self) -> bool {
1108 true
1109 }
1110}
1111
1112#[derive(Clone)]
1116pub struct SemanticsDismiss(Rc<dyn Fn() -> bool>);
1117
1118impl SemanticsDismiss {
1119 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1120 Self(Rc::new(handler))
1121 }
1122
1123 pub fn invoke(&self) -> bool {
1124 (self.0)()
1125 }
1126}
1127
1128impl fmt::Debug for SemanticsDismiss {
1129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1130 f.write_str("SemanticsDismiss")
1131 }
1132}
1133
1134impl PartialEq for SemanticsDismiss {
1135 fn eq(&self, _other: &Self) -> bool {
1136 true
1137 }
1138}
1139
1140impl PartialEq for SemanticsSetText {
1141 fn eq(&self, _other: &Self) -> bool {
1142 true
1143 }
1144}
1145
1146impl PartialEq for SemanticsSetSelection {
1147 fn eq(&self, _other: &Self) -> bool {
1148 true
1149 }
1150}
1151
1152#[derive(Clone)]
1158pub struct SemanticsMagicTap(Rc<dyn Fn() -> bool>);
1159
1160impl SemanticsMagicTap {
1161 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1162 Self(Rc::new(handler))
1163 }
1164
1165 pub fn invoke(&self) -> bool {
1166 (self.0)()
1167 }
1168}
1169
1170impl fmt::Debug for SemanticsMagicTap {
1171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1172 f.write_str("SemanticsMagicTap")
1173 }
1174}
1175
1176impl PartialEq for SemanticsMagicTap {
1177 fn eq(&self, _other: &Self) -> bool {
1178 true
1179 }
1180}
1181
1182impl PartialEq for SemanticsSetProgress {
1183 fn eq(&self, _other: &Self) -> bool {
1184 true
1185 }
1186}
1187
1188impl Eq for SemanticsSetProgress {}
1189
1190#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1197pub enum LiveRegionMode {
1198 Polite,
1200 Assertive,
1203}
1204
1205#[derive(Clone)]
1212pub struct SemanticsCustomAction {
1213 pub label: String,
1215 handler: Rc<dyn Fn()>,
1216}
1217
1218impl SemanticsCustomAction {
1219 pub fn new(label: impl Into<String>, handler: impl Fn() + 'static) -> Self {
1220 Self {
1221 label: label.into(),
1222 handler: Rc::new(handler),
1223 }
1224 }
1225
1226 pub fn invoke(&self) {
1227 (self.handler)();
1228 }
1229}
1230
1231impl fmt::Debug for SemanticsCustomAction {
1232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1233 f.debug_struct("SemanticsCustomAction")
1234 .field("label", &self.label)
1235 .finish_non_exhaustive()
1236 }
1237}
1238
1239impl PartialEq for SemanticsCustomAction {
1240 fn eq(&self, other: &Self) -> bool {
1241 self.label == other.label
1242 }
1243}
1244
1245impl Eq for SemanticsCustomAction {}
1246
1247#[derive(Clone, Debug, PartialEq)]
1262pub struct CanvasSemanticsNode {
1263 pub key: u64,
1270 pub bounds: cranpose_ui_graphics::Rect,
1272 pub label: String,
1273 pub role: Option<SemanticsWidgetRole>,
1274 pub state_description: Option<String>,
1278 pub on_click_label: Option<String>,
1281 pub clickable: bool,
1282 pub selected: Option<bool>,
1284 pub toggled: Option<bool>,
1286 pub enabled: bool,
1287 pub custom_actions: Vec<SemanticsCustomAction>,
1288}
1289
1290impl Default for CanvasSemanticsNode {
1291 fn default() -> Self {
1292 Self {
1293 key: 0,
1294 bounds: cranpose_ui_graphics::Rect {
1295 x: 0.0,
1296 y: 0.0,
1297 width: 0.0,
1298 height: 0.0,
1299 },
1300 label: String::new(),
1301 role: None,
1302 state_description: None,
1303 on_click_label: None,
1304 clickable: false,
1305 selected: None,
1306 toggled: None,
1307 enabled: true,
1308 custom_actions: Vec::new(),
1309 }
1310 }
1311}
1312
1313impl CanvasSemanticsNode {
1314 pub fn control(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1316 Self {
1317 key,
1318 bounds,
1319 label: label.into(),
1320 clickable: true,
1321 ..Self::default()
1322 }
1323 }
1324
1325 pub fn text(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1327 Self {
1328 key,
1329 bounds,
1330 label: label.into(),
1331 ..Self::default()
1332 }
1333 }
1334
1335 pub fn with_role(mut self, role: SemanticsWidgetRole) -> Self {
1336 self.role = Some(role);
1337 self
1338 }
1339
1340 pub fn with_state_description(mut self, state: impl Into<String>) -> Self {
1341 self.state_description = Some(state.into());
1342 self
1343 }
1344
1345 pub fn with_click_label(mut self, label: impl Into<String>) -> Self {
1346 self.on_click_label = Some(label.into());
1347 self.clickable = true;
1348 self
1349 }
1350
1351 pub fn with_selected(mut self, selected: bool) -> Self {
1352 self.selected = Some(selected);
1353 self
1354 }
1355
1356 pub fn with_toggled(mut self, toggled: bool) -> Self {
1357 self.toggled = Some(toggled);
1358 self
1359 }
1360
1361 pub fn with_enabled(mut self, enabled: bool) -> Self {
1362 self.enabled = enabled;
1363 self
1364 }
1365
1366 pub fn with_custom_action(mut self, action: SemanticsCustomAction) -> Self {
1367 self.custom_actions.push(action);
1368 self
1369 }
1370}
1371
1372#[derive(Clone, Debug, PartialEq)]
1374pub struct SemanticsConfiguration {
1375 pub content_description: Option<String>,
1376 pub state_description: Option<String>,
1378 pub on_click_label: Option<String>,
1380 pub on_click: Option<SemanticsCustomAction>,
1383 pub on_long_click: Option<SemanticsLongClick>,
1386 pub on_long_click_label: Option<String>,
1389 pub on_magic_tap: Option<SemanticsMagicTap>,
1393 pub on_magic_tap_label: Option<String>,
1396 pub input_labels: Vec<String>,
1400 pub language: Option<String>,
1404 pub role: Option<SemanticsWidgetRole>,
1406 pub selected: Option<bool>,
1407 pub toggled: Option<bool>,
1408 pub enabled: bool,
1409 pub is_clickable: bool,
1410 pub is_editable_text: bool,
1411 pub multiline: bool,
1413 pub text: Option<String>,
1416 pub text_selection: Option<crate::text::TextRange>,
1417 pub custom_actions: Vec<SemanticsCustomAction>,
1418 pub canvas_children: Vec<CanvasSemanticsNode>,
1421 pub is_modal: bool,
1424 pub hidden: bool,
1428 pub merge_descendants: bool,
1432 pub selectable_group: bool,
1436 pub pane_title: Option<String>,
1439 pub error: Option<String>,
1442 pub password: bool,
1445 pub traversal_index: f32,
1449 pub live_region: Option<LiveRegionMode>,
1452 pub progress: Option<ProgressBarRangeInfo>,
1455 pub set_progress: Option<SemanticsSetProgress>,
1458 pub set_text: Option<SemanticsSetText>,
1461 pub set_selection: Option<SemanticsSetSelection>,
1464 pub expand: Option<SemanticsExpand>,
1467 pub dismiss: Option<SemanticsDismiss>,
1471 pub collapse: Option<SemanticsExpand>,
1474 pub vertical_scroll: Option<ScrollAxisRange>,
1477 pub horizontal_scroll: Option<ScrollAxisRange>,
1480 pub scroll_by: Option<SemanticsScrollBy>,
1483 pub scroll_to_index: Option<SemanticsScrollToIndex>,
1487 pub collection: Option<CollectionInfo>,
1489}
1490
1491impl Default for SemanticsConfiguration {
1492 fn default() -> Self {
1493 Self {
1494 content_description: None,
1495 state_description: None,
1496 on_click_label: None,
1497 on_click: None,
1498 on_long_click: None,
1499 on_long_click_label: None,
1500 on_magic_tap: None,
1501 on_magic_tap_label: None,
1502 input_labels: Vec::new(),
1503 language: None,
1504 role: None,
1505 selected: None,
1506 toggled: None,
1507 enabled: true,
1508 is_clickable: false,
1509 is_editable_text: false,
1510 multiline: false,
1511 text: None,
1512 text_selection: None,
1513 custom_actions: Vec::new(),
1514 canvas_children: Vec::new(),
1515 is_modal: false,
1516 hidden: false,
1517 merge_descendants: false,
1518 selectable_group: false,
1519 pane_title: None,
1520 error: None,
1521 password: false,
1522 traversal_index: 0.0,
1523 live_region: None,
1524 progress: None,
1525 set_progress: None,
1526 set_text: None,
1527 set_selection: None,
1528 expand: None,
1529 dismiss: None,
1530 collapse: None,
1531 vertical_scroll: None,
1532 horizontal_scroll: None,
1533 scroll_by: None,
1534 scroll_to_index: None,
1535 collection: None,
1536 }
1537 }
1538}
1539
1540pub type SemanticsSpec = SemanticsConfiguration;
1549
1550impl SemanticsConfiguration {
1551 pub fn new() -> Self {
1554 Self::default()
1555 }
1556
1557 pub fn content_description(mut self, name: impl Into<String>) -> Self {
1560 self.content_description = Some(name.into());
1561 self
1562 }
1563
1564 pub fn state_description(mut self, state: impl Into<String>) -> Self {
1567 self.state_description = Some(state.into());
1568 self
1569 }
1570
1571 pub fn clickable(mut self) -> Self {
1573 self.is_clickable = true;
1574 self
1575 }
1576
1577 pub fn on_click(mut self, label: impl Into<String>, action: impl Fn() + 'static) -> Self {
1580 self.on_click = Some(SemanticsCustomAction::new(label, action));
1581 self
1582 }
1583
1584 pub fn on_long_click(
1588 mut self,
1589 label: impl Into<String>,
1590 action: impl Fn() -> bool + 'static,
1591 ) -> Self {
1592 self.on_long_click_label = Some(label.into());
1593 self.on_long_click = Some(SemanticsLongClick::new(action));
1594 self
1595 }
1596
1597 pub fn on_magic_tap(
1601 mut self,
1602 label: impl Into<String>,
1603 action: impl Fn() -> bool + 'static,
1604 ) -> Self {
1605 self.on_magic_tap_label = Some(label.into());
1606 self.on_magic_tap = Some(SemanticsMagicTap::new(action));
1607 self
1608 }
1609
1610 pub fn input_labels<S: Into<String>>(mut self, labels: impl IntoIterator<Item = S>) -> Self {
1613 self.input_labels = labels.into_iter().map(Into::into).collect();
1614 self
1615 }
1616
1617 pub fn language(mut self, tag: impl Into<String>) -> Self {
1620 self.language = Some(tag.into());
1621 self
1622 }
1623
1624 pub fn toggled(mut self, toggled: bool) -> Self {
1626 self.toggled = Some(toggled);
1627 self
1628 }
1629
1630 pub fn selected(mut self, selected: bool) -> Self {
1633 self.selected = Some(selected);
1634 self
1635 }
1636
1637 pub fn role(mut self, role: SemanticsWidgetRole) -> Self {
1639 self.role = Some(role);
1640 self
1641 }
1642
1643 pub fn heading(self) -> Self {
1646 self.role(SemanticsWidgetRole::Header)
1647 }
1648
1649 pub fn error(mut self, message: impl Into<String>) -> Self {
1651 self.error = Some(message.into());
1652 self
1653 }
1654
1655 pub fn password(mut self) -> Self {
1657 self.password = true;
1658 self
1659 }
1660
1661 pub fn pane_title(mut self, title: impl Into<String>) -> Self {
1664 self.pane_title = Some(title.into());
1665 self
1666 }
1667
1668 pub fn traversal_index(mut self, index: f32) -> Self {
1671 self.traversal_index = index;
1672 self
1673 }
1674
1675 pub fn hidden(mut self) -> Self {
1678 self.hidden = true;
1679 self
1680 }
1681
1682 pub fn merge_descendants(mut self) -> Self {
1685 self.merge_descendants = true;
1686 self
1687 }
1688
1689 pub fn selectable_group(mut self) -> Self {
1692 self.selectable_group = true;
1693 self
1694 }
1695
1696 pub fn live_region(mut self, mode: LiveRegionMode) -> Self {
1699 self.live_region = Some(mode);
1700 self
1701 }
1702 pub fn merge(&mut self, other: &SemanticsConfiguration) {
1703 if let Some(description) = &other.content_description {
1704 self.content_description = Some(description.clone());
1705 }
1706 if let Some(state) = &other.state_description {
1707 self.state_description = Some(state.clone());
1708 }
1709 if let Some(label) = &other.on_click_label {
1710 self.on_click_label = Some(label.clone());
1711 }
1712 if let Some(label) = &other.on_long_click_label {
1713 self.on_long_click_label = Some(label.clone());
1714 }
1715 if let Some(label) = &other.on_magic_tap_label {
1716 self.on_magic_tap_label = Some(label.clone());
1717 }
1718 if !other.input_labels.is_empty() {
1719 self.input_labels.clone_from(&other.input_labels);
1720 }
1721 if let Some(language) = &other.language {
1722 self.language = Some(language.clone());
1723 }
1724 if let Some(role) = other.role {
1725 self.role = Some(role);
1726 }
1727 if let Some(selected) = other.selected {
1728 self.selected = Some(selected);
1729 }
1730 if let Some(toggled) = other.toggled {
1731 self.toggled = Some(toggled);
1732 }
1733 self.enabled &= other.enabled;
1734 self.is_clickable |= other.is_clickable;
1735 self.is_editable_text |= other.is_editable_text;
1736 self.multiline |= other.multiline;
1737 if let Some(text) = &other.text {
1738 self.text = Some(text.clone());
1739 }
1740 self.is_modal |= other.is_modal;
1741 self.hidden |= other.hidden;
1742 self.merge_descendants |= other.merge_descendants;
1743 self.selectable_group |= other.selectable_group;
1744 self.password |= other.password;
1745 if other.traversal_index != 0.0 {
1746 self.traversal_index = other.traversal_index;
1747 }
1748 if let Some(live_region) = other.live_region {
1749 self.live_region = Some(live_region);
1750 }
1751 self.merge_words(other);
1752 self.merge_actions(other);
1753 self.merge_ranges(other);
1754 }
1755
1756 fn merge_words(&mut self, other: &SemanticsConfiguration) {
1757 if let Some(title) = &other.pane_title {
1758 self.pane_title = Some(title.clone());
1759 }
1760 if let Some(error) = &other.error {
1761 self.error = Some(error.clone());
1762 }
1763 }
1764
1765 fn merge_actions(&mut self, other: &SemanticsConfiguration) {
1766 if let Some(on_click) = &other.on_click {
1767 self.on_click = Some(on_click.clone());
1768 }
1769 self.custom_actions
1770 .extend(other.custom_actions.iter().cloned());
1771 self.canvas_children
1772 .extend(other.canvas_children.iter().cloned());
1773 if let Some(set_progress) = &other.set_progress {
1774 self.set_progress = Some(set_progress.clone());
1775 }
1776 if let Some(set_text) = &other.set_text {
1777 self.set_text = Some(set_text.clone());
1778 }
1779 if let Some(set_selection) = &other.set_selection {
1780 self.set_selection = Some(set_selection.clone());
1781 }
1782 if let Some(expand) = &other.expand {
1783 self.expand = Some(expand.clone());
1784 }
1785 if let Some(collapse) = &other.collapse {
1786 self.collapse = Some(collapse.clone());
1787 }
1788 if let Some(dismiss) = &other.dismiss {
1789 self.dismiss = Some(dismiss.clone());
1790 }
1791 if let Some(long_click) = &other.on_long_click {
1792 self.on_long_click = Some(long_click.clone());
1793 }
1794 if let Some(magic_tap) = &other.on_magic_tap {
1795 self.on_magic_tap = Some(magic_tap.clone());
1796 }
1797 if let Some(scroll_by) = &other.scroll_by {
1798 self.scroll_by = Some(scroll_by.clone());
1799 }
1800 if let Some(scroll_to_index) = &other.scroll_to_index {
1801 self.scroll_to_index = Some(scroll_to_index.clone());
1802 }
1803 }
1804
1805 fn merge_ranges(&mut self, other: &SemanticsConfiguration) {
1806 if let Some(selection) = other.text_selection {
1807 self.text_selection = Some(selection);
1808 }
1809 if let Some(progress) = other.progress {
1810 self.progress = Some(progress);
1811 }
1812 if let Some(range) = other.vertical_scroll {
1813 self.vertical_scroll = Some(range);
1814 }
1815 if let Some(range) = other.horizontal_scroll {
1816 self.horizontal_scroll = Some(range);
1817 }
1818 if let Some(collection) = other.collection {
1819 self.collection = Some(collection);
1820 }
1821 }
1822
1823 pub fn is_activatable(&self) -> bool {
1826 self.is_clickable || self.on_click_label.is_some() || self.on_click.is_some()
1827 }
1828}
1829
1830impl fmt::Debug for dyn ModifierNode {
1831 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1832 f.debug_struct("ModifierNode").finish_non_exhaustive()
1833 }
1834}
1835
1836impl dyn ModifierNode {
1837 pub fn as_any(&self) -> &dyn Any {
1838 self
1839 }
1840
1841 pub fn as_any_mut(&mut self) -> &mut dyn Any {
1842 self
1843 }
1844}
1845
1846pub trait ModifierNodeElement: fmt::Debug + Hash + PartialEq + 'static {
1849 type Node: ModifierNode;
1850
1851 fn create(&self) -> Self::Node;
1853
1854 fn update(&self, node: &mut Self::Node);
1856
1857 fn key(&self) -> Option<u64> {
1859 None
1860 }
1861
1862 fn inspector_name(&self) -> &'static str {
1864 type_name::<Self>()
1865 }
1866
1867 fn inspector_properties(&self, _inspector: &mut dyn FnMut(&'static str, String)) {}
1869
1870 fn capabilities(&self) -> NodeCapabilities {
1873 NodeCapabilities::default()
1874 }
1875
1876 fn always_update(&self) -> bool {
1882 false
1883 }
1884
1885 fn auto_invalidate_on_update(&self) -> bool {
1888 true
1889 }
1890
1891 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
1898 None
1899 }
1900
1901 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
1908 Vec::new()
1909 }
1910}
1911
1912#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1914pub struct NodeCapabilities(u32);
1915
1916impl NodeCapabilities {
1917 pub const NONE: Self = Self(0);
1919 pub const LAYOUT: Self = Self(1 << 0);
1921 pub const DRAW: Self = Self(1 << 1);
1923 pub const POINTER_INPUT: Self = Self(1 << 2);
1925 pub const SEMANTICS: Self = Self(1 << 3);
1927 pub const MODIFIER_LOCALS: Self = Self(1 << 4);
1929 pub const FOCUS: Self = Self(1 << 5);
1931 pub const WINDOW_ROOT: Self = Self(1 << 6);
1935 pub const KEY_INPUT: Self = Self(1 << 7);
1937
1938 pub const fn empty() -> Self {
1940 Self::NONE
1941 }
1942
1943 pub const fn contains(self, other: Self) -> bool {
1945 (self.0 & other.0) == other.0
1946 }
1947
1948 pub const fn intersects(self, other: Self) -> bool {
1950 (self.0 & other.0) != 0
1951 }
1952
1953 pub fn insert(&mut self, other: Self) {
1955 self.0 |= other.0;
1956 }
1957
1958 pub const fn bits(self) -> u32 {
1960 self.0
1961 }
1962
1963 pub const fn is_empty(self) -> bool {
1965 self.0 == 0
1966 }
1967
1968 pub const fn for_invalidation(kind: InvalidationKind) -> Self {
1970 match kind {
1971 InvalidationKind::Layout => Self::LAYOUT,
1972 InvalidationKind::Draw => Self::DRAW,
1973 InvalidationKind::PointerInput => Self::POINTER_INPUT,
1974 InvalidationKind::Semantics => Self::SEMANTICS,
1975 InvalidationKind::Focus => Self::FOCUS,
1976 }
1977 }
1978}
1979
1980impl Default for NodeCapabilities {
1981 fn default() -> Self {
1982 Self::NONE
1983 }
1984}
1985
1986impl fmt::Debug for NodeCapabilities {
1987 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1988 f.debug_struct("NodeCapabilities")
1989 .field("layout", &self.contains(Self::LAYOUT))
1990 .field("draw", &self.contains(Self::DRAW))
1991 .field("pointer_input", &self.contains(Self::POINTER_INPUT))
1992 .field("semantics", &self.contains(Self::SEMANTICS))
1993 .field("modifier_locals", &self.contains(Self::MODIFIER_LOCALS))
1994 .field("focus", &self.contains(Self::FOCUS))
1995 .field("window_root", &self.contains(Self::WINDOW_ROOT))
1996 .field("key_input", &self.contains(Self::KEY_INPUT))
1997 .finish()
1998 }
1999}
2000
2001impl BitOr for NodeCapabilities {
2002 type Output = Self;
2003
2004 fn bitor(self, rhs: Self) -> Self::Output {
2005 Self(self.0 | rhs.0)
2006 }
2007}
2008
2009impl BitOrAssign for NodeCapabilities {
2010 fn bitor_assign(&mut self, rhs: Self) {
2011 self.0 |= rhs.0;
2012 }
2013}
2014
2015pub type ModifierInvalidations = smallvec::SmallVec<[ModifierInvalidation; 5]>;
2018
2019#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2021pub struct ModifierInvalidation {
2022 kind: InvalidationKind,
2023 capabilities: NodeCapabilities,
2024}
2025
2026impl ModifierInvalidation {
2027 pub const fn new(kind: InvalidationKind, capabilities: NodeCapabilities) -> Self {
2029 Self { kind, capabilities }
2030 }
2031
2032 pub const fn kind(self) -> InvalidationKind {
2034 self.kind
2035 }
2036
2037 pub const fn capabilities(self) -> NodeCapabilities {
2039 self.capabilities
2040 }
2041}
2042
2043pub trait AnyModifierElement: fmt::Debug {
2045 fn node_type(&self) -> TypeId;
2046
2047 fn element_type(&self) -> TypeId;
2048
2049 fn create_node(&self) -> Rc<RefCell<dyn ModifierNode>>;
2051
2052 fn can_update_node(&self, node: &dyn ModifierNode) -> bool;
2053
2054 fn update_node(&self, node: &mut dyn ModifierNode);
2055
2056 fn key(&self) -> Option<u64>;
2057
2058 fn capabilities(&self) -> NodeCapabilities {
2059 NodeCapabilities::default()
2060 }
2061
2062 fn hash_code(&self) -> u64;
2063
2064 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool;
2065
2066 fn inspector_name(&self) -> &'static str;
2067
2068 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String));
2069
2070 fn requires_update(&self) -> bool;
2071
2072 fn auto_invalidates_on_update(&self) -> bool;
2073
2074 fn update_invalidation_kind(&self) -> Option<InvalidationKind>;
2075
2076 fn provides_composition_locals(&self) -> bool {
2078 false
2079 }
2080
2081 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2083 Vec::new()
2084 }
2085
2086 fn as_any(&self) -> &dyn Any;
2087}
2088
2089struct TypedModifierElement<E: ModifierNodeElement> {
2090 element: E,
2091 cached_hash: u64,
2092 provides_locals: bool,
2093}
2094
2095impl<E: ModifierNodeElement> TypedModifierElement<E> {
2096 fn new(element: E) -> Self {
2097 let mut hasher = default::new();
2098 element.hash(&mut hasher);
2099 let provides_locals = !element.provided_composition_locals().is_empty();
2100 Self {
2101 element,
2102 cached_hash: hasher.finish(),
2103 provides_locals,
2104 }
2105 }
2106}
2107
2108impl<E> fmt::Debug for TypedModifierElement<E>
2109where
2110 E: ModifierNodeElement,
2111{
2112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2113 f.debug_struct("TypedModifierElement")
2114 .field("type", &type_name::<E>())
2115 .finish()
2116 }
2117}
2118
2119impl<E> AnyModifierElement for TypedModifierElement<E>
2120where
2121 E: ModifierNodeElement,
2122{
2123 fn node_type(&self) -> TypeId {
2124 TypeId::of::<E::Node>()
2125 }
2126
2127 fn element_type(&self) -> TypeId {
2128 TypeId::of::<E>()
2129 }
2130
2131 fn create_node(&self) -> Rc<RefCell<dyn ModifierNode>> {
2132 Rc::new(RefCell::new(self.element.create()))
2133 }
2134
2135 fn can_update_node(&self, node: &dyn ModifierNode) -> bool {
2136 node.as_any().is::<E::Node>()
2137 }
2138
2139 fn update_node(&self, node: &mut dyn ModifierNode) {
2140 if let Some(typed) = node.as_any_mut().downcast_mut::<E::Node>() {
2141 self.element.update(typed);
2142 }
2143 }
2144
2145 fn key(&self) -> Option<u64> {
2146 self.element.key()
2147 }
2148
2149 fn capabilities(&self) -> NodeCapabilities {
2150 self.element.capabilities()
2151 }
2152
2153 fn provides_composition_locals(&self) -> bool {
2154 self.provides_locals
2155 }
2156
2157 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2158 self.element.provided_composition_locals()
2159 }
2160
2161 fn hash_code(&self) -> u64 {
2162 self.cached_hash
2163 }
2164
2165 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool {
2166 other
2167 .as_any()
2168 .downcast_ref::<Self>()
2169 .is_some_and(|typed| typed.element == self.element)
2170 }
2171
2172 fn inspector_name(&self) -> &'static str {
2173 self.element.inspector_name()
2174 }
2175
2176 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String)) {
2177 self.element.inspector_properties(visitor);
2178 }
2179
2180 fn requires_update(&self) -> bool {
2181 self.element.always_update()
2182 }
2183
2184 fn auto_invalidates_on_update(&self) -> bool {
2185 self.element.auto_invalidate_on_update()
2186 }
2187
2188 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
2189 self.element.update_invalidation_kind()
2190 }
2191
2192 fn as_any(&self) -> &dyn Any {
2193 self
2194 }
2195}
2196
2197fn request_update_auto_invalidations(
2198 element: &dyn AnyModifierElement,
2199 context: &mut dyn ModifierNodeContext,
2200 capabilities: NodeCapabilities,
2201) {
2202 if let Some(kind) = element.update_invalidation_kind() {
2203 let capabilities = NodeCapabilities::for_invalidation(kind);
2204 context.push_active_capabilities(capabilities);
2205 context.invalidate(kind);
2206 context.pop_active_capabilities();
2207 } else if element.auto_invalidates_on_update() {
2208 request_auto_invalidations(context, capabilities);
2209 }
2210}
2211
2212pub fn modifier_element<E: ModifierNodeElement>(element: E) -> DynModifierElement {
2215 Rc::new(TypedModifierElement::new(element))
2216}
2217
2218pub type DynModifierElement = Rc<dyn AnyModifierElement>;
2220
2221#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2222enum TraversalDirection {
2223 Forward,
2224 Backward,
2225}
2226
2227pub struct ModifierChainIter<'a> {
2232 chain: &'a ModifierNodeChain,
2233 cursor: usize,
2234 remaining: usize,
2235 direction: TraversalDirection,
2236}
2237
2238impl<'a> ModifierChainIter<'a> {
2239 fn forward(chain: &'a ModifierNodeChain) -> Self {
2240 Self {
2241 chain,
2242 cursor: 0,
2243 remaining: chain.ordered_nodes.len(),
2244 direction: TraversalDirection::Forward,
2245 }
2246 }
2247
2248 fn backward(chain: &'a ModifierNodeChain) -> Self {
2249 let len = chain.ordered_nodes.len();
2250 Self {
2251 chain,
2252 cursor: len.wrapping_sub(1),
2253 remaining: len,
2254 direction: TraversalDirection::Backward,
2255 }
2256 }
2257}
2258
2259impl<'a> Iterator for ModifierChainIter<'a> {
2260 type Item = ModifierChainNodeRef<'a>;
2261
2262 #[inline]
2263 fn next(&mut self) -> Option<Self::Item> {
2264 if self.remaining == 0 {
2265 return None;
2266 }
2267 let (link, caps, agg) = self.chain.ordered_nodes[self.cursor];
2268 let node_ref = self.chain.make_node_ref_with_caps(link, caps, agg);
2269 self.remaining -= 1;
2270 match self.direction {
2271 TraversalDirection::Forward => self.cursor += 1,
2272 TraversalDirection::Backward => self.cursor = self.cursor.wrapping_sub(1),
2273 }
2274 Some(node_ref)
2275 }
2276
2277 #[inline]
2278 fn size_hint(&self) -> (usize, Option<usize>) {
2279 (self.remaining, Some(self.remaining))
2280 }
2281}
2282
2283impl ExactSizeIterator for ModifierChainIter<'_> {}
2284impl std::iter::FusedIterator for ModifierChainIter<'_> {}
2285
2286#[derive(Debug)]
2287struct ModifierNodeEntry {
2288 key: Option<u64>,
2289 hash_code: u64,
2290 element: DynModifierElement,
2291 node: Rc<RefCell<dyn ModifierNode>>,
2292 capabilities: NodeCapabilities,
2293}
2294
2295impl ModifierNodeEntry {
2296 fn new(
2297 key: Option<u64>,
2298 element: DynModifierElement,
2299 node: Rc<RefCell<dyn ModifierNode>>,
2300 hash_code: u64,
2301 capabilities: NodeCapabilities,
2302 ) -> Self {
2303 let entry = Self {
2304 key,
2305 hash_code,
2306 element,
2307 node,
2308 capabilities,
2309 };
2310 entry
2311 .node
2312 .borrow()
2313 .node_state()
2314 .set_capabilities(entry.capabilities);
2315 entry
2316 }
2317}
2318
2319fn visit_node_tree_mut(
2320 node: &mut dyn ModifierNode,
2321 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
2322) {
2323 visitor(node);
2324 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
2325}
2326
2327fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
2328 let mut current = 0usize;
2329 let mut result: Option<&dyn ModifierNode> = None;
2330 node.for_each_delegate(&mut |child| {
2331 if result.is_none() && current == target {
2332 result = Some(child);
2333 }
2334 current += 1;
2335 });
2336 result
2337}
2338
2339fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
2340 let mut current = 0usize;
2341 let mut result: Option<&mut dyn ModifierNode> = None;
2342 node.for_each_delegate_mut(&mut |child| {
2343 if result.is_none() && current == target {
2344 result = Some(child);
2345 }
2346 current += 1;
2347 });
2348 result
2349}
2350
2351fn with_node_context<F, R>(
2352 node: &mut dyn ModifierNode,
2353 context: &mut dyn ModifierNodeContext,
2354 f: F,
2355) -> R
2356where
2357 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
2358{
2359 context.push_active_capabilities(node.node_state().capabilities());
2360 let result = f(node, context);
2361 context.pop_active_capabilities();
2362 result
2363}
2364
2365fn request_auto_invalidations(
2366 context: &mut dyn ModifierNodeContext,
2367 capabilities: NodeCapabilities,
2368) {
2369 if capabilities.is_empty() {
2370 return;
2371 }
2372
2373 context.push_active_capabilities(capabilities);
2374
2375 if capabilities.contains(NodeCapabilities::LAYOUT) {
2376 context.invalidate(InvalidationKind::Layout);
2377 }
2378 if capabilities.contains(NodeCapabilities::DRAW) {
2379 context.invalidate(InvalidationKind::Draw);
2380 }
2381 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
2382 context.invalidate(InvalidationKind::PointerInput);
2383 }
2384 if capabilities.contains(NodeCapabilities::SEMANTICS) {
2385 context.invalidate(InvalidationKind::Semantics);
2386 }
2387 if capabilities.contains(NodeCapabilities::FOCUS) {
2388 context.invalidate(InvalidationKind::Focus);
2389 }
2390
2391 context.pop_active_capabilities();
2392}
2393
2394fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
2395 visit_node_tree_mut(node, &mut |n| {
2396 if !n.node_state().is_attached() {
2397 n.node_state().set_attached(true);
2398 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
2399 }
2400 });
2401}
2402
2403fn reset_node_tree(node: &mut dyn ModifierNode) {
2404 visit_node_tree_mut(node, &mut |n| n.on_reset());
2405}
2406
2407fn detach_node_tree(node: &mut dyn ModifierNode) {
2408 visit_node_tree_mut(node, &mut |n| {
2409 if n.node_state().is_attached() {
2410 n.on_detach();
2411 n.node_state().set_attached(false);
2412 }
2413 n.node_state().set_parent_link(None);
2414 n.node_state().set_child_link(None);
2415 n.node_state()
2416 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2417 });
2418}
2419
2420pub struct ModifierNodeChain {
2427 entries: Vec<ModifierNodeEntry>,
2428 aggregated_capabilities: NodeCapabilities,
2429 head_aggregate_child_capabilities: NodeCapabilities,
2430 head_sentinel: SentinelNode,
2431 tail_sentinel: SentinelNode,
2432 ordered_nodes: Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
2433 attached: bool,
2437 links_cleared: bool,
2440}
2441
2442#[derive(Default)]
2446struct ReconcileScratch {
2447 old_used: Vec<bool>,
2448 match_order: Vec<Option<usize>>,
2449 final_slots: Vec<Option<ModifierNodeEntry>>,
2450 elements: Vec<DynModifierElement>,
2451}
2452
2453thread_local! {
2454 static RECONCILE_SCRATCH: std::cell::RefCell<ReconcileScratch> =
2455 std::cell::RefCell::default();
2456}
2457
2458struct SentinelNode {
2459 state: NodeState,
2460}
2461
2462impl SentinelNode {
2463 fn new() -> Self {
2464 Self {
2465 state: NodeState::sentinel(),
2466 }
2467 }
2468}
2469
2470impl DelegatableNode for SentinelNode {
2471 fn node_state(&self) -> &NodeState {
2472 &self.state
2473 }
2474}
2475
2476impl ModifierNode for SentinelNode {}
2477
2478#[derive(Clone)]
2479pub struct ModifierChainNodeRef<'a> {
2480 chain: &'a ModifierNodeChain,
2481 link: NodeLink,
2482 cached_capabilities: Option<NodeCapabilities>,
2483 cached_aggregate_child: Option<NodeCapabilities>,
2484}
2485
2486impl Default for ModifierNodeChain {
2487 fn default() -> Self {
2488 Self::new()
2489 }
2490}
2491
2492struct EntryIndex {
2493 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2494 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2495 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
2496}
2497
2498struct EntryMatchQuery<'a> {
2499 element_type: TypeId,
2500 node_type: TypeId,
2501 key: Option<u64>,
2502 hash_code: u64,
2503 element: &'a DynModifierElement,
2504}
2505
2506impl EntryIndex {
2507 fn build(entries: &[ModifierNodeEntry]) -> Self {
2508 let mut keyed = HashMap::default();
2509 let mut hashed = HashMap::default();
2510 let mut typed = HashMap::default();
2511
2512 for (i, entry) in entries.iter().enumerate() {
2513 let (element_type, node_type) =
2514 (entry.element.element_type(), entry.element.node_type());
2515 if let Some(key_value) = entry.key {
2516 keyed
2517 .entry((element_type, node_type, key_value))
2518 .or_insert_with(Vec::new)
2519 .push(i);
2520 } else {
2521 hashed
2522 .entry((element_type, node_type, entry.hash_code))
2523 .or_insert_with(Vec::new)
2524 .push(i);
2525 typed
2526 .entry((element_type, node_type))
2527 .or_insert_with(Vec::new)
2528 .push(i);
2529 }
2530 }
2531
2532 Self {
2533 keyed,
2534 hashed,
2535 typed,
2536 }
2537 }
2538
2539 fn find_match(
2540 &self,
2541 entries: &[ModifierNodeEntry],
2542 used: &[bool],
2543 query: EntryMatchQuery<'_>,
2544 ) -> Option<usize> {
2545 if let Some(key_value) = query.key {
2546 if let Some(candidates) =
2547 self.keyed
2548 .get(&(query.element_type, query.node_type, key_value))
2549 {
2550 for &i in candidates {
2551 if !used[i] {
2552 return Some(i);
2553 }
2554 }
2555 }
2556 } else {
2557 if let Some(candidates) =
2558 self.hashed
2559 .get(&(query.element_type, query.node_type, query.hash_code))
2560 {
2561 for &i in candidates {
2562 if !used[i]
2563 && entries[i]
2564 .element
2565 .as_ref()
2566 .equals_element(query.element.as_ref())
2567 {
2568 return Some(i);
2569 }
2570 }
2571 }
2572
2573 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
2574 for &i in candidates {
2575 if !used[i] {
2576 return Some(i);
2577 }
2578 }
2579 }
2580 }
2581
2582 None
2583 }
2584}
2585
2586fn update_entry_in_place(
2591 entry: &mut ModifierNodeEntry,
2592 element: &DynModifierElement,
2593 context: &mut dyn ModifierNodeContext,
2594) -> bool {
2595 if entry.element.element_type() != element.element_type()
2596 || entry.element.node_type() != element.node_type()
2597 || entry.key != element.key()
2598 || !element.can_update_node(&*entry.node.borrow())
2599 {
2600 return false;
2601 }
2602 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2603 let capabilities = element.capabilities();
2604 if !same_element || element.requires_update() {
2605 element.update_node(&mut *entry.node.borrow_mut());
2606 entry.element = element.clone();
2607 entry.hash_code = element.hash_code();
2608 request_update_auto_invalidations(element.as_ref(), context, capabilities);
2609 }
2610 entry.capabilities = capabilities;
2611 entry
2612 .node
2613 .borrow()
2614 .node_state()
2615 .set_capabilities(capabilities);
2616 true
2617}
2618
2619fn fresh_entry(
2622 element: DynModifierElement,
2623 context: &mut dyn ModifierNodeContext,
2624 attach: bool,
2625) -> ModifierNodeEntry {
2626 let capabilities = element.capabilities();
2627 let entry = ModifierNodeEntry::new(
2628 element.key(),
2629 element.clone(),
2630 element.create_node(),
2631 element.hash_code(),
2632 capabilities,
2633 );
2634 if attach {
2635 attach_node_tree(&mut *entry.node.borrow_mut(), context);
2636 }
2637 element.update_node(&mut *entry.node.borrow_mut());
2638 request_auto_invalidations(context, capabilities);
2639 entry
2640}
2641
2642fn reconcile_element(
2647 element: DynModifierElement,
2648 new_pos: usize,
2649 (old_entries, index): (&mut [ModifierNodeEntry], &EntryIndex),
2650 (used, match_order): (&mut [bool], &mut [Option<usize>]),
2651 context: &mut dyn ModifierNodeContext,
2652 attach: bool,
2653) -> Option<ModifierNodeEntry> {
2654 let element_type = element.element_type();
2655 let node_type = element.node_type();
2656 let key = element.key();
2657 let hash_code = element.hash_code();
2658 let capabilities = element.capabilities();
2659 let Some(idx) = index.find_match(
2660 old_entries,
2661 used,
2662 EntryMatchQuery {
2663 element_type,
2664 node_type,
2665 key,
2666 hash_code,
2667 element: &element,
2668 },
2669 ) else {
2670 return Some(fresh_entry(element, context, attach));
2671 };
2672 let entry = &mut old_entries[idx];
2673 if !element.can_update_node(&*entry.node.borrow()) {
2674 return Some(fresh_entry(element, context, attach));
2675 }
2676
2677 used[idx] = true;
2678 match_order[idx] = Some(new_pos);
2679 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2680 if !same_element || element.requires_update() {
2681 element.update_node(&mut *entry.node.borrow_mut());
2682 entry.element = element;
2683 entry.hash_code = hash_code;
2684 request_update_auto_invalidations(entry.element.as_ref(), context, capabilities);
2685 }
2686 if idx != new_pos {
2687 request_auto_invalidations(context, capabilities);
2688 }
2689 entry.key = key;
2690 entry.capabilities = capabilities;
2691 entry
2692 .node
2693 .borrow()
2694 .node_state()
2695 .set_capabilities(capabilities);
2696 None
2697}
2698
2699impl ModifierNodeChain {
2700 pub fn new() -> Self {
2702 let mut chain = Self::detached();
2703 chain.attached = true;
2704 chain
2705 }
2706
2707 pub fn detached() -> Self {
2710 let mut chain = Self {
2711 entries: Vec::new(),
2712 aggregated_capabilities: NodeCapabilities::empty(),
2713 head_aggregate_child_capabilities: NodeCapabilities::empty(),
2714 head_sentinel: SentinelNode::new(),
2715 tail_sentinel: SentinelNode::new(),
2716 ordered_nodes: Vec::new(),
2717 attached: false,
2718 links_cleared: false,
2719 };
2720 chain.sync_chain_links();
2721 chain
2722 }
2723
2724 pub fn detach_nodes(&mut self) {
2726 if !self.attached {
2727 return;
2728 }
2729 self.attached = false;
2730 for entry in &self.entries {
2731 detach_node_tree(&mut *entry.node.borrow_mut());
2732 }
2733 self.links_cleared = !self.entries.is_empty();
2734 }
2735
2736 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
2738 if self.attached {
2739 return;
2740 }
2741 self.attached = true;
2742 for entry in &self.entries {
2743 attach_node_tree(&mut *entry.node.borrow_mut(), context);
2744 }
2745 }
2746
2747 pub fn repair_chain(&mut self) {
2750 if self.links_cleared {
2751 self.sync_chain_links();
2752 }
2753 }
2754
2755 pub fn update_from_slice(
2761 &mut self,
2762 elements: &[DynModifierElement],
2763 context: &mut dyn ModifierNodeContext,
2764 ) {
2765 self.update_from_ref_iter(elements.iter(), context);
2766 }
2767
2768 pub fn update_entries_of_type<'a, I>(
2778 &mut self,
2779 elements: I,
2780 element_count: usize,
2781 element_type: TypeId,
2782 context: &mut dyn ModifierNodeContext,
2783 ) -> bool
2784 where
2785 I: Iterator<Item = &'a DynModifierElement>,
2786 {
2787 if element_count != self.entries.len() {
2788 return false;
2789 }
2790 self.entries
2791 .iter_mut()
2792 .zip(elements)
2793 .filter(|(_, element)| element.element_type() == element_type)
2794 .all(|(entry, element)| update_entry_in_place(entry, element, context))
2795 }
2796
2797 pub fn update_from_ref_iter<'a, I>(
2798 &mut self,
2799 elements: I,
2800 context: &mut dyn ModifierNodeContext,
2801 ) where
2802 I: Iterator<Item = &'a DynModifierElement>,
2803 {
2804 let mut scratch = RECONCILE_SCRATCH
2807 .try_with(|scratch| std::mem::take(&mut *scratch.borrow_mut()))
2808 .unwrap_or_default();
2809 self.reconcile(elements, context, &mut scratch);
2810 scratch.elements.clear();
2811 scratch.final_slots.clear();
2812 let _ = RECONCILE_SCRATCH.try_with(|slot| *slot.borrow_mut() = scratch);
2813 }
2814
2815 fn reconcile<'a, I>(
2816 &mut self,
2817 elements: I,
2818 context: &mut dyn ModifierNodeContext,
2819 scratch: &mut ReconcileScratch,
2820 ) where
2821 I: Iterator<Item = &'a DynModifierElement>,
2822 {
2823 let old_len = self.entries.len();
2824 let mut fast_path_failed_at: Option<usize> = None;
2825 let mut elements_count = 0;
2826
2827 scratch.elements.clear();
2828
2829 for (idx, element) in elements.enumerate() {
2830 elements_count = idx + 1;
2831 if fast_path_failed_at.is_none() && idx < old_len {
2832 if update_entry_in_place(&mut self.entries[idx], element, context) {
2833 continue;
2834 }
2835 fast_path_failed_at = Some(idx);
2836 }
2837 scratch.elements.push(element.clone());
2838 }
2839
2840 if fast_path_failed_at.is_none() && scratch.elements.is_empty() {
2841 if elements_count < self.entries.len() {
2842 for entry in self.entries.drain(elements_count..) {
2843 request_auto_invalidations(context, entry.capabilities);
2844 detach_node_tree(&mut *entry.node.borrow_mut());
2845 }
2846 }
2847 self.sync_chain_links();
2848 return;
2849 }
2850
2851 self.rebuild_tail(fast_path_failed_at.unwrap_or(old_len), context, scratch);
2852 }
2853
2854 fn rebuild_tail(
2858 &mut self,
2859 fail_idx: usize,
2860 context: &mut dyn ModifierNodeContext,
2861 scratch: &mut ReconcileScratch,
2862 ) {
2863 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
2864 let processed_entries_len = self.entries.len();
2865 let old_len = old_entries.len();
2866
2867 scratch.old_used.clear();
2868 scratch.old_used.resize(old_len, false);
2869
2870 scratch.match_order.clear();
2871 scratch.match_order.resize(old_len, None);
2872
2873 let index = EntryIndex::build(&old_entries);
2874
2875 let new_elements_count = scratch.elements.len();
2876 scratch.final_slots.clear();
2877 scratch.final_slots.reserve(new_elements_count);
2878
2879 for (new_pos, element) in scratch.elements.drain(..).enumerate() {
2880 let fresh = reconcile_element(
2881 element,
2882 new_pos,
2883 (&mut old_entries, &index),
2884 (&mut scratch.old_used, &mut scratch.match_order),
2885 context,
2886 self.attached,
2887 );
2888 scratch.final_slots.push(fresh);
2889 }
2890
2891 for (i, entry) in old_entries.into_iter().enumerate() {
2892 match scratch.match_order[i] {
2893 Some(pos) if scratch.old_used[i] => scratch.final_slots[pos] = Some(entry),
2894 _ => {
2895 request_auto_invalidations(context, entry.capabilities);
2896 detach_node_tree(&mut *entry.node.borrow_mut());
2897 }
2898 }
2899 }
2900
2901 self.entries.reserve_exact(scratch.final_slots.len());
2905 for slot in scratch.final_slots.drain(..) {
2906 if let Some(entry) = slot {
2907 self.entries.push(entry);
2908 } else {
2909 log::error!("modifier reconciliation produced an empty final slot");
2910 }
2911 }
2912
2913 debug_assert_eq!(
2914 self.entries.len(),
2915 processed_entries_len + new_elements_count
2916 );
2917 self.sync_chain_links();
2918 }
2919
2920 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
2924 where
2925 I: IntoIterator<Item = DynModifierElement>,
2926 {
2927 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
2928 self.update_from_slice(&collected, context);
2929 }
2930
2931 pub fn reset(&mut self) {
2934 for entry in &mut self.entries {
2935 reset_node_tree(&mut *entry.node.borrow_mut());
2936 }
2937 }
2938
2939 pub fn detach_all(&mut self) {
2941 for entry in std::mem::take(&mut self.entries) {
2942 detach_node_tree(&mut *entry.node.borrow_mut());
2943 {
2944 let node_borrow = entry.node.borrow();
2945 let state = node_borrow.node_state();
2946 state.set_capabilities(NodeCapabilities::empty());
2947 }
2948 }
2949 self.aggregated_capabilities = NodeCapabilities::empty();
2950 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2951 self.ordered_nodes.clear();
2952 self.sync_chain_links();
2953 }
2954
2955 pub fn len(&self) -> usize {
2956 self.entries.len()
2957 }
2958
2959 pub fn is_empty(&self) -> bool {
2960 self.entries.is_empty()
2961 }
2962
2963 pub fn capabilities(&self) -> NodeCapabilities {
2965 self.aggregated_capabilities
2966 }
2967
2968 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
2970 self.aggregated_capabilities.contains(capability)
2971 }
2972
2973 pub fn head(&self) -> ModifierChainNodeRef<'_> {
2975 self.make_node_ref(NodeLink::Head)
2976 }
2977
2978 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
2980 self.make_node_ref(NodeLink::Tail)
2981 }
2982
2983 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
2985 ModifierChainIter::forward(self)
2986 }
2987
2988 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
2990 ModifierChainIter::backward(self)
2991 }
2992
2993 pub fn for_each_forward<F>(&self, mut f: F)
2995 where
2996 F: FnMut(ModifierChainNodeRef<'_>),
2997 {
2998 for node in self.head_to_tail() {
2999 f(node);
3000 }
3001 }
3002
3003 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
3005 where
3006 F: FnMut(ModifierChainNodeRef<'_>),
3007 {
3008 if mask.is_empty() {
3009 self.for_each_forward(f);
3010 return;
3011 }
3012
3013 if !self.head().aggregate_child_capabilities().intersects(mask) {
3014 return;
3015 }
3016
3017 for node in self.head_to_tail() {
3018 if node.kind_set().intersects(mask) {
3019 f(node);
3020 }
3021 }
3022 }
3023
3024 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
3026 where
3027 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
3028 {
3029 self.for_each_forward_matching(mask, |node_ref| {
3030 node_ref.with_node(|node| f(node_ref.clone(), node));
3031 });
3032 }
3033
3034 pub fn for_each_backward<F>(&self, mut f: F)
3036 where
3037 F: FnMut(ModifierChainNodeRef<'_>),
3038 {
3039 for node in self.tail_to_head() {
3040 f(node);
3041 }
3042 }
3043
3044 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
3046 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
3047 node as *const dyn ModifierNode as *const ()
3048 }
3049
3050 let target = node_data_ptr(node);
3051 for (index, entry) in self.entries.iter().enumerate() {
3052 if node_data_ptr(&*entry.node.borrow()) == target {
3053 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
3054 }
3055 }
3056
3057 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
3058 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
3059 return None;
3060 }
3061 let matches_target = match link {
3062 NodeLink::Head => node_data_ptr(&self.head_sentinel) == target,
3063 NodeLink::Tail => node_data_ptr(&self.tail_sentinel) == target,
3064 NodeLink::Entry(path) => {
3065 let node_borrow = self.entries[path.entry()].node.borrow();
3066 node_data_ptr(&*node_borrow) == target
3067 }
3068 };
3069 if matches_target {
3070 Some(self.make_node_ref(*link))
3071 } else {
3072 None
3073 }
3074 })
3075 }
3076
3077 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
3080 self.entries.get(index).and_then(|entry| {
3081 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
3082 boxed_node.as_any().downcast_ref::<N>()
3083 })
3084 .ok()
3085 })
3086 }
3087
3088 pub fn node_mut<N: ModifierNode + 'static>(
3091 &self,
3092 index: usize,
3093 ) -> Option<std::cell::RefMut<'_, N>> {
3094 self.entries.get(index).and_then(|entry| {
3095 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
3096 boxed_node.as_any_mut().downcast_mut::<N>()
3097 })
3098 .ok()
3099 })
3100 }
3101
3102 pub fn get_node_rc(&self, index: usize) -> Option<&Rc<RefCell<dyn ModifierNode>>> {
3105 self.entries.get(index).map(|entry| &entry.node)
3106 }
3107
3108 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
3110 self.aggregated_capabilities
3111 .contains(NodeCapabilities::for_invalidation(kind))
3112 }
3113
3114 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
3116 where
3117 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
3118 {
3119 for index in 0..self.ordered_nodes.len() {
3120 let (link, cached_caps, _agg) = self.ordered_nodes[index];
3121 match link {
3122 NodeLink::Head => {
3123 f(&mut self.head_sentinel, cached_caps);
3124 }
3125 NodeLink::Tail => {
3126 f(&mut self.tail_sentinel, cached_caps);
3127 }
3128 NodeLink::Entry(path) => {
3129 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
3130 if path.delegates().is_empty() {
3131 f(&mut *node_borrow, cached_caps);
3132 } else {
3133 let mut current: &mut dyn ModifierNode = &mut *node_borrow;
3134 for &delegate_index in path.delegates() {
3135 if let Some(delegate) =
3136 nth_delegate_mut(current, delegate_index as usize)
3137 {
3138 current = delegate;
3139 } else {
3140 return;
3141 }
3142 }
3143 f(current, cached_caps);
3144 }
3145 }
3146 }
3147 }
3148 }
3149
3150 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
3151 ModifierChainNodeRef {
3152 chain: self,
3153 link,
3154 cached_capabilities: None,
3155 cached_aggregate_child: None,
3156 }
3157 }
3158
3159 fn make_node_ref_with_caps(
3160 &self,
3161 link: NodeLink,
3162 caps: NodeCapabilities,
3163 aggregate_child: NodeCapabilities,
3164 ) -> ModifierChainNodeRef<'_> {
3165 ModifierChainNodeRef {
3166 chain: self,
3167 link,
3168 cached_capabilities: Some(caps),
3169 cached_aggregate_child: Some(aggregate_child),
3170 }
3171 }
3172
3173 fn sync_chain_links(&mut self) {
3174 self.links_cleared = false;
3175 self.rebuild_ordered_nodes();
3176
3177 self.head_sentinel.node_state().set_parent_link(None);
3178 self.tail_sentinel.node_state().set_child_link(None);
3179
3180 if self.ordered_nodes.is_empty() {
3181 self.head_sentinel
3182 .node_state()
3183 .set_child_link(Some(NodeLink::Tail));
3184 self.tail_sentinel
3185 .node_state()
3186 .set_parent_link(Some(NodeLink::Head));
3187 self.aggregated_capabilities = NodeCapabilities::empty();
3188 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
3189 self.head_sentinel
3190 .node_state()
3191 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3192 self.tail_sentinel
3193 .node_state()
3194 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3195 return;
3196 }
3197
3198 let mut previous = NodeLink::Head;
3199 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
3200 match &previous {
3201 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
3202 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
3203 NodeLink::Entry(path) => {
3204 let node_borrow = self.entries[path.entry()].node.borrow();
3205 if path.delegates().is_empty() {
3206 node_borrow.node_state().set_child_link(Some(link));
3207 } else {
3208 let mut current: &dyn ModifierNode = &*node_borrow;
3209 for &delegate_index in path.delegates() {
3210 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3211 current = delegate;
3212 }
3213 }
3214 current.node_state().set_child_link(Some(link));
3215 }
3216 }
3217 }
3218 match &link {
3219 NodeLink::Head => self
3220 .head_sentinel
3221 .node_state()
3222 .set_parent_link(Some(previous)),
3223 NodeLink::Tail => self
3224 .tail_sentinel
3225 .node_state()
3226 .set_parent_link(Some(previous)),
3227 NodeLink::Entry(path) => {
3228 let node_borrow = self.entries[path.entry()].node.borrow();
3229 if path.delegates().is_empty() {
3230 node_borrow.node_state().set_parent_link(Some(previous));
3231 } else {
3232 let mut current: &dyn ModifierNode = &*node_borrow;
3233 for &delegate_index in path.delegates() {
3234 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3235 current = delegate;
3236 }
3237 }
3238 current.node_state().set_parent_link(Some(previous));
3239 }
3240 }
3241 }
3242 previous = link;
3243 }
3244
3245 match &previous {
3246 NodeLink::Head => self
3247 .head_sentinel
3248 .node_state()
3249 .set_child_link(Some(NodeLink::Tail)),
3250 NodeLink::Tail => self
3251 .tail_sentinel
3252 .node_state()
3253 .set_child_link(Some(NodeLink::Tail)),
3254 NodeLink::Entry(path) => {
3255 let node_borrow = self.entries[path.entry()].node.borrow();
3256 if path.delegates().is_empty() {
3257 node_borrow
3258 .node_state()
3259 .set_child_link(Some(NodeLink::Tail));
3260 } else {
3261 let mut current: &dyn ModifierNode = &*node_borrow;
3262 for &delegate_index in path.delegates() {
3263 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3264 current = delegate;
3265 }
3266 }
3267 current.node_state().set_child_link(Some(NodeLink::Tail));
3268 }
3269 }
3270 }
3271 self.tail_sentinel
3272 .node_state()
3273 .set_parent_link(Some(previous));
3274 self.tail_sentinel.node_state().set_child_link(None);
3275
3276 let mut aggregate = NodeCapabilities::empty();
3277 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
3278 aggregate |= *cached_caps;
3279 *cached_aggregate = aggregate;
3280 match link {
3281 NodeLink::Head => {
3282 self.head_sentinel
3283 .node_state()
3284 .set_aggregate_child_capabilities(aggregate);
3285 }
3286 NodeLink::Tail => {
3287 self.tail_sentinel
3288 .node_state()
3289 .set_aggregate_child_capabilities(aggregate);
3290 }
3291 NodeLink::Entry(path) => {
3292 let node_borrow = self.entries[path.entry()].node.borrow();
3293 let state = if path.delegates().is_empty() {
3294 node_borrow.node_state()
3295 } else {
3296 let mut current: &dyn ModifierNode = &*node_borrow;
3297 for &delegate_index in path.delegates() {
3298 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3299 current = delegate;
3300 }
3301 }
3302 current.node_state()
3303 };
3304 state.set_aggregate_child_capabilities(aggregate);
3305 }
3306 }
3307 }
3308
3309 self.aggregated_capabilities = aggregate;
3310 self.head_aggregate_child_capabilities = aggregate;
3311 self.head_sentinel
3312 .node_state()
3313 .set_aggregate_child_capabilities(aggregate);
3314 self.tail_sentinel
3315 .node_state()
3316 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3317 }
3318
3319 fn rebuild_ordered_nodes(&mut self) {
3320 self.ordered_nodes.clear();
3321 self.ordered_nodes.reserve_exact(self.entries.len());
3323 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
3324 for (index, entry) in self.entries.iter().enumerate() {
3325 let node_borrow = entry.node.borrow();
3326 Self::enumerate_link_order(
3327 &*node_borrow,
3328 index,
3329 &mut path_buf,
3330 0,
3331 &mut self.ordered_nodes,
3332 );
3333 }
3334 }
3335
3336 fn enumerate_link_order(
3337 node: &dyn ModifierNode,
3338 entry: usize,
3339 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
3340 path_len: usize,
3341 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
3342 ) {
3343 let caps = node.node_state().capabilities();
3344 out.push((
3345 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
3346 caps,
3347 NodeCapabilities::empty(),
3348 ));
3349 let mut delegate_index = 0usize;
3350 node.for_each_delegate(&mut |child| {
3351 if path_len < MAX_DELEGATE_DEPTH {
3352 path_buf[path_len] = delegate_index;
3353 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
3354 }
3355 delegate_index += 1;
3356 });
3357 }
3358}
3359
3360impl<'a> ModifierChainNodeRef<'a> {
3361 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
3362 match &self.link {
3363 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
3364 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
3365 NodeLink::Entry(path) => {
3366 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3367 if path.delegates().is_empty() {
3368 f(node_borrow.node_state())
3369 } else {
3370 let mut current: &dyn ModifierNode = &*node_borrow;
3371 for &delegate_index in path.delegates() {
3372 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3373 current = delegate;
3374 } else {
3375 return f(node_borrow.node_state());
3376 }
3377 }
3378 f(current.node_state())
3379 }
3380 }
3381 }
3382 }
3383
3384 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
3387 match &self.link {
3388 NodeLink::Head => None,
3389 NodeLink::Tail => None,
3390 NodeLink::Entry(path) => {
3391 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3392 if path.delegates().is_empty() {
3393 Some(f(&*node_borrow))
3394 } else {
3395 let mut current: &dyn ModifierNode = &*node_borrow;
3396 for &delegate_index in path.delegates() {
3397 current = nth_delegate(current, delegate_index as usize)?;
3398 }
3399 Some(f(current))
3400 }
3401 }
3402 }
3403 }
3404
3405 #[inline]
3407 pub fn parent(&self) -> Option<Self> {
3408 self.with_state(NodeState::parent_link)
3409 .map(|link| self.chain.make_node_ref(link))
3410 }
3411
3412 #[inline]
3414 pub fn child(&self) -> Option<Self> {
3415 self.with_state(NodeState::child_link)
3416 .map(|link| self.chain.make_node_ref(link))
3417 }
3418
3419 #[inline]
3421 pub fn kind_set(&self) -> NodeCapabilities {
3422 if let Some(caps) = self.cached_capabilities {
3423 return caps;
3424 }
3425 match &self.link {
3426 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
3427 NodeLink::Entry(_) => self.with_state(NodeState::capabilities),
3428 }
3429 }
3430
3431 pub fn entry_index(&self) -> Option<usize> {
3433 match &self.link {
3434 NodeLink::Entry(path) => Some(path.entry()),
3435 _ => None,
3436 }
3437 }
3438
3439 pub fn delegate_depth(&self) -> usize {
3441 match &self.link {
3442 NodeLink::Entry(path) => path.delegates().len(),
3443 _ => 0,
3444 }
3445 }
3446
3447 #[inline]
3449 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
3450 if let Some(agg) = self.cached_aggregate_child {
3451 return agg;
3452 }
3453 if self.is_tail() {
3454 NodeCapabilities::empty()
3455 } else {
3456 self.with_state(NodeState::aggregate_child_capabilities)
3457 }
3458 }
3459
3460 pub fn is_head(&self) -> bool {
3462 matches!(self.link, NodeLink::Head)
3463 }
3464
3465 pub fn is_tail(&self) -> bool {
3467 matches!(self.link, NodeLink::Tail)
3468 }
3469
3470 pub fn is_sentinel(&self) -> bool {
3472 matches!(self.link, NodeLink::Head | NodeLink::Tail)
3473 }
3474
3475 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
3477 !mask.is_empty() && self.kind_set().intersects(mask)
3478 }
3479
3480 pub fn visit_descendants<F>(self, include_self: bool, mut f: F)
3482 where
3483 F: FnMut(ModifierChainNodeRef<'a>),
3484 {
3485 let mut current = if include_self {
3486 Some(self)
3487 } else {
3488 self.child()
3489 };
3490 while let Some(node) = current {
3491 if node.is_tail() {
3492 break;
3493 }
3494 if !node.is_sentinel() {
3495 f(node.clone());
3496 }
3497 current = node.child();
3498 }
3499 }
3500
3501 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3503 where
3504 F: FnMut(ModifierChainNodeRef<'a>),
3505 {
3506 if mask.is_empty() {
3507 self.visit_descendants(include_self, f);
3508 return;
3509 }
3510
3511 if !self.aggregate_child_capabilities().intersects(mask) {
3512 return;
3513 }
3514
3515 self.visit_descendants(include_self, |node| {
3516 if node.kind_set().intersects(mask) {
3517 f(node);
3518 }
3519 });
3520 }
3521
3522 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
3524 where
3525 F: FnMut(ModifierChainNodeRef<'a>),
3526 {
3527 let mut current = if include_self {
3528 Some(self)
3529 } else {
3530 self.parent()
3531 };
3532 while let Some(node) = current {
3533 if node.is_head() {
3534 break;
3535 }
3536 f(node.clone());
3537 current = node.parent();
3538 }
3539 }
3540
3541 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3543 where
3544 F: FnMut(ModifierChainNodeRef<'a>),
3545 {
3546 if mask.is_empty() {
3547 self.visit_ancestors(include_self, f);
3548 return;
3549 }
3550
3551 self.visit_ancestors(include_self, |node| {
3552 if node.kind_set().intersects(mask) {
3553 f(node);
3554 }
3555 });
3556 }
3557}
3558
3559#[cfg(test)]
3560#[path = "tests/modifier_tests.rs"]
3561mod tests;