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