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::{collections::map::HashMap, hash::default};
18pub use cranpose_ui_graphics::{DrawScope, Size};
19pub use cranpose_ui_layout::{Constraints, Measurable};
20
21use crate::nodes::input::types::PointerEvent;
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
26pub enum InvalidationKind {
27 Layout,
28 Draw,
29 PointerInput,
30 Semantics,
31 Focus,
32}
33
34pub trait ModifierNodeContext {
36 fn invalidate(&mut self, _kind: InvalidationKind) {}
38
39 fn request_update(&mut self) {}
42
43 fn node_id(&self) -> Option<cranpose_core::NodeId> {
46 None
47 }
48
49 fn push_active_capabilities(&mut self, _capabilities: NodeCapabilities) {}
51
52 fn pop_active_capabilities(&mut self) {}
54}
55
56#[derive(Default, Debug, Clone)]
65pub struct BasicModifierNodeContext {
66 invalidations: Vec<ModifierInvalidation>,
67 update_requested: bool,
68 active_capabilities: Vec<NodeCapabilities>,
69 node_id: Option<cranpose_core::NodeId>,
70}
71
72impl BasicModifierNodeContext {
73 pub fn new() -> Self {
75 Self::default()
76 }
77
78 pub fn invalidations(&self) -> &[ModifierInvalidation] {
82 &self.invalidations
83 }
84
85 pub fn clear_invalidations(&mut self) {
87 self.invalidations.clear();
88 }
89
90 pub fn take_invalidations(&mut self) -> Vec<ModifierInvalidation> {
92 std::mem::take(&mut self.invalidations)
93 }
94
95 pub fn update_requested(&self) -> bool {
98 self.update_requested
99 }
100
101 pub fn take_update_requested(&mut self) -> bool {
103 std::mem::take(&mut self.update_requested)
104 }
105
106 pub fn set_node_id(&mut self, id: Option<cranpose_core::NodeId>) {
108 self.node_id = id;
109 }
110
111 fn push_invalidation(&mut self, kind: InvalidationKind) {
112 let mut capabilities = self.current_capabilities();
113 capabilities.insert(NodeCapabilities::for_invalidation(kind));
114 if let Some(existing) = self
115 .invalidations
116 .iter_mut()
117 .find(|entry| entry.kind() == kind)
118 {
119 let updated = existing.capabilities() | capabilities;
120 *existing = ModifierInvalidation::new(kind, updated);
121 } else {
122 self.invalidations
123 .push(ModifierInvalidation::new(kind, capabilities));
124 }
125 }
126
127 fn current_capabilities(&self) -> NodeCapabilities {
128 self.active_capabilities
129 .last()
130 .copied()
131 .unwrap_or_else(NodeCapabilities::empty)
132 }
133}
134
135impl ModifierNodeContext for BasicModifierNodeContext {
136 fn invalidate(&mut self, kind: InvalidationKind) {
137 self.push_invalidation(kind);
138 }
139
140 fn request_update(&mut self) {
141 self.update_requested = true;
142 }
143
144 fn push_active_capabilities(&mut self, capabilities: NodeCapabilities) {
145 self.active_capabilities.push(capabilities);
146 }
147
148 fn pop_active_capabilities(&mut self) {
149 self.active_capabilities.pop();
150 }
151
152 fn node_id(&self) -> Option<cranpose_core::NodeId> {
153 self.node_id
154 }
155}
156
157const MAX_DELEGATE_DEPTH: usize = 3;
161
162#[derive(Copy, Clone, Debug, PartialEq, Eq)]
163pub(crate) struct NodePath {
164 entry: usize,
165 delegate_buf: [u8; MAX_DELEGATE_DEPTH],
166 delegate_len: u8,
167}
168
169impl NodePath {
170 #[inline]
171 fn root(entry: usize) -> Self {
172 Self {
173 entry,
174 delegate_buf: [0; MAX_DELEGATE_DEPTH],
175 delegate_len: 0,
176 }
177 }
178
179 #[inline]
180 fn from_slice(entry: usize, path: &[usize]) -> Self {
181 debug_assert!(
182 path.len() <= MAX_DELEGATE_DEPTH,
183 "delegate depth {} exceeds MAX_DELEGATE_DEPTH {}",
184 path.len(),
185 MAX_DELEGATE_DEPTH
186 );
187 debug_assert!(
188 path.iter().all(|&i| i <= u8::MAX as usize),
189 "delegate index exceeds u8 range"
190 );
191 let mut delegate_buf = [0u8; MAX_DELEGATE_DEPTH];
192 for (i, &v) in path.iter().enumerate().take(MAX_DELEGATE_DEPTH) {
193 delegate_buf[i] = v as u8;
194 }
195 Self {
196 entry,
197 delegate_buf,
198 delegate_len: path.len().min(MAX_DELEGATE_DEPTH) as u8,
199 }
200 }
201
202 #[inline]
203 fn entry(&self) -> usize {
204 self.entry
205 }
206
207 #[inline]
208 fn delegates(&self) -> &[u8] {
209 &self.delegate_buf[..self.delegate_len as usize]
210 }
211}
212
213#[derive(Copy, Clone, Debug, PartialEq, Eq)]
214pub(crate) enum NodeLink {
215 Head,
216 Tail,
217 Entry(NodePath),
218}
219
220#[derive(Debug)]
226pub struct NodeState {
227 aggregate_child_capabilities: Cell<NodeCapabilities>,
228 capabilities: Cell<NodeCapabilities>,
229 parent: RefCell<Option<NodeLink>>,
230 child: RefCell<Option<NodeLink>>,
231 attached: Cell<bool>,
232 is_sentinel: bool,
233}
234
235impl Default for NodeState {
236 fn default() -> Self {
237 Self::new()
238 }
239}
240
241impl NodeState {
242 pub const fn new() -> Self {
243 Self {
244 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
245 capabilities: Cell::new(NodeCapabilities::empty()),
246 parent: RefCell::new(None),
247 child: RefCell::new(None),
248 attached: Cell::new(false),
249 is_sentinel: false,
250 }
251 }
252
253 pub const fn sentinel() -> Self {
254 Self {
255 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
256 capabilities: Cell::new(NodeCapabilities::empty()),
257 parent: RefCell::new(None),
258 child: RefCell::new(None),
259 attached: Cell::new(true),
260 is_sentinel: true,
261 }
262 }
263
264 pub fn set_capabilities(&self, capabilities: NodeCapabilities) {
265 self.capabilities.set(capabilities);
266 }
267
268 #[inline]
269 pub fn capabilities(&self) -> NodeCapabilities {
270 self.capabilities.get()
271 }
272
273 pub fn set_aggregate_child_capabilities(&self, capabilities: NodeCapabilities) {
274 self.aggregate_child_capabilities.set(capabilities);
275 }
276
277 #[inline]
278 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
279 self.aggregate_child_capabilities.get()
280 }
281
282 pub(crate) fn set_parent_link(&self, parent: Option<NodeLink>) {
283 *self.parent.borrow_mut() = parent;
284 }
285
286 #[inline]
287 pub(crate) fn parent_link(&self) -> Option<NodeLink> {
288 *self.parent.borrow()
289 }
290
291 pub(crate) fn set_child_link(&self, child: Option<NodeLink>) {
292 *self.child.borrow_mut() = child;
293 }
294
295 #[inline]
296 pub(crate) fn child_link(&self) -> Option<NodeLink> {
297 *self.child.borrow()
298 }
299
300 pub fn set_attached(&self, attached: bool) {
301 self.attached.set(attached);
302 }
303
304 pub fn is_attached(&self) -> bool {
305 self.attached.get()
306 }
307
308 pub fn is_sentinel(&self) -> bool {
309 self.is_sentinel
310 }
311}
312
313pub trait DelegatableNode {
315 fn node_state(&self) -> &NodeState;
316 fn aggregate_child_capabilities(&self) -> NodeCapabilities {
317 self.node_state().aggregate_child_capabilities()
318 }
319}
320
321pub trait ModifierNode: Any + DelegatableNode {
379 fn on_attach(&mut self, _context: &mut dyn ModifierNodeContext) {}
380
381 fn on_detach(&mut self) {}
382
383 fn on_reset(&mut self) {}
384
385 fn as_draw_node(&self) -> Option<&dyn DrawModifierNode> {
387 None
388 }
389
390 fn as_draw_node_mut(&mut self) -> Option<&mut dyn DrawModifierNode> {
392 None
393 }
394
395 fn as_pointer_input_node(&self) -> Option<&dyn PointerInputNode> {
397 None
398 }
399
400 fn as_pointer_input_node_mut(&mut self) -> Option<&mut dyn PointerInputNode> {
402 None
403 }
404
405 fn as_semantics_node(&self) -> Option<&dyn SemanticsNode> {
407 None
408 }
409
410 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn SemanticsNode> {
412 None
413 }
414
415 fn as_focus_node(&self) -> Option<&dyn FocusNode> {
417 None
418 }
419
420 fn as_focus_node_mut(&mut self) -> Option<&mut dyn FocusNode> {
422 None
423 }
424
425 fn as_layout_node(&self) -> Option<&dyn LayoutModifierNode> {
427 None
428 }
429
430 fn as_layout_node_mut(&mut self) -> Option<&mut dyn LayoutModifierNode> {
432 None
433 }
434
435 fn for_each_delegate<'b>(&'b self, _visitor: &mut dyn FnMut(&'b dyn ModifierNode)) {}
437
438 fn for_each_delegate_mut<'b>(&'b mut self, _visitor: &mut dyn FnMut(&'b mut dyn ModifierNode)) {
440 }
441}
442
443pub trait LayoutModifierNode: ModifierNode {
449 fn measure(
471 &self,
472 _context: &mut dyn ModifierNodeContext,
473 measurable: &dyn Measurable,
474 constraints: Constraints,
475 ) -> cranpose_ui_layout::LayoutModifierMeasureResult {
476 let placeable = measurable.measure(constraints);
477 cranpose_ui_layout::LayoutModifierMeasureResult::with_size(Size {
478 width: placeable.width(),
479 height: placeable.height(),
480 })
481 }
482
483 fn min_intrinsic_width(&self, _measurable: &dyn Measurable, _height: f32) -> f32 {
485 0.0
486 }
487
488 fn max_intrinsic_width(&self, _measurable: &dyn Measurable, _height: f32) -> f32 {
490 0.0
491 }
492
493 fn min_intrinsic_height(&self, _measurable: &dyn Measurable, _width: f32) -> f32 {
495 0.0
496 }
497
498 fn max_intrinsic_height(&self, _measurable: &dyn Measurable, _width: f32) -> f32 {
500 0.0
501 }
502}
503
504pub trait DrawModifierNode: ModifierNode {
512 fn draw(&self, _draw_scope: &mut dyn DrawScope) {}
521
522 fn create_draw_closure(&self) -> Option<NodeDrawClosure> {
533 None
534 }
535
536 fn create_behind_draw_closure(&self) -> Option<NodeDrawClosure> {
541 None
542 }
543}
544
545pub type NodeDrawClosure = Rc<dyn Fn(&mut cranpose_ui_graphics::DrawScopeDefault)>;
550
551pub trait PointerInputNode: ModifierNode {
557 fn on_pointer_event(
560 &mut self,
561 _context: &mut dyn ModifierNodeContext,
562 _event: &PointerEvent,
563 ) -> bool {
564 false
565 }
566
567 fn hit_test(&self, _x: f32, _y: f32) -> bool {
570 true
571 }
572
573 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
575 None
576 }
577
578 fn layout_size_sink(&self) -> Option<Rc<Cell<Size>>> {
591 None
592 }
593}
594
595pub trait SemanticsNode: ModifierNode {
601 fn merge_semantics(&self, _config: &mut SemanticsConfiguration) {}
603}
604
605#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
610pub enum FocusState {
611 Active,
613 ActiveParent,
615 Captured,
619 #[default]
622 Inactive,
623}
624
625impl FocusState {
626 pub fn is_focused(self) -> bool {
628 matches!(self, FocusState::Active | FocusState::Captured)
629 }
630
631 pub fn has_focus(self) -> bool {
633 matches!(
634 self,
635 FocusState::Active | FocusState::ActiveParent | FocusState::Captured
636 )
637 }
638
639 pub fn is_captured(self) -> bool {
641 matches!(self, FocusState::Captured)
642 }
643}
644
645pub trait FocusNode: ModifierNode {
650 fn focus_state(&self) -> FocusState;
652
653 fn on_focus_changed(&mut self, _context: &mut dyn ModifierNodeContext, _state: FocusState) {}
655}
656
657#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
668pub enum SemanticsWidgetRole {
669 Button,
670 Checkbox,
671 Switch,
672 RadioButton,
673 Tab,
674 Image,
675 DropdownList,
678 ValuePicker,
681 Header,
686 Dialog,
690 Link,
693 SearchField,
696 ProgressBar,
699 ToggleButton,
702 Alert,
705 Toolbar,
708 Menu,
710 MenuItem,
712 TabBar,
715 List,
717 ListItem,
719}
720
721#[derive(Clone, Copy, Debug, PartialEq)]
729pub struct ProgressBarRangeInfo {
730 pub current: f32,
731 pub start: f32,
732 pub end: f32,
733 pub steps: u32,
736}
737
738impl ProgressBarRangeInfo {
739 pub fn new(current: f32, start: f32, end: f32, steps: u32) -> Self {
740 Self {
741 current,
742 start,
743 end,
744 steps,
745 }
746 }
747
748 pub fn fraction(&self) -> f32 {
750 let span = self.end - self.start;
751 if span.abs() < f32::EPSILON {
752 return 0.0;
753 }
754 ((self.current - self.start) / span).clamp(0.0, 1.0)
755 }
756
757 pub fn step(&self) -> f32 {
760 let span = self.end - self.start;
761 if self.steps == 0 {
762 span / 10.0
763 } else {
764 span / (self.steps as f32 + 1.0)
765 }
766 }
767}
768
769#[derive(Clone, Copy, Debug, PartialEq, Eq)]
774pub struct CollectionInfo {
775 pub rows: usize,
776 pub columns: usize,
777}
778
779#[derive(Clone, Copy, Debug, PartialEq)]
785pub struct ScrollAxisRange {
786 pub value: f32,
787 pub max_value: f32,
788 pub reverse: bool,
789}
790
791impl ScrollAxisRange {
792 pub fn new(value: f32, max_value: f32, reverse: bool) -> Self {
793 Self {
794 value,
795 max_value,
796 reverse,
797 }
798 }
799
800 pub fn can_scroll_forward(&self) -> bool {
801 self.value < self.max_value
802 }
803
804 pub fn can_scroll_backward(&self) -> bool {
805 self.value > 0.0
806 }
807}
808
809#[derive(Clone)]
815pub struct SemanticsScrollBy {
816 handler: Rc<dyn Fn(f32, f32) -> bool>,
817}
818
819impl SemanticsScrollBy {
820 pub fn new(handler: impl Fn(f32, f32) -> bool + 'static) -> Self {
821 Self {
822 handler: Rc::new(handler),
823 }
824 }
825
826 pub fn invoke(&self, dx: f32, dy: f32) -> bool {
827 (self.handler)(dx, dy)
828 }
829}
830
831impl fmt::Debug for SemanticsScrollBy {
832 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
833 f.debug_struct("SemanticsScrollBy").finish_non_exhaustive()
834 }
835}
836
837impl PartialEq for SemanticsScrollBy {
840 fn eq(&self, _other: &Self) -> bool {
841 true
842 }
843}
844
845impl Eq for SemanticsScrollBy {}
846
847#[derive(Clone)]
853pub struct SemanticsScrollToIndex {
854 handler: Rc<dyn Fn(usize) -> bool>,
855}
856
857impl SemanticsScrollToIndex {
858 pub fn new(handler: impl Fn(usize) -> bool + 'static) -> Self {
859 Self {
860 handler: Rc::new(handler),
861 }
862 }
863
864 pub fn invoke(&self, index: usize) -> bool {
865 (self.handler)(index)
866 }
867}
868
869impl fmt::Debug for SemanticsScrollToIndex {
870 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
871 f.debug_struct("SemanticsScrollToIndex")
872 .finish_non_exhaustive()
873 }
874}
875
876impl PartialEq for SemanticsScrollToIndex {
879 fn eq(&self, _other: &Self) -> bool {
880 true
881 }
882}
883
884impl Eq for SemanticsScrollToIndex {}
885
886#[derive(Clone)]
892pub struct SemanticsSetProgress {
893 handler: Rc<dyn Fn(f32) -> bool>,
894}
895
896impl SemanticsSetProgress {
897 pub fn new(handler: impl Fn(f32) -> bool + 'static) -> Self {
898 Self {
899 handler: Rc::new(handler),
900 }
901 }
902
903 pub fn invoke(&self, value: f32) -> bool {
904 (self.handler)(value)
905 }
906}
907
908impl fmt::Debug for SemanticsSetProgress {
909 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
910 f.debug_struct("SemanticsSetProgress")
911 .finish_non_exhaustive()
912 }
913}
914
915#[derive(Clone)]
919pub struct SemanticsSetText(Rc<dyn Fn(&str) -> bool>);
920
921impl SemanticsSetText {
922 pub fn new(handler: impl Fn(&str) -> bool + 'static) -> Self {
923 Self(Rc::new(handler))
924 }
925
926 pub fn invoke(&self, text: &str) -> bool {
927 (self.0)(text)
928 }
929}
930
931impl fmt::Debug for SemanticsSetText {
932 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
933 f.write_str("SemanticsSetText")
934 }
935}
936
937#[derive(Clone)]
943pub struct SemanticsSetSelection(Rc<dyn Fn(usize, usize) -> bool>);
944
945impl SemanticsSetSelection {
946 pub fn new(handler: impl Fn(usize, usize) -> bool + 'static) -> Self {
947 Self(Rc::new(handler))
948 }
949
950 pub fn invoke(&self, anchor: usize, focus: usize) -> bool {
951 (self.0)(anchor, focus)
952 }
953}
954
955impl fmt::Debug for SemanticsSetSelection {
956 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
957 f.write_str("SemanticsSetSelection")
958 }
959}
960
961#[derive(Clone)]
964pub struct SemanticsExpand(Rc<dyn Fn() -> bool>);
965
966impl SemanticsExpand {
967 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
968 Self(Rc::new(handler))
969 }
970
971 pub fn invoke(&self) -> bool {
972 (self.0)()
973 }
974}
975
976impl fmt::Debug for SemanticsExpand {
977 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
978 f.write_str("SemanticsExpand")
979 }
980}
981
982#[derive(Clone)]
986pub struct SemanticsLongClick(Rc<dyn Fn() -> bool>);
987
988impl SemanticsLongClick {
989 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
990 Self(Rc::new(handler))
991 }
992
993 pub fn invoke(&self) -> bool {
994 (self.0)()
995 }
996}
997
998impl fmt::Debug for SemanticsLongClick {
999 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1000 f.write_str("SemanticsLongClick")
1001 }
1002}
1003
1004impl PartialEq for SemanticsLongClick {
1005 fn eq(&self, _other: &Self) -> bool {
1006 true
1007 }
1008}
1009
1010impl PartialEq for SemanticsExpand {
1011 fn eq(&self, _other: &Self) -> bool {
1012 true
1013 }
1014}
1015
1016#[derive(Clone)]
1020pub struct SemanticsDismiss(Rc<dyn Fn() -> bool>);
1021
1022impl SemanticsDismiss {
1023 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1024 Self(Rc::new(handler))
1025 }
1026
1027 pub fn invoke(&self) -> bool {
1028 (self.0)()
1029 }
1030}
1031
1032impl fmt::Debug for SemanticsDismiss {
1033 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1034 f.write_str("SemanticsDismiss")
1035 }
1036}
1037
1038impl PartialEq for SemanticsDismiss {
1039 fn eq(&self, _other: &Self) -> bool {
1040 true
1041 }
1042}
1043
1044impl PartialEq for SemanticsSetText {
1045 fn eq(&self, _other: &Self) -> bool {
1046 true
1047 }
1048}
1049
1050impl PartialEq for SemanticsSetSelection {
1051 fn eq(&self, _other: &Self) -> bool {
1052 true
1053 }
1054}
1055
1056#[derive(Clone)]
1062pub struct SemanticsMagicTap(Rc<dyn Fn() -> bool>);
1063
1064impl SemanticsMagicTap {
1065 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1066 Self(Rc::new(handler))
1067 }
1068
1069 pub fn invoke(&self) -> bool {
1070 (self.0)()
1071 }
1072}
1073
1074impl fmt::Debug for SemanticsMagicTap {
1075 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1076 f.write_str("SemanticsMagicTap")
1077 }
1078}
1079
1080impl PartialEq for SemanticsMagicTap {
1081 fn eq(&self, _other: &Self) -> bool {
1082 true
1083 }
1084}
1085
1086impl PartialEq for SemanticsSetProgress {
1091 fn eq(&self, _other: &Self) -> bool {
1092 true
1093 }
1094}
1095
1096impl Eq for SemanticsSetProgress {}
1097
1098#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1105pub enum LiveRegionMode {
1106 Polite,
1108 Assertive,
1111}
1112
1113#[derive(Clone)]
1120pub struct SemanticsCustomAction {
1121 pub label: String,
1123 handler: Rc<dyn Fn()>,
1124}
1125
1126impl SemanticsCustomAction {
1127 pub fn new(label: impl Into<String>, handler: impl Fn() + 'static) -> Self {
1128 Self {
1129 label: label.into(),
1130 handler: Rc::new(handler),
1131 }
1132 }
1133
1134 pub fn invoke(&self) {
1135 (self.handler)();
1136 }
1137}
1138
1139impl fmt::Debug for SemanticsCustomAction {
1140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1141 f.debug_struct("SemanticsCustomAction")
1142 .field("label", &self.label)
1143 .finish_non_exhaustive()
1144 }
1145}
1146
1147impl PartialEq for SemanticsCustomAction {
1157 fn eq(&self, other: &Self) -> bool {
1158 self.label == other.label
1159 }
1160}
1161
1162impl Eq for SemanticsCustomAction {}
1163
1164#[derive(Clone, Debug, PartialEq)]
1179pub struct CanvasSemanticsNode {
1180 pub key: u64,
1187 pub bounds: cranpose_ui_graphics::Rect,
1189 pub label: String,
1190 pub role: Option<SemanticsWidgetRole>,
1191 pub state_description: Option<String>,
1195 pub on_click_label: Option<String>,
1198 pub clickable: bool,
1199 pub selected: Option<bool>,
1201 pub toggled: Option<bool>,
1203 pub enabled: bool,
1204 pub custom_actions: Vec<SemanticsCustomAction>,
1205}
1206
1207impl Default for CanvasSemanticsNode {
1208 fn default() -> Self {
1209 Self {
1210 key: 0,
1211 bounds: cranpose_ui_graphics::Rect {
1212 x: 0.0,
1213 y: 0.0,
1214 width: 0.0,
1215 height: 0.0,
1216 },
1217 label: String::new(),
1218 role: None,
1219 state_description: None,
1220 on_click_label: None,
1221 clickable: false,
1222 selected: None,
1223 toggled: None,
1224 enabled: true,
1225 custom_actions: Vec::new(),
1226 }
1227 }
1228}
1229
1230impl CanvasSemanticsNode {
1231 pub fn control(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1233 Self {
1234 key,
1235 bounds,
1236 label: label.into(),
1237 clickable: true,
1238 ..Self::default()
1239 }
1240 }
1241
1242 pub fn text(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1244 Self {
1245 key,
1246 bounds,
1247 label: label.into(),
1248 ..Self::default()
1249 }
1250 }
1251
1252 pub fn with_role(mut self, role: SemanticsWidgetRole) -> Self {
1253 self.role = Some(role);
1254 self
1255 }
1256
1257 pub fn with_state_description(mut self, state: impl Into<String>) -> Self {
1258 self.state_description = Some(state.into());
1259 self
1260 }
1261
1262 pub fn with_click_label(mut self, label: impl Into<String>) -> Self {
1263 self.on_click_label = Some(label.into());
1264 self.clickable = true;
1265 self
1266 }
1267
1268 pub fn with_selected(mut self, selected: bool) -> Self {
1269 self.selected = Some(selected);
1270 self
1271 }
1272
1273 pub fn with_toggled(mut self, toggled: bool) -> Self {
1274 self.toggled = Some(toggled);
1275 self
1276 }
1277
1278 pub fn with_enabled(mut self, enabled: bool) -> Self {
1279 self.enabled = enabled;
1280 self
1281 }
1282
1283 pub fn with_custom_action(mut self, action: SemanticsCustomAction) -> Self {
1284 self.custom_actions.push(action);
1285 self
1286 }
1287}
1288
1289#[derive(Clone, Debug, PartialEq)]
1291pub struct SemanticsConfiguration {
1292 pub content_description: Option<String>,
1293 pub state_description: Option<String>,
1295 pub on_click_label: Option<String>,
1297 pub on_long_click: Option<SemanticsLongClick>,
1300 pub on_long_click_label: Option<String>,
1303 pub on_magic_tap: Option<SemanticsMagicTap>,
1307 pub on_magic_tap_label: Option<String>,
1310 pub input_labels: Vec<String>,
1314 pub language: Option<String>,
1318 pub role: Option<SemanticsWidgetRole>,
1320 pub selected: Option<bool>,
1321 pub toggled: Option<bool>,
1322 pub enabled: bool,
1323 pub is_clickable: bool,
1324 pub is_editable_text: bool,
1325 pub text: Option<String>,
1328 pub text_selection: Option<crate::text::TextRange>,
1329 pub custom_actions: Vec<SemanticsCustomAction>,
1330 pub canvas_children: Vec<CanvasSemanticsNode>,
1333 pub is_modal: bool,
1336 pub hidden: bool,
1340 pub merge_descendants: bool,
1344 pub selectable_group: bool,
1348 pub pane_title: Option<String>,
1351 pub error: Option<String>,
1354 pub password: bool,
1357 pub traversal_index: f32,
1361 pub live_region: Option<LiveRegionMode>,
1364 pub progress: Option<ProgressBarRangeInfo>,
1367 pub set_progress: Option<SemanticsSetProgress>,
1370 pub set_text: Option<SemanticsSetText>,
1373 pub set_selection: Option<SemanticsSetSelection>,
1376 pub expand: Option<SemanticsExpand>,
1379 pub dismiss: Option<SemanticsDismiss>,
1383 pub collapse: Option<SemanticsExpand>,
1386 pub vertical_scroll: Option<ScrollAxisRange>,
1389 pub horizontal_scroll: Option<ScrollAxisRange>,
1392 pub scroll_by: Option<SemanticsScrollBy>,
1395 pub scroll_to_index: Option<SemanticsScrollToIndex>,
1399 pub collection: Option<CollectionInfo>,
1401}
1402
1403impl Default for SemanticsConfiguration {
1404 fn default() -> Self {
1405 Self {
1406 content_description: None,
1407 state_description: None,
1408 on_click_label: None,
1409 on_long_click: None,
1410 on_long_click_label: None,
1411 on_magic_tap: None,
1412 on_magic_tap_label: None,
1413 input_labels: Vec::new(),
1414 language: None,
1415 role: None,
1416 selected: None,
1417 toggled: None,
1418 enabled: true,
1419 is_clickable: false,
1420 is_editable_text: false,
1421 text: None,
1422 text_selection: None,
1423 custom_actions: Vec::new(),
1424 canvas_children: Vec::new(),
1425 is_modal: false,
1426 hidden: false,
1427 merge_descendants: false,
1428 selectable_group: false,
1429 pane_title: None,
1430 error: None,
1431 password: false,
1432 traversal_index: 0.0,
1433 live_region: None,
1434 progress: None,
1435 set_progress: None,
1436 set_text: None,
1437 set_selection: None,
1438 expand: None,
1439 dismiss: None,
1440 collapse: None,
1441 vertical_scroll: None,
1442 horizontal_scroll: None,
1443 scroll_by: None,
1444 scroll_to_index: None,
1445 collection: None,
1446 }
1447 }
1448}
1449
1450pub type SemanticsSpec = SemanticsConfiguration;
1459
1460impl SemanticsConfiguration {
1461 pub fn new() -> Self {
1464 Self::default()
1465 }
1466
1467 pub fn content_description(mut self, name: impl Into<String>) -> Self {
1470 self.content_description = Some(name.into());
1471 self
1472 }
1473
1474 pub fn state_description(mut self, state: impl Into<String>) -> Self {
1477 self.state_description = Some(state.into());
1478 self
1479 }
1480
1481 pub fn clickable(mut self) -> Self {
1483 self.is_clickable = true;
1484 self
1485 }
1486
1487 pub fn on_long_click(
1491 mut self,
1492 label: impl Into<String>,
1493 action: impl Fn() -> bool + 'static,
1494 ) -> Self {
1495 self.on_long_click_label = Some(label.into());
1496 self.on_long_click = Some(SemanticsLongClick::new(action));
1497 self
1498 }
1499
1500 pub fn on_magic_tap(
1504 mut self,
1505 label: impl Into<String>,
1506 action: impl Fn() -> bool + 'static,
1507 ) -> Self {
1508 self.on_magic_tap_label = Some(label.into());
1509 self.on_magic_tap = Some(SemanticsMagicTap::new(action));
1510 self
1511 }
1512
1513 pub fn input_labels<S: Into<String>>(mut self, labels: impl IntoIterator<Item = S>) -> Self {
1516 self.input_labels = labels.into_iter().map(Into::into).collect();
1517 self
1518 }
1519
1520 pub fn language(mut self, tag: impl Into<String>) -> Self {
1523 self.language = Some(tag.into());
1524 self
1525 }
1526
1527 pub fn toggled(mut self, toggled: bool) -> Self {
1529 self.toggled = Some(toggled);
1530 self
1531 }
1532
1533 pub fn selected(mut self, selected: bool) -> Self {
1536 self.selected = Some(selected);
1537 self
1538 }
1539
1540 pub fn role(mut self, role: SemanticsWidgetRole) -> Self {
1542 self.role = Some(role);
1543 self
1544 }
1545
1546 pub fn heading(self) -> Self {
1549 self.role(SemanticsWidgetRole::Header)
1550 }
1551
1552 pub fn error(mut self, message: impl Into<String>) -> Self {
1554 self.error = Some(message.into());
1555 self
1556 }
1557
1558 pub fn password(mut self) -> Self {
1560 self.password = true;
1561 self
1562 }
1563
1564 pub fn pane_title(mut self, title: impl Into<String>) -> Self {
1567 self.pane_title = Some(title.into());
1568 self
1569 }
1570
1571 pub fn traversal_index(mut self, index: f32) -> Self {
1574 self.traversal_index = index;
1575 self
1576 }
1577
1578 pub fn hidden(mut self) -> Self {
1581 self.hidden = true;
1582 self
1583 }
1584
1585 pub fn merge_descendants(mut self) -> Self {
1588 self.merge_descendants = true;
1589 self
1590 }
1591
1592 pub fn selectable_group(mut self) -> Self {
1595 self.selectable_group = true;
1596 self
1597 }
1598
1599 pub fn live_region(mut self, mode: LiveRegionMode) -> Self {
1602 self.live_region = Some(mode);
1603 self
1604 }
1605 pub fn merge(&mut self, other: &SemanticsConfiguration) {
1606 if let Some(description) = &other.content_description {
1607 self.content_description = Some(description.clone());
1608 }
1609 if let Some(state) = &other.state_description {
1610 self.state_description = Some(state.clone());
1611 }
1612 if let Some(label) = &other.on_click_label {
1613 self.on_click_label = Some(label.clone());
1614 }
1615 if let Some(label) = &other.on_long_click_label {
1616 self.on_long_click_label = Some(label.clone());
1617 }
1618 if let Some(label) = &other.on_magic_tap_label {
1619 self.on_magic_tap_label = Some(label.clone());
1620 }
1621 if !other.input_labels.is_empty() {
1622 self.input_labels.clone_from(&other.input_labels);
1623 }
1624 if let Some(language) = &other.language {
1625 self.language = Some(language.clone());
1626 }
1627 if let Some(role) = other.role {
1628 self.role = Some(role);
1629 }
1630 if let Some(selected) = other.selected {
1631 self.selected = Some(selected);
1632 }
1633 if let Some(toggled) = other.toggled {
1634 self.toggled = Some(toggled);
1635 }
1636 self.enabled &= other.enabled;
1637 self.is_clickable |= other.is_clickable;
1638 self.is_editable_text |= other.is_editable_text;
1639 if let Some(text) = &other.text {
1640 self.text = Some(text.clone());
1641 }
1642 self.is_modal |= other.is_modal;
1643 self.hidden |= other.hidden;
1644 self.merge_descendants |= other.merge_descendants;
1645 self.selectable_group |= other.selectable_group;
1646 self.password |= other.password;
1647 if other.traversal_index != 0.0 {
1648 self.traversal_index = other.traversal_index;
1649 }
1650 if let Some(live_region) = other.live_region {
1651 self.live_region = Some(live_region);
1652 }
1653 self.merge_words(other);
1654 self.merge_actions(other);
1655 self.merge_ranges(other);
1656 }
1657
1658 fn merge_words(&mut self, other: &SemanticsConfiguration) {
1661 if let Some(title) = &other.pane_title {
1662 self.pane_title = Some(title.clone());
1663 }
1664 if let Some(error) = &other.error {
1665 self.error = Some(error.clone());
1666 }
1667 }
1668
1669 fn merge_actions(&mut self, other: &SemanticsConfiguration) {
1672 self.custom_actions
1673 .extend(other.custom_actions.iter().cloned());
1674 self.canvas_children
1675 .extend(other.canvas_children.iter().cloned());
1676 if let Some(set_progress) = &other.set_progress {
1677 self.set_progress = Some(set_progress.clone());
1678 }
1679 if let Some(set_text) = &other.set_text {
1680 self.set_text = Some(set_text.clone());
1681 }
1682 if let Some(set_selection) = &other.set_selection {
1683 self.set_selection = Some(set_selection.clone());
1684 }
1685 if let Some(expand) = &other.expand {
1686 self.expand = Some(expand.clone());
1687 }
1688 if let Some(collapse) = &other.collapse {
1689 self.collapse = Some(collapse.clone());
1690 }
1691 if let Some(dismiss) = &other.dismiss {
1692 self.dismiss = Some(dismiss.clone());
1693 }
1694 if let Some(long_click) = &other.on_long_click {
1695 self.on_long_click = Some(long_click.clone());
1696 }
1697 if let Some(magic_tap) = &other.on_magic_tap {
1698 self.on_magic_tap = Some(magic_tap.clone());
1699 }
1700 if let Some(scroll_by) = &other.scroll_by {
1701 self.scroll_by = Some(scroll_by.clone());
1702 }
1703 if let Some(scroll_to_index) = &other.scroll_to_index {
1704 self.scroll_to_index = Some(scroll_to_index.clone());
1705 }
1706 }
1707
1708 fn merge_ranges(&mut self, other: &SemanticsConfiguration) {
1711 if let Some(selection) = other.text_selection {
1712 self.text_selection = Some(selection);
1713 }
1714 if let Some(progress) = other.progress {
1715 self.progress = Some(progress);
1716 }
1717 if let Some(range) = other.vertical_scroll {
1718 self.vertical_scroll = Some(range);
1719 }
1720 if let Some(range) = other.horizontal_scroll {
1721 self.horizontal_scroll = Some(range);
1722 }
1723 if let Some(collection) = other.collection {
1724 self.collection = Some(collection);
1725 }
1726 }
1727
1728 pub fn is_activatable(&self) -> bool {
1731 self.is_clickable || self.on_click_label.is_some()
1732 }
1733}
1734
1735impl fmt::Debug for dyn ModifierNode {
1736 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1737 f.debug_struct("ModifierNode").finish_non_exhaustive()
1738 }
1739}
1740
1741impl dyn ModifierNode {
1742 pub fn as_any(&self) -> &dyn Any {
1743 self
1744 }
1745
1746 pub fn as_any_mut(&mut self) -> &mut dyn Any {
1747 self
1748 }
1749}
1750
1751pub trait ModifierNodeElement: fmt::Debug + Hash + PartialEq + 'static {
1754 type Node: ModifierNode;
1755
1756 fn create(&self) -> Self::Node;
1758
1759 fn update(&self, node: &mut Self::Node);
1761
1762 fn key(&self) -> Option<u64> {
1764 None
1765 }
1766
1767 fn inspector_name(&self) -> &'static str {
1769 type_name::<Self>()
1770 }
1771
1772 fn inspector_properties(&self, _inspector: &mut dyn FnMut(&'static str, String)) {}
1774
1775 fn capabilities(&self) -> NodeCapabilities {
1778 NodeCapabilities::default()
1779 }
1780
1781 fn always_update(&self) -> bool {
1787 false
1788 }
1789
1790 fn auto_invalidate_on_update(&self) -> bool {
1793 true
1794 }
1795
1796 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
1803 None
1804 }
1805}
1806
1807#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1809pub struct NodeCapabilities(u32);
1810
1811impl NodeCapabilities {
1812 pub const NONE: Self = Self(0);
1814 pub const LAYOUT: Self = Self(1 << 0);
1816 pub const DRAW: Self = Self(1 << 1);
1818 pub const POINTER_INPUT: Self = Self(1 << 2);
1820 pub const SEMANTICS: Self = Self(1 << 3);
1822 pub const MODIFIER_LOCALS: Self = Self(1 << 4);
1824 pub const FOCUS: Self = Self(1 << 5);
1826
1827 pub const fn empty() -> Self {
1829 Self::NONE
1830 }
1831
1832 pub const fn contains(self, other: Self) -> bool {
1834 (self.0 & other.0) == other.0
1835 }
1836
1837 pub const fn intersects(self, other: Self) -> bool {
1839 (self.0 & other.0) != 0
1840 }
1841
1842 pub fn insert(&mut self, other: Self) {
1844 self.0 |= other.0;
1845 }
1846
1847 pub const fn bits(self) -> u32 {
1849 self.0
1850 }
1851
1852 pub const fn is_empty(self) -> bool {
1854 self.0 == 0
1855 }
1856
1857 pub const fn for_invalidation(kind: InvalidationKind) -> Self {
1859 match kind {
1860 InvalidationKind::Layout => Self::LAYOUT,
1861 InvalidationKind::Draw => Self::DRAW,
1862 InvalidationKind::PointerInput => Self::POINTER_INPUT,
1863 InvalidationKind::Semantics => Self::SEMANTICS,
1864 InvalidationKind::Focus => Self::FOCUS,
1865 }
1866 }
1867}
1868
1869impl Default for NodeCapabilities {
1870 fn default() -> Self {
1871 Self::NONE
1872 }
1873}
1874
1875impl fmt::Debug for NodeCapabilities {
1876 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1877 f.debug_struct("NodeCapabilities")
1878 .field("layout", &self.contains(Self::LAYOUT))
1879 .field("draw", &self.contains(Self::DRAW))
1880 .field("pointer_input", &self.contains(Self::POINTER_INPUT))
1881 .field("semantics", &self.contains(Self::SEMANTICS))
1882 .field("modifier_locals", &self.contains(Self::MODIFIER_LOCALS))
1883 .field("focus", &self.contains(Self::FOCUS))
1884 .finish()
1885 }
1886}
1887
1888impl BitOr for NodeCapabilities {
1889 type Output = Self;
1890
1891 fn bitor(self, rhs: Self) -> Self::Output {
1892 Self(self.0 | rhs.0)
1893 }
1894}
1895
1896impl BitOrAssign for NodeCapabilities {
1897 fn bitor_assign(&mut self, rhs: Self) {
1898 self.0 |= rhs.0;
1899 }
1900}
1901
1902#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1904pub struct ModifierInvalidation {
1905 kind: InvalidationKind,
1906 capabilities: NodeCapabilities,
1907}
1908
1909impl ModifierInvalidation {
1910 pub const fn new(kind: InvalidationKind, capabilities: NodeCapabilities) -> Self {
1912 Self { kind, capabilities }
1913 }
1914
1915 pub const fn kind(self) -> InvalidationKind {
1917 self.kind
1918 }
1919
1920 pub const fn capabilities(self) -> NodeCapabilities {
1922 self.capabilities
1923 }
1924}
1925
1926pub trait AnyModifierElement: fmt::Debug {
1928 fn node_type(&self) -> TypeId;
1929
1930 fn element_type(&self) -> TypeId;
1931
1932 fn create_node(&self) -> Box<dyn ModifierNode>;
1933
1934 fn can_update_node(&self, node: &dyn ModifierNode) -> bool;
1935
1936 fn update_node(&self, node: &mut dyn ModifierNode);
1937
1938 fn key(&self) -> Option<u64>;
1939
1940 fn capabilities(&self) -> NodeCapabilities {
1941 NodeCapabilities::default()
1942 }
1943
1944 fn hash_code(&self) -> u64;
1945
1946 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool;
1947
1948 fn inspector_name(&self) -> &'static str;
1949
1950 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String));
1951
1952 fn requires_update(&self) -> bool;
1953
1954 fn auto_invalidates_on_update(&self) -> bool;
1955
1956 fn update_invalidation_kind(&self) -> Option<InvalidationKind>;
1957
1958 fn as_any(&self) -> &dyn Any;
1959}
1960
1961struct TypedModifierElement<E: ModifierNodeElement> {
1962 element: E,
1963 cached_hash: u64,
1964}
1965
1966impl<E: ModifierNodeElement> TypedModifierElement<E> {
1967 fn new(element: E) -> Self {
1968 let mut hasher = default::new();
1969 element.hash(&mut hasher);
1970 Self {
1971 element,
1972 cached_hash: hasher.finish(),
1973 }
1974 }
1975}
1976
1977impl<E> fmt::Debug for TypedModifierElement<E>
1978where
1979 E: ModifierNodeElement,
1980{
1981 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1982 f.debug_struct("TypedModifierElement")
1983 .field("type", &type_name::<E>())
1984 .finish()
1985 }
1986}
1987
1988impl<E> AnyModifierElement for TypedModifierElement<E>
1989where
1990 E: ModifierNodeElement,
1991{
1992 fn node_type(&self) -> TypeId {
1993 TypeId::of::<E::Node>()
1994 }
1995
1996 fn element_type(&self) -> TypeId {
1997 TypeId::of::<E>()
1998 }
1999
2000 fn create_node(&self) -> Box<dyn ModifierNode> {
2001 Box::new(self.element.create())
2002 }
2003
2004 fn can_update_node(&self, node: &dyn ModifierNode) -> bool {
2005 node.as_any().is::<E::Node>()
2006 }
2007
2008 fn update_node(&self, node: &mut dyn ModifierNode) {
2009 if let Some(typed) = node.as_any_mut().downcast_mut::<E::Node>() {
2010 self.element.update(typed);
2011 }
2012 }
2013
2014 fn key(&self) -> Option<u64> {
2015 self.element.key()
2016 }
2017
2018 fn capabilities(&self) -> NodeCapabilities {
2019 self.element.capabilities()
2020 }
2021
2022 fn hash_code(&self) -> u64 {
2023 self.cached_hash
2024 }
2025
2026 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool {
2027 other
2028 .as_any()
2029 .downcast_ref::<Self>()
2030 .map(|typed| typed.element == self.element)
2031 .unwrap_or(false)
2032 }
2033
2034 fn inspector_name(&self) -> &'static str {
2035 self.element.inspector_name()
2036 }
2037
2038 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String)) {
2039 self.element.inspector_properties(visitor);
2040 }
2041
2042 fn requires_update(&self) -> bool {
2043 self.element.always_update()
2044 }
2045
2046 fn auto_invalidates_on_update(&self) -> bool {
2047 self.element.auto_invalidate_on_update()
2048 }
2049
2050 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
2051 self.element.update_invalidation_kind()
2052 }
2053
2054 fn as_any(&self) -> &dyn Any {
2055 self
2056 }
2057}
2058
2059fn request_update_auto_invalidations(
2060 element: &dyn AnyModifierElement,
2061 context: &mut dyn ModifierNodeContext,
2062 capabilities: NodeCapabilities,
2063) {
2064 if let Some(kind) = element.update_invalidation_kind() {
2065 let capabilities = NodeCapabilities::for_invalidation(kind);
2066 context.push_active_capabilities(capabilities);
2067 context.invalidate(kind);
2068 context.pop_active_capabilities();
2069 } else if element.auto_invalidates_on_update() {
2070 request_auto_invalidations(context, capabilities);
2071 }
2072}
2073
2074pub fn modifier_element<E: ModifierNodeElement>(element: E) -> DynModifierElement {
2077 Rc::new(TypedModifierElement::new(element))
2078}
2079
2080pub type DynModifierElement = Rc<dyn AnyModifierElement>;
2082
2083#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2084enum TraversalDirection {
2085 Forward,
2086 Backward,
2087}
2088
2089pub struct ModifierChainIter<'a> {
2094 chain: &'a ModifierNodeChain,
2095 cursor: usize,
2096 remaining: usize,
2097 direction: TraversalDirection,
2098}
2099
2100impl<'a> ModifierChainIter<'a> {
2101 fn forward(chain: &'a ModifierNodeChain) -> Self {
2102 Self {
2103 chain,
2104 cursor: 0,
2105 remaining: chain.ordered_nodes.len(),
2106 direction: TraversalDirection::Forward,
2107 }
2108 }
2109
2110 fn backward(chain: &'a ModifierNodeChain) -> Self {
2111 let len = chain.ordered_nodes.len();
2112 Self {
2113 chain,
2114 cursor: len.wrapping_sub(1),
2115 remaining: len,
2116 direction: TraversalDirection::Backward,
2117 }
2118 }
2119}
2120
2121impl<'a> Iterator for ModifierChainIter<'a> {
2122 type Item = ModifierChainNodeRef<'a>;
2123
2124 #[inline]
2125 fn next(&mut self) -> Option<Self::Item> {
2126 if self.remaining == 0 {
2127 return None;
2128 }
2129 let (link, caps, agg) = self.chain.ordered_nodes[self.cursor];
2130 let node_ref = self.chain.make_node_ref_with_caps(link, caps, agg);
2131 self.remaining -= 1;
2132 match self.direction {
2133 TraversalDirection::Forward => self.cursor += 1,
2134 TraversalDirection::Backward => self.cursor = self.cursor.wrapping_sub(1),
2135 }
2136 Some(node_ref)
2137 }
2138
2139 #[inline]
2140 fn size_hint(&self) -> (usize, Option<usize>) {
2141 (self.remaining, Some(self.remaining))
2142 }
2143}
2144
2145impl<'a> ExactSizeIterator for ModifierChainIter<'a> {}
2146impl<'a> std::iter::FusedIterator for ModifierChainIter<'a> {}
2147
2148#[derive(Debug)]
2149struct ModifierNodeEntry {
2150 element_type: TypeId,
2151 node_type: TypeId,
2152 key: Option<u64>,
2153 hash_code: u64,
2154 element: DynModifierElement,
2155 node: Rc<RefCell<Box<dyn ModifierNode>>>,
2156 capabilities: NodeCapabilities,
2157}
2158
2159impl ModifierNodeEntry {
2160 fn new(
2161 element_type: TypeId,
2162 node_type: TypeId,
2163 key: Option<u64>,
2164 element: DynModifierElement,
2165 node: Box<dyn ModifierNode>,
2166 hash_code: u64,
2167 capabilities: NodeCapabilities,
2168 ) -> Self {
2169 let node_rc = Rc::new(RefCell::new(node));
2170 let entry = Self {
2171 element_type,
2172 node_type,
2173 key,
2174 hash_code,
2175 element,
2176 node: Rc::clone(&node_rc),
2177 capabilities,
2178 };
2179 entry
2180 .node
2181 .borrow()
2182 .node_state()
2183 .set_capabilities(entry.capabilities);
2184 entry
2185 }
2186}
2187
2188fn visit_node_tree_mut(
2189 node: &mut dyn ModifierNode,
2190 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
2191) {
2192 visitor(node);
2193 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
2194}
2195
2196fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
2197 let mut current = 0usize;
2198 let mut result: Option<&dyn ModifierNode> = None;
2199 node.for_each_delegate(&mut |child| {
2200 if result.is_none() && current == target {
2201 result = Some(child);
2202 }
2203 current += 1;
2204 });
2205 result
2206}
2207
2208fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
2209 let mut current = 0usize;
2210 let mut result: Option<&mut dyn ModifierNode> = None;
2211 node.for_each_delegate_mut(&mut |child| {
2212 if result.is_none() && current == target {
2213 result = Some(child);
2214 }
2215 current += 1;
2216 });
2217 result
2218}
2219
2220fn with_node_context<F, R>(
2221 node: &mut dyn ModifierNode,
2222 context: &mut dyn ModifierNodeContext,
2223 f: F,
2224) -> R
2225where
2226 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
2227{
2228 context.push_active_capabilities(node.node_state().capabilities());
2229 let result = f(node, context);
2230 context.pop_active_capabilities();
2231 result
2232}
2233
2234fn request_auto_invalidations(
2235 context: &mut dyn ModifierNodeContext,
2236 capabilities: NodeCapabilities,
2237) {
2238 if capabilities.is_empty() {
2239 return;
2240 }
2241
2242 context.push_active_capabilities(capabilities);
2243
2244 if capabilities.contains(NodeCapabilities::LAYOUT) {
2245 context.invalidate(InvalidationKind::Layout);
2246 }
2247 if capabilities.contains(NodeCapabilities::DRAW) {
2248 context.invalidate(InvalidationKind::Draw);
2249 }
2250 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
2251 context.invalidate(InvalidationKind::PointerInput);
2252 }
2253 if capabilities.contains(NodeCapabilities::SEMANTICS) {
2254 context.invalidate(InvalidationKind::Semantics);
2255 }
2256 if capabilities.contains(NodeCapabilities::FOCUS) {
2257 context.invalidate(InvalidationKind::Focus);
2258 }
2259
2260 context.pop_active_capabilities();
2261}
2262
2263fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
2271 visit_node_tree_mut(node, &mut |n| {
2272 if !n.node_state().is_attached() {
2273 n.node_state().set_attached(true);
2274 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
2275 }
2276 });
2277}
2278
2279fn reset_node_tree(node: &mut dyn ModifierNode) {
2280 visit_node_tree_mut(node, &mut |n| n.on_reset());
2281}
2282
2283fn detach_node_tree(node: &mut dyn ModifierNode) {
2284 visit_node_tree_mut(node, &mut |n| {
2285 if n.node_state().is_attached() {
2286 n.on_detach();
2287 n.node_state().set_attached(false);
2288 }
2289 n.node_state().set_parent_link(None);
2290 n.node_state().set_child_link(None);
2291 n.node_state()
2292 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2293 });
2294}
2295
2296pub struct ModifierNodeChain {
2303 entries: Vec<ModifierNodeEntry>,
2304 aggregated_capabilities: NodeCapabilities,
2305 head_aggregate_child_capabilities: NodeCapabilities,
2306 head_sentinel: Box<SentinelNode>,
2307 tail_sentinel: Box<SentinelNode>,
2308 ordered_nodes: Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
2309 scratch_old_used: Vec<bool>,
2310 scratch_match_order: Vec<Option<usize>>,
2311 scratch_final_slots: Vec<Option<ModifierNodeEntry>>,
2312 scratch_elements: Vec<DynModifierElement>,
2313}
2314
2315struct SentinelNode {
2316 state: NodeState,
2317}
2318
2319impl SentinelNode {
2320 fn new() -> Self {
2321 Self {
2322 state: NodeState::sentinel(),
2323 }
2324 }
2325}
2326
2327impl DelegatableNode for SentinelNode {
2328 fn node_state(&self) -> &NodeState {
2329 &self.state
2330 }
2331}
2332
2333impl ModifierNode for SentinelNode {}
2334
2335#[derive(Clone)]
2336pub struct ModifierChainNodeRef<'a> {
2337 chain: &'a ModifierNodeChain,
2338 link: NodeLink,
2339 cached_capabilities: Option<NodeCapabilities>,
2340 cached_aggregate_child: Option<NodeCapabilities>,
2341}
2342
2343impl Default for ModifierNodeChain {
2344 fn default() -> Self {
2345 Self::new()
2346 }
2347}
2348
2349struct EntryIndex {
2354 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2355 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2356 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
2357}
2358
2359struct EntryMatchQuery<'a> {
2360 element_type: TypeId,
2361 node_type: TypeId,
2362 key: Option<u64>,
2363 hash_code: u64,
2364 element: &'a DynModifierElement,
2365}
2366
2367impl EntryIndex {
2368 fn build(entries: &[ModifierNodeEntry]) -> Self {
2369 let mut keyed = HashMap::default();
2370 let mut hashed = HashMap::default();
2371 let mut typed = HashMap::default();
2372
2373 for (i, entry) in entries.iter().enumerate() {
2374 if let Some(key_value) = entry.key {
2375 keyed
2376 .entry((entry.element_type, entry.node_type, key_value))
2377 .or_insert_with(Vec::new)
2378 .push(i);
2379 } else {
2380 hashed
2381 .entry((entry.element_type, entry.node_type, entry.hash_code))
2382 .or_insert_with(Vec::new)
2383 .push(i);
2384 typed
2385 .entry((entry.element_type, entry.node_type))
2386 .or_insert_with(Vec::new)
2387 .push(i);
2388 }
2389 }
2390
2391 Self {
2392 keyed,
2393 hashed,
2394 typed,
2395 }
2396 }
2397
2398 fn find_match(
2399 &self,
2400 entries: &[ModifierNodeEntry],
2401 used: &[bool],
2402 query: EntryMatchQuery<'_>,
2403 ) -> Option<usize> {
2404 if let Some(key_value) = query.key {
2405 if let Some(candidates) =
2406 self.keyed
2407 .get(&(query.element_type, query.node_type, key_value))
2408 {
2409 for &i in candidates {
2410 if !used[i] {
2411 return Some(i);
2412 }
2413 }
2414 }
2415 } else {
2416 if let Some(candidates) =
2417 self.hashed
2418 .get(&(query.element_type, query.node_type, query.hash_code))
2419 {
2420 for &i in candidates {
2421 if !used[i]
2422 && entries[i]
2423 .element
2424 .as_ref()
2425 .equals_element(query.element.as_ref())
2426 {
2427 return Some(i);
2428 }
2429 }
2430 }
2431
2432 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
2433 for &i in candidates {
2434 if !used[i] {
2435 return Some(i);
2436 }
2437 }
2438 }
2439 }
2440
2441 None
2442 }
2443}
2444
2445impl ModifierNodeChain {
2446 pub fn new() -> Self {
2447 let mut chain = Self {
2448 entries: Vec::new(),
2449 aggregated_capabilities: NodeCapabilities::empty(),
2450 head_aggregate_child_capabilities: NodeCapabilities::empty(),
2451 head_sentinel: Box::new(SentinelNode::new()),
2452 tail_sentinel: Box::new(SentinelNode::new()),
2453 ordered_nodes: Vec::new(),
2454 scratch_old_used: Vec::new(),
2455 scratch_match_order: Vec::new(),
2456 scratch_final_slots: Vec::new(),
2457 scratch_elements: Vec::new(),
2458 };
2459 chain.sync_chain_links();
2460 chain
2461 }
2462
2463 pub fn detach_nodes(&mut self) {
2465 for entry in &self.entries {
2466 detach_node_tree(&mut **entry.node.borrow_mut());
2467 }
2468 }
2469
2470 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
2472 for entry in &self.entries {
2473 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2474 }
2475 }
2476
2477 pub fn repair_chain(&mut self) {
2480 self.sync_chain_links();
2481 }
2482
2483 pub fn update_from_slice(
2489 &mut self,
2490 elements: &[DynModifierElement],
2491 context: &mut dyn ModifierNodeContext,
2492 ) {
2493 self.update_from_ref_iter(elements.iter(), context);
2494 }
2495
2496 pub fn update_from_ref_iter<'a, I>(
2501 &mut self,
2502 elements: I,
2503 context: &mut dyn ModifierNodeContext,
2504 ) where
2505 I: Iterator<Item = &'a DynModifierElement>,
2506 {
2507 let old_len = self.entries.len();
2508 let mut fast_path_failed_at: Option<usize> = None;
2509 let mut elements_count = 0;
2510
2511 self.scratch_elements.clear();
2512
2513 for (idx, element) in elements.enumerate() {
2514 elements_count = idx + 1;
2515
2516 if fast_path_failed_at.is_none() && idx < old_len {
2517 let entry = &mut self.entries[idx];
2518 let same_type = entry.element_type == element.element_type();
2519 let same_node_type = entry.node_type == element.node_type();
2520 let same_key = entry.key == element.key();
2521 let same_hash = entry.hash_code == element.hash_code();
2522
2523 let positional_update = element.requires_update();
2524 if same_type && same_node_type && same_key && (same_hash || positional_update) {
2525 let can_update_node = {
2526 let node_borrow = entry.node.borrow();
2527 element.can_update_node(&**node_borrow)
2528 };
2529 if !can_update_node {
2530 fast_path_failed_at = Some(idx);
2531 self.scratch_elements.push(element.clone());
2532 continue;
2533 }
2534
2535 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2536 let capabilities = element.capabilities();
2537
2538 {
2539 let node_borrow = entry.node.borrow();
2540 if !node_borrow.node_state().is_attached() {
2541 drop(node_borrow);
2542 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2543 }
2544 }
2545
2546 let needs_update = !same_element || element.requires_update();
2547 if needs_update {
2548 element.update_node(&mut **entry.node.borrow_mut());
2549 entry.element = element.clone();
2550 entry.hash_code = element.hash_code();
2551 request_update_auto_invalidations(element.as_ref(), context, capabilities);
2552 }
2553
2554 entry.capabilities = capabilities;
2555 entry
2556 .node
2557 .borrow()
2558 .node_state()
2559 .set_capabilities(capabilities);
2560 continue;
2561 }
2562 fast_path_failed_at = Some(idx);
2563 }
2564
2565 self.scratch_elements.push(element.clone());
2566 }
2567
2568 if fast_path_failed_at.is_none() && self.scratch_elements.is_empty() {
2569 if elements_count < self.entries.len() {
2570 for entry in self.entries.drain(elements_count..) {
2571 request_auto_invalidations(context, entry.capabilities);
2572 detach_node_tree(&mut **entry.node.borrow_mut());
2573 }
2574 }
2575 self.sync_chain_links();
2576 return;
2577 }
2578
2579 let fail_idx = fast_path_failed_at.unwrap_or(old_len);
2580
2581 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
2582 let processed_entries_len = self.entries.len();
2583 let old_len = old_entries.len();
2584
2585 self.scratch_old_used.clear();
2586 self.scratch_old_used.resize(old_len, false);
2587
2588 self.scratch_match_order.clear();
2589 self.scratch_match_order.resize(old_len, None);
2590
2591 let index = EntryIndex::build(&old_entries);
2592
2593 let new_elements_count = self.scratch_elements.len();
2594 self.scratch_final_slots.clear();
2595 self.scratch_final_slots.reserve(new_elements_count);
2596
2597 for (new_pos, element) in self.scratch_elements.drain(..).enumerate() {
2598 self.scratch_final_slots.push(None);
2599 let element_type = element.element_type();
2600 let node_type = element.node_type();
2601 let key = element.key();
2602 let hash_code = element.hash_code();
2603 let capabilities = element.capabilities();
2604
2605 let matched_idx = index.find_match(
2606 &old_entries,
2607 &self.scratch_old_used,
2608 EntryMatchQuery {
2609 element_type,
2610 node_type,
2611 key,
2612 hash_code,
2613 element: &element,
2614 },
2615 );
2616
2617 if let Some(idx) = matched_idx {
2618 let entry = &mut old_entries[idx];
2619 let can_update_node = {
2620 let node_borrow = entry.node.borrow();
2621 element.can_update_node(&**node_borrow)
2622 };
2623 if !can_update_node {
2624 let replacement = ModifierNodeEntry::new(
2625 element_type,
2626 node_type,
2627 key,
2628 element.clone(),
2629 element.create_node(),
2630 hash_code,
2631 capabilities,
2632 );
2633 attach_node_tree(&mut **replacement.node.borrow_mut(), context);
2634 element.update_node(&mut **replacement.node.borrow_mut());
2635 request_auto_invalidations(context, capabilities);
2636 self.scratch_final_slots[new_pos] = Some(replacement);
2637 continue;
2638 }
2639
2640 self.scratch_old_used[idx] = true;
2641 self.scratch_match_order[idx] = Some(new_pos);
2642 let moved = idx != new_pos;
2643
2644 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2645
2646 {
2647 let node_borrow = entry.node.borrow();
2648 if !node_borrow.node_state().is_attached() {
2649 drop(node_borrow);
2650 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2651 }
2652 }
2653
2654 let needs_update = !same_element || element.requires_update();
2655 if needs_update {
2656 element.update_node(&mut **entry.node.borrow_mut());
2657 entry.element = element;
2658 entry.hash_code = hash_code;
2659 request_update_auto_invalidations(
2660 entry.element.as_ref(),
2661 context,
2662 capabilities,
2663 );
2664 }
2665 if moved {
2666 request_auto_invalidations(context, capabilities);
2667 }
2668
2669 entry.key = key;
2670 entry.element_type = element_type;
2671 entry.node_type = node_type;
2672 entry.capabilities = capabilities;
2673 entry
2674 .node
2675 .borrow()
2676 .node_state()
2677 .set_capabilities(capabilities);
2678 } else {
2679 let entry = ModifierNodeEntry::new(
2680 element_type,
2681 node_type,
2682 key,
2683 element.clone(),
2684 element.create_node(),
2685 hash_code,
2686 capabilities,
2687 );
2688 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2689 element.update_node(&mut **entry.node.borrow_mut());
2690 request_auto_invalidations(context, capabilities);
2691 self.scratch_final_slots[new_pos] = Some(entry);
2692 }
2693 }
2694
2695 for (i, entry) in old_entries.into_iter().enumerate() {
2696 if self.scratch_old_used[i] {
2697 if let Some(pos) = self.scratch_match_order[i] {
2698 self.scratch_final_slots[pos] = Some(entry);
2699 } else {
2700 request_auto_invalidations(context, entry.capabilities);
2701 detach_node_tree(&mut **entry.node.borrow_mut());
2702 }
2703 } else {
2704 request_auto_invalidations(context, entry.capabilities);
2705 detach_node_tree(&mut **entry.node.borrow_mut());
2706 }
2707 }
2708
2709 self.entries.reserve(self.scratch_final_slots.len());
2710 for slot in self.scratch_final_slots.drain(..) {
2711 if let Some(entry) = slot {
2712 self.entries.push(entry);
2713 } else {
2714 log::error!("modifier reconciliation produced an empty final slot");
2715 }
2716 }
2717
2718 debug_assert_eq!(
2719 self.entries.len(),
2720 processed_entries_len + new_elements_count
2721 );
2722 self.sync_chain_links();
2723 }
2724
2725 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
2729 where
2730 I: IntoIterator<Item = DynModifierElement>,
2731 {
2732 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
2733 self.update_from_slice(&collected, context);
2734 }
2735
2736 pub fn reset(&mut self) {
2739 for entry in &mut self.entries {
2740 reset_node_tree(&mut **entry.node.borrow_mut());
2741 }
2742 }
2743
2744 pub fn detach_all(&mut self) {
2746 for entry in std::mem::take(&mut self.entries) {
2747 detach_node_tree(&mut **entry.node.borrow_mut());
2748 {
2749 let node_borrow = entry.node.borrow();
2750 let state = node_borrow.node_state();
2751 state.set_capabilities(NodeCapabilities::empty());
2752 }
2753 }
2754 self.aggregated_capabilities = NodeCapabilities::empty();
2755 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2756 self.ordered_nodes.clear();
2757 self.sync_chain_links();
2758 }
2759
2760 pub fn len(&self) -> usize {
2761 self.entries.len()
2762 }
2763
2764 pub fn is_empty(&self) -> bool {
2765 self.entries.is_empty()
2766 }
2767
2768 pub fn capabilities(&self) -> NodeCapabilities {
2770 self.aggregated_capabilities
2771 }
2772
2773 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
2775 self.aggregated_capabilities.contains(capability)
2776 }
2777
2778 pub fn head(&self) -> ModifierChainNodeRef<'_> {
2780 self.make_node_ref(NodeLink::Head)
2781 }
2782
2783 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
2785 self.make_node_ref(NodeLink::Tail)
2786 }
2787
2788 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
2790 ModifierChainIter::forward(self)
2791 }
2792
2793 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
2795 ModifierChainIter::backward(self)
2796 }
2797
2798 pub fn for_each_forward<F>(&self, mut f: F)
2800 where
2801 F: FnMut(ModifierChainNodeRef<'_>),
2802 {
2803 for node in self.head_to_tail() {
2804 f(node);
2805 }
2806 }
2807
2808 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
2810 where
2811 F: FnMut(ModifierChainNodeRef<'_>),
2812 {
2813 if mask.is_empty() {
2814 self.for_each_forward(f);
2815 return;
2816 }
2817
2818 if !self.head().aggregate_child_capabilities().intersects(mask) {
2819 return;
2820 }
2821
2822 for node in self.head_to_tail() {
2823 if node.kind_set().intersects(mask) {
2824 f(node);
2825 }
2826 }
2827 }
2828
2829 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
2831 where
2832 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
2833 {
2834 self.for_each_forward_matching(mask, |node_ref| {
2835 node_ref.with_node(|node| f(node_ref.clone(), node));
2836 });
2837 }
2838
2839 pub fn for_each_backward<F>(&self, mut f: F)
2841 where
2842 F: FnMut(ModifierChainNodeRef<'_>),
2843 {
2844 for node in self.tail_to_head() {
2845 f(node);
2846 }
2847 }
2848
2849 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
2851 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
2852 node as *const dyn ModifierNode as *const ()
2853 }
2854
2855 let target = node_data_ptr(node);
2856 for (index, entry) in self.entries.iter().enumerate() {
2857 if node_data_ptr(&**entry.node.borrow()) == target {
2858 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
2859 }
2860 }
2861
2862 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
2863 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
2864 return None;
2865 }
2866 let matches_target = match link {
2867 NodeLink::Head => node_data_ptr(self.head_sentinel.as_ref()) == target,
2868 NodeLink::Tail => node_data_ptr(self.tail_sentinel.as_ref()) == target,
2869 NodeLink::Entry(path) => {
2870 let node_borrow = self.entries[path.entry()].node.borrow();
2871 node_data_ptr(&**node_borrow) == target
2872 }
2873 };
2874 if matches_target {
2875 Some(self.make_node_ref(*link))
2876 } else {
2877 None
2878 }
2879 })
2880 }
2881
2882 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
2885 self.entries.get(index).and_then(|entry| {
2886 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
2887 boxed_node.as_any().downcast_ref::<N>()
2888 })
2889 .ok()
2890 })
2891 }
2892
2893 pub fn node_mut<N: ModifierNode + 'static>(
2896 &self,
2897 index: usize,
2898 ) -> Option<std::cell::RefMut<'_, N>> {
2899 self.entries.get(index).and_then(|entry| {
2900 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
2901 boxed_node.as_any_mut().downcast_mut::<N>()
2902 })
2903 .ok()
2904 })
2905 }
2906
2907 pub fn get_node_rc(&self, index: usize) -> Option<Rc<RefCell<Box<dyn ModifierNode>>>> {
2910 self.entries.get(index).map(|entry| Rc::clone(&entry.node))
2911 }
2912
2913 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
2915 self.aggregated_capabilities
2916 .contains(NodeCapabilities::for_invalidation(kind))
2917 }
2918
2919 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
2921 where
2922 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
2923 {
2924 for index in 0..self.ordered_nodes.len() {
2925 let (link, cached_caps, _agg) = self.ordered_nodes[index];
2926 match link {
2927 NodeLink::Head => {
2928 f(self.head_sentinel.as_mut(), cached_caps);
2929 }
2930 NodeLink::Tail => {
2931 f(self.tail_sentinel.as_mut(), cached_caps);
2932 }
2933 NodeLink::Entry(path) => {
2934 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
2935 if path.delegates().is_empty() {
2936 f(&mut **node_borrow, cached_caps);
2937 } else {
2938 let mut current: &mut dyn ModifierNode = &mut **node_borrow;
2939 for &delegate_index in path.delegates() {
2940 if let Some(delegate) =
2941 nth_delegate_mut(current, delegate_index as usize)
2942 {
2943 current = delegate;
2944 } else {
2945 return;
2946 }
2947 }
2948 f(current, cached_caps);
2949 }
2950 }
2951 }
2952 }
2953 }
2954
2955 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
2956 ModifierChainNodeRef {
2957 chain: self,
2958 link,
2959 cached_capabilities: None,
2960 cached_aggregate_child: None,
2961 }
2962 }
2963
2964 fn make_node_ref_with_caps(
2965 &self,
2966 link: NodeLink,
2967 caps: NodeCapabilities,
2968 aggregate_child: NodeCapabilities,
2969 ) -> ModifierChainNodeRef<'_> {
2970 ModifierChainNodeRef {
2971 chain: self,
2972 link,
2973 cached_capabilities: Some(caps),
2974 cached_aggregate_child: Some(aggregate_child),
2975 }
2976 }
2977
2978 fn sync_chain_links(&mut self) {
2979 self.rebuild_ordered_nodes();
2980
2981 self.head_sentinel.node_state().set_parent_link(None);
2982 self.tail_sentinel.node_state().set_child_link(None);
2983
2984 if self.ordered_nodes.is_empty() {
2985 self.head_sentinel
2986 .node_state()
2987 .set_child_link(Some(NodeLink::Tail));
2988 self.tail_sentinel
2989 .node_state()
2990 .set_parent_link(Some(NodeLink::Head));
2991 self.aggregated_capabilities = NodeCapabilities::empty();
2992 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2993 self.head_sentinel
2994 .node_state()
2995 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2996 self.tail_sentinel
2997 .node_state()
2998 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2999 return;
3000 }
3001
3002 let mut previous = NodeLink::Head;
3003 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
3004 match &previous {
3005 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
3006 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
3007 NodeLink::Entry(path) => {
3008 let node_borrow = self.entries[path.entry()].node.borrow();
3009 if path.delegates().is_empty() {
3010 node_borrow.node_state().set_child_link(Some(link));
3011 } else {
3012 let mut current: &dyn ModifierNode = &**node_borrow;
3013 for &delegate_index in path.delegates() {
3014 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3015 current = delegate;
3016 }
3017 }
3018 current.node_state().set_child_link(Some(link));
3019 }
3020 }
3021 }
3022 match &link {
3023 NodeLink::Head => self
3024 .head_sentinel
3025 .node_state()
3026 .set_parent_link(Some(previous)),
3027 NodeLink::Tail => self
3028 .tail_sentinel
3029 .node_state()
3030 .set_parent_link(Some(previous)),
3031 NodeLink::Entry(path) => {
3032 let node_borrow = self.entries[path.entry()].node.borrow();
3033 if path.delegates().is_empty() {
3034 node_borrow.node_state().set_parent_link(Some(previous));
3035 } else {
3036 let mut current: &dyn ModifierNode = &**node_borrow;
3037 for &delegate_index in path.delegates() {
3038 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3039 current = delegate;
3040 }
3041 }
3042 current.node_state().set_parent_link(Some(previous));
3043 }
3044 }
3045 }
3046 previous = link;
3047 }
3048
3049 match &previous {
3050 NodeLink::Head => self
3051 .head_sentinel
3052 .node_state()
3053 .set_child_link(Some(NodeLink::Tail)),
3054 NodeLink::Tail => self
3055 .tail_sentinel
3056 .node_state()
3057 .set_child_link(Some(NodeLink::Tail)),
3058 NodeLink::Entry(path) => {
3059 let node_borrow = self.entries[path.entry()].node.borrow();
3060 if path.delegates().is_empty() {
3061 node_borrow
3062 .node_state()
3063 .set_child_link(Some(NodeLink::Tail));
3064 } else {
3065 let mut current: &dyn ModifierNode = &**node_borrow;
3066 for &delegate_index in path.delegates() {
3067 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3068 current = delegate;
3069 }
3070 }
3071 current.node_state().set_child_link(Some(NodeLink::Tail));
3072 }
3073 }
3074 }
3075 self.tail_sentinel
3076 .node_state()
3077 .set_parent_link(Some(previous));
3078 self.tail_sentinel.node_state().set_child_link(None);
3079
3080 let mut aggregate = NodeCapabilities::empty();
3081 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
3082 aggregate |= *cached_caps;
3083 *cached_aggregate = aggregate;
3084 match link {
3085 NodeLink::Head => {
3086 self.head_sentinel
3087 .node_state()
3088 .set_aggregate_child_capabilities(aggregate);
3089 }
3090 NodeLink::Tail => {
3091 self.tail_sentinel
3092 .node_state()
3093 .set_aggregate_child_capabilities(aggregate);
3094 }
3095 NodeLink::Entry(path) => {
3096 let node_borrow = self.entries[path.entry()].node.borrow();
3097 let state = if path.delegates().is_empty() {
3098 node_borrow.node_state()
3099 } else {
3100 let mut current: &dyn ModifierNode = &**node_borrow;
3101 for &delegate_index in path.delegates() {
3102 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3103 current = delegate;
3104 }
3105 }
3106 current.node_state()
3107 };
3108 state.set_aggregate_child_capabilities(aggregate);
3109 }
3110 }
3111 }
3112
3113 self.aggregated_capabilities = aggregate;
3114 self.head_aggregate_child_capabilities = aggregate;
3115 self.head_sentinel
3116 .node_state()
3117 .set_aggregate_child_capabilities(aggregate);
3118 self.tail_sentinel
3119 .node_state()
3120 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3121 }
3122
3123 fn rebuild_ordered_nodes(&mut self) {
3124 self.ordered_nodes.clear();
3125 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
3126 for (index, entry) in self.entries.iter().enumerate() {
3127 let node_borrow = entry.node.borrow();
3128 Self::enumerate_link_order(
3129 &**node_borrow,
3130 index,
3131 &mut path_buf,
3132 0,
3133 &mut self.ordered_nodes,
3134 );
3135 }
3136 }
3137
3138 fn enumerate_link_order(
3139 node: &dyn ModifierNode,
3140 entry: usize,
3141 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
3142 path_len: usize,
3143 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
3144 ) {
3145 let caps = node.node_state().capabilities();
3146 out.push((
3147 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
3148 caps,
3149 NodeCapabilities::empty(),
3150 ));
3151 let mut delegate_index = 0usize;
3152 node.for_each_delegate(&mut |child| {
3153 if path_len < MAX_DELEGATE_DEPTH {
3154 path_buf[path_len] = delegate_index;
3155 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
3156 }
3157 delegate_index += 1;
3158 });
3159 }
3160}
3161
3162impl<'a> ModifierChainNodeRef<'a> {
3163 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
3164 match &self.link {
3165 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
3166 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
3167 NodeLink::Entry(path) => {
3168 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3169 if path.delegates().is_empty() {
3170 f(node_borrow.node_state())
3171 } else {
3172 let mut current: &dyn ModifierNode = &**node_borrow;
3173 for &delegate_index in path.delegates() {
3174 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3175 current = delegate;
3176 } else {
3177 return f(node_borrow.node_state());
3178 }
3179 }
3180 f(current.node_state())
3181 }
3182 }
3183 }
3184 }
3185
3186 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
3189 match &self.link {
3190 NodeLink::Head => None,
3191 NodeLink::Tail => None,
3192 NodeLink::Entry(path) => {
3193 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3194 if path.delegates().is_empty() {
3195 Some(f(&**node_borrow))
3196 } else {
3197 let mut current: &dyn ModifierNode = &**node_borrow;
3198 for &delegate_index in path.delegates() {
3199 current = nth_delegate(current, delegate_index as usize)?;
3200 }
3201 Some(f(current))
3202 }
3203 }
3204 }
3205 }
3206
3207 #[inline]
3209 pub fn parent(&self) -> Option<Self> {
3210 self.with_state(|state| state.parent_link())
3211 .map(|link| self.chain.make_node_ref(link))
3212 }
3213
3214 #[inline]
3216 pub fn child(&self) -> Option<Self> {
3217 self.with_state(|state| state.child_link())
3218 .map(|link| self.chain.make_node_ref(link))
3219 }
3220
3221 #[inline]
3223 pub fn kind_set(&self) -> NodeCapabilities {
3224 if let Some(caps) = self.cached_capabilities {
3225 return caps;
3226 }
3227 match &self.link {
3228 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
3229 NodeLink::Entry(_) => self.with_state(|state| state.capabilities()),
3230 }
3231 }
3232
3233 pub fn entry_index(&self) -> Option<usize> {
3235 match &self.link {
3236 NodeLink::Entry(path) => Some(path.entry()),
3237 _ => None,
3238 }
3239 }
3240
3241 pub fn delegate_depth(&self) -> usize {
3243 match &self.link {
3244 NodeLink::Entry(path) => path.delegates().len(),
3245 _ => 0,
3246 }
3247 }
3248
3249 #[inline]
3251 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
3252 if let Some(agg) = self.cached_aggregate_child {
3253 return agg;
3254 }
3255 if self.is_tail() {
3256 NodeCapabilities::empty()
3257 } else {
3258 self.with_state(|state| state.aggregate_child_capabilities())
3259 }
3260 }
3261
3262 pub fn is_head(&self) -> bool {
3264 matches!(self.link, NodeLink::Head)
3265 }
3266
3267 pub fn is_tail(&self) -> bool {
3269 matches!(self.link, NodeLink::Tail)
3270 }
3271
3272 pub fn is_sentinel(&self) -> bool {
3274 matches!(self.link, NodeLink::Head | NodeLink::Tail)
3275 }
3276
3277 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
3279 !mask.is_empty() && self.kind_set().intersects(mask)
3280 }
3281
3282 pub fn visit_descendants<F>(self, include_self: bool, mut f: F)
3284 where
3285 F: FnMut(ModifierChainNodeRef<'a>),
3286 {
3287 let mut current = if include_self {
3288 Some(self)
3289 } else {
3290 self.child()
3291 };
3292 while let Some(node) = current {
3293 if node.is_tail() {
3294 break;
3295 }
3296 if !node.is_sentinel() {
3297 f(node.clone());
3298 }
3299 current = node.child();
3300 }
3301 }
3302
3303 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3305 where
3306 F: FnMut(ModifierChainNodeRef<'a>),
3307 {
3308 if mask.is_empty() {
3309 self.visit_descendants(include_self, f);
3310 return;
3311 }
3312
3313 if !self.aggregate_child_capabilities().intersects(mask) {
3314 return;
3315 }
3316
3317 self.visit_descendants(include_self, |node| {
3318 if node.kind_set().intersects(mask) {
3319 f(node);
3320 }
3321 });
3322 }
3323
3324 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
3326 where
3327 F: FnMut(ModifierChainNodeRef<'a>),
3328 {
3329 let mut current = if include_self {
3330 Some(self)
3331 } else {
3332 self.parent()
3333 };
3334 while let Some(node) = current {
3335 if node.is_head() {
3336 break;
3337 }
3338 f(node.clone());
3339 current = node.parent();
3340 }
3341 }
3342
3343 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3345 where
3346 F: FnMut(ModifierChainNodeRef<'a>),
3347 {
3348 if mask.is_empty() {
3349 self.visit_ancestors(include_self, f);
3350 return;
3351 }
3352
3353 self.visit_ancestors(include_self, |node| {
3354 if node.kind_set().intersects(mask) {
3355 f(node);
3356 }
3357 });
3358 }
3359}
3360
3361#[cfg(test)]
3362#[path = "tests/modifier_tests.rs"]
3363mod tests;