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 measure_hold(
498 &self,
499 _density: f32,
500 _constraints: Constraints,
501 _size: Size,
502 _wrapped: cranpose_ui_layout::WrappedHold,
503 ) -> Option<cranpose_ui_layout::ConstraintsHold> {
504 None
505 }
506
507 fn min_intrinsic_width(&self, measurable: &dyn Measurable, height: f32, _density: f32) -> f32 {
510 measurable.min_intrinsic_width(height)
511 }
512
513 fn max_intrinsic_width(&self, measurable: &dyn Measurable, height: f32, _density: f32) -> f32 {
516 measurable.max_intrinsic_width(height)
517 }
518
519 fn min_intrinsic_height(&self, measurable: &dyn Measurable, width: f32, _density: f32) -> f32 {
522 measurable.min_intrinsic_height(width)
523 }
524
525 fn max_intrinsic_height(&self, measurable: &dyn Measurable, width: f32, _density: f32) -> f32 {
528 measurable.max_intrinsic_height(width)
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_entries_of_type<'a, I>(
2740 &mut self,
2741 elements: I,
2742 element_count: usize,
2743 element_type: TypeId,
2744 context: &mut dyn ModifierNodeContext,
2745 ) -> bool
2746 where
2747 I: Iterator<Item = &'a DynModifierElement>,
2748 {
2749 if element_count != self.entries.len() {
2750 return false;
2751 }
2752 self.entries
2753 .iter_mut()
2754 .zip(elements)
2755 .filter(|(_, element)| element.element_type() == element_type)
2756 .all(|(entry, element)| update_entry_in_place(entry, element, context))
2757 }
2758
2759 pub fn update_from_ref_iter<'a, I>(
2760 &mut self,
2761 elements: I,
2762 context: &mut dyn ModifierNodeContext,
2763 ) where
2764 I: Iterator<Item = &'a DynModifierElement>,
2765 {
2766 let mut scratch = RECONCILE_SCRATCH
2769 .try_with(|scratch| std::mem::take(&mut *scratch.borrow_mut()))
2770 .unwrap_or_default();
2771 self.reconcile(elements, context, &mut scratch);
2772 scratch.elements.clear();
2773 scratch.final_slots.clear();
2774 let _ = RECONCILE_SCRATCH.try_with(|slot| *slot.borrow_mut() = scratch);
2775 }
2776
2777 fn reconcile<'a, I>(
2778 &mut self,
2779 elements: I,
2780 context: &mut dyn ModifierNodeContext,
2781 scratch: &mut ReconcileScratch,
2782 ) where
2783 I: Iterator<Item = &'a DynModifierElement>,
2784 {
2785 let old_len = self.entries.len();
2786 let mut fast_path_failed_at: Option<usize> = None;
2787 let mut elements_count = 0;
2788
2789 scratch.elements.clear();
2790
2791 for (idx, element) in elements.enumerate() {
2792 elements_count = idx + 1;
2793 if fast_path_failed_at.is_none() && idx < old_len {
2794 if update_entry_in_place(&mut self.entries[idx], element, context) {
2795 continue;
2796 }
2797 fast_path_failed_at = Some(idx);
2798 }
2799 scratch.elements.push(element.clone());
2800 }
2801
2802 if fast_path_failed_at.is_none() && scratch.elements.is_empty() {
2803 if elements_count < self.entries.len() {
2804 for entry in self.entries.drain(elements_count..) {
2805 request_auto_invalidations(context, entry.capabilities);
2806 detach_node_tree(&mut *entry.node.borrow_mut());
2807 }
2808 }
2809 self.sync_chain_links();
2810 return;
2811 }
2812
2813 self.rebuild_tail(fast_path_failed_at.unwrap_or(old_len), context, scratch);
2814 }
2815
2816 fn rebuild_tail(
2820 &mut self,
2821 fail_idx: usize,
2822 context: &mut dyn ModifierNodeContext,
2823 scratch: &mut ReconcileScratch,
2824 ) {
2825 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
2826 let processed_entries_len = self.entries.len();
2827 let old_len = old_entries.len();
2828
2829 scratch.old_used.clear();
2830 scratch.old_used.resize(old_len, false);
2831
2832 scratch.match_order.clear();
2833 scratch.match_order.resize(old_len, None);
2834
2835 let index = EntryIndex::build(&old_entries);
2836
2837 let new_elements_count = scratch.elements.len();
2838 scratch.final_slots.clear();
2839 scratch.final_slots.reserve(new_elements_count);
2840
2841 for (new_pos, element) in scratch.elements.drain(..).enumerate() {
2842 let fresh = reconcile_element(
2843 element,
2844 new_pos,
2845 (&mut old_entries, &index),
2846 (&mut scratch.old_used, &mut scratch.match_order),
2847 context,
2848 );
2849 scratch.final_slots.push(fresh);
2850 }
2851
2852 for (i, entry) in old_entries.into_iter().enumerate() {
2853 match scratch.match_order[i] {
2854 Some(pos) if scratch.old_used[i] => scratch.final_slots[pos] = Some(entry),
2855 _ => {
2856 request_auto_invalidations(context, entry.capabilities);
2857 detach_node_tree(&mut *entry.node.borrow_mut());
2858 }
2859 }
2860 }
2861
2862 self.entries.reserve_exact(scratch.final_slots.len());
2866 for slot in scratch.final_slots.drain(..) {
2867 if let Some(entry) = slot {
2868 self.entries.push(entry);
2869 } else {
2870 log::error!("modifier reconciliation produced an empty final slot");
2871 }
2872 }
2873
2874 debug_assert_eq!(
2875 self.entries.len(),
2876 processed_entries_len + new_elements_count
2877 );
2878 self.sync_chain_links();
2879 }
2880
2881 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
2885 where
2886 I: IntoIterator<Item = DynModifierElement>,
2887 {
2888 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
2889 self.update_from_slice(&collected, context);
2890 }
2891
2892 pub fn reset(&mut self) {
2895 for entry in &mut self.entries {
2896 reset_node_tree(&mut *entry.node.borrow_mut());
2897 }
2898 }
2899
2900 pub fn detach_all(&mut self) {
2902 for entry in std::mem::take(&mut self.entries) {
2903 detach_node_tree(&mut *entry.node.borrow_mut());
2904 {
2905 let node_borrow = entry.node.borrow();
2906 let state = node_borrow.node_state();
2907 state.set_capabilities(NodeCapabilities::empty());
2908 }
2909 }
2910 self.aggregated_capabilities = NodeCapabilities::empty();
2911 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2912 self.ordered_nodes.clear();
2913 self.sync_chain_links();
2914 }
2915
2916 pub fn len(&self) -> usize {
2917 self.entries.len()
2918 }
2919
2920 pub fn is_empty(&self) -> bool {
2921 self.entries.is_empty()
2922 }
2923
2924 pub fn capabilities(&self) -> NodeCapabilities {
2926 self.aggregated_capabilities
2927 }
2928
2929 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
2931 self.aggregated_capabilities.contains(capability)
2932 }
2933
2934 pub fn head(&self) -> ModifierChainNodeRef<'_> {
2936 self.make_node_ref(NodeLink::Head)
2937 }
2938
2939 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
2941 self.make_node_ref(NodeLink::Tail)
2942 }
2943
2944 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
2946 ModifierChainIter::forward(self)
2947 }
2948
2949 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
2951 ModifierChainIter::backward(self)
2952 }
2953
2954 pub fn for_each_forward<F>(&self, mut f: F)
2956 where
2957 F: FnMut(ModifierChainNodeRef<'_>),
2958 {
2959 for node in self.head_to_tail() {
2960 f(node);
2961 }
2962 }
2963
2964 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
2966 where
2967 F: FnMut(ModifierChainNodeRef<'_>),
2968 {
2969 if mask.is_empty() {
2970 self.for_each_forward(f);
2971 return;
2972 }
2973
2974 if !self.head().aggregate_child_capabilities().intersects(mask) {
2975 return;
2976 }
2977
2978 for node in self.head_to_tail() {
2979 if node.kind_set().intersects(mask) {
2980 f(node);
2981 }
2982 }
2983 }
2984
2985 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
2987 where
2988 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
2989 {
2990 self.for_each_forward_matching(mask, |node_ref| {
2991 node_ref.with_node(|node| f(node_ref.clone(), node));
2992 });
2993 }
2994
2995 pub fn for_each_backward<F>(&self, mut f: F)
2997 where
2998 F: FnMut(ModifierChainNodeRef<'_>),
2999 {
3000 for node in self.tail_to_head() {
3001 f(node);
3002 }
3003 }
3004
3005 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
3007 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
3008 node as *const dyn ModifierNode as *const ()
3009 }
3010
3011 let target = node_data_ptr(node);
3012 for (index, entry) in self.entries.iter().enumerate() {
3013 if node_data_ptr(&*entry.node.borrow()) == target {
3014 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
3015 }
3016 }
3017
3018 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
3019 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
3020 return None;
3021 }
3022 let matches_target = match link {
3023 NodeLink::Head => node_data_ptr(&self.head_sentinel) == target,
3024 NodeLink::Tail => node_data_ptr(&self.tail_sentinel) == target,
3025 NodeLink::Entry(path) => {
3026 let node_borrow = self.entries[path.entry()].node.borrow();
3027 node_data_ptr(&*node_borrow) == target
3028 }
3029 };
3030 if matches_target {
3031 Some(self.make_node_ref(*link))
3032 } else {
3033 None
3034 }
3035 })
3036 }
3037
3038 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
3041 self.entries.get(index).and_then(|entry| {
3042 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
3043 boxed_node.as_any().downcast_ref::<N>()
3044 })
3045 .ok()
3046 })
3047 }
3048
3049 pub fn node_mut<N: ModifierNode + 'static>(
3052 &self,
3053 index: usize,
3054 ) -> Option<std::cell::RefMut<'_, N>> {
3055 self.entries.get(index).and_then(|entry| {
3056 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
3057 boxed_node.as_any_mut().downcast_mut::<N>()
3058 })
3059 .ok()
3060 })
3061 }
3062
3063 pub fn get_node_rc(&self, index: usize) -> Option<&Rc<RefCell<dyn ModifierNode>>> {
3066 self.entries.get(index).map(|entry| &entry.node)
3067 }
3068
3069 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
3071 self.aggregated_capabilities
3072 .contains(NodeCapabilities::for_invalidation(kind))
3073 }
3074
3075 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
3077 where
3078 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
3079 {
3080 for index in 0..self.ordered_nodes.len() {
3081 let (link, cached_caps, _agg) = self.ordered_nodes[index];
3082 match link {
3083 NodeLink::Head => {
3084 f(&mut self.head_sentinel, cached_caps);
3085 }
3086 NodeLink::Tail => {
3087 f(&mut self.tail_sentinel, cached_caps);
3088 }
3089 NodeLink::Entry(path) => {
3090 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
3091 if path.delegates().is_empty() {
3092 f(&mut *node_borrow, cached_caps);
3093 } else {
3094 let mut current: &mut dyn ModifierNode = &mut *node_borrow;
3095 for &delegate_index in path.delegates() {
3096 if let Some(delegate) =
3097 nth_delegate_mut(current, delegate_index as usize)
3098 {
3099 current = delegate;
3100 } else {
3101 return;
3102 }
3103 }
3104 f(current, cached_caps);
3105 }
3106 }
3107 }
3108 }
3109 }
3110
3111 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
3112 ModifierChainNodeRef {
3113 chain: self,
3114 link,
3115 cached_capabilities: None,
3116 cached_aggregate_child: None,
3117 }
3118 }
3119
3120 fn make_node_ref_with_caps(
3121 &self,
3122 link: NodeLink,
3123 caps: NodeCapabilities,
3124 aggregate_child: NodeCapabilities,
3125 ) -> ModifierChainNodeRef<'_> {
3126 ModifierChainNodeRef {
3127 chain: self,
3128 link,
3129 cached_capabilities: Some(caps),
3130 cached_aggregate_child: Some(aggregate_child),
3131 }
3132 }
3133
3134 fn sync_chain_links(&mut self) {
3135 self.rebuild_ordered_nodes();
3136
3137 self.head_sentinel.node_state().set_parent_link(None);
3138 self.tail_sentinel.node_state().set_child_link(None);
3139
3140 if self.ordered_nodes.is_empty() {
3141 self.head_sentinel
3142 .node_state()
3143 .set_child_link(Some(NodeLink::Tail));
3144 self.tail_sentinel
3145 .node_state()
3146 .set_parent_link(Some(NodeLink::Head));
3147 self.aggregated_capabilities = NodeCapabilities::empty();
3148 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
3149 self.head_sentinel
3150 .node_state()
3151 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3152 self.tail_sentinel
3153 .node_state()
3154 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3155 return;
3156 }
3157
3158 let mut previous = NodeLink::Head;
3159 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
3160 match &previous {
3161 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
3162 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
3163 NodeLink::Entry(path) => {
3164 let node_borrow = self.entries[path.entry()].node.borrow();
3165 if path.delegates().is_empty() {
3166 node_borrow.node_state().set_child_link(Some(link));
3167 } else {
3168 let mut current: &dyn ModifierNode = &*node_borrow;
3169 for &delegate_index in path.delegates() {
3170 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3171 current = delegate;
3172 }
3173 }
3174 current.node_state().set_child_link(Some(link));
3175 }
3176 }
3177 }
3178 match &link {
3179 NodeLink::Head => self
3180 .head_sentinel
3181 .node_state()
3182 .set_parent_link(Some(previous)),
3183 NodeLink::Tail => self
3184 .tail_sentinel
3185 .node_state()
3186 .set_parent_link(Some(previous)),
3187 NodeLink::Entry(path) => {
3188 let node_borrow = self.entries[path.entry()].node.borrow();
3189 if path.delegates().is_empty() {
3190 node_borrow.node_state().set_parent_link(Some(previous));
3191 } else {
3192 let mut current: &dyn ModifierNode = &*node_borrow;
3193 for &delegate_index in path.delegates() {
3194 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3195 current = delegate;
3196 }
3197 }
3198 current.node_state().set_parent_link(Some(previous));
3199 }
3200 }
3201 }
3202 previous = link;
3203 }
3204
3205 match &previous {
3206 NodeLink::Head => self
3207 .head_sentinel
3208 .node_state()
3209 .set_child_link(Some(NodeLink::Tail)),
3210 NodeLink::Tail => self
3211 .tail_sentinel
3212 .node_state()
3213 .set_child_link(Some(NodeLink::Tail)),
3214 NodeLink::Entry(path) => {
3215 let node_borrow = self.entries[path.entry()].node.borrow();
3216 if path.delegates().is_empty() {
3217 node_borrow
3218 .node_state()
3219 .set_child_link(Some(NodeLink::Tail));
3220 } else {
3221 let mut current: &dyn ModifierNode = &*node_borrow;
3222 for &delegate_index in path.delegates() {
3223 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3224 current = delegate;
3225 }
3226 }
3227 current.node_state().set_child_link(Some(NodeLink::Tail));
3228 }
3229 }
3230 }
3231 self.tail_sentinel
3232 .node_state()
3233 .set_parent_link(Some(previous));
3234 self.tail_sentinel.node_state().set_child_link(None);
3235
3236 let mut aggregate = NodeCapabilities::empty();
3237 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
3238 aggregate |= *cached_caps;
3239 *cached_aggregate = aggregate;
3240 match link {
3241 NodeLink::Head => {
3242 self.head_sentinel
3243 .node_state()
3244 .set_aggregate_child_capabilities(aggregate);
3245 }
3246 NodeLink::Tail => {
3247 self.tail_sentinel
3248 .node_state()
3249 .set_aggregate_child_capabilities(aggregate);
3250 }
3251 NodeLink::Entry(path) => {
3252 let node_borrow = self.entries[path.entry()].node.borrow();
3253 let state = if path.delegates().is_empty() {
3254 node_borrow.node_state()
3255 } else {
3256 let mut current: &dyn ModifierNode = &*node_borrow;
3257 for &delegate_index in path.delegates() {
3258 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3259 current = delegate;
3260 }
3261 }
3262 current.node_state()
3263 };
3264 state.set_aggregate_child_capabilities(aggregate);
3265 }
3266 }
3267 }
3268
3269 self.aggregated_capabilities = aggregate;
3270 self.head_aggregate_child_capabilities = aggregate;
3271 self.head_sentinel
3272 .node_state()
3273 .set_aggregate_child_capabilities(aggregate);
3274 self.tail_sentinel
3275 .node_state()
3276 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3277 }
3278
3279 fn rebuild_ordered_nodes(&mut self) {
3280 self.ordered_nodes.clear();
3281 self.ordered_nodes.reserve_exact(self.entries.len());
3283 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
3284 for (index, entry) in self.entries.iter().enumerate() {
3285 let node_borrow = entry.node.borrow();
3286 Self::enumerate_link_order(
3287 &*node_borrow,
3288 index,
3289 &mut path_buf,
3290 0,
3291 &mut self.ordered_nodes,
3292 );
3293 }
3294 }
3295
3296 fn enumerate_link_order(
3297 node: &dyn ModifierNode,
3298 entry: usize,
3299 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
3300 path_len: usize,
3301 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
3302 ) {
3303 let caps = node.node_state().capabilities();
3304 out.push((
3305 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
3306 caps,
3307 NodeCapabilities::empty(),
3308 ));
3309 let mut delegate_index = 0usize;
3310 node.for_each_delegate(&mut |child| {
3311 if path_len < MAX_DELEGATE_DEPTH {
3312 path_buf[path_len] = delegate_index;
3313 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
3314 }
3315 delegate_index += 1;
3316 });
3317 }
3318}
3319
3320impl<'a> ModifierChainNodeRef<'a> {
3321 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
3322 match &self.link {
3323 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
3324 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
3325 NodeLink::Entry(path) => {
3326 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3327 if path.delegates().is_empty() {
3328 f(node_borrow.node_state())
3329 } else {
3330 let mut current: &dyn ModifierNode = &*node_borrow;
3331 for &delegate_index in path.delegates() {
3332 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3333 current = delegate;
3334 } else {
3335 return f(node_borrow.node_state());
3336 }
3337 }
3338 f(current.node_state())
3339 }
3340 }
3341 }
3342 }
3343
3344 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
3347 match &self.link {
3348 NodeLink::Head => None,
3349 NodeLink::Tail => None,
3350 NodeLink::Entry(path) => {
3351 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3352 if path.delegates().is_empty() {
3353 Some(f(&*node_borrow))
3354 } else {
3355 let mut current: &dyn ModifierNode = &*node_borrow;
3356 for &delegate_index in path.delegates() {
3357 current = nth_delegate(current, delegate_index as usize)?;
3358 }
3359 Some(f(current))
3360 }
3361 }
3362 }
3363 }
3364
3365 #[inline]
3367 pub fn parent(&self) -> Option<Self> {
3368 self.with_state(NodeState::parent_link)
3369 .map(|link| self.chain.make_node_ref(link))
3370 }
3371
3372 #[inline]
3374 pub fn child(&self) -> Option<Self> {
3375 self.with_state(NodeState::child_link)
3376 .map(|link| self.chain.make_node_ref(link))
3377 }
3378
3379 #[inline]
3381 pub fn kind_set(&self) -> NodeCapabilities {
3382 if let Some(caps) = self.cached_capabilities {
3383 return caps;
3384 }
3385 match &self.link {
3386 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
3387 NodeLink::Entry(_) => self.with_state(NodeState::capabilities),
3388 }
3389 }
3390
3391 pub fn entry_index(&self) -> Option<usize> {
3393 match &self.link {
3394 NodeLink::Entry(path) => Some(path.entry()),
3395 _ => None,
3396 }
3397 }
3398
3399 pub fn delegate_depth(&self) -> usize {
3401 match &self.link {
3402 NodeLink::Entry(path) => path.delegates().len(),
3403 _ => 0,
3404 }
3405 }
3406
3407 #[inline]
3409 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
3410 if let Some(agg) = self.cached_aggregate_child {
3411 return agg;
3412 }
3413 if self.is_tail() {
3414 NodeCapabilities::empty()
3415 } else {
3416 self.with_state(NodeState::aggregate_child_capabilities)
3417 }
3418 }
3419
3420 pub fn is_head(&self) -> bool {
3422 matches!(self.link, NodeLink::Head)
3423 }
3424
3425 pub fn is_tail(&self) -> bool {
3427 matches!(self.link, NodeLink::Tail)
3428 }
3429
3430 pub fn is_sentinel(&self) -> bool {
3432 matches!(self.link, NodeLink::Head | NodeLink::Tail)
3433 }
3434
3435 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
3437 !mask.is_empty() && self.kind_set().intersects(mask)
3438 }
3439
3440 pub fn visit_descendants<F>(self, include_self: bool, mut f: F)
3442 where
3443 F: FnMut(ModifierChainNodeRef<'a>),
3444 {
3445 let mut current = if include_self {
3446 Some(self)
3447 } else {
3448 self.child()
3449 };
3450 while let Some(node) = current {
3451 if node.is_tail() {
3452 break;
3453 }
3454 if !node.is_sentinel() {
3455 f(node.clone());
3456 }
3457 current = node.child();
3458 }
3459 }
3460
3461 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3463 where
3464 F: FnMut(ModifierChainNodeRef<'a>),
3465 {
3466 if mask.is_empty() {
3467 self.visit_descendants(include_self, f);
3468 return;
3469 }
3470
3471 if !self.aggregate_child_capabilities().intersects(mask) {
3472 return;
3473 }
3474
3475 self.visit_descendants(include_self, |node| {
3476 if node.kind_set().intersects(mask) {
3477 f(node);
3478 }
3479 });
3480 }
3481
3482 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
3484 where
3485 F: FnMut(ModifierChainNodeRef<'a>),
3486 {
3487 let mut current = if include_self {
3488 Some(self)
3489 } else {
3490 self.parent()
3491 };
3492 while let Some(node) = current {
3493 if node.is_head() {
3494 break;
3495 }
3496 f(node.clone());
3497 current = node.parent();
3498 }
3499 }
3500
3501 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3503 where
3504 F: FnMut(ModifierChainNodeRef<'a>),
3505 {
3506 if mask.is_empty() {
3507 self.visit_ancestors(include_self, f);
3508 return;
3509 }
3510
3511 self.visit_ancestors(include_self, |node| {
3512 if node.kind_set().intersects(mask) {
3513 f(node);
3514 }
3515 });
3516 }
3517}
3518
3519#[cfg(test)]
3520#[path = "tests/modifier_tests.rs"]
3521mod tests;