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 {
508 fn create_draw_closure(&self) -> Option<NodeDrawClosure> {
519 None
520 }
521
522 fn create_behind_draw_closure(&self) -> Option<NodeDrawClosure> {
527 None
528 }
529}
530
531pub type NodeDrawClosure = Rc<dyn Fn(&mut cranpose_ui_graphics::DrawScopeDefault)>;
536
537pub trait PointerInputNode: ModifierNode {
543 fn on_pointer_event(
546 &mut self,
547 _context: &mut dyn ModifierNodeContext,
548 _event: &PointerEvent,
549 ) -> bool {
550 false
551 }
552
553 fn hit_test(&self, _x: f32, _y: f32) -> bool {
556 true
557 }
558
559 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
561 None
562 }
563
564 fn layout_size_sink(&self) -> Option<Rc<Cell<Size>>> {
577 None
578 }
579}
580
581pub trait SemanticsNode: ModifierNode {
587 fn merge_semantics(&self, _config: &mut SemanticsConfiguration) {}
589
590 fn reach(&self) -> SemanticsReach {
594 let mut config = SemanticsConfiguration::default();
595 self.merge_semantics(&mut config);
596 SemanticsReach {
597 is_modal: config.is_modal,
598 hidden: config.hidden,
599 }
600 }
601}
602
603#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
606pub struct SemanticsReach {
607 pub is_modal: bool,
609 pub hidden: bool,
611}
612
613impl SemanticsReach {
614 pub fn union(self, other: Self) -> Self {
616 Self {
617 is_modal: self.is_modal || other.is_modal,
618 hidden: self.hidden || other.hidden,
619 }
620 }
621}
622
623#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
628pub enum FocusState {
629 Active,
631 ActiveParent,
633 Captured,
637 #[default]
640 Inactive,
641}
642
643impl FocusState {
644 pub fn is_focused(self) -> bool {
646 matches!(self, FocusState::Active | FocusState::Captured)
647 }
648
649 pub fn has_focus(self) -> bool {
651 matches!(
652 self,
653 FocusState::Active | FocusState::ActiveParent | FocusState::Captured
654 )
655 }
656
657 pub fn is_captured(self) -> bool {
659 matches!(self, FocusState::Captured)
660 }
661}
662
663pub trait FocusNode: ModifierNode {
668 fn focus_state(&self) -> FocusState;
670
671 fn on_focus_changed(&mut self, _context: &mut dyn ModifierNodeContext, _state: FocusState) {}
673}
674
675#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
686pub enum SemanticsWidgetRole {
687 Button,
688 Checkbox,
689 Switch,
690 RadioButton,
691 Tab,
692 Image,
693 DropdownList,
696 ValuePicker,
699 Header,
704 Dialog,
708 Link,
711 SearchField,
714 ProgressBar,
717 ToggleButton,
720 Alert,
723 Toolbar,
726 Menu,
728 MenuItem,
730 TabBar,
733 List,
735 ListItem,
737 RadioGroup,
739}
740
741#[derive(Clone, Copy, Debug, PartialEq)]
749pub struct ProgressBarRangeInfo {
750 pub current: f32,
751 pub start: f32,
752 pub end: f32,
753 pub steps: u32,
756}
757
758impl ProgressBarRangeInfo {
759 pub fn new(current: f32, start: f32, end: f32, steps: u32) -> Self {
760 Self {
761 current,
762 start,
763 end,
764 steps,
765 }
766 }
767
768 pub fn fraction(&self) -> f32 {
770 let span = self.end - self.start;
771 if span.abs() < f32::EPSILON {
772 return 0.0;
773 }
774 ((self.current - self.start) / span).clamp(0.0, 1.0)
775 }
776
777 pub fn step(&self) -> f32 {
780 let span = self.end - self.start;
781 if self.steps == 0 {
782 span / 10.0
783 } else {
784 span / (self.steps as f32 + 1.0)
785 }
786 }
787}
788
789#[derive(Clone, Copy, Debug, PartialEq, Eq)]
794pub struct CollectionInfo {
795 pub rows: usize,
796 pub columns: usize,
797}
798
799#[derive(Clone, Copy, Debug, PartialEq)]
810pub struct ScrollAxisRange {
811 pub value: f32,
812 pub max_value: f32,
813 pub reverse: bool,
814 pub content_padding_start: f32,
815 pub content_padding_end: f32,
816}
817
818impl ScrollAxisRange {
819 pub fn new(value: f32, max_value: f32, reverse: bool) -> Self {
820 Self {
821 value,
822 max_value,
823 reverse,
824 content_padding_start: 0.0,
825 content_padding_end: 0.0,
826 }
827 }
828
829 pub fn with_content_padding(self, start: f32, end: f32) -> Self {
832 Self {
833 content_padding_start: start,
834 content_padding_end: end,
835 ..self
836 }
837 }
838
839 pub fn can_scroll_forward(&self) -> bool {
840 self.value < self.max_value
841 }
842
843 pub fn can_scroll_backward(&self) -> bool {
844 self.value > 0.0
845 }
846}
847
848#[derive(Clone)]
854pub struct SemanticsScrollBy {
855 handler: Rc<dyn Fn(f32, f32) -> bool>,
856}
857
858impl SemanticsScrollBy {
859 pub fn new(handler: impl Fn(f32, f32) -> bool + 'static) -> Self {
860 Self {
861 handler: Rc::new(handler),
862 }
863 }
864
865 pub fn invoke(&self, dx: f32, dy: f32) -> bool {
866 (self.handler)(dx, dy)
867 }
868}
869
870impl fmt::Debug for SemanticsScrollBy {
871 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
872 f.debug_struct("SemanticsScrollBy").finish_non_exhaustive()
873 }
874}
875
876impl PartialEq for SemanticsScrollBy {
877 fn eq(&self, _other: &Self) -> bool {
878 true
879 }
880}
881
882impl Eq for SemanticsScrollBy {}
883
884#[derive(Clone)]
890pub struct SemanticsScrollToIndex {
891 handler: Rc<dyn Fn(usize) -> bool>,
892}
893
894impl SemanticsScrollToIndex {
895 pub fn new(handler: impl Fn(usize) -> bool + 'static) -> Self {
896 Self {
897 handler: Rc::new(handler),
898 }
899 }
900
901 pub fn invoke(&self, index: usize) -> bool {
902 (self.handler)(index)
903 }
904}
905
906impl fmt::Debug for SemanticsScrollToIndex {
907 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
908 f.debug_struct("SemanticsScrollToIndex")
909 .finish_non_exhaustive()
910 }
911}
912
913impl PartialEq for SemanticsScrollToIndex {
914 fn eq(&self, _other: &Self) -> bool {
915 true
916 }
917}
918
919impl Eq for SemanticsScrollToIndex {}
920
921#[derive(Clone)]
927pub struct SemanticsSetProgress {
928 handler: Rc<dyn Fn(f32) -> bool>,
929}
930
931impl SemanticsSetProgress {
932 pub fn new(handler: impl Fn(f32) -> bool + 'static) -> Self {
933 Self {
934 handler: Rc::new(handler),
935 }
936 }
937
938 pub fn invoke(&self, value: f32) -> bool {
939 (self.handler)(value)
940 }
941}
942
943impl fmt::Debug for SemanticsSetProgress {
944 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
945 f.debug_struct("SemanticsSetProgress")
946 .finish_non_exhaustive()
947 }
948}
949
950#[derive(Clone)]
954pub struct SemanticsSetText(Rc<dyn Fn(&str) -> bool>);
955
956impl SemanticsSetText {
957 pub fn new(handler: impl Fn(&str) -> bool + 'static) -> Self {
958 Self(Rc::new(handler))
959 }
960
961 pub fn invoke(&self, text: &str) -> bool {
962 (self.0)(text)
963 }
964}
965
966impl fmt::Debug for SemanticsSetText {
967 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
968 f.write_str("SemanticsSetText")
969 }
970}
971
972#[derive(Clone)]
978pub struct SemanticsSetSelection(Rc<dyn Fn(usize, usize) -> bool>);
979
980impl SemanticsSetSelection {
981 pub fn new(handler: impl Fn(usize, usize) -> bool + 'static) -> Self {
982 Self(Rc::new(handler))
983 }
984
985 pub fn invoke(&self, anchor: usize, focus: usize) -> bool {
986 (self.0)(anchor, focus)
987 }
988}
989
990impl fmt::Debug for SemanticsSetSelection {
991 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
992 f.write_str("SemanticsSetSelection")
993 }
994}
995
996#[derive(Clone)]
999pub struct SemanticsExpand(Rc<dyn Fn() -> bool>);
1000
1001impl SemanticsExpand {
1002 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1003 Self(Rc::new(handler))
1004 }
1005
1006 pub fn invoke(&self) -> bool {
1007 (self.0)()
1008 }
1009}
1010
1011impl fmt::Debug for SemanticsExpand {
1012 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1013 f.write_str("SemanticsExpand")
1014 }
1015}
1016
1017#[derive(Clone)]
1021pub struct SemanticsLongClick(Rc<dyn Fn() -> bool>);
1022
1023impl SemanticsLongClick {
1024 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1025 Self(Rc::new(handler))
1026 }
1027
1028 pub fn invoke(&self) -> bool {
1029 (self.0)()
1030 }
1031}
1032
1033impl fmt::Debug for SemanticsLongClick {
1034 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1035 f.write_str("SemanticsLongClick")
1036 }
1037}
1038
1039impl PartialEq for SemanticsLongClick {
1040 fn eq(&self, _other: &Self) -> bool {
1041 true
1042 }
1043}
1044
1045impl PartialEq for SemanticsExpand {
1046 fn eq(&self, _other: &Self) -> bool {
1047 true
1048 }
1049}
1050
1051#[derive(Clone)]
1055pub struct SemanticsDismiss(Rc<dyn Fn() -> bool>);
1056
1057impl SemanticsDismiss {
1058 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1059 Self(Rc::new(handler))
1060 }
1061
1062 pub fn invoke(&self) -> bool {
1063 (self.0)()
1064 }
1065}
1066
1067impl fmt::Debug for SemanticsDismiss {
1068 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1069 f.write_str("SemanticsDismiss")
1070 }
1071}
1072
1073impl PartialEq for SemanticsDismiss {
1074 fn eq(&self, _other: &Self) -> bool {
1075 true
1076 }
1077}
1078
1079impl PartialEq for SemanticsSetText {
1080 fn eq(&self, _other: &Self) -> bool {
1081 true
1082 }
1083}
1084
1085impl PartialEq for SemanticsSetSelection {
1086 fn eq(&self, _other: &Self) -> bool {
1087 true
1088 }
1089}
1090
1091#[derive(Clone)]
1097pub struct SemanticsMagicTap(Rc<dyn Fn() -> bool>);
1098
1099impl SemanticsMagicTap {
1100 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1101 Self(Rc::new(handler))
1102 }
1103
1104 pub fn invoke(&self) -> bool {
1105 (self.0)()
1106 }
1107}
1108
1109impl fmt::Debug for SemanticsMagicTap {
1110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1111 f.write_str("SemanticsMagicTap")
1112 }
1113}
1114
1115impl PartialEq for SemanticsMagicTap {
1116 fn eq(&self, _other: &Self) -> bool {
1117 true
1118 }
1119}
1120
1121impl PartialEq for SemanticsSetProgress {
1122 fn eq(&self, _other: &Self) -> bool {
1123 true
1124 }
1125}
1126
1127impl Eq for SemanticsSetProgress {}
1128
1129#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1136pub enum LiveRegionMode {
1137 Polite,
1139 Assertive,
1142}
1143
1144#[derive(Clone)]
1151pub struct SemanticsCustomAction {
1152 pub label: String,
1154 handler: Rc<dyn Fn()>,
1155}
1156
1157impl SemanticsCustomAction {
1158 pub fn new(label: impl Into<String>, handler: impl Fn() + 'static) -> Self {
1159 Self {
1160 label: label.into(),
1161 handler: Rc::new(handler),
1162 }
1163 }
1164
1165 pub fn invoke(&self) {
1166 (self.handler)();
1167 }
1168}
1169
1170impl fmt::Debug for SemanticsCustomAction {
1171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1172 f.debug_struct("SemanticsCustomAction")
1173 .field("label", &self.label)
1174 .finish_non_exhaustive()
1175 }
1176}
1177
1178impl PartialEq for SemanticsCustomAction {
1179 fn eq(&self, other: &Self) -> bool {
1180 self.label == other.label
1181 }
1182}
1183
1184impl Eq for SemanticsCustomAction {}
1185
1186#[derive(Clone, Debug, PartialEq)]
1201pub struct CanvasSemanticsNode {
1202 pub key: u64,
1209 pub bounds: cranpose_ui_graphics::Rect,
1211 pub label: String,
1212 pub role: Option<SemanticsWidgetRole>,
1213 pub state_description: Option<String>,
1217 pub on_click_label: Option<String>,
1220 pub clickable: bool,
1221 pub selected: Option<bool>,
1223 pub toggled: Option<bool>,
1225 pub enabled: bool,
1226 pub custom_actions: Vec<SemanticsCustomAction>,
1227}
1228
1229impl Default for CanvasSemanticsNode {
1230 fn default() -> Self {
1231 Self {
1232 key: 0,
1233 bounds: cranpose_ui_graphics::Rect {
1234 x: 0.0,
1235 y: 0.0,
1236 width: 0.0,
1237 height: 0.0,
1238 },
1239 label: String::new(),
1240 role: None,
1241 state_description: None,
1242 on_click_label: None,
1243 clickable: false,
1244 selected: None,
1245 toggled: None,
1246 enabled: true,
1247 custom_actions: Vec::new(),
1248 }
1249 }
1250}
1251
1252impl CanvasSemanticsNode {
1253 pub fn control(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1255 Self {
1256 key,
1257 bounds,
1258 label: label.into(),
1259 clickable: true,
1260 ..Self::default()
1261 }
1262 }
1263
1264 pub fn text(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1266 Self {
1267 key,
1268 bounds,
1269 label: label.into(),
1270 ..Self::default()
1271 }
1272 }
1273
1274 pub fn with_role(mut self, role: SemanticsWidgetRole) -> Self {
1275 self.role = Some(role);
1276 self
1277 }
1278
1279 pub fn with_state_description(mut self, state: impl Into<String>) -> Self {
1280 self.state_description = Some(state.into());
1281 self
1282 }
1283
1284 pub fn with_click_label(mut self, label: impl Into<String>) -> Self {
1285 self.on_click_label = Some(label.into());
1286 self.clickable = true;
1287 self
1288 }
1289
1290 pub fn with_selected(mut self, selected: bool) -> Self {
1291 self.selected = Some(selected);
1292 self
1293 }
1294
1295 pub fn with_toggled(mut self, toggled: bool) -> Self {
1296 self.toggled = Some(toggled);
1297 self
1298 }
1299
1300 pub fn with_enabled(mut self, enabled: bool) -> Self {
1301 self.enabled = enabled;
1302 self
1303 }
1304
1305 pub fn with_custom_action(mut self, action: SemanticsCustomAction) -> Self {
1306 self.custom_actions.push(action);
1307 self
1308 }
1309}
1310
1311#[derive(Clone, Debug, PartialEq)]
1313pub struct SemanticsConfiguration {
1314 pub content_description: Option<String>,
1315 pub state_description: Option<String>,
1317 pub on_click_label: Option<String>,
1319 pub on_click: Option<SemanticsCustomAction>,
1322 pub on_long_click: Option<SemanticsLongClick>,
1325 pub on_long_click_label: Option<String>,
1328 pub on_magic_tap: Option<SemanticsMagicTap>,
1332 pub on_magic_tap_label: Option<String>,
1335 pub input_labels: Vec<String>,
1339 pub language: Option<String>,
1343 pub role: Option<SemanticsWidgetRole>,
1345 pub selected: Option<bool>,
1346 pub toggled: Option<bool>,
1347 pub enabled: bool,
1348 pub is_clickable: bool,
1349 pub is_editable_text: bool,
1350 pub multiline: bool,
1352 pub text: Option<String>,
1355 pub text_selection: Option<crate::text::TextRange>,
1356 pub custom_actions: Vec<SemanticsCustomAction>,
1357 pub canvas_children: Vec<CanvasSemanticsNode>,
1360 pub is_modal: bool,
1363 pub hidden: bool,
1367 pub merge_descendants: bool,
1371 pub selectable_group: bool,
1375 pub pane_title: Option<String>,
1378 pub error: Option<String>,
1381 pub password: bool,
1384 pub traversal_index: f32,
1388 pub live_region: Option<LiveRegionMode>,
1391 pub progress: Option<ProgressBarRangeInfo>,
1394 pub set_progress: Option<SemanticsSetProgress>,
1397 pub set_text: Option<SemanticsSetText>,
1400 pub set_selection: Option<SemanticsSetSelection>,
1403 pub expand: Option<SemanticsExpand>,
1406 pub dismiss: Option<SemanticsDismiss>,
1410 pub collapse: Option<SemanticsExpand>,
1413 pub vertical_scroll: Option<ScrollAxisRange>,
1416 pub horizontal_scroll: Option<ScrollAxisRange>,
1419 pub scroll_by: Option<SemanticsScrollBy>,
1422 pub scroll_to_index: Option<SemanticsScrollToIndex>,
1426 pub collection: Option<CollectionInfo>,
1428}
1429
1430impl Default for SemanticsConfiguration {
1431 fn default() -> Self {
1432 Self {
1433 content_description: None,
1434 state_description: None,
1435 on_click_label: None,
1436 on_click: None,
1437 on_long_click: None,
1438 on_long_click_label: None,
1439 on_magic_tap: None,
1440 on_magic_tap_label: None,
1441 input_labels: Vec::new(),
1442 language: None,
1443 role: None,
1444 selected: None,
1445 toggled: None,
1446 enabled: true,
1447 is_clickable: false,
1448 is_editable_text: false,
1449 multiline: false,
1450 text: None,
1451 text_selection: None,
1452 custom_actions: Vec::new(),
1453 canvas_children: Vec::new(),
1454 is_modal: false,
1455 hidden: false,
1456 merge_descendants: false,
1457 selectable_group: false,
1458 pane_title: None,
1459 error: None,
1460 password: false,
1461 traversal_index: 0.0,
1462 live_region: None,
1463 progress: None,
1464 set_progress: None,
1465 set_text: None,
1466 set_selection: None,
1467 expand: None,
1468 dismiss: None,
1469 collapse: None,
1470 vertical_scroll: None,
1471 horizontal_scroll: None,
1472 scroll_by: None,
1473 scroll_to_index: None,
1474 collection: None,
1475 }
1476 }
1477}
1478
1479pub type SemanticsSpec = SemanticsConfiguration;
1488
1489impl SemanticsConfiguration {
1490 pub fn new() -> Self {
1493 Self::default()
1494 }
1495
1496 pub fn content_description(mut self, name: impl Into<String>) -> Self {
1499 self.content_description = Some(name.into());
1500 self
1501 }
1502
1503 pub fn state_description(mut self, state: impl Into<String>) -> Self {
1506 self.state_description = Some(state.into());
1507 self
1508 }
1509
1510 pub fn clickable(mut self) -> Self {
1512 self.is_clickable = true;
1513 self
1514 }
1515
1516 pub fn on_click(mut self, label: impl Into<String>, action: impl Fn() + 'static) -> Self {
1519 self.on_click = Some(SemanticsCustomAction::new(label, action));
1520 self
1521 }
1522
1523 pub fn on_long_click(
1527 mut self,
1528 label: impl Into<String>,
1529 action: impl Fn() -> bool + 'static,
1530 ) -> Self {
1531 self.on_long_click_label = Some(label.into());
1532 self.on_long_click = Some(SemanticsLongClick::new(action));
1533 self
1534 }
1535
1536 pub fn on_magic_tap(
1540 mut self,
1541 label: impl Into<String>,
1542 action: impl Fn() -> bool + 'static,
1543 ) -> Self {
1544 self.on_magic_tap_label = Some(label.into());
1545 self.on_magic_tap = Some(SemanticsMagicTap::new(action));
1546 self
1547 }
1548
1549 pub fn input_labels<S: Into<String>>(mut self, labels: impl IntoIterator<Item = S>) -> Self {
1552 self.input_labels = labels.into_iter().map(Into::into).collect();
1553 self
1554 }
1555
1556 pub fn language(mut self, tag: impl Into<String>) -> Self {
1559 self.language = Some(tag.into());
1560 self
1561 }
1562
1563 pub fn toggled(mut self, toggled: bool) -> Self {
1565 self.toggled = Some(toggled);
1566 self
1567 }
1568
1569 pub fn selected(mut self, selected: bool) -> Self {
1572 self.selected = Some(selected);
1573 self
1574 }
1575
1576 pub fn role(mut self, role: SemanticsWidgetRole) -> Self {
1578 self.role = Some(role);
1579 self
1580 }
1581
1582 pub fn heading(self) -> Self {
1585 self.role(SemanticsWidgetRole::Header)
1586 }
1587
1588 pub fn error(mut self, message: impl Into<String>) -> Self {
1590 self.error = Some(message.into());
1591 self
1592 }
1593
1594 pub fn password(mut self) -> Self {
1596 self.password = true;
1597 self
1598 }
1599
1600 pub fn pane_title(mut self, title: impl Into<String>) -> Self {
1603 self.pane_title = Some(title.into());
1604 self
1605 }
1606
1607 pub fn traversal_index(mut self, index: f32) -> Self {
1610 self.traversal_index = index;
1611 self
1612 }
1613
1614 pub fn hidden(mut self) -> Self {
1617 self.hidden = true;
1618 self
1619 }
1620
1621 pub fn merge_descendants(mut self) -> Self {
1624 self.merge_descendants = true;
1625 self
1626 }
1627
1628 pub fn selectable_group(mut self) -> Self {
1631 self.selectable_group = true;
1632 self
1633 }
1634
1635 pub fn live_region(mut self, mode: LiveRegionMode) -> Self {
1638 self.live_region = Some(mode);
1639 self
1640 }
1641 pub fn merge(&mut self, other: &SemanticsConfiguration) {
1642 if let Some(description) = &other.content_description {
1643 self.content_description = Some(description.clone());
1644 }
1645 if let Some(state) = &other.state_description {
1646 self.state_description = Some(state.clone());
1647 }
1648 if let Some(label) = &other.on_click_label {
1649 self.on_click_label = Some(label.clone());
1650 }
1651 if let Some(label) = &other.on_long_click_label {
1652 self.on_long_click_label = Some(label.clone());
1653 }
1654 if let Some(label) = &other.on_magic_tap_label {
1655 self.on_magic_tap_label = Some(label.clone());
1656 }
1657 if !other.input_labels.is_empty() {
1658 self.input_labels.clone_from(&other.input_labels);
1659 }
1660 if let Some(language) = &other.language {
1661 self.language = Some(language.clone());
1662 }
1663 if let Some(role) = other.role {
1664 self.role = Some(role);
1665 }
1666 if let Some(selected) = other.selected {
1667 self.selected = Some(selected);
1668 }
1669 if let Some(toggled) = other.toggled {
1670 self.toggled = Some(toggled);
1671 }
1672 self.enabled &= other.enabled;
1673 self.is_clickable |= other.is_clickable;
1674 self.is_editable_text |= other.is_editable_text;
1675 self.multiline |= other.multiline;
1676 if let Some(text) = &other.text {
1677 self.text = Some(text.clone());
1678 }
1679 self.is_modal |= other.is_modal;
1680 self.hidden |= other.hidden;
1681 self.merge_descendants |= other.merge_descendants;
1682 self.selectable_group |= other.selectable_group;
1683 self.password |= other.password;
1684 if other.traversal_index != 0.0 {
1685 self.traversal_index = other.traversal_index;
1686 }
1687 if let Some(live_region) = other.live_region {
1688 self.live_region = Some(live_region);
1689 }
1690 self.merge_words(other);
1691 self.merge_actions(other);
1692 self.merge_ranges(other);
1693 }
1694
1695 fn merge_words(&mut self, other: &SemanticsConfiguration) {
1696 if let Some(title) = &other.pane_title {
1697 self.pane_title = Some(title.clone());
1698 }
1699 if let Some(error) = &other.error {
1700 self.error = Some(error.clone());
1701 }
1702 }
1703
1704 fn merge_actions(&mut self, other: &SemanticsConfiguration) {
1705 if let Some(on_click) = &other.on_click {
1706 self.on_click = Some(on_click.clone());
1707 }
1708 self.custom_actions
1709 .extend(other.custom_actions.iter().cloned());
1710 self.canvas_children
1711 .extend(other.canvas_children.iter().cloned());
1712 if let Some(set_progress) = &other.set_progress {
1713 self.set_progress = Some(set_progress.clone());
1714 }
1715 if let Some(set_text) = &other.set_text {
1716 self.set_text = Some(set_text.clone());
1717 }
1718 if let Some(set_selection) = &other.set_selection {
1719 self.set_selection = Some(set_selection.clone());
1720 }
1721 if let Some(expand) = &other.expand {
1722 self.expand = Some(expand.clone());
1723 }
1724 if let Some(collapse) = &other.collapse {
1725 self.collapse = Some(collapse.clone());
1726 }
1727 if let Some(dismiss) = &other.dismiss {
1728 self.dismiss = Some(dismiss.clone());
1729 }
1730 if let Some(long_click) = &other.on_long_click {
1731 self.on_long_click = Some(long_click.clone());
1732 }
1733 if let Some(magic_tap) = &other.on_magic_tap {
1734 self.on_magic_tap = Some(magic_tap.clone());
1735 }
1736 if let Some(scroll_by) = &other.scroll_by {
1737 self.scroll_by = Some(scroll_by.clone());
1738 }
1739 if let Some(scroll_to_index) = &other.scroll_to_index {
1740 self.scroll_to_index = Some(scroll_to_index.clone());
1741 }
1742 }
1743
1744 fn merge_ranges(&mut self, other: &SemanticsConfiguration) {
1745 if let Some(selection) = other.text_selection {
1746 self.text_selection = Some(selection);
1747 }
1748 if let Some(progress) = other.progress {
1749 self.progress = Some(progress);
1750 }
1751 if let Some(range) = other.vertical_scroll {
1752 self.vertical_scroll = Some(range);
1753 }
1754 if let Some(range) = other.horizontal_scroll {
1755 self.horizontal_scroll = Some(range);
1756 }
1757 if let Some(collection) = other.collection {
1758 self.collection = Some(collection);
1759 }
1760 }
1761
1762 pub fn is_activatable(&self) -> bool {
1765 self.is_clickable || self.on_click_label.is_some() || self.on_click.is_some()
1766 }
1767}
1768
1769impl fmt::Debug for dyn ModifierNode {
1770 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1771 f.debug_struct("ModifierNode").finish_non_exhaustive()
1772 }
1773}
1774
1775impl dyn ModifierNode {
1776 pub fn as_any(&self) -> &dyn Any {
1777 self
1778 }
1779
1780 pub fn as_any_mut(&mut self) -> &mut dyn Any {
1781 self
1782 }
1783}
1784
1785pub trait ModifierNodeElement: fmt::Debug + Hash + PartialEq + 'static {
1788 type Node: ModifierNode;
1789
1790 fn create(&self) -> Self::Node;
1792
1793 fn update(&self, node: &mut Self::Node);
1795
1796 fn key(&self) -> Option<u64> {
1798 None
1799 }
1800
1801 fn inspector_name(&self) -> &'static str {
1803 type_name::<Self>()
1804 }
1805
1806 fn inspector_properties(&self, _inspector: &mut dyn FnMut(&'static str, String)) {}
1808
1809 fn capabilities(&self) -> NodeCapabilities {
1812 NodeCapabilities::default()
1813 }
1814
1815 fn always_update(&self) -> bool {
1821 false
1822 }
1823
1824 fn auto_invalidate_on_update(&self) -> bool {
1827 true
1828 }
1829
1830 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
1837 None
1838 }
1839
1840 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
1847 Vec::new()
1848 }
1849}
1850
1851#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1853pub struct NodeCapabilities(u32);
1854
1855impl NodeCapabilities {
1856 pub const NONE: Self = Self(0);
1858 pub const LAYOUT: Self = Self(1 << 0);
1860 pub const DRAW: Self = Self(1 << 1);
1862 pub const POINTER_INPUT: Self = Self(1 << 2);
1864 pub const SEMANTICS: Self = Self(1 << 3);
1866 pub const MODIFIER_LOCALS: Self = Self(1 << 4);
1868 pub const FOCUS: Self = Self(1 << 5);
1870 pub const WINDOW_ROOT: Self = Self(1 << 6);
1874
1875 pub const fn empty() -> Self {
1877 Self::NONE
1878 }
1879
1880 pub const fn contains(self, other: Self) -> bool {
1882 (self.0 & other.0) == other.0
1883 }
1884
1885 pub const fn intersects(self, other: Self) -> bool {
1887 (self.0 & other.0) != 0
1888 }
1889
1890 pub fn insert(&mut self, other: Self) {
1892 self.0 |= other.0;
1893 }
1894
1895 pub const fn bits(self) -> u32 {
1897 self.0
1898 }
1899
1900 pub const fn is_empty(self) -> bool {
1902 self.0 == 0
1903 }
1904
1905 pub const fn for_invalidation(kind: InvalidationKind) -> Self {
1907 match kind {
1908 InvalidationKind::Layout => Self::LAYOUT,
1909 InvalidationKind::Draw => Self::DRAW,
1910 InvalidationKind::PointerInput => Self::POINTER_INPUT,
1911 InvalidationKind::Semantics => Self::SEMANTICS,
1912 InvalidationKind::Focus => Self::FOCUS,
1913 }
1914 }
1915}
1916
1917impl Default for NodeCapabilities {
1918 fn default() -> Self {
1919 Self::NONE
1920 }
1921}
1922
1923impl fmt::Debug for NodeCapabilities {
1924 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1925 f.debug_struct("NodeCapabilities")
1926 .field("layout", &self.contains(Self::LAYOUT))
1927 .field("draw", &self.contains(Self::DRAW))
1928 .field("pointer_input", &self.contains(Self::POINTER_INPUT))
1929 .field("semantics", &self.contains(Self::SEMANTICS))
1930 .field("modifier_locals", &self.contains(Self::MODIFIER_LOCALS))
1931 .field("focus", &self.contains(Self::FOCUS))
1932 .field("window_root", &self.contains(Self::WINDOW_ROOT))
1933 .finish()
1934 }
1935}
1936
1937impl BitOr for NodeCapabilities {
1938 type Output = Self;
1939
1940 fn bitor(self, rhs: Self) -> Self::Output {
1941 Self(self.0 | rhs.0)
1942 }
1943}
1944
1945impl BitOrAssign for NodeCapabilities {
1946 fn bitor_assign(&mut self, rhs: Self) {
1947 self.0 |= rhs.0;
1948 }
1949}
1950
1951#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1953pub struct ModifierInvalidation {
1954 kind: InvalidationKind,
1955 capabilities: NodeCapabilities,
1956}
1957
1958impl ModifierInvalidation {
1959 pub const fn new(kind: InvalidationKind, capabilities: NodeCapabilities) -> Self {
1961 Self { kind, capabilities }
1962 }
1963
1964 pub const fn kind(self) -> InvalidationKind {
1966 self.kind
1967 }
1968
1969 pub const fn capabilities(self) -> NodeCapabilities {
1971 self.capabilities
1972 }
1973}
1974
1975pub trait AnyModifierElement: fmt::Debug {
1977 fn node_type(&self) -> TypeId;
1978
1979 fn element_type(&self) -> TypeId;
1980
1981 fn create_node(&self) -> Box<dyn ModifierNode>;
1982
1983 fn can_update_node(&self, node: &dyn ModifierNode) -> bool;
1984
1985 fn update_node(&self, node: &mut dyn ModifierNode);
1986
1987 fn key(&self) -> Option<u64>;
1988
1989 fn capabilities(&self) -> NodeCapabilities {
1990 NodeCapabilities::default()
1991 }
1992
1993 fn hash_code(&self) -> u64;
1994
1995 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool;
1996
1997 fn inspector_name(&self) -> &'static str;
1998
1999 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String));
2000
2001 fn requires_update(&self) -> bool;
2002
2003 fn auto_invalidates_on_update(&self) -> bool;
2004
2005 fn update_invalidation_kind(&self) -> Option<InvalidationKind>;
2006
2007 fn provides_composition_locals(&self) -> bool {
2009 false
2010 }
2011
2012 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2014 Vec::new()
2015 }
2016
2017 fn as_any(&self) -> &dyn Any;
2018}
2019
2020struct TypedModifierElement<E: ModifierNodeElement> {
2021 element: E,
2022 cached_hash: u64,
2023 provides_locals: bool,
2024}
2025
2026impl<E: ModifierNodeElement> TypedModifierElement<E> {
2027 fn new(element: E) -> Self {
2028 let mut hasher = default::new();
2029 element.hash(&mut hasher);
2030 let provides_locals = !element.provided_composition_locals().is_empty();
2031 Self {
2032 element,
2033 cached_hash: hasher.finish(),
2034 provides_locals,
2035 }
2036 }
2037}
2038
2039impl<E> fmt::Debug for TypedModifierElement<E>
2040where
2041 E: ModifierNodeElement,
2042{
2043 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2044 f.debug_struct("TypedModifierElement")
2045 .field("type", &type_name::<E>())
2046 .finish()
2047 }
2048}
2049
2050impl<E> AnyModifierElement for TypedModifierElement<E>
2051where
2052 E: ModifierNodeElement,
2053{
2054 fn node_type(&self) -> TypeId {
2055 TypeId::of::<E::Node>()
2056 }
2057
2058 fn element_type(&self) -> TypeId {
2059 TypeId::of::<E>()
2060 }
2061
2062 fn create_node(&self) -> Box<dyn ModifierNode> {
2063 Box::new(self.element.create())
2064 }
2065
2066 fn can_update_node(&self, node: &dyn ModifierNode) -> bool {
2067 node.as_any().is::<E::Node>()
2068 }
2069
2070 fn update_node(&self, node: &mut dyn ModifierNode) {
2071 if let Some(typed) = node.as_any_mut().downcast_mut::<E::Node>() {
2072 self.element.update(typed);
2073 }
2074 }
2075
2076 fn key(&self) -> Option<u64> {
2077 self.element.key()
2078 }
2079
2080 fn capabilities(&self) -> NodeCapabilities {
2081 self.element.capabilities()
2082 }
2083
2084 fn provides_composition_locals(&self) -> bool {
2085 self.provides_locals
2086 }
2087
2088 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2089 self.element.provided_composition_locals()
2090 }
2091
2092 fn hash_code(&self) -> u64 {
2093 self.cached_hash
2094 }
2095
2096 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool {
2097 other
2098 .as_any()
2099 .downcast_ref::<Self>()
2100 .is_some_and(|typed| typed.element == self.element)
2101 }
2102
2103 fn inspector_name(&self) -> &'static str {
2104 self.element.inspector_name()
2105 }
2106
2107 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String)) {
2108 self.element.inspector_properties(visitor);
2109 }
2110
2111 fn requires_update(&self) -> bool {
2112 self.element.always_update()
2113 }
2114
2115 fn auto_invalidates_on_update(&self) -> bool {
2116 self.element.auto_invalidate_on_update()
2117 }
2118
2119 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
2120 self.element.update_invalidation_kind()
2121 }
2122
2123 fn as_any(&self) -> &dyn Any {
2124 self
2125 }
2126}
2127
2128fn request_update_auto_invalidations(
2129 element: &dyn AnyModifierElement,
2130 context: &mut dyn ModifierNodeContext,
2131 capabilities: NodeCapabilities,
2132) {
2133 if let Some(kind) = element.update_invalidation_kind() {
2134 let capabilities = NodeCapabilities::for_invalidation(kind);
2135 context.push_active_capabilities(capabilities);
2136 context.invalidate(kind);
2137 context.pop_active_capabilities();
2138 } else if element.auto_invalidates_on_update() {
2139 request_auto_invalidations(context, capabilities);
2140 }
2141}
2142
2143pub fn modifier_element<E: ModifierNodeElement>(element: E) -> DynModifierElement {
2146 Rc::new(TypedModifierElement::new(element))
2147}
2148
2149pub type DynModifierElement = Rc<dyn AnyModifierElement>;
2151
2152#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2153enum TraversalDirection {
2154 Forward,
2155 Backward,
2156}
2157
2158pub struct ModifierChainIter<'a> {
2163 chain: &'a ModifierNodeChain,
2164 cursor: usize,
2165 remaining: usize,
2166 direction: TraversalDirection,
2167}
2168
2169impl<'a> ModifierChainIter<'a> {
2170 fn forward(chain: &'a ModifierNodeChain) -> Self {
2171 Self {
2172 chain,
2173 cursor: 0,
2174 remaining: chain.ordered_nodes.len(),
2175 direction: TraversalDirection::Forward,
2176 }
2177 }
2178
2179 fn backward(chain: &'a ModifierNodeChain) -> Self {
2180 let len = chain.ordered_nodes.len();
2181 Self {
2182 chain,
2183 cursor: len.wrapping_sub(1),
2184 remaining: len,
2185 direction: TraversalDirection::Backward,
2186 }
2187 }
2188}
2189
2190impl<'a> Iterator for ModifierChainIter<'a> {
2191 type Item = ModifierChainNodeRef<'a>;
2192
2193 #[inline]
2194 fn next(&mut self) -> Option<Self::Item> {
2195 if self.remaining == 0 {
2196 return None;
2197 }
2198 let (link, caps, agg) = self.chain.ordered_nodes[self.cursor];
2199 let node_ref = self.chain.make_node_ref_with_caps(link, caps, agg);
2200 self.remaining -= 1;
2201 match self.direction {
2202 TraversalDirection::Forward => self.cursor += 1,
2203 TraversalDirection::Backward => self.cursor = self.cursor.wrapping_sub(1),
2204 }
2205 Some(node_ref)
2206 }
2207
2208 #[inline]
2209 fn size_hint(&self) -> (usize, Option<usize>) {
2210 (self.remaining, Some(self.remaining))
2211 }
2212}
2213
2214impl ExactSizeIterator for ModifierChainIter<'_> {}
2215impl std::iter::FusedIterator for ModifierChainIter<'_> {}
2216
2217#[derive(Debug)]
2218struct ModifierNodeEntry {
2219 element_type: TypeId,
2220 node_type: TypeId,
2221 key: Option<u64>,
2222 hash_code: u64,
2223 element: DynModifierElement,
2224 node: Rc<RefCell<Box<dyn ModifierNode>>>,
2225 capabilities: NodeCapabilities,
2226}
2227
2228impl ModifierNodeEntry {
2229 fn new(
2230 element_type: TypeId,
2231 node_type: TypeId,
2232 key: Option<u64>,
2233 element: DynModifierElement,
2234 node: Box<dyn ModifierNode>,
2235 hash_code: u64,
2236 capabilities: NodeCapabilities,
2237 ) -> Self {
2238 let node_rc = Rc::new(RefCell::new(node));
2239 let entry = Self {
2240 element_type,
2241 node_type,
2242 key,
2243 hash_code,
2244 element,
2245 node: Rc::clone(&node_rc),
2246 capabilities,
2247 };
2248 entry
2249 .node
2250 .borrow()
2251 .node_state()
2252 .set_capabilities(entry.capabilities);
2253 entry
2254 }
2255}
2256
2257fn visit_node_tree_mut(
2258 node: &mut dyn ModifierNode,
2259 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
2260) {
2261 visitor(node);
2262 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
2263}
2264
2265fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
2266 let mut current = 0usize;
2267 let mut result: Option<&dyn ModifierNode> = None;
2268 node.for_each_delegate(&mut |child| {
2269 if result.is_none() && current == target {
2270 result = Some(child);
2271 }
2272 current += 1;
2273 });
2274 result
2275}
2276
2277fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
2278 let mut current = 0usize;
2279 let mut result: Option<&mut dyn ModifierNode> = None;
2280 node.for_each_delegate_mut(&mut |child| {
2281 if result.is_none() && current == target {
2282 result = Some(child);
2283 }
2284 current += 1;
2285 });
2286 result
2287}
2288
2289fn with_node_context<F, R>(
2290 node: &mut dyn ModifierNode,
2291 context: &mut dyn ModifierNodeContext,
2292 f: F,
2293) -> R
2294where
2295 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
2296{
2297 context.push_active_capabilities(node.node_state().capabilities());
2298 let result = f(node, context);
2299 context.pop_active_capabilities();
2300 result
2301}
2302
2303fn request_auto_invalidations(
2304 context: &mut dyn ModifierNodeContext,
2305 capabilities: NodeCapabilities,
2306) {
2307 if capabilities.is_empty() {
2308 return;
2309 }
2310
2311 context.push_active_capabilities(capabilities);
2312
2313 if capabilities.contains(NodeCapabilities::LAYOUT) {
2314 context.invalidate(InvalidationKind::Layout);
2315 }
2316 if capabilities.contains(NodeCapabilities::DRAW) {
2317 context.invalidate(InvalidationKind::Draw);
2318 }
2319 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
2320 context.invalidate(InvalidationKind::PointerInput);
2321 }
2322 if capabilities.contains(NodeCapabilities::SEMANTICS) {
2323 context.invalidate(InvalidationKind::Semantics);
2324 }
2325 if capabilities.contains(NodeCapabilities::FOCUS) {
2326 context.invalidate(InvalidationKind::Focus);
2327 }
2328
2329 context.pop_active_capabilities();
2330}
2331
2332fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
2333 visit_node_tree_mut(node, &mut |n| {
2334 if !n.node_state().is_attached() {
2335 n.node_state().set_attached(true);
2336 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
2337 }
2338 });
2339}
2340
2341fn reset_node_tree(node: &mut dyn ModifierNode) {
2342 visit_node_tree_mut(node, &mut |n| n.on_reset());
2343}
2344
2345fn detach_node_tree(node: &mut dyn ModifierNode) {
2346 visit_node_tree_mut(node, &mut |n| {
2347 if n.node_state().is_attached() {
2348 n.on_detach();
2349 n.node_state().set_attached(false);
2350 }
2351 n.node_state().set_parent_link(None);
2352 n.node_state().set_child_link(None);
2353 n.node_state()
2354 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2355 });
2356}
2357
2358pub struct ModifierNodeChain {
2365 entries: Vec<ModifierNodeEntry>,
2366 aggregated_capabilities: NodeCapabilities,
2367 head_aggregate_child_capabilities: NodeCapabilities,
2368 head_sentinel: Box<SentinelNode>,
2369 tail_sentinel: Box<SentinelNode>,
2370 ordered_nodes: Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
2371 scratch_old_used: Vec<bool>,
2372 scratch_match_order: Vec<Option<usize>>,
2373 scratch_final_slots: Vec<Option<ModifierNodeEntry>>,
2374 scratch_elements: Vec<DynModifierElement>,
2375}
2376
2377struct SentinelNode {
2378 state: NodeState,
2379}
2380
2381impl SentinelNode {
2382 fn new() -> Self {
2383 Self {
2384 state: NodeState::sentinel(),
2385 }
2386 }
2387}
2388
2389impl DelegatableNode for SentinelNode {
2390 fn node_state(&self) -> &NodeState {
2391 &self.state
2392 }
2393}
2394
2395impl ModifierNode for SentinelNode {}
2396
2397#[derive(Clone)]
2398pub struct ModifierChainNodeRef<'a> {
2399 chain: &'a ModifierNodeChain,
2400 link: NodeLink,
2401 cached_capabilities: Option<NodeCapabilities>,
2402 cached_aggregate_child: Option<NodeCapabilities>,
2403}
2404
2405impl Default for ModifierNodeChain {
2406 fn default() -> Self {
2407 Self::new()
2408 }
2409}
2410
2411struct EntryIndex {
2412 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2413 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2414 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
2415}
2416
2417struct EntryMatchQuery<'a> {
2418 element_type: TypeId,
2419 node_type: TypeId,
2420 key: Option<u64>,
2421 hash_code: u64,
2422 element: &'a DynModifierElement,
2423}
2424
2425impl EntryIndex {
2426 fn build(entries: &[ModifierNodeEntry]) -> Self {
2427 let mut keyed = HashMap::default();
2428 let mut hashed = HashMap::default();
2429 let mut typed = HashMap::default();
2430
2431 for (i, entry) in entries.iter().enumerate() {
2432 if let Some(key_value) = entry.key {
2433 keyed
2434 .entry((entry.element_type, entry.node_type, key_value))
2435 .or_insert_with(Vec::new)
2436 .push(i);
2437 } else {
2438 hashed
2439 .entry((entry.element_type, entry.node_type, entry.hash_code))
2440 .or_insert_with(Vec::new)
2441 .push(i);
2442 typed
2443 .entry((entry.element_type, entry.node_type))
2444 .or_insert_with(Vec::new)
2445 .push(i);
2446 }
2447 }
2448
2449 Self {
2450 keyed,
2451 hashed,
2452 typed,
2453 }
2454 }
2455
2456 fn find_match(
2457 &self,
2458 entries: &[ModifierNodeEntry],
2459 used: &[bool],
2460 query: EntryMatchQuery<'_>,
2461 ) -> Option<usize> {
2462 if let Some(key_value) = query.key {
2463 if let Some(candidates) =
2464 self.keyed
2465 .get(&(query.element_type, query.node_type, key_value))
2466 {
2467 for &i in candidates {
2468 if !used[i] {
2469 return Some(i);
2470 }
2471 }
2472 }
2473 } else {
2474 if let Some(candidates) =
2475 self.hashed
2476 .get(&(query.element_type, query.node_type, query.hash_code))
2477 {
2478 for &i in candidates {
2479 if !used[i]
2480 && entries[i]
2481 .element
2482 .as_ref()
2483 .equals_element(query.element.as_ref())
2484 {
2485 return Some(i);
2486 }
2487 }
2488 }
2489
2490 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
2491 for &i in candidates {
2492 if !used[i] {
2493 return Some(i);
2494 }
2495 }
2496 }
2497 }
2498
2499 None
2500 }
2501}
2502
2503impl ModifierNodeChain {
2504 pub fn new() -> Self {
2505 let mut chain = Self {
2506 entries: Vec::new(),
2507 aggregated_capabilities: NodeCapabilities::empty(),
2508 head_aggregate_child_capabilities: NodeCapabilities::empty(),
2509 head_sentinel: Box::new(SentinelNode::new()),
2510 tail_sentinel: Box::new(SentinelNode::new()),
2511 ordered_nodes: Vec::new(),
2512 scratch_old_used: Vec::new(),
2513 scratch_match_order: Vec::new(),
2514 scratch_final_slots: Vec::new(),
2515 scratch_elements: Vec::new(),
2516 };
2517 chain.sync_chain_links();
2518 chain
2519 }
2520
2521 pub fn detach_nodes(&mut self) {
2523 for entry in &self.entries {
2524 detach_node_tree(&mut **entry.node.borrow_mut());
2525 }
2526 }
2527
2528 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
2530 for entry in &self.entries {
2531 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2532 }
2533 }
2534
2535 pub fn repair_chain(&mut self) {
2538 self.sync_chain_links();
2539 }
2540
2541 pub fn update_from_slice(
2547 &mut self,
2548 elements: &[DynModifierElement],
2549 context: &mut dyn ModifierNodeContext,
2550 ) {
2551 self.update_from_ref_iter(elements.iter(), context);
2552 }
2553
2554 pub fn update_from_ref_iter<'a, I>(
2559 &mut self,
2560 elements: I,
2561 context: &mut dyn ModifierNodeContext,
2562 ) where
2563 I: Iterator<Item = &'a DynModifierElement>,
2564 {
2565 let old_len = self.entries.len();
2566 let mut fast_path_failed_at: Option<usize> = None;
2567 let mut elements_count = 0;
2568
2569 self.scratch_elements.clear();
2570
2571 for (idx, element) in elements.enumerate() {
2572 elements_count = idx + 1;
2573
2574 if fast_path_failed_at.is_none() && idx < old_len {
2575 let entry = &mut self.entries[idx];
2576 let same_type = entry.element_type == element.element_type();
2577 let same_node_type = entry.node_type == element.node_type();
2578 let same_key = entry.key == element.key();
2579 let same_hash = entry.hash_code == element.hash_code();
2580
2581 let positional_update = element.requires_update();
2582 if same_type && same_node_type && same_key && (same_hash || positional_update) {
2583 let can_update_node = {
2584 let node_borrow = entry.node.borrow();
2585 element.can_update_node(&**node_borrow)
2586 };
2587 if !can_update_node {
2588 fast_path_failed_at = Some(idx);
2589 self.scratch_elements.push(element.clone());
2590 continue;
2591 }
2592
2593 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2594 let capabilities = element.capabilities();
2595
2596 {
2597 let node_borrow = entry.node.borrow();
2598 if !node_borrow.node_state().is_attached() {
2599 drop(node_borrow);
2600 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2601 }
2602 }
2603
2604 let needs_update = !same_element || element.requires_update();
2605 if needs_update {
2606 element.update_node(&mut **entry.node.borrow_mut());
2607 entry.element = element.clone();
2608 entry.hash_code = element.hash_code();
2609 request_update_auto_invalidations(element.as_ref(), context, capabilities);
2610 }
2611
2612 entry.capabilities = capabilities;
2613 entry
2614 .node
2615 .borrow()
2616 .node_state()
2617 .set_capabilities(capabilities);
2618 continue;
2619 }
2620 fast_path_failed_at = Some(idx);
2621 }
2622
2623 self.scratch_elements.push(element.clone());
2624 }
2625
2626 if fast_path_failed_at.is_none() && self.scratch_elements.is_empty() {
2627 if elements_count < self.entries.len() {
2628 for entry in self.entries.drain(elements_count..) {
2629 request_auto_invalidations(context, entry.capabilities);
2630 detach_node_tree(&mut **entry.node.borrow_mut());
2631 }
2632 }
2633 self.sync_chain_links();
2634 return;
2635 }
2636
2637 let fail_idx = fast_path_failed_at.unwrap_or(old_len);
2638
2639 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
2640 let processed_entries_len = self.entries.len();
2641 let old_len = old_entries.len();
2642
2643 self.scratch_old_used.clear();
2644 self.scratch_old_used.resize(old_len, false);
2645
2646 self.scratch_match_order.clear();
2647 self.scratch_match_order.resize(old_len, None);
2648
2649 let index = EntryIndex::build(&old_entries);
2650
2651 let new_elements_count = self.scratch_elements.len();
2652 self.scratch_final_slots.clear();
2653 self.scratch_final_slots.reserve(new_elements_count);
2654
2655 for (new_pos, element) in self.scratch_elements.drain(..).enumerate() {
2656 self.scratch_final_slots.push(None);
2657 let element_type = element.element_type();
2658 let node_type = element.node_type();
2659 let key = element.key();
2660 let hash_code = element.hash_code();
2661 let capabilities = element.capabilities();
2662
2663 let matched_idx = index.find_match(
2664 &old_entries,
2665 &self.scratch_old_used,
2666 EntryMatchQuery {
2667 element_type,
2668 node_type,
2669 key,
2670 hash_code,
2671 element: &element,
2672 },
2673 );
2674
2675 if let Some(idx) = matched_idx {
2676 let entry = &mut old_entries[idx];
2677 let can_update_node = {
2678 let node_borrow = entry.node.borrow();
2679 element.can_update_node(&**node_borrow)
2680 };
2681 if !can_update_node {
2682 let replacement = ModifierNodeEntry::new(
2683 element_type,
2684 node_type,
2685 key,
2686 element.clone(),
2687 element.create_node(),
2688 hash_code,
2689 capabilities,
2690 );
2691 attach_node_tree(&mut **replacement.node.borrow_mut(), context);
2692 element.update_node(&mut **replacement.node.borrow_mut());
2693 request_auto_invalidations(context, capabilities);
2694 self.scratch_final_slots[new_pos] = Some(replacement);
2695 continue;
2696 }
2697
2698 self.scratch_old_used[idx] = true;
2699 self.scratch_match_order[idx] = Some(new_pos);
2700 let moved = idx != new_pos;
2701
2702 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2703
2704 {
2705 let node_borrow = entry.node.borrow();
2706 if !node_borrow.node_state().is_attached() {
2707 drop(node_borrow);
2708 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2709 }
2710 }
2711
2712 let needs_update = !same_element || element.requires_update();
2713 if needs_update {
2714 element.update_node(&mut **entry.node.borrow_mut());
2715 entry.element = element;
2716 entry.hash_code = hash_code;
2717 request_update_auto_invalidations(
2718 entry.element.as_ref(),
2719 context,
2720 capabilities,
2721 );
2722 }
2723 if moved {
2724 request_auto_invalidations(context, capabilities);
2725 }
2726
2727 entry.key = key;
2728 entry.element_type = element_type;
2729 entry.node_type = node_type;
2730 entry.capabilities = capabilities;
2731 entry
2732 .node
2733 .borrow()
2734 .node_state()
2735 .set_capabilities(capabilities);
2736 } else {
2737 let entry = ModifierNodeEntry::new(
2738 element_type,
2739 node_type,
2740 key,
2741 element.clone(),
2742 element.create_node(),
2743 hash_code,
2744 capabilities,
2745 );
2746 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2747 element.update_node(&mut **entry.node.borrow_mut());
2748 request_auto_invalidations(context, capabilities);
2749 self.scratch_final_slots[new_pos] = Some(entry);
2750 }
2751 }
2752
2753 for (i, entry) in old_entries.into_iter().enumerate() {
2754 if self.scratch_old_used[i] {
2755 if let Some(pos) = self.scratch_match_order[i] {
2756 self.scratch_final_slots[pos] = Some(entry);
2757 } else {
2758 request_auto_invalidations(context, entry.capabilities);
2759 detach_node_tree(&mut **entry.node.borrow_mut());
2760 }
2761 } else {
2762 request_auto_invalidations(context, entry.capabilities);
2763 detach_node_tree(&mut **entry.node.borrow_mut());
2764 }
2765 }
2766
2767 self.entries.reserve(self.scratch_final_slots.len());
2768 for slot in self.scratch_final_slots.drain(..) {
2769 if let Some(entry) = slot {
2770 self.entries.push(entry);
2771 } else {
2772 log::error!("modifier reconciliation produced an empty final slot");
2773 }
2774 }
2775
2776 debug_assert_eq!(
2777 self.entries.len(),
2778 processed_entries_len + new_elements_count
2779 );
2780 self.sync_chain_links();
2781 }
2782
2783 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
2787 where
2788 I: IntoIterator<Item = DynModifierElement>,
2789 {
2790 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
2791 self.update_from_slice(&collected, context);
2792 }
2793
2794 pub fn reset(&mut self) {
2797 for entry in &mut self.entries {
2798 reset_node_tree(&mut **entry.node.borrow_mut());
2799 }
2800 }
2801
2802 pub fn detach_all(&mut self) {
2804 for entry in std::mem::take(&mut self.entries) {
2805 detach_node_tree(&mut **entry.node.borrow_mut());
2806 {
2807 let node_borrow = entry.node.borrow();
2808 let state = node_borrow.node_state();
2809 state.set_capabilities(NodeCapabilities::empty());
2810 }
2811 }
2812 self.aggregated_capabilities = NodeCapabilities::empty();
2813 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2814 self.ordered_nodes.clear();
2815 self.sync_chain_links();
2816 }
2817
2818 pub fn len(&self) -> usize {
2819 self.entries.len()
2820 }
2821
2822 pub fn is_empty(&self) -> bool {
2823 self.entries.is_empty()
2824 }
2825
2826 pub fn capabilities(&self) -> NodeCapabilities {
2828 self.aggregated_capabilities
2829 }
2830
2831 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
2833 self.aggregated_capabilities.contains(capability)
2834 }
2835
2836 pub fn head(&self) -> ModifierChainNodeRef<'_> {
2838 self.make_node_ref(NodeLink::Head)
2839 }
2840
2841 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
2843 self.make_node_ref(NodeLink::Tail)
2844 }
2845
2846 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
2848 ModifierChainIter::forward(self)
2849 }
2850
2851 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
2853 ModifierChainIter::backward(self)
2854 }
2855
2856 pub fn for_each_forward<F>(&self, mut f: F)
2858 where
2859 F: FnMut(ModifierChainNodeRef<'_>),
2860 {
2861 for node in self.head_to_tail() {
2862 f(node);
2863 }
2864 }
2865
2866 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
2868 where
2869 F: FnMut(ModifierChainNodeRef<'_>),
2870 {
2871 if mask.is_empty() {
2872 self.for_each_forward(f);
2873 return;
2874 }
2875
2876 if !self.head().aggregate_child_capabilities().intersects(mask) {
2877 return;
2878 }
2879
2880 for node in self.head_to_tail() {
2881 if node.kind_set().intersects(mask) {
2882 f(node);
2883 }
2884 }
2885 }
2886
2887 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
2889 where
2890 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
2891 {
2892 self.for_each_forward_matching(mask, |node_ref| {
2893 node_ref.with_node(|node| f(node_ref.clone(), node));
2894 });
2895 }
2896
2897 pub fn for_each_backward<F>(&self, mut f: F)
2899 where
2900 F: FnMut(ModifierChainNodeRef<'_>),
2901 {
2902 for node in self.tail_to_head() {
2903 f(node);
2904 }
2905 }
2906
2907 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
2909 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
2910 node as *const dyn ModifierNode as *const ()
2911 }
2912
2913 let target = node_data_ptr(node);
2914 for (index, entry) in self.entries.iter().enumerate() {
2915 if node_data_ptr(&**entry.node.borrow()) == target {
2916 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
2917 }
2918 }
2919
2920 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
2921 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
2922 return None;
2923 }
2924 let matches_target = match link {
2925 NodeLink::Head => node_data_ptr(self.head_sentinel.as_ref()) == target,
2926 NodeLink::Tail => node_data_ptr(self.tail_sentinel.as_ref()) == target,
2927 NodeLink::Entry(path) => {
2928 let node_borrow = self.entries[path.entry()].node.borrow();
2929 node_data_ptr(&**node_borrow) == target
2930 }
2931 };
2932 if matches_target {
2933 Some(self.make_node_ref(*link))
2934 } else {
2935 None
2936 }
2937 })
2938 }
2939
2940 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
2943 self.entries.get(index).and_then(|entry| {
2944 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
2945 boxed_node.as_any().downcast_ref::<N>()
2946 })
2947 .ok()
2948 })
2949 }
2950
2951 pub fn node_mut<N: ModifierNode + 'static>(
2954 &self,
2955 index: usize,
2956 ) -> Option<std::cell::RefMut<'_, N>> {
2957 self.entries.get(index).and_then(|entry| {
2958 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
2959 boxed_node.as_any_mut().downcast_mut::<N>()
2960 })
2961 .ok()
2962 })
2963 }
2964
2965 pub fn get_node_rc(&self, index: usize) -> Option<Rc<RefCell<Box<dyn ModifierNode>>>> {
2968 self.entries.get(index).map(|entry| Rc::clone(&entry.node))
2969 }
2970
2971 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
2973 self.aggregated_capabilities
2974 .contains(NodeCapabilities::for_invalidation(kind))
2975 }
2976
2977 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
2979 where
2980 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
2981 {
2982 for index in 0..self.ordered_nodes.len() {
2983 let (link, cached_caps, _agg) = self.ordered_nodes[index];
2984 match link {
2985 NodeLink::Head => {
2986 f(self.head_sentinel.as_mut(), cached_caps);
2987 }
2988 NodeLink::Tail => {
2989 f(self.tail_sentinel.as_mut(), cached_caps);
2990 }
2991 NodeLink::Entry(path) => {
2992 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
2993 if path.delegates().is_empty() {
2994 f(&mut **node_borrow, cached_caps);
2995 } else {
2996 let mut current: &mut dyn ModifierNode = &mut **node_borrow;
2997 for &delegate_index in path.delegates() {
2998 if let Some(delegate) =
2999 nth_delegate_mut(current, delegate_index as usize)
3000 {
3001 current = delegate;
3002 } else {
3003 return;
3004 }
3005 }
3006 f(current, cached_caps);
3007 }
3008 }
3009 }
3010 }
3011 }
3012
3013 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
3014 ModifierChainNodeRef {
3015 chain: self,
3016 link,
3017 cached_capabilities: None,
3018 cached_aggregate_child: None,
3019 }
3020 }
3021
3022 fn make_node_ref_with_caps(
3023 &self,
3024 link: NodeLink,
3025 caps: NodeCapabilities,
3026 aggregate_child: NodeCapabilities,
3027 ) -> ModifierChainNodeRef<'_> {
3028 ModifierChainNodeRef {
3029 chain: self,
3030 link,
3031 cached_capabilities: Some(caps),
3032 cached_aggregate_child: Some(aggregate_child),
3033 }
3034 }
3035
3036 fn sync_chain_links(&mut self) {
3037 self.rebuild_ordered_nodes();
3038
3039 self.head_sentinel.node_state().set_parent_link(None);
3040 self.tail_sentinel.node_state().set_child_link(None);
3041
3042 if self.ordered_nodes.is_empty() {
3043 self.head_sentinel
3044 .node_state()
3045 .set_child_link(Some(NodeLink::Tail));
3046 self.tail_sentinel
3047 .node_state()
3048 .set_parent_link(Some(NodeLink::Head));
3049 self.aggregated_capabilities = NodeCapabilities::empty();
3050 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
3051 self.head_sentinel
3052 .node_state()
3053 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3054 self.tail_sentinel
3055 .node_state()
3056 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3057 return;
3058 }
3059
3060 let mut previous = NodeLink::Head;
3061 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
3062 match &previous {
3063 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
3064 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
3065 NodeLink::Entry(path) => {
3066 let node_borrow = self.entries[path.entry()].node.borrow();
3067 if path.delegates().is_empty() {
3068 node_borrow.node_state().set_child_link(Some(link));
3069 } else {
3070 let mut current: &dyn ModifierNode = &**node_borrow;
3071 for &delegate_index in path.delegates() {
3072 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3073 current = delegate;
3074 }
3075 }
3076 current.node_state().set_child_link(Some(link));
3077 }
3078 }
3079 }
3080 match &link {
3081 NodeLink::Head => self
3082 .head_sentinel
3083 .node_state()
3084 .set_parent_link(Some(previous)),
3085 NodeLink::Tail => self
3086 .tail_sentinel
3087 .node_state()
3088 .set_parent_link(Some(previous)),
3089 NodeLink::Entry(path) => {
3090 let node_borrow = self.entries[path.entry()].node.borrow();
3091 if path.delegates().is_empty() {
3092 node_borrow.node_state().set_parent_link(Some(previous));
3093 } else {
3094 let mut current: &dyn ModifierNode = &**node_borrow;
3095 for &delegate_index in path.delegates() {
3096 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3097 current = delegate;
3098 }
3099 }
3100 current.node_state().set_parent_link(Some(previous));
3101 }
3102 }
3103 }
3104 previous = link;
3105 }
3106
3107 match &previous {
3108 NodeLink::Head => self
3109 .head_sentinel
3110 .node_state()
3111 .set_child_link(Some(NodeLink::Tail)),
3112 NodeLink::Tail => self
3113 .tail_sentinel
3114 .node_state()
3115 .set_child_link(Some(NodeLink::Tail)),
3116 NodeLink::Entry(path) => {
3117 let node_borrow = self.entries[path.entry()].node.borrow();
3118 if path.delegates().is_empty() {
3119 node_borrow
3120 .node_state()
3121 .set_child_link(Some(NodeLink::Tail));
3122 } else {
3123 let mut current: &dyn ModifierNode = &**node_borrow;
3124 for &delegate_index in path.delegates() {
3125 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3126 current = delegate;
3127 }
3128 }
3129 current.node_state().set_child_link(Some(NodeLink::Tail));
3130 }
3131 }
3132 }
3133 self.tail_sentinel
3134 .node_state()
3135 .set_parent_link(Some(previous));
3136 self.tail_sentinel.node_state().set_child_link(None);
3137
3138 let mut aggregate = NodeCapabilities::empty();
3139 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
3140 aggregate |= *cached_caps;
3141 *cached_aggregate = aggregate;
3142 match link {
3143 NodeLink::Head => {
3144 self.head_sentinel
3145 .node_state()
3146 .set_aggregate_child_capabilities(aggregate);
3147 }
3148 NodeLink::Tail => {
3149 self.tail_sentinel
3150 .node_state()
3151 .set_aggregate_child_capabilities(aggregate);
3152 }
3153 NodeLink::Entry(path) => {
3154 let node_borrow = self.entries[path.entry()].node.borrow();
3155 let state = if path.delegates().is_empty() {
3156 node_borrow.node_state()
3157 } else {
3158 let mut current: &dyn ModifierNode = &**node_borrow;
3159 for &delegate_index in path.delegates() {
3160 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3161 current = delegate;
3162 }
3163 }
3164 current.node_state()
3165 };
3166 state.set_aggregate_child_capabilities(aggregate);
3167 }
3168 }
3169 }
3170
3171 self.aggregated_capabilities = aggregate;
3172 self.head_aggregate_child_capabilities = aggregate;
3173 self.head_sentinel
3174 .node_state()
3175 .set_aggregate_child_capabilities(aggregate);
3176 self.tail_sentinel
3177 .node_state()
3178 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3179 }
3180
3181 fn rebuild_ordered_nodes(&mut self) {
3182 self.ordered_nodes.clear();
3183 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
3184 for (index, entry) in self.entries.iter().enumerate() {
3185 let node_borrow = entry.node.borrow();
3186 Self::enumerate_link_order(
3187 &**node_borrow,
3188 index,
3189 &mut path_buf,
3190 0,
3191 &mut self.ordered_nodes,
3192 );
3193 }
3194 }
3195
3196 fn enumerate_link_order(
3197 node: &dyn ModifierNode,
3198 entry: usize,
3199 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
3200 path_len: usize,
3201 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
3202 ) {
3203 let caps = node.node_state().capabilities();
3204 out.push((
3205 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
3206 caps,
3207 NodeCapabilities::empty(),
3208 ));
3209 let mut delegate_index = 0usize;
3210 node.for_each_delegate(&mut |child| {
3211 if path_len < MAX_DELEGATE_DEPTH {
3212 path_buf[path_len] = delegate_index;
3213 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
3214 }
3215 delegate_index += 1;
3216 });
3217 }
3218}
3219
3220impl<'a> ModifierChainNodeRef<'a> {
3221 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
3222 match &self.link {
3223 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
3224 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
3225 NodeLink::Entry(path) => {
3226 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3227 if path.delegates().is_empty() {
3228 f(node_borrow.node_state())
3229 } else {
3230 let mut current: &dyn ModifierNode = &**node_borrow;
3231 for &delegate_index in path.delegates() {
3232 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3233 current = delegate;
3234 } else {
3235 return f(node_borrow.node_state());
3236 }
3237 }
3238 f(current.node_state())
3239 }
3240 }
3241 }
3242 }
3243
3244 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
3247 match &self.link {
3248 NodeLink::Head => None,
3249 NodeLink::Tail => None,
3250 NodeLink::Entry(path) => {
3251 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3252 if path.delegates().is_empty() {
3253 Some(f(&**node_borrow))
3254 } else {
3255 let mut current: &dyn ModifierNode = &**node_borrow;
3256 for &delegate_index in path.delegates() {
3257 current = nth_delegate(current, delegate_index as usize)?;
3258 }
3259 Some(f(current))
3260 }
3261 }
3262 }
3263 }
3264
3265 #[inline]
3267 pub fn parent(&self) -> Option<Self> {
3268 self.with_state(NodeState::parent_link)
3269 .map(|link| self.chain.make_node_ref(link))
3270 }
3271
3272 #[inline]
3274 pub fn child(&self) -> Option<Self> {
3275 self.with_state(NodeState::child_link)
3276 .map(|link| self.chain.make_node_ref(link))
3277 }
3278
3279 #[inline]
3281 pub fn kind_set(&self) -> NodeCapabilities {
3282 if let Some(caps) = self.cached_capabilities {
3283 return caps;
3284 }
3285 match &self.link {
3286 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
3287 NodeLink::Entry(_) => self.with_state(NodeState::capabilities),
3288 }
3289 }
3290
3291 pub fn entry_index(&self) -> Option<usize> {
3293 match &self.link {
3294 NodeLink::Entry(path) => Some(path.entry()),
3295 _ => None,
3296 }
3297 }
3298
3299 pub fn delegate_depth(&self) -> usize {
3301 match &self.link {
3302 NodeLink::Entry(path) => path.delegates().len(),
3303 _ => 0,
3304 }
3305 }
3306
3307 #[inline]
3309 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
3310 if let Some(agg) = self.cached_aggregate_child {
3311 return agg;
3312 }
3313 if self.is_tail() {
3314 NodeCapabilities::empty()
3315 } else {
3316 self.with_state(NodeState::aggregate_child_capabilities)
3317 }
3318 }
3319
3320 pub fn is_head(&self) -> bool {
3322 matches!(self.link, NodeLink::Head)
3323 }
3324
3325 pub fn is_tail(&self) -> bool {
3327 matches!(self.link, NodeLink::Tail)
3328 }
3329
3330 pub fn is_sentinel(&self) -> bool {
3332 matches!(self.link, NodeLink::Head | NodeLink::Tail)
3333 }
3334
3335 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
3337 !mask.is_empty() && self.kind_set().intersects(mask)
3338 }
3339
3340 pub fn visit_descendants<F>(self, include_self: bool, mut f: F)
3342 where
3343 F: FnMut(ModifierChainNodeRef<'a>),
3344 {
3345 let mut current = if include_self {
3346 Some(self)
3347 } else {
3348 self.child()
3349 };
3350 while let Some(node) = current {
3351 if node.is_tail() {
3352 break;
3353 }
3354 if !node.is_sentinel() {
3355 f(node.clone());
3356 }
3357 current = node.child();
3358 }
3359 }
3360
3361 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3363 where
3364 F: FnMut(ModifierChainNodeRef<'a>),
3365 {
3366 if mask.is_empty() {
3367 self.visit_descendants(include_self, f);
3368 return;
3369 }
3370
3371 if !self.aggregate_child_capabilities().intersects(mask) {
3372 return;
3373 }
3374
3375 self.visit_descendants(include_self, |node| {
3376 if node.kind_set().intersects(mask) {
3377 f(node);
3378 }
3379 });
3380 }
3381
3382 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
3384 where
3385 F: FnMut(ModifierChainNodeRef<'a>),
3386 {
3387 let mut current = if include_self {
3388 Some(self)
3389 } else {
3390 self.parent()
3391 };
3392 while let Some(node) = current {
3393 if node.is_head() {
3394 break;
3395 }
3396 f(node.clone());
3397 current = node.parent();
3398 }
3399 }
3400
3401 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3403 where
3404 F: FnMut(ModifierChainNodeRef<'a>),
3405 {
3406 if mask.is_empty() {
3407 self.visit_ancestors(include_self, f);
3408 return;
3409 }
3410
3411 self.visit_ancestors(include_self, |node| {
3412 if node.kind_set().intersects(mask) {
3413 f(node);
3414 }
3415 });
3416 }
3417}
3418
3419#[cfg(test)]
3420#[path = "tests/modifier_tests.rs"]
3421mod tests;