1use std::{
9 any::{Any, TypeId, type_name},
10 cell::{Cell, RefCell},
11 fmt,
12 hash::{Hash, Hasher},
13 ops::{BitOr, BitOrAssign},
14 rc::Rc,
15};
16
17use cranpose_core::{ProvidedValue, collections::map::HashMap, hash::default};
18pub use cranpose_ui_graphics::{DrawScope, Size};
19pub use cranpose_ui_layout::{Constraints, Measurable};
20
21use crate::nodes::input::types::PointerEvent;
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
26pub enum InvalidationKind {
27 Layout,
28 Draw,
29 PointerInput,
30 Semantics,
31 Focus,
32}
33
34pub trait ModifierNodeContext {
36 fn invalidate(&mut self, _kind: InvalidationKind) {}
38
39 fn request_update(&mut self) {}
42
43 fn node_id(&self) -> Option<cranpose_core::NodeId> {
46 None
47 }
48
49 fn push_active_capabilities(&mut self, _capabilities: NodeCapabilities) {}
51
52 fn pop_active_capabilities(&mut self) {}
54
55 fn density(&self) -> f32 {
60 1.0
61 }
62}
63
64#[derive(Default, Debug, Clone)]
73pub struct BasicModifierNodeContext {
74 invalidations: ModifierInvalidations,
75 update_requested: bool,
76 active_capabilities: Vec<NodeCapabilities>,
77 node_id: Option<cranpose_core::NodeId>,
78}
79
80impl BasicModifierNodeContext {
81 pub fn new() -> Self {
83 Self::default()
84 }
85
86 pub fn 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) -> ModifierInvalidations {
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: u32,
172 delegate_buf: [u8; MAX_DELEGATE_DEPTH],
173 delegate_len: u8,
174}
175
176impl NodePath {
177 #[inline]
178 fn root(entry: usize) -> Self {
179 debug_assert!(entry <= u32::MAX as usize, "chain entry exceeds u32 range");
180 Self {
181 entry: entry as u32,
182 delegate_buf: [0; MAX_DELEGATE_DEPTH],
183 delegate_len: 0,
184 }
185 }
186
187 #[inline]
188 fn from_slice(entry: usize, path: &[usize]) -> Self {
189 debug_assert!(
190 path.len() <= MAX_DELEGATE_DEPTH,
191 "delegate depth {} exceeds MAX_DELEGATE_DEPTH {}",
192 path.len(),
193 MAX_DELEGATE_DEPTH
194 );
195 debug_assert!(
196 path.iter().all(|&i| i <= u8::MAX as usize),
197 "delegate index exceeds u8 range"
198 );
199 let mut delegate_buf = [0u8; MAX_DELEGATE_DEPTH];
200 for (i, &v) in path.iter().enumerate().take(MAX_DELEGATE_DEPTH) {
201 delegate_buf[i] = v as u8;
202 }
203 Self {
204 delegate_buf,
205 delegate_len: path.len().min(MAX_DELEGATE_DEPTH) as u8,
206 ..Self::root(entry)
207 }
208 }
209
210 #[inline]
211 fn entry(&self) -> usize {
212 self.entry as usize
213 }
214
215 #[inline]
216 fn delegates(&self) -> &[u8] {
217 &self.delegate_buf[..self.delegate_len as usize]
218 }
219}
220
221#[derive(Copy, Clone, Debug, PartialEq, Eq)]
222pub(crate) enum NodeLink {
223 Head,
224 Tail,
225 Entry(NodePath),
226}
227
228#[derive(Debug)]
234pub struct NodeState {
235 aggregate_child_capabilities: Cell<NodeCapabilities>,
236 capabilities: Cell<NodeCapabilities>,
237 parent: Cell<Option<NodeLink>>,
238 child: Cell<Option<NodeLink>>,
239 attached: Cell<bool>,
240 is_sentinel: bool,
241}
242
243impl Default for NodeState {
244 fn default() -> Self {
245 Self::new()
246 }
247}
248
249impl NodeState {
250 pub const fn new() -> Self {
251 Self {
252 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
253 capabilities: Cell::new(NodeCapabilities::empty()),
254 parent: Cell::new(None),
255 child: Cell::new(None),
256 attached: Cell::new(false),
257 is_sentinel: false,
258 }
259 }
260
261 pub const fn sentinel() -> Self {
262 Self {
263 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
264 capabilities: Cell::new(NodeCapabilities::empty()),
265 parent: Cell::new(None),
266 child: Cell::new(None),
267 attached: Cell::new(true),
268 is_sentinel: true,
269 }
270 }
271
272 pub fn set_capabilities(&self, capabilities: NodeCapabilities) {
273 self.capabilities.set(capabilities);
274 }
275
276 #[inline]
277 pub fn capabilities(&self) -> NodeCapabilities {
278 self.capabilities.get()
279 }
280
281 pub fn set_aggregate_child_capabilities(&self, capabilities: NodeCapabilities) {
282 self.aggregate_child_capabilities.set(capabilities);
283 }
284
285 #[inline]
286 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
287 self.aggregate_child_capabilities.get()
288 }
289
290 pub(crate) fn set_parent_link(&self, parent: Option<NodeLink>) {
291 self.parent.set(parent);
292 }
293
294 #[inline]
295 pub(crate) fn parent_link(&self) -> Option<NodeLink> {
296 self.parent.get()
297 }
298
299 pub(crate) fn set_child_link(&self, child: Option<NodeLink>) {
300 self.child.set(child);
301 }
302
303 #[inline]
304 pub(crate) fn child_link(&self) -> Option<NodeLink> {
305 self.child.get()
306 }
307
308 pub fn set_attached(&self, attached: bool) {
309 self.attached.set(attached);
310 }
311
312 pub fn is_attached(&self) -> bool {
313 self.attached.get()
314 }
315
316 pub fn is_sentinel(&self) -> bool {
317 self.is_sentinel
318 }
319}
320
321pub trait DelegatableNode {
323 fn node_state(&self) -> &NodeState;
324 fn aggregate_child_capabilities(&self) -> NodeCapabilities {
325 self.node_state().aggregate_child_capabilities()
326 }
327}
328
329pub trait ModifierNode: Any + DelegatableNode {
387 fn on_attach(&mut self, _context: &mut dyn ModifierNodeContext) {}
388
389 fn on_detach(&mut self) {}
390
391 fn on_reset(&mut self) {}
392
393 fn as_draw_node(&self) -> Option<&dyn DrawModifierNode> {
395 None
396 }
397
398 fn as_draw_node_mut(&mut self) -> Option<&mut dyn DrawModifierNode> {
400 None
401 }
402
403 fn as_pointer_input_node(&self) -> Option<&dyn PointerInputNode> {
405 None
406 }
407
408 fn as_pointer_input_node_mut(&mut self) -> Option<&mut dyn PointerInputNode> {
410 None
411 }
412
413 fn as_semantics_node(&self) -> Option<&dyn SemanticsNode> {
415 None
416 }
417
418 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn SemanticsNode> {
420 None
421 }
422
423 fn as_focus_node(&self) -> Option<&dyn FocusNode> {
425 None
426 }
427
428 fn as_focus_node_mut(&mut self) -> Option<&mut dyn FocusNode> {
430 None
431 }
432
433 fn as_layout_node(&self) -> Option<&dyn LayoutModifierNode> {
435 None
436 }
437
438 fn as_layout_node_mut(&mut self) -> Option<&mut dyn LayoutModifierNode> {
440 None
441 }
442
443 fn for_each_delegate<'b>(&'b self, _visitor: &mut dyn FnMut(&'b dyn ModifierNode)) {}
445
446 fn for_each_delegate_mut<'b>(&'b mut self, _visitor: &mut dyn FnMut(&'b mut dyn ModifierNode)) {
448 }
449}
450
451pub trait LayoutModifierNode: ModifierNode {
457 fn measure(
479 &self,
480 _context: &mut dyn ModifierNodeContext,
481 measurable: &dyn Measurable,
482 constraints: Constraints,
483 ) -> cranpose_ui_layout::LayoutModifierMeasureResult {
484 let placeable = measurable.measure(constraints);
485 cranpose_ui_layout::LayoutModifierMeasureResult::with_size(Size {
486 width: placeable.width(),
487 height: placeable.height(),
488 })
489 }
490
491 fn min_intrinsic_width(
493 &self,
494 _measurable: &dyn Measurable,
495 _height: f32,
496 _density: f32,
497 ) -> f32 {
498 0.0
499 }
500
501 fn max_intrinsic_width(
503 &self,
504 _measurable: &dyn Measurable,
505 _height: f32,
506 _density: f32,
507 ) -> f32 {
508 0.0
509 }
510
511 fn min_intrinsic_height(
513 &self,
514 _measurable: &dyn Measurable,
515 _width: f32,
516 _density: f32,
517 ) -> f32 {
518 0.0
519 }
520
521 fn max_intrinsic_height(
523 &self,
524 _measurable: &dyn Measurable,
525 _width: f32,
526 _density: f32,
527 ) -> f32 {
528 0.0
529 }
530}
531
532pub trait DrawModifierNode: ModifierNode {
539 fn create_draw_closure(&self) -> Option<NodeDrawClosure> {
550 None
551 }
552
553 fn create_behind_draw_closure(&self) -> Option<NodeDrawClosure> {
558 None
559 }
560}
561
562pub type NodeDrawClosure = Rc<dyn Fn(&mut cranpose_ui_graphics::DrawScopeDefault)>;
567
568pub trait PointerInputNode: ModifierNode {
574 fn on_pointer_event(
577 &mut self,
578 _context: &mut dyn ModifierNodeContext,
579 _event: &PointerEvent,
580 ) -> bool {
581 false
582 }
583
584 fn hit_test(&self, _x: f32, _y: f32) -> bool {
587 true
588 }
589
590 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
592 None
593 }
594
595 fn layout_size_sink(&self) -> Option<Rc<Cell<Size>>> {
608 None
609 }
610}
611
612pub trait SemanticsNode: ModifierNode {
618 fn merge_semantics(&self, _config: &mut SemanticsConfiguration) {}
620
621 fn reach(&self) -> SemanticsReach {
628 SemanticsReach::merged_by(self, true)
629 }
630}
631
632#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
637pub struct SemanticsReach {
638 pub is_modal: bool,
640 pub hidden: bool,
642 pub merges_live_state: bool,
646}
647
648impl SemanticsReach {
649 pub fn merged_by(node: &(impl SemanticsNode + ?Sized), merges_live_state: bool) -> Self {
652 let mut config = SemanticsConfiguration::default();
653 node.merge_semantics(&mut config);
654 Self {
655 is_modal: config.is_modal,
656 hidden: config.hidden,
657 merges_live_state,
658 }
659 }
660
661 pub fn union(self, other: Self) -> Self {
663 Self {
664 is_modal: self.is_modal || other.is_modal,
665 hidden: self.hidden || other.hidden,
666 merges_live_state: self.merges_live_state || other.merges_live_state,
667 }
668 }
669}
670
671#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
676pub enum FocusState {
677 Active,
679 ActiveParent,
681 Captured,
685 #[default]
688 Inactive,
689}
690
691impl FocusState {
692 pub fn is_focused(self) -> bool {
694 matches!(self, FocusState::Active | FocusState::Captured)
695 }
696
697 pub fn has_focus(self) -> bool {
699 matches!(
700 self,
701 FocusState::Active | FocusState::ActiveParent | FocusState::Captured
702 )
703 }
704
705 pub fn is_captured(self) -> bool {
707 matches!(self, FocusState::Captured)
708 }
709}
710
711pub trait FocusNode: ModifierNode {
716 fn focus_state(&self) -> FocusState;
718
719 fn on_focus_changed(&mut self, _context: &mut dyn ModifierNodeContext, _state: FocusState) {}
721}
722
723#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
734pub enum SemanticsWidgetRole {
735 Button,
736 Checkbox,
737 Switch,
738 RadioButton,
739 Tab,
740 Image,
741 DropdownList,
744 ValuePicker,
747 Header,
752 Dialog,
756 Link,
759 SearchField,
762 ProgressBar,
765 ToggleButton,
768 Alert,
771 Toolbar,
774 Menu,
776 MenuItem,
778 TabBar,
781 List,
783 ListItem,
785 RadioGroup,
787}
788
789#[derive(Clone, Copy, Debug, PartialEq)]
797pub struct ProgressBarRangeInfo {
798 pub current: f32,
799 pub start: f32,
800 pub end: f32,
801 pub steps: u32,
804}
805
806impl ProgressBarRangeInfo {
807 pub fn new(current: f32, start: f32, end: f32, steps: u32) -> Self {
808 Self {
809 current,
810 start,
811 end,
812 steps,
813 }
814 }
815
816 pub fn fraction(&self) -> f32 {
818 let span = self.end - self.start;
819 if span.abs() < f32::EPSILON {
820 return 0.0;
821 }
822 ((self.current - self.start) / span).clamp(0.0, 1.0)
823 }
824
825 pub fn step(&self) -> f32 {
828 let span = self.end - self.start;
829 if self.steps == 0 {
830 span / 10.0
831 } else {
832 span / (self.steps as f32 + 1.0)
833 }
834 }
835}
836
837#[derive(Clone, Copy, Debug, PartialEq, Eq)]
842pub struct CollectionInfo {
843 pub rows: usize,
844 pub columns: usize,
845}
846
847#[derive(Clone, Copy, Debug, PartialEq)]
858pub struct ScrollAxisRange {
859 pub value: f32,
860 pub max_value: f32,
861 pub reverse: bool,
862 pub content_padding_start: f32,
863 pub content_padding_end: f32,
864}
865
866impl ScrollAxisRange {
867 pub fn new(value: f32, max_value: f32, reverse: bool) -> Self {
868 Self {
869 value,
870 max_value,
871 reverse,
872 content_padding_start: 0.0,
873 content_padding_end: 0.0,
874 }
875 }
876
877 pub fn with_content_padding(self, start: f32, end: f32) -> Self {
880 Self {
881 content_padding_start: start,
882 content_padding_end: end,
883 ..self
884 }
885 }
886
887 pub fn can_scroll_forward(&self) -> bool {
888 self.value < self.max_value
889 }
890
891 pub fn can_scroll_backward(&self) -> bool {
892 self.value > 0.0
893 }
894}
895
896#[derive(Clone)]
902pub struct SemanticsScrollBy {
903 handler: Rc<dyn Fn(f32, f32) -> bool>,
904}
905
906impl SemanticsScrollBy {
907 pub fn new(handler: impl Fn(f32, f32) -> bool + 'static) -> Self {
908 Self {
909 handler: Rc::new(handler),
910 }
911 }
912
913 pub fn invoke(&self, dx: f32, dy: f32) -> bool {
914 (self.handler)(dx, dy)
915 }
916}
917
918impl fmt::Debug for SemanticsScrollBy {
919 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
920 f.debug_struct("SemanticsScrollBy").finish_non_exhaustive()
921 }
922}
923
924impl PartialEq for SemanticsScrollBy {
925 fn eq(&self, _other: &Self) -> bool {
926 true
927 }
928}
929
930impl Eq for SemanticsScrollBy {}
931
932#[derive(Clone)]
938pub struct SemanticsScrollToIndex {
939 handler: Rc<dyn Fn(usize) -> bool>,
940}
941
942impl SemanticsScrollToIndex {
943 pub fn new(handler: impl Fn(usize) -> bool + 'static) -> Self {
944 Self {
945 handler: Rc::new(handler),
946 }
947 }
948
949 pub fn invoke(&self, index: usize) -> bool {
950 (self.handler)(index)
951 }
952}
953
954impl fmt::Debug for SemanticsScrollToIndex {
955 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
956 f.debug_struct("SemanticsScrollToIndex")
957 .finish_non_exhaustive()
958 }
959}
960
961impl PartialEq for SemanticsScrollToIndex {
962 fn eq(&self, _other: &Self) -> bool {
963 true
964 }
965}
966
967impl Eq for SemanticsScrollToIndex {}
968
969#[derive(Clone)]
975pub struct SemanticsSetProgress {
976 handler: Rc<dyn Fn(f32) -> bool>,
977}
978
979impl SemanticsSetProgress {
980 pub fn new(handler: impl Fn(f32) -> bool + 'static) -> Self {
981 Self {
982 handler: Rc::new(handler),
983 }
984 }
985
986 pub fn invoke(&self, value: f32) -> bool {
987 (self.handler)(value)
988 }
989}
990
991impl fmt::Debug for SemanticsSetProgress {
992 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
993 f.debug_struct("SemanticsSetProgress")
994 .finish_non_exhaustive()
995 }
996}
997
998#[derive(Clone)]
1002pub struct SemanticsSetText(Rc<dyn Fn(&str) -> bool>);
1003
1004impl SemanticsSetText {
1005 pub fn new(handler: impl Fn(&str) -> bool + 'static) -> Self {
1006 Self(Rc::new(handler))
1007 }
1008
1009 pub fn invoke(&self, text: &str) -> bool {
1010 (self.0)(text)
1011 }
1012}
1013
1014impl fmt::Debug for SemanticsSetText {
1015 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1016 f.write_str("SemanticsSetText")
1017 }
1018}
1019
1020#[derive(Clone)]
1026pub struct SemanticsSetSelection(Rc<dyn Fn(usize, usize) -> bool>);
1027
1028impl SemanticsSetSelection {
1029 pub fn new(handler: impl Fn(usize, usize) -> bool + 'static) -> Self {
1030 Self(Rc::new(handler))
1031 }
1032
1033 pub fn invoke(&self, anchor: usize, focus: usize) -> bool {
1034 (self.0)(anchor, focus)
1035 }
1036}
1037
1038impl fmt::Debug for SemanticsSetSelection {
1039 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1040 f.write_str("SemanticsSetSelection")
1041 }
1042}
1043
1044#[derive(Clone)]
1047pub struct SemanticsExpand(Rc<dyn Fn() -> bool>);
1048
1049impl SemanticsExpand {
1050 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1051 Self(Rc::new(handler))
1052 }
1053
1054 pub fn invoke(&self) -> bool {
1055 (self.0)()
1056 }
1057}
1058
1059impl fmt::Debug for SemanticsExpand {
1060 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1061 f.write_str("SemanticsExpand")
1062 }
1063}
1064
1065#[derive(Clone)]
1069pub struct SemanticsLongClick(Rc<dyn Fn() -> bool>);
1070
1071impl SemanticsLongClick {
1072 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1073 Self(Rc::new(handler))
1074 }
1075
1076 pub fn invoke(&self) -> bool {
1077 (self.0)()
1078 }
1079}
1080
1081impl fmt::Debug for SemanticsLongClick {
1082 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1083 f.write_str("SemanticsLongClick")
1084 }
1085}
1086
1087impl PartialEq for SemanticsLongClick {
1088 fn eq(&self, _other: &Self) -> bool {
1089 true
1090 }
1091}
1092
1093impl PartialEq for SemanticsExpand {
1094 fn eq(&self, _other: &Self) -> bool {
1095 true
1096 }
1097}
1098
1099#[derive(Clone)]
1103pub struct SemanticsDismiss(Rc<dyn Fn() -> bool>);
1104
1105impl SemanticsDismiss {
1106 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1107 Self(Rc::new(handler))
1108 }
1109
1110 pub fn invoke(&self) -> bool {
1111 (self.0)()
1112 }
1113}
1114
1115impl fmt::Debug for SemanticsDismiss {
1116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1117 f.write_str("SemanticsDismiss")
1118 }
1119}
1120
1121impl PartialEq for SemanticsDismiss {
1122 fn eq(&self, _other: &Self) -> bool {
1123 true
1124 }
1125}
1126
1127impl PartialEq for SemanticsSetText {
1128 fn eq(&self, _other: &Self) -> bool {
1129 true
1130 }
1131}
1132
1133impl PartialEq for SemanticsSetSelection {
1134 fn eq(&self, _other: &Self) -> bool {
1135 true
1136 }
1137}
1138
1139#[derive(Clone)]
1145pub struct SemanticsMagicTap(Rc<dyn Fn() -> bool>);
1146
1147impl SemanticsMagicTap {
1148 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1149 Self(Rc::new(handler))
1150 }
1151
1152 pub fn invoke(&self) -> bool {
1153 (self.0)()
1154 }
1155}
1156
1157impl fmt::Debug for SemanticsMagicTap {
1158 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1159 f.write_str("SemanticsMagicTap")
1160 }
1161}
1162
1163impl PartialEq for SemanticsMagicTap {
1164 fn eq(&self, _other: &Self) -> bool {
1165 true
1166 }
1167}
1168
1169impl PartialEq for SemanticsSetProgress {
1170 fn eq(&self, _other: &Self) -> bool {
1171 true
1172 }
1173}
1174
1175impl Eq for SemanticsSetProgress {}
1176
1177#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1184pub enum LiveRegionMode {
1185 Polite,
1187 Assertive,
1190}
1191
1192#[derive(Clone)]
1199pub struct SemanticsCustomAction {
1200 pub label: String,
1202 handler: Rc<dyn Fn()>,
1203}
1204
1205impl SemanticsCustomAction {
1206 pub fn new(label: impl Into<String>, handler: impl Fn() + 'static) -> Self {
1207 Self {
1208 label: label.into(),
1209 handler: Rc::new(handler),
1210 }
1211 }
1212
1213 pub fn invoke(&self) {
1214 (self.handler)();
1215 }
1216}
1217
1218impl fmt::Debug for SemanticsCustomAction {
1219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1220 f.debug_struct("SemanticsCustomAction")
1221 .field("label", &self.label)
1222 .finish_non_exhaustive()
1223 }
1224}
1225
1226impl PartialEq for SemanticsCustomAction {
1227 fn eq(&self, other: &Self) -> bool {
1228 self.label == other.label
1229 }
1230}
1231
1232impl Eq for SemanticsCustomAction {}
1233
1234#[derive(Clone, Debug, PartialEq)]
1249pub struct CanvasSemanticsNode {
1250 pub key: u64,
1257 pub bounds: cranpose_ui_graphics::Rect,
1259 pub label: String,
1260 pub role: Option<SemanticsWidgetRole>,
1261 pub state_description: Option<String>,
1265 pub on_click_label: Option<String>,
1268 pub clickable: bool,
1269 pub selected: Option<bool>,
1271 pub toggled: Option<bool>,
1273 pub enabled: bool,
1274 pub custom_actions: Vec<SemanticsCustomAction>,
1275}
1276
1277impl Default for CanvasSemanticsNode {
1278 fn default() -> Self {
1279 Self {
1280 key: 0,
1281 bounds: cranpose_ui_graphics::Rect {
1282 x: 0.0,
1283 y: 0.0,
1284 width: 0.0,
1285 height: 0.0,
1286 },
1287 label: String::new(),
1288 role: None,
1289 state_description: None,
1290 on_click_label: None,
1291 clickable: false,
1292 selected: None,
1293 toggled: None,
1294 enabled: true,
1295 custom_actions: Vec::new(),
1296 }
1297 }
1298}
1299
1300impl CanvasSemanticsNode {
1301 pub fn control(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1303 Self {
1304 key,
1305 bounds,
1306 label: label.into(),
1307 clickable: true,
1308 ..Self::default()
1309 }
1310 }
1311
1312 pub fn text(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1314 Self {
1315 key,
1316 bounds,
1317 label: label.into(),
1318 ..Self::default()
1319 }
1320 }
1321
1322 pub fn with_role(mut self, role: SemanticsWidgetRole) -> Self {
1323 self.role = Some(role);
1324 self
1325 }
1326
1327 pub fn with_state_description(mut self, state: impl Into<String>) -> Self {
1328 self.state_description = Some(state.into());
1329 self
1330 }
1331
1332 pub fn with_click_label(mut self, label: impl Into<String>) -> Self {
1333 self.on_click_label = Some(label.into());
1334 self.clickable = true;
1335 self
1336 }
1337
1338 pub fn with_selected(mut self, selected: bool) -> Self {
1339 self.selected = Some(selected);
1340 self
1341 }
1342
1343 pub fn with_toggled(mut self, toggled: bool) -> Self {
1344 self.toggled = Some(toggled);
1345 self
1346 }
1347
1348 pub fn with_enabled(mut self, enabled: bool) -> Self {
1349 self.enabled = enabled;
1350 self
1351 }
1352
1353 pub fn with_custom_action(mut self, action: SemanticsCustomAction) -> Self {
1354 self.custom_actions.push(action);
1355 self
1356 }
1357}
1358
1359#[derive(Clone, Debug, PartialEq)]
1361pub struct SemanticsConfiguration {
1362 pub content_description: Option<String>,
1363 pub state_description: Option<String>,
1365 pub on_click_label: Option<String>,
1367 pub on_click: Option<SemanticsCustomAction>,
1370 pub on_long_click: Option<SemanticsLongClick>,
1373 pub on_long_click_label: Option<String>,
1376 pub on_magic_tap: Option<SemanticsMagicTap>,
1380 pub on_magic_tap_label: Option<String>,
1383 pub input_labels: Vec<String>,
1387 pub language: Option<String>,
1391 pub role: Option<SemanticsWidgetRole>,
1393 pub selected: Option<bool>,
1394 pub toggled: Option<bool>,
1395 pub enabled: bool,
1396 pub is_clickable: bool,
1397 pub is_editable_text: bool,
1398 pub multiline: bool,
1400 pub text: Option<String>,
1403 pub text_selection: Option<crate::text::TextRange>,
1404 pub custom_actions: Vec<SemanticsCustomAction>,
1405 pub canvas_children: Vec<CanvasSemanticsNode>,
1408 pub is_modal: bool,
1411 pub hidden: bool,
1415 pub merge_descendants: bool,
1419 pub selectable_group: bool,
1423 pub pane_title: Option<String>,
1426 pub error: Option<String>,
1429 pub password: bool,
1432 pub traversal_index: f32,
1436 pub live_region: Option<LiveRegionMode>,
1439 pub progress: Option<ProgressBarRangeInfo>,
1442 pub set_progress: Option<SemanticsSetProgress>,
1445 pub set_text: Option<SemanticsSetText>,
1448 pub set_selection: Option<SemanticsSetSelection>,
1451 pub expand: Option<SemanticsExpand>,
1454 pub dismiss: Option<SemanticsDismiss>,
1458 pub collapse: Option<SemanticsExpand>,
1461 pub vertical_scroll: Option<ScrollAxisRange>,
1464 pub horizontal_scroll: Option<ScrollAxisRange>,
1467 pub scroll_by: Option<SemanticsScrollBy>,
1470 pub scroll_to_index: Option<SemanticsScrollToIndex>,
1474 pub collection: Option<CollectionInfo>,
1476}
1477
1478impl Default for SemanticsConfiguration {
1479 fn default() -> Self {
1480 Self {
1481 content_description: None,
1482 state_description: None,
1483 on_click_label: None,
1484 on_click: None,
1485 on_long_click: None,
1486 on_long_click_label: None,
1487 on_magic_tap: None,
1488 on_magic_tap_label: None,
1489 input_labels: Vec::new(),
1490 language: None,
1491 role: None,
1492 selected: None,
1493 toggled: None,
1494 enabled: true,
1495 is_clickable: false,
1496 is_editable_text: false,
1497 multiline: false,
1498 text: None,
1499 text_selection: None,
1500 custom_actions: Vec::new(),
1501 canvas_children: Vec::new(),
1502 is_modal: false,
1503 hidden: false,
1504 merge_descendants: false,
1505 selectable_group: false,
1506 pane_title: None,
1507 error: None,
1508 password: false,
1509 traversal_index: 0.0,
1510 live_region: None,
1511 progress: None,
1512 set_progress: None,
1513 set_text: None,
1514 set_selection: None,
1515 expand: None,
1516 dismiss: None,
1517 collapse: None,
1518 vertical_scroll: None,
1519 horizontal_scroll: None,
1520 scroll_by: None,
1521 scroll_to_index: None,
1522 collection: None,
1523 }
1524 }
1525}
1526
1527pub type SemanticsSpec = SemanticsConfiguration;
1536
1537impl SemanticsConfiguration {
1538 pub fn new() -> Self {
1541 Self::default()
1542 }
1543
1544 pub fn content_description(mut self, name: impl Into<String>) -> Self {
1547 self.content_description = Some(name.into());
1548 self
1549 }
1550
1551 pub fn state_description(mut self, state: impl Into<String>) -> Self {
1554 self.state_description = Some(state.into());
1555 self
1556 }
1557
1558 pub fn clickable(mut self) -> Self {
1560 self.is_clickable = true;
1561 self
1562 }
1563
1564 pub fn on_click(mut self, label: impl Into<String>, action: impl Fn() + 'static) -> Self {
1567 self.on_click = Some(SemanticsCustomAction::new(label, action));
1568 self
1569 }
1570
1571 pub fn on_long_click(
1575 mut self,
1576 label: impl Into<String>,
1577 action: impl Fn() -> bool + 'static,
1578 ) -> Self {
1579 self.on_long_click_label = Some(label.into());
1580 self.on_long_click = Some(SemanticsLongClick::new(action));
1581 self
1582 }
1583
1584 pub fn on_magic_tap(
1588 mut self,
1589 label: impl Into<String>,
1590 action: impl Fn() -> bool + 'static,
1591 ) -> Self {
1592 self.on_magic_tap_label = Some(label.into());
1593 self.on_magic_tap = Some(SemanticsMagicTap::new(action));
1594 self
1595 }
1596
1597 pub fn input_labels<S: Into<String>>(mut self, labels: impl IntoIterator<Item = S>) -> Self {
1600 self.input_labels = labels.into_iter().map(Into::into).collect();
1601 self
1602 }
1603
1604 pub fn language(mut self, tag: impl Into<String>) -> Self {
1607 self.language = Some(tag.into());
1608 self
1609 }
1610
1611 pub fn toggled(mut self, toggled: bool) -> Self {
1613 self.toggled = Some(toggled);
1614 self
1615 }
1616
1617 pub fn selected(mut self, selected: bool) -> Self {
1620 self.selected = Some(selected);
1621 self
1622 }
1623
1624 pub fn role(mut self, role: SemanticsWidgetRole) -> Self {
1626 self.role = Some(role);
1627 self
1628 }
1629
1630 pub fn heading(self) -> Self {
1633 self.role(SemanticsWidgetRole::Header)
1634 }
1635
1636 pub fn error(mut self, message: impl Into<String>) -> Self {
1638 self.error = Some(message.into());
1639 self
1640 }
1641
1642 pub fn password(mut self) -> Self {
1644 self.password = true;
1645 self
1646 }
1647
1648 pub fn pane_title(mut self, title: impl Into<String>) -> Self {
1651 self.pane_title = Some(title.into());
1652 self
1653 }
1654
1655 pub fn traversal_index(mut self, index: f32) -> Self {
1658 self.traversal_index = index;
1659 self
1660 }
1661
1662 pub fn hidden(mut self) -> Self {
1665 self.hidden = true;
1666 self
1667 }
1668
1669 pub fn merge_descendants(mut self) -> Self {
1672 self.merge_descendants = true;
1673 self
1674 }
1675
1676 pub fn selectable_group(mut self) -> Self {
1679 self.selectable_group = true;
1680 self
1681 }
1682
1683 pub fn live_region(mut self, mode: LiveRegionMode) -> Self {
1686 self.live_region = Some(mode);
1687 self
1688 }
1689 pub fn merge(&mut self, other: &SemanticsConfiguration) {
1690 if let Some(description) = &other.content_description {
1691 self.content_description = Some(description.clone());
1692 }
1693 if let Some(state) = &other.state_description {
1694 self.state_description = Some(state.clone());
1695 }
1696 if let Some(label) = &other.on_click_label {
1697 self.on_click_label = Some(label.clone());
1698 }
1699 if let Some(label) = &other.on_long_click_label {
1700 self.on_long_click_label = Some(label.clone());
1701 }
1702 if let Some(label) = &other.on_magic_tap_label {
1703 self.on_magic_tap_label = Some(label.clone());
1704 }
1705 if !other.input_labels.is_empty() {
1706 self.input_labels.clone_from(&other.input_labels);
1707 }
1708 if let Some(language) = &other.language {
1709 self.language = Some(language.clone());
1710 }
1711 if let Some(role) = other.role {
1712 self.role = Some(role);
1713 }
1714 if let Some(selected) = other.selected {
1715 self.selected = Some(selected);
1716 }
1717 if let Some(toggled) = other.toggled {
1718 self.toggled = Some(toggled);
1719 }
1720 self.enabled &= other.enabled;
1721 self.is_clickable |= other.is_clickable;
1722 self.is_editable_text |= other.is_editable_text;
1723 self.multiline |= other.multiline;
1724 if let Some(text) = &other.text {
1725 self.text = Some(text.clone());
1726 }
1727 self.is_modal |= other.is_modal;
1728 self.hidden |= other.hidden;
1729 self.merge_descendants |= other.merge_descendants;
1730 self.selectable_group |= other.selectable_group;
1731 self.password |= other.password;
1732 if other.traversal_index != 0.0 {
1733 self.traversal_index = other.traversal_index;
1734 }
1735 if let Some(live_region) = other.live_region {
1736 self.live_region = Some(live_region);
1737 }
1738 self.merge_words(other);
1739 self.merge_actions(other);
1740 self.merge_ranges(other);
1741 }
1742
1743 fn merge_words(&mut self, other: &SemanticsConfiguration) {
1744 if let Some(title) = &other.pane_title {
1745 self.pane_title = Some(title.clone());
1746 }
1747 if let Some(error) = &other.error {
1748 self.error = Some(error.clone());
1749 }
1750 }
1751
1752 fn merge_actions(&mut self, other: &SemanticsConfiguration) {
1753 if let Some(on_click) = &other.on_click {
1754 self.on_click = Some(on_click.clone());
1755 }
1756 self.custom_actions
1757 .extend(other.custom_actions.iter().cloned());
1758 self.canvas_children
1759 .extend(other.canvas_children.iter().cloned());
1760 if let Some(set_progress) = &other.set_progress {
1761 self.set_progress = Some(set_progress.clone());
1762 }
1763 if let Some(set_text) = &other.set_text {
1764 self.set_text = Some(set_text.clone());
1765 }
1766 if let Some(set_selection) = &other.set_selection {
1767 self.set_selection = Some(set_selection.clone());
1768 }
1769 if let Some(expand) = &other.expand {
1770 self.expand = Some(expand.clone());
1771 }
1772 if let Some(collapse) = &other.collapse {
1773 self.collapse = Some(collapse.clone());
1774 }
1775 if let Some(dismiss) = &other.dismiss {
1776 self.dismiss = Some(dismiss.clone());
1777 }
1778 if let Some(long_click) = &other.on_long_click {
1779 self.on_long_click = Some(long_click.clone());
1780 }
1781 if let Some(magic_tap) = &other.on_magic_tap {
1782 self.on_magic_tap = Some(magic_tap.clone());
1783 }
1784 if let Some(scroll_by) = &other.scroll_by {
1785 self.scroll_by = Some(scroll_by.clone());
1786 }
1787 if let Some(scroll_to_index) = &other.scroll_to_index {
1788 self.scroll_to_index = Some(scroll_to_index.clone());
1789 }
1790 }
1791
1792 fn merge_ranges(&mut self, other: &SemanticsConfiguration) {
1793 if let Some(selection) = other.text_selection {
1794 self.text_selection = Some(selection);
1795 }
1796 if let Some(progress) = other.progress {
1797 self.progress = Some(progress);
1798 }
1799 if let Some(range) = other.vertical_scroll {
1800 self.vertical_scroll = Some(range);
1801 }
1802 if let Some(range) = other.horizontal_scroll {
1803 self.horizontal_scroll = Some(range);
1804 }
1805 if let Some(collection) = other.collection {
1806 self.collection = Some(collection);
1807 }
1808 }
1809
1810 pub fn is_activatable(&self) -> bool {
1813 self.is_clickable || self.on_click_label.is_some() || self.on_click.is_some()
1814 }
1815}
1816
1817impl fmt::Debug for dyn ModifierNode {
1818 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1819 f.debug_struct("ModifierNode").finish_non_exhaustive()
1820 }
1821}
1822
1823impl dyn ModifierNode {
1824 pub fn as_any(&self) -> &dyn Any {
1825 self
1826 }
1827
1828 pub fn as_any_mut(&mut self) -> &mut dyn Any {
1829 self
1830 }
1831}
1832
1833pub trait ModifierNodeElement: fmt::Debug + Hash + PartialEq + 'static {
1836 type Node: ModifierNode;
1837
1838 fn create(&self) -> Self::Node;
1840
1841 fn update(&self, node: &mut Self::Node);
1843
1844 fn key(&self) -> Option<u64> {
1846 None
1847 }
1848
1849 fn inspector_name(&self) -> &'static str {
1851 type_name::<Self>()
1852 }
1853
1854 fn inspector_properties(&self, _inspector: &mut dyn FnMut(&'static str, String)) {}
1856
1857 fn capabilities(&self) -> NodeCapabilities {
1860 NodeCapabilities::default()
1861 }
1862
1863 fn always_update(&self) -> bool {
1869 false
1870 }
1871
1872 fn auto_invalidate_on_update(&self) -> bool {
1875 true
1876 }
1877
1878 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
1885 None
1886 }
1887
1888 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
1895 Vec::new()
1896 }
1897}
1898
1899#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1901pub struct NodeCapabilities(u32);
1902
1903impl NodeCapabilities {
1904 pub const NONE: Self = Self(0);
1906 pub const LAYOUT: Self = Self(1 << 0);
1908 pub const DRAW: Self = Self(1 << 1);
1910 pub const POINTER_INPUT: Self = Self(1 << 2);
1912 pub const SEMANTICS: Self = Self(1 << 3);
1914 pub const MODIFIER_LOCALS: Self = Self(1 << 4);
1916 pub const FOCUS: Self = Self(1 << 5);
1918 pub const WINDOW_ROOT: Self = Self(1 << 6);
1922 pub const KEY_INPUT: Self = Self(1 << 7);
1924
1925 pub const fn empty() -> Self {
1927 Self::NONE
1928 }
1929
1930 pub const fn contains(self, other: Self) -> bool {
1932 (self.0 & other.0) == other.0
1933 }
1934
1935 pub const fn intersects(self, other: Self) -> bool {
1937 (self.0 & other.0) != 0
1938 }
1939
1940 pub fn insert(&mut self, other: Self) {
1942 self.0 |= other.0;
1943 }
1944
1945 pub const fn bits(self) -> u32 {
1947 self.0
1948 }
1949
1950 pub const fn is_empty(self) -> bool {
1952 self.0 == 0
1953 }
1954
1955 pub const fn for_invalidation(kind: InvalidationKind) -> Self {
1957 match kind {
1958 InvalidationKind::Layout => Self::LAYOUT,
1959 InvalidationKind::Draw => Self::DRAW,
1960 InvalidationKind::PointerInput => Self::POINTER_INPUT,
1961 InvalidationKind::Semantics => Self::SEMANTICS,
1962 InvalidationKind::Focus => Self::FOCUS,
1963 }
1964 }
1965}
1966
1967impl Default for NodeCapabilities {
1968 fn default() -> Self {
1969 Self::NONE
1970 }
1971}
1972
1973impl fmt::Debug for NodeCapabilities {
1974 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1975 f.debug_struct("NodeCapabilities")
1976 .field("layout", &self.contains(Self::LAYOUT))
1977 .field("draw", &self.contains(Self::DRAW))
1978 .field("pointer_input", &self.contains(Self::POINTER_INPUT))
1979 .field("semantics", &self.contains(Self::SEMANTICS))
1980 .field("modifier_locals", &self.contains(Self::MODIFIER_LOCALS))
1981 .field("focus", &self.contains(Self::FOCUS))
1982 .field("window_root", &self.contains(Self::WINDOW_ROOT))
1983 .field("key_input", &self.contains(Self::KEY_INPUT))
1984 .finish()
1985 }
1986}
1987
1988impl BitOr for NodeCapabilities {
1989 type Output = Self;
1990
1991 fn bitor(self, rhs: Self) -> Self::Output {
1992 Self(self.0 | rhs.0)
1993 }
1994}
1995
1996impl BitOrAssign for NodeCapabilities {
1997 fn bitor_assign(&mut self, rhs: Self) {
1998 self.0 |= rhs.0;
1999 }
2000}
2001
2002pub type ModifierInvalidations = smallvec::SmallVec<[ModifierInvalidation; 5]>;
2005
2006#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2008pub struct ModifierInvalidation {
2009 kind: InvalidationKind,
2010 capabilities: NodeCapabilities,
2011}
2012
2013impl ModifierInvalidation {
2014 pub const fn new(kind: InvalidationKind, capabilities: NodeCapabilities) -> Self {
2016 Self { kind, capabilities }
2017 }
2018
2019 pub const fn kind(self) -> InvalidationKind {
2021 self.kind
2022 }
2023
2024 pub const fn capabilities(self) -> NodeCapabilities {
2026 self.capabilities
2027 }
2028}
2029
2030pub trait AnyModifierElement: fmt::Debug {
2032 fn node_type(&self) -> TypeId;
2033
2034 fn element_type(&self) -> TypeId;
2035
2036 fn create_node(&self) -> Rc<RefCell<dyn ModifierNode>>;
2038
2039 fn can_update_node(&self, node: &dyn ModifierNode) -> bool;
2040
2041 fn update_node(&self, node: &mut dyn ModifierNode);
2042
2043 fn key(&self) -> Option<u64>;
2044
2045 fn capabilities(&self) -> NodeCapabilities {
2046 NodeCapabilities::default()
2047 }
2048
2049 fn hash_code(&self) -> u64;
2050
2051 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool;
2052
2053 fn inspector_name(&self) -> &'static str;
2054
2055 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String));
2056
2057 fn requires_update(&self) -> bool;
2058
2059 fn auto_invalidates_on_update(&self) -> bool;
2060
2061 fn update_invalidation_kind(&self) -> Option<InvalidationKind>;
2062
2063 fn provides_composition_locals(&self) -> bool {
2065 false
2066 }
2067
2068 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2070 Vec::new()
2071 }
2072
2073 fn as_any(&self) -> &dyn Any;
2074}
2075
2076struct TypedModifierElement<E: ModifierNodeElement> {
2077 element: E,
2078 cached_hash: u64,
2079 provides_locals: bool,
2080}
2081
2082impl<E: ModifierNodeElement> TypedModifierElement<E> {
2083 fn new(element: E) -> Self {
2084 let mut hasher = default::new();
2085 element.hash(&mut hasher);
2086 let provides_locals = !element.provided_composition_locals().is_empty();
2087 Self {
2088 element,
2089 cached_hash: hasher.finish(),
2090 provides_locals,
2091 }
2092 }
2093}
2094
2095impl<E> fmt::Debug for TypedModifierElement<E>
2096where
2097 E: ModifierNodeElement,
2098{
2099 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2100 f.debug_struct("TypedModifierElement")
2101 .field("type", &type_name::<E>())
2102 .finish()
2103 }
2104}
2105
2106impl<E> AnyModifierElement for TypedModifierElement<E>
2107where
2108 E: ModifierNodeElement,
2109{
2110 fn node_type(&self) -> TypeId {
2111 TypeId::of::<E::Node>()
2112 }
2113
2114 fn element_type(&self) -> TypeId {
2115 TypeId::of::<E>()
2116 }
2117
2118 fn create_node(&self) -> Rc<RefCell<dyn ModifierNode>> {
2119 Rc::new(RefCell::new(self.element.create()))
2120 }
2121
2122 fn can_update_node(&self, node: &dyn ModifierNode) -> bool {
2123 node.as_any().is::<E::Node>()
2124 }
2125
2126 fn update_node(&self, node: &mut dyn ModifierNode) {
2127 if let Some(typed) = node.as_any_mut().downcast_mut::<E::Node>() {
2128 self.element.update(typed);
2129 }
2130 }
2131
2132 fn key(&self) -> Option<u64> {
2133 self.element.key()
2134 }
2135
2136 fn capabilities(&self) -> NodeCapabilities {
2137 self.element.capabilities()
2138 }
2139
2140 fn provides_composition_locals(&self) -> bool {
2141 self.provides_locals
2142 }
2143
2144 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2145 self.element.provided_composition_locals()
2146 }
2147
2148 fn hash_code(&self) -> u64 {
2149 self.cached_hash
2150 }
2151
2152 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool {
2153 other
2154 .as_any()
2155 .downcast_ref::<Self>()
2156 .is_some_and(|typed| typed.element == self.element)
2157 }
2158
2159 fn inspector_name(&self) -> &'static str {
2160 self.element.inspector_name()
2161 }
2162
2163 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String)) {
2164 self.element.inspector_properties(visitor);
2165 }
2166
2167 fn requires_update(&self) -> bool {
2168 self.element.always_update()
2169 }
2170
2171 fn auto_invalidates_on_update(&self) -> bool {
2172 self.element.auto_invalidate_on_update()
2173 }
2174
2175 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
2176 self.element.update_invalidation_kind()
2177 }
2178
2179 fn as_any(&self) -> &dyn Any {
2180 self
2181 }
2182}
2183
2184fn request_update_auto_invalidations(
2185 element: &dyn AnyModifierElement,
2186 context: &mut dyn ModifierNodeContext,
2187 capabilities: NodeCapabilities,
2188) {
2189 if let Some(kind) = element.update_invalidation_kind() {
2190 let capabilities = NodeCapabilities::for_invalidation(kind);
2191 context.push_active_capabilities(capabilities);
2192 context.invalidate(kind);
2193 context.pop_active_capabilities();
2194 } else if element.auto_invalidates_on_update() {
2195 request_auto_invalidations(context, capabilities);
2196 }
2197}
2198
2199pub fn modifier_element<E: ModifierNodeElement>(element: E) -> DynModifierElement {
2202 Rc::new(TypedModifierElement::new(element))
2203}
2204
2205pub type DynModifierElement = Rc<dyn AnyModifierElement>;
2207
2208#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2209enum TraversalDirection {
2210 Forward,
2211 Backward,
2212}
2213
2214pub struct ModifierChainIter<'a> {
2219 chain: &'a ModifierNodeChain,
2220 cursor: usize,
2221 remaining: usize,
2222 direction: TraversalDirection,
2223}
2224
2225impl<'a> ModifierChainIter<'a> {
2226 fn forward(chain: &'a ModifierNodeChain) -> Self {
2227 Self {
2228 chain,
2229 cursor: 0,
2230 remaining: chain.ordered_nodes.len(),
2231 direction: TraversalDirection::Forward,
2232 }
2233 }
2234
2235 fn backward(chain: &'a ModifierNodeChain) -> Self {
2236 let len = chain.ordered_nodes.len();
2237 Self {
2238 chain,
2239 cursor: len.wrapping_sub(1),
2240 remaining: len,
2241 direction: TraversalDirection::Backward,
2242 }
2243 }
2244}
2245
2246impl<'a> Iterator for ModifierChainIter<'a> {
2247 type Item = ModifierChainNodeRef<'a>;
2248
2249 #[inline]
2250 fn next(&mut self) -> Option<Self::Item> {
2251 if self.remaining == 0 {
2252 return None;
2253 }
2254 let (link, caps, agg) = self.chain.ordered_nodes[self.cursor];
2255 let node_ref = self.chain.make_node_ref_with_caps(link, caps, agg);
2256 self.remaining -= 1;
2257 match self.direction {
2258 TraversalDirection::Forward => self.cursor += 1,
2259 TraversalDirection::Backward => self.cursor = self.cursor.wrapping_sub(1),
2260 }
2261 Some(node_ref)
2262 }
2263
2264 #[inline]
2265 fn size_hint(&self) -> (usize, Option<usize>) {
2266 (self.remaining, Some(self.remaining))
2267 }
2268}
2269
2270impl ExactSizeIterator for ModifierChainIter<'_> {}
2271impl std::iter::FusedIterator for ModifierChainIter<'_> {}
2272
2273#[derive(Debug)]
2274struct ModifierNodeEntry {
2275 key: Option<u64>,
2276 hash_code: u64,
2277 element: DynModifierElement,
2278 node: Rc<RefCell<dyn ModifierNode>>,
2279 capabilities: NodeCapabilities,
2280}
2281
2282impl ModifierNodeEntry {
2283 fn new(
2284 key: Option<u64>,
2285 element: DynModifierElement,
2286 node: Rc<RefCell<dyn ModifierNode>>,
2287 hash_code: u64,
2288 capabilities: NodeCapabilities,
2289 ) -> Self {
2290 let entry = Self {
2291 key,
2292 hash_code,
2293 element,
2294 node,
2295 capabilities,
2296 };
2297 entry
2298 .node
2299 .borrow()
2300 .node_state()
2301 .set_capabilities(entry.capabilities);
2302 entry
2303 }
2304}
2305
2306fn visit_node_tree_mut(
2307 node: &mut dyn ModifierNode,
2308 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
2309) {
2310 visitor(node);
2311 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
2312}
2313
2314fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
2315 let mut current = 0usize;
2316 let mut result: Option<&dyn ModifierNode> = None;
2317 node.for_each_delegate(&mut |child| {
2318 if result.is_none() && current == target {
2319 result = Some(child);
2320 }
2321 current += 1;
2322 });
2323 result
2324}
2325
2326fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
2327 let mut current = 0usize;
2328 let mut result: Option<&mut dyn ModifierNode> = None;
2329 node.for_each_delegate_mut(&mut |child| {
2330 if result.is_none() && current == target {
2331 result = Some(child);
2332 }
2333 current += 1;
2334 });
2335 result
2336}
2337
2338fn with_node_context<F, R>(
2339 node: &mut dyn ModifierNode,
2340 context: &mut dyn ModifierNodeContext,
2341 f: F,
2342) -> R
2343where
2344 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
2345{
2346 context.push_active_capabilities(node.node_state().capabilities());
2347 let result = f(node, context);
2348 context.pop_active_capabilities();
2349 result
2350}
2351
2352fn request_auto_invalidations(
2353 context: &mut dyn ModifierNodeContext,
2354 capabilities: NodeCapabilities,
2355) {
2356 if capabilities.is_empty() {
2357 return;
2358 }
2359
2360 context.push_active_capabilities(capabilities);
2361
2362 if capabilities.contains(NodeCapabilities::LAYOUT) {
2363 context.invalidate(InvalidationKind::Layout);
2364 }
2365 if capabilities.contains(NodeCapabilities::DRAW) {
2366 context.invalidate(InvalidationKind::Draw);
2367 }
2368 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
2369 context.invalidate(InvalidationKind::PointerInput);
2370 }
2371 if capabilities.contains(NodeCapabilities::SEMANTICS) {
2372 context.invalidate(InvalidationKind::Semantics);
2373 }
2374 if capabilities.contains(NodeCapabilities::FOCUS) {
2375 context.invalidate(InvalidationKind::Focus);
2376 }
2377
2378 context.pop_active_capabilities();
2379}
2380
2381fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
2382 visit_node_tree_mut(node, &mut |n| {
2383 if !n.node_state().is_attached() {
2384 n.node_state().set_attached(true);
2385 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
2386 }
2387 });
2388}
2389
2390fn reset_node_tree(node: &mut dyn ModifierNode) {
2391 visit_node_tree_mut(node, &mut |n| n.on_reset());
2392}
2393
2394fn detach_node_tree(node: &mut dyn ModifierNode) {
2395 visit_node_tree_mut(node, &mut |n| {
2396 if n.node_state().is_attached() {
2397 n.on_detach();
2398 n.node_state().set_attached(false);
2399 }
2400 n.node_state().set_parent_link(None);
2401 n.node_state().set_child_link(None);
2402 n.node_state()
2403 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2404 });
2405}
2406
2407pub struct ModifierNodeChain {
2414 entries: Vec<ModifierNodeEntry>,
2415 aggregated_capabilities: NodeCapabilities,
2416 head_aggregate_child_capabilities: NodeCapabilities,
2417 head_sentinel: SentinelNode,
2418 tail_sentinel: SentinelNode,
2419 ordered_nodes: Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
2420}
2421
2422#[derive(Default)]
2426struct ReconcileScratch {
2427 old_used: Vec<bool>,
2428 match_order: Vec<Option<usize>>,
2429 final_slots: Vec<Option<ModifierNodeEntry>>,
2430 elements: Vec<DynModifierElement>,
2431}
2432
2433thread_local! {
2434 static RECONCILE_SCRATCH: std::cell::RefCell<ReconcileScratch> =
2435 std::cell::RefCell::default();
2436}
2437
2438struct SentinelNode {
2439 state: NodeState,
2440}
2441
2442impl SentinelNode {
2443 fn new() -> Self {
2444 Self {
2445 state: NodeState::sentinel(),
2446 }
2447 }
2448}
2449
2450impl DelegatableNode for SentinelNode {
2451 fn node_state(&self) -> &NodeState {
2452 &self.state
2453 }
2454}
2455
2456impl ModifierNode for SentinelNode {}
2457
2458#[derive(Clone)]
2459pub struct ModifierChainNodeRef<'a> {
2460 chain: &'a ModifierNodeChain,
2461 link: NodeLink,
2462 cached_capabilities: Option<NodeCapabilities>,
2463 cached_aggregate_child: Option<NodeCapabilities>,
2464}
2465
2466impl Default for ModifierNodeChain {
2467 fn default() -> Self {
2468 Self::new()
2469 }
2470}
2471
2472struct EntryIndex {
2473 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2474 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2475 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
2476}
2477
2478struct EntryMatchQuery<'a> {
2479 element_type: TypeId,
2480 node_type: TypeId,
2481 key: Option<u64>,
2482 hash_code: u64,
2483 element: &'a DynModifierElement,
2484}
2485
2486impl EntryIndex {
2487 fn build(entries: &[ModifierNodeEntry]) -> Self {
2488 let mut keyed = HashMap::default();
2489 let mut hashed = HashMap::default();
2490 let mut typed = HashMap::default();
2491
2492 for (i, entry) in entries.iter().enumerate() {
2493 let (element_type, node_type) =
2494 (entry.element.element_type(), entry.element.node_type());
2495 if let Some(key_value) = entry.key {
2496 keyed
2497 .entry((element_type, node_type, key_value))
2498 .or_insert_with(Vec::new)
2499 .push(i);
2500 } else {
2501 hashed
2502 .entry((element_type, node_type, entry.hash_code))
2503 .or_insert_with(Vec::new)
2504 .push(i);
2505 typed
2506 .entry((element_type, node_type))
2507 .or_insert_with(Vec::new)
2508 .push(i);
2509 }
2510 }
2511
2512 Self {
2513 keyed,
2514 hashed,
2515 typed,
2516 }
2517 }
2518
2519 fn find_match(
2520 &self,
2521 entries: &[ModifierNodeEntry],
2522 used: &[bool],
2523 query: EntryMatchQuery<'_>,
2524 ) -> Option<usize> {
2525 if let Some(key_value) = query.key {
2526 if let Some(candidates) =
2527 self.keyed
2528 .get(&(query.element_type, query.node_type, key_value))
2529 {
2530 for &i in candidates {
2531 if !used[i] {
2532 return Some(i);
2533 }
2534 }
2535 }
2536 } else {
2537 if let Some(candidates) =
2538 self.hashed
2539 .get(&(query.element_type, query.node_type, query.hash_code))
2540 {
2541 for &i in candidates {
2542 if !used[i]
2543 && entries[i]
2544 .element
2545 .as_ref()
2546 .equals_element(query.element.as_ref())
2547 {
2548 return Some(i);
2549 }
2550 }
2551 }
2552
2553 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
2554 for &i in candidates {
2555 if !used[i] {
2556 return Some(i);
2557 }
2558 }
2559 }
2560 }
2561
2562 None
2563 }
2564}
2565
2566fn update_entry_in_place(
2571 entry: &mut ModifierNodeEntry,
2572 element: &DynModifierElement,
2573 context: &mut dyn ModifierNodeContext,
2574) -> bool {
2575 if entry.element.element_type() != element.element_type()
2576 || entry.element.node_type() != element.node_type()
2577 || entry.key != element.key()
2578 || !element.can_update_node(&*entry.node.borrow())
2579 {
2580 return false;
2581 }
2582 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2583 let capabilities = element.capabilities();
2584 attach_if_detached(entry, context);
2585 if !same_element || element.requires_update() {
2586 element.update_node(&mut *entry.node.borrow_mut());
2587 entry.element = element.clone();
2588 entry.hash_code = element.hash_code();
2589 request_update_auto_invalidations(element.as_ref(), context, capabilities);
2590 }
2591 entry.capabilities = capabilities;
2592 entry
2593 .node
2594 .borrow()
2595 .node_state()
2596 .set_capabilities(capabilities);
2597 true
2598}
2599
2600fn attach_if_detached(entry: &ModifierNodeEntry, context: &mut dyn ModifierNodeContext) {
2601 let attached = entry.node.borrow().node_state().is_attached();
2602 if !attached {
2603 attach_node_tree(&mut *entry.node.borrow_mut(), context);
2604 }
2605}
2606
2607fn fresh_entry(
2609 element: DynModifierElement,
2610 context: &mut dyn ModifierNodeContext,
2611) -> ModifierNodeEntry {
2612 let capabilities = element.capabilities();
2613 let entry = ModifierNodeEntry::new(
2614 element.key(),
2615 element.clone(),
2616 element.create_node(),
2617 element.hash_code(),
2618 capabilities,
2619 );
2620 attach_node_tree(&mut *entry.node.borrow_mut(), context);
2621 element.update_node(&mut *entry.node.borrow_mut());
2622 request_auto_invalidations(context, capabilities);
2623 entry
2624}
2625
2626fn reconcile_element(
2631 element: DynModifierElement,
2632 new_pos: usize,
2633 (old_entries, index): (&mut [ModifierNodeEntry], &EntryIndex),
2634 (used, match_order): (&mut [bool], &mut [Option<usize>]),
2635 context: &mut dyn ModifierNodeContext,
2636) -> Option<ModifierNodeEntry> {
2637 let element_type = element.element_type();
2638 let node_type = element.node_type();
2639 let key = element.key();
2640 let hash_code = element.hash_code();
2641 let capabilities = element.capabilities();
2642 let Some(idx) = index.find_match(
2643 old_entries,
2644 used,
2645 EntryMatchQuery {
2646 element_type,
2647 node_type,
2648 key,
2649 hash_code,
2650 element: &element,
2651 },
2652 ) else {
2653 return Some(fresh_entry(element, context));
2654 };
2655 let entry = &mut old_entries[idx];
2656 if !element.can_update_node(&*entry.node.borrow()) {
2657 return Some(fresh_entry(element, context));
2658 }
2659
2660 used[idx] = true;
2661 match_order[idx] = Some(new_pos);
2662 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2663 attach_if_detached(entry, context);
2664 if !same_element || element.requires_update() {
2665 element.update_node(&mut *entry.node.borrow_mut());
2666 entry.element = element;
2667 entry.hash_code = hash_code;
2668 request_update_auto_invalidations(entry.element.as_ref(), context, capabilities);
2669 }
2670 if idx != new_pos {
2671 request_auto_invalidations(context, capabilities);
2672 }
2673 entry.key = key;
2674 entry.capabilities = capabilities;
2675 entry
2676 .node
2677 .borrow()
2678 .node_state()
2679 .set_capabilities(capabilities);
2680 None
2681}
2682
2683impl ModifierNodeChain {
2684 pub fn new() -> Self {
2685 let mut chain = Self {
2686 entries: Vec::new(),
2687 aggregated_capabilities: NodeCapabilities::empty(),
2688 head_aggregate_child_capabilities: NodeCapabilities::empty(),
2689 head_sentinel: SentinelNode::new(),
2690 tail_sentinel: SentinelNode::new(),
2691 ordered_nodes: Vec::new(),
2692 };
2693 chain.sync_chain_links();
2694 chain
2695 }
2696
2697 pub fn detach_nodes(&mut self) {
2699 for entry in &self.entries {
2700 detach_node_tree(&mut *entry.node.borrow_mut());
2701 }
2702 }
2703
2704 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
2706 for entry in &self.entries {
2707 attach_node_tree(&mut *entry.node.borrow_mut(), context);
2708 }
2709 }
2710
2711 pub fn repair_chain(&mut self) {
2714 self.sync_chain_links();
2715 }
2716
2717 pub fn update_from_slice(
2723 &mut self,
2724 elements: &[DynModifierElement],
2725 context: &mut dyn ModifierNodeContext,
2726 ) {
2727 self.update_from_ref_iter(elements.iter(), context);
2728 }
2729
2730 pub fn update_from_ref_iter<'a, I>(
2735 &mut self,
2736 elements: I,
2737 context: &mut dyn ModifierNodeContext,
2738 ) where
2739 I: Iterator<Item = &'a DynModifierElement>,
2740 {
2741 let mut scratch = RECONCILE_SCRATCH
2744 .try_with(|scratch| std::mem::take(&mut *scratch.borrow_mut()))
2745 .unwrap_or_default();
2746 self.reconcile(elements, context, &mut scratch);
2747 scratch.elements.clear();
2748 scratch.final_slots.clear();
2749 let _ = RECONCILE_SCRATCH.try_with(|slot| *slot.borrow_mut() = scratch);
2750 }
2751
2752 fn reconcile<'a, I>(
2753 &mut self,
2754 elements: I,
2755 context: &mut dyn ModifierNodeContext,
2756 scratch: &mut ReconcileScratch,
2757 ) where
2758 I: Iterator<Item = &'a DynModifierElement>,
2759 {
2760 let old_len = self.entries.len();
2761 let mut fast_path_failed_at: Option<usize> = None;
2762 let mut elements_count = 0;
2763
2764 scratch.elements.clear();
2765
2766 for (idx, element) in elements.enumerate() {
2767 elements_count = idx + 1;
2768 if fast_path_failed_at.is_none() && idx < old_len {
2769 if update_entry_in_place(&mut self.entries[idx], element, context) {
2770 continue;
2771 }
2772 fast_path_failed_at = Some(idx);
2773 }
2774 scratch.elements.push(element.clone());
2775 }
2776
2777 if fast_path_failed_at.is_none() && scratch.elements.is_empty() {
2778 if elements_count < self.entries.len() {
2779 for entry in self.entries.drain(elements_count..) {
2780 request_auto_invalidations(context, entry.capabilities);
2781 detach_node_tree(&mut *entry.node.borrow_mut());
2782 }
2783 }
2784 self.sync_chain_links();
2785 return;
2786 }
2787
2788 self.rebuild_tail(fast_path_failed_at.unwrap_or(old_len), context, scratch);
2789 }
2790
2791 fn rebuild_tail(
2795 &mut self,
2796 fail_idx: usize,
2797 context: &mut dyn ModifierNodeContext,
2798 scratch: &mut ReconcileScratch,
2799 ) {
2800 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
2801 let processed_entries_len = self.entries.len();
2802 let old_len = old_entries.len();
2803
2804 scratch.old_used.clear();
2805 scratch.old_used.resize(old_len, false);
2806
2807 scratch.match_order.clear();
2808 scratch.match_order.resize(old_len, None);
2809
2810 let index = EntryIndex::build(&old_entries);
2811
2812 let new_elements_count = scratch.elements.len();
2813 scratch.final_slots.clear();
2814 scratch.final_slots.reserve(new_elements_count);
2815
2816 for (new_pos, element) in scratch.elements.drain(..).enumerate() {
2817 let fresh = reconcile_element(
2818 element,
2819 new_pos,
2820 (&mut old_entries, &index),
2821 (&mut scratch.old_used, &mut scratch.match_order),
2822 context,
2823 );
2824 scratch.final_slots.push(fresh);
2825 }
2826
2827 for (i, entry) in old_entries.into_iter().enumerate() {
2828 match scratch.match_order[i] {
2829 Some(pos) if scratch.old_used[i] => scratch.final_slots[pos] = Some(entry),
2830 _ => {
2831 request_auto_invalidations(context, entry.capabilities);
2832 detach_node_tree(&mut *entry.node.borrow_mut());
2833 }
2834 }
2835 }
2836
2837 self.entries.reserve(scratch.final_slots.len());
2838 for slot in scratch.final_slots.drain(..) {
2839 if let Some(entry) = slot {
2840 self.entries.push(entry);
2841 } else {
2842 log::error!("modifier reconciliation produced an empty final slot");
2843 }
2844 }
2845
2846 debug_assert_eq!(
2847 self.entries.len(),
2848 processed_entries_len + new_elements_count
2849 );
2850 self.sync_chain_links();
2851 }
2852
2853 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
2857 where
2858 I: IntoIterator<Item = DynModifierElement>,
2859 {
2860 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
2861 self.update_from_slice(&collected, context);
2862 }
2863
2864 pub fn reset(&mut self) {
2867 for entry in &mut self.entries {
2868 reset_node_tree(&mut *entry.node.borrow_mut());
2869 }
2870 }
2871
2872 pub fn detach_all(&mut self) {
2874 for entry in std::mem::take(&mut self.entries) {
2875 detach_node_tree(&mut *entry.node.borrow_mut());
2876 {
2877 let node_borrow = entry.node.borrow();
2878 let state = node_borrow.node_state();
2879 state.set_capabilities(NodeCapabilities::empty());
2880 }
2881 }
2882 self.aggregated_capabilities = NodeCapabilities::empty();
2883 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2884 self.ordered_nodes.clear();
2885 self.sync_chain_links();
2886 }
2887
2888 pub fn len(&self) -> usize {
2889 self.entries.len()
2890 }
2891
2892 pub fn is_empty(&self) -> bool {
2893 self.entries.is_empty()
2894 }
2895
2896 pub fn capabilities(&self) -> NodeCapabilities {
2898 self.aggregated_capabilities
2899 }
2900
2901 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
2903 self.aggregated_capabilities.contains(capability)
2904 }
2905
2906 pub fn head(&self) -> ModifierChainNodeRef<'_> {
2908 self.make_node_ref(NodeLink::Head)
2909 }
2910
2911 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
2913 self.make_node_ref(NodeLink::Tail)
2914 }
2915
2916 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
2918 ModifierChainIter::forward(self)
2919 }
2920
2921 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
2923 ModifierChainIter::backward(self)
2924 }
2925
2926 pub fn for_each_forward<F>(&self, mut f: F)
2928 where
2929 F: FnMut(ModifierChainNodeRef<'_>),
2930 {
2931 for node in self.head_to_tail() {
2932 f(node);
2933 }
2934 }
2935
2936 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
2938 where
2939 F: FnMut(ModifierChainNodeRef<'_>),
2940 {
2941 if mask.is_empty() {
2942 self.for_each_forward(f);
2943 return;
2944 }
2945
2946 if !self.head().aggregate_child_capabilities().intersects(mask) {
2947 return;
2948 }
2949
2950 for node in self.head_to_tail() {
2951 if node.kind_set().intersects(mask) {
2952 f(node);
2953 }
2954 }
2955 }
2956
2957 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
2959 where
2960 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
2961 {
2962 self.for_each_forward_matching(mask, |node_ref| {
2963 node_ref.with_node(|node| f(node_ref.clone(), node));
2964 });
2965 }
2966
2967 pub fn for_each_backward<F>(&self, mut f: F)
2969 where
2970 F: FnMut(ModifierChainNodeRef<'_>),
2971 {
2972 for node in self.tail_to_head() {
2973 f(node);
2974 }
2975 }
2976
2977 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
2979 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
2980 node as *const dyn ModifierNode as *const ()
2981 }
2982
2983 let target = node_data_ptr(node);
2984 for (index, entry) in self.entries.iter().enumerate() {
2985 if node_data_ptr(&*entry.node.borrow()) == target {
2986 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
2987 }
2988 }
2989
2990 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
2991 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
2992 return None;
2993 }
2994 let matches_target = match link {
2995 NodeLink::Head => node_data_ptr(&self.head_sentinel) == target,
2996 NodeLink::Tail => node_data_ptr(&self.tail_sentinel) == target,
2997 NodeLink::Entry(path) => {
2998 let node_borrow = self.entries[path.entry()].node.borrow();
2999 node_data_ptr(&*node_borrow) == target
3000 }
3001 };
3002 if matches_target {
3003 Some(self.make_node_ref(*link))
3004 } else {
3005 None
3006 }
3007 })
3008 }
3009
3010 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
3013 self.entries.get(index).and_then(|entry| {
3014 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
3015 boxed_node.as_any().downcast_ref::<N>()
3016 })
3017 .ok()
3018 })
3019 }
3020
3021 pub fn node_mut<N: ModifierNode + 'static>(
3024 &self,
3025 index: usize,
3026 ) -> Option<std::cell::RefMut<'_, N>> {
3027 self.entries.get(index).and_then(|entry| {
3028 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
3029 boxed_node.as_any_mut().downcast_mut::<N>()
3030 })
3031 .ok()
3032 })
3033 }
3034
3035 pub fn get_node_rc(&self, index: usize) -> Option<&Rc<RefCell<dyn ModifierNode>>> {
3038 self.entries.get(index).map(|entry| &entry.node)
3039 }
3040
3041 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
3043 self.aggregated_capabilities
3044 .contains(NodeCapabilities::for_invalidation(kind))
3045 }
3046
3047 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
3049 where
3050 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
3051 {
3052 for index in 0..self.ordered_nodes.len() {
3053 let (link, cached_caps, _agg) = self.ordered_nodes[index];
3054 match link {
3055 NodeLink::Head => {
3056 f(&mut self.head_sentinel, cached_caps);
3057 }
3058 NodeLink::Tail => {
3059 f(&mut self.tail_sentinel, cached_caps);
3060 }
3061 NodeLink::Entry(path) => {
3062 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
3063 if path.delegates().is_empty() {
3064 f(&mut *node_borrow, cached_caps);
3065 } else {
3066 let mut current: &mut dyn ModifierNode = &mut *node_borrow;
3067 for &delegate_index in path.delegates() {
3068 if let Some(delegate) =
3069 nth_delegate_mut(current, delegate_index as usize)
3070 {
3071 current = delegate;
3072 } else {
3073 return;
3074 }
3075 }
3076 f(current, cached_caps);
3077 }
3078 }
3079 }
3080 }
3081 }
3082
3083 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
3084 ModifierChainNodeRef {
3085 chain: self,
3086 link,
3087 cached_capabilities: None,
3088 cached_aggregate_child: None,
3089 }
3090 }
3091
3092 fn make_node_ref_with_caps(
3093 &self,
3094 link: NodeLink,
3095 caps: NodeCapabilities,
3096 aggregate_child: NodeCapabilities,
3097 ) -> ModifierChainNodeRef<'_> {
3098 ModifierChainNodeRef {
3099 chain: self,
3100 link,
3101 cached_capabilities: Some(caps),
3102 cached_aggregate_child: Some(aggregate_child),
3103 }
3104 }
3105
3106 fn sync_chain_links(&mut self) {
3107 self.rebuild_ordered_nodes();
3108
3109 self.head_sentinel.node_state().set_parent_link(None);
3110 self.tail_sentinel.node_state().set_child_link(None);
3111
3112 if self.ordered_nodes.is_empty() {
3113 self.head_sentinel
3114 .node_state()
3115 .set_child_link(Some(NodeLink::Tail));
3116 self.tail_sentinel
3117 .node_state()
3118 .set_parent_link(Some(NodeLink::Head));
3119 self.aggregated_capabilities = NodeCapabilities::empty();
3120 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
3121 self.head_sentinel
3122 .node_state()
3123 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3124 self.tail_sentinel
3125 .node_state()
3126 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3127 return;
3128 }
3129
3130 let mut previous = NodeLink::Head;
3131 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
3132 match &previous {
3133 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
3134 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
3135 NodeLink::Entry(path) => {
3136 let node_borrow = self.entries[path.entry()].node.borrow();
3137 if path.delegates().is_empty() {
3138 node_borrow.node_state().set_child_link(Some(link));
3139 } else {
3140 let mut current: &dyn ModifierNode = &*node_borrow;
3141 for &delegate_index in path.delegates() {
3142 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3143 current = delegate;
3144 }
3145 }
3146 current.node_state().set_child_link(Some(link));
3147 }
3148 }
3149 }
3150 match &link {
3151 NodeLink::Head => self
3152 .head_sentinel
3153 .node_state()
3154 .set_parent_link(Some(previous)),
3155 NodeLink::Tail => self
3156 .tail_sentinel
3157 .node_state()
3158 .set_parent_link(Some(previous)),
3159 NodeLink::Entry(path) => {
3160 let node_borrow = self.entries[path.entry()].node.borrow();
3161 if path.delegates().is_empty() {
3162 node_borrow.node_state().set_parent_link(Some(previous));
3163 } else {
3164 let mut current: &dyn ModifierNode = &*node_borrow;
3165 for &delegate_index in path.delegates() {
3166 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3167 current = delegate;
3168 }
3169 }
3170 current.node_state().set_parent_link(Some(previous));
3171 }
3172 }
3173 }
3174 previous = link;
3175 }
3176
3177 match &previous {
3178 NodeLink::Head => self
3179 .head_sentinel
3180 .node_state()
3181 .set_child_link(Some(NodeLink::Tail)),
3182 NodeLink::Tail => self
3183 .tail_sentinel
3184 .node_state()
3185 .set_child_link(Some(NodeLink::Tail)),
3186 NodeLink::Entry(path) => {
3187 let node_borrow = self.entries[path.entry()].node.borrow();
3188 if path.delegates().is_empty() {
3189 node_borrow
3190 .node_state()
3191 .set_child_link(Some(NodeLink::Tail));
3192 } else {
3193 let mut current: &dyn ModifierNode = &*node_borrow;
3194 for &delegate_index in path.delegates() {
3195 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3196 current = delegate;
3197 }
3198 }
3199 current.node_state().set_child_link(Some(NodeLink::Tail));
3200 }
3201 }
3202 }
3203 self.tail_sentinel
3204 .node_state()
3205 .set_parent_link(Some(previous));
3206 self.tail_sentinel.node_state().set_child_link(None);
3207
3208 let mut aggregate = NodeCapabilities::empty();
3209 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
3210 aggregate |= *cached_caps;
3211 *cached_aggregate = aggregate;
3212 match link {
3213 NodeLink::Head => {
3214 self.head_sentinel
3215 .node_state()
3216 .set_aggregate_child_capabilities(aggregate);
3217 }
3218 NodeLink::Tail => {
3219 self.tail_sentinel
3220 .node_state()
3221 .set_aggregate_child_capabilities(aggregate);
3222 }
3223 NodeLink::Entry(path) => {
3224 let node_borrow = self.entries[path.entry()].node.borrow();
3225 let state = if path.delegates().is_empty() {
3226 node_borrow.node_state()
3227 } else {
3228 let mut current: &dyn ModifierNode = &*node_borrow;
3229 for &delegate_index in path.delegates() {
3230 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3231 current = delegate;
3232 }
3233 }
3234 current.node_state()
3235 };
3236 state.set_aggregate_child_capabilities(aggregate);
3237 }
3238 }
3239 }
3240
3241 self.aggregated_capabilities = aggregate;
3242 self.head_aggregate_child_capabilities = aggregate;
3243 self.head_sentinel
3244 .node_state()
3245 .set_aggregate_child_capabilities(aggregate);
3246 self.tail_sentinel
3247 .node_state()
3248 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3249 }
3250
3251 fn rebuild_ordered_nodes(&mut self) {
3252 self.ordered_nodes.clear();
3253 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
3254 for (index, entry) in self.entries.iter().enumerate() {
3255 let node_borrow = entry.node.borrow();
3256 Self::enumerate_link_order(
3257 &*node_borrow,
3258 index,
3259 &mut path_buf,
3260 0,
3261 &mut self.ordered_nodes,
3262 );
3263 }
3264 }
3265
3266 fn enumerate_link_order(
3267 node: &dyn ModifierNode,
3268 entry: usize,
3269 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
3270 path_len: usize,
3271 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
3272 ) {
3273 let caps = node.node_state().capabilities();
3274 out.push((
3275 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
3276 caps,
3277 NodeCapabilities::empty(),
3278 ));
3279 let mut delegate_index = 0usize;
3280 node.for_each_delegate(&mut |child| {
3281 if path_len < MAX_DELEGATE_DEPTH {
3282 path_buf[path_len] = delegate_index;
3283 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
3284 }
3285 delegate_index += 1;
3286 });
3287 }
3288}
3289
3290impl<'a> ModifierChainNodeRef<'a> {
3291 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
3292 match &self.link {
3293 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
3294 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
3295 NodeLink::Entry(path) => {
3296 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3297 if path.delegates().is_empty() {
3298 f(node_borrow.node_state())
3299 } else {
3300 let mut current: &dyn ModifierNode = &*node_borrow;
3301 for &delegate_index in path.delegates() {
3302 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3303 current = delegate;
3304 } else {
3305 return f(node_borrow.node_state());
3306 }
3307 }
3308 f(current.node_state())
3309 }
3310 }
3311 }
3312 }
3313
3314 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
3317 match &self.link {
3318 NodeLink::Head => None,
3319 NodeLink::Tail => None,
3320 NodeLink::Entry(path) => {
3321 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3322 if path.delegates().is_empty() {
3323 Some(f(&*node_borrow))
3324 } else {
3325 let mut current: &dyn ModifierNode = &*node_borrow;
3326 for &delegate_index in path.delegates() {
3327 current = nth_delegate(current, delegate_index as usize)?;
3328 }
3329 Some(f(current))
3330 }
3331 }
3332 }
3333 }
3334
3335 #[inline]
3337 pub fn parent(&self) -> Option<Self> {
3338 self.with_state(NodeState::parent_link)
3339 .map(|link| self.chain.make_node_ref(link))
3340 }
3341
3342 #[inline]
3344 pub fn child(&self) -> Option<Self> {
3345 self.with_state(NodeState::child_link)
3346 .map(|link| self.chain.make_node_ref(link))
3347 }
3348
3349 #[inline]
3351 pub fn kind_set(&self) -> NodeCapabilities {
3352 if let Some(caps) = self.cached_capabilities {
3353 return caps;
3354 }
3355 match &self.link {
3356 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
3357 NodeLink::Entry(_) => self.with_state(NodeState::capabilities),
3358 }
3359 }
3360
3361 pub fn entry_index(&self) -> Option<usize> {
3363 match &self.link {
3364 NodeLink::Entry(path) => Some(path.entry()),
3365 _ => None,
3366 }
3367 }
3368
3369 pub fn delegate_depth(&self) -> usize {
3371 match &self.link {
3372 NodeLink::Entry(path) => path.delegates().len(),
3373 _ => 0,
3374 }
3375 }
3376
3377 #[inline]
3379 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
3380 if let Some(agg) = self.cached_aggregate_child {
3381 return agg;
3382 }
3383 if self.is_tail() {
3384 NodeCapabilities::empty()
3385 } else {
3386 self.with_state(NodeState::aggregate_child_capabilities)
3387 }
3388 }
3389
3390 pub fn is_head(&self) -> bool {
3392 matches!(self.link, NodeLink::Head)
3393 }
3394
3395 pub fn is_tail(&self) -> bool {
3397 matches!(self.link, NodeLink::Tail)
3398 }
3399
3400 pub fn is_sentinel(&self) -> bool {
3402 matches!(self.link, NodeLink::Head | NodeLink::Tail)
3403 }
3404
3405 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
3407 !mask.is_empty() && self.kind_set().intersects(mask)
3408 }
3409
3410 pub fn visit_descendants<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.child()
3419 };
3420 while let Some(node) = current {
3421 if node.is_tail() {
3422 break;
3423 }
3424 if !node.is_sentinel() {
3425 f(node.clone());
3426 }
3427 current = node.child();
3428 }
3429 }
3430
3431 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3433 where
3434 F: FnMut(ModifierChainNodeRef<'a>),
3435 {
3436 if mask.is_empty() {
3437 self.visit_descendants(include_self, f);
3438 return;
3439 }
3440
3441 if !self.aggregate_child_capabilities().intersects(mask) {
3442 return;
3443 }
3444
3445 self.visit_descendants(include_self, |node| {
3446 if node.kind_set().intersects(mask) {
3447 f(node);
3448 }
3449 });
3450 }
3451
3452 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
3454 where
3455 F: FnMut(ModifierChainNodeRef<'a>),
3456 {
3457 let mut current = if include_self {
3458 Some(self)
3459 } else {
3460 self.parent()
3461 };
3462 while let Some(node) = current {
3463 if node.is_head() {
3464 break;
3465 }
3466 f(node.clone());
3467 current = node.parent();
3468 }
3469 }
3470
3471 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3473 where
3474 F: FnMut(ModifierChainNodeRef<'a>),
3475 {
3476 if mask.is_empty() {
3477 self.visit_ancestors(include_self, f);
3478 return;
3479 }
3480
3481 self.visit_ancestors(include_self, |node| {
3482 if node.kind_set().intersects(mask) {
3483 f(node);
3484 }
3485 });
3486 }
3487}
3488
3489#[cfg(test)]
3490#[path = "tests/modifier_tests.rs"]
3491mod tests;