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