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: Vec<ModifierInvalidation>,
75 update_requested: bool,
76 active_capabilities: Vec<NodeCapabilities>,
77 node_id: Option<cranpose_core::NodeId>,
78}
79
80impl BasicModifierNodeContext {
81 pub fn new() -> Self {
83 Self::default()
84 }
85
86 pub fn invalidations(&self) -> &[ModifierInvalidation] {
90 &self.invalidations
91 }
92
93 pub fn clear_invalidations(&mut self) {
95 self.invalidations.clear();
96 }
97
98 pub fn take_invalidations(&mut self) -> Vec<ModifierInvalidation> {
100 std::mem::take(&mut self.invalidations)
101 }
102
103 pub fn update_requested(&self) -> bool {
106 self.update_requested
107 }
108
109 pub fn take_update_requested(&mut self) -> bool {
111 std::mem::take(&mut self.update_requested)
112 }
113
114 pub fn set_node_id(&mut self, id: Option<cranpose_core::NodeId>) {
116 self.node_id = id;
117 }
118
119 fn push_invalidation(&mut self, kind: InvalidationKind) {
120 let mut capabilities = self.current_capabilities();
121 capabilities.insert(NodeCapabilities::for_invalidation(kind));
122 if let Some(existing) = self
123 .invalidations
124 .iter_mut()
125 .find(|entry| entry.kind() == kind)
126 {
127 let updated = existing.capabilities() | capabilities;
128 *existing = ModifierInvalidation::new(kind, updated);
129 } else {
130 self.invalidations
131 .push(ModifierInvalidation::new(kind, capabilities));
132 }
133 }
134
135 fn current_capabilities(&self) -> NodeCapabilities {
136 self.active_capabilities
137 .last()
138 .copied()
139 .unwrap_or_else(NodeCapabilities::empty)
140 }
141}
142
143impl ModifierNodeContext for BasicModifierNodeContext {
144 fn invalidate(&mut self, kind: InvalidationKind) {
145 self.push_invalidation(kind);
146 }
147
148 fn request_update(&mut self) {
149 self.update_requested = true;
150 }
151
152 fn push_active_capabilities(&mut self, capabilities: NodeCapabilities) {
153 self.active_capabilities.push(capabilities);
154 }
155
156 fn pop_active_capabilities(&mut self) {
157 self.active_capabilities.pop();
158 }
159
160 fn node_id(&self) -> Option<cranpose_core::NodeId> {
161 self.node_id
162 }
163}
164
165const MAX_DELEGATE_DEPTH: usize = 3;
166
167#[derive(Copy, Clone, Debug, PartialEq, Eq)]
168pub(crate) struct NodePath {
169 entry: usize,
170 delegate_buf: [u8; MAX_DELEGATE_DEPTH],
171 delegate_len: u8,
172}
173
174impl NodePath {
175 #[inline]
176 fn root(entry: usize) -> Self {
177 Self {
178 entry,
179 delegate_buf: [0; MAX_DELEGATE_DEPTH],
180 delegate_len: 0,
181 }
182 }
183
184 #[inline]
185 fn from_slice(entry: usize, path: &[usize]) -> Self {
186 debug_assert!(
187 path.len() <= MAX_DELEGATE_DEPTH,
188 "delegate depth {} exceeds MAX_DELEGATE_DEPTH {}",
189 path.len(),
190 MAX_DELEGATE_DEPTH
191 );
192 debug_assert!(
193 path.iter().all(|&i| i <= u8::MAX as usize),
194 "delegate index exceeds u8 range"
195 );
196 let mut delegate_buf = [0u8; MAX_DELEGATE_DEPTH];
197 for (i, &v) in path.iter().enumerate().take(MAX_DELEGATE_DEPTH) {
198 delegate_buf[i] = v as u8;
199 }
200 Self {
201 entry,
202 delegate_buf,
203 delegate_len: path.len().min(MAX_DELEGATE_DEPTH) as u8,
204 }
205 }
206
207 #[inline]
208 fn entry(&self) -> usize {
209 self.entry
210 }
211
212 #[inline]
213 fn delegates(&self) -> &[u8] {
214 &self.delegate_buf[..self.delegate_len as usize]
215 }
216}
217
218#[derive(Copy, Clone, Debug, PartialEq, Eq)]
219pub(crate) enum NodeLink {
220 Head,
221 Tail,
222 Entry(NodePath),
223}
224
225#[derive(Debug)]
231pub struct NodeState {
232 aggregate_child_capabilities: Cell<NodeCapabilities>,
233 capabilities: Cell<NodeCapabilities>,
234 parent: RefCell<Option<NodeLink>>,
235 child: RefCell<Option<NodeLink>>,
236 attached: Cell<bool>,
237 is_sentinel: bool,
238}
239
240impl Default for NodeState {
241 fn default() -> Self {
242 Self::new()
243 }
244}
245
246impl NodeState {
247 pub const fn new() -> Self {
248 Self {
249 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
250 capabilities: Cell::new(NodeCapabilities::empty()),
251 parent: RefCell::new(None),
252 child: RefCell::new(None),
253 attached: Cell::new(false),
254 is_sentinel: false,
255 }
256 }
257
258 pub const fn sentinel() -> Self {
259 Self {
260 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
261 capabilities: Cell::new(NodeCapabilities::empty()),
262 parent: RefCell::new(None),
263 child: RefCell::new(None),
264 attached: Cell::new(true),
265 is_sentinel: true,
266 }
267 }
268
269 pub fn set_capabilities(&self, capabilities: NodeCapabilities) {
270 self.capabilities.set(capabilities);
271 }
272
273 #[inline]
274 pub fn capabilities(&self) -> NodeCapabilities {
275 self.capabilities.get()
276 }
277
278 pub fn set_aggregate_child_capabilities(&self, capabilities: NodeCapabilities) {
279 self.aggregate_child_capabilities.set(capabilities);
280 }
281
282 #[inline]
283 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
284 self.aggregate_child_capabilities.get()
285 }
286
287 pub(crate) fn set_parent_link(&self, parent: Option<NodeLink>) {
288 *self.parent.borrow_mut() = parent;
289 }
290
291 #[inline]
292 pub(crate) fn parent_link(&self) -> Option<NodeLink> {
293 *self.parent.borrow()
294 }
295
296 pub(crate) fn set_child_link(&self, child: Option<NodeLink>) {
297 *self.child.borrow_mut() = child;
298 }
299
300 #[inline]
301 pub(crate) fn child_link(&self) -> Option<NodeLink> {
302 *self.child.borrow()
303 }
304
305 pub fn set_attached(&self, attached: bool) {
306 self.attached.set(attached);
307 }
308
309 pub fn is_attached(&self) -> bool {
310 self.attached.get()
311 }
312
313 pub fn is_sentinel(&self) -> bool {
314 self.is_sentinel
315 }
316}
317
318pub trait DelegatableNode {
320 fn node_state(&self) -> &NodeState;
321 fn aggregate_child_capabilities(&self) -> NodeCapabilities {
322 self.node_state().aggregate_child_capabilities()
323 }
324}
325
326pub trait ModifierNode: Any + DelegatableNode {
384 fn on_attach(&mut self, _context: &mut dyn ModifierNodeContext) {}
385
386 fn on_detach(&mut self) {}
387
388 fn on_reset(&mut self) {}
389
390 fn as_draw_node(&self) -> Option<&dyn DrawModifierNode> {
392 None
393 }
394
395 fn as_draw_node_mut(&mut self) -> Option<&mut dyn DrawModifierNode> {
397 None
398 }
399
400 fn as_pointer_input_node(&self) -> Option<&dyn PointerInputNode> {
402 None
403 }
404
405 fn as_pointer_input_node_mut(&mut self) -> Option<&mut dyn PointerInputNode> {
407 None
408 }
409
410 fn as_semantics_node(&self) -> Option<&dyn SemanticsNode> {
412 None
413 }
414
415 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn SemanticsNode> {
417 None
418 }
419
420 fn as_focus_node(&self) -> Option<&dyn FocusNode> {
422 None
423 }
424
425 fn as_focus_node_mut(&mut self) -> Option<&mut dyn FocusNode> {
427 None
428 }
429
430 fn as_layout_node(&self) -> Option<&dyn LayoutModifierNode> {
432 None
433 }
434
435 fn as_layout_node_mut(&mut self) -> Option<&mut dyn LayoutModifierNode> {
437 None
438 }
439
440 fn for_each_delegate<'b>(&'b self, _visitor: &mut dyn FnMut(&'b dyn ModifierNode)) {}
442
443 fn for_each_delegate_mut<'b>(&'b mut self, _visitor: &mut dyn FnMut(&'b mut dyn ModifierNode)) {
445 }
446}
447
448pub trait LayoutModifierNode: ModifierNode {
454 fn measure(
476 &self,
477 _context: &mut dyn ModifierNodeContext,
478 measurable: &dyn Measurable,
479 constraints: Constraints,
480 ) -> cranpose_ui_layout::LayoutModifierMeasureResult {
481 let placeable = measurable.measure(constraints);
482 cranpose_ui_layout::LayoutModifierMeasureResult::with_size(Size {
483 width: placeable.width(),
484 height: placeable.height(),
485 })
486 }
487
488 fn min_intrinsic_width(
490 &self,
491 _measurable: &dyn Measurable,
492 _height: f32,
493 _density: f32,
494 ) -> f32 {
495 0.0
496 }
497
498 fn max_intrinsic_width(
500 &self,
501 _measurable: &dyn Measurable,
502 _height: f32,
503 _density: f32,
504 ) -> f32 {
505 0.0
506 }
507
508 fn min_intrinsic_height(
510 &self,
511 _measurable: &dyn Measurable,
512 _width: f32,
513 _density: f32,
514 ) -> f32 {
515 0.0
516 }
517
518 fn max_intrinsic_height(
520 &self,
521 _measurable: &dyn Measurable,
522 _width: f32,
523 _density: f32,
524 ) -> f32 {
525 0.0
526 }
527}
528
529pub trait DrawModifierNode: ModifierNode {
536 fn create_draw_closure(&self) -> Option<NodeDrawClosure> {
547 None
548 }
549
550 fn create_behind_draw_closure(&self) -> Option<NodeDrawClosure> {
555 None
556 }
557}
558
559pub type NodeDrawClosure = Rc<dyn Fn(&mut cranpose_ui_graphics::DrawScopeDefault)>;
564
565pub trait PointerInputNode: ModifierNode {
571 fn on_pointer_event(
574 &mut self,
575 _context: &mut dyn ModifierNodeContext,
576 _event: &PointerEvent,
577 ) -> bool {
578 false
579 }
580
581 fn hit_test(&self, _x: f32, _y: f32) -> bool {
584 true
585 }
586
587 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
589 None
590 }
591
592 fn layout_size_sink(&self) -> Option<Rc<Cell<Size>>> {
605 None
606 }
607}
608
609pub trait SemanticsNode: ModifierNode {
615 fn merge_semantics(&self, _config: &mut SemanticsConfiguration) {}
617
618 fn reach(&self) -> SemanticsReach {
622 let mut config = SemanticsConfiguration::default();
623 self.merge_semantics(&mut config);
624 SemanticsReach {
625 is_modal: config.is_modal,
626 hidden: config.hidden,
627 }
628 }
629}
630
631#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
634pub struct SemanticsReach {
635 pub is_modal: bool,
637 pub hidden: bool,
639}
640
641impl SemanticsReach {
642 pub fn union(self, other: Self) -> Self {
644 Self {
645 is_modal: self.is_modal || other.is_modal,
646 hidden: self.hidden || other.hidden,
647 }
648 }
649}
650
651#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
656pub enum FocusState {
657 Active,
659 ActiveParent,
661 Captured,
665 #[default]
668 Inactive,
669}
670
671impl FocusState {
672 pub fn is_focused(self) -> bool {
674 matches!(self, FocusState::Active | FocusState::Captured)
675 }
676
677 pub fn has_focus(self) -> bool {
679 matches!(
680 self,
681 FocusState::Active | FocusState::ActiveParent | FocusState::Captured
682 )
683 }
684
685 pub fn is_captured(self) -> bool {
687 matches!(self, FocusState::Captured)
688 }
689}
690
691pub trait FocusNode: ModifierNode {
696 fn focus_state(&self) -> FocusState;
698
699 fn on_focus_changed(&mut self, _context: &mut dyn ModifierNodeContext, _state: FocusState) {}
701}
702
703#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
714pub enum SemanticsWidgetRole {
715 Button,
716 Checkbox,
717 Switch,
718 RadioButton,
719 Tab,
720 Image,
721 DropdownList,
724 ValuePicker,
727 Header,
732 Dialog,
736 Link,
739 SearchField,
742 ProgressBar,
745 ToggleButton,
748 Alert,
751 Toolbar,
754 Menu,
756 MenuItem,
758 TabBar,
761 List,
763 ListItem,
765 RadioGroup,
767}
768
769#[derive(Clone, Copy, Debug, PartialEq)]
777pub struct ProgressBarRangeInfo {
778 pub current: f32,
779 pub start: f32,
780 pub end: f32,
781 pub steps: u32,
784}
785
786impl ProgressBarRangeInfo {
787 pub fn new(current: f32, start: f32, end: f32, steps: u32) -> Self {
788 Self {
789 current,
790 start,
791 end,
792 steps,
793 }
794 }
795
796 pub fn fraction(&self) -> f32 {
798 let span = self.end - self.start;
799 if span.abs() < f32::EPSILON {
800 return 0.0;
801 }
802 ((self.current - self.start) / span).clamp(0.0, 1.0)
803 }
804
805 pub fn step(&self) -> f32 {
808 let span = self.end - self.start;
809 if self.steps == 0 {
810 span / 10.0
811 } else {
812 span / (self.steps as f32 + 1.0)
813 }
814 }
815}
816
817#[derive(Clone, Copy, Debug, PartialEq, Eq)]
822pub struct CollectionInfo {
823 pub rows: usize,
824 pub columns: usize,
825}
826
827#[derive(Clone, Copy, Debug, PartialEq)]
838pub struct ScrollAxisRange {
839 pub value: f32,
840 pub max_value: f32,
841 pub reverse: bool,
842 pub content_padding_start: f32,
843 pub content_padding_end: f32,
844}
845
846impl ScrollAxisRange {
847 pub fn new(value: f32, max_value: f32, reverse: bool) -> Self {
848 Self {
849 value,
850 max_value,
851 reverse,
852 content_padding_start: 0.0,
853 content_padding_end: 0.0,
854 }
855 }
856
857 pub fn with_content_padding(self, start: f32, end: f32) -> Self {
860 Self {
861 content_padding_start: start,
862 content_padding_end: end,
863 ..self
864 }
865 }
866
867 pub fn can_scroll_forward(&self) -> bool {
868 self.value < self.max_value
869 }
870
871 pub fn can_scroll_backward(&self) -> bool {
872 self.value > 0.0
873 }
874}
875
876#[derive(Clone)]
882pub struct SemanticsScrollBy {
883 handler: Rc<dyn Fn(f32, f32) -> bool>,
884}
885
886impl SemanticsScrollBy {
887 pub fn new(handler: impl Fn(f32, f32) -> bool + 'static) -> Self {
888 Self {
889 handler: Rc::new(handler),
890 }
891 }
892
893 pub fn invoke(&self, dx: f32, dy: f32) -> bool {
894 (self.handler)(dx, dy)
895 }
896}
897
898impl fmt::Debug for SemanticsScrollBy {
899 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
900 f.debug_struct("SemanticsScrollBy").finish_non_exhaustive()
901 }
902}
903
904impl PartialEq for SemanticsScrollBy {
905 fn eq(&self, _other: &Self) -> bool {
906 true
907 }
908}
909
910impl Eq for SemanticsScrollBy {}
911
912#[derive(Clone)]
918pub struct SemanticsScrollToIndex {
919 handler: Rc<dyn Fn(usize) -> bool>,
920}
921
922impl SemanticsScrollToIndex {
923 pub fn new(handler: impl Fn(usize) -> bool + 'static) -> Self {
924 Self {
925 handler: Rc::new(handler),
926 }
927 }
928
929 pub fn invoke(&self, index: usize) -> bool {
930 (self.handler)(index)
931 }
932}
933
934impl fmt::Debug for SemanticsScrollToIndex {
935 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
936 f.debug_struct("SemanticsScrollToIndex")
937 .finish_non_exhaustive()
938 }
939}
940
941impl PartialEq for SemanticsScrollToIndex {
942 fn eq(&self, _other: &Self) -> bool {
943 true
944 }
945}
946
947impl Eq for SemanticsScrollToIndex {}
948
949#[derive(Clone)]
955pub struct SemanticsSetProgress {
956 handler: Rc<dyn Fn(f32) -> bool>,
957}
958
959impl SemanticsSetProgress {
960 pub fn new(handler: impl Fn(f32) -> bool + 'static) -> Self {
961 Self {
962 handler: Rc::new(handler),
963 }
964 }
965
966 pub fn invoke(&self, value: f32) -> bool {
967 (self.handler)(value)
968 }
969}
970
971impl fmt::Debug for SemanticsSetProgress {
972 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
973 f.debug_struct("SemanticsSetProgress")
974 .finish_non_exhaustive()
975 }
976}
977
978#[derive(Clone)]
982pub struct SemanticsSetText(Rc<dyn Fn(&str) -> bool>);
983
984impl SemanticsSetText {
985 pub fn new(handler: impl Fn(&str) -> bool + 'static) -> Self {
986 Self(Rc::new(handler))
987 }
988
989 pub fn invoke(&self, text: &str) -> bool {
990 (self.0)(text)
991 }
992}
993
994impl fmt::Debug for SemanticsSetText {
995 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
996 f.write_str("SemanticsSetText")
997 }
998}
999
1000#[derive(Clone)]
1006pub struct SemanticsSetSelection(Rc<dyn Fn(usize, usize) -> bool>);
1007
1008impl SemanticsSetSelection {
1009 pub fn new(handler: impl Fn(usize, usize) -> bool + 'static) -> Self {
1010 Self(Rc::new(handler))
1011 }
1012
1013 pub fn invoke(&self, anchor: usize, focus: usize) -> bool {
1014 (self.0)(anchor, focus)
1015 }
1016}
1017
1018impl fmt::Debug for SemanticsSetSelection {
1019 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1020 f.write_str("SemanticsSetSelection")
1021 }
1022}
1023
1024#[derive(Clone)]
1027pub struct SemanticsExpand(Rc<dyn Fn() -> bool>);
1028
1029impl SemanticsExpand {
1030 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1031 Self(Rc::new(handler))
1032 }
1033
1034 pub fn invoke(&self) -> bool {
1035 (self.0)()
1036 }
1037}
1038
1039impl fmt::Debug for SemanticsExpand {
1040 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1041 f.write_str("SemanticsExpand")
1042 }
1043}
1044
1045#[derive(Clone)]
1049pub struct SemanticsLongClick(Rc<dyn Fn() -> bool>);
1050
1051impl SemanticsLongClick {
1052 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1053 Self(Rc::new(handler))
1054 }
1055
1056 pub fn invoke(&self) -> bool {
1057 (self.0)()
1058 }
1059}
1060
1061impl fmt::Debug for SemanticsLongClick {
1062 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1063 f.write_str("SemanticsLongClick")
1064 }
1065}
1066
1067impl PartialEq for SemanticsLongClick {
1068 fn eq(&self, _other: &Self) -> bool {
1069 true
1070 }
1071}
1072
1073impl PartialEq for SemanticsExpand {
1074 fn eq(&self, _other: &Self) -> bool {
1075 true
1076 }
1077}
1078
1079#[derive(Clone)]
1083pub struct SemanticsDismiss(Rc<dyn Fn() -> bool>);
1084
1085impl SemanticsDismiss {
1086 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1087 Self(Rc::new(handler))
1088 }
1089
1090 pub fn invoke(&self) -> bool {
1091 (self.0)()
1092 }
1093}
1094
1095impl fmt::Debug for SemanticsDismiss {
1096 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1097 f.write_str("SemanticsDismiss")
1098 }
1099}
1100
1101impl PartialEq for SemanticsDismiss {
1102 fn eq(&self, _other: &Self) -> bool {
1103 true
1104 }
1105}
1106
1107impl PartialEq for SemanticsSetText {
1108 fn eq(&self, _other: &Self) -> bool {
1109 true
1110 }
1111}
1112
1113impl PartialEq for SemanticsSetSelection {
1114 fn eq(&self, _other: &Self) -> bool {
1115 true
1116 }
1117}
1118
1119#[derive(Clone)]
1125pub struct SemanticsMagicTap(Rc<dyn Fn() -> bool>);
1126
1127impl SemanticsMagicTap {
1128 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1129 Self(Rc::new(handler))
1130 }
1131
1132 pub fn invoke(&self) -> bool {
1133 (self.0)()
1134 }
1135}
1136
1137impl fmt::Debug for SemanticsMagicTap {
1138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1139 f.write_str("SemanticsMagicTap")
1140 }
1141}
1142
1143impl PartialEq for SemanticsMagicTap {
1144 fn eq(&self, _other: &Self) -> bool {
1145 true
1146 }
1147}
1148
1149impl PartialEq for SemanticsSetProgress {
1150 fn eq(&self, _other: &Self) -> bool {
1151 true
1152 }
1153}
1154
1155impl Eq for SemanticsSetProgress {}
1156
1157#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1164pub enum LiveRegionMode {
1165 Polite,
1167 Assertive,
1170}
1171
1172#[derive(Clone)]
1179pub struct SemanticsCustomAction {
1180 pub label: String,
1182 handler: Rc<dyn Fn()>,
1183}
1184
1185impl SemanticsCustomAction {
1186 pub fn new(label: impl Into<String>, handler: impl Fn() + 'static) -> Self {
1187 Self {
1188 label: label.into(),
1189 handler: Rc::new(handler),
1190 }
1191 }
1192
1193 pub fn invoke(&self) {
1194 (self.handler)();
1195 }
1196}
1197
1198impl fmt::Debug for SemanticsCustomAction {
1199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1200 f.debug_struct("SemanticsCustomAction")
1201 .field("label", &self.label)
1202 .finish_non_exhaustive()
1203 }
1204}
1205
1206impl PartialEq for SemanticsCustomAction {
1207 fn eq(&self, other: &Self) -> bool {
1208 self.label == other.label
1209 }
1210}
1211
1212impl Eq for SemanticsCustomAction {}
1213
1214#[derive(Clone, Debug, PartialEq)]
1229pub struct CanvasSemanticsNode {
1230 pub key: u64,
1237 pub bounds: cranpose_ui_graphics::Rect,
1239 pub label: String,
1240 pub role: Option<SemanticsWidgetRole>,
1241 pub state_description: Option<String>,
1245 pub on_click_label: Option<String>,
1248 pub clickable: bool,
1249 pub selected: Option<bool>,
1251 pub toggled: Option<bool>,
1253 pub enabled: bool,
1254 pub custom_actions: Vec<SemanticsCustomAction>,
1255}
1256
1257impl Default for CanvasSemanticsNode {
1258 fn default() -> Self {
1259 Self {
1260 key: 0,
1261 bounds: cranpose_ui_graphics::Rect {
1262 x: 0.0,
1263 y: 0.0,
1264 width: 0.0,
1265 height: 0.0,
1266 },
1267 label: String::new(),
1268 role: None,
1269 state_description: None,
1270 on_click_label: None,
1271 clickable: false,
1272 selected: None,
1273 toggled: None,
1274 enabled: true,
1275 custom_actions: Vec::new(),
1276 }
1277 }
1278}
1279
1280impl CanvasSemanticsNode {
1281 pub fn control(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1283 Self {
1284 key,
1285 bounds,
1286 label: label.into(),
1287 clickable: true,
1288 ..Self::default()
1289 }
1290 }
1291
1292 pub fn text(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1294 Self {
1295 key,
1296 bounds,
1297 label: label.into(),
1298 ..Self::default()
1299 }
1300 }
1301
1302 pub fn with_role(mut self, role: SemanticsWidgetRole) -> Self {
1303 self.role = Some(role);
1304 self
1305 }
1306
1307 pub fn with_state_description(mut self, state: impl Into<String>) -> Self {
1308 self.state_description = Some(state.into());
1309 self
1310 }
1311
1312 pub fn with_click_label(mut self, label: impl Into<String>) -> Self {
1313 self.on_click_label = Some(label.into());
1314 self.clickable = true;
1315 self
1316 }
1317
1318 pub fn with_selected(mut self, selected: bool) -> Self {
1319 self.selected = Some(selected);
1320 self
1321 }
1322
1323 pub fn with_toggled(mut self, toggled: bool) -> Self {
1324 self.toggled = Some(toggled);
1325 self
1326 }
1327
1328 pub fn with_enabled(mut self, enabled: bool) -> Self {
1329 self.enabled = enabled;
1330 self
1331 }
1332
1333 pub fn with_custom_action(mut self, action: SemanticsCustomAction) -> Self {
1334 self.custom_actions.push(action);
1335 self
1336 }
1337}
1338
1339#[derive(Clone, Debug, PartialEq)]
1341pub struct SemanticsConfiguration {
1342 pub content_description: Option<String>,
1343 pub state_description: Option<String>,
1345 pub on_click_label: Option<String>,
1347 pub on_click: Option<SemanticsCustomAction>,
1350 pub on_long_click: Option<SemanticsLongClick>,
1353 pub on_long_click_label: Option<String>,
1356 pub on_magic_tap: Option<SemanticsMagicTap>,
1360 pub on_magic_tap_label: Option<String>,
1363 pub input_labels: Vec<String>,
1367 pub language: Option<String>,
1371 pub role: Option<SemanticsWidgetRole>,
1373 pub selected: Option<bool>,
1374 pub toggled: Option<bool>,
1375 pub enabled: bool,
1376 pub is_clickable: bool,
1377 pub is_editable_text: bool,
1378 pub multiline: bool,
1380 pub text: Option<String>,
1383 pub text_selection: Option<crate::text::TextRange>,
1384 pub custom_actions: Vec<SemanticsCustomAction>,
1385 pub canvas_children: Vec<CanvasSemanticsNode>,
1388 pub is_modal: bool,
1391 pub hidden: bool,
1395 pub merge_descendants: bool,
1399 pub selectable_group: bool,
1403 pub pane_title: Option<String>,
1406 pub error: Option<String>,
1409 pub password: bool,
1412 pub traversal_index: f32,
1416 pub live_region: Option<LiveRegionMode>,
1419 pub progress: Option<ProgressBarRangeInfo>,
1422 pub set_progress: Option<SemanticsSetProgress>,
1425 pub set_text: Option<SemanticsSetText>,
1428 pub set_selection: Option<SemanticsSetSelection>,
1431 pub expand: Option<SemanticsExpand>,
1434 pub dismiss: Option<SemanticsDismiss>,
1438 pub collapse: Option<SemanticsExpand>,
1441 pub vertical_scroll: Option<ScrollAxisRange>,
1444 pub horizontal_scroll: Option<ScrollAxisRange>,
1447 pub scroll_by: Option<SemanticsScrollBy>,
1450 pub scroll_to_index: Option<SemanticsScrollToIndex>,
1454 pub collection: Option<CollectionInfo>,
1456}
1457
1458impl Default for SemanticsConfiguration {
1459 fn default() -> Self {
1460 Self {
1461 content_description: None,
1462 state_description: None,
1463 on_click_label: None,
1464 on_click: None,
1465 on_long_click: None,
1466 on_long_click_label: None,
1467 on_magic_tap: None,
1468 on_magic_tap_label: None,
1469 input_labels: Vec::new(),
1470 language: None,
1471 role: None,
1472 selected: None,
1473 toggled: None,
1474 enabled: true,
1475 is_clickable: false,
1476 is_editable_text: false,
1477 multiline: false,
1478 text: None,
1479 text_selection: None,
1480 custom_actions: Vec::new(),
1481 canvas_children: Vec::new(),
1482 is_modal: false,
1483 hidden: false,
1484 merge_descendants: false,
1485 selectable_group: false,
1486 pane_title: None,
1487 error: None,
1488 password: false,
1489 traversal_index: 0.0,
1490 live_region: None,
1491 progress: None,
1492 set_progress: None,
1493 set_text: None,
1494 set_selection: None,
1495 expand: None,
1496 dismiss: None,
1497 collapse: None,
1498 vertical_scroll: None,
1499 horizontal_scroll: None,
1500 scroll_by: None,
1501 scroll_to_index: None,
1502 collection: None,
1503 }
1504 }
1505}
1506
1507pub type SemanticsSpec = SemanticsConfiguration;
1516
1517impl SemanticsConfiguration {
1518 pub fn new() -> Self {
1521 Self::default()
1522 }
1523
1524 pub fn content_description(mut self, name: impl Into<String>) -> Self {
1527 self.content_description = Some(name.into());
1528 self
1529 }
1530
1531 pub fn state_description(mut self, state: impl Into<String>) -> Self {
1534 self.state_description = Some(state.into());
1535 self
1536 }
1537
1538 pub fn clickable(mut self) -> Self {
1540 self.is_clickable = true;
1541 self
1542 }
1543
1544 pub fn on_click(mut self, label: impl Into<String>, action: impl Fn() + 'static) -> Self {
1547 self.on_click = Some(SemanticsCustomAction::new(label, action));
1548 self
1549 }
1550
1551 pub fn on_long_click(
1555 mut self,
1556 label: impl Into<String>,
1557 action: impl Fn() -> bool + 'static,
1558 ) -> Self {
1559 self.on_long_click_label = Some(label.into());
1560 self.on_long_click = Some(SemanticsLongClick::new(action));
1561 self
1562 }
1563
1564 pub fn on_magic_tap(
1568 mut self,
1569 label: impl Into<String>,
1570 action: impl Fn() -> bool + 'static,
1571 ) -> Self {
1572 self.on_magic_tap_label = Some(label.into());
1573 self.on_magic_tap = Some(SemanticsMagicTap::new(action));
1574 self
1575 }
1576
1577 pub fn input_labels<S: Into<String>>(mut self, labels: impl IntoIterator<Item = S>) -> Self {
1580 self.input_labels = labels.into_iter().map(Into::into).collect();
1581 self
1582 }
1583
1584 pub fn language(mut self, tag: impl Into<String>) -> Self {
1587 self.language = Some(tag.into());
1588 self
1589 }
1590
1591 pub fn toggled(mut self, toggled: bool) -> Self {
1593 self.toggled = Some(toggled);
1594 self
1595 }
1596
1597 pub fn selected(mut self, selected: bool) -> Self {
1600 self.selected = Some(selected);
1601 self
1602 }
1603
1604 pub fn role(mut self, role: SemanticsWidgetRole) -> Self {
1606 self.role = Some(role);
1607 self
1608 }
1609
1610 pub fn heading(self) -> Self {
1613 self.role(SemanticsWidgetRole::Header)
1614 }
1615
1616 pub fn error(mut self, message: impl Into<String>) -> Self {
1618 self.error = Some(message.into());
1619 self
1620 }
1621
1622 pub fn password(mut self) -> Self {
1624 self.password = true;
1625 self
1626 }
1627
1628 pub fn pane_title(mut self, title: impl Into<String>) -> Self {
1631 self.pane_title = Some(title.into());
1632 self
1633 }
1634
1635 pub fn traversal_index(mut self, index: f32) -> Self {
1638 self.traversal_index = index;
1639 self
1640 }
1641
1642 pub fn hidden(mut self) -> Self {
1645 self.hidden = true;
1646 self
1647 }
1648
1649 pub fn merge_descendants(mut self) -> Self {
1652 self.merge_descendants = true;
1653 self
1654 }
1655
1656 pub fn selectable_group(mut self) -> Self {
1659 self.selectable_group = true;
1660 self
1661 }
1662
1663 pub fn live_region(mut self, mode: LiveRegionMode) -> Self {
1666 self.live_region = Some(mode);
1667 self
1668 }
1669 pub fn merge(&mut self, other: &SemanticsConfiguration) {
1670 if let Some(description) = &other.content_description {
1671 self.content_description = Some(description.clone());
1672 }
1673 if let Some(state) = &other.state_description {
1674 self.state_description = Some(state.clone());
1675 }
1676 if let Some(label) = &other.on_click_label {
1677 self.on_click_label = Some(label.clone());
1678 }
1679 if let Some(label) = &other.on_long_click_label {
1680 self.on_long_click_label = Some(label.clone());
1681 }
1682 if let Some(label) = &other.on_magic_tap_label {
1683 self.on_magic_tap_label = Some(label.clone());
1684 }
1685 if !other.input_labels.is_empty() {
1686 self.input_labels.clone_from(&other.input_labels);
1687 }
1688 if let Some(language) = &other.language {
1689 self.language = Some(language.clone());
1690 }
1691 if let Some(role) = other.role {
1692 self.role = Some(role);
1693 }
1694 if let Some(selected) = other.selected {
1695 self.selected = Some(selected);
1696 }
1697 if let Some(toggled) = other.toggled {
1698 self.toggled = Some(toggled);
1699 }
1700 self.enabled &= other.enabled;
1701 self.is_clickable |= other.is_clickable;
1702 self.is_editable_text |= other.is_editable_text;
1703 self.multiline |= other.multiline;
1704 if let Some(text) = &other.text {
1705 self.text = Some(text.clone());
1706 }
1707 self.is_modal |= other.is_modal;
1708 self.hidden |= other.hidden;
1709 self.merge_descendants |= other.merge_descendants;
1710 self.selectable_group |= other.selectable_group;
1711 self.password |= other.password;
1712 if other.traversal_index != 0.0 {
1713 self.traversal_index = other.traversal_index;
1714 }
1715 if let Some(live_region) = other.live_region {
1716 self.live_region = Some(live_region);
1717 }
1718 self.merge_words(other);
1719 self.merge_actions(other);
1720 self.merge_ranges(other);
1721 }
1722
1723 fn merge_words(&mut self, other: &SemanticsConfiguration) {
1724 if let Some(title) = &other.pane_title {
1725 self.pane_title = Some(title.clone());
1726 }
1727 if let Some(error) = &other.error {
1728 self.error = Some(error.clone());
1729 }
1730 }
1731
1732 fn merge_actions(&mut self, other: &SemanticsConfiguration) {
1733 if let Some(on_click) = &other.on_click {
1734 self.on_click = Some(on_click.clone());
1735 }
1736 self.custom_actions
1737 .extend(other.custom_actions.iter().cloned());
1738 self.canvas_children
1739 .extend(other.canvas_children.iter().cloned());
1740 if let Some(set_progress) = &other.set_progress {
1741 self.set_progress = Some(set_progress.clone());
1742 }
1743 if let Some(set_text) = &other.set_text {
1744 self.set_text = Some(set_text.clone());
1745 }
1746 if let Some(set_selection) = &other.set_selection {
1747 self.set_selection = Some(set_selection.clone());
1748 }
1749 if let Some(expand) = &other.expand {
1750 self.expand = Some(expand.clone());
1751 }
1752 if let Some(collapse) = &other.collapse {
1753 self.collapse = Some(collapse.clone());
1754 }
1755 if let Some(dismiss) = &other.dismiss {
1756 self.dismiss = Some(dismiss.clone());
1757 }
1758 if let Some(long_click) = &other.on_long_click {
1759 self.on_long_click = Some(long_click.clone());
1760 }
1761 if let Some(magic_tap) = &other.on_magic_tap {
1762 self.on_magic_tap = Some(magic_tap.clone());
1763 }
1764 if let Some(scroll_by) = &other.scroll_by {
1765 self.scroll_by = Some(scroll_by.clone());
1766 }
1767 if let Some(scroll_to_index) = &other.scroll_to_index {
1768 self.scroll_to_index = Some(scroll_to_index.clone());
1769 }
1770 }
1771
1772 fn merge_ranges(&mut self, other: &SemanticsConfiguration) {
1773 if let Some(selection) = other.text_selection {
1774 self.text_selection = Some(selection);
1775 }
1776 if let Some(progress) = other.progress {
1777 self.progress = Some(progress);
1778 }
1779 if let Some(range) = other.vertical_scroll {
1780 self.vertical_scroll = Some(range);
1781 }
1782 if let Some(range) = other.horizontal_scroll {
1783 self.horizontal_scroll = Some(range);
1784 }
1785 if let Some(collection) = other.collection {
1786 self.collection = Some(collection);
1787 }
1788 }
1789
1790 pub fn is_activatable(&self) -> bool {
1793 self.is_clickable || self.on_click_label.is_some() || self.on_click.is_some()
1794 }
1795}
1796
1797impl fmt::Debug for dyn ModifierNode {
1798 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1799 f.debug_struct("ModifierNode").finish_non_exhaustive()
1800 }
1801}
1802
1803impl dyn ModifierNode {
1804 pub fn as_any(&self) -> &dyn Any {
1805 self
1806 }
1807
1808 pub fn as_any_mut(&mut self) -> &mut dyn Any {
1809 self
1810 }
1811}
1812
1813pub trait ModifierNodeElement: fmt::Debug + Hash + PartialEq + 'static {
1816 type Node: ModifierNode;
1817
1818 fn create(&self) -> Self::Node;
1820
1821 fn update(&self, node: &mut Self::Node);
1823
1824 fn key(&self) -> Option<u64> {
1826 None
1827 }
1828
1829 fn inspector_name(&self) -> &'static str {
1831 type_name::<Self>()
1832 }
1833
1834 fn inspector_properties(&self, _inspector: &mut dyn FnMut(&'static str, String)) {}
1836
1837 fn capabilities(&self) -> NodeCapabilities {
1840 NodeCapabilities::default()
1841 }
1842
1843 fn always_update(&self) -> bool {
1849 false
1850 }
1851
1852 fn auto_invalidate_on_update(&self) -> bool {
1855 true
1856 }
1857
1858 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
1865 None
1866 }
1867
1868 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
1875 Vec::new()
1876 }
1877}
1878
1879#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1881pub struct NodeCapabilities(u32);
1882
1883impl NodeCapabilities {
1884 pub const NONE: Self = Self(0);
1886 pub const LAYOUT: Self = Self(1 << 0);
1888 pub const DRAW: Self = Self(1 << 1);
1890 pub const POINTER_INPUT: Self = Self(1 << 2);
1892 pub const SEMANTICS: Self = Self(1 << 3);
1894 pub const MODIFIER_LOCALS: Self = Self(1 << 4);
1896 pub const FOCUS: Self = Self(1 << 5);
1898 pub const WINDOW_ROOT: Self = Self(1 << 6);
1902
1903 pub const fn empty() -> Self {
1905 Self::NONE
1906 }
1907
1908 pub const fn contains(self, other: Self) -> bool {
1910 (self.0 & other.0) == other.0
1911 }
1912
1913 pub const fn intersects(self, other: Self) -> bool {
1915 (self.0 & other.0) != 0
1916 }
1917
1918 pub fn insert(&mut self, other: Self) {
1920 self.0 |= other.0;
1921 }
1922
1923 pub const fn bits(self) -> u32 {
1925 self.0
1926 }
1927
1928 pub const fn is_empty(self) -> bool {
1930 self.0 == 0
1931 }
1932
1933 pub const fn for_invalidation(kind: InvalidationKind) -> Self {
1935 match kind {
1936 InvalidationKind::Layout => Self::LAYOUT,
1937 InvalidationKind::Draw => Self::DRAW,
1938 InvalidationKind::PointerInput => Self::POINTER_INPUT,
1939 InvalidationKind::Semantics => Self::SEMANTICS,
1940 InvalidationKind::Focus => Self::FOCUS,
1941 }
1942 }
1943}
1944
1945impl Default for NodeCapabilities {
1946 fn default() -> Self {
1947 Self::NONE
1948 }
1949}
1950
1951impl fmt::Debug for NodeCapabilities {
1952 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1953 f.debug_struct("NodeCapabilities")
1954 .field("layout", &self.contains(Self::LAYOUT))
1955 .field("draw", &self.contains(Self::DRAW))
1956 .field("pointer_input", &self.contains(Self::POINTER_INPUT))
1957 .field("semantics", &self.contains(Self::SEMANTICS))
1958 .field("modifier_locals", &self.contains(Self::MODIFIER_LOCALS))
1959 .field("focus", &self.contains(Self::FOCUS))
1960 .field("window_root", &self.contains(Self::WINDOW_ROOT))
1961 .finish()
1962 }
1963}
1964
1965impl BitOr for NodeCapabilities {
1966 type Output = Self;
1967
1968 fn bitor(self, rhs: Self) -> Self::Output {
1969 Self(self.0 | rhs.0)
1970 }
1971}
1972
1973impl BitOrAssign for NodeCapabilities {
1974 fn bitor_assign(&mut self, rhs: Self) {
1975 self.0 |= rhs.0;
1976 }
1977}
1978
1979#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1981pub struct ModifierInvalidation {
1982 kind: InvalidationKind,
1983 capabilities: NodeCapabilities,
1984}
1985
1986impl ModifierInvalidation {
1987 pub const fn new(kind: InvalidationKind, capabilities: NodeCapabilities) -> Self {
1989 Self { kind, capabilities }
1990 }
1991
1992 pub const fn kind(self) -> InvalidationKind {
1994 self.kind
1995 }
1996
1997 pub const fn capabilities(self) -> NodeCapabilities {
1999 self.capabilities
2000 }
2001}
2002
2003pub trait AnyModifierElement: fmt::Debug {
2005 fn node_type(&self) -> TypeId;
2006
2007 fn element_type(&self) -> TypeId;
2008
2009 fn create_node(&self) -> Box<dyn ModifierNode>;
2010
2011 fn can_update_node(&self, node: &dyn ModifierNode) -> bool;
2012
2013 fn update_node(&self, node: &mut dyn ModifierNode);
2014
2015 fn key(&self) -> Option<u64>;
2016
2017 fn capabilities(&self) -> NodeCapabilities {
2018 NodeCapabilities::default()
2019 }
2020
2021 fn hash_code(&self) -> u64;
2022
2023 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool;
2024
2025 fn inspector_name(&self) -> &'static str;
2026
2027 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String));
2028
2029 fn requires_update(&self) -> bool;
2030
2031 fn auto_invalidates_on_update(&self) -> bool;
2032
2033 fn update_invalidation_kind(&self) -> Option<InvalidationKind>;
2034
2035 fn provides_composition_locals(&self) -> bool {
2037 false
2038 }
2039
2040 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2042 Vec::new()
2043 }
2044
2045 fn as_any(&self) -> &dyn Any;
2046}
2047
2048struct TypedModifierElement<E: ModifierNodeElement> {
2049 element: E,
2050 cached_hash: u64,
2051 provides_locals: bool,
2052}
2053
2054impl<E: ModifierNodeElement> TypedModifierElement<E> {
2055 fn new(element: E) -> Self {
2056 let mut hasher = default::new();
2057 element.hash(&mut hasher);
2058 let provides_locals = !element.provided_composition_locals().is_empty();
2059 Self {
2060 element,
2061 cached_hash: hasher.finish(),
2062 provides_locals,
2063 }
2064 }
2065}
2066
2067impl<E> fmt::Debug for TypedModifierElement<E>
2068where
2069 E: ModifierNodeElement,
2070{
2071 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2072 f.debug_struct("TypedModifierElement")
2073 .field("type", &type_name::<E>())
2074 .finish()
2075 }
2076}
2077
2078impl<E> AnyModifierElement for TypedModifierElement<E>
2079where
2080 E: ModifierNodeElement,
2081{
2082 fn node_type(&self) -> TypeId {
2083 TypeId::of::<E::Node>()
2084 }
2085
2086 fn element_type(&self) -> TypeId {
2087 TypeId::of::<E>()
2088 }
2089
2090 fn create_node(&self) -> Box<dyn ModifierNode> {
2091 Box::new(self.element.create())
2092 }
2093
2094 fn can_update_node(&self, node: &dyn ModifierNode) -> bool {
2095 node.as_any().is::<E::Node>()
2096 }
2097
2098 fn update_node(&self, node: &mut dyn ModifierNode) {
2099 if let Some(typed) = node.as_any_mut().downcast_mut::<E::Node>() {
2100 self.element.update(typed);
2101 }
2102 }
2103
2104 fn key(&self) -> Option<u64> {
2105 self.element.key()
2106 }
2107
2108 fn capabilities(&self) -> NodeCapabilities {
2109 self.element.capabilities()
2110 }
2111
2112 fn provides_composition_locals(&self) -> bool {
2113 self.provides_locals
2114 }
2115
2116 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2117 self.element.provided_composition_locals()
2118 }
2119
2120 fn hash_code(&self) -> u64 {
2121 self.cached_hash
2122 }
2123
2124 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool {
2125 other
2126 .as_any()
2127 .downcast_ref::<Self>()
2128 .is_some_and(|typed| typed.element == self.element)
2129 }
2130
2131 fn inspector_name(&self) -> &'static str {
2132 self.element.inspector_name()
2133 }
2134
2135 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String)) {
2136 self.element.inspector_properties(visitor);
2137 }
2138
2139 fn requires_update(&self) -> bool {
2140 self.element.always_update()
2141 }
2142
2143 fn auto_invalidates_on_update(&self) -> bool {
2144 self.element.auto_invalidate_on_update()
2145 }
2146
2147 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
2148 self.element.update_invalidation_kind()
2149 }
2150
2151 fn as_any(&self) -> &dyn Any {
2152 self
2153 }
2154}
2155
2156fn request_update_auto_invalidations(
2157 element: &dyn AnyModifierElement,
2158 context: &mut dyn ModifierNodeContext,
2159 capabilities: NodeCapabilities,
2160) {
2161 if let Some(kind) = element.update_invalidation_kind() {
2162 let capabilities = NodeCapabilities::for_invalidation(kind);
2163 context.push_active_capabilities(capabilities);
2164 context.invalidate(kind);
2165 context.pop_active_capabilities();
2166 } else if element.auto_invalidates_on_update() {
2167 request_auto_invalidations(context, capabilities);
2168 }
2169}
2170
2171pub fn modifier_element<E: ModifierNodeElement>(element: E) -> DynModifierElement {
2174 Rc::new(TypedModifierElement::new(element))
2175}
2176
2177pub type DynModifierElement = Rc<dyn AnyModifierElement>;
2179
2180#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2181enum TraversalDirection {
2182 Forward,
2183 Backward,
2184}
2185
2186pub struct ModifierChainIter<'a> {
2191 chain: &'a ModifierNodeChain,
2192 cursor: usize,
2193 remaining: usize,
2194 direction: TraversalDirection,
2195}
2196
2197impl<'a> ModifierChainIter<'a> {
2198 fn forward(chain: &'a ModifierNodeChain) -> Self {
2199 Self {
2200 chain,
2201 cursor: 0,
2202 remaining: chain.ordered_nodes.len(),
2203 direction: TraversalDirection::Forward,
2204 }
2205 }
2206
2207 fn backward(chain: &'a ModifierNodeChain) -> Self {
2208 let len = chain.ordered_nodes.len();
2209 Self {
2210 chain,
2211 cursor: len.wrapping_sub(1),
2212 remaining: len,
2213 direction: TraversalDirection::Backward,
2214 }
2215 }
2216}
2217
2218impl<'a> Iterator for ModifierChainIter<'a> {
2219 type Item = ModifierChainNodeRef<'a>;
2220
2221 #[inline]
2222 fn next(&mut self) -> Option<Self::Item> {
2223 if self.remaining == 0 {
2224 return None;
2225 }
2226 let (link, caps, agg) = self.chain.ordered_nodes[self.cursor];
2227 let node_ref = self.chain.make_node_ref_with_caps(link, caps, agg);
2228 self.remaining -= 1;
2229 match self.direction {
2230 TraversalDirection::Forward => self.cursor += 1,
2231 TraversalDirection::Backward => self.cursor = self.cursor.wrapping_sub(1),
2232 }
2233 Some(node_ref)
2234 }
2235
2236 #[inline]
2237 fn size_hint(&self) -> (usize, Option<usize>) {
2238 (self.remaining, Some(self.remaining))
2239 }
2240}
2241
2242impl ExactSizeIterator for ModifierChainIter<'_> {}
2243impl std::iter::FusedIterator for ModifierChainIter<'_> {}
2244
2245#[derive(Debug)]
2246struct ModifierNodeEntry {
2247 element_type: TypeId,
2248 node_type: TypeId,
2249 key: Option<u64>,
2250 hash_code: u64,
2251 element: DynModifierElement,
2252 node: Rc<RefCell<Box<dyn ModifierNode>>>,
2253 capabilities: NodeCapabilities,
2254}
2255
2256impl ModifierNodeEntry {
2257 fn new(
2258 element_type: TypeId,
2259 node_type: TypeId,
2260 key: Option<u64>,
2261 element: DynModifierElement,
2262 node: Box<dyn ModifierNode>,
2263 hash_code: u64,
2264 capabilities: NodeCapabilities,
2265 ) -> Self {
2266 let node_rc = Rc::new(RefCell::new(node));
2267 let entry = Self {
2268 element_type,
2269 node_type,
2270 key,
2271 hash_code,
2272 element,
2273 node: Rc::clone(&node_rc),
2274 capabilities,
2275 };
2276 entry
2277 .node
2278 .borrow()
2279 .node_state()
2280 .set_capabilities(entry.capabilities);
2281 entry
2282 }
2283}
2284
2285fn visit_node_tree_mut(
2286 node: &mut dyn ModifierNode,
2287 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
2288) {
2289 visitor(node);
2290 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
2291}
2292
2293fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
2294 let mut current = 0usize;
2295 let mut result: Option<&dyn ModifierNode> = None;
2296 node.for_each_delegate(&mut |child| {
2297 if result.is_none() && current == target {
2298 result = Some(child);
2299 }
2300 current += 1;
2301 });
2302 result
2303}
2304
2305fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
2306 let mut current = 0usize;
2307 let mut result: Option<&mut dyn ModifierNode> = None;
2308 node.for_each_delegate_mut(&mut |child| {
2309 if result.is_none() && current == target {
2310 result = Some(child);
2311 }
2312 current += 1;
2313 });
2314 result
2315}
2316
2317fn with_node_context<F, R>(
2318 node: &mut dyn ModifierNode,
2319 context: &mut dyn ModifierNodeContext,
2320 f: F,
2321) -> R
2322where
2323 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
2324{
2325 context.push_active_capabilities(node.node_state().capabilities());
2326 let result = f(node, context);
2327 context.pop_active_capabilities();
2328 result
2329}
2330
2331fn request_auto_invalidations(
2332 context: &mut dyn ModifierNodeContext,
2333 capabilities: NodeCapabilities,
2334) {
2335 if capabilities.is_empty() {
2336 return;
2337 }
2338
2339 context.push_active_capabilities(capabilities);
2340
2341 if capabilities.contains(NodeCapabilities::LAYOUT) {
2342 context.invalidate(InvalidationKind::Layout);
2343 }
2344 if capabilities.contains(NodeCapabilities::DRAW) {
2345 context.invalidate(InvalidationKind::Draw);
2346 }
2347 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
2348 context.invalidate(InvalidationKind::PointerInput);
2349 }
2350 if capabilities.contains(NodeCapabilities::SEMANTICS) {
2351 context.invalidate(InvalidationKind::Semantics);
2352 }
2353 if capabilities.contains(NodeCapabilities::FOCUS) {
2354 context.invalidate(InvalidationKind::Focus);
2355 }
2356
2357 context.pop_active_capabilities();
2358}
2359
2360fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
2361 visit_node_tree_mut(node, &mut |n| {
2362 if !n.node_state().is_attached() {
2363 n.node_state().set_attached(true);
2364 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
2365 }
2366 });
2367}
2368
2369fn reset_node_tree(node: &mut dyn ModifierNode) {
2370 visit_node_tree_mut(node, &mut |n| n.on_reset());
2371}
2372
2373fn detach_node_tree(node: &mut dyn ModifierNode) {
2374 visit_node_tree_mut(node, &mut |n| {
2375 if n.node_state().is_attached() {
2376 n.on_detach();
2377 n.node_state().set_attached(false);
2378 }
2379 n.node_state().set_parent_link(None);
2380 n.node_state().set_child_link(None);
2381 n.node_state()
2382 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2383 });
2384}
2385
2386pub struct ModifierNodeChain {
2393 entries: Vec<ModifierNodeEntry>,
2394 aggregated_capabilities: NodeCapabilities,
2395 head_aggregate_child_capabilities: NodeCapabilities,
2396 head_sentinel: Box<SentinelNode>,
2397 tail_sentinel: Box<SentinelNode>,
2398 ordered_nodes: Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
2399 scratch_old_used: Vec<bool>,
2400 scratch_match_order: Vec<Option<usize>>,
2401 scratch_final_slots: Vec<Option<ModifierNodeEntry>>,
2402 scratch_elements: Vec<DynModifierElement>,
2403}
2404
2405struct SentinelNode {
2406 state: NodeState,
2407}
2408
2409impl SentinelNode {
2410 fn new() -> Self {
2411 Self {
2412 state: NodeState::sentinel(),
2413 }
2414 }
2415}
2416
2417impl DelegatableNode for SentinelNode {
2418 fn node_state(&self) -> &NodeState {
2419 &self.state
2420 }
2421}
2422
2423impl ModifierNode for SentinelNode {}
2424
2425#[derive(Clone)]
2426pub struct ModifierChainNodeRef<'a> {
2427 chain: &'a ModifierNodeChain,
2428 link: NodeLink,
2429 cached_capabilities: Option<NodeCapabilities>,
2430 cached_aggregate_child: Option<NodeCapabilities>,
2431}
2432
2433impl Default for ModifierNodeChain {
2434 fn default() -> Self {
2435 Self::new()
2436 }
2437}
2438
2439struct EntryIndex {
2440 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2441 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2442 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
2443}
2444
2445struct EntryMatchQuery<'a> {
2446 element_type: TypeId,
2447 node_type: TypeId,
2448 key: Option<u64>,
2449 hash_code: u64,
2450 element: &'a DynModifierElement,
2451}
2452
2453impl EntryIndex {
2454 fn build(entries: &[ModifierNodeEntry]) -> Self {
2455 let mut keyed = HashMap::default();
2456 let mut hashed = HashMap::default();
2457 let mut typed = HashMap::default();
2458
2459 for (i, entry) in entries.iter().enumerate() {
2460 if let Some(key_value) = entry.key {
2461 keyed
2462 .entry((entry.element_type, entry.node_type, key_value))
2463 .or_insert_with(Vec::new)
2464 .push(i);
2465 } else {
2466 hashed
2467 .entry((entry.element_type, entry.node_type, entry.hash_code))
2468 .or_insert_with(Vec::new)
2469 .push(i);
2470 typed
2471 .entry((entry.element_type, entry.node_type))
2472 .or_insert_with(Vec::new)
2473 .push(i);
2474 }
2475 }
2476
2477 Self {
2478 keyed,
2479 hashed,
2480 typed,
2481 }
2482 }
2483
2484 fn find_match(
2485 &self,
2486 entries: &[ModifierNodeEntry],
2487 used: &[bool],
2488 query: EntryMatchQuery<'_>,
2489 ) -> Option<usize> {
2490 if let Some(key_value) = query.key {
2491 if let Some(candidates) =
2492 self.keyed
2493 .get(&(query.element_type, query.node_type, key_value))
2494 {
2495 for &i in candidates {
2496 if !used[i] {
2497 return Some(i);
2498 }
2499 }
2500 }
2501 } else {
2502 if let Some(candidates) =
2503 self.hashed
2504 .get(&(query.element_type, query.node_type, query.hash_code))
2505 {
2506 for &i in candidates {
2507 if !used[i]
2508 && entries[i]
2509 .element
2510 .as_ref()
2511 .equals_element(query.element.as_ref())
2512 {
2513 return Some(i);
2514 }
2515 }
2516 }
2517
2518 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
2519 for &i in candidates {
2520 if !used[i] {
2521 return Some(i);
2522 }
2523 }
2524 }
2525 }
2526
2527 None
2528 }
2529}
2530
2531impl ModifierNodeChain {
2532 pub fn new() -> Self {
2533 let mut chain = Self {
2534 entries: Vec::new(),
2535 aggregated_capabilities: NodeCapabilities::empty(),
2536 head_aggregate_child_capabilities: NodeCapabilities::empty(),
2537 head_sentinel: Box::new(SentinelNode::new()),
2538 tail_sentinel: Box::new(SentinelNode::new()),
2539 ordered_nodes: Vec::new(),
2540 scratch_old_used: Vec::new(),
2541 scratch_match_order: Vec::new(),
2542 scratch_final_slots: Vec::new(),
2543 scratch_elements: Vec::new(),
2544 };
2545 chain.sync_chain_links();
2546 chain
2547 }
2548
2549 pub fn detach_nodes(&mut self) {
2551 for entry in &self.entries {
2552 detach_node_tree(&mut **entry.node.borrow_mut());
2553 }
2554 }
2555
2556 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
2558 for entry in &self.entries {
2559 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2560 }
2561 }
2562
2563 pub fn repair_chain(&mut self) {
2566 self.sync_chain_links();
2567 }
2568
2569 pub fn update_from_slice(
2575 &mut self,
2576 elements: &[DynModifierElement],
2577 context: &mut dyn ModifierNodeContext,
2578 ) {
2579 self.update_from_ref_iter(elements.iter(), context);
2580 }
2581
2582 pub fn update_from_ref_iter<'a, I>(
2587 &mut self,
2588 elements: I,
2589 context: &mut dyn ModifierNodeContext,
2590 ) where
2591 I: Iterator<Item = &'a DynModifierElement>,
2592 {
2593 let old_len = self.entries.len();
2594 let mut fast_path_failed_at: Option<usize> = None;
2595 let mut elements_count = 0;
2596
2597 self.scratch_elements.clear();
2598
2599 for (idx, element) in elements.enumerate() {
2600 elements_count = idx + 1;
2601
2602 if fast_path_failed_at.is_none() && idx < old_len {
2603 let entry = &mut self.entries[idx];
2604 let same_type = entry.element_type == element.element_type();
2605 let same_node_type = entry.node_type == element.node_type();
2606 let same_key = entry.key == element.key();
2607 let same_hash = entry.hash_code == element.hash_code();
2608
2609 let positional_update = element.requires_update();
2610 if same_type && same_node_type && same_key && (same_hash || positional_update) {
2611 let can_update_node = {
2612 let node_borrow = entry.node.borrow();
2613 element.can_update_node(&**node_borrow)
2614 };
2615 if !can_update_node {
2616 fast_path_failed_at = Some(idx);
2617 self.scratch_elements.push(element.clone());
2618 continue;
2619 }
2620
2621 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2622 let capabilities = element.capabilities();
2623
2624 {
2625 let node_borrow = entry.node.borrow();
2626 if !node_borrow.node_state().is_attached() {
2627 drop(node_borrow);
2628 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2629 }
2630 }
2631
2632 let needs_update = !same_element || element.requires_update();
2633 if needs_update {
2634 element.update_node(&mut **entry.node.borrow_mut());
2635 entry.element = element.clone();
2636 entry.hash_code = element.hash_code();
2637 request_update_auto_invalidations(element.as_ref(), context, capabilities);
2638 }
2639
2640 entry.capabilities = capabilities;
2641 entry
2642 .node
2643 .borrow()
2644 .node_state()
2645 .set_capabilities(capabilities);
2646 continue;
2647 }
2648 fast_path_failed_at = Some(idx);
2649 }
2650
2651 self.scratch_elements.push(element.clone());
2652 }
2653
2654 if fast_path_failed_at.is_none() && self.scratch_elements.is_empty() {
2655 if elements_count < self.entries.len() {
2656 for entry in self.entries.drain(elements_count..) {
2657 request_auto_invalidations(context, entry.capabilities);
2658 detach_node_tree(&mut **entry.node.borrow_mut());
2659 }
2660 }
2661 self.sync_chain_links();
2662 return;
2663 }
2664
2665 let fail_idx = fast_path_failed_at.unwrap_or(old_len);
2666
2667 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
2668 let processed_entries_len = self.entries.len();
2669 let old_len = old_entries.len();
2670
2671 self.scratch_old_used.clear();
2672 self.scratch_old_used.resize(old_len, false);
2673
2674 self.scratch_match_order.clear();
2675 self.scratch_match_order.resize(old_len, None);
2676
2677 let index = EntryIndex::build(&old_entries);
2678
2679 let new_elements_count = self.scratch_elements.len();
2680 self.scratch_final_slots.clear();
2681 self.scratch_final_slots.reserve(new_elements_count);
2682
2683 for (new_pos, element) in self.scratch_elements.drain(..).enumerate() {
2684 self.scratch_final_slots.push(None);
2685 let element_type = element.element_type();
2686 let node_type = element.node_type();
2687 let key = element.key();
2688 let hash_code = element.hash_code();
2689 let capabilities = element.capabilities();
2690
2691 let matched_idx = index.find_match(
2692 &old_entries,
2693 &self.scratch_old_used,
2694 EntryMatchQuery {
2695 element_type,
2696 node_type,
2697 key,
2698 hash_code,
2699 element: &element,
2700 },
2701 );
2702
2703 if let Some(idx) = matched_idx {
2704 let entry = &mut old_entries[idx];
2705 let can_update_node = {
2706 let node_borrow = entry.node.borrow();
2707 element.can_update_node(&**node_borrow)
2708 };
2709 if !can_update_node {
2710 let replacement = ModifierNodeEntry::new(
2711 element_type,
2712 node_type,
2713 key,
2714 element.clone(),
2715 element.create_node(),
2716 hash_code,
2717 capabilities,
2718 );
2719 attach_node_tree(&mut **replacement.node.borrow_mut(), context);
2720 element.update_node(&mut **replacement.node.borrow_mut());
2721 request_auto_invalidations(context, capabilities);
2722 self.scratch_final_slots[new_pos] = Some(replacement);
2723 continue;
2724 }
2725
2726 self.scratch_old_used[idx] = true;
2727 self.scratch_match_order[idx] = Some(new_pos);
2728 let moved = idx != new_pos;
2729
2730 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2731
2732 {
2733 let node_borrow = entry.node.borrow();
2734 if !node_borrow.node_state().is_attached() {
2735 drop(node_borrow);
2736 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2737 }
2738 }
2739
2740 let needs_update = !same_element || element.requires_update();
2741 if needs_update {
2742 element.update_node(&mut **entry.node.borrow_mut());
2743 entry.element = element;
2744 entry.hash_code = hash_code;
2745 request_update_auto_invalidations(
2746 entry.element.as_ref(),
2747 context,
2748 capabilities,
2749 );
2750 }
2751 if moved {
2752 request_auto_invalidations(context, capabilities);
2753 }
2754
2755 entry.key = key;
2756 entry.element_type = element_type;
2757 entry.node_type = node_type;
2758 entry.capabilities = capabilities;
2759 entry
2760 .node
2761 .borrow()
2762 .node_state()
2763 .set_capabilities(capabilities);
2764 } else {
2765 let entry = ModifierNodeEntry::new(
2766 element_type,
2767 node_type,
2768 key,
2769 element.clone(),
2770 element.create_node(),
2771 hash_code,
2772 capabilities,
2773 );
2774 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2775 element.update_node(&mut **entry.node.borrow_mut());
2776 request_auto_invalidations(context, capabilities);
2777 self.scratch_final_slots[new_pos] = Some(entry);
2778 }
2779 }
2780
2781 for (i, entry) in old_entries.into_iter().enumerate() {
2782 if self.scratch_old_used[i] {
2783 if let Some(pos) = self.scratch_match_order[i] {
2784 self.scratch_final_slots[pos] = Some(entry);
2785 } else {
2786 request_auto_invalidations(context, entry.capabilities);
2787 detach_node_tree(&mut **entry.node.borrow_mut());
2788 }
2789 } else {
2790 request_auto_invalidations(context, entry.capabilities);
2791 detach_node_tree(&mut **entry.node.borrow_mut());
2792 }
2793 }
2794
2795 self.entries.reserve(self.scratch_final_slots.len());
2796 for slot in self.scratch_final_slots.drain(..) {
2797 if let Some(entry) = slot {
2798 self.entries.push(entry);
2799 } else {
2800 log::error!("modifier reconciliation produced an empty final slot");
2801 }
2802 }
2803
2804 debug_assert_eq!(
2805 self.entries.len(),
2806 processed_entries_len + new_elements_count
2807 );
2808 self.sync_chain_links();
2809 }
2810
2811 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
2815 where
2816 I: IntoIterator<Item = DynModifierElement>,
2817 {
2818 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
2819 self.update_from_slice(&collected, context);
2820 }
2821
2822 pub fn reset(&mut self) {
2825 for entry in &mut self.entries {
2826 reset_node_tree(&mut **entry.node.borrow_mut());
2827 }
2828 }
2829
2830 pub fn detach_all(&mut self) {
2832 for entry in std::mem::take(&mut self.entries) {
2833 detach_node_tree(&mut **entry.node.borrow_mut());
2834 {
2835 let node_borrow = entry.node.borrow();
2836 let state = node_borrow.node_state();
2837 state.set_capabilities(NodeCapabilities::empty());
2838 }
2839 }
2840 self.aggregated_capabilities = NodeCapabilities::empty();
2841 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2842 self.ordered_nodes.clear();
2843 self.sync_chain_links();
2844 }
2845
2846 pub fn len(&self) -> usize {
2847 self.entries.len()
2848 }
2849
2850 pub fn is_empty(&self) -> bool {
2851 self.entries.is_empty()
2852 }
2853
2854 pub fn capabilities(&self) -> NodeCapabilities {
2856 self.aggregated_capabilities
2857 }
2858
2859 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
2861 self.aggregated_capabilities.contains(capability)
2862 }
2863
2864 pub fn head(&self) -> ModifierChainNodeRef<'_> {
2866 self.make_node_ref(NodeLink::Head)
2867 }
2868
2869 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
2871 self.make_node_ref(NodeLink::Tail)
2872 }
2873
2874 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
2876 ModifierChainIter::forward(self)
2877 }
2878
2879 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
2881 ModifierChainIter::backward(self)
2882 }
2883
2884 pub fn for_each_forward<F>(&self, mut f: F)
2886 where
2887 F: FnMut(ModifierChainNodeRef<'_>),
2888 {
2889 for node in self.head_to_tail() {
2890 f(node);
2891 }
2892 }
2893
2894 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
2896 where
2897 F: FnMut(ModifierChainNodeRef<'_>),
2898 {
2899 if mask.is_empty() {
2900 self.for_each_forward(f);
2901 return;
2902 }
2903
2904 if !self.head().aggregate_child_capabilities().intersects(mask) {
2905 return;
2906 }
2907
2908 for node in self.head_to_tail() {
2909 if node.kind_set().intersects(mask) {
2910 f(node);
2911 }
2912 }
2913 }
2914
2915 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
2917 where
2918 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
2919 {
2920 self.for_each_forward_matching(mask, |node_ref| {
2921 node_ref.with_node(|node| f(node_ref.clone(), node));
2922 });
2923 }
2924
2925 pub fn for_each_backward<F>(&self, mut f: F)
2927 where
2928 F: FnMut(ModifierChainNodeRef<'_>),
2929 {
2930 for node in self.tail_to_head() {
2931 f(node);
2932 }
2933 }
2934
2935 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
2937 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
2938 node as *const dyn ModifierNode as *const ()
2939 }
2940
2941 let target = node_data_ptr(node);
2942 for (index, entry) in self.entries.iter().enumerate() {
2943 if node_data_ptr(&**entry.node.borrow()) == target {
2944 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
2945 }
2946 }
2947
2948 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
2949 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
2950 return None;
2951 }
2952 let matches_target = match link {
2953 NodeLink::Head => node_data_ptr(self.head_sentinel.as_ref()) == target,
2954 NodeLink::Tail => node_data_ptr(self.tail_sentinel.as_ref()) == target,
2955 NodeLink::Entry(path) => {
2956 let node_borrow = self.entries[path.entry()].node.borrow();
2957 node_data_ptr(&**node_borrow) == target
2958 }
2959 };
2960 if matches_target {
2961 Some(self.make_node_ref(*link))
2962 } else {
2963 None
2964 }
2965 })
2966 }
2967
2968 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
2971 self.entries.get(index).and_then(|entry| {
2972 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
2973 boxed_node.as_any().downcast_ref::<N>()
2974 })
2975 .ok()
2976 })
2977 }
2978
2979 pub fn node_mut<N: ModifierNode + 'static>(
2982 &self,
2983 index: usize,
2984 ) -> Option<std::cell::RefMut<'_, N>> {
2985 self.entries.get(index).and_then(|entry| {
2986 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
2987 boxed_node.as_any_mut().downcast_mut::<N>()
2988 })
2989 .ok()
2990 })
2991 }
2992
2993 pub fn get_node_rc(&self, index: usize) -> Option<Rc<RefCell<Box<dyn ModifierNode>>>> {
2996 self.entries.get(index).map(|entry| Rc::clone(&entry.node))
2997 }
2998
2999 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
3001 self.aggregated_capabilities
3002 .contains(NodeCapabilities::for_invalidation(kind))
3003 }
3004
3005 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
3007 where
3008 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
3009 {
3010 for index in 0..self.ordered_nodes.len() {
3011 let (link, cached_caps, _agg) = self.ordered_nodes[index];
3012 match link {
3013 NodeLink::Head => {
3014 f(self.head_sentinel.as_mut(), cached_caps);
3015 }
3016 NodeLink::Tail => {
3017 f(self.tail_sentinel.as_mut(), cached_caps);
3018 }
3019 NodeLink::Entry(path) => {
3020 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
3021 if path.delegates().is_empty() {
3022 f(&mut **node_borrow, cached_caps);
3023 } else {
3024 let mut current: &mut dyn ModifierNode = &mut **node_borrow;
3025 for &delegate_index in path.delegates() {
3026 if let Some(delegate) =
3027 nth_delegate_mut(current, delegate_index as usize)
3028 {
3029 current = delegate;
3030 } else {
3031 return;
3032 }
3033 }
3034 f(current, cached_caps);
3035 }
3036 }
3037 }
3038 }
3039 }
3040
3041 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
3042 ModifierChainNodeRef {
3043 chain: self,
3044 link,
3045 cached_capabilities: None,
3046 cached_aggregate_child: None,
3047 }
3048 }
3049
3050 fn make_node_ref_with_caps(
3051 &self,
3052 link: NodeLink,
3053 caps: NodeCapabilities,
3054 aggregate_child: NodeCapabilities,
3055 ) -> ModifierChainNodeRef<'_> {
3056 ModifierChainNodeRef {
3057 chain: self,
3058 link,
3059 cached_capabilities: Some(caps),
3060 cached_aggregate_child: Some(aggregate_child),
3061 }
3062 }
3063
3064 fn sync_chain_links(&mut self) {
3065 self.rebuild_ordered_nodes();
3066
3067 self.head_sentinel.node_state().set_parent_link(None);
3068 self.tail_sentinel.node_state().set_child_link(None);
3069
3070 if self.ordered_nodes.is_empty() {
3071 self.head_sentinel
3072 .node_state()
3073 .set_child_link(Some(NodeLink::Tail));
3074 self.tail_sentinel
3075 .node_state()
3076 .set_parent_link(Some(NodeLink::Head));
3077 self.aggregated_capabilities = NodeCapabilities::empty();
3078 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
3079 self.head_sentinel
3080 .node_state()
3081 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3082 self.tail_sentinel
3083 .node_state()
3084 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3085 return;
3086 }
3087
3088 let mut previous = NodeLink::Head;
3089 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
3090 match &previous {
3091 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
3092 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
3093 NodeLink::Entry(path) => {
3094 let node_borrow = self.entries[path.entry()].node.borrow();
3095 if path.delegates().is_empty() {
3096 node_borrow.node_state().set_child_link(Some(link));
3097 } else {
3098 let mut current: &dyn ModifierNode = &**node_borrow;
3099 for &delegate_index in path.delegates() {
3100 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3101 current = delegate;
3102 }
3103 }
3104 current.node_state().set_child_link(Some(link));
3105 }
3106 }
3107 }
3108 match &link {
3109 NodeLink::Head => self
3110 .head_sentinel
3111 .node_state()
3112 .set_parent_link(Some(previous)),
3113 NodeLink::Tail => self
3114 .tail_sentinel
3115 .node_state()
3116 .set_parent_link(Some(previous)),
3117 NodeLink::Entry(path) => {
3118 let node_borrow = self.entries[path.entry()].node.borrow();
3119 if path.delegates().is_empty() {
3120 node_borrow.node_state().set_parent_link(Some(previous));
3121 } else {
3122 let mut current: &dyn ModifierNode = &**node_borrow;
3123 for &delegate_index in path.delegates() {
3124 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3125 current = delegate;
3126 }
3127 }
3128 current.node_state().set_parent_link(Some(previous));
3129 }
3130 }
3131 }
3132 previous = link;
3133 }
3134
3135 match &previous {
3136 NodeLink::Head => self
3137 .head_sentinel
3138 .node_state()
3139 .set_child_link(Some(NodeLink::Tail)),
3140 NodeLink::Tail => self
3141 .tail_sentinel
3142 .node_state()
3143 .set_child_link(Some(NodeLink::Tail)),
3144 NodeLink::Entry(path) => {
3145 let node_borrow = self.entries[path.entry()].node.borrow();
3146 if path.delegates().is_empty() {
3147 node_borrow
3148 .node_state()
3149 .set_child_link(Some(NodeLink::Tail));
3150 } else {
3151 let mut current: &dyn ModifierNode = &**node_borrow;
3152 for &delegate_index in path.delegates() {
3153 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3154 current = delegate;
3155 }
3156 }
3157 current.node_state().set_child_link(Some(NodeLink::Tail));
3158 }
3159 }
3160 }
3161 self.tail_sentinel
3162 .node_state()
3163 .set_parent_link(Some(previous));
3164 self.tail_sentinel.node_state().set_child_link(None);
3165
3166 let mut aggregate = NodeCapabilities::empty();
3167 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
3168 aggregate |= *cached_caps;
3169 *cached_aggregate = aggregate;
3170 match link {
3171 NodeLink::Head => {
3172 self.head_sentinel
3173 .node_state()
3174 .set_aggregate_child_capabilities(aggregate);
3175 }
3176 NodeLink::Tail => {
3177 self.tail_sentinel
3178 .node_state()
3179 .set_aggregate_child_capabilities(aggregate);
3180 }
3181 NodeLink::Entry(path) => {
3182 let node_borrow = self.entries[path.entry()].node.borrow();
3183 let state = if path.delegates().is_empty() {
3184 node_borrow.node_state()
3185 } else {
3186 let mut current: &dyn ModifierNode = &**node_borrow;
3187 for &delegate_index in path.delegates() {
3188 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3189 current = delegate;
3190 }
3191 }
3192 current.node_state()
3193 };
3194 state.set_aggregate_child_capabilities(aggregate);
3195 }
3196 }
3197 }
3198
3199 self.aggregated_capabilities = aggregate;
3200 self.head_aggregate_child_capabilities = aggregate;
3201 self.head_sentinel
3202 .node_state()
3203 .set_aggregate_child_capabilities(aggregate);
3204 self.tail_sentinel
3205 .node_state()
3206 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3207 }
3208
3209 fn rebuild_ordered_nodes(&mut self) {
3210 self.ordered_nodes.clear();
3211 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
3212 for (index, entry) in self.entries.iter().enumerate() {
3213 let node_borrow = entry.node.borrow();
3214 Self::enumerate_link_order(
3215 &**node_borrow,
3216 index,
3217 &mut path_buf,
3218 0,
3219 &mut self.ordered_nodes,
3220 );
3221 }
3222 }
3223
3224 fn enumerate_link_order(
3225 node: &dyn ModifierNode,
3226 entry: usize,
3227 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
3228 path_len: usize,
3229 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
3230 ) {
3231 let caps = node.node_state().capabilities();
3232 out.push((
3233 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
3234 caps,
3235 NodeCapabilities::empty(),
3236 ));
3237 let mut delegate_index = 0usize;
3238 node.for_each_delegate(&mut |child| {
3239 if path_len < MAX_DELEGATE_DEPTH {
3240 path_buf[path_len] = delegate_index;
3241 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
3242 }
3243 delegate_index += 1;
3244 });
3245 }
3246}
3247
3248impl<'a> ModifierChainNodeRef<'a> {
3249 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
3250 match &self.link {
3251 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
3252 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
3253 NodeLink::Entry(path) => {
3254 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3255 if path.delegates().is_empty() {
3256 f(node_borrow.node_state())
3257 } else {
3258 let mut current: &dyn ModifierNode = &**node_borrow;
3259 for &delegate_index in path.delegates() {
3260 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3261 current = delegate;
3262 } else {
3263 return f(node_borrow.node_state());
3264 }
3265 }
3266 f(current.node_state())
3267 }
3268 }
3269 }
3270 }
3271
3272 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
3275 match &self.link {
3276 NodeLink::Head => None,
3277 NodeLink::Tail => None,
3278 NodeLink::Entry(path) => {
3279 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3280 if path.delegates().is_empty() {
3281 Some(f(&**node_borrow))
3282 } else {
3283 let mut current: &dyn ModifierNode = &**node_borrow;
3284 for &delegate_index in path.delegates() {
3285 current = nth_delegate(current, delegate_index as usize)?;
3286 }
3287 Some(f(current))
3288 }
3289 }
3290 }
3291 }
3292
3293 #[inline]
3295 pub fn parent(&self) -> Option<Self> {
3296 self.with_state(NodeState::parent_link)
3297 .map(|link| self.chain.make_node_ref(link))
3298 }
3299
3300 #[inline]
3302 pub fn child(&self) -> Option<Self> {
3303 self.with_state(NodeState::child_link)
3304 .map(|link| self.chain.make_node_ref(link))
3305 }
3306
3307 #[inline]
3309 pub fn kind_set(&self) -> NodeCapabilities {
3310 if let Some(caps) = self.cached_capabilities {
3311 return caps;
3312 }
3313 match &self.link {
3314 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
3315 NodeLink::Entry(_) => self.with_state(NodeState::capabilities),
3316 }
3317 }
3318
3319 pub fn entry_index(&self) -> Option<usize> {
3321 match &self.link {
3322 NodeLink::Entry(path) => Some(path.entry()),
3323 _ => None,
3324 }
3325 }
3326
3327 pub fn delegate_depth(&self) -> usize {
3329 match &self.link {
3330 NodeLink::Entry(path) => path.delegates().len(),
3331 _ => 0,
3332 }
3333 }
3334
3335 #[inline]
3337 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
3338 if let Some(agg) = self.cached_aggregate_child {
3339 return agg;
3340 }
3341 if self.is_tail() {
3342 NodeCapabilities::empty()
3343 } else {
3344 self.with_state(NodeState::aggregate_child_capabilities)
3345 }
3346 }
3347
3348 pub fn is_head(&self) -> bool {
3350 matches!(self.link, NodeLink::Head)
3351 }
3352
3353 pub fn is_tail(&self) -> bool {
3355 matches!(self.link, NodeLink::Tail)
3356 }
3357
3358 pub fn is_sentinel(&self) -> bool {
3360 matches!(self.link, NodeLink::Head | NodeLink::Tail)
3361 }
3362
3363 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
3365 !mask.is_empty() && self.kind_set().intersects(mask)
3366 }
3367
3368 pub fn visit_descendants<F>(self, include_self: bool, mut f: F)
3370 where
3371 F: FnMut(ModifierChainNodeRef<'a>),
3372 {
3373 let mut current = if include_self {
3374 Some(self)
3375 } else {
3376 self.child()
3377 };
3378 while let Some(node) = current {
3379 if node.is_tail() {
3380 break;
3381 }
3382 if !node.is_sentinel() {
3383 f(node.clone());
3384 }
3385 current = node.child();
3386 }
3387 }
3388
3389 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3391 where
3392 F: FnMut(ModifierChainNodeRef<'a>),
3393 {
3394 if mask.is_empty() {
3395 self.visit_descendants(include_self, f);
3396 return;
3397 }
3398
3399 if !self.aggregate_child_capabilities().intersects(mask) {
3400 return;
3401 }
3402
3403 self.visit_descendants(include_self, |node| {
3404 if node.kind_set().intersects(mask) {
3405 f(node);
3406 }
3407 });
3408 }
3409
3410 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
3412 where
3413 F: FnMut(ModifierChainNodeRef<'a>),
3414 {
3415 let mut current = if include_self {
3416 Some(self)
3417 } else {
3418 self.parent()
3419 };
3420 while let Some(node) = current {
3421 if node.is_head() {
3422 break;
3423 }
3424 f(node.clone());
3425 current = node.parent();
3426 }
3427 }
3428
3429 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3431 where
3432 F: FnMut(ModifierChainNodeRef<'a>),
3433 {
3434 if mask.is_empty() {
3435 self.visit_ancestors(include_self, f);
3436 return;
3437 }
3438
3439 self.visit_ancestors(include_self, |node| {
3440 if node.kind_set().intersects(mask) {
3441 f(node);
3442 }
3443 });
3444 }
3445}
3446
3447#[cfg(test)]
3448#[path = "tests/modifier_tests.rs"]
3449mod tests;