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 .map(|typed| typed.element == self.element)
2080 .unwrap_or(false)
2081 }
2082
2083 fn inspector_name(&self) -> &'static str {
2084 self.element.inspector_name()
2085 }
2086
2087 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String)) {
2088 self.element.inspector_properties(visitor);
2089 }
2090
2091 fn requires_update(&self) -> bool {
2092 self.element.always_update()
2093 }
2094
2095 fn auto_invalidates_on_update(&self) -> bool {
2096 self.element.auto_invalidate_on_update()
2097 }
2098
2099 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
2100 self.element.update_invalidation_kind()
2101 }
2102
2103 fn as_any(&self) -> &dyn Any {
2104 self
2105 }
2106}
2107
2108fn request_update_auto_invalidations(
2109 element: &dyn AnyModifierElement,
2110 context: &mut dyn ModifierNodeContext,
2111 capabilities: NodeCapabilities,
2112) {
2113 if let Some(kind) = element.update_invalidation_kind() {
2114 let capabilities = NodeCapabilities::for_invalidation(kind);
2115 context.push_active_capabilities(capabilities);
2116 context.invalidate(kind);
2117 context.pop_active_capabilities();
2118 } else if element.auto_invalidates_on_update() {
2119 request_auto_invalidations(context, capabilities);
2120 }
2121}
2122
2123pub fn modifier_element<E: ModifierNodeElement>(element: E) -> DynModifierElement {
2126 Rc::new(TypedModifierElement::new(element))
2127}
2128
2129pub type DynModifierElement = Rc<dyn AnyModifierElement>;
2131
2132#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2133enum TraversalDirection {
2134 Forward,
2135 Backward,
2136}
2137
2138pub struct ModifierChainIter<'a> {
2143 chain: &'a ModifierNodeChain,
2144 cursor: usize,
2145 remaining: usize,
2146 direction: TraversalDirection,
2147}
2148
2149impl<'a> ModifierChainIter<'a> {
2150 fn forward(chain: &'a ModifierNodeChain) -> Self {
2151 Self {
2152 chain,
2153 cursor: 0,
2154 remaining: chain.ordered_nodes.len(),
2155 direction: TraversalDirection::Forward,
2156 }
2157 }
2158
2159 fn backward(chain: &'a ModifierNodeChain) -> Self {
2160 let len = chain.ordered_nodes.len();
2161 Self {
2162 chain,
2163 cursor: len.wrapping_sub(1),
2164 remaining: len,
2165 direction: TraversalDirection::Backward,
2166 }
2167 }
2168}
2169
2170impl<'a> Iterator for ModifierChainIter<'a> {
2171 type Item = ModifierChainNodeRef<'a>;
2172
2173 #[inline]
2174 fn next(&mut self) -> Option<Self::Item> {
2175 if self.remaining == 0 {
2176 return None;
2177 }
2178 let (link, caps, agg) = self.chain.ordered_nodes[self.cursor];
2179 let node_ref = self.chain.make_node_ref_with_caps(link, caps, agg);
2180 self.remaining -= 1;
2181 match self.direction {
2182 TraversalDirection::Forward => self.cursor += 1,
2183 TraversalDirection::Backward => self.cursor = self.cursor.wrapping_sub(1),
2184 }
2185 Some(node_ref)
2186 }
2187
2188 #[inline]
2189 fn size_hint(&self) -> (usize, Option<usize>) {
2190 (self.remaining, Some(self.remaining))
2191 }
2192}
2193
2194impl<'a> ExactSizeIterator for ModifierChainIter<'a> {}
2195impl<'a> std::iter::FusedIterator for ModifierChainIter<'a> {}
2196
2197#[derive(Debug)]
2198struct ModifierNodeEntry {
2199 element_type: TypeId,
2200 node_type: TypeId,
2201 key: Option<u64>,
2202 hash_code: u64,
2203 element: DynModifierElement,
2204 node: Rc<RefCell<Box<dyn ModifierNode>>>,
2205 capabilities: NodeCapabilities,
2206}
2207
2208impl ModifierNodeEntry {
2209 fn new(
2210 element_type: TypeId,
2211 node_type: TypeId,
2212 key: Option<u64>,
2213 element: DynModifierElement,
2214 node: Box<dyn ModifierNode>,
2215 hash_code: u64,
2216 capabilities: NodeCapabilities,
2217 ) -> Self {
2218 let node_rc = Rc::new(RefCell::new(node));
2219 let entry = Self {
2220 element_type,
2221 node_type,
2222 key,
2223 hash_code,
2224 element,
2225 node: Rc::clone(&node_rc),
2226 capabilities,
2227 };
2228 entry
2229 .node
2230 .borrow()
2231 .node_state()
2232 .set_capabilities(entry.capabilities);
2233 entry
2234 }
2235}
2236
2237fn visit_node_tree_mut(
2238 node: &mut dyn ModifierNode,
2239 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
2240) {
2241 visitor(node);
2242 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
2243}
2244
2245fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
2246 let mut current = 0usize;
2247 let mut result: Option<&dyn ModifierNode> = None;
2248 node.for_each_delegate(&mut |child| {
2249 if result.is_none() && current == target {
2250 result = Some(child);
2251 }
2252 current += 1;
2253 });
2254 result
2255}
2256
2257fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
2258 let mut current = 0usize;
2259 let mut result: Option<&mut dyn ModifierNode> = None;
2260 node.for_each_delegate_mut(&mut |child| {
2261 if result.is_none() && current == target {
2262 result = Some(child);
2263 }
2264 current += 1;
2265 });
2266 result
2267}
2268
2269fn with_node_context<F, R>(
2270 node: &mut dyn ModifierNode,
2271 context: &mut dyn ModifierNodeContext,
2272 f: F,
2273) -> R
2274where
2275 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
2276{
2277 context.push_active_capabilities(node.node_state().capabilities());
2278 let result = f(node, context);
2279 context.pop_active_capabilities();
2280 result
2281}
2282
2283fn request_auto_invalidations(
2284 context: &mut dyn ModifierNodeContext,
2285 capabilities: NodeCapabilities,
2286) {
2287 if capabilities.is_empty() {
2288 return;
2289 }
2290
2291 context.push_active_capabilities(capabilities);
2292
2293 if capabilities.contains(NodeCapabilities::LAYOUT) {
2294 context.invalidate(InvalidationKind::Layout);
2295 }
2296 if capabilities.contains(NodeCapabilities::DRAW) {
2297 context.invalidate(InvalidationKind::Draw);
2298 }
2299 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
2300 context.invalidate(InvalidationKind::PointerInput);
2301 }
2302 if capabilities.contains(NodeCapabilities::SEMANTICS) {
2303 context.invalidate(InvalidationKind::Semantics);
2304 }
2305 if capabilities.contains(NodeCapabilities::FOCUS) {
2306 context.invalidate(InvalidationKind::Focus);
2307 }
2308
2309 context.pop_active_capabilities();
2310}
2311
2312fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
2313 visit_node_tree_mut(node, &mut |n| {
2314 if !n.node_state().is_attached() {
2315 n.node_state().set_attached(true);
2316 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
2317 }
2318 });
2319}
2320
2321fn reset_node_tree(node: &mut dyn ModifierNode) {
2322 visit_node_tree_mut(node, &mut |n| n.on_reset());
2323}
2324
2325fn detach_node_tree(node: &mut dyn ModifierNode) {
2326 visit_node_tree_mut(node, &mut |n| {
2327 if n.node_state().is_attached() {
2328 n.on_detach();
2329 n.node_state().set_attached(false);
2330 }
2331 n.node_state().set_parent_link(None);
2332 n.node_state().set_child_link(None);
2333 n.node_state()
2334 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2335 });
2336}
2337
2338pub struct ModifierNodeChain {
2345 entries: Vec<ModifierNodeEntry>,
2346 aggregated_capabilities: NodeCapabilities,
2347 head_aggregate_child_capabilities: NodeCapabilities,
2348 head_sentinel: Box<SentinelNode>,
2349 tail_sentinel: Box<SentinelNode>,
2350 ordered_nodes: Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
2351 scratch_old_used: Vec<bool>,
2352 scratch_match_order: Vec<Option<usize>>,
2353 scratch_final_slots: Vec<Option<ModifierNodeEntry>>,
2354 scratch_elements: Vec<DynModifierElement>,
2355}
2356
2357struct SentinelNode {
2358 state: NodeState,
2359}
2360
2361impl SentinelNode {
2362 fn new() -> Self {
2363 Self {
2364 state: NodeState::sentinel(),
2365 }
2366 }
2367}
2368
2369impl DelegatableNode for SentinelNode {
2370 fn node_state(&self) -> &NodeState {
2371 &self.state
2372 }
2373}
2374
2375impl ModifierNode for SentinelNode {}
2376
2377#[derive(Clone)]
2378pub struct ModifierChainNodeRef<'a> {
2379 chain: &'a ModifierNodeChain,
2380 link: NodeLink,
2381 cached_capabilities: Option<NodeCapabilities>,
2382 cached_aggregate_child: Option<NodeCapabilities>,
2383}
2384
2385impl Default for ModifierNodeChain {
2386 fn default() -> Self {
2387 Self::new()
2388 }
2389}
2390
2391struct EntryIndex {
2392 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2393 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2394 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
2395}
2396
2397struct EntryMatchQuery<'a> {
2398 element_type: TypeId,
2399 node_type: TypeId,
2400 key: Option<u64>,
2401 hash_code: u64,
2402 element: &'a DynModifierElement,
2403}
2404
2405impl EntryIndex {
2406 fn build(entries: &[ModifierNodeEntry]) -> Self {
2407 let mut keyed = HashMap::default();
2408 let mut hashed = HashMap::default();
2409 let mut typed = HashMap::default();
2410
2411 for (i, entry) in entries.iter().enumerate() {
2412 if let Some(key_value) = entry.key {
2413 keyed
2414 .entry((entry.element_type, entry.node_type, key_value))
2415 .or_insert_with(Vec::new)
2416 .push(i);
2417 } else {
2418 hashed
2419 .entry((entry.element_type, entry.node_type, entry.hash_code))
2420 .or_insert_with(Vec::new)
2421 .push(i);
2422 typed
2423 .entry((entry.element_type, entry.node_type))
2424 .or_insert_with(Vec::new)
2425 .push(i);
2426 }
2427 }
2428
2429 Self {
2430 keyed,
2431 hashed,
2432 typed,
2433 }
2434 }
2435
2436 fn find_match(
2437 &self,
2438 entries: &[ModifierNodeEntry],
2439 used: &[bool],
2440 query: EntryMatchQuery<'_>,
2441 ) -> Option<usize> {
2442 if let Some(key_value) = query.key {
2443 if let Some(candidates) =
2444 self.keyed
2445 .get(&(query.element_type, query.node_type, key_value))
2446 {
2447 for &i in candidates {
2448 if !used[i] {
2449 return Some(i);
2450 }
2451 }
2452 }
2453 } else {
2454 if let Some(candidates) =
2455 self.hashed
2456 .get(&(query.element_type, query.node_type, query.hash_code))
2457 {
2458 for &i in candidates {
2459 if !used[i]
2460 && entries[i]
2461 .element
2462 .as_ref()
2463 .equals_element(query.element.as_ref())
2464 {
2465 return Some(i);
2466 }
2467 }
2468 }
2469
2470 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
2471 for &i in candidates {
2472 if !used[i] {
2473 return Some(i);
2474 }
2475 }
2476 }
2477 }
2478
2479 None
2480 }
2481}
2482
2483impl ModifierNodeChain {
2484 pub fn new() -> Self {
2485 let mut chain = Self {
2486 entries: Vec::new(),
2487 aggregated_capabilities: NodeCapabilities::empty(),
2488 head_aggregate_child_capabilities: NodeCapabilities::empty(),
2489 head_sentinel: Box::new(SentinelNode::new()),
2490 tail_sentinel: Box::new(SentinelNode::new()),
2491 ordered_nodes: Vec::new(),
2492 scratch_old_used: Vec::new(),
2493 scratch_match_order: Vec::new(),
2494 scratch_final_slots: Vec::new(),
2495 scratch_elements: Vec::new(),
2496 };
2497 chain.sync_chain_links();
2498 chain
2499 }
2500
2501 pub fn detach_nodes(&mut self) {
2503 for entry in &self.entries {
2504 detach_node_tree(&mut **entry.node.borrow_mut());
2505 }
2506 }
2507
2508 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
2510 for entry in &self.entries {
2511 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2512 }
2513 }
2514
2515 pub fn repair_chain(&mut self) {
2518 self.sync_chain_links();
2519 }
2520
2521 pub fn update_from_slice(
2527 &mut self,
2528 elements: &[DynModifierElement],
2529 context: &mut dyn ModifierNodeContext,
2530 ) {
2531 self.update_from_ref_iter(elements.iter(), context);
2532 }
2533
2534 pub fn update_from_ref_iter<'a, I>(
2539 &mut self,
2540 elements: I,
2541 context: &mut dyn ModifierNodeContext,
2542 ) where
2543 I: Iterator<Item = &'a DynModifierElement>,
2544 {
2545 let old_len = self.entries.len();
2546 let mut fast_path_failed_at: Option<usize> = None;
2547 let mut elements_count = 0;
2548
2549 self.scratch_elements.clear();
2550
2551 for (idx, element) in elements.enumerate() {
2552 elements_count = idx + 1;
2553
2554 if fast_path_failed_at.is_none() && idx < old_len {
2555 let entry = &mut self.entries[idx];
2556 let same_type = entry.element_type == element.element_type();
2557 let same_node_type = entry.node_type == element.node_type();
2558 let same_key = entry.key == element.key();
2559 let same_hash = entry.hash_code == element.hash_code();
2560
2561 let positional_update = element.requires_update();
2562 if same_type && same_node_type && same_key && (same_hash || positional_update) {
2563 let can_update_node = {
2564 let node_borrow = entry.node.borrow();
2565 element.can_update_node(&**node_borrow)
2566 };
2567 if !can_update_node {
2568 fast_path_failed_at = Some(idx);
2569 self.scratch_elements.push(element.clone());
2570 continue;
2571 }
2572
2573 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2574 let capabilities = element.capabilities();
2575
2576 {
2577 let node_borrow = entry.node.borrow();
2578 if !node_borrow.node_state().is_attached() {
2579 drop(node_borrow);
2580 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2581 }
2582 }
2583
2584 let needs_update = !same_element || element.requires_update();
2585 if needs_update {
2586 element.update_node(&mut **entry.node.borrow_mut());
2587 entry.element = element.clone();
2588 entry.hash_code = element.hash_code();
2589 request_update_auto_invalidations(element.as_ref(), context, capabilities);
2590 }
2591
2592 entry.capabilities = capabilities;
2593 entry
2594 .node
2595 .borrow()
2596 .node_state()
2597 .set_capabilities(capabilities);
2598 continue;
2599 }
2600 fast_path_failed_at = Some(idx);
2601 }
2602
2603 self.scratch_elements.push(element.clone());
2604 }
2605
2606 if fast_path_failed_at.is_none() && self.scratch_elements.is_empty() {
2607 if elements_count < self.entries.len() {
2608 for entry in self.entries.drain(elements_count..) {
2609 request_auto_invalidations(context, entry.capabilities);
2610 detach_node_tree(&mut **entry.node.borrow_mut());
2611 }
2612 }
2613 self.sync_chain_links();
2614 return;
2615 }
2616
2617 let fail_idx = fast_path_failed_at.unwrap_or(old_len);
2618
2619 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
2620 let processed_entries_len = self.entries.len();
2621 let old_len = old_entries.len();
2622
2623 self.scratch_old_used.clear();
2624 self.scratch_old_used.resize(old_len, false);
2625
2626 self.scratch_match_order.clear();
2627 self.scratch_match_order.resize(old_len, None);
2628
2629 let index = EntryIndex::build(&old_entries);
2630
2631 let new_elements_count = self.scratch_elements.len();
2632 self.scratch_final_slots.clear();
2633 self.scratch_final_slots.reserve(new_elements_count);
2634
2635 for (new_pos, element) in self.scratch_elements.drain(..).enumerate() {
2636 self.scratch_final_slots.push(None);
2637 let element_type = element.element_type();
2638 let node_type = element.node_type();
2639 let key = element.key();
2640 let hash_code = element.hash_code();
2641 let capabilities = element.capabilities();
2642
2643 let matched_idx = index.find_match(
2644 &old_entries,
2645 &self.scratch_old_used,
2646 EntryMatchQuery {
2647 element_type,
2648 node_type,
2649 key,
2650 hash_code,
2651 element: &element,
2652 },
2653 );
2654
2655 if let Some(idx) = matched_idx {
2656 let entry = &mut old_entries[idx];
2657 let can_update_node = {
2658 let node_borrow = entry.node.borrow();
2659 element.can_update_node(&**node_borrow)
2660 };
2661 if !can_update_node {
2662 let replacement = ModifierNodeEntry::new(
2663 element_type,
2664 node_type,
2665 key,
2666 element.clone(),
2667 element.create_node(),
2668 hash_code,
2669 capabilities,
2670 );
2671 attach_node_tree(&mut **replacement.node.borrow_mut(), context);
2672 element.update_node(&mut **replacement.node.borrow_mut());
2673 request_auto_invalidations(context, capabilities);
2674 self.scratch_final_slots[new_pos] = Some(replacement);
2675 continue;
2676 }
2677
2678 self.scratch_old_used[idx] = true;
2679 self.scratch_match_order[idx] = Some(new_pos);
2680 let moved = idx != new_pos;
2681
2682 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2683
2684 {
2685 let node_borrow = entry.node.borrow();
2686 if !node_borrow.node_state().is_attached() {
2687 drop(node_borrow);
2688 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2689 }
2690 }
2691
2692 let needs_update = !same_element || element.requires_update();
2693 if needs_update {
2694 element.update_node(&mut **entry.node.borrow_mut());
2695 entry.element = element;
2696 entry.hash_code = hash_code;
2697 request_update_auto_invalidations(
2698 entry.element.as_ref(),
2699 context,
2700 capabilities,
2701 );
2702 }
2703 if moved {
2704 request_auto_invalidations(context, capabilities);
2705 }
2706
2707 entry.key = key;
2708 entry.element_type = element_type;
2709 entry.node_type = node_type;
2710 entry.capabilities = capabilities;
2711 entry
2712 .node
2713 .borrow()
2714 .node_state()
2715 .set_capabilities(capabilities);
2716 } else {
2717 let entry = ModifierNodeEntry::new(
2718 element_type,
2719 node_type,
2720 key,
2721 element.clone(),
2722 element.create_node(),
2723 hash_code,
2724 capabilities,
2725 );
2726 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2727 element.update_node(&mut **entry.node.borrow_mut());
2728 request_auto_invalidations(context, capabilities);
2729 self.scratch_final_slots[new_pos] = Some(entry);
2730 }
2731 }
2732
2733 for (i, entry) in old_entries.into_iter().enumerate() {
2734 if self.scratch_old_used[i] {
2735 if let Some(pos) = self.scratch_match_order[i] {
2736 self.scratch_final_slots[pos] = Some(entry);
2737 } else {
2738 request_auto_invalidations(context, entry.capabilities);
2739 detach_node_tree(&mut **entry.node.borrow_mut());
2740 }
2741 } else {
2742 request_auto_invalidations(context, entry.capabilities);
2743 detach_node_tree(&mut **entry.node.borrow_mut());
2744 }
2745 }
2746
2747 self.entries.reserve(self.scratch_final_slots.len());
2748 for slot in self.scratch_final_slots.drain(..) {
2749 if let Some(entry) = slot {
2750 self.entries.push(entry);
2751 } else {
2752 log::error!("modifier reconciliation produced an empty final slot");
2753 }
2754 }
2755
2756 debug_assert_eq!(
2757 self.entries.len(),
2758 processed_entries_len + new_elements_count
2759 );
2760 self.sync_chain_links();
2761 }
2762
2763 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
2767 where
2768 I: IntoIterator<Item = DynModifierElement>,
2769 {
2770 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
2771 self.update_from_slice(&collected, context);
2772 }
2773
2774 pub fn reset(&mut self) {
2777 for entry in &mut self.entries {
2778 reset_node_tree(&mut **entry.node.borrow_mut());
2779 }
2780 }
2781
2782 pub fn detach_all(&mut self) {
2784 for entry in std::mem::take(&mut self.entries) {
2785 detach_node_tree(&mut **entry.node.borrow_mut());
2786 {
2787 let node_borrow = entry.node.borrow();
2788 let state = node_borrow.node_state();
2789 state.set_capabilities(NodeCapabilities::empty());
2790 }
2791 }
2792 self.aggregated_capabilities = NodeCapabilities::empty();
2793 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2794 self.ordered_nodes.clear();
2795 self.sync_chain_links();
2796 }
2797
2798 pub fn len(&self) -> usize {
2799 self.entries.len()
2800 }
2801
2802 pub fn is_empty(&self) -> bool {
2803 self.entries.is_empty()
2804 }
2805
2806 pub fn capabilities(&self) -> NodeCapabilities {
2808 self.aggregated_capabilities
2809 }
2810
2811 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
2813 self.aggregated_capabilities.contains(capability)
2814 }
2815
2816 pub fn head(&self) -> ModifierChainNodeRef<'_> {
2818 self.make_node_ref(NodeLink::Head)
2819 }
2820
2821 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
2823 self.make_node_ref(NodeLink::Tail)
2824 }
2825
2826 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
2828 ModifierChainIter::forward(self)
2829 }
2830
2831 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
2833 ModifierChainIter::backward(self)
2834 }
2835
2836 pub fn for_each_forward<F>(&self, mut f: F)
2838 where
2839 F: FnMut(ModifierChainNodeRef<'_>),
2840 {
2841 for node in self.head_to_tail() {
2842 f(node);
2843 }
2844 }
2845
2846 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
2848 where
2849 F: FnMut(ModifierChainNodeRef<'_>),
2850 {
2851 if mask.is_empty() {
2852 self.for_each_forward(f);
2853 return;
2854 }
2855
2856 if !self.head().aggregate_child_capabilities().intersects(mask) {
2857 return;
2858 }
2859
2860 for node in self.head_to_tail() {
2861 if node.kind_set().intersects(mask) {
2862 f(node);
2863 }
2864 }
2865 }
2866
2867 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
2869 where
2870 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
2871 {
2872 self.for_each_forward_matching(mask, |node_ref| {
2873 node_ref.with_node(|node| f(node_ref.clone(), node));
2874 });
2875 }
2876
2877 pub fn for_each_backward<F>(&self, mut f: F)
2879 where
2880 F: FnMut(ModifierChainNodeRef<'_>),
2881 {
2882 for node in self.tail_to_head() {
2883 f(node);
2884 }
2885 }
2886
2887 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
2889 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
2890 node as *const dyn ModifierNode as *const ()
2891 }
2892
2893 let target = node_data_ptr(node);
2894 for (index, entry) in self.entries.iter().enumerate() {
2895 if node_data_ptr(&**entry.node.borrow()) == target {
2896 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
2897 }
2898 }
2899
2900 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
2901 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
2902 return None;
2903 }
2904 let matches_target = match link {
2905 NodeLink::Head => node_data_ptr(self.head_sentinel.as_ref()) == target,
2906 NodeLink::Tail => node_data_ptr(self.tail_sentinel.as_ref()) == target,
2907 NodeLink::Entry(path) => {
2908 let node_borrow = self.entries[path.entry()].node.borrow();
2909 node_data_ptr(&**node_borrow) == target
2910 }
2911 };
2912 if matches_target {
2913 Some(self.make_node_ref(*link))
2914 } else {
2915 None
2916 }
2917 })
2918 }
2919
2920 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
2923 self.entries.get(index).and_then(|entry| {
2924 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
2925 boxed_node.as_any().downcast_ref::<N>()
2926 })
2927 .ok()
2928 })
2929 }
2930
2931 pub fn node_mut<N: ModifierNode + 'static>(
2934 &self,
2935 index: usize,
2936 ) -> Option<std::cell::RefMut<'_, N>> {
2937 self.entries.get(index).and_then(|entry| {
2938 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
2939 boxed_node.as_any_mut().downcast_mut::<N>()
2940 })
2941 .ok()
2942 })
2943 }
2944
2945 pub fn get_node_rc(&self, index: usize) -> Option<Rc<RefCell<Box<dyn ModifierNode>>>> {
2948 self.entries.get(index).map(|entry| Rc::clone(&entry.node))
2949 }
2950
2951 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
2953 self.aggregated_capabilities
2954 .contains(NodeCapabilities::for_invalidation(kind))
2955 }
2956
2957 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
2959 where
2960 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
2961 {
2962 for index in 0..self.ordered_nodes.len() {
2963 let (link, cached_caps, _agg) = self.ordered_nodes[index];
2964 match link {
2965 NodeLink::Head => {
2966 f(self.head_sentinel.as_mut(), cached_caps);
2967 }
2968 NodeLink::Tail => {
2969 f(self.tail_sentinel.as_mut(), cached_caps);
2970 }
2971 NodeLink::Entry(path) => {
2972 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
2973 if path.delegates().is_empty() {
2974 f(&mut **node_borrow, cached_caps);
2975 } else {
2976 let mut current: &mut dyn ModifierNode = &mut **node_borrow;
2977 for &delegate_index in path.delegates() {
2978 if let Some(delegate) =
2979 nth_delegate_mut(current, delegate_index as usize)
2980 {
2981 current = delegate;
2982 } else {
2983 return;
2984 }
2985 }
2986 f(current, cached_caps);
2987 }
2988 }
2989 }
2990 }
2991 }
2992
2993 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
2994 ModifierChainNodeRef {
2995 chain: self,
2996 link,
2997 cached_capabilities: None,
2998 cached_aggregate_child: None,
2999 }
3000 }
3001
3002 fn make_node_ref_with_caps(
3003 &self,
3004 link: NodeLink,
3005 caps: NodeCapabilities,
3006 aggregate_child: NodeCapabilities,
3007 ) -> ModifierChainNodeRef<'_> {
3008 ModifierChainNodeRef {
3009 chain: self,
3010 link,
3011 cached_capabilities: Some(caps),
3012 cached_aggregate_child: Some(aggregate_child),
3013 }
3014 }
3015
3016 fn sync_chain_links(&mut self) {
3017 self.rebuild_ordered_nodes();
3018
3019 self.head_sentinel.node_state().set_parent_link(None);
3020 self.tail_sentinel.node_state().set_child_link(None);
3021
3022 if self.ordered_nodes.is_empty() {
3023 self.head_sentinel
3024 .node_state()
3025 .set_child_link(Some(NodeLink::Tail));
3026 self.tail_sentinel
3027 .node_state()
3028 .set_parent_link(Some(NodeLink::Head));
3029 self.aggregated_capabilities = NodeCapabilities::empty();
3030 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
3031 self.head_sentinel
3032 .node_state()
3033 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3034 self.tail_sentinel
3035 .node_state()
3036 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3037 return;
3038 }
3039
3040 let mut previous = NodeLink::Head;
3041 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
3042 match &previous {
3043 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
3044 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
3045 NodeLink::Entry(path) => {
3046 let node_borrow = self.entries[path.entry()].node.borrow();
3047 if path.delegates().is_empty() {
3048 node_borrow.node_state().set_child_link(Some(link));
3049 } else {
3050 let mut current: &dyn ModifierNode = &**node_borrow;
3051 for &delegate_index in path.delegates() {
3052 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3053 current = delegate;
3054 }
3055 }
3056 current.node_state().set_child_link(Some(link));
3057 }
3058 }
3059 }
3060 match &link {
3061 NodeLink::Head => self
3062 .head_sentinel
3063 .node_state()
3064 .set_parent_link(Some(previous)),
3065 NodeLink::Tail => self
3066 .tail_sentinel
3067 .node_state()
3068 .set_parent_link(Some(previous)),
3069 NodeLink::Entry(path) => {
3070 let node_borrow = self.entries[path.entry()].node.borrow();
3071 if path.delegates().is_empty() {
3072 node_borrow.node_state().set_parent_link(Some(previous));
3073 } else {
3074 let mut current: &dyn ModifierNode = &**node_borrow;
3075 for &delegate_index in path.delegates() {
3076 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3077 current = delegate;
3078 }
3079 }
3080 current.node_state().set_parent_link(Some(previous));
3081 }
3082 }
3083 }
3084 previous = link;
3085 }
3086
3087 match &previous {
3088 NodeLink::Head => self
3089 .head_sentinel
3090 .node_state()
3091 .set_child_link(Some(NodeLink::Tail)),
3092 NodeLink::Tail => self
3093 .tail_sentinel
3094 .node_state()
3095 .set_child_link(Some(NodeLink::Tail)),
3096 NodeLink::Entry(path) => {
3097 let node_borrow = self.entries[path.entry()].node.borrow();
3098 if path.delegates().is_empty() {
3099 node_borrow
3100 .node_state()
3101 .set_child_link(Some(NodeLink::Tail));
3102 } else {
3103 let mut current: &dyn ModifierNode = &**node_borrow;
3104 for &delegate_index in path.delegates() {
3105 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3106 current = delegate;
3107 }
3108 }
3109 current.node_state().set_child_link(Some(NodeLink::Tail));
3110 }
3111 }
3112 }
3113 self.tail_sentinel
3114 .node_state()
3115 .set_parent_link(Some(previous));
3116 self.tail_sentinel.node_state().set_child_link(None);
3117
3118 let mut aggregate = NodeCapabilities::empty();
3119 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
3120 aggregate |= *cached_caps;
3121 *cached_aggregate = aggregate;
3122 match link {
3123 NodeLink::Head => {
3124 self.head_sentinel
3125 .node_state()
3126 .set_aggregate_child_capabilities(aggregate);
3127 }
3128 NodeLink::Tail => {
3129 self.tail_sentinel
3130 .node_state()
3131 .set_aggregate_child_capabilities(aggregate);
3132 }
3133 NodeLink::Entry(path) => {
3134 let node_borrow = self.entries[path.entry()].node.borrow();
3135 let state = if path.delegates().is_empty() {
3136 node_borrow.node_state()
3137 } else {
3138 let mut current: &dyn ModifierNode = &**node_borrow;
3139 for &delegate_index in path.delegates() {
3140 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3141 current = delegate;
3142 }
3143 }
3144 current.node_state()
3145 };
3146 state.set_aggregate_child_capabilities(aggregate);
3147 }
3148 }
3149 }
3150
3151 self.aggregated_capabilities = aggregate;
3152 self.head_aggregate_child_capabilities = aggregate;
3153 self.head_sentinel
3154 .node_state()
3155 .set_aggregate_child_capabilities(aggregate);
3156 self.tail_sentinel
3157 .node_state()
3158 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3159 }
3160
3161 fn rebuild_ordered_nodes(&mut self) {
3162 self.ordered_nodes.clear();
3163 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
3164 for (index, entry) in self.entries.iter().enumerate() {
3165 let node_borrow = entry.node.borrow();
3166 Self::enumerate_link_order(
3167 &**node_borrow,
3168 index,
3169 &mut path_buf,
3170 0,
3171 &mut self.ordered_nodes,
3172 );
3173 }
3174 }
3175
3176 fn enumerate_link_order(
3177 node: &dyn ModifierNode,
3178 entry: usize,
3179 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
3180 path_len: usize,
3181 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
3182 ) {
3183 let caps = node.node_state().capabilities();
3184 out.push((
3185 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
3186 caps,
3187 NodeCapabilities::empty(),
3188 ));
3189 let mut delegate_index = 0usize;
3190 node.for_each_delegate(&mut |child| {
3191 if path_len < MAX_DELEGATE_DEPTH {
3192 path_buf[path_len] = delegate_index;
3193 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
3194 }
3195 delegate_index += 1;
3196 });
3197 }
3198}
3199
3200impl<'a> ModifierChainNodeRef<'a> {
3201 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
3202 match &self.link {
3203 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
3204 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
3205 NodeLink::Entry(path) => {
3206 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3207 if path.delegates().is_empty() {
3208 f(node_borrow.node_state())
3209 } else {
3210 let mut current: &dyn ModifierNode = &**node_borrow;
3211 for &delegate_index in path.delegates() {
3212 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3213 current = delegate;
3214 } else {
3215 return f(node_borrow.node_state());
3216 }
3217 }
3218 f(current.node_state())
3219 }
3220 }
3221 }
3222 }
3223
3224 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
3227 match &self.link {
3228 NodeLink::Head => None,
3229 NodeLink::Tail => None,
3230 NodeLink::Entry(path) => {
3231 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3232 if path.delegates().is_empty() {
3233 Some(f(&**node_borrow))
3234 } else {
3235 let mut current: &dyn ModifierNode = &**node_borrow;
3236 for &delegate_index in path.delegates() {
3237 current = nth_delegate(current, delegate_index as usize)?;
3238 }
3239 Some(f(current))
3240 }
3241 }
3242 }
3243 }
3244
3245 #[inline]
3247 pub fn parent(&self) -> Option<Self> {
3248 self.with_state(|state| state.parent_link())
3249 .map(|link| self.chain.make_node_ref(link))
3250 }
3251
3252 #[inline]
3254 pub fn child(&self) -> Option<Self> {
3255 self.with_state(|state| state.child_link())
3256 .map(|link| self.chain.make_node_ref(link))
3257 }
3258
3259 #[inline]
3261 pub fn kind_set(&self) -> NodeCapabilities {
3262 if let Some(caps) = self.cached_capabilities {
3263 return caps;
3264 }
3265 match &self.link {
3266 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
3267 NodeLink::Entry(_) => self.with_state(|state| state.capabilities()),
3268 }
3269 }
3270
3271 pub fn entry_index(&self) -> Option<usize> {
3273 match &self.link {
3274 NodeLink::Entry(path) => Some(path.entry()),
3275 _ => None,
3276 }
3277 }
3278
3279 pub fn delegate_depth(&self) -> usize {
3281 match &self.link {
3282 NodeLink::Entry(path) => path.delegates().len(),
3283 _ => 0,
3284 }
3285 }
3286
3287 #[inline]
3289 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
3290 if let Some(agg) = self.cached_aggregate_child {
3291 return agg;
3292 }
3293 if self.is_tail() {
3294 NodeCapabilities::empty()
3295 } else {
3296 self.with_state(|state| state.aggregate_child_capabilities())
3297 }
3298 }
3299
3300 pub fn is_head(&self) -> bool {
3302 matches!(self.link, NodeLink::Head)
3303 }
3304
3305 pub fn is_tail(&self) -> bool {
3307 matches!(self.link, NodeLink::Tail)
3308 }
3309
3310 pub fn is_sentinel(&self) -> bool {
3312 matches!(self.link, NodeLink::Head | NodeLink::Tail)
3313 }
3314
3315 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
3317 !mask.is_empty() && self.kind_set().intersects(mask)
3318 }
3319
3320 pub fn visit_descendants<F>(self, include_self: bool, mut f: F)
3322 where
3323 F: FnMut(ModifierChainNodeRef<'a>),
3324 {
3325 let mut current = if include_self {
3326 Some(self)
3327 } else {
3328 self.child()
3329 };
3330 while let Some(node) = current {
3331 if node.is_tail() {
3332 break;
3333 }
3334 if !node.is_sentinel() {
3335 f(node.clone());
3336 }
3337 current = node.child();
3338 }
3339 }
3340
3341 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3343 where
3344 F: FnMut(ModifierChainNodeRef<'a>),
3345 {
3346 if mask.is_empty() {
3347 self.visit_descendants(include_self, f);
3348 return;
3349 }
3350
3351 if !self.aggregate_child_capabilities().intersects(mask) {
3352 return;
3353 }
3354
3355 self.visit_descendants(include_self, |node| {
3356 if node.kind_set().intersects(mask) {
3357 f(node);
3358 }
3359 });
3360 }
3361
3362 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
3364 where
3365 F: FnMut(ModifierChainNodeRef<'a>),
3366 {
3367 let mut current = if include_self {
3368 Some(self)
3369 } else {
3370 self.parent()
3371 };
3372 while let Some(node) = current {
3373 if node.is_head() {
3374 break;
3375 }
3376 f(node.clone());
3377 current = node.parent();
3378 }
3379 }
3380
3381 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3383 where
3384 F: FnMut(ModifierChainNodeRef<'a>),
3385 {
3386 if mask.is_empty() {
3387 self.visit_ancestors(include_self, f);
3388 return;
3389 }
3390
3391 self.visit_ancestors(include_self, |node| {
3392 if node.kind_set().intersects(mask) {
3393 f(node);
3394 }
3395 });
3396 }
3397}
3398
3399#[cfg(test)]
3400#[path = "tests/modifier_tests.rs"]
3401mod tests;