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
56#[derive(Default, Debug, Clone)]
65pub struct BasicModifierNodeContext {
66 invalidations: Vec<ModifierInvalidation>,
67 update_requested: bool,
68 active_capabilities: Vec<NodeCapabilities>,
69 node_id: Option<cranpose_core::NodeId>,
70}
71
72impl BasicModifierNodeContext {
73 pub fn new() -> Self {
75 Self::default()
76 }
77
78 pub fn invalidations(&self) -> &[ModifierInvalidation] {
82 &self.invalidations
83 }
84
85 pub fn clear_invalidations(&mut self) {
87 self.invalidations.clear();
88 }
89
90 pub fn take_invalidations(&mut self) -> Vec<ModifierInvalidation> {
92 std::mem::take(&mut self.invalidations)
93 }
94
95 pub fn update_requested(&self) -> bool {
98 self.update_requested
99 }
100
101 pub fn take_update_requested(&mut self) -> bool {
103 std::mem::take(&mut self.update_requested)
104 }
105
106 pub fn set_node_id(&mut self, id: Option<cranpose_core::NodeId>) {
108 self.node_id = id;
109 }
110
111 fn push_invalidation(&mut self, kind: InvalidationKind) {
112 let mut capabilities = self.current_capabilities();
113 capabilities.insert(NodeCapabilities::for_invalidation(kind));
114 if let Some(existing) = self
115 .invalidations
116 .iter_mut()
117 .find(|entry| entry.kind() == kind)
118 {
119 let updated = existing.capabilities() | capabilities;
120 *existing = ModifierInvalidation::new(kind, updated);
121 } else {
122 self.invalidations
123 .push(ModifierInvalidation::new(kind, capabilities));
124 }
125 }
126
127 fn current_capabilities(&self) -> NodeCapabilities {
128 self.active_capabilities
129 .last()
130 .copied()
131 .unwrap_or_else(NodeCapabilities::empty)
132 }
133}
134
135impl ModifierNodeContext for BasicModifierNodeContext {
136 fn invalidate(&mut self, kind: InvalidationKind) {
137 self.push_invalidation(kind);
138 }
139
140 fn request_update(&mut self) {
141 self.update_requested = true;
142 }
143
144 fn push_active_capabilities(&mut self, capabilities: NodeCapabilities) {
145 self.active_capabilities.push(capabilities);
146 }
147
148 fn pop_active_capabilities(&mut self) {
149 self.active_capabilities.pop();
150 }
151
152 fn node_id(&self) -> Option<cranpose_core::NodeId> {
153 self.node_id
154 }
155}
156
157const MAX_DELEGATE_DEPTH: usize = 3;
158
159#[derive(Copy, Clone, Debug, PartialEq, Eq)]
160pub(crate) struct NodePath {
161 entry: usize,
162 delegate_buf: [u8; MAX_DELEGATE_DEPTH],
163 delegate_len: u8,
164}
165
166impl NodePath {
167 #[inline]
168 fn root(entry: usize) -> Self {
169 Self {
170 entry,
171 delegate_buf: [0; MAX_DELEGATE_DEPTH],
172 delegate_len: 0,
173 }
174 }
175
176 #[inline]
177 fn from_slice(entry: usize, path: &[usize]) -> Self {
178 debug_assert!(
179 path.len() <= MAX_DELEGATE_DEPTH,
180 "delegate depth {} exceeds MAX_DELEGATE_DEPTH {}",
181 path.len(),
182 MAX_DELEGATE_DEPTH
183 );
184 debug_assert!(
185 path.iter().all(|&i| i <= u8::MAX as usize),
186 "delegate index exceeds u8 range"
187 );
188 let mut delegate_buf = [0u8; MAX_DELEGATE_DEPTH];
189 for (i, &v) in path.iter().enumerate().take(MAX_DELEGATE_DEPTH) {
190 delegate_buf[i] = v as u8;
191 }
192 Self {
193 entry,
194 delegate_buf,
195 delegate_len: path.len().min(MAX_DELEGATE_DEPTH) as u8,
196 }
197 }
198
199 #[inline]
200 fn entry(&self) -> usize {
201 self.entry
202 }
203
204 #[inline]
205 fn delegates(&self) -> &[u8] {
206 &self.delegate_buf[..self.delegate_len as usize]
207 }
208}
209
210#[derive(Copy, Clone, Debug, PartialEq, Eq)]
211pub(crate) enum NodeLink {
212 Head,
213 Tail,
214 Entry(NodePath),
215}
216
217#[derive(Debug)]
223pub struct NodeState {
224 aggregate_child_capabilities: Cell<NodeCapabilities>,
225 capabilities: Cell<NodeCapabilities>,
226 parent: RefCell<Option<NodeLink>>,
227 child: RefCell<Option<NodeLink>>,
228 attached: Cell<bool>,
229 is_sentinel: bool,
230}
231
232impl Default for NodeState {
233 fn default() -> Self {
234 Self::new()
235 }
236}
237
238impl NodeState {
239 pub const fn new() -> Self {
240 Self {
241 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
242 capabilities: Cell::new(NodeCapabilities::empty()),
243 parent: RefCell::new(None),
244 child: RefCell::new(None),
245 attached: Cell::new(false),
246 is_sentinel: false,
247 }
248 }
249
250 pub const fn sentinel() -> Self {
251 Self {
252 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
253 capabilities: Cell::new(NodeCapabilities::empty()),
254 parent: RefCell::new(None),
255 child: RefCell::new(None),
256 attached: Cell::new(true),
257 is_sentinel: true,
258 }
259 }
260
261 pub fn set_capabilities(&self, capabilities: NodeCapabilities) {
262 self.capabilities.set(capabilities);
263 }
264
265 #[inline]
266 pub fn capabilities(&self) -> NodeCapabilities {
267 self.capabilities.get()
268 }
269
270 pub fn set_aggregate_child_capabilities(&self, capabilities: NodeCapabilities) {
271 self.aggregate_child_capabilities.set(capabilities);
272 }
273
274 #[inline]
275 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
276 self.aggregate_child_capabilities.get()
277 }
278
279 pub(crate) fn set_parent_link(&self, parent: Option<NodeLink>) {
280 *self.parent.borrow_mut() = parent;
281 }
282
283 #[inline]
284 pub(crate) fn parent_link(&self) -> Option<NodeLink> {
285 *self.parent.borrow()
286 }
287
288 pub(crate) fn set_child_link(&self, child: Option<NodeLink>) {
289 *self.child.borrow_mut() = child;
290 }
291
292 #[inline]
293 pub(crate) fn child_link(&self) -> Option<NodeLink> {
294 *self.child.borrow()
295 }
296
297 pub fn set_attached(&self, attached: bool) {
298 self.attached.set(attached);
299 }
300
301 pub fn is_attached(&self) -> bool {
302 self.attached.get()
303 }
304
305 pub fn is_sentinel(&self) -> bool {
306 self.is_sentinel
307 }
308}
309
310pub trait DelegatableNode {
312 fn node_state(&self) -> &NodeState;
313 fn aggregate_child_capabilities(&self) -> NodeCapabilities {
314 self.node_state().aggregate_child_capabilities()
315 }
316}
317
318pub trait ModifierNode: Any + DelegatableNode {
376 fn on_attach(&mut self, _context: &mut dyn ModifierNodeContext) {}
377
378 fn on_detach(&mut self) {}
379
380 fn on_reset(&mut self) {}
381
382 fn as_draw_node(&self) -> Option<&dyn DrawModifierNode> {
384 None
385 }
386
387 fn as_draw_node_mut(&mut self) -> Option<&mut dyn DrawModifierNode> {
389 None
390 }
391
392 fn as_pointer_input_node(&self) -> Option<&dyn PointerInputNode> {
394 None
395 }
396
397 fn as_pointer_input_node_mut(&mut self) -> Option<&mut dyn PointerInputNode> {
399 None
400 }
401
402 fn as_semantics_node(&self) -> Option<&dyn SemanticsNode> {
404 None
405 }
406
407 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn SemanticsNode> {
409 None
410 }
411
412 fn as_focus_node(&self) -> Option<&dyn FocusNode> {
414 None
415 }
416
417 fn as_focus_node_mut(&mut self) -> Option<&mut dyn FocusNode> {
419 None
420 }
421
422 fn as_layout_node(&self) -> Option<&dyn LayoutModifierNode> {
424 None
425 }
426
427 fn as_layout_node_mut(&mut self) -> Option<&mut dyn LayoutModifierNode> {
429 None
430 }
431
432 fn for_each_delegate<'b>(&'b self, _visitor: &mut dyn FnMut(&'b dyn ModifierNode)) {}
434
435 fn for_each_delegate_mut<'b>(&'b mut self, _visitor: &mut dyn FnMut(&'b mut dyn ModifierNode)) {
437 }
438}
439
440pub trait LayoutModifierNode: ModifierNode {
446 fn measure(
468 &self,
469 _context: &mut dyn ModifierNodeContext,
470 measurable: &dyn Measurable,
471 constraints: Constraints,
472 ) -> cranpose_ui_layout::LayoutModifierMeasureResult {
473 let placeable = measurable.measure(constraints);
474 cranpose_ui_layout::LayoutModifierMeasureResult::with_size(Size {
475 width: placeable.width(),
476 height: placeable.height(),
477 })
478 }
479
480 fn min_intrinsic_width(&self, _measurable: &dyn Measurable, _height: f32) -> f32 {
482 0.0
483 }
484
485 fn max_intrinsic_width(&self, _measurable: &dyn Measurable, _height: f32) -> f32 {
487 0.0
488 }
489
490 fn min_intrinsic_height(&self, _measurable: &dyn Measurable, _width: f32) -> f32 {
492 0.0
493 }
494
495 fn max_intrinsic_height(&self, _measurable: &dyn Measurable, _width: f32) -> f32 {
497 0.0
498 }
499}
500
501pub trait DrawModifierNode: ModifierNode {
509 fn draw(&self, _draw_scope: &mut dyn DrawScope) {}
518
519 fn create_draw_closure(&self) -> Option<NodeDrawClosure> {
530 None
531 }
532
533 fn create_behind_draw_closure(&self) -> Option<NodeDrawClosure> {
538 None
539 }
540}
541
542pub type NodeDrawClosure = Rc<dyn Fn(&mut cranpose_ui_graphics::DrawScopeDefault)>;
547
548pub trait PointerInputNode: ModifierNode {
554 fn on_pointer_event(
557 &mut self,
558 _context: &mut dyn ModifierNodeContext,
559 _event: &PointerEvent,
560 ) -> bool {
561 false
562 }
563
564 fn hit_test(&self, _x: f32, _y: f32) -> bool {
567 true
568 }
569
570 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
572 None
573 }
574
575 fn layout_size_sink(&self) -> Option<Rc<Cell<Size>>> {
588 None
589 }
590}
591
592pub trait SemanticsNode: ModifierNode {
598 fn merge_semantics(&self, _config: &mut SemanticsConfiguration) {}
600
601 fn reach(&self) -> SemanticsReach {
605 let mut config = SemanticsConfiguration::default();
606 self.merge_semantics(&mut config);
607 SemanticsReach {
608 is_modal: config.is_modal,
609 hidden: config.hidden,
610 }
611 }
612}
613
614#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
617pub struct SemanticsReach {
618 pub is_modal: bool,
620 pub hidden: bool,
622}
623
624impl SemanticsReach {
625 pub fn union(self, other: Self) -> Self {
627 Self {
628 is_modal: self.is_modal || other.is_modal,
629 hidden: self.hidden || other.hidden,
630 }
631 }
632}
633
634#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
639pub enum FocusState {
640 Active,
642 ActiveParent,
644 Captured,
648 #[default]
651 Inactive,
652}
653
654impl FocusState {
655 pub fn is_focused(self) -> bool {
657 matches!(self, FocusState::Active | FocusState::Captured)
658 }
659
660 pub fn has_focus(self) -> bool {
662 matches!(
663 self,
664 FocusState::Active | FocusState::ActiveParent | FocusState::Captured
665 )
666 }
667
668 pub fn is_captured(self) -> bool {
670 matches!(self, FocusState::Captured)
671 }
672}
673
674pub trait FocusNode: ModifierNode {
679 fn focus_state(&self) -> FocusState;
681
682 fn on_focus_changed(&mut self, _context: &mut dyn ModifierNodeContext, _state: FocusState) {}
684}
685
686#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
697pub enum SemanticsWidgetRole {
698 Button,
699 Checkbox,
700 Switch,
701 RadioButton,
702 Tab,
703 Image,
704 DropdownList,
707 ValuePicker,
710 Header,
715 Dialog,
719 Link,
722 SearchField,
725 ProgressBar,
728 ToggleButton,
731 Alert,
734 Toolbar,
737 Menu,
739 MenuItem,
741 TabBar,
744 List,
746 ListItem,
748 RadioGroup,
750}
751
752#[derive(Clone, Copy, Debug, PartialEq)]
760pub struct ProgressBarRangeInfo {
761 pub current: f32,
762 pub start: f32,
763 pub end: f32,
764 pub steps: u32,
767}
768
769impl ProgressBarRangeInfo {
770 pub fn new(current: f32, start: f32, end: f32, steps: u32) -> Self {
771 Self {
772 current,
773 start,
774 end,
775 steps,
776 }
777 }
778
779 pub fn fraction(&self) -> f32 {
781 let span = self.end - self.start;
782 if span.abs() < f32::EPSILON {
783 return 0.0;
784 }
785 ((self.current - self.start) / span).clamp(0.0, 1.0)
786 }
787
788 pub fn step(&self) -> f32 {
791 let span = self.end - self.start;
792 if self.steps == 0 {
793 span / 10.0
794 } else {
795 span / (self.steps as f32 + 1.0)
796 }
797 }
798}
799
800#[derive(Clone, Copy, Debug, PartialEq, Eq)]
805pub struct CollectionInfo {
806 pub rows: usize,
807 pub columns: usize,
808}
809
810#[derive(Clone, Copy, Debug, PartialEq)]
821pub struct ScrollAxisRange {
822 pub value: f32,
823 pub max_value: f32,
824 pub reverse: bool,
825 pub content_padding_start: f32,
826 pub content_padding_end: f32,
827}
828
829impl ScrollAxisRange {
830 pub fn new(value: f32, max_value: f32, reverse: bool) -> Self {
831 Self {
832 value,
833 max_value,
834 reverse,
835 content_padding_start: 0.0,
836 content_padding_end: 0.0,
837 }
838 }
839
840 pub fn with_content_padding(self, start: f32, end: f32) -> Self {
843 Self {
844 content_padding_start: start,
845 content_padding_end: end,
846 ..self
847 }
848 }
849
850 pub fn can_scroll_forward(&self) -> bool {
851 self.value < self.max_value
852 }
853
854 pub fn can_scroll_backward(&self) -> bool {
855 self.value > 0.0
856 }
857}
858
859#[derive(Clone)]
865pub struct SemanticsScrollBy {
866 handler: Rc<dyn Fn(f32, f32) -> bool>,
867}
868
869impl SemanticsScrollBy {
870 pub fn new(handler: impl Fn(f32, f32) -> bool + 'static) -> Self {
871 Self {
872 handler: Rc::new(handler),
873 }
874 }
875
876 pub fn invoke(&self, dx: f32, dy: f32) -> bool {
877 (self.handler)(dx, dy)
878 }
879}
880
881impl fmt::Debug for SemanticsScrollBy {
882 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
883 f.debug_struct("SemanticsScrollBy").finish_non_exhaustive()
884 }
885}
886
887impl PartialEq for SemanticsScrollBy {
888 fn eq(&self, _other: &Self) -> bool {
889 true
890 }
891}
892
893impl Eq for SemanticsScrollBy {}
894
895#[derive(Clone)]
901pub struct SemanticsScrollToIndex {
902 handler: Rc<dyn Fn(usize) -> bool>,
903}
904
905impl SemanticsScrollToIndex {
906 pub fn new(handler: impl Fn(usize) -> bool + 'static) -> Self {
907 Self {
908 handler: Rc::new(handler),
909 }
910 }
911
912 pub fn invoke(&self, index: usize) -> bool {
913 (self.handler)(index)
914 }
915}
916
917impl fmt::Debug for SemanticsScrollToIndex {
918 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
919 f.debug_struct("SemanticsScrollToIndex")
920 .finish_non_exhaustive()
921 }
922}
923
924impl PartialEq for SemanticsScrollToIndex {
925 fn eq(&self, _other: &Self) -> bool {
926 true
927 }
928}
929
930impl Eq for SemanticsScrollToIndex {}
931
932#[derive(Clone)]
938pub struct SemanticsSetProgress {
939 handler: Rc<dyn Fn(f32) -> bool>,
940}
941
942impl SemanticsSetProgress {
943 pub fn new(handler: impl Fn(f32) -> bool + 'static) -> Self {
944 Self {
945 handler: Rc::new(handler),
946 }
947 }
948
949 pub fn invoke(&self, value: f32) -> bool {
950 (self.handler)(value)
951 }
952}
953
954impl fmt::Debug for SemanticsSetProgress {
955 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
956 f.debug_struct("SemanticsSetProgress")
957 .finish_non_exhaustive()
958 }
959}
960
961#[derive(Clone)]
965pub struct SemanticsSetText(Rc<dyn Fn(&str) -> bool>);
966
967impl SemanticsSetText {
968 pub fn new(handler: impl Fn(&str) -> bool + 'static) -> Self {
969 Self(Rc::new(handler))
970 }
971
972 pub fn invoke(&self, text: &str) -> bool {
973 (self.0)(text)
974 }
975}
976
977impl fmt::Debug for SemanticsSetText {
978 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
979 f.write_str("SemanticsSetText")
980 }
981}
982
983#[derive(Clone)]
989pub struct SemanticsSetSelection(Rc<dyn Fn(usize, usize) -> bool>);
990
991impl SemanticsSetSelection {
992 pub fn new(handler: impl Fn(usize, usize) -> bool + 'static) -> Self {
993 Self(Rc::new(handler))
994 }
995
996 pub fn invoke(&self, anchor: usize, focus: usize) -> bool {
997 (self.0)(anchor, focus)
998 }
999}
1000
1001impl fmt::Debug for SemanticsSetSelection {
1002 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1003 f.write_str("SemanticsSetSelection")
1004 }
1005}
1006
1007#[derive(Clone)]
1010pub struct SemanticsExpand(Rc<dyn Fn() -> bool>);
1011
1012impl SemanticsExpand {
1013 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1014 Self(Rc::new(handler))
1015 }
1016
1017 pub fn invoke(&self) -> bool {
1018 (self.0)()
1019 }
1020}
1021
1022impl fmt::Debug for SemanticsExpand {
1023 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1024 f.write_str("SemanticsExpand")
1025 }
1026}
1027
1028#[derive(Clone)]
1032pub struct SemanticsLongClick(Rc<dyn Fn() -> bool>);
1033
1034impl SemanticsLongClick {
1035 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1036 Self(Rc::new(handler))
1037 }
1038
1039 pub fn invoke(&self) -> bool {
1040 (self.0)()
1041 }
1042}
1043
1044impl fmt::Debug for SemanticsLongClick {
1045 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1046 f.write_str("SemanticsLongClick")
1047 }
1048}
1049
1050impl PartialEq for SemanticsLongClick {
1051 fn eq(&self, _other: &Self) -> bool {
1052 true
1053 }
1054}
1055
1056impl PartialEq for SemanticsExpand {
1057 fn eq(&self, _other: &Self) -> bool {
1058 true
1059 }
1060}
1061
1062#[derive(Clone)]
1066pub struct SemanticsDismiss(Rc<dyn Fn() -> bool>);
1067
1068impl SemanticsDismiss {
1069 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1070 Self(Rc::new(handler))
1071 }
1072
1073 pub fn invoke(&self) -> bool {
1074 (self.0)()
1075 }
1076}
1077
1078impl fmt::Debug for SemanticsDismiss {
1079 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1080 f.write_str("SemanticsDismiss")
1081 }
1082}
1083
1084impl PartialEq for SemanticsDismiss {
1085 fn eq(&self, _other: &Self) -> bool {
1086 true
1087 }
1088}
1089
1090impl PartialEq for SemanticsSetText {
1091 fn eq(&self, _other: &Self) -> bool {
1092 true
1093 }
1094}
1095
1096impl PartialEq for SemanticsSetSelection {
1097 fn eq(&self, _other: &Self) -> bool {
1098 true
1099 }
1100}
1101
1102#[derive(Clone)]
1108pub struct SemanticsMagicTap(Rc<dyn Fn() -> bool>);
1109
1110impl SemanticsMagicTap {
1111 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1112 Self(Rc::new(handler))
1113 }
1114
1115 pub fn invoke(&self) -> bool {
1116 (self.0)()
1117 }
1118}
1119
1120impl fmt::Debug for SemanticsMagicTap {
1121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1122 f.write_str("SemanticsMagicTap")
1123 }
1124}
1125
1126impl PartialEq for SemanticsMagicTap {
1127 fn eq(&self, _other: &Self) -> bool {
1128 true
1129 }
1130}
1131
1132impl PartialEq for SemanticsSetProgress {
1133 fn eq(&self, _other: &Self) -> bool {
1134 true
1135 }
1136}
1137
1138impl Eq for SemanticsSetProgress {}
1139
1140#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1147pub enum LiveRegionMode {
1148 Polite,
1150 Assertive,
1153}
1154
1155#[derive(Clone)]
1162pub struct SemanticsCustomAction {
1163 pub label: String,
1165 handler: Rc<dyn Fn()>,
1166}
1167
1168impl SemanticsCustomAction {
1169 pub fn new(label: impl Into<String>, handler: impl Fn() + 'static) -> Self {
1170 Self {
1171 label: label.into(),
1172 handler: Rc::new(handler),
1173 }
1174 }
1175
1176 pub fn invoke(&self) {
1177 (self.handler)();
1178 }
1179}
1180
1181impl fmt::Debug for SemanticsCustomAction {
1182 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1183 f.debug_struct("SemanticsCustomAction")
1184 .field("label", &self.label)
1185 .finish_non_exhaustive()
1186 }
1187}
1188
1189impl PartialEq for SemanticsCustomAction {
1190 fn eq(&self, other: &Self) -> bool {
1191 self.label == other.label
1192 }
1193}
1194
1195impl Eq for SemanticsCustomAction {}
1196
1197#[derive(Clone, Debug, PartialEq)]
1212pub struct CanvasSemanticsNode {
1213 pub key: u64,
1220 pub bounds: cranpose_ui_graphics::Rect,
1222 pub label: String,
1223 pub role: Option<SemanticsWidgetRole>,
1224 pub state_description: Option<String>,
1228 pub on_click_label: Option<String>,
1231 pub clickable: bool,
1232 pub selected: Option<bool>,
1234 pub toggled: Option<bool>,
1236 pub enabled: bool,
1237 pub custom_actions: Vec<SemanticsCustomAction>,
1238}
1239
1240impl Default for CanvasSemanticsNode {
1241 fn default() -> Self {
1242 Self {
1243 key: 0,
1244 bounds: cranpose_ui_graphics::Rect {
1245 x: 0.0,
1246 y: 0.0,
1247 width: 0.0,
1248 height: 0.0,
1249 },
1250 label: String::new(),
1251 role: None,
1252 state_description: None,
1253 on_click_label: None,
1254 clickable: false,
1255 selected: None,
1256 toggled: None,
1257 enabled: true,
1258 custom_actions: Vec::new(),
1259 }
1260 }
1261}
1262
1263impl CanvasSemanticsNode {
1264 pub fn control(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1266 Self {
1267 key,
1268 bounds,
1269 label: label.into(),
1270 clickable: true,
1271 ..Self::default()
1272 }
1273 }
1274
1275 pub fn text(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1277 Self {
1278 key,
1279 bounds,
1280 label: label.into(),
1281 ..Self::default()
1282 }
1283 }
1284
1285 pub fn with_role(mut self, role: SemanticsWidgetRole) -> Self {
1286 self.role = Some(role);
1287 self
1288 }
1289
1290 pub fn with_state_description(mut self, state: impl Into<String>) -> Self {
1291 self.state_description = Some(state.into());
1292 self
1293 }
1294
1295 pub fn with_click_label(mut self, label: impl Into<String>) -> Self {
1296 self.on_click_label = Some(label.into());
1297 self.clickable = true;
1298 self
1299 }
1300
1301 pub fn with_selected(mut self, selected: bool) -> Self {
1302 self.selected = Some(selected);
1303 self
1304 }
1305
1306 pub fn with_toggled(mut self, toggled: bool) -> Self {
1307 self.toggled = Some(toggled);
1308 self
1309 }
1310
1311 pub fn with_enabled(mut self, enabled: bool) -> Self {
1312 self.enabled = enabled;
1313 self
1314 }
1315
1316 pub fn with_custom_action(mut self, action: SemanticsCustomAction) -> Self {
1317 self.custom_actions.push(action);
1318 self
1319 }
1320}
1321
1322#[derive(Clone, Debug, PartialEq)]
1324pub struct SemanticsConfiguration {
1325 pub content_description: Option<String>,
1326 pub state_description: Option<String>,
1328 pub on_click_label: Option<String>,
1330 pub on_click: Option<SemanticsCustomAction>,
1333 pub on_long_click: Option<SemanticsLongClick>,
1336 pub on_long_click_label: Option<String>,
1339 pub on_magic_tap: Option<SemanticsMagicTap>,
1343 pub on_magic_tap_label: Option<String>,
1346 pub input_labels: Vec<String>,
1350 pub language: Option<String>,
1354 pub role: Option<SemanticsWidgetRole>,
1356 pub selected: Option<bool>,
1357 pub toggled: Option<bool>,
1358 pub enabled: bool,
1359 pub is_clickable: bool,
1360 pub is_editable_text: bool,
1361 pub multiline: bool,
1363 pub text: Option<String>,
1366 pub text_selection: Option<crate::text::TextRange>,
1367 pub custom_actions: Vec<SemanticsCustomAction>,
1368 pub canvas_children: Vec<CanvasSemanticsNode>,
1371 pub is_modal: bool,
1374 pub hidden: bool,
1378 pub merge_descendants: bool,
1382 pub selectable_group: bool,
1386 pub pane_title: Option<String>,
1389 pub error: Option<String>,
1392 pub password: bool,
1395 pub traversal_index: f32,
1399 pub live_region: Option<LiveRegionMode>,
1402 pub progress: Option<ProgressBarRangeInfo>,
1405 pub set_progress: Option<SemanticsSetProgress>,
1408 pub set_text: Option<SemanticsSetText>,
1411 pub set_selection: Option<SemanticsSetSelection>,
1414 pub expand: Option<SemanticsExpand>,
1417 pub dismiss: Option<SemanticsDismiss>,
1421 pub collapse: Option<SemanticsExpand>,
1424 pub vertical_scroll: Option<ScrollAxisRange>,
1427 pub horizontal_scroll: Option<ScrollAxisRange>,
1430 pub scroll_by: Option<SemanticsScrollBy>,
1433 pub scroll_to_index: Option<SemanticsScrollToIndex>,
1437 pub collection: Option<CollectionInfo>,
1439}
1440
1441impl Default for SemanticsConfiguration {
1442 fn default() -> Self {
1443 Self {
1444 content_description: None,
1445 state_description: None,
1446 on_click_label: None,
1447 on_click: None,
1448 on_long_click: None,
1449 on_long_click_label: None,
1450 on_magic_tap: None,
1451 on_magic_tap_label: None,
1452 input_labels: Vec::new(),
1453 language: None,
1454 role: None,
1455 selected: None,
1456 toggled: None,
1457 enabled: true,
1458 is_clickable: false,
1459 is_editable_text: false,
1460 multiline: false,
1461 text: None,
1462 text_selection: None,
1463 custom_actions: Vec::new(),
1464 canvas_children: Vec::new(),
1465 is_modal: false,
1466 hidden: false,
1467 merge_descendants: false,
1468 selectable_group: false,
1469 pane_title: None,
1470 error: None,
1471 password: false,
1472 traversal_index: 0.0,
1473 live_region: None,
1474 progress: None,
1475 set_progress: None,
1476 set_text: None,
1477 set_selection: None,
1478 expand: None,
1479 dismiss: None,
1480 collapse: None,
1481 vertical_scroll: None,
1482 horizontal_scroll: None,
1483 scroll_by: None,
1484 scroll_to_index: None,
1485 collection: None,
1486 }
1487 }
1488}
1489
1490pub type SemanticsSpec = SemanticsConfiguration;
1499
1500impl SemanticsConfiguration {
1501 pub fn new() -> Self {
1504 Self::default()
1505 }
1506
1507 pub fn content_description(mut self, name: impl Into<String>) -> Self {
1510 self.content_description = Some(name.into());
1511 self
1512 }
1513
1514 pub fn state_description(mut self, state: impl Into<String>) -> Self {
1517 self.state_description = Some(state.into());
1518 self
1519 }
1520
1521 pub fn clickable(mut self) -> Self {
1523 self.is_clickable = true;
1524 self
1525 }
1526
1527 pub fn on_click(mut self, label: impl Into<String>, action: impl Fn() + 'static) -> Self {
1530 self.on_click = Some(SemanticsCustomAction::new(label, action));
1531 self
1532 }
1533
1534 pub fn on_long_click(
1538 mut self,
1539 label: impl Into<String>,
1540 action: impl Fn() -> bool + 'static,
1541 ) -> Self {
1542 self.on_long_click_label = Some(label.into());
1543 self.on_long_click = Some(SemanticsLongClick::new(action));
1544 self
1545 }
1546
1547 pub fn on_magic_tap(
1551 mut self,
1552 label: impl Into<String>,
1553 action: impl Fn() -> bool + 'static,
1554 ) -> Self {
1555 self.on_magic_tap_label = Some(label.into());
1556 self.on_magic_tap = Some(SemanticsMagicTap::new(action));
1557 self
1558 }
1559
1560 pub fn input_labels<S: Into<String>>(mut self, labels: impl IntoIterator<Item = S>) -> Self {
1563 self.input_labels = labels.into_iter().map(Into::into).collect();
1564 self
1565 }
1566
1567 pub fn language(mut self, tag: impl Into<String>) -> Self {
1570 self.language = Some(tag.into());
1571 self
1572 }
1573
1574 pub fn toggled(mut self, toggled: bool) -> Self {
1576 self.toggled = Some(toggled);
1577 self
1578 }
1579
1580 pub fn selected(mut self, selected: bool) -> Self {
1583 self.selected = Some(selected);
1584 self
1585 }
1586
1587 pub fn role(mut self, role: SemanticsWidgetRole) -> Self {
1589 self.role = Some(role);
1590 self
1591 }
1592
1593 pub fn heading(self) -> Self {
1596 self.role(SemanticsWidgetRole::Header)
1597 }
1598
1599 pub fn error(mut self, message: impl Into<String>) -> Self {
1601 self.error = Some(message.into());
1602 self
1603 }
1604
1605 pub fn password(mut self) -> Self {
1607 self.password = true;
1608 self
1609 }
1610
1611 pub fn pane_title(mut self, title: impl Into<String>) -> Self {
1614 self.pane_title = Some(title.into());
1615 self
1616 }
1617
1618 pub fn traversal_index(mut self, index: f32) -> Self {
1621 self.traversal_index = index;
1622 self
1623 }
1624
1625 pub fn hidden(mut self) -> Self {
1628 self.hidden = true;
1629 self
1630 }
1631
1632 pub fn merge_descendants(mut self) -> Self {
1635 self.merge_descendants = true;
1636 self
1637 }
1638
1639 pub fn selectable_group(mut self) -> Self {
1642 self.selectable_group = true;
1643 self
1644 }
1645
1646 pub fn live_region(mut self, mode: LiveRegionMode) -> Self {
1649 self.live_region = Some(mode);
1650 self
1651 }
1652 pub fn merge(&mut self, other: &SemanticsConfiguration) {
1653 if let Some(description) = &other.content_description {
1654 self.content_description = Some(description.clone());
1655 }
1656 if let Some(state) = &other.state_description {
1657 self.state_description = Some(state.clone());
1658 }
1659 if let Some(label) = &other.on_click_label {
1660 self.on_click_label = Some(label.clone());
1661 }
1662 if let Some(label) = &other.on_long_click_label {
1663 self.on_long_click_label = Some(label.clone());
1664 }
1665 if let Some(label) = &other.on_magic_tap_label {
1666 self.on_magic_tap_label = Some(label.clone());
1667 }
1668 if !other.input_labels.is_empty() {
1669 self.input_labels.clone_from(&other.input_labels);
1670 }
1671 if let Some(language) = &other.language {
1672 self.language = Some(language.clone());
1673 }
1674 if let Some(role) = other.role {
1675 self.role = Some(role);
1676 }
1677 if let Some(selected) = other.selected {
1678 self.selected = Some(selected);
1679 }
1680 if let Some(toggled) = other.toggled {
1681 self.toggled = Some(toggled);
1682 }
1683 self.enabled &= other.enabled;
1684 self.is_clickable |= other.is_clickable;
1685 self.is_editable_text |= other.is_editable_text;
1686 self.multiline |= other.multiline;
1687 if let Some(text) = &other.text {
1688 self.text = Some(text.clone());
1689 }
1690 self.is_modal |= other.is_modal;
1691 self.hidden |= other.hidden;
1692 self.merge_descendants |= other.merge_descendants;
1693 self.selectable_group |= other.selectable_group;
1694 self.password |= other.password;
1695 if other.traversal_index != 0.0 {
1696 self.traversal_index = other.traversal_index;
1697 }
1698 if let Some(live_region) = other.live_region {
1699 self.live_region = Some(live_region);
1700 }
1701 self.merge_words(other);
1702 self.merge_actions(other);
1703 self.merge_ranges(other);
1704 }
1705
1706 fn merge_words(&mut self, other: &SemanticsConfiguration) {
1707 if let Some(title) = &other.pane_title {
1708 self.pane_title = Some(title.clone());
1709 }
1710 if let Some(error) = &other.error {
1711 self.error = Some(error.clone());
1712 }
1713 }
1714
1715 fn merge_actions(&mut self, other: &SemanticsConfiguration) {
1716 if let Some(on_click) = &other.on_click {
1717 self.on_click = Some(on_click.clone());
1718 }
1719 self.custom_actions
1720 .extend(other.custom_actions.iter().cloned());
1721 self.canvas_children
1722 .extend(other.canvas_children.iter().cloned());
1723 if let Some(set_progress) = &other.set_progress {
1724 self.set_progress = Some(set_progress.clone());
1725 }
1726 if let Some(set_text) = &other.set_text {
1727 self.set_text = Some(set_text.clone());
1728 }
1729 if let Some(set_selection) = &other.set_selection {
1730 self.set_selection = Some(set_selection.clone());
1731 }
1732 if let Some(expand) = &other.expand {
1733 self.expand = Some(expand.clone());
1734 }
1735 if let Some(collapse) = &other.collapse {
1736 self.collapse = Some(collapse.clone());
1737 }
1738 if let Some(dismiss) = &other.dismiss {
1739 self.dismiss = Some(dismiss.clone());
1740 }
1741 if let Some(long_click) = &other.on_long_click {
1742 self.on_long_click = Some(long_click.clone());
1743 }
1744 if let Some(magic_tap) = &other.on_magic_tap {
1745 self.on_magic_tap = Some(magic_tap.clone());
1746 }
1747 if let Some(scroll_by) = &other.scroll_by {
1748 self.scroll_by = Some(scroll_by.clone());
1749 }
1750 if let Some(scroll_to_index) = &other.scroll_to_index {
1751 self.scroll_to_index = Some(scroll_to_index.clone());
1752 }
1753 }
1754
1755 fn merge_ranges(&mut self, other: &SemanticsConfiguration) {
1756 if let Some(selection) = other.text_selection {
1757 self.text_selection = Some(selection);
1758 }
1759 if let Some(progress) = other.progress {
1760 self.progress = Some(progress);
1761 }
1762 if let Some(range) = other.vertical_scroll {
1763 self.vertical_scroll = Some(range);
1764 }
1765 if let Some(range) = other.horizontal_scroll {
1766 self.horizontal_scroll = Some(range);
1767 }
1768 if let Some(collection) = other.collection {
1769 self.collection = Some(collection);
1770 }
1771 }
1772
1773 pub fn is_activatable(&self) -> bool {
1776 self.is_clickable || self.on_click_label.is_some() || self.on_click.is_some()
1777 }
1778}
1779
1780impl fmt::Debug for dyn ModifierNode {
1781 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1782 f.debug_struct("ModifierNode").finish_non_exhaustive()
1783 }
1784}
1785
1786impl dyn ModifierNode {
1787 pub fn as_any(&self) -> &dyn Any {
1788 self
1789 }
1790
1791 pub fn as_any_mut(&mut self) -> &mut dyn Any {
1792 self
1793 }
1794}
1795
1796pub trait ModifierNodeElement: fmt::Debug + Hash + PartialEq + 'static {
1799 type Node: ModifierNode;
1800
1801 fn create(&self) -> Self::Node;
1803
1804 fn update(&self, node: &mut Self::Node);
1806
1807 fn key(&self) -> Option<u64> {
1809 None
1810 }
1811
1812 fn inspector_name(&self) -> &'static str {
1814 type_name::<Self>()
1815 }
1816
1817 fn inspector_properties(&self, _inspector: &mut dyn FnMut(&'static str, String)) {}
1819
1820 fn capabilities(&self) -> NodeCapabilities {
1823 NodeCapabilities::default()
1824 }
1825
1826 fn always_update(&self) -> bool {
1832 false
1833 }
1834
1835 fn auto_invalidate_on_update(&self) -> bool {
1838 true
1839 }
1840
1841 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
1848 None
1849 }
1850
1851 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
1858 Vec::new()
1859 }
1860}
1861
1862#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1864pub struct NodeCapabilities(u32);
1865
1866impl NodeCapabilities {
1867 pub const NONE: Self = Self(0);
1869 pub const LAYOUT: Self = Self(1 << 0);
1871 pub const DRAW: Self = Self(1 << 1);
1873 pub const POINTER_INPUT: Self = Self(1 << 2);
1875 pub const SEMANTICS: Self = Self(1 << 3);
1877 pub const MODIFIER_LOCALS: Self = Self(1 << 4);
1879 pub const FOCUS: Self = Self(1 << 5);
1881 pub const WINDOW_ROOT: Self = Self(1 << 6);
1885
1886 pub const fn empty() -> Self {
1888 Self::NONE
1889 }
1890
1891 pub const fn contains(self, other: Self) -> bool {
1893 (self.0 & other.0) == other.0
1894 }
1895
1896 pub const fn intersects(self, other: Self) -> bool {
1898 (self.0 & other.0) != 0
1899 }
1900
1901 pub fn insert(&mut self, other: Self) {
1903 self.0 |= other.0;
1904 }
1905
1906 pub const fn bits(self) -> u32 {
1908 self.0
1909 }
1910
1911 pub const fn is_empty(self) -> bool {
1913 self.0 == 0
1914 }
1915
1916 pub const fn for_invalidation(kind: InvalidationKind) -> Self {
1918 match kind {
1919 InvalidationKind::Layout => Self::LAYOUT,
1920 InvalidationKind::Draw => Self::DRAW,
1921 InvalidationKind::PointerInput => Self::POINTER_INPUT,
1922 InvalidationKind::Semantics => Self::SEMANTICS,
1923 InvalidationKind::Focus => Self::FOCUS,
1924 }
1925 }
1926}
1927
1928impl Default for NodeCapabilities {
1929 fn default() -> Self {
1930 Self::NONE
1931 }
1932}
1933
1934impl fmt::Debug for NodeCapabilities {
1935 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1936 f.debug_struct("NodeCapabilities")
1937 .field("layout", &self.contains(Self::LAYOUT))
1938 .field("draw", &self.contains(Self::DRAW))
1939 .field("pointer_input", &self.contains(Self::POINTER_INPUT))
1940 .field("semantics", &self.contains(Self::SEMANTICS))
1941 .field("modifier_locals", &self.contains(Self::MODIFIER_LOCALS))
1942 .field("focus", &self.contains(Self::FOCUS))
1943 .field("window_root", &self.contains(Self::WINDOW_ROOT))
1944 .finish()
1945 }
1946}
1947
1948impl BitOr for NodeCapabilities {
1949 type Output = Self;
1950
1951 fn bitor(self, rhs: Self) -> Self::Output {
1952 Self(self.0 | rhs.0)
1953 }
1954}
1955
1956impl BitOrAssign for NodeCapabilities {
1957 fn bitor_assign(&mut self, rhs: Self) {
1958 self.0 |= rhs.0;
1959 }
1960}
1961
1962#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1964pub struct ModifierInvalidation {
1965 kind: InvalidationKind,
1966 capabilities: NodeCapabilities,
1967}
1968
1969impl ModifierInvalidation {
1970 pub const fn new(kind: InvalidationKind, capabilities: NodeCapabilities) -> Self {
1972 Self { kind, capabilities }
1973 }
1974
1975 pub const fn kind(self) -> InvalidationKind {
1977 self.kind
1978 }
1979
1980 pub const fn capabilities(self) -> NodeCapabilities {
1982 self.capabilities
1983 }
1984}
1985
1986pub trait AnyModifierElement: fmt::Debug {
1988 fn node_type(&self) -> TypeId;
1989
1990 fn element_type(&self) -> TypeId;
1991
1992 fn create_node(&self) -> Box<dyn ModifierNode>;
1993
1994 fn can_update_node(&self, node: &dyn ModifierNode) -> bool;
1995
1996 fn update_node(&self, node: &mut dyn ModifierNode);
1997
1998 fn key(&self) -> Option<u64>;
1999
2000 fn capabilities(&self) -> NodeCapabilities {
2001 NodeCapabilities::default()
2002 }
2003
2004 fn hash_code(&self) -> u64;
2005
2006 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool;
2007
2008 fn inspector_name(&self) -> &'static str;
2009
2010 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String));
2011
2012 fn requires_update(&self) -> bool;
2013
2014 fn auto_invalidates_on_update(&self) -> bool;
2015
2016 fn update_invalidation_kind(&self) -> Option<InvalidationKind>;
2017
2018 fn provides_composition_locals(&self) -> bool {
2020 false
2021 }
2022
2023 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2025 Vec::new()
2026 }
2027
2028 fn as_any(&self) -> &dyn Any;
2029}
2030
2031struct TypedModifierElement<E: ModifierNodeElement> {
2032 element: E,
2033 cached_hash: u64,
2034 provides_locals: bool,
2035}
2036
2037impl<E: ModifierNodeElement> TypedModifierElement<E> {
2038 fn new(element: E) -> Self {
2039 let mut hasher = default::new();
2040 element.hash(&mut hasher);
2041 let provides_locals = !element.provided_composition_locals().is_empty();
2042 Self {
2043 element,
2044 cached_hash: hasher.finish(),
2045 provides_locals,
2046 }
2047 }
2048}
2049
2050impl<E> fmt::Debug for TypedModifierElement<E>
2051where
2052 E: ModifierNodeElement,
2053{
2054 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2055 f.debug_struct("TypedModifierElement")
2056 .field("type", &type_name::<E>())
2057 .finish()
2058 }
2059}
2060
2061impl<E> AnyModifierElement for TypedModifierElement<E>
2062where
2063 E: ModifierNodeElement,
2064{
2065 fn node_type(&self) -> TypeId {
2066 TypeId::of::<E::Node>()
2067 }
2068
2069 fn element_type(&self) -> TypeId {
2070 TypeId::of::<E>()
2071 }
2072
2073 fn create_node(&self) -> Box<dyn ModifierNode> {
2074 Box::new(self.element.create())
2075 }
2076
2077 fn can_update_node(&self, node: &dyn ModifierNode) -> bool {
2078 node.as_any().is::<E::Node>()
2079 }
2080
2081 fn update_node(&self, node: &mut dyn ModifierNode) {
2082 if let Some(typed) = node.as_any_mut().downcast_mut::<E::Node>() {
2083 self.element.update(typed);
2084 }
2085 }
2086
2087 fn key(&self) -> Option<u64> {
2088 self.element.key()
2089 }
2090
2091 fn capabilities(&self) -> NodeCapabilities {
2092 self.element.capabilities()
2093 }
2094
2095 fn provides_composition_locals(&self) -> bool {
2096 self.provides_locals
2097 }
2098
2099 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2100 self.element.provided_composition_locals()
2101 }
2102
2103 fn hash_code(&self) -> u64 {
2104 self.cached_hash
2105 }
2106
2107 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool {
2108 other
2109 .as_any()
2110 .downcast_ref::<Self>()
2111 .is_some_and(|typed| typed.element == self.element)
2112 }
2113
2114 fn inspector_name(&self) -> &'static str {
2115 self.element.inspector_name()
2116 }
2117
2118 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String)) {
2119 self.element.inspector_properties(visitor);
2120 }
2121
2122 fn requires_update(&self) -> bool {
2123 self.element.always_update()
2124 }
2125
2126 fn auto_invalidates_on_update(&self) -> bool {
2127 self.element.auto_invalidate_on_update()
2128 }
2129
2130 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
2131 self.element.update_invalidation_kind()
2132 }
2133
2134 fn as_any(&self) -> &dyn Any {
2135 self
2136 }
2137}
2138
2139fn request_update_auto_invalidations(
2140 element: &dyn AnyModifierElement,
2141 context: &mut dyn ModifierNodeContext,
2142 capabilities: NodeCapabilities,
2143) {
2144 if let Some(kind) = element.update_invalidation_kind() {
2145 let capabilities = NodeCapabilities::for_invalidation(kind);
2146 context.push_active_capabilities(capabilities);
2147 context.invalidate(kind);
2148 context.pop_active_capabilities();
2149 } else if element.auto_invalidates_on_update() {
2150 request_auto_invalidations(context, capabilities);
2151 }
2152}
2153
2154pub fn modifier_element<E: ModifierNodeElement>(element: E) -> DynModifierElement {
2157 Rc::new(TypedModifierElement::new(element))
2158}
2159
2160pub type DynModifierElement = Rc<dyn AnyModifierElement>;
2162
2163#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2164enum TraversalDirection {
2165 Forward,
2166 Backward,
2167}
2168
2169pub struct ModifierChainIter<'a> {
2174 chain: &'a ModifierNodeChain,
2175 cursor: usize,
2176 remaining: usize,
2177 direction: TraversalDirection,
2178}
2179
2180impl<'a> ModifierChainIter<'a> {
2181 fn forward(chain: &'a ModifierNodeChain) -> Self {
2182 Self {
2183 chain,
2184 cursor: 0,
2185 remaining: chain.ordered_nodes.len(),
2186 direction: TraversalDirection::Forward,
2187 }
2188 }
2189
2190 fn backward(chain: &'a ModifierNodeChain) -> Self {
2191 let len = chain.ordered_nodes.len();
2192 Self {
2193 chain,
2194 cursor: len.wrapping_sub(1),
2195 remaining: len,
2196 direction: TraversalDirection::Backward,
2197 }
2198 }
2199}
2200
2201impl<'a> Iterator for ModifierChainIter<'a> {
2202 type Item = ModifierChainNodeRef<'a>;
2203
2204 #[inline]
2205 fn next(&mut self) -> Option<Self::Item> {
2206 if self.remaining == 0 {
2207 return None;
2208 }
2209 let (link, caps, agg) = self.chain.ordered_nodes[self.cursor];
2210 let node_ref = self.chain.make_node_ref_with_caps(link, caps, agg);
2211 self.remaining -= 1;
2212 match self.direction {
2213 TraversalDirection::Forward => self.cursor += 1,
2214 TraversalDirection::Backward => self.cursor = self.cursor.wrapping_sub(1),
2215 }
2216 Some(node_ref)
2217 }
2218
2219 #[inline]
2220 fn size_hint(&self) -> (usize, Option<usize>) {
2221 (self.remaining, Some(self.remaining))
2222 }
2223}
2224
2225impl ExactSizeIterator for ModifierChainIter<'_> {}
2226impl std::iter::FusedIterator for ModifierChainIter<'_> {}
2227
2228#[derive(Debug)]
2229struct ModifierNodeEntry {
2230 element_type: TypeId,
2231 node_type: TypeId,
2232 key: Option<u64>,
2233 hash_code: u64,
2234 element: DynModifierElement,
2235 node: Rc<RefCell<Box<dyn ModifierNode>>>,
2236 capabilities: NodeCapabilities,
2237}
2238
2239impl ModifierNodeEntry {
2240 fn new(
2241 element_type: TypeId,
2242 node_type: TypeId,
2243 key: Option<u64>,
2244 element: DynModifierElement,
2245 node: Box<dyn ModifierNode>,
2246 hash_code: u64,
2247 capabilities: NodeCapabilities,
2248 ) -> Self {
2249 let node_rc = Rc::new(RefCell::new(node));
2250 let entry = Self {
2251 element_type,
2252 node_type,
2253 key,
2254 hash_code,
2255 element,
2256 node: Rc::clone(&node_rc),
2257 capabilities,
2258 };
2259 entry
2260 .node
2261 .borrow()
2262 .node_state()
2263 .set_capabilities(entry.capabilities);
2264 entry
2265 }
2266}
2267
2268fn visit_node_tree_mut(
2269 node: &mut dyn ModifierNode,
2270 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
2271) {
2272 visitor(node);
2273 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
2274}
2275
2276fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
2277 let mut current = 0usize;
2278 let mut result: Option<&dyn ModifierNode> = None;
2279 node.for_each_delegate(&mut |child| {
2280 if result.is_none() && current == target {
2281 result = Some(child);
2282 }
2283 current += 1;
2284 });
2285 result
2286}
2287
2288fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
2289 let mut current = 0usize;
2290 let mut result: Option<&mut dyn ModifierNode> = None;
2291 node.for_each_delegate_mut(&mut |child| {
2292 if result.is_none() && current == target {
2293 result = Some(child);
2294 }
2295 current += 1;
2296 });
2297 result
2298}
2299
2300fn with_node_context<F, R>(
2301 node: &mut dyn ModifierNode,
2302 context: &mut dyn ModifierNodeContext,
2303 f: F,
2304) -> R
2305where
2306 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
2307{
2308 context.push_active_capabilities(node.node_state().capabilities());
2309 let result = f(node, context);
2310 context.pop_active_capabilities();
2311 result
2312}
2313
2314fn request_auto_invalidations(
2315 context: &mut dyn ModifierNodeContext,
2316 capabilities: NodeCapabilities,
2317) {
2318 if capabilities.is_empty() {
2319 return;
2320 }
2321
2322 context.push_active_capabilities(capabilities);
2323
2324 if capabilities.contains(NodeCapabilities::LAYOUT) {
2325 context.invalidate(InvalidationKind::Layout);
2326 }
2327 if capabilities.contains(NodeCapabilities::DRAW) {
2328 context.invalidate(InvalidationKind::Draw);
2329 }
2330 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
2331 context.invalidate(InvalidationKind::PointerInput);
2332 }
2333 if capabilities.contains(NodeCapabilities::SEMANTICS) {
2334 context.invalidate(InvalidationKind::Semantics);
2335 }
2336 if capabilities.contains(NodeCapabilities::FOCUS) {
2337 context.invalidate(InvalidationKind::Focus);
2338 }
2339
2340 context.pop_active_capabilities();
2341}
2342
2343fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
2344 visit_node_tree_mut(node, &mut |n| {
2345 if !n.node_state().is_attached() {
2346 n.node_state().set_attached(true);
2347 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
2348 }
2349 });
2350}
2351
2352fn reset_node_tree(node: &mut dyn ModifierNode) {
2353 visit_node_tree_mut(node, &mut |n| n.on_reset());
2354}
2355
2356fn detach_node_tree(node: &mut dyn ModifierNode) {
2357 visit_node_tree_mut(node, &mut |n| {
2358 if n.node_state().is_attached() {
2359 n.on_detach();
2360 n.node_state().set_attached(false);
2361 }
2362 n.node_state().set_parent_link(None);
2363 n.node_state().set_child_link(None);
2364 n.node_state()
2365 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2366 });
2367}
2368
2369pub struct ModifierNodeChain {
2376 entries: Vec<ModifierNodeEntry>,
2377 aggregated_capabilities: NodeCapabilities,
2378 head_aggregate_child_capabilities: NodeCapabilities,
2379 head_sentinel: Box<SentinelNode>,
2380 tail_sentinel: Box<SentinelNode>,
2381 ordered_nodes: Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
2382 scratch_old_used: Vec<bool>,
2383 scratch_match_order: Vec<Option<usize>>,
2384 scratch_final_slots: Vec<Option<ModifierNodeEntry>>,
2385 scratch_elements: Vec<DynModifierElement>,
2386}
2387
2388struct SentinelNode {
2389 state: NodeState,
2390}
2391
2392impl SentinelNode {
2393 fn new() -> Self {
2394 Self {
2395 state: NodeState::sentinel(),
2396 }
2397 }
2398}
2399
2400impl DelegatableNode for SentinelNode {
2401 fn node_state(&self) -> &NodeState {
2402 &self.state
2403 }
2404}
2405
2406impl ModifierNode for SentinelNode {}
2407
2408#[derive(Clone)]
2409pub struct ModifierChainNodeRef<'a> {
2410 chain: &'a ModifierNodeChain,
2411 link: NodeLink,
2412 cached_capabilities: Option<NodeCapabilities>,
2413 cached_aggregate_child: Option<NodeCapabilities>,
2414}
2415
2416impl Default for ModifierNodeChain {
2417 fn default() -> Self {
2418 Self::new()
2419 }
2420}
2421
2422struct EntryIndex {
2423 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2424 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2425 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
2426}
2427
2428struct EntryMatchQuery<'a> {
2429 element_type: TypeId,
2430 node_type: TypeId,
2431 key: Option<u64>,
2432 hash_code: u64,
2433 element: &'a DynModifierElement,
2434}
2435
2436impl EntryIndex {
2437 fn build(entries: &[ModifierNodeEntry]) -> Self {
2438 let mut keyed = HashMap::default();
2439 let mut hashed = HashMap::default();
2440 let mut typed = HashMap::default();
2441
2442 for (i, entry) in entries.iter().enumerate() {
2443 if let Some(key_value) = entry.key {
2444 keyed
2445 .entry((entry.element_type, entry.node_type, key_value))
2446 .or_insert_with(Vec::new)
2447 .push(i);
2448 } else {
2449 hashed
2450 .entry((entry.element_type, entry.node_type, entry.hash_code))
2451 .or_insert_with(Vec::new)
2452 .push(i);
2453 typed
2454 .entry((entry.element_type, entry.node_type))
2455 .or_insert_with(Vec::new)
2456 .push(i);
2457 }
2458 }
2459
2460 Self {
2461 keyed,
2462 hashed,
2463 typed,
2464 }
2465 }
2466
2467 fn find_match(
2468 &self,
2469 entries: &[ModifierNodeEntry],
2470 used: &[bool],
2471 query: EntryMatchQuery<'_>,
2472 ) -> Option<usize> {
2473 if let Some(key_value) = query.key {
2474 if let Some(candidates) =
2475 self.keyed
2476 .get(&(query.element_type, query.node_type, key_value))
2477 {
2478 for &i in candidates {
2479 if !used[i] {
2480 return Some(i);
2481 }
2482 }
2483 }
2484 } else {
2485 if let Some(candidates) =
2486 self.hashed
2487 .get(&(query.element_type, query.node_type, query.hash_code))
2488 {
2489 for &i in candidates {
2490 if !used[i]
2491 && entries[i]
2492 .element
2493 .as_ref()
2494 .equals_element(query.element.as_ref())
2495 {
2496 return Some(i);
2497 }
2498 }
2499 }
2500
2501 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
2502 for &i in candidates {
2503 if !used[i] {
2504 return Some(i);
2505 }
2506 }
2507 }
2508 }
2509
2510 None
2511 }
2512}
2513
2514impl ModifierNodeChain {
2515 pub fn new() -> Self {
2516 let mut chain = Self {
2517 entries: Vec::new(),
2518 aggregated_capabilities: NodeCapabilities::empty(),
2519 head_aggregate_child_capabilities: NodeCapabilities::empty(),
2520 head_sentinel: Box::new(SentinelNode::new()),
2521 tail_sentinel: Box::new(SentinelNode::new()),
2522 ordered_nodes: Vec::new(),
2523 scratch_old_used: Vec::new(),
2524 scratch_match_order: Vec::new(),
2525 scratch_final_slots: Vec::new(),
2526 scratch_elements: Vec::new(),
2527 };
2528 chain.sync_chain_links();
2529 chain
2530 }
2531
2532 pub fn detach_nodes(&mut self) {
2534 for entry in &self.entries {
2535 detach_node_tree(&mut **entry.node.borrow_mut());
2536 }
2537 }
2538
2539 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
2541 for entry in &self.entries {
2542 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2543 }
2544 }
2545
2546 pub fn repair_chain(&mut self) {
2549 self.sync_chain_links();
2550 }
2551
2552 pub fn update_from_slice(
2558 &mut self,
2559 elements: &[DynModifierElement],
2560 context: &mut dyn ModifierNodeContext,
2561 ) {
2562 self.update_from_ref_iter(elements.iter(), context);
2563 }
2564
2565 pub fn update_from_ref_iter<'a, I>(
2570 &mut self,
2571 elements: I,
2572 context: &mut dyn ModifierNodeContext,
2573 ) where
2574 I: Iterator<Item = &'a DynModifierElement>,
2575 {
2576 let old_len = self.entries.len();
2577 let mut fast_path_failed_at: Option<usize> = None;
2578 let mut elements_count = 0;
2579
2580 self.scratch_elements.clear();
2581
2582 for (idx, element) in elements.enumerate() {
2583 elements_count = idx + 1;
2584
2585 if fast_path_failed_at.is_none() && idx < old_len {
2586 let entry = &mut self.entries[idx];
2587 let same_type = entry.element_type == element.element_type();
2588 let same_node_type = entry.node_type == element.node_type();
2589 let same_key = entry.key == element.key();
2590 let same_hash = entry.hash_code == element.hash_code();
2591
2592 let positional_update = element.requires_update();
2593 if same_type && same_node_type && same_key && (same_hash || positional_update) {
2594 let can_update_node = {
2595 let node_borrow = entry.node.borrow();
2596 element.can_update_node(&**node_borrow)
2597 };
2598 if !can_update_node {
2599 fast_path_failed_at = Some(idx);
2600 self.scratch_elements.push(element.clone());
2601 continue;
2602 }
2603
2604 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2605 let capabilities = element.capabilities();
2606
2607 {
2608 let node_borrow = entry.node.borrow();
2609 if !node_borrow.node_state().is_attached() {
2610 drop(node_borrow);
2611 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2612 }
2613 }
2614
2615 let needs_update = !same_element || element.requires_update();
2616 if needs_update {
2617 element.update_node(&mut **entry.node.borrow_mut());
2618 entry.element = element.clone();
2619 entry.hash_code = element.hash_code();
2620 request_update_auto_invalidations(element.as_ref(), context, capabilities);
2621 }
2622
2623 entry.capabilities = capabilities;
2624 entry
2625 .node
2626 .borrow()
2627 .node_state()
2628 .set_capabilities(capabilities);
2629 continue;
2630 }
2631 fast_path_failed_at = Some(idx);
2632 }
2633
2634 self.scratch_elements.push(element.clone());
2635 }
2636
2637 if fast_path_failed_at.is_none() && self.scratch_elements.is_empty() {
2638 if elements_count < self.entries.len() {
2639 for entry in self.entries.drain(elements_count..) {
2640 request_auto_invalidations(context, entry.capabilities);
2641 detach_node_tree(&mut **entry.node.borrow_mut());
2642 }
2643 }
2644 self.sync_chain_links();
2645 return;
2646 }
2647
2648 let fail_idx = fast_path_failed_at.unwrap_or(old_len);
2649
2650 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
2651 let processed_entries_len = self.entries.len();
2652 let old_len = old_entries.len();
2653
2654 self.scratch_old_used.clear();
2655 self.scratch_old_used.resize(old_len, false);
2656
2657 self.scratch_match_order.clear();
2658 self.scratch_match_order.resize(old_len, None);
2659
2660 let index = EntryIndex::build(&old_entries);
2661
2662 let new_elements_count = self.scratch_elements.len();
2663 self.scratch_final_slots.clear();
2664 self.scratch_final_slots.reserve(new_elements_count);
2665
2666 for (new_pos, element) in self.scratch_elements.drain(..).enumerate() {
2667 self.scratch_final_slots.push(None);
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
2674 let matched_idx = index.find_match(
2675 &old_entries,
2676 &self.scratch_old_used,
2677 EntryMatchQuery {
2678 element_type,
2679 node_type,
2680 key,
2681 hash_code,
2682 element: &element,
2683 },
2684 );
2685
2686 if let Some(idx) = matched_idx {
2687 let entry = &mut old_entries[idx];
2688 let can_update_node = {
2689 let node_borrow = entry.node.borrow();
2690 element.can_update_node(&**node_borrow)
2691 };
2692 if !can_update_node {
2693 let replacement = ModifierNodeEntry::new(
2694 element_type,
2695 node_type,
2696 key,
2697 element.clone(),
2698 element.create_node(),
2699 hash_code,
2700 capabilities,
2701 );
2702 attach_node_tree(&mut **replacement.node.borrow_mut(), context);
2703 element.update_node(&mut **replacement.node.borrow_mut());
2704 request_auto_invalidations(context, capabilities);
2705 self.scratch_final_slots[new_pos] = Some(replacement);
2706 continue;
2707 }
2708
2709 self.scratch_old_used[idx] = true;
2710 self.scratch_match_order[idx] = Some(new_pos);
2711 let moved = idx != new_pos;
2712
2713 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2714
2715 {
2716 let node_borrow = entry.node.borrow();
2717 if !node_borrow.node_state().is_attached() {
2718 drop(node_borrow);
2719 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2720 }
2721 }
2722
2723 let needs_update = !same_element || element.requires_update();
2724 if needs_update {
2725 element.update_node(&mut **entry.node.borrow_mut());
2726 entry.element = element;
2727 entry.hash_code = hash_code;
2728 request_update_auto_invalidations(
2729 entry.element.as_ref(),
2730 context,
2731 capabilities,
2732 );
2733 }
2734 if moved {
2735 request_auto_invalidations(context, capabilities);
2736 }
2737
2738 entry.key = key;
2739 entry.element_type = element_type;
2740 entry.node_type = node_type;
2741 entry.capabilities = capabilities;
2742 entry
2743 .node
2744 .borrow()
2745 .node_state()
2746 .set_capabilities(capabilities);
2747 } else {
2748 let entry = ModifierNodeEntry::new(
2749 element_type,
2750 node_type,
2751 key,
2752 element.clone(),
2753 element.create_node(),
2754 hash_code,
2755 capabilities,
2756 );
2757 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2758 element.update_node(&mut **entry.node.borrow_mut());
2759 request_auto_invalidations(context, capabilities);
2760 self.scratch_final_slots[new_pos] = Some(entry);
2761 }
2762 }
2763
2764 for (i, entry) in old_entries.into_iter().enumerate() {
2765 if self.scratch_old_used[i] {
2766 if let Some(pos) = self.scratch_match_order[i] {
2767 self.scratch_final_slots[pos] = Some(entry);
2768 } else {
2769 request_auto_invalidations(context, entry.capabilities);
2770 detach_node_tree(&mut **entry.node.borrow_mut());
2771 }
2772 } else {
2773 request_auto_invalidations(context, entry.capabilities);
2774 detach_node_tree(&mut **entry.node.borrow_mut());
2775 }
2776 }
2777
2778 self.entries.reserve(self.scratch_final_slots.len());
2779 for slot in self.scratch_final_slots.drain(..) {
2780 if let Some(entry) = slot {
2781 self.entries.push(entry);
2782 } else {
2783 log::error!("modifier reconciliation produced an empty final slot");
2784 }
2785 }
2786
2787 debug_assert_eq!(
2788 self.entries.len(),
2789 processed_entries_len + new_elements_count
2790 );
2791 self.sync_chain_links();
2792 }
2793
2794 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
2798 where
2799 I: IntoIterator<Item = DynModifierElement>,
2800 {
2801 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
2802 self.update_from_slice(&collected, context);
2803 }
2804
2805 pub fn reset(&mut self) {
2808 for entry in &mut self.entries {
2809 reset_node_tree(&mut **entry.node.borrow_mut());
2810 }
2811 }
2812
2813 pub fn detach_all(&mut self) {
2815 for entry in std::mem::take(&mut self.entries) {
2816 detach_node_tree(&mut **entry.node.borrow_mut());
2817 {
2818 let node_borrow = entry.node.borrow();
2819 let state = node_borrow.node_state();
2820 state.set_capabilities(NodeCapabilities::empty());
2821 }
2822 }
2823 self.aggregated_capabilities = NodeCapabilities::empty();
2824 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2825 self.ordered_nodes.clear();
2826 self.sync_chain_links();
2827 }
2828
2829 pub fn len(&self) -> usize {
2830 self.entries.len()
2831 }
2832
2833 pub fn is_empty(&self) -> bool {
2834 self.entries.is_empty()
2835 }
2836
2837 pub fn capabilities(&self) -> NodeCapabilities {
2839 self.aggregated_capabilities
2840 }
2841
2842 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
2844 self.aggregated_capabilities.contains(capability)
2845 }
2846
2847 pub fn head(&self) -> ModifierChainNodeRef<'_> {
2849 self.make_node_ref(NodeLink::Head)
2850 }
2851
2852 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
2854 self.make_node_ref(NodeLink::Tail)
2855 }
2856
2857 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
2859 ModifierChainIter::forward(self)
2860 }
2861
2862 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
2864 ModifierChainIter::backward(self)
2865 }
2866
2867 pub fn for_each_forward<F>(&self, mut f: F)
2869 where
2870 F: FnMut(ModifierChainNodeRef<'_>),
2871 {
2872 for node in self.head_to_tail() {
2873 f(node);
2874 }
2875 }
2876
2877 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
2879 where
2880 F: FnMut(ModifierChainNodeRef<'_>),
2881 {
2882 if mask.is_empty() {
2883 self.for_each_forward(f);
2884 return;
2885 }
2886
2887 if !self.head().aggregate_child_capabilities().intersects(mask) {
2888 return;
2889 }
2890
2891 for node in self.head_to_tail() {
2892 if node.kind_set().intersects(mask) {
2893 f(node);
2894 }
2895 }
2896 }
2897
2898 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
2900 where
2901 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
2902 {
2903 self.for_each_forward_matching(mask, |node_ref| {
2904 node_ref.with_node(|node| f(node_ref.clone(), node));
2905 });
2906 }
2907
2908 pub fn for_each_backward<F>(&self, mut f: F)
2910 where
2911 F: FnMut(ModifierChainNodeRef<'_>),
2912 {
2913 for node in self.tail_to_head() {
2914 f(node);
2915 }
2916 }
2917
2918 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
2920 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
2921 node as *const dyn ModifierNode as *const ()
2922 }
2923
2924 let target = node_data_ptr(node);
2925 for (index, entry) in self.entries.iter().enumerate() {
2926 if node_data_ptr(&**entry.node.borrow()) == target {
2927 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
2928 }
2929 }
2930
2931 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
2932 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
2933 return None;
2934 }
2935 let matches_target = match link {
2936 NodeLink::Head => node_data_ptr(self.head_sentinel.as_ref()) == target,
2937 NodeLink::Tail => node_data_ptr(self.tail_sentinel.as_ref()) == target,
2938 NodeLink::Entry(path) => {
2939 let node_borrow = self.entries[path.entry()].node.borrow();
2940 node_data_ptr(&**node_borrow) == target
2941 }
2942 };
2943 if matches_target {
2944 Some(self.make_node_ref(*link))
2945 } else {
2946 None
2947 }
2948 })
2949 }
2950
2951 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
2954 self.entries.get(index).and_then(|entry| {
2955 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
2956 boxed_node.as_any().downcast_ref::<N>()
2957 })
2958 .ok()
2959 })
2960 }
2961
2962 pub fn node_mut<N: ModifierNode + 'static>(
2965 &self,
2966 index: usize,
2967 ) -> Option<std::cell::RefMut<'_, N>> {
2968 self.entries.get(index).and_then(|entry| {
2969 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
2970 boxed_node.as_any_mut().downcast_mut::<N>()
2971 })
2972 .ok()
2973 })
2974 }
2975
2976 pub fn get_node_rc(&self, index: usize) -> Option<Rc<RefCell<Box<dyn ModifierNode>>>> {
2979 self.entries.get(index).map(|entry| Rc::clone(&entry.node))
2980 }
2981
2982 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
2984 self.aggregated_capabilities
2985 .contains(NodeCapabilities::for_invalidation(kind))
2986 }
2987
2988 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
2990 where
2991 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
2992 {
2993 for index in 0..self.ordered_nodes.len() {
2994 let (link, cached_caps, _agg) = self.ordered_nodes[index];
2995 match link {
2996 NodeLink::Head => {
2997 f(self.head_sentinel.as_mut(), cached_caps);
2998 }
2999 NodeLink::Tail => {
3000 f(self.tail_sentinel.as_mut(), cached_caps);
3001 }
3002 NodeLink::Entry(path) => {
3003 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
3004 if path.delegates().is_empty() {
3005 f(&mut **node_borrow, cached_caps);
3006 } else {
3007 let mut current: &mut dyn ModifierNode = &mut **node_borrow;
3008 for &delegate_index in path.delegates() {
3009 if let Some(delegate) =
3010 nth_delegate_mut(current, delegate_index as usize)
3011 {
3012 current = delegate;
3013 } else {
3014 return;
3015 }
3016 }
3017 f(current, cached_caps);
3018 }
3019 }
3020 }
3021 }
3022 }
3023
3024 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
3025 ModifierChainNodeRef {
3026 chain: self,
3027 link,
3028 cached_capabilities: None,
3029 cached_aggregate_child: None,
3030 }
3031 }
3032
3033 fn make_node_ref_with_caps(
3034 &self,
3035 link: NodeLink,
3036 caps: NodeCapabilities,
3037 aggregate_child: NodeCapabilities,
3038 ) -> ModifierChainNodeRef<'_> {
3039 ModifierChainNodeRef {
3040 chain: self,
3041 link,
3042 cached_capabilities: Some(caps),
3043 cached_aggregate_child: Some(aggregate_child),
3044 }
3045 }
3046
3047 fn sync_chain_links(&mut self) {
3048 self.rebuild_ordered_nodes();
3049
3050 self.head_sentinel.node_state().set_parent_link(None);
3051 self.tail_sentinel.node_state().set_child_link(None);
3052
3053 if self.ordered_nodes.is_empty() {
3054 self.head_sentinel
3055 .node_state()
3056 .set_child_link(Some(NodeLink::Tail));
3057 self.tail_sentinel
3058 .node_state()
3059 .set_parent_link(Some(NodeLink::Head));
3060 self.aggregated_capabilities = NodeCapabilities::empty();
3061 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
3062 self.head_sentinel
3063 .node_state()
3064 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3065 self.tail_sentinel
3066 .node_state()
3067 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3068 return;
3069 }
3070
3071 let mut previous = NodeLink::Head;
3072 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
3073 match &previous {
3074 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
3075 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
3076 NodeLink::Entry(path) => {
3077 let node_borrow = self.entries[path.entry()].node.borrow();
3078 if path.delegates().is_empty() {
3079 node_borrow.node_state().set_child_link(Some(link));
3080 } else {
3081 let mut current: &dyn ModifierNode = &**node_borrow;
3082 for &delegate_index in path.delegates() {
3083 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3084 current = delegate;
3085 }
3086 }
3087 current.node_state().set_child_link(Some(link));
3088 }
3089 }
3090 }
3091 match &link {
3092 NodeLink::Head => self
3093 .head_sentinel
3094 .node_state()
3095 .set_parent_link(Some(previous)),
3096 NodeLink::Tail => self
3097 .tail_sentinel
3098 .node_state()
3099 .set_parent_link(Some(previous)),
3100 NodeLink::Entry(path) => {
3101 let node_borrow = self.entries[path.entry()].node.borrow();
3102 if path.delegates().is_empty() {
3103 node_borrow.node_state().set_parent_link(Some(previous));
3104 } else {
3105 let mut current: &dyn ModifierNode = &**node_borrow;
3106 for &delegate_index in path.delegates() {
3107 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3108 current = delegate;
3109 }
3110 }
3111 current.node_state().set_parent_link(Some(previous));
3112 }
3113 }
3114 }
3115 previous = link;
3116 }
3117
3118 match &previous {
3119 NodeLink::Head => self
3120 .head_sentinel
3121 .node_state()
3122 .set_child_link(Some(NodeLink::Tail)),
3123 NodeLink::Tail => self
3124 .tail_sentinel
3125 .node_state()
3126 .set_child_link(Some(NodeLink::Tail)),
3127 NodeLink::Entry(path) => {
3128 let node_borrow = self.entries[path.entry()].node.borrow();
3129 if path.delegates().is_empty() {
3130 node_borrow
3131 .node_state()
3132 .set_child_link(Some(NodeLink::Tail));
3133 } else {
3134 let mut current: &dyn ModifierNode = &**node_borrow;
3135 for &delegate_index in path.delegates() {
3136 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3137 current = delegate;
3138 }
3139 }
3140 current.node_state().set_child_link(Some(NodeLink::Tail));
3141 }
3142 }
3143 }
3144 self.tail_sentinel
3145 .node_state()
3146 .set_parent_link(Some(previous));
3147 self.tail_sentinel.node_state().set_child_link(None);
3148
3149 let mut aggregate = NodeCapabilities::empty();
3150 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
3151 aggregate |= *cached_caps;
3152 *cached_aggregate = aggregate;
3153 match link {
3154 NodeLink::Head => {
3155 self.head_sentinel
3156 .node_state()
3157 .set_aggregate_child_capabilities(aggregate);
3158 }
3159 NodeLink::Tail => {
3160 self.tail_sentinel
3161 .node_state()
3162 .set_aggregate_child_capabilities(aggregate);
3163 }
3164 NodeLink::Entry(path) => {
3165 let node_borrow = self.entries[path.entry()].node.borrow();
3166 let state = if path.delegates().is_empty() {
3167 node_borrow.node_state()
3168 } else {
3169 let mut current: &dyn ModifierNode = &**node_borrow;
3170 for &delegate_index in path.delegates() {
3171 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3172 current = delegate;
3173 }
3174 }
3175 current.node_state()
3176 };
3177 state.set_aggregate_child_capabilities(aggregate);
3178 }
3179 }
3180 }
3181
3182 self.aggregated_capabilities = aggregate;
3183 self.head_aggregate_child_capabilities = aggregate;
3184 self.head_sentinel
3185 .node_state()
3186 .set_aggregate_child_capabilities(aggregate);
3187 self.tail_sentinel
3188 .node_state()
3189 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3190 }
3191
3192 fn rebuild_ordered_nodes(&mut self) {
3193 self.ordered_nodes.clear();
3194 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
3195 for (index, entry) in self.entries.iter().enumerate() {
3196 let node_borrow = entry.node.borrow();
3197 Self::enumerate_link_order(
3198 &**node_borrow,
3199 index,
3200 &mut path_buf,
3201 0,
3202 &mut self.ordered_nodes,
3203 );
3204 }
3205 }
3206
3207 fn enumerate_link_order(
3208 node: &dyn ModifierNode,
3209 entry: usize,
3210 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
3211 path_len: usize,
3212 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
3213 ) {
3214 let caps = node.node_state().capabilities();
3215 out.push((
3216 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
3217 caps,
3218 NodeCapabilities::empty(),
3219 ));
3220 let mut delegate_index = 0usize;
3221 node.for_each_delegate(&mut |child| {
3222 if path_len < MAX_DELEGATE_DEPTH {
3223 path_buf[path_len] = delegate_index;
3224 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
3225 }
3226 delegate_index += 1;
3227 });
3228 }
3229}
3230
3231impl<'a> ModifierChainNodeRef<'a> {
3232 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
3233 match &self.link {
3234 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
3235 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
3236 NodeLink::Entry(path) => {
3237 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3238 if path.delegates().is_empty() {
3239 f(node_borrow.node_state())
3240 } else {
3241 let mut current: &dyn ModifierNode = &**node_borrow;
3242 for &delegate_index in path.delegates() {
3243 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3244 current = delegate;
3245 } else {
3246 return f(node_borrow.node_state());
3247 }
3248 }
3249 f(current.node_state())
3250 }
3251 }
3252 }
3253 }
3254
3255 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
3258 match &self.link {
3259 NodeLink::Head => None,
3260 NodeLink::Tail => None,
3261 NodeLink::Entry(path) => {
3262 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3263 if path.delegates().is_empty() {
3264 Some(f(&**node_borrow))
3265 } else {
3266 let mut current: &dyn ModifierNode = &**node_borrow;
3267 for &delegate_index in path.delegates() {
3268 current = nth_delegate(current, delegate_index as usize)?;
3269 }
3270 Some(f(current))
3271 }
3272 }
3273 }
3274 }
3275
3276 #[inline]
3278 pub fn parent(&self) -> Option<Self> {
3279 self.with_state(NodeState::parent_link)
3280 .map(|link| self.chain.make_node_ref(link))
3281 }
3282
3283 #[inline]
3285 pub fn child(&self) -> Option<Self> {
3286 self.with_state(NodeState::child_link)
3287 .map(|link| self.chain.make_node_ref(link))
3288 }
3289
3290 #[inline]
3292 pub fn kind_set(&self) -> NodeCapabilities {
3293 if let Some(caps) = self.cached_capabilities {
3294 return caps;
3295 }
3296 match &self.link {
3297 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
3298 NodeLink::Entry(_) => self.with_state(NodeState::capabilities),
3299 }
3300 }
3301
3302 pub fn entry_index(&self) -> Option<usize> {
3304 match &self.link {
3305 NodeLink::Entry(path) => Some(path.entry()),
3306 _ => None,
3307 }
3308 }
3309
3310 pub fn delegate_depth(&self) -> usize {
3312 match &self.link {
3313 NodeLink::Entry(path) => path.delegates().len(),
3314 _ => 0,
3315 }
3316 }
3317
3318 #[inline]
3320 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
3321 if let Some(agg) = self.cached_aggregate_child {
3322 return agg;
3323 }
3324 if self.is_tail() {
3325 NodeCapabilities::empty()
3326 } else {
3327 self.with_state(NodeState::aggregate_child_capabilities)
3328 }
3329 }
3330
3331 pub fn is_head(&self) -> bool {
3333 matches!(self.link, NodeLink::Head)
3334 }
3335
3336 pub fn is_tail(&self) -> bool {
3338 matches!(self.link, NodeLink::Tail)
3339 }
3340
3341 pub fn is_sentinel(&self) -> bool {
3343 matches!(self.link, NodeLink::Head | NodeLink::Tail)
3344 }
3345
3346 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
3348 !mask.is_empty() && self.kind_set().intersects(mask)
3349 }
3350
3351 pub fn visit_descendants<F>(self, include_self: bool, mut f: F)
3353 where
3354 F: FnMut(ModifierChainNodeRef<'a>),
3355 {
3356 let mut current = if include_self {
3357 Some(self)
3358 } else {
3359 self.child()
3360 };
3361 while let Some(node) = current {
3362 if node.is_tail() {
3363 break;
3364 }
3365 if !node.is_sentinel() {
3366 f(node.clone());
3367 }
3368 current = node.child();
3369 }
3370 }
3371
3372 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3374 where
3375 F: FnMut(ModifierChainNodeRef<'a>),
3376 {
3377 if mask.is_empty() {
3378 self.visit_descendants(include_self, f);
3379 return;
3380 }
3381
3382 if !self.aggregate_child_capabilities().intersects(mask) {
3383 return;
3384 }
3385
3386 self.visit_descendants(include_self, |node| {
3387 if node.kind_set().intersects(mask) {
3388 f(node);
3389 }
3390 });
3391 }
3392
3393 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
3395 where
3396 F: FnMut(ModifierChainNodeRef<'a>),
3397 {
3398 let mut current = if include_self {
3399 Some(self)
3400 } else {
3401 self.parent()
3402 };
3403 while let Some(node) = current {
3404 if node.is_head() {
3405 break;
3406 }
3407 f(node.clone());
3408 current = node.parent();
3409 }
3410 }
3411
3412 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3414 where
3415 F: FnMut(ModifierChainNodeRef<'a>),
3416 {
3417 if mask.is_empty() {
3418 self.visit_ancestors(include_self, f);
3419 return;
3420 }
3421
3422 self.visit_ancestors(include_self, |node| {
3423 if node.kind_set().intersects(mask) {
3424 f(node);
3425 }
3426 });
3427 }
3428}
3429
3430#[cfg(test)]
3431#[path = "tests/modifier_tests.rs"]
3432mod tests;