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 test_tag: Option<String>,
1452 pub live_region: Option<LiveRegionMode>,
1455 pub progress: Option<ProgressBarRangeInfo>,
1458 pub set_progress: Option<SemanticsSetProgress>,
1461 pub set_text: Option<SemanticsSetText>,
1464 pub set_selection: Option<SemanticsSetSelection>,
1467 pub expand: Option<SemanticsExpand>,
1470 pub dismiss: Option<SemanticsDismiss>,
1474 pub collapse: Option<SemanticsExpand>,
1477 pub vertical_scroll: Option<ScrollAxisRange>,
1480 pub horizontal_scroll: Option<ScrollAxisRange>,
1483 pub scroll_by: Option<SemanticsScrollBy>,
1486 pub scroll_to_index: Option<SemanticsScrollToIndex>,
1490 pub collection: Option<CollectionInfo>,
1492}
1493
1494impl Default for SemanticsConfiguration {
1495 fn default() -> Self {
1496 Self {
1497 content_description: None,
1498 state_description: None,
1499 on_click_label: None,
1500 on_click: None,
1501 on_long_click: None,
1502 on_long_click_label: None,
1503 on_magic_tap: None,
1504 on_magic_tap_label: None,
1505 input_labels: Vec::new(),
1506 language: None,
1507 role: None,
1508 selected: None,
1509 toggled: None,
1510 enabled: true,
1511 is_clickable: false,
1512 is_editable_text: false,
1513 multiline: false,
1514 text: None,
1515 text_selection: None,
1516 custom_actions: Vec::new(),
1517 canvas_children: Vec::new(),
1518 is_modal: false,
1519 hidden: false,
1520 merge_descendants: false,
1521 selectable_group: false,
1522 pane_title: None,
1523 error: None,
1524 password: false,
1525 traversal_index: 0.0,
1526 test_tag: None,
1527 live_region: None,
1528 progress: None,
1529 set_progress: None,
1530 set_text: None,
1531 set_selection: None,
1532 expand: None,
1533 dismiss: None,
1534 collapse: None,
1535 vertical_scroll: None,
1536 horizontal_scroll: None,
1537 scroll_by: None,
1538 scroll_to_index: None,
1539 collection: None,
1540 }
1541 }
1542}
1543
1544pub type SemanticsSpec = SemanticsConfiguration;
1553
1554impl SemanticsConfiguration {
1555 pub fn new() -> Self {
1558 Self::default()
1559 }
1560
1561 pub fn content_description(mut self, name: impl Into<String>) -> Self {
1564 self.content_description = Some(name.into());
1565 self
1566 }
1567
1568 pub fn test_tag(mut self, tag: impl Into<String>) -> Self {
1571 self.test_tag = Some(tag.into());
1572 self
1573 }
1574
1575 pub fn state_description(mut self, state: impl Into<String>) -> Self {
1578 self.state_description = Some(state.into());
1579 self
1580 }
1581
1582 pub fn clickable(mut self) -> Self {
1584 self.is_clickable = true;
1585 self
1586 }
1587
1588 pub fn on_click(mut self, label: impl Into<String>, action: impl Fn() + 'static) -> Self {
1591 self.on_click = Some(SemanticsCustomAction::new(label, action));
1592 self
1593 }
1594
1595 pub fn on_long_click(
1599 mut self,
1600 label: impl Into<String>,
1601 action: impl Fn() -> bool + 'static,
1602 ) -> Self {
1603 self.on_long_click_label = Some(label.into());
1604 self.on_long_click = Some(SemanticsLongClick::new(action));
1605 self
1606 }
1607
1608 pub fn on_magic_tap(
1612 mut self,
1613 label: impl Into<String>,
1614 action: impl Fn() -> bool + 'static,
1615 ) -> Self {
1616 self.on_magic_tap_label = Some(label.into());
1617 self.on_magic_tap = Some(SemanticsMagicTap::new(action));
1618 self
1619 }
1620
1621 pub fn input_labels<S: Into<String>>(mut self, labels: impl IntoIterator<Item = S>) -> Self {
1624 self.input_labels = labels.into_iter().map(Into::into).collect();
1625 self
1626 }
1627
1628 pub fn language(mut self, tag: impl Into<String>) -> Self {
1631 self.language = Some(tag.into());
1632 self
1633 }
1634
1635 pub fn toggled(mut self, toggled: bool) -> Self {
1637 self.toggled = Some(toggled);
1638 self
1639 }
1640
1641 pub fn selected(mut self, selected: bool) -> Self {
1644 self.selected = Some(selected);
1645 self
1646 }
1647
1648 pub fn role(mut self, role: SemanticsWidgetRole) -> Self {
1650 self.role = Some(role);
1651 self
1652 }
1653
1654 pub fn heading(self) -> Self {
1657 self.role(SemanticsWidgetRole::Header)
1658 }
1659
1660 pub fn error(mut self, message: impl Into<String>) -> Self {
1662 self.error = Some(message.into());
1663 self
1664 }
1665
1666 pub fn password(mut self) -> Self {
1668 self.password = true;
1669 self
1670 }
1671
1672 pub fn pane_title(mut self, title: impl Into<String>) -> Self {
1675 self.pane_title = Some(title.into());
1676 self
1677 }
1678
1679 pub fn traversal_index(mut self, index: f32) -> Self {
1682 self.traversal_index = index;
1683 self
1684 }
1685
1686 pub fn hidden(mut self) -> Self {
1689 self.hidden = true;
1690 self
1691 }
1692
1693 pub fn merge_descendants(mut self) -> Self {
1696 self.merge_descendants = true;
1697 self
1698 }
1699
1700 pub fn selectable_group(mut self) -> Self {
1703 self.selectable_group = true;
1704 self
1705 }
1706
1707 pub fn live_region(mut self, mode: LiveRegionMode) -> Self {
1710 self.live_region = Some(mode);
1711 self
1712 }
1713 pub fn merge(&mut self, other: &SemanticsConfiguration) {
1714 if let Some(description) = &other.content_description {
1715 self.content_description = Some(description.clone());
1716 }
1717 if let Some(state) = &other.state_description {
1718 self.state_description = Some(state.clone());
1719 }
1720 if let Some(label) = &other.on_click_label {
1721 self.on_click_label = Some(label.clone());
1722 }
1723 if let Some(label) = &other.on_long_click_label {
1724 self.on_long_click_label = Some(label.clone());
1725 }
1726 if let Some(label) = &other.on_magic_tap_label {
1727 self.on_magic_tap_label = Some(label.clone());
1728 }
1729 if !other.input_labels.is_empty() {
1730 self.input_labels.clone_from(&other.input_labels);
1731 }
1732 if let Some(language) = &other.language {
1733 self.language = Some(language.clone());
1734 }
1735 if let Some(role) = other.role {
1736 self.role = Some(role);
1737 }
1738 if let Some(selected) = other.selected {
1739 self.selected = Some(selected);
1740 }
1741 if let Some(toggled) = other.toggled {
1742 self.toggled = Some(toggled);
1743 }
1744 self.enabled &= other.enabled;
1745 self.is_clickable |= other.is_clickable;
1746 self.is_editable_text |= other.is_editable_text;
1747 self.multiline |= other.multiline;
1748 if let Some(text) = &other.text {
1749 self.text = Some(text.clone());
1750 }
1751 self.is_modal |= other.is_modal;
1752 self.hidden |= other.hidden;
1753 self.merge_descendants |= other.merge_descendants;
1754 self.selectable_group |= other.selectable_group;
1755 self.password |= other.password;
1756 if other.traversal_index != 0.0 {
1757 self.traversal_index = other.traversal_index;
1758 }
1759 if let Some(live_region) = other.live_region {
1760 self.live_region = Some(live_region);
1761 }
1762 self.merge_words(other);
1763 self.merge_actions(other);
1764 self.merge_ranges(other);
1765 }
1766
1767 fn merge_words(&mut self, other: &SemanticsConfiguration) {
1768 if let Some(title) = &other.pane_title {
1769 self.pane_title = Some(title.clone());
1770 }
1771 if let Some(error) = &other.error {
1772 self.error = Some(error.clone());
1773 }
1774 if let Some(tag) = &other.test_tag {
1775 self.test_tag = Some(tag.clone());
1776 }
1777 }
1778
1779 fn merge_actions(&mut self, other: &SemanticsConfiguration) {
1780 if let Some(on_click) = &other.on_click {
1781 self.on_click = Some(on_click.clone());
1782 }
1783 self.custom_actions
1784 .extend(other.custom_actions.iter().cloned());
1785 self.canvas_children
1786 .extend(other.canvas_children.iter().cloned());
1787 if let Some(set_progress) = &other.set_progress {
1788 self.set_progress = Some(set_progress.clone());
1789 }
1790 if let Some(set_text) = &other.set_text {
1791 self.set_text = Some(set_text.clone());
1792 }
1793 if let Some(set_selection) = &other.set_selection {
1794 self.set_selection = Some(set_selection.clone());
1795 }
1796 if let Some(expand) = &other.expand {
1797 self.expand = Some(expand.clone());
1798 }
1799 if let Some(collapse) = &other.collapse {
1800 self.collapse = Some(collapse.clone());
1801 }
1802 if let Some(dismiss) = &other.dismiss {
1803 self.dismiss = Some(dismiss.clone());
1804 }
1805 if let Some(long_click) = &other.on_long_click {
1806 self.on_long_click = Some(long_click.clone());
1807 }
1808 if let Some(magic_tap) = &other.on_magic_tap {
1809 self.on_magic_tap = Some(magic_tap.clone());
1810 }
1811 if let Some(scroll_by) = &other.scroll_by {
1812 self.scroll_by = Some(scroll_by.clone());
1813 }
1814 if let Some(scroll_to_index) = &other.scroll_to_index {
1815 self.scroll_to_index = Some(scroll_to_index.clone());
1816 }
1817 }
1818
1819 fn merge_ranges(&mut self, other: &SemanticsConfiguration) {
1820 if let Some(selection) = other.text_selection {
1821 self.text_selection = Some(selection);
1822 }
1823 if let Some(progress) = other.progress {
1824 self.progress = Some(progress);
1825 }
1826 if let Some(range) = other.vertical_scroll {
1827 self.vertical_scroll = Some(range);
1828 }
1829 if let Some(range) = other.horizontal_scroll {
1830 self.horizontal_scroll = Some(range);
1831 }
1832 if let Some(collection) = other.collection {
1833 self.collection = Some(collection);
1834 }
1835 }
1836
1837 pub fn is_activatable(&self) -> bool {
1840 self.is_clickable || self.on_click_label.is_some() || self.on_click.is_some()
1841 }
1842}
1843
1844impl fmt::Debug for dyn ModifierNode {
1845 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1846 f.debug_struct("ModifierNode").finish_non_exhaustive()
1847 }
1848}
1849
1850impl dyn ModifierNode {
1851 pub fn as_any(&self) -> &dyn Any {
1852 self
1853 }
1854
1855 pub fn as_any_mut(&mut self) -> &mut dyn Any {
1856 self
1857 }
1858}
1859
1860pub trait ModifierNodeElement: fmt::Debug + Hash + PartialEq + 'static {
1863 type Node: ModifierNode;
1864
1865 fn create(&self) -> Self::Node;
1867
1868 fn update(&self, node: &mut Self::Node);
1870
1871 fn key(&self) -> Option<u64> {
1873 None
1874 }
1875
1876 fn inspector_name(&self) -> &'static str {
1878 type_name::<Self>()
1879 }
1880
1881 fn inspector_properties(&self, _inspector: &mut dyn FnMut(&'static str, String)) {}
1883
1884 fn capabilities(&self) -> NodeCapabilities {
1887 NodeCapabilities::default()
1888 }
1889
1890 fn always_update(&self) -> bool {
1896 false
1897 }
1898
1899 fn auto_invalidate_on_update(&self) -> bool {
1902 true
1903 }
1904
1905 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
1912 None
1913 }
1914
1915 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
1922 Vec::new()
1923 }
1924}
1925
1926#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1928pub struct NodeCapabilities(u32);
1929
1930impl NodeCapabilities {
1931 pub const NONE: Self = Self(0);
1933 pub const LAYOUT: Self = Self(1 << 0);
1935 pub const DRAW: Self = Self(1 << 1);
1937 pub const POINTER_INPUT: Self = Self(1 << 2);
1939 pub const SEMANTICS: Self = Self(1 << 3);
1941 pub const MODIFIER_LOCALS: Self = Self(1 << 4);
1943 pub const FOCUS: Self = Self(1 << 5);
1945 pub const WINDOW_ROOT: Self = Self(1 << 6);
1949 pub const KEY_INPUT: Self = Self(1 << 7);
1951
1952 pub const fn empty() -> Self {
1954 Self::NONE
1955 }
1956
1957 pub const fn contains(self, other: Self) -> bool {
1959 (self.0 & other.0) == other.0
1960 }
1961
1962 pub const fn intersects(self, other: Self) -> bool {
1964 (self.0 & other.0) != 0
1965 }
1966
1967 pub fn insert(&mut self, other: Self) {
1969 self.0 |= other.0;
1970 }
1971
1972 pub const fn bits(self) -> u32 {
1974 self.0
1975 }
1976
1977 pub const fn is_empty(self) -> bool {
1979 self.0 == 0
1980 }
1981
1982 pub const fn for_invalidation(kind: InvalidationKind) -> Self {
1984 match kind {
1985 InvalidationKind::Layout => Self::LAYOUT,
1986 InvalidationKind::Draw => Self::DRAW,
1987 InvalidationKind::PointerInput => Self::POINTER_INPUT,
1988 InvalidationKind::Semantics => Self::SEMANTICS,
1989 InvalidationKind::Focus => Self::FOCUS,
1990 }
1991 }
1992}
1993
1994impl Default for NodeCapabilities {
1995 fn default() -> Self {
1996 Self::NONE
1997 }
1998}
1999
2000impl fmt::Debug for NodeCapabilities {
2001 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2002 f.debug_struct("NodeCapabilities")
2003 .field("layout", &self.contains(Self::LAYOUT))
2004 .field("draw", &self.contains(Self::DRAW))
2005 .field("pointer_input", &self.contains(Self::POINTER_INPUT))
2006 .field("semantics", &self.contains(Self::SEMANTICS))
2007 .field("modifier_locals", &self.contains(Self::MODIFIER_LOCALS))
2008 .field("focus", &self.contains(Self::FOCUS))
2009 .field("window_root", &self.contains(Self::WINDOW_ROOT))
2010 .field("key_input", &self.contains(Self::KEY_INPUT))
2011 .finish()
2012 }
2013}
2014
2015impl BitOr for NodeCapabilities {
2016 type Output = Self;
2017
2018 fn bitor(self, rhs: Self) -> Self::Output {
2019 Self(self.0 | rhs.0)
2020 }
2021}
2022
2023impl BitOrAssign for NodeCapabilities {
2024 fn bitor_assign(&mut self, rhs: Self) {
2025 self.0 |= rhs.0;
2026 }
2027}
2028
2029pub type ModifierInvalidations = smallvec::SmallVec<[ModifierInvalidation; 5]>;
2032
2033#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2035pub struct ModifierInvalidation {
2036 kind: InvalidationKind,
2037 capabilities: NodeCapabilities,
2038}
2039
2040impl ModifierInvalidation {
2041 pub const fn new(kind: InvalidationKind, capabilities: NodeCapabilities) -> Self {
2043 Self { kind, capabilities }
2044 }
2045
2046 pub const fn kind(self) -> InvalidationKind {
2048 self.kind
2049 }
2050
2051 pub const fn capabilities(self) -> NodeCapabilities {
2053 self.capabilities
2054 }
2055}
2056
2057pub trait AnyModifierElement: fmt::Debug {
2059 fn node_type(&self) -> TypeId;
2060
2061 fn element_type(&self) -> TypeId;
2062
2063 fn create_node(&self) -> Rc<RefCell<dyn ModifierNode>>;
2065
2066 fn can_update_node(&self, node: &dyn ModifierNode) -> bool;
2067
2068 fn update_node(&self, node: &mut dyn ModifierNode);
2069
2070 fn key(&self) -> Option<u64>;
2071
2072 fn capabilities(&self) -> NodeCapabilities {
2073 NodeCapabilities::default()
2074 }
2075
2076 fn hash_code(&self) -> u64;
2077
2078 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool;
2079
2080 fn inspector_name(&self) -> &'static str;
2081
2082 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String));
2083
2084 fn requires_update(&self) -> bool;
2085
2086 fn auto_invalidates_on_update(&self) -> bool;
2087
2088 fn update_invalidation_kind(&self) -> Option<InvalidationKind>;
2089
2090 fn provides_composition_locals(&self) -> bool {
2092 false
2093 }
2094
2095 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2097 Vec::new()
2098 }
2099
2100 fn as_any(&self) -> &dyn Any;
2101}
2102
2103struct TypedModifierElement<E: ModifierNodeElement> {
2104 element: E,
2105 cached_hash: u64,
2106 provides_locals: bool,
2107}
2108
2109impl<E: ModifierNodeElement> TypedModifierElement<E> {
2110 fn new(element: E) -> Self {
2111 let mut hasher = default::new();
2112 element.hash(&mut hasher);
2113 let provides_locals = !element.provided_composition_locals().is_empty();
2114 Self {
2115 element,
2116 cached_hash: hasher.finish(),
2117 provides_locals,
2118 }
2119 }
2120}
2121
2122impl<E> fmt::Debug for TypedModifierElement<E>
2123where
2124 E: ModifierNodeElement,
2125{
2126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2127 f.debug_struct("TypedModifierElement")
2128 .field("type", &type_name::<E>())
2129 .finish()
2130 }
2131}
2132
2133impl<E> AnyModifierElement for TypedModifierElement<E>
2134where
2135 E: ModifierNodeElement,
2136{
2137 fn node_type(&self) -> TypeId {
2138 TypeId::of::<E::Node>()
2139 }
2140
2141 fn element_type(&self) -> TypeId {
2142 TypeId::of::<E>()
2143 }
2144
2145 fn create_node(&self) -> Rc<RefCell<dyn ModifierNode>> {
2146 Rc::new(RefCell::new(self.element.create()))
2147 }
2148
2149 fn can_update_node(&self, node: &dyn ModifierNode) -> bool {
2150 node.as_any().is::<E::Node>()
2151 }
2152
2153 fn update_node(&self, node: &mut dyn ModifierNode) {
2154 if let Some(typed) = node.as_any_mut().downcast_mut::<E::Node>() {
2155 self.element.update(typed);
2156 }
2157 }
2158
2159 fn key(&self) -> Option<u64> {
2160 self.element.key()
2161 }
2162
2163 fn capabilities(&self) -> NodeCapabilities {
2164 self.element.capabilities()
2165 }
2166
2167 fn provides_composition_locals(&self) -> bool {
2168 self.provides_locals
2169 }
2170
2171 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2172 self.element.provided_composition_locals()
2173 }
2174
2175 fn hash_code(&self) -> u64 {
2176 self.cached_hash
2177 }
2178
2179 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool {
2180 other
2181 .as_any()
2182 .downcast_ref::<Self>()
2183 .is_some_and(|typed| typed.element == self.element)
2184 }
2185
2186 fn inspector_name(&self) -> &'static str {
2187 self.element.inspector_name()
2188 }
2189
2190 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String)) {
2191 self.element.inspector_properties(visitor);
2192 }
2193
2194 fn requires_update(&self) -> bool {
2195 self.element.always_update()
2196 }
2197
2198 fn auto_invalidates_on_update(&self) -> bool {
2199 self.element.auto_invalidate_on_update()
2200 }
2201
2202 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
2203 self.element.update_invalidation_kind()
2204 }
2205
2206 fn as_any(&self) -> &dyn Any {
2207 self
2208 }
2209}
2210
2211fn request_update_auto_invalidations(
2212 element: &dyn AnyModifierElement,
2213 context: &mut dyn ModifierNodeContext,
2214 capabilities: NodeCapabilities,
2215) {
2216 if let Some(kind) = element.update_invalidation_kind() {
2217 let capabilities = NodeCapabilities::for_invalidation(kind);
2218 context.push_active_capabilities(capabilities);
2219 context.invalidate(kind);
2220 context.pop_active_capabilities();
2221 } else if element.auto_invalidates_on_update() {
2222 request_auto_invalidations(context, capabilities);
2223 }
2224}
2225
2226pub fn modifier_element<E: ModifierNodeElement>(element: E) -> DynModifierElement {
2229 Rc::new(TypedModifierElement::new(element))
2230}
2231
2232pub type DynModifierElement = Rc<dyn AnyModifierElement>;
2234
2235#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2236enum TraversalDirection {
2237 Forward,
2238 Backward,
2239}
2240
2241pub struct ModifierChainIter<'a> {
2246 chain: &'a ModifierNodeChain,
2247 cursor: usize,
2248 remaining: usize,
2249 direction: TraversalDirection,
2250}
2251
2252impl<'a> ModifierChainIter<'a> {
2253 fn forward(chain: &'a ModifierNodeChain) -> Self {
2254 Self {
2255 chain,
2256 cursor: 0,
2257 remaining: chain.ordered_nodes.len(),
2258 direction: TraversalDirection::Forward,
2259 }
2260 }
2261
2262 fn backward(chain: &'a ModifierNodeChain) -> Self {
2263 let len = chain.ordered_nodes.len();
2264 Self {
2265 chain,
2266 cursor: len.wrapping_sub(1),
2267 remaining: len,
2268 direction: TraversalDirection::Backward,
2269 }
2270 }
2271}
2272
2273impl<'a> Iterator for ModifierChainIter<'a> {
2274 type Item = ModifierChainNodeRef<'a>;
2275
2276 #[inline]
2277 fn next(&mut self) -> Option<Self::Item> {
2278 if self.remaining == 0 {
2279 return None;
2280 }
2281 let (link, caps, agg) = self.chain.ordered_nodes[self.cursor];
2282 let node_ref = self.chain.make_node_ref_with_caps(link, caps, agg);
2283 self.remaining -= 1;
2284 match self.direction {
2285 TraversalDirection::Forward => self.cursor += 1,
2286 TraversalDirection::Backward => self.cursor = self.cursor.wrapping_sub(1),
2287 }
2288 Some(node_ref)
2289 }
2290
2291 #[inline]
2292 fn size_hint(&self) -> (usize, Option<usize>) {
2293 (self.remaining, Some(self.remaining))
2294 }
2295}
2296
2297impl ExactSizeIterator for ModifierChainIter<'_> {}
2298impl std::iter::FusedIterator for ModifierChainIter<'_> {}
2299
2300#[derive(Debug)]
2301struct ModifierNodeEntry {
2302 key: Option<u64>,
2303 hash_code: u64,
2304 element: DynModifierElement,
2305 node: Rc<RefCell<dyn ModifierNode>>,
2306 capabilities: NodeCapabilities,
2307}
2308
2309impl ModifierNodeEntry {
2310 fn new(
2311 key: Option<u64>,
2312 element: DynModifierElement,
2313 node: Rc<RefCell<dyn ModifierNode>>,
2314 hash_code: u64,
2315 capabilities: NodeCapabilities,
2316 ) -> Self {
2317 let entry = Self {
2318 key,
2319 hash_code,
2320 element,
2321 node,
2322 capabilities,
2323 };
2324 entry
2325 .node
2326 .borrow()
2327 .node_state()
2328 .set_capabilities(entry.capabilities);
2329 entry
2330 }
2331}
2332
2333fn visit_node_tree_mut(
2334 node: &mut dyn ModifierNode,
2335 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
2336) {
2337 visitor(node);
2338 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
2339}
2340
2341fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
2342 let mut current = 0usize;
2343 let mut result: Option<&dyn ModifierNode> = None;
2344 node.for_each_delegate(&mut |child| {
2345 if result.is_none() && current == target {
2346 result = Some(child);
2347 }
2348 current += 1;
2349 });
2350 result
2351}
2352
2353fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
2354 let mut current = 0usize;
2355 let mut result: Option<&mut dyn ModifierNode> = None;
2356 node.for_each_delegate_mut(&mut |child| {
2357 if result.is_none() && current == target {
2358 result = Some(child);
2359 }
2360 current += 1;
2361 });
2362 result
2363}
2364
2365fn with_node_context<F, R>(
2366 node: &mut dyn ModifierNode,
2367 context: &mut dyn ModifierNodeContext,
2368 f: F,
2369) -> R
2370where
2371 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
2372{
2373 context.push_active_capabilities(node.node_state().capabilities());
2374 let result = f(node, context);
2375 context.pop_active_capabilities();
2376 result
2377}
2378
2379fn request_auto_invalidations(
2380 context: &mut dyn ModifierNodeContext,
2381 capabilities: NodeCapabilities,
2382) {
2383 if capabilities.is_empty() {
2384 return;
2385 }
2386
2387 context.push_active_capabilities(capabilities);
2388
2389 if capabilities.contains(NodeCapabilities::LAYOUT) {
2390 context.invalidate(InvalidationKind::Layout);
2391 }
2392 if capabilities.contains(NodeCapabilities::DRAW) {
2393 context.invalidate(InvalidationKind::Draw);
2394 }
2395 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
2396 context.invalidate(InvalidationKind::PointerInput);
2397 }
2398 if capabilities.contains(NodeCapabilities::SEMANTICS) {
2399 context.invalidate(InvalidationKind::Semantics);
2400 }
2401 if capabilities.contains(NodeCapabilities::FOCUS) {
2402 context.invalidate(InvalidationKind::Focus);
2403 }
2404
2405 context.pop_active_capabilities();
2406}
2407
2408fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
2409 visit_node_tree_mut(node, &mut |n| {
2410 if !n.node_state().is_attached() {
2411 n.node_state().set_attached(true);
2412 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
2413 }
2414 });
2415}
2416
2417fn reset_node_tree(node: &mut dyn ModifierNode) {
2418 visit_node_tree_mut(node, &mut |n| n.on_reset());
2419}
2420
2421fn detach_node_tree(node: &mut dyn ModifierNode) {
2422 visit_node_tree_mut(node, &mut |n| {
2423 if n.node_state().is_attached() {
2424 n.on_detach();
2425 n.node_state().set_attached(false);
2426 }
2427 n.node_state().set_parent_link(None);
2428 n.node_state().set_child_link(None);
2429 n.node_state()
2430 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2431 });
2432}
2433
2434pub struct ModifierNodeChain {
2441 entries: Vec<ModifierNodeEntry>,
2442 aggregated_capabilities: NodeCapabilities,
2443 head_aggregate_child_capabilities: NodeCapabilities,
2444 head_sentinel: SentinelNode,
2445 tail_sentinel: SentinelNode,
2446 ordered_nodes: Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
2447 attached: bool,
2451 links_cleared: bool,
2454}
2455
2456#[derive(Default)]
2460struct ReconcileScratch {
2461 old_used: Vec<bool>,
2462 match_order: Vec<Option<usize>>,
2463 final_slots: Vec<Option<ModifierNodeEntry>>,
2464 elements: Vec<DynModifierElement>,
2465}
2466
2467thread_local! {
2468 static RECONCILE_SCRATCH: std::cell::RefCell<ReconcileScratch> =
2469 std::cell::RefCell::default();
2470}
2471
2472struct SentinelNode {
2473 state: NodeState,
2474}
2475
2476impl SentinelNode {
2477 fn new() -> Self {
2478 Self {
2479 state: NodeState::sentinel(),
2480 }
2481 }
2482}
2483
2484impl DelegatableNode for SentinelNode {
2485 fn node_state(&self) -> &NodeState {
2486 &self.state
2487 }
2488}
2489
2490impl ModifierNode for SentinelNode {}
2491
2492#[derive(Clone)]
2493pub struct ModifierChainNodeRef<'a> {
2494 chain: &'a ModifierNodeChain,
2495 link: NodeLink,
2496 cached_capabilities: Option<NodeCapabilities>,
2497 cached_aggregate_child: Option<NodeCapabilities>,
2498}
2499
2500impl Default for ModifierNodeChain {
2501 fn default() -> Self {
2502 Self::new()
2503 }
2504}
2505
2506struct EntryIndex {
2507 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2508 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2509 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
2510}
2511
2512struct EntryMatchQuery<'a> {
2513 element_type: TypeId,
2514 node_type: TypeId,
2515 key: Option<u64>,
2516 hash_code: u64,
2517 element: &'a DynModifierElement,
2518}
2519
2520impl EntryIndex {
2521 fn build(entries: &[ModifierNodeEntry]) -> Self {
2522 let mut keyed = HashMap::default();
2523 let mut hashed = HashMap::default();
2524 let mut typed = HashMap::default();
2525
2526 for (i, entry) in entries.iter().enumerate() {
2527 let (element_type, node_type) =
2528 (entry.element.element_type(), entry.element.node_type());
2529 if let Some(key_value) = entry.key {
2530 keyed
2531 .entry((element_type, node_type, key_value))
2532 .or_insert_with(Vec::new)
2533 .push(i);
2534 } else {
2535 hashed
2536 .entry((element_type, node_type, entry.hash_code))
2537 .or_insert_with(Vec::new)
2538 .push(i);
2539 typed
2540 .entry((element_type, node_type))
2541 .or_insert_with(Vec::new)
2542 .push(i);
2543 }
2544 }
2545
2546 Self {
2547 keyed,
2548 hashed,
2549 typed,
2550 }
2551 }
2552
2553 fn find_match(
2554 &self,
2555 entries: &[ModifierNodeEntry],
2556 used: &[bool],
2557 query: EntryMatchQuery<'_>,
2558 ) -> Option<usize> {
2559 if let Some(key_value) = query.key {
2560 if let Some(candidates) =
2561 self.keyed
2562 .get(&(query.element_type, query.node_type, key_value))
2563 {
2564 for &i in candidates {
2565 if !used[i] {
2566 return Some(i);
2567 }
2568 }
2569 }
2570 } else {
2571 if let Some(candidates) =
2572 self.hashed
2573 .get(&(query.element_type, query.node_type, query.hash_code))
2574 {
2575 for &i in candidates {
2576 if !used[i]
2577 && entries[i]
2578 .element
2579 .as_ref()
2580 .equals_element(query.element.as_ref())
2581 {
2582 return Some(i);
2583 }
2584 }
2585 }
2586
2587 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
2588 for &i in candidates {
2589 if !used[i] {
2590 return Some(i);
2591 }
2592 }
2593 }
2594 }
2595
2596 None
2597 }
2598}
2599
2600fn update_entry_in_place(
2605 entry: &mut ModifierNodeEntry,
2606 element: &DynModifierElement,
2607 context: &mut dyn ModifierNodeContext,
2608) -> bool {
2609 if entry.element.element_type() != element.element_type()
2610 || entry.element.node_type() != element.node_type()
2611 || entry.key != element.key()
2612 || !element.can_update_node(&*entry.node.borrow())
2613 {
2614 return false;
2615 }
2616 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2617 let capabilities = element.capabilities();
2618 if !same_element || element.requires_update() {
2619 element.update_node(&mut *entry.node.borrow_mut());
2620 entry.element = element.clone();
2621 entry.hash_code = element.hash_code();
2622 request_update_auto_invalidations(element.as_ref(), context, capabilities);
2623 }
2624 entry.capabilities = capabilities;
2625 entry
2626 .node
2627 .borrow()
2628 .node_state()
2629 .set_capabilities(capabilities);
2630 true
2631}
2632
2633fn fresh_entry(
2636 element: DynModifierElement,
2637 context: &mut dyn ModifierNodeContext,
2638 attach: bool,
2639) -> ModifierNodeEntry {
2640 let capabilities = element.capabilities();
2641 let entry = ModifierNodeEntry::new(
2642 element.key(),
2643 element.clone(),
2644 element.create_node(),
2645 element.hash_code(),
2646 capabilities,
2647 );
2648 if attach {
2649 attach_node_tree(&mut *entry.node.borrow_mut(), context);
2650 }
2651 element.update_node(&mut *entry.node.borrow_mut());
2652 request_auto_invalidations(context, capabilities);
2653 entry
2654}
2655
2656fn reconcile_element(
2661 element: DynModifierElement,
2662 new_pos: usize,
2663 (old_entries, index): (&mut [ModifierNodeEntry], &EntryIndex),
2664 (used, match_order): (&mut [bool], &mut [Option<usize>]),
2665 context: &mut dyn ModifierNodeContext,
2666 attach: bool,
2667) -> Option<ModifierNodeEntry> {
2668 let element_type = element.element_type();
2669 let node_type = element.node_type();
2670 let key = element.key();
2671 let hash_code = element.hash_code();
2672 let capabilities = element.capabilities();
2673 let Some(idx) = index.find_match(
2674 old_entries,
2675 used,
2676 EntryMatchQuery {
2677 element_type,
2678 node_type,
2679 key,
2680 hash_code,
2681 element: &element,
2682 },
2683 ) else {
2684 return Some(fresh_entry(element, context, attach));
2685 };
2686 let entry = &mut old_entries[idx];
2687 if !element.can_update_node(&*entry.node.borrow()) {
2688 return Some(fresh_entry(element, context, attach));
2689 }
2690
2691 used[idx] = true;
2692 match_order[idx] = Some(new_pos);
2693 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2694 if !same_element || element.requires_update() {
2695 element.update_node(&mut *entry.node.borrow_mut());
2696 entry.element = element;
2697 entry.hash_code = hash_code;
2698 request_update_auto_invalidations(entry.element.as_ref(), context, capabilities);
2699 }
2700 if idx != new_pos {
2701 request_auto_invalidations(context, capabilities);
2702 }
2703 entry.key = key;
2704 entry.capabilities = capabilities;
2705 entry
2706 .node
2707 .borrow()
2708 .node_state()
2709 .set_capabilities(capabilities);
2710 None
2711}
2712
2713impl ModifierNodeChain {
2714 pub fn new() -> Self {
2716 let mut chain = Self::detached();
2717 chain.attached = true;
2718 chain
2719 }
2720
2721 pub fn detached() -> Self {
2724 let mut chain = Self {
2725 entries: Vec::new(),
2726 aggregated_capabilities: NodeCapabilities::empty(),
2727 head_aggregate_child_capabilities: NodeCapabilities::empty(),
2728 head_sentinel: SentinelNode::new(),
2729 tail_sentinel: SentinelNode::new(),
2730 ordered_nodes: Vec::new(),
2731 attached: false,
2732 links_cleared: false,
2733 };
2734 chain.sync_chain_links();
2735 chain
2736 }
2737
2738 pub fn detach_nodes(&mut self) {
2740 if !self.attached {
2741 return;
2742 }
2743 self.attached = false;
2744 for entry in &self.entries {
2745 detach_node_tree(&mut *entry.node.borrow_mut());
2746 }
2747 self.links_cleared = !self.entries.is_empty();
2748 }
2749
2750 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
2752 if self.attached {
2753 return;
2754 }
2755 self.attached = true;
2756 for entry in &self.entries {
2757 attach_node_tree(&mut *entry.node.borrow_mut(), context);
2758 }
2759 }
2760
2761 pub fn repair_chain(&mut self) {
2764 if self.links_cleared {
2765 self.sync_chain_links();
2766 }
2767 }
2768
2769 pub fn update_from_slice(
2775 &mut self,
2776 elements: &[DynModifierElement],
2777 context: &mut dyn ModifierNodeContext,
2778 ) {
2779 self.update_from_ref_iter(elements.iter(), context);
2780 }
2781
2782 pub fn update_entries_of_type<'a, I>(
2792 &mut self,
2793 elements: I,
2794 element_count: usize,
2795 element_type: TypeId,
2796 context: &mut dyn ModifierNodeContext,
2797 ) -> bool
2798 where
2799 I: Iterator<Item = &'a DynModifierElement>,
2800 {
2801 if element_count != self.entries.len() {
2802 return false;
2803 }
2804 self.entries
2805 .iter_mut()
2806 .zip(elements)
2807 .filter(|(_, element)| element.element_type() == element_type)
2808 .all(|(entry, element)| update_entry_in_place(entry, element, context))
2809 }
2810
2811 pub fn update_from_ref_iter<'a, I>(
2812 &mut self,
2813 elements: I,
2814 context: &mut dyn ModifierNodeContext,
2815 ) where
2816 I: Iterator<Item = &'a DynModifierElement>,
2817 {
2818 let mut scratch = RECONCILE_SCRATCH
2821 .try_with(|scratch| std::mem::take(&mut *scratch.borrow_mut()))
2822 .unwrap_or_default();
2823 self.reconcile(elements, context, &mut scratch);
2824 scratch.elements.clear();
2825 scratch.final_slots.clear();
2826 let _ = RECONCILE_SCRATCH.try_with(|slot| *slot.borrow_mut() = scratch);
2827 }
2828
2829 fn reconcile<'a, I>(
2830 &mut self,
2831 elements: I,
2832 context: &mut dyn ModifierNodeContext,
2833 scratch: &mut ReconcileScratch,
2834 ) where
2835 I: Iterator<Item = &'a DynModifierElement>,
2836 {
2837 let old_len = self.entries.len();
2838 let mut fast_path_failed_at: Option<usize> = None;
2839 let mut elements_count = 0;
2840
2841 scratch.elements.clear();
2842
2843 for (idx, element) in elements.enumerate() {
2844 elements_count = idx + 1;
2845 if fast_path_failed_at.is_none() && idx < old_len {
2846 if update_entry_in_place(&mut self.entries[idx], element, context) {
2847 continue;
2848 }
2849 fast_path_failed_at = Some(idx);
2850 }
2851 scratch.elements.push(element.clone());
2852 }
2853
2854 if fast_path_failed_at.is_none() && scratch.elements.is_empty() {
2855 if elements_count < self.entries.len() {
2856 for entry in self.entries.drain(elements_count..) {
2857 request_auto_invalidations(context, entry.capabilities);
2858 detach_node_tree(&mut *entry.node.borrow_mut());
2859 }
2860 }
2861 self.sync_chain_links();
2862 return;
2863 }
2864
2865 self.rebuild_tail(fast_path_failed_at.unwrap_or(old_len), context, scratch);
2866 }
2867
2868 fn rebuild_tail(
2872 &mut self,
2873 fail_idx: usize,
2874 context: &mut dyn ModifierNodeContext,
2875 scratch: &mut ReconcileScratch,
2876 ) {
2877 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
2878 let processed_entries_len = self.entries.len();
2879 let old_len = old_entries.len();
2880
2881 scratch.old_used.clear();
2882 scratch.old_used.resize(old_len, false);
2883
2884 scratch.match_order.clear();
2885 scratch.match_order.resize(old_len, None);
2886
2887 let index = EntryIndex::build(&old_entries);
2888
2889 let new_elements_count = scratch.elements.len();
2890 scratch.final_slots.clear();
2891 scratch.final_slots.reserve(new_elements_count);
2892
2893 for (new_pos, element) in scratch.elements.drain(..).enumerate() {
2894 let fresh = reconcile_element(
2895 element,
2896 new_pos,
2897 (&mut old_entries, &index),
2898 (&mut scratch.old_used, &mut scratch.match_order),
2899 context,
2900 self.attached,
2901 );
2902 scratch.final_slots.push(fresh);
2903 }
2904
2905 for (i, entry) in old_entries.into_iter().enumerate() {
2906 match scratch.match_order[i] {
2907 Some(pos) if scratch.old_used[i] => scratch.final_slots[pos] = Some(entry),
2908 _ => {
2909 request_auto_invalidations(context, entry.capabilities);
2910 detach_node_tree(&mut *entry.node.borrow_mut());
2911 }
2912 }
2913 }
2914
2915 self.entries.reserve_exact(scratch.final_slots.len());
2919 for slot in scratch.final_slots.drain(..) {
2920 if let Some(entry) = slot {
2921 self.entries.push(entry);
2922 } else {
2923 log::error!("modifier reconciliation produced an empty final slot");
2924 }
2925 }
2926
2927 debug_assert_eq!(
2928 self.entries.len(),
2929 processed_entries_len + new_elements_count
2930 );
2931 self.sync_chain_links();
2932 }
2933
2934 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
2938 where
2939 I: IntoIterator<Item = DynModifierElement>,
2940 {
2941 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
2942 self.update_from_slice(&collected, context);
2943 }
2944
2945 pub fn reset(&mut self) {
2948 for entry in &mut self.entries {
2949 reset_node_tree(&mut *entry.node.borrow_mut());
2950 }
2951 }
2952
2953 pub fn detach_all(&mut self) {
2955 for entry in std::mem::take(&mut self.entries) {
2956 detach_node_tree(&mut *entry.node.borrow_mut());
2957 {
2958 let node_borrow = entry.node.borrow();
2959 let state = node_borrow.node_state();
2960 state.set_capabilities(NodeCapabilities::empty());
2961 }
2962 }
2963 self.aggregated_capabilities = NodeCapabilities::empty();
2964 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2965 self.ordered_nodes.clear();
2966 self.sync_chain_links();
2967 }
2968
2969 pub fn len(&self) -> usize {
2970 self.entries.len()
2971 }
2972
2973 pub fn is_empty(&self) -> bool {
2974 self.entries.is_empty()
2975 }
2976
2977 pub fn capabilities(&self) -> NodeCapabilities {
2979 self.aggregated_capabilities
2980 }
2981
2982 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
2984 self.aggregated_capabilities.contains(capability)
2985 }
2986
2987 pub fn head(&self) -> ModifierChainNodeRef<'_> {
2989 self.make_node_ref(NodeLink::Head)
2990 }
2991
2992 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
2994 self.make_node_ref(NodeLink::Tail)
2995 }
2996
2997 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
2999 ModifierChainIter::forward(self)
3000 }
3001
3002 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
3004 ModifierChainIter::backward(self)
3005 }
3006
3007 pub fn for_each_forward<F>(&self, mut f: F)
3009 where
3010 F: FnMut(ModifierChainNodeRef<'_>),
3011 {
3012 for node in self.head_to_tail() {
3013 f(node);
3014 }
3015 }
3016
3017 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
3019 where
3020 F: FnMut(ModifierChainNodeRef<'_>),
3021 {
3022 if mask.is_empty() {
3023 self.for_each_forward(f);
3024 return;
3025 }
3026
3027 if !self.head().aggregate_child_capabilities().intersects(mask) {
3028 return;
3029 }
3030
3031 for node in self.head_to_tail() {
3032 if node.kind_set().intersects(mask) {
3033 f(node);
3034 }
3035 }
3036 }
3037
3038 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
3040 where
3041 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
3042 {
3043 self.for_each_forward_matching(mask, |node_ref| {
3044 node_ref.with_node(|node| f(node_ref.clone(), node));
3045 });
3046 }
3047
3048 pub fn for_each_backward<F>(&self, mut f: F)
3050 where
3051 F: FnMut(ModifierChainNodeRef<'_>),
3052 {
3053 for node in self.tail_to_head() {
3054 f(node);
3055 }
3056 }
3057
3058 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
3060 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
3061 node as *const dyn ModifierNode as *const ()
3062 }
3063
3064 let target = node_data_ptr(node);
3065 for (index, entry) in self.entries.iter().enumerate() {
3066 if node_data_ptr(&*entry.node.borrow()) == target {
3067 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
3068 }
3069 }
3070
3071 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
3072 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
3073 return None;
3074 }
3075 let matches_target = match link {
3076 NodeLink::Head => node_data_ptr(&self.head_sentinel) == target,
3077 NodeLink::Tail => node_data_ptr(&self.tail_sentinel) == target,
3078 NodeLink::Entry(path) => {
3079 let node_borrow = self.entries[path.entry()].node.borrow();
3080 node_data_ptr(&*node_borrow) == target
3081 }
3082 };
3083 if matches_target {
3084 Some(self.make_node_ref(*link))
3085 } else {
3086 None
3087 }
3088 })
3089 }
3090
3091 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
3094 self.entries.get(index).and_then(|entry| {
3095 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
3096 boxed_node.as_any().downcast_ref::<N>()
3097 })
3098 .ok()
3099 })
3100 }
3101
3102 pub fn node_mut<N: ModifierNode + 'static>(
3105 &self,
3106 index: usize,
3107 ) -> Option<std::cell::RefMut<'_, N>> {
3108 self.entries.get(index).and_then(|entry| {
3109 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
3110 boxed_node.as_any_mut().downcast_mut::<N>()
3111 })
3112 .ok()
3113 })
3114 }
3115
3116 pub fn get_node_rc(&self, index: usize) -> Option<&Rc<RefCell<dyn ModifierNode>>> {
3119 self.entries.get(index).map(|entry| &entry.node)
3120 }
3121
3122 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
3124 self.aggregated_capabilities
3125 .contains(NodeCapabilities::for_invalidation(kind))
3126 }
3127
3128 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
3130 where
3131 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
3132 {
3133 for index in 0..self.ordered_nodes.len() {
3134 let (link, cached_caps, _agg) = self.ordered_nodes[index];
3135 match link {
3136 NodeLink::Head => {
3137 f(&mut self.head_sentinel, cached_caps);
3138 }
3139 NodeLink::Tail => {
3140 f(&mut self.tail_sentinel, cached_caps);
3141 }
3142 NodeLink::Entry(path) => {
3143 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
3144 if path.delegates().is_empty() {
3145 f(&mut *node_borrow, cached_caps);
3146 } else {
3147 let mut current: &mut dyn ModifierNode = &mut *node_borrow;
3148 for &delegate_index in path.delegates() {
3149 if let Some(delegate) =
3150 nth_delegate_mut(current, delegate_index as usize)
3151 {
3152 current = delegate;
3153 } else {
3154 return;
3155 }
3156 }
3157 f(current, cached_caps);
3158 }
3159 }
3160 }
3161 }
3162 }
3163
3164 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
3165 ModifierChainNodeRef {
3166 chain: self,
3167 link,
3168 cached_capabilities: None,
3169 cached_aggregate_child: None,
3170 }
3171 }
3172
3173 fn make_node_ref_with_caps(
3174 &self,
3175 link: NodeLink,
3176 caps: NodeCapabilities,
3177 aggregate_child: NodeCapabilities,
3178 ) -> ModifierChainNodeRef<'_> {
3179 ModifierChainNodeRef {
3180 chain: self,
3181 link,
3182 cached_capabilities: Some(caps),
3183 cached_aggregate_child: Some(aggregate_child),
3184 }
3185 }
3186
3187 fn sync_chain_links(&mut self) {
3188 self.links_cleared = false;
3189 self.rebuild_ordered_nodes();
3190
3191 self.head_sentinel.node_state().set_parent_link(None);
3192 self.tail_sentinel.node_state().set_child_link(None);
3193
3194 if self.ordered_nodes.is_empty() {
3195 self.head_sentinel
3196 .node_state()
3197 .set_child_link(Some(NodeLink::Tail));
3198 self.tail_sentinel
3199 .node_state()
3200 .set_parent_link(Some(NodeLink::Head));
3201 self.aggregated_capabilities = NodeCapabilities::empty();
3202 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
3203 self.head_sentinel
3204 .node_state()
3205 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3206 self.tail_sentinel
3207 .node_state()
3208 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3209 return;
3210 }
3211
3212 let mut previous = NodeLink::Head;
3213 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
3214 match &previous {
3215 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
3216 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
3217 NodeLink::Entry(path) => {
3218 let node_borrow = self.entries[path.entry()].node.borrow();
3219 if path.delegates().is_empty() {
3220 node_borrow.node_state().set_child_link(Some(link));
3221 } else {
3222 let mut current: &dyn ModifierNode = &*node_borrow;
3223 for &delegate_index in path.delegates() {
3224 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3225 current = delegate;
3226 }
3227 }
3228 current.node_state().set_child_link(Some(link));
3229 }
3230 }
3231 }
3232 match &link {
3233 NodeLink::Head => self
3234 .head_sentinel
3235 .node_state()
3236 .set_parent_link(Some(previous)),
3237 NodeLink::Tail => self
3238 .tail_sentinel
3239 .node_state()
3240 .set_parent_link(Some(previous)),
3241 NodeLink::Entry(path) => {
3242 let node_borrow = self.entries[path.entry()].node.borrow();
3243 if path.delegates().is_empty() {
3244 node_borrow.node_state().set_parent_link(Some(previous));
3245 } else {
3246 let mut current: &dyn ModifierNode = &*node_borrow;
3247 for &delegate_index in path.delegates() {
3248 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3249 current = delegate;
3250 }
3251 }
3252 current.node_state().set_parent_link(Some(previous));
3253 }
3254 }
3255 }
3256 previous = link;
3257 }
3258
3259 match &previous {
3260 NodeLink::Head => self
3261 .head_sentinel
3262 .node_state()
3263 .set_child_link(Some(NodeLink::Tail)),
3264 NodeLink::Tail => self
3265 .tail_sentinel
3266 .node_state()
3267 .set_child_link(Some(NodeLink::Tail)),
3268 NodeLink::Entry(path) => {
3269 let node_borrow = self.entries[path.entry()].node.borrow();
3270 if path.delegates().is_empty() {
3271 node_borrow
3272 .node_state()
3273 .set_child_link(Some(NodeLink::Tail));
3274 } else {
3275 let mut current: &dyn ModifierNode = &*node_borrow;
3276 for &delegate_index in path.delegates() {
3277 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3278 current = delegate;
3279 }
3280 }
3281 current.node_state().set_child_link(Some(NodeLink::Tail));
3282 }
3283 }
3284 }
3285 self.tail_sentinel
3286 .node_state()
3287 .set_parent_link(Some(previous));
3288 self.tail_sentinel.node_state().set_child_link(None);
3289
3290 let mut aggregate = NodeCapabilities::empty();
3291 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
3292 aggregate |= *cached_caps;
3293 *cached_aggregate = aggregate;
3294 match link {
3295 NodeLink::Head => {
3296 self.head_sentinel
3297 .node_state()
3298 .set_aggregate_child_capabilities(aggregate);
3299 }
3300 NodeLink::Tail => {
3301 self.tail_sentinel
3302 .node_state()
3303 .set_aggregate_child_capabilities(aggregate);
3304 }
3305 NodeLink::Entry(path) => {
3306 let node_borrow = self.entries[path.entry()].node.borrow();
3307 let state = if path.delegates().is_empty() {
3308 node_borrow.node_state()
3309 } else {
3310 let mut current: &dyn ModifierNode = &*node_borrow;
3311 for &delegate_index in path.delegates() {
3312 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3313 current = delegate;
3314 }
3315 }
3316 current.node_state()
3317 };
3318 state.set_aggregate_child_capabilities(aggregate);
3319 }
3320 }
3321 }
3322
3323 self.aggregated_capabilities = aggregate;
3324 self.head_aggregate_child_capabilities = aggregate;
3325 self.head_sentinel
3326 .node_state()
3327 .set_aggregate_child_capabilities(aggregate);
3328 self.tail_sentinel
3329 .node_state()
3330 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3331 }
3332
3333 fn rebuild_ordered_nodes(&mut self) {
3334 self.ordered_nodes.clear();
3335 self.ordered_nodes.reserve_exact(self.entries.len());
3337 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
3338 for (index, entry) in self.entries.iter().enumerate() {
3339 let node_borrow = entry.node.borrow();
3340 Self::enumerate_link_order(
3341 &*node_borrow,
3342 index,
3343 &mut path_buf,
3344 0,
3345 &mut self.ordered_nodes,
3346 );
3347 }
3348 }
3349
3350 fn enumerate_link_order(
3351 node: &dyn ModifierNode,
3352 entry: usize,
3353 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
3354 path_len: usize,
3355 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
3356 ) {
3357 let caps = node.node_state().capabilities();
3358 out.push((
3359 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
3360 caps,
3361 NodeCapabilities::empty(),
3362 ));
3363 let mut delegate_index = 0usize;
3364 node.for_each_delegate(&mut |child| {
3365 if path_len < MAX_DELEGATE_DEPTH {
3366 path_buf[path_len] = delegate_index;
3367 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
3368 }
3369 delegate_index += 1;
3370 });
3371 }
3372}
3373
3374impl<'a> ModifierChainNodeRef<'a> {
3375 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
3376 match &self.link {
3377 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
3378 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
3379 NodeLink::Entry(path) => {
3380 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3381 if path.delegates().is_empty() {
3382 f(node_borrow.node_state())
3383 } else {
3384 let mut current: &dyn ModifierNode = &*node_borrow;
3385 for &delegate_index in path.delegates() {
3386 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3387 current = delegate;
3388 } else {
3389 return f(node_borrow.node_state());
3390 }
3391 }
3392 f(current.node_state())
3393 }
3394 }
3395 }
3396 }
3397
3398 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
3401 match &self.link {
3402 NodeLink::Head => None,
3403 NodeLink::Tail => None,
3404 NodeLink::Entry(path) => {
3405 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3406 if path.delegates().is_empty() {
3407 Some(f(&*node_borrow))
3408 } else {
3409 let mut current: &dyn ModifierNode = &*node_borrow;
3410 for &delegate_index in path.delegates() {
3411 current = nth_delegate(current, delegate_index as usize)?;
3412 }
3413 Some(f(current))
3414 }
3415 }
3416 }
3417 }
3418
3419 #[inline]
3421 pub fn parent(&self) -> Option<Self> {
3422 self.with_state(NodeState::parent_link)
3423 .map(|link| self.chain.make_node_ref(link))
3424 }
3425
3426 #[inline]
3428 pub fn child(&self) -> Option<Self> {
3429 self.with_state(NodeState::child_link)
3430 .map(|link| self.chain.make_node_ref(link))
3431 }
3432
3433 #[inline]
3435 pub fn kind_set(&self) -> NodeCapabilities {
3436 if let Some(caps) = self.cached_capabilities {
3437 return caps;
3438 }
3439 match &self.link {
3440 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
3441 NodeLink::Entry(_) => self.with_state(NodeState::capabilities),
3442 }
3443 }
3444
3445 pub fn entry_index(&self) -> Option<usize> {
3447 match &self.link {
3448 NodeLink::Entry(path) => Some(path.entry()),
3449 _ => None,
3450 }
3451 }
3452
3453 pub fn delegate_depth(&self) -> usize {
3455 match &self.link {
3456 NodeLink::Entry(path) => path.delegates().len(),
3457 _ => 0,
3458 }
3459 }
3460
3461 #[inline]
3463 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
3464 if let Some(agg) = self.cached_aggregate_child {
3465 return agg;
3466 }
3467 if self.is_tail() {
3468 NodeCapabilities::empty()
3469 } else {
3470 self.with_state(NodeState::aggregate_child_capabilities)
3471 }
3472 }
3473
3474 pub fn is_head(&self) -> bool {
3476 matches!(self.link, NodeLink::Head)
3477 }
3478
3479 pub fn is_tail(&self) -> bool {
3481 matches!(self.link, NodeLink::Tail)
3482 }
3483
3484 pub fn is_sentinel(&self) -> bool {
3486 matches!(self.link, NodeLink::Head | NodeLink::Tail)
3487 }
3488
3489 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
3491 !mask.is_empty() && self.kind_set().intersects(mask)
3492 }
3493
3494 pub fn visit_descendants<F>(self, include_self: bool, mut f: F)
3496 where
3497 F: FnMut(ModifierChainNodeRef<'a>),
3498 {
3499 let mut current = if include_self {
3500 Some(self)
3501 } else {
3502 self.child()
3503 };
3504 while let Some(node) = current {
3505 if node.is_tail() {
3506 break;
3507 }
3508 if !node.is_sentinel() {
3509 f(node.clone());
3510 }
3511 current = node.child();
3512 }
3513 }
3514
3515 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3517 where
3518 F: FnMut(ModifierChainNodeRef<'a>),
3519 {
3520 if mask.is_empty() {
3521 self.visit_descendants(include_self, f);
3522 return;
3523 }
3524
3525 if !self.aggregate_child_capabilities().intersects(mask) {
3526 return;
3527 }
3528
3529 self.visit_descendants(include_self, |node| {
3530 if node.kind_set().intersects(mask) {
3531 f(node);
3532 }
3533 });
3534 }
3535
3536 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
3538 where
3539 F: FnMut(ModifierChainNodeRef<'a>),
3540 {
3541 let mut current = if include_self {
3542 Some(self)
3543 } else {
3544 self.parent()
3545 };
3546 while let Some(node) = current {
3547 if node.is_head() {
3548 break;
3549 }
3550 f(node.clone());
3551 current = node.parent();
3552 }
3553 }
3554
3555 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3557 where
3558 F: FnMut(ModifierChainNodeRef<'a>),
3559 {
3560 if mask.is_empty() {
3561 self.visit_ancestors(include_self, f);
3562 return;
3563 }
3564
3565 self.visit_ancestors(include_self, |node| {
3566 if node.kind_set().intersects(mask) {
3567 f(node);
3568 }
3569 });
3570 }
3571}
3572
3573#[cfg(test)]
3574#[path = "tests/modifier_tests.rs"]
3575mod tests;