1use std::{
9 any::{Any, TypeId, type_name},
10 cell::{Cell, RefCell},
11 fmt,
12 hash::{Hash, Hasher},
13 ops::{BitOr, BitOrAssign},
14 rc::Rc,
15};
16
17use cranpose_core::{ProvidedValue, collections::map::HashMap, hash::default};
18pub use cranpose_ui_graphics::{DrawScope, Size};
19pub use cranpose_ui_layout::{Constraints, Measurable};
20
21use crate::nodes::input::types::PointerEvent;
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
26pub enum InvalidationKind {
27 Layout,
28 Draw,
29 PointerInput,
30 Semantics,
31 Focus,
32}
33
34pub trait ModifierNodeContext {
36 fn invalidate(&mut self, _kind: InvalidationKind) {}
38
39 fn request_update(&mut self) {}
42
43 fn node_id(&self) -> Option<cranpose_core::NodeId> {
46 None
47 }
48
49 fn push_active_capabilities(&mut self, _capabilities: NodeCapabilities) {}
51
52 fn pop_active_capabilities(&mut self) {}
54
55 fn density(&self) -> f32 {
60 1.0
61 }
62}
63
64#[derive(Default, Debug, Clone)]
73pub struct BasicModifierNodeContext {
74 invalidations: ModifierInvalidations,
75 update_requested: bool,
76 active_capabilities: Vec<NodeCapabilities>,
77 node_id: Option<cranpose_core::NodeId>,
78}
79
80impl BasicModifierNodeContext {
81 pub fn new() -> Self {
83 Self::default()
84 }
85
86 pub fn invalidations(&self) -> &[ModifierInvalidation] {
90 &self.invalidations
91 }
92
93 pub fn clear_invalidations(&mut self) {
95 self.invalidations.clear();
96 }
97
98 pub fn take_invalidations(&mut self) -> ModifierInvalidations {
100 std::mem::take(&mut self.invalidations)
101 }
102
103 pub fn update_requested(&self) -> bool {
106 self.update_requested
107 }
108
109 pub fn take_update_requested(&mut self) -> bool {
111 std::mem::take(&mut self.update_requested)
112 }
113
114 pub fn set_node_id(&mut self, id: Option<cranpose_core::NodeId>) {
116 self.node_id = id;
117 }
118
119 fn push_invalidation(&mut self, kind: InvalidationKind) {
120 let mut capabilities = self.current_capabilities();
121 capabilities.insert(NodeCapabilities::for_invalidation(kind));
122 if let Some(existing) = self
123 .invalidations
124 .iter_mut()
125 .find(|entry| entry.kind() == kind)
126 {
127 let updated = existing.capabilities() | capabilities;
128 *existing = ModifierInvalidation::new(kind, updated);
129 } else {
130 self.invalidations
131 .push(ModifierInvalidation::new(kind, capabilities));
132 }
133 }
134
135 fn current_capabilities(&self) -> NodeCapabilities {
136 self.active_capabilities
137 .last()
138 .copied()
139 .unwrap_or_else(NodeCapabilities::empty)
140 }
141}
142
143impl ModifierNodeContext for BasicModifierNodeContext {
144 fn invalidate(&mut self, kind: InvalidationKind) {
145 self.push_invalidation(kind);
146 }
147
148 fn request_update(&mut self) {
149 self.update_requested = true;
150 }
151
152 fn push_active_capabilities(&mut self, capabilities: NodeCapabilities) {
153 self.active_capabilities.push(capabilities);
154 }
155
156 fn pop_active_capabilities(&mut self) {
157 self.active_capabilities.pop();
158 }
159
160 fn node_id(&self) -> Option<cranpose_core::NodeId> {
161 self.node_id
162 }
163}
164
165const MAX_DELEGATE_DEPTH: usize = 3;
166
167#[derive(Copy, Clone, Debug, PartialEq, Eq)]
168pub(crate) struct NodePath {
169 entry: usize,
170 delegate_buf: [u8; MAX_DELEGATE_DEPTH],
171 delegate_len: u8,
172}
173
174impl NodePath {
175 #[inline]
176 fn root(entry: usize) -> Self {
177 Self {
178 entry,
179 delegate_buf: [0; MAX_DELEGATE_DEPTH],
180 delegate_len: 0,
181 }
182 }
183
184 #[inline]
185 fn from_slice(entry: usize, path: &[usize]) -> Self {
186 debug_assert!(
187 path.len() <= MAX_DELEGATE_DEPTH,
188 "delegate depth {} exceeds MAX_DELEGATE_DEPTH {}",
189 path.len(),
190 MAX_DELEGATE_DEPTH
191 );
192 debug_assert!(
193 path.iter().all(|&i| i <= u8::MAX as usize),
194 "delegate index exceeds u8 range"
195 );
196 let mut delegate_buf = [0u8; MAX_DELEGATE_DEPTH];
197 for (i, &v) in path.iter().enumerate().take(MAX_DELEGATE_DEPTH) {
198 delegate_buf[i] = v as u8;
199 }
200 Self {
201 entry,
202 delegate_buf,
203 delegate_len: path.len().min(MAX_DELEGATE_DEPTH) as u8,
204 }
205 }
206
207 #[inline]
208 fn entry(&self) -> usize {
209 self.entry
210 }
211
212 #[inline]
213 fn delegates(&self) -> &[u8] {
214 &self.delegate_buf[..self.delegate_len as usize]
215 }
216}
217
218#[derive(Copy, Clone, Debug, PartialEq, Eq)]
219pub(crate) enum NodeLink {
220 Head,
221 Tail,
222 Entry(NodePath),
223}
224
225#[derive(Debug)]
231pub struct NodeState {
232 aggregate_child_capabilities: Cell<NodeCapabilities>,
233 capabilities: Cell<NodeCapabilities>,
234 parent: RefCell<Option<NodeLink>>,
235 child: RefCell<Option<NodeLink>>,
236 attached: Cell<bool>,
237 is_sentinel: bool,
238}
239
240impl Default for NodeState {
241 fn default() -> Self {
242 Self::new()
243 }
244}
245
246impl NodeState {
247 pub const fn new() -> Self {
248 Self {
249 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
250 capabilities: Cell::new(NodeCapabilities::empty()),
251 parent: RefCell::new(None),
252 child: RefCell::new(None),
253 attached: Cell::new(false),
254 is_sentinel: false,
255 }
256 }
257
258 pub const fn sentinel() -> Self {
259 Self {
260 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
261 capabilities: Cell::new(NodeCapabilities::empty()),
262 parent: RefCell::new(None),
263 child: RefCell::new(None),
264 attached: Cell::new(true),
265 is_sentinel: true,
266 }
267 }
268
269 pub fn set_capabilities(&self, capabilities: NodeCapabilities) {
270 self.capabilities.set(capabilities);
271 }
272
273 #[inline]
274 pub fn capabilities(&self) -> NodeCapabilities {
275 self.capabilities.get()
276 }
277
278 pub fn set_aggregate_child_capabilities(&self, capabilities: NodeCapabilities) {
279 self.aggregate_child_capabilities.set(capabilities);
280 }
281
282 #[inline]
283 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
284 self.aggregate_child_capabilities.get()
285 }
286
287 pub(crate) fn set_parent_link(&self, parent: Option<NodeLink>) {
288 *self.parent.borrow_mut() = parent;
289 }
290
291 #[inline]
292 pub(crate) fn parent_link(&self) -> Option<NodeLink> {
293 *self.parent.borrow()
294 }
295
296 pub(crate) fn set_child_link(&self, child: Option<NodeLink>) {
297 *self.child.borrow_mut() = child;
298 }
299
300 #[inline]
301 pub(crate) fn child_link(&self) -> Option<NodeLink> {
302 *self.child.borrow()
303 }
304
305 pub fn set_attached(&self, attached: bool) {
306 self.attached.set(attached);
307 }
308
309 pub fn is_attached(&self) -> bool {
310 self.attached.get()
311 }
312
313 pub fn is_sentinel(&self) -> bool {
314 self.is_sentinel
315 }
316}
317
318pub trait DelegatableNode {
320 fn node_state(&self) -> &NodeState;
321 fn aggregate_child_capabilities(&self) -> NodeCapabilities {
322 self.node_state().aggregate_child_capabilities()
323 }
324}
325
326pub trait ModifierNode: Any + DelegatableNode {
384 fn on_attach(&mut self, _context: &mut dyn ModifierNodeContext) {}
385
386 fn on_detach(&mut self) {}
387
388 fn on_reset(&mut self) {}
389
390 fn as_draw_node(&self) -> Option<&dyn DrawModifierNode> {
392 None
393 }
394
395 fn as_draw_node_mut(&mut self) -> Option<&mut dyn DrawModifierNode> {
397 None
398 }
399
400 fn as_pointer_input_node(&self) -> Option<&dyn PointerInputNode> {
402 None
403 }
404
405 fn as_pointer_input_node_mut(&mut self) -> Option<&mut dyn PointerInputNode> {
407 None
408 }
409
410 fn as_semantics_node(&self) -> Option<&dyn SemanticsNode> {
412 None
413 }
414
415 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn SemanticsNode> {
417 None
418 }
419
420 fn as_focus_node(&self) -> Option<&dyn FocusNode> {
422 None
423 }
424
425 fn as_focus_node_mut(&mut self) -> Option<&mut dyn FocusNode> {
427 None
428 }
429
430 fn as_layout_node(&self) -> Option<&dyn LayoutModifierNode> {
432 None
433 }
434
435 fn as_layout_node_mut(&mut self) -> Option<&mut dyn LayoutModifierNode> {
437 None
438 }
439
440 fn for_each_delegate<'b>(&'b self, _visitor: &mut dyn FnMut(&'b dyn ModifierNode)) {}
442
443 fn for_each_delegate_mut<'b>(&'b mut self, _visitor: &mut dyn FnMut(&'b mut dyn ModifierNode)) {
445 }
446}
447
448pub trait LayoutModifierNode: ModifierNode {
454 fn measure(
476 &self,
477 _context: &mut dyn ModifierNodeContext,
478 measurable: &dyn Measurable,
479 constraints: Constraints,
480 ) -> cranpose_ui_layout::LayoutModifierMeasureResult {
481 let placeable = measurable.measure(constraints);
482 cranpose_ui_layout::LayoutModifierMeasureResult::with_size(Size {
483 width: placeable.width(),
484 height: placeable.height(),
485 })
486 }
487
488 fn min_intrinsic_width(
490 &self,
491 _measurable: &dyn Measurable,
492 _height: f32,
493 _density: f32,
494 ) -> f32 {
495 0.0
496 }
497
498 fn max_intrinsic_width(
500 &self,
501 _measurable: &dyn Measurable,
502 _height: f32,
503 _density: f32,
504 ) -> f32 {
505 0.0
506 }
507
508 fn min_intrinsic_height(
510 &self,
511 _measurable: &dyn Measurable,
512 _width: f32,
513 _density: f32,
514 ) -> f32 {
515 0.0
516 }
517
518 fn max_intrinsic_height(
520 &self,
521 _measurable: &dyn Measurable,
522 _width: f32,
523 _density: f32,
524 ) -> f32 {
525 0.0
526 }
527}
528
529pub trait DrawModifierNode: ModifierNode {
536 fn create_draw_closure(&self) -> Option<NodeDrawClosure> {
547 None
548 }
549
550 fn create_behind_draw_closure(&self) -> Option<NodeDrawClosure> {
555 None
556 }
557}
558
559pub type NodeDrawClosure = Rc<dyn Fn(&mut cranpose_ui_graphics::DrawScopeDefault)>;
564
565pub trait PointerInputNode: ModifierNode {
571 fn on_pointer_event(
574 &mut self,
575 _context: &mut dyn ModifierNodeContext,
576 _event: &PointerEvent,
577 ) -> bool {
578 false
579 }
580
581 fn hit_test(&self, _x: f32, _y: f32) -> bool {
584 true
585 }
586
587 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
589 None
590 }
591
592 fn layout_size_sink(&self) -> Option<Rc<Cell<Size>>> {
605 None
606 }
607}
608
609pub trait SemanticsNode: ModifierNode {
615 fn merge_semantics(&self, _config: &mut SemanticsConfiguration) {}
617
618 fn reach(&self) -> SemanticsReach {
625 SemanticsReach::merged_by(self, true)
626 }
627}
628
629#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
634pub struct SemanticsReach {
635 pub is_modal: bool,
637 pub hidden: bool,
639 pub merges_live_state: bool,
643}
644
645impl SemanticsReach {
646 pub fn merged_by(node: &(impl SemanticsNode + ?Sized), merges_live_state: bool) -> Self {
649 let mut config = SemanticsConfiguration::default();
650 node.merge_semantics(&mut config);
651 Self {
652 is_modal: config.is_modal,
653 hidden: config.hidden,
654 merges_live_state,
655 }
656 }
657
658 pub fn union(self, other: Self) -> Self {
660 Self {
661 is_modal: self.is_modal || other.is_modal,
662 hidden: self.hidden || other.hidden,
663 merges_live_state: self.merges_live_state || other.merges_live_state,
664 }
665 }
666}
667
668#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
673pub enum FocusState {
674 Active,
676 ActiveParent,
678 Captured,
682 #[default]
685 Inactive,
686}
687
688impl FocusState {
689 pub fn is_focused(self) -> bool {
691 matches!(self, FocusState::Active | FocusState::Captured)
692 }
693
694 pub fn has_focus(self) -> bool {
696 matches!(
697 self,
698 FocusState::Active | FocusState::ActiveParent | FocusState::Captured
699 )
700 }
701
702 pub fn is_captured(self) -> bool {
704 matches!(self, FocusState::Captured)
705 }
706}
707
708pub trait FocusNode: ModifierNode {
713 fn focus_state(&self) -> FocusState;
715
716 fn on_focus_changed(&mut self, _context: &mut dyn ModifierNodeContext, _state: FocusState) {}
718}
719
720#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
731pub enum SemanticsWidgetRole {
732 Button,
733 Checkbox,
734 Switch,
735 RadioButton,
736 Tab,
737 Image,
738 DropdownList,
741 ValuePicker,
744 Header,
749 Dialog,
753 Link,
756 SearchField,
759 ProgressBar,
762 ToggleButton,
765 Alert,
768 Toolbar,
771 Menu,
773 MenuItem,
775 TabBar,
778 List,
780 ListItem,
782 RadioGroup,
784}
785
786#[derive(Clone, Copy, Debug, PartialEq)]
794pub struct ProgressBarRangeInfo {
795 pub current: f32,
796 pub start: f32,
797 pub end: f32,
798 pub steps: u32,
801}
802
803impl ProgressBarRangeInfo {
804 pub fn new(current: f32, start: f32, end: f32, steps: u32) -> Self {
805 Self {
806 current,
807 start,
808 end,
809 steps,
810 }
811 }
812
813 pub fn fraction(&self) -> f32 {
815 let span = self.end - self.start;
816 if span.abs() < f32::EPSILON {
817 return 0.0;
818 }
819 ((self.current - self.start) / span).clamp(0.0, 1.0)
820 }
821
822 pub fn step(&self) -> f32 {
825 let span = self.end - self.start;
826 if self.steps == 0 {
827 span / 10.0
828 } else {
829 span / (self.steps as f32 + 1.0)
830 }
831 }
832}
833
834#[derive(Clone, Copy, Debug, PartialEq, Eq)]
839pub struct CollectionInfo {
840 pub rows: usize,
841 pub columns: usize,
842}
843
844#[derive(Clone, Copy, Debug, PartialEq)]
855pub struct ScrollAxisRange {
856 pub value: f32,
857 pub max_value: f32,
858 pub reverse: bool,
859 pub content_padding_start: f32,
860 pub content_padding_end: f32,
861}
862
863impl ScrollAxisRange {
864 pub fn new(value: f32, max_value: f32, reverse: bool) -> Self {
865 Self {
866 value,
867 max_value,
868 reverse,
869 content_padding_start: 0.0,
870 content_padding_end: 0.0,
871 }
872 }
873
874 pub fn with_content_padding(self, start: f32, end: f32) -> Self {
877 Self {
878 content_padding_start: start,
879 content_padding_end: end,
880 ..self
881 }
882 }
883
884 pub fn can_scroll_forward(&self) -> bool {
885 self.value < self.max_value
886 }
887
888 pub fn can_scroll_backward(&self) -> bool {
889 self.value > 0.0
890 }
891}
892
893#[derive(Clone)]
899pub struct SemanticsScrollBy {
900 handler: Rc<dyn Fn(f32, f32) -> bool>,
901}
902
903impl SemanticsScrollBy {
904 pub fn new(handler: impl Fn(f32, f32) -> bool + 'static) -> Self {
905 Self {
906 handler: Rc::new(handler),
907 }
908 }
909
910 pub fn invoke(&self, dx: f32, dy: f32) -> bool {
911 (self.handler)(dx, dy)
912 }
913}
914
915impl fmt::Debug for SemanticsScrollBy {
916 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
917 f.debug_struct("SemanticsScrollBy").finish_non_exhaustive()
918 }
919}
920
921impl PartialEq for SemanticsScrollBy {
922 fn eq(&self, _other: &Self) -> bool {
923 true
924 }
925}
926
927impl Eq for SemanticsScrollBy {}
928
929#[derive(Clone)]
935pub struct SemanticsScrollToIndex {
936 handler: Rc<dyn Fn(usize) -> bool>,
937}
938
939impl SemanticsScrollToIndex {
940 pub fn new(handler: impl Fn(usize) -> bool + 'static) -> Self {
941 Self {
942 handler: Rc::new(handler),
943 }
944 }
945
946 pub fn invoke(&self, index: usize) -> bool {
947 (self.handler)(index)
948 }
949}
950
951impl fmt::Debug for SemanticsScrollToIndex {
952 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
953 f.debug_struct("SemanticsScrollToIndex")
954 .finish_non_exhaustive()
955 }
956}
957
958impl PartialEq for SemanticsScrollToIndex {
959 fn eq(&self, _other: &Self) -> bool {
960 true
961 }
962}
963
964impl Eq for SemanticsScrollToIndex {}
965
966#[derive(Clone)]
972pub struct SemanticsSetProgress {
973 handler: Rc<dyn Fn(f32) -> bool>,
974}
975
976impl SemanticsSetProgress {
977 pub fn new(handler: impl Fn(f32) -> bool + 'static) -> Self {
978 Self {
979 handler: Rc::new(handler),
980 }
981 }
982
983 pub fn invoke(&self, value: f32) -> bool {
984 (self.handler)(value)
985 }
986}
987
988impl fmt::Debug for SemanticsSetProgress {
989 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
990 f.debug_struct("SemanticsSetProgress")
991 .finish_non_exhaustive()
992 }
993}
994
995#[derive(Clone)]
999pub struct SemanticsSetText(Rc<dyn Fn(&str) -> bool>);
1000
1001impl SemanticsSetText {
1002 pub fn new(handler: impl Fn(&str) -> bool + 'static) -> Self {
1003 Self(Rc::new(handler))
1004 }
1005
1006 pub fn invoke(&self, text: &str) -> bool {
1007 (self.0)(text)
1008 }
1009}
1010
1011impl fmt::Debug for SemanticsSetText {
1012 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1013 f.write_str("SemanticsSetText")
1014 }
1015}
1016
1017#[derive(Clone)]
1023pub struct SemanticsSetSelection(Rc<dyn Fn(usize, usize) -> bool>);
1024
1025impl SemanticsSetSelection {
1026 pub fn new(handler: impl Fn(usize, usize) -> bool + 'static) -> Self {
1027 Self(Rc::new(handler))
1028 }
1029
1030 pub fn invoke(&self, anchor: usize, focus: usize) -> bool {
1031 (self.0)(anchor, focus)
1032 }
1033}
1034
1035impl fmt::Debug for SemanticsSetSelection {
1036 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1037 f.write_str("SemanticsSetSelection")
1038 }
1039}
1040
1041#[derive(Clone)]
1044pub struct SemanticsExpand(Rc<dyn Fn() -> bool>);
1045
1046impl SemanticsExpand {
1047 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1048 Self(Rc::new(handler))
1049 }
1050
1051 pub fn invoke(&self) -> bool {
1052 (self.0)()
1053 }
1054}
1055
1056impl fmt::Debug for SemanticsExpand {
1057 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1058 f.write_str("SemanticsExpand")
1059 }
1060}
1061
1062#[derive(Clone)]
1066pub struct SemanticsLongClick(Rc<dyn Fn() -> bool>);
1067
1068impl SemanticsLongClick {
1069 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1070 Self(Rc::new(handler))
1071 }
1072
1073 pub fn invoke(&self) -> bool {
1074 (self.0)()
1075 }
1076}
1077
1078impl fmt::Debug for SemanticsLongClick {
1079 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1080 f.write_str("SemanticsLongClick")
1081 }
1082}
1083
1084impl PartialEq for SemanticsLongClick {
1085 fn eq(&self, _other: &Self) -> bool {
1086 true
1087 }
1088}
1089
1090impl PartialEq for SemanticsExpand {
1091 fn eq(&self, _other: &Self) -> bool {
1092 true
1093 }
1094}
1095
1096#[derive(Clone)]
1100pub struct SemanticsDismiss(Rc<dyn Fn() -> bool>);
1101
1102impl SemanticsDismiss {
1103 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1104 Self(Rc::new(handler))
1105 }
1106
1107 pub fn invoke(&self) -> bool {
1108 (self.0)()
1109 }
1110}
1111
1112impl fmt::Debug for SemanticsDismiss {
1113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1114 f.write_str("SemanticsDismiss")
1115 }
1116}
1117
1118impl PartialEq for SemanticsDismiss {
1119 fn eq(&self, _other: &Self) -> bool {
1120 true
1121 }
1122}
1123
1124impl PartialEq for SemanticsSetText {
1125 fn eq(&self, _other: &Self) -> bool {
1126 true
1127 }
1128}
1129
1130impl PartialEq for SemanticsSetSelection {
1131 fn eq(&self, _other: &Self) -> bool {
1132 true
1133 }
1134}
1135
1136#[derive(Clone)]
1142pub struct SemanticsMagicTap(Rc<dyn Fn() -> bool>);
1143
1144impl SemanticsMagicTap {
1145 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1146 Self(Rc::new(handler))
1147 }
1148
1149 pub fn invoke(&self) -> bool {
1150 (self.0)()
1151 }
1152}
1153
1154impl fmt::Debug for SemanticsMagicTap {
1155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1156 f.write_str("SemanticsMagicTap")
1157 }
1158}
1159
1160impl PartialEq for SemanticsMagicTap {
1161 fn eq(&self, _other: &Self) -> bool {
1162 true
1163 }
1164}
1165
1166impl PartialEq for SemanticsSetProgress {
1167 fn eq(&self, _other: &Self) -> bool {
1168 true
1169 }
1170}
1171
1172impl Eq for SemanticsSetProgress {}
1173
1174#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1181pub enum LiveRegionMode {
1182 Polite,
1184 Assertive,
1187}
1188
1189#[derive(Clone)]
1196pub struct SemanticsCustomAction {
1197 pub label: String,
1199 handler: Rc<dyn Fn()>,
1200}
1201
1202impl SemanticsCustomAction {
1203 pub fn new(label: impl Into<String>, handler: impl Fn() + 'static) -> Self {
1204 Self {
1205 label: label.into(),
1206 handler: Rc::new(handler),
1207 }
1208 }
1209
1210 pub fn invoke(&self) {
1211 (self.handler)();
1212 }
1213}
1214
1215impl fmt::Debug for SemanticsCustomAction {
1216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1217 f.debug_struct("SemanticsCustomAction")
1218 .field("label", &self.label)
1219 .finish_non_exhaustive()
1220 }
1221}
1222
1223impl PartialEq for SemanticsCustomAction {
1224 fn eq(&self, other: &Self) -> bool {
1225 self.label == other.label
1226 }
1227}
1228
1229impl Eq for SemanticsCustomAction {}
1230
1231#[derive(Clone, Debug, PartialEq)]
1246pub struct CanvasSemanticsNode {
1247 pub key: u64,
1254 pub bounds: cranpose_ui_graphics::Rect,
1256 pub label: String,
1257 pub role: Option<SemanticsWidgetRole>,
1258 pub state_description: Option<String>,
1262 pub on_click_label: Option<String>,
1265 pub clickable: bool,
1266 pub selected: Option<bool>,
1268 pub toggled: Option<bool>,
1270 pub enabled: bool,
1271 pub custom_actions: Vec<SemanticsCustomAction>,
1272}
1273
1274impl Default for CanvasSemanticsNode {
1275 fn default() -> Self {
1276 Self {
1277 key: 0,
1278 bounds: cranpose_ui_graphics::Rect {
1279 x: 0.0,
1280 y: 0.0,
1281 width: 0.0,
1282 height: 0.0,
1283 },
1284 label: String::new(),
1285 role: None,
1286 state_description: None,
1287 on_click_label: None,
1288 clickable: false,
1289 selected: None,
1290 toggled: None,
1291 enabled: true,
1292 custom_actions: Vec::new(),
1293 }
1294 }
1295}
1296
1297impl CanvasSemanticsNode {
1298 pub fn control(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1300 Self {
1301 key,
1302 bounds,
1303 label: label.into(),
1304 clickable: true,
1305 ..Self::default()
1306 }
1307 }
1308
1309 pub fn text(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1311 Self {
1312 key,
1313 bounds,
1314 label: label.into(),
1315 ..Self::default()
1316 }
1317 }
1318
1319 pub fn with_role(mut self, role: SemanticsWidgetRole) -> Self {
1320 self.role = Some(role);
1321 self
1322 }
1323
1324 pub fn with_state_description(mut self, state: impl Into<String>) -> Self {
1325 self.state_description = Some(state.into());
1326 self
1327 }
1328
1329 pub fn with_click_label(mut self, label: impl Into<String>) -> Self {
1330 self.on_click_label = Some(label.into());
1331 self.clickable = true;
1332 self
1333 }
1334
1335 pub fn with_selected(mut self, selected: bool) -> Self {
1336 self.selected = Some(selected);
1337 self
1338 }
1339
1340 pub fn with_toggled(mut self, toggled: bool) -> Self {
1341 self.toggled = Some(toggled);
1342 self
1343 }
1344
1345 pub fn with_enabled(mut self, enabled: bool) -> Self {
1346 self.enabled = enabled;
1347 self
1348 }
1349
1350 pub fn with_custom_action(mut self, action: SemanticsCustomAction) -> Self {
1351 self.custom_actions.push(action);
1352 self
1353 }
1354}
1355
1356#[derive(Clone, Debug, PartialEq)]
1358pub struct SemanticsConfiguration {
1359 pub content_description: Option<String>,
1360 pub state_description: Option<String>,
1362 pub on_click_label: Option<String>,
1364 pub on_click: Option<SemanticsCustomAction>,
1367 pub on_long_click: Option<SemanticsLongClick>,
1370 pub on_long_click_label: Option<String>,
1373 pub on_magic_tap: Option<SemanticsMagicTap>,
1377 pub on_magic_tap_label: Option<String>,
1380 pub input_labels: Vec<String>,
1384 pub language: Option<String>,
1388 pub role: Option<SemanticsWidgetRole>,
1390 pub selected: Option<bool>,
1391 pub toggled: Option<bool>,
1392 pub enabled: bool,
1393 pub is_clickable: bool,
1394 pub is_editable_text: bool,
1395 pub multiline: bool,
1397 pub text: Option<String>,
1400 pub text_selection: Option<crate::text::TextRange>,
1401 pub custom_actions: Vec<SemanticsCustomAction>,
1402 pub canvas_children: Vec<CanvasSemanticsNode>,
1405 pub is_modal: bool,
1408 pub hidden: bool,
1412 pub merge_descendants: bool,
1416 pub selectable_group: bool,
1420 pub pane_title: Option<String>,
1423 pub error: Option<String>,
1426 pub password: bool,
1429 pub traversal_index: f32,
1433 pub live_region: Option<LiveRegionMode>,
1436 pub progress: Option<ProgressBarRangeInfo>,
1439 pub set_progress: Option<SemanticsSetProgress>,
1442 pub set_text: Option<SemanticsSetText>,
1445 pub set_selection: Option<SemanticsSetSelection>,
1448 pub expand: Option<SemanticsExpand>,
1451 pub dismiss: Option<SemanticsDismiss>,
1455 pub collapse: Option<SemanticsExpand>,
1458 pub vertical_scroll: Option<ScrollAxisRange>,
1461 pub horizontal_scroll: Option<ScrollAxisRange>,
1464 pub scroll_by: Option<SemanticsScrollBy>,
1467 pub scroll_to_index: Option<SemanticsScrollToIndex>,
1471 pub collection: Option<CollectionInfo>,
1473}
1474
1475impl Default for SemanticsConfiguration {
1476 fn default() -> Self {
1477 Self {
1478 content_description: None,
1479 state_description: None,
1480 on_click_label: None,
1481 on_click: None,
1482 on_long_click: None,
1483 on_long_click_label: None,
1484 on_magic_tap: None,
1485 on_magic_tap_label: None,
1486 input_labels: Vec::new(),
1487 language: None,
1488 role: None,
1489 selected: None,
1490 toggled: None,
1491 enabled: true,
1492 is_clickable: false,
1493 is_editable_text: false,
1494 multiline: false,
1495 text: None,
1496 text_selection: None,
1497 custom_actions: Vec::new(),
1498 canvas_children: Vec::new(),
1499 is_modal: false,
1500 hidden: false,
1501 merge_descendants: false,
1502 selectable_group: false,
1503 pane_title: None,
1504 error: None,
1505 password: false,
1506 traversal_index: 0.0,
1507 live_region: None,
1508 progress: None,
1509 set_progress: None,
1510 set_text: None,
1511 set_selection: None,
1512 expand: None,
1513 dismiss: None,
1514 collapse: None,
1515 vertical_scroll: None,
1516 horizontal_scroll: None,
1517 scroll_by: None,
1518 scroll_to_index: None,
1519 collection: None,
1520 }
1521 }
1522}
1523
1524pub type SemanticsSpec = SemanticsConfiguration;
1533
1534impl SemanticsConfiguration {
1535 pub fn new() -> Self {
1538 Self::default()
1539 }
1540
1541 pub fn content_description(mut self, name: impl Into<String>) -> Self {
1544 self.content_description = Some(name.into());
1545 self
1546 }
1547
1548 pub fn state_description(mut self, state: impl Into<String>) -> Self {
1551 self.state_description = Some(state.into());
1552 self
1553 }
1554
1555 pub fn clickable(mut self) -> Self {
1557 self.is_clickable = true;
1558 self
1559 }
1560
1561 pub fn on_click(mut self, label: impl Into<String>, action: impl Fn() + 'static) -> Self {
1564 self.on_click = Some(SemanticsCustomAction::new(label, action));
1565 self
1566 }
1567
1568 pub fn on_long_click(
1572 mut self,
1573 label: impl Into<String>,
1574 action: impl Fn() -> bool + 'static,
1575 ) -> Self {
1576 self.on_long_click_label = Some(label.into());
1577 self.on_long_click = Some(SemanticsLongClick::new(action));
1578 self
1579 }
1580
1581 pub fn on_magic_tap(
1585 mut self,
1586 label: impl Into<String>,
1587 action: impl Fn() -> bool + 'static,
1588 ) -> Self {
1589 self.on_magic_tap_label = Some(label.into());
1590 self.on_magic_tap = Some(SemanticsMagicTap::new(action));
1591 self
1592 }
1593
1594 pub fn input_labels<S: Into<String>>(mut self, labels: impl IntoIterator<Item = S>) -> Self {
1597 self.input_labels = labels.into_iter().map(Into::into).collect();
1598 self
1599 }
1600
1601 pub fn language(mut self, tag: impl Into<String>) -> Self {
1604 self.language = Some(tag.into());
1605 self
1606 }
1607
1608 pub fn toggled(mut self, toggled: bool) -> Self {
1610 self.toggled = Some(toggled);
1611 self
1612 }
1613
1614 pub fn selected(mut self, selected: bool) -> Self {
1617 self.selected = Some(selected);
1618 self
1619 }
1620
1621 pub fn role(mut self, role: SemanticsWidgetRole) -> Self {
1623 self.role = Some(role);
1624 self
1625 }
1626
1627 pub fn heading(self) -> Self {
1630 self.role(SemanticsWidgetRole::Header)
1631 }
1632
1633 pub fn error(mut self, message: impl Into<String>) -> Self {
1635 self.error = Some(message.into());
1636 self
1637 }
1638
1639 pub fn password(mut self) -> Self {
1641 self.password = true;
1642 self
1643 }
1644
1645 pub fn pane_title(mut self, title: impl Into<String>) -> Self {
1648 self.pane_title = Some(title.into());
1649 self
1650 }
1651
1652 pub fn traversal_index(mut self, index: f32) -> Self {
1655 self.traversal_index = index;
1656 self
1657 }
1658
1659 pub fn hidden(mut self) -> Self {
1662 self.hidden = true;
1663 self
1664 }
1665
1666 pub fn merge_descendants(mut self) -> Self {
1669 self.merge_descendants = true;
1670 self
1671 }
1672
1673 pub fn selectable_group(mut self) -> Self {
1676 self.selectable_group = true;
1677 self
1678 }
1679
1680 pub fn live_region(mut self, mode: LiveRegionMode) -> Self {
1683 self.live_region = Some(mode);
1684 self
1685 }
1686 pub fn merge(&mut self, other: &SemanticsConfiguration) {
1687 if let Some(description) = &other.content_description {
1688 self.content_description = Some(description.clone());
1689 }
1690 if let Some(state) = &other.state_description {
1691 self.state_description = Some(state.clone());
1692 }
1693 if let Some(label) = &other.on_click_label {
1694 self.on_click_label = Some(label.clone());
1695 }
1696 if let Some(label) = &other.on_long_click_label {
1697 self.on_long_click_label = Some(label.clone());
1698 }
1699 if let Some(label) = &other.on_magic_tap_label {
1700 self.on_magic_tap_label = Some(label.clone());
1701 }
1702 if !other.input_labels.is_empty() {
1703 self.input_labels.clone_from(&other.input_labels);
1704 }
1705 if let Some(language) = &other.language {
1706 self.language = Some(language.clone());
1707 }
1708 if let Some(role) = other.role {
1709 self.role = Some(role);
1710 }
1711 if let Some(selected) = other.selected {
1712 self.selected = Some(selected);
1713 }
1714 if let Some(toggled) = other.toggled {
1715 self.toggled = Some(toggled);
1716 }
1717 self.enabled &= other.enabled;
1718 self.is_clickable |= other.is_clickable;
1719 self.is_editable_text |= other.is_editable_text;
1720 self.multiline |= other.multiline;
1721 if let Some(text) = &other.text {
1722 self.text = Some(text.clone());
1723 }
1724 self.is_modal |= other.is_modal;
1725 self.hidden |= other.hidden;
1726 self.merge_descendants |= other.merge_descendants;
1727 self.selectable_group |= other.selectable_group;
1728 self.password |= other.password;
1729 if other.traversal_index != 0.0 {
1730 self.traversal_index = other.traversal_index;
1731 }
1732 if let Some(live_region) = other.live_region {
1733 self.live_region = Some(live_region);
1734 }
1735 self.merge_words(other);
1736 self.merge_actions(other);
1737 self.merge_ranges(other);
1738 }
1739
1740 fn merge_words(&mut self, other: &SemanticsConfiguration) {
1741 if let Some(title) = &other.pane_title {
1742 self.pane_title = Some(title.clone());
1743 }
1744 if let Some(error) = &other.error {
1745 self.error = Some(error.clone());
1746 }
1747 }
1748
1749 fn merge_actions(&mut self, other: &SemanticsConfiguration) {
1750 if let Some(on_click) = &other.on_click {
1751 self.on_click = Some(on_click.clone());
1752 }
1753 self.custom_actions
1754 .extend(other.custom_actions.iter().cloned());
1755 self.canvas_children
1756 .extend(other.canvas_children.iter().cloned());
1757 if let Some(set_progress) = &other.set_progress {
1758 self.set_progress = Some(set_progress.clone());
1759 }
1760 if let Some(set_text) = &other.set_text {
1761 self.set_text = Some(set_text.clone());
1762 }
1763 if let Some(set_selection) = &other.set_selection {
1764 self.set_selection = Some(set_selection.clone());
1765 }
1766 if let Some(expand) = &other.expand {
1767 self.expand = Some(expand.clone());
1768 }
1769 if let Some(collapse) = &other.collapse {
1770 self.collapse = Some(collapse.clone());
1771 }
1772 if let Some(dismiss) = &other.dismiss {
1773 self.dismiss = Some(dismiss.clone());
1774 }
1775 if let Some(long_click) = &other.on_long_click {
1776 self.on_long_click = Some(long_click.clone());
1777 }
1778 if let Some(magic_tap) = &other.on_magic_tap {
1779 self.on_magic_tap = Some(magic_tap.clone());
1780 }
1781 if let Some(scroll_by) = &other.scroll_by {
1782 self.scroll_by = Some(scroll_by.clone());
1783 }
1784 if let Some(scroll_to_index) = &other.scroll_to_index {
1785 self.scroll_to_index = Some(scroll_to_index.clone());
1786 }
1787 }
1788
1789 fn merge_ranges(&mut self, other: &SemanticsConfiguration) {
1790 if let Some(selection) = other.text_selection {
1791 self.text_selection = Some(selection);
1792 }
1793 if let Some(progress) = other.progress {
1794 self.progress = Some(progress);
1795 }
1796 if let Some(range) = other.vertical_scroll {
1797 self.vertical_scroll = Some(range);
1798 }
1799 if let Some(range) = other.horizontal_scroll {
1800 self.horizontal_scroll = Some(range);
1801 }
1802 if let Some(collection) = other.collection {
1803 self.collection = Some(collection);
1804 }
1805 }
1806
1807 pub fn is_activatable(&self) -> bool {
1810 self.is_clickable || self.on_click_label.is_some() || self.on_click.is_some()
1811 }
1812}
1813
1814impl fmt::Debug for dyn ModifierNode {
1815 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1816 f.debug_struct("ModifierNode").finish_non_exhaustive()
1817 }
1818}
1819
1820impl dyn ModifierNode {
1821 pub fn as_any(&self) -> &dyn Any {
1822 self
1823 }
1824
1825 pub fn as_any_mut(&mut self) -> &mut dyn Any {
1826 self
1827 }
1828}
1829
1830pub trait ModifierNodeElement: fmt::Debug + Hash + PartialEq + 'static {
1833 type Node: ModifierNode;
1834
1835 fn create(&self) -> Self::Node;
1837
1838 fn update(&self, node: &mut Self::Node);
1840
1841 fn key(&self) -> Option<u64> {
1843 None
1844 }
1845
1846 fn inspector_name(&self) -> &'static str {
1848 type_name::<Self>()
1849 }
1850
1851 fn inspector_properties(&self, _inspector: &mut dyn FnMut(&'static str, String)) {}
1853
1854 fn capabilities(&self) -> NodeCapabilities {
1857 NodeCapabilities::default()
1858 }
1859
1860 fn always_update(&self) -> bool {
1866 false
1867 }
1868
1869 fn auto_invalidate_on_update(&self) -> bool {
1872 true
1873 }
1874
1875 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
1882 None
1883 }
1884
1885 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
1892 Vec::new()
1893 }
1894}
1895
1896#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1898pub struct NodeCapabilities(u32);
1899
1900impl NodeCapabilities {
1901 pub const NONE: Self = Self(0);
1903 pub const LAYOUT: Self = Self(1 << 0);
1905 pub const DRAW: Self = Self(1 << 1);
1907 pub const POINTER_INPUT: Self = Self(1 << 2);
1909 pub const SEMANTICS: Self = Self(1 << 3);
1911 pub const MODIFIER_LOCALS: Self = Self(1 << 4);
1913 pub const FOCUS: Self = Self(1 << 5);
1915 pub const WINDOW_ROOT: Self = Self(1 << 6);
1919
1920 pub const fn empty() -> Self {
1922 Self::NONE
1923 }
1924
1925 pub const fn contains(self, other: Self) -> bool {
1927 (self.0 & other.0) == other.0
1928 }
1929
1930 pub const fn intersects(self, other: Self) -> bool {
1932 (self.0 & other.0) != 0
1933 }
1934
1935 pub fn insert(&mut self, other: Self) {
1937 self.0 |= other.0;
1938 }
1939
1940 pub const fn bits(self) -> u32 {
1942 self.0
1943 }
1944
1945 pub const fn is_empty(self) -> bool {
1947 self.0 == 0
1948 }
1949
1950 pub const fn for_invalidation(kind: InvalidationKind) -> Self {
1952 match kind {
1953 InvalidationKind::Layout => Self::LAYOUT,
1954 InvalidationKind::Draw => Self::DRAW,
1955 InvalidationKind::PointerInput => Self::POINTER_INPUT,
1956 InvalidationKind::Semantics => Self::SEMANTICS,
1957 InvalidationKind::Focus => Self::FOCUS,
1958 }
1959 }
1960}
1961
1962impl Default for NodeCapabilities {
1963 fn default() -> Self {
1964 Self::NONE
1965 }
1966}
1967
1968impl fmt::Debug for NodeCapabilities {
1969 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1970 f.debug_struct("NodeCapabilities")
1971 .field("layout", &self.contains(Self::LAYOUT))
1972 .field("draw", &self.contains(Self::DRAW))
1973 .field("pointer_input", &self.contains(Self::POINTER_INPUT))
1974 .field("semantics", &self.contains(Self::SEMANTICS))
1975 .field("modifier_locals", &self.contains(Self::MODIFIER_LOCALS))
1976 .field("focus", &self.contains(Self::FOCUS))
1977 .field("window_root", &self.contains(Self::WINDOW_ROOT))
1978 .finish()
1979 }
1980}
1981
1982impl BitOr for NodeCapabilities {
1983 type Output = Self;
1984
1985 fn bitor(self, rhs: Self) -> Self::Output {
1986 Self(self.0 | rhs.0)
1987 }
1988}
1989
1990impl BitOrAssign for NodeCapabilities {
1991 fn bitor_assign(&mut self, rhs: Self) {
1992 self.0 |= rhs.0;
1993 }
1994}
1995
1996pub type ModifierInvalidations = smallvec::SmallVec<[ModifierInvalidation; 5]>;
1999
2000#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2002pub struct ModifierInvalidation {
2003 kind: InvalidationKind,
2004 capabilities: NodeCapabilities,
2005}
2006
2007impl ModifierInvalidation {
2008 pub const fn new(kind: InvalidationKind, capabilities: NodeCapabilities) -> Self {
2010 Self { kind, capabilities }
2011 }
2012
2013 pub const fn kind(self) -> InvalidationKind {
2015 self.kind
2016 }
2017
2018 pub const fn capabilities(self) -> NodeCapabilities {
2020 self.capabilities
2021 }
2022}
2023
2024pub trait AnyModifierElement: fmt::Debug {
2026 fn node_type(&self) -> TypeId;
2027
2028 fn element_type(&self) -> TypeId;
2029
2030 fn create_node(&self) -> Box<dyn ModifierNode>;
2031
2032 fn can_update_node(&self, node: &dyn ModifierNode) -> bool;
2033
2034 fn update_node(&self, node: &mut dyn ModifierNode);
2035
2036 fn key(&self) -> Option<u64>;
2037
2038 fn capabilities(&self) -> NodeCapabilities {
2039 NodeCapabilities::default()
2040 }
2041
2042 fn hash_code(&self) -> u64;
2043
2044 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool;
2045
2046 fn inspector_name(&self) -> &'static str;
2047
2048 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String));
2049
2050 fn requires_update(&self) -> bool;
2051
2052 fn auto_invalidates_on_update(&self) -> bool;
2053
2054 fn update_invalidation_kind(&self) -> Option<InvalidationKind>;
2055
2056 fn provides_composition_locals(&self) -> bool {
2058 false
2059 }
2060
2061 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2063 Vec::new()
2064 }
2065
2066 fn as_any(&self) -> &dyn Any;
2067}
2068
2069struct TypedModifierElement<E: ModifierNodeElement> {
2070 element: E,
2071 cached_hash: u64,
2072 provides_locals: bool,
2073}
2074
2075impl<E: ModifierNodeElement> TypedModifierElement<E> {
2076 fn new(element: E) -> Self {
2077 let mut hasher = default::new();
2078 element.hash(&mut hasher);
2079 let provides_locals = !element.provided_composition_locals().is_empty();
2080 Self {
2081 element,
2082 cached_hash: hasher.finish(),
2083 provides_locals,
2084 }
2085 }
2086}
2087
2088impl<E> fmt::Debug for TypedModifierElement<E>
2089where
2090 E: ModifierNodeElement,
2091{
2092 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2093 f.debug_struct("TypedModifierElement")
2094 .field("type", &type_name::<E>())
2095 .finish()
2096 }
2097}
2098
2099impl<E> AnyModifierElement for TypedModifierElement<E>
2100where
2101 E: ModifierNodeElement,
2102{
2103 fn node_type(&self) -> TypeId {
2104 TypeId::of::<E::Node>()
2105 }
2106
2107 fn element_type(&self) -> TypeId {
2108 TypeId::of::<E>()
2109 }
2110
2111 fn create_node(&self) -> Box<dyn ModifierNode> {
2112 Box::new(self.element.create())
2113 }
2114
2115 fn can_update_node(&self, node: &dyn ModifierNode) -> bool {
2116 node.as_any().is::<E::Node>()
2117 }
2118
2119 fn update_node(&self, node: &mut dyn ModifierNode) {
2120 if let Some(typed) = node.as_any_mut().downcast_mut::<E::Node>() {
2121 self.element.update(typed);
2122 }
2123 }
2124
2125 fn key(&self) -> Option<u64> {
2126 self.element.key()
2127 }
2128
2129 fn capabilities(&self) -> NodeCapabilities {
2130 self.element.capabilities()
2131 }
2132
2133 fn provides_composition_locals(&self) -> bool {
2134 self.provides_locals
2135 }
2136
2137 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2138 self.element.provided_composition_locals()
2139 }
2140
2141 fn hash_code(&self) -> u64 {
2142 self.cached_hash
2143 }
2144
2145 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool {
2146 other
2147 .as_any()
2148 .downcast_ref::<Self>()
2149 .is_some_and(|typed| typed.element == self.element)
2150 }
2151
2152 fn inspector_name(&self) -> &'static str {
2153 self.element.inspector_name()
2154 }
2155
2156 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String)) {
2157 self.element.inspector_properties(visitor);
2158 }
2159
2160 fn requires_update(&self) -> bool {
2161 self.element.always_update()
2162 }
2163
2164 fn auto_invalidates_on_update(&self) -> bool {
2165 self.element.auto_invalidate_on_update()
2166 }
2167
2168 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
2169 self.element.update_invalidation_kind()
2170 }
2171
2172 fn as_any(&self) -> &dyn Any {
2173 self
2174 }
2175}
2176
2177fn request_update_auto_invalidations(
2178 element: &dyn AnyModifierElement,
2179 context: &mut dyn ModifierNodeContext,
2180 capabilities: NodeCapabilities,
2181) {
2182 if let Some(kind) = element.update_invalidation_kind() {
2183 let capabilities = NodeCapabilities::for_invalidation(kind);
2184 context.push_active_capabilities(capabilities);
2185 context.invalidate(kind);
2186 context.pop_active_capabilities();
2187 } else if element.auto_invalidates_on_update() {
2188 request_auto_invalidations(context, capabilities);
2189 }
2190}
2191
2192pub fn modifier_element<E: ModifierNodeElement>(element: E) -> DynModifierElement {
2195 Rc::new(TypedModifierElement::new(element))
2196}
2197
2198pub type DynModifierElement = Rc<dyn AnyModifierElement>;
2200
2201#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2202enum TraversalDirection {
2203 Forward,
2204 Backward,
2205}
2206
2207pub struct ModifierChainIter<'a> {
2212 chain: &'a ModifierNodeChain,
2213 cursor: usize,
2214 remaining: usize,
2215 direction: TraversalDirection,
2216}
2217
2218impl<'a> ModifierChainIter<'a> {
2219 fn forward(chain: &'a ModifierNodeChain) -> Self {
2220 Self {
2221 chain,
2222 cursor: 0,
2223 remaining: chain.ordered_nodes.len(),
2224 direction: TraversalDirection::Forward,
2225 }
2226 }
2227
2228 fn backward(chain: &'a ModifierNodeChain) -> Self {
2229 let len = chain.ordered_nodes.len();
2230 Self {
2231 chain,
2232 cursor: len.wrapping_sub(1),
2233 remaining: len,
2234 direction: TraversalDirection::Backward,
2235 }
2236 }
2237}
2238
2239impl<'a> Iterator for ModifierChainIter<'a> {
2240 type Item = ModifierChainNodeRef<'a>;
2241
2242 #[inline]
2243 fn next(&mut self) -> Option<Self::Item> {
2244 if self.remaining == 0 {
2245 return None;
2246 }
2247 let (link, caps, agg) = self.chain.ordered_nodes[self.cursor];
2248 let node_ref = self.chain.make_node_ref_with_caps(link, caps, agg);
2249 self.remaining -= 1;
2250 match self.direction {
2251 TraversalDirection::Forward => self.cursor += 1,
2252 TraversalDirection::Backward => self.cursor = self.cursor.wrapping_sub(1),
2253 }
2254 Some(node_ref)
2255 }
2256
2257 #[inline]
2258 fn size_hint(&self) -> (usize, Option<usize>) {
2259 (self.remaining, Some(self.remaining))
2260 }
2261}
2262
2263impl ExactSizeIterator for ModifierChainIter<'_> {}
2264impl std::iter::FusedIterator for ModifierChainIter<'_> {}
2265
2266#[derive(Debug)]
2267struct ModifierNodeEntry {
2268 element_type: TypeId,
2269 node_type: TypeId,
2270 key: Option<u64>,
2271 hash_code: u64,
2272 element: DynModifierElement,
2273 node: Rc<RefCell<Box<dyn ModifierNode>>>,
2274 capabilities: NodeCapabilities,
2275}
2276
2277impl ModifierNodeEntry {
2278 fn new(
2279 element_type: TypeId,
2280 node_type: TypeId,
2281 key: Option<u64>,
2282 element: DynModifierElement,
2283 node: Box<dyn ModifierNode>,
2284 hash_code: u64,
2285 capabilities: NodeCapabilities,
2286 ) -> Self {
2287 let node_rc = Rc::new(RefCell::new(node));
2288 let entry = Self {
2289 element_type,
2290 node_type,
2291 key,
2292 hash_code,
2293 element,
2294 node: Rc::clone(&node_rc),
2295 capabilities,
2296 };
2297 entry
2298 .node
2299 .borrow()
2300 .node_state()
2301 .set_capabilities(entry.capabilities);
2302 entry
2303 }
2304}
2305
2306fn visit_node_tree_mut(
2307 node: &mut dyn ModifierNode,
2308 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
2309) {
2310 visitor(node);
2311 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
2312}
2313
2314fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
2315 let mut current = 0usize;
2316 let mut result: Option<&dyn ModifierNode> = None;
2317 node.for_each_delegate(&mut |child| {
2318 if result.is_none() && current == target {
2319 result = Some(child);
2320 }
2321 current += 1;
2322 });
2323 result
2324}
2325
2326fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
2327 let mut current = 0usize;
2328 let mut result: Option<&mut dyn ModifierNode> = None;
2329 node.for_each_delegate_mut(&mut |child| {
2330 if result.is_none() && current == target {
2331 result = Some(child);
2332 }
2333 current += 1;
2334 });
2335 result
2336}
2337
2338fn with_node_context<F, R>(
2339 node: &mut dyn ModifierNode,
2340 context: &mut dyn ModifierNodeContext,
2341 f: F,
2342) -> R
2343where
2344 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
2345{
2346 context.push_active_capabilities(node.node_state().capabilities());
2347 let result = f(node, context);
2348 context.pop_active_capabilities();
2349 result
2350}
2351
2352fn request_auto_invalidations(
2353 context: &mut dyn ModifierNodeContext,
2354 capabilities: NodeCapabilities,
2355) {
2356 if capabilities.is_empty() {
2357 return;
2358 }
2359
2360 context.push_active_capabilities(capabilities);
2361
2362 if capabilities.contains(NodeCapabilities::LAYOUT) {
2363 context.invalidate(InvalidationKind::Layout);
2364 }
2365 if capabilities.contains(NodeCapabilities::DRAW) {
2366 context.invalidate(InvalidationKind::Draw);
2367 }
2368 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
2369 context.invalidate(InvalidationKind::PointerInput);
2370 }
2371 if capabilities.contains(NodeCapabilities::SEMANTICS) {
2372 context.invalidate(InvalidationKind::Semantics);
2373 }
2374 if capabilities.contains(NodeCapabilities::FOCUS) {
2375 context.invalidate(InvalidationKind::Focus);
2376 }
2377
2378 context.pop_active_capabilities();
2379}
2380
2381fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
2382 visit_node_tree_mut(node, &mut |n| {
2383 if !n.node_state().is_attached() {
2384 n.node_state().set_attached(true);
2385 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
2386 }
2387 });
2388}
2389
2390fn reset_node_tree(node: &mut dyn ModifierNode) {
2391 visit_node_tree_mut(node, &mut |n| n.on_reset());
2392}
2393
2394fn detach_node_tree(node: &mut dyn ModifierNode) {
2395 visit_node_tree_mut(node, &mut |n| {
2396 if n.node_state().is_attached() {
2397 n.on_detach();
2398 n.node_state().set_attached(false);
2399 }
2400 n.node_state().set_parent_link(None);
2401 n.node_state().set_child_link(None);
2402 n.node_state()
2403 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2404 });
2405}
2406
2407pub struct ModifierNodeChain {
2414 entries: Vec<ModifierNodeEntry>,
2415 aggregated_capabilities: NodeCapabilities,
2416 head_aggregate_child_capabilities: NodeCapabilities,
2417 head_sentinel: Box<SentinelNode>,
2418 tail_sentinel: Box<SentinelNode>,
2419 ordered_nodes: Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
2420}
2421
2422#[derive(Default)]
2426struct ReconcileScratch {
2427 old_used: Vec<bool>,
2428 match_order: Vec<Option<usize>>,
2429 final_slots: Vec<Option<ModifierNodeEntry>>,
2430 elements: Vec<DynModifierElement>,
2431}
2432
2433thread_local! {
2434 static RECONCILE_SCRATCH: std::cell::RefCell<ReconcileScratch> =
2435 std::cell::RefCell::default();
2436}
2437
2438struct SentinelNode {
2439 state: NodeState,
2440}
2441
2442impl SentinelNode {
2443 fn new() -> Self {
2444 Self {
2445 state: NodeState::sentinel(),
2446 }
2447 }
2448}
2449
2450impl DelegatableNode for SentinelNode {
2451 fn node_state(&self) -> &NodeState {
2452 &self.state
2453 }
2454}
2455
2456impl ModifierNode for SentinelNode {}
2457
2458#[derive(Clone)]
2459pub struct ModifierChainNodeRef<'a> {
2460 chain: &'a ModifierNodeChain,
2461 link: NodeLink,
2462 cached_capabilities: Option<NodeCapabilities>,
2463 cached_aggregate_child: Option<NodeCapabilities>,
2464}
2465
2466impl Default for ModifierNodeChain {
2467 fn default() -> Self {
2468 Self::new()
2469 }
2470}
2471
2472struct EntryIndex {
2473 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2474 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2475 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
2476}
2477
2478struct EntryMatchQuery<'a> {
2479 element_type: TypeId,
2480 node_type: TypeId,
2481 key: Option<u64>,
2482 hash_code: u64,
2483 element: &'a DynModifierElement,
2484}
2485
2486impl EntryIndex {
2487 fn build(entries: &[ModifierNodeEntry]) -> Self {
2488 let mut keyed = HashMap::default();
2489 let mut hashed = HashMap::default();
2490 let mut typed = HashMap::default();
2491
2492 for (i, entry) in entries.iter().enumerate() {
2493 if let Some(key_value) = entry.key {
2494 keyed
2495 .entry((entry.element_type, entry.node_type, key_value))
2496 .or_insert_with(Vec::new)
2497 .push(i);
2498 } else {
2499 hashed
2500 .entry((entry.element_type, entry.node_type, entry.hash_code))
2501 .or_insert_with(Vec::new)
2502 .push(i);
2503 typed
2504 .entry((entry.element_type, entry.node_type))
2505 .or_insert_with(Vec::new)
2506 .push(i);
2507 }
2508 }
2509
2510 Self {
2511 keyed,
2512 hashed,
2513 typed,
2514 }
2515 }
2516
2517 fn find_match(
2518 &self,
2519 entries: &[ModifierNodeEntry],
2520 used: &[bool],
2521 query: EntryMatchQuery<'_>,
2522 ) -> Option<usize> {
2523 if let Some(key_value) = query.key {
2524 if let Some(candidates) =
2525 self.keyed
2526 .get(&(query.element_type, query.node_type, key_value))
2527 {
2528 for &i in candidates {
2529 if !used[i] {
2530 return Some(i);
2531 }
2532 }
2533 }
2534 } else {
2535 if let Some(candidates) =
2536 self.hashed
2537 .get(&(query.element_type, query.node_type, query.hash_code))
2538 {
2539 for &i in candidates {
2540 if !used[i]
2541 && entries[i]
2542 .element
2543 .as_ref()
2544 .equals_element(query.element.as_ref())
2545 {
2546 return Some(i);
2547 }
2548 }
2549 }
2550
2551 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
2552 for &i in candidates {
2553 if !used[i] {
2554 return Some(i);
2555 }
2556 }
2557 }
2558 }
2559
2560 None
2561 }
2562}
2563
2564fn update_entry_in_place(
2569 entry: &mut ModifierNodeEntry,
2570 element: &DynModifierElement,
2571 context: &mut dyn ModifierNodeContext,
2572) -> bool {
2573 if entry.element_type != element.element_type()
2574 || entry.node_type != element.node_type()
2575 || entry.key != element.key()
2576 || !element.can_update_node(&**entry.node.borrow())
2577 {
2578 return false;
2579 }
2580 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2581 let capabilities = element.capabilities();
2582 attach_if_detached(entry, context);
2583 if !same_element || element.requires_update() {
2584 element.update_node(&mut **entry.node.borrow_mut());
2585 entry.element = element.clone();
2586 entry.hash_code = element.hash_code();
2587 request_update_auto_invalidations(element.as_ref(), context, capabilities);
2588 }
2589 entry.capabilities = capabilities;
2590 entry
2591 .node
2592 .borrow()
2593 .node_state()
2594 .set_capabilities(capabilities);
2595 true
2596}
2597
2598fn attach_if_detached(entry: &ModifierNodeEntry, context: &mut dyn ModifierNodeContext) {
2599 let attached = entry.node.borrow().node_state().is_attached();
2600 if !attached {
2601 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2602 }
2603}
2604
2605fn fresh_entry(
2607 element: DynModifierElement,
2608 context: &mut dyn ModifierNodeContext,
2609) -> ModifierNodeEntry {
2610 let capabilities = element.capabilities();
2611 let entry = ModifierNodeEntry::new(
2612 element.element_type(),
2613 element.node_type(),
2614 element.key(),
2615 element.clone(),
2616 element.create_node(),
2617 element.hash_code(),
2618 capabilities,
2619 );
2620 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2621 element.update_node(&mut **entry.node.borrow_mut());
2622 request_auto_invalidations(context, capabilities);
2623 entry
2624}
2625
2626fn reconcile_element(
2631 element: DynModifierElement,
2632 new_pos: usize,
2633 (old_entries, index): (&mut [ModifierNodeEntry], &EntryIndex),
2634 (used, match_order): (&mut [bool], &mut [Option<usize>]),
2635 context: &mut dyn ModifierNodeContext,
2636) -> Option<ModifierNodeEntry> {
2637 let element_type = element.element_type();
2638 let node_type = element.node_type();
2639 let key = element.key();
2640 let hash_code = element.hash_code();
2641 let capabilities = element.capabilities();
2642 let Some(idx) = index.find_match(
2643 old_entries,
2644 used,
2645 EntryMatchQuery {
2646 element_type,
2647 node_type,
2648 key,
2649 hash_code,
2650 element: &element,
2651 },
2652 ) else {
2653 return Some(fresh_entry(element, context));
2654 };
2655 let entry = &mut old_entries[idx];
2656 if !element.can_update_node(&**entry.node.borrow()) {
2657 return Some(fresh_entry(element, context));
2658 }
2659
2660 used[idx] = true;
2661 match_order[idx] = Some(new_pos);
2662 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2663 attach_if_detached(entry, context);
2664 if !same_element || element.requires_update() {
2665 element.update_node(&mut **entry.node.borrow_mut());
2666 entry.element = element;
2667 entry.hash_code = hash_code;
2668 request_update_auto_invalidations(entry.element.as_ref(), context, capabilities);
2669 }
2670 if idx != new_pos {
2671 request_auto_invalidations(context, capabilities);
2672 }
2673 entry.key = key;
2674 entry.element_type = element_type;
2675 entry.node_type = node_type;
2676 entry.capabilities = capabilities;
2677 entry
2678 .node
2679 .borrow()
2680 .node_state()
2681 .set_capabilities(capabilities);
2682 None
2683}
2684
2685impl ModifierNodeChain {
2686 pub fn new() -> Self {
2687 let mut chain = Self {
2688 entries: Vec::new(),
2689 aggregated_capabilities: NodeCapabilities::empty(),
2690 head_aggregate_child_capabilities: NodeCapabilities::empty(),
2691 head_sentinel: Box::new(SentinelNode::new()),
2692 tail_sentinel: Box::new(SentinelNode::new()),
2693 ordered_nodes: Vec::new(),
2694 };
2695 chain.sync_chain_links();
2696 chain
2697 }
2698
2699 pub fn detach_nodes(&mut self) {
2701 for entry in &self.entries {
2702 detach_node_tree(&mut **entry.node.borrow_mut());
2703 }
2704 }
2705
2706 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
2708 for entry in &self.entries {
2709 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2710 }
2711 }
2712
2713 pub fn repair_chain(&mut self) {
2716 self.sync_chain_links();
2717 }
2718
2719 pub fn update_from_slice(
2725 &mut self,
2726 elements: &[DynModifierElement],
2727 context: &mut dyn ModifierNodeContext,
2728 ) {
2729 self.update_from_ref_iter(elements.iter(), context);
2730 }
2731
2732 pub fn update_from_ref_iter<'a, I>(
2737 &mut self,
2738 elements: I,
2739 context: &mut dyn ModifierNodeContext,
2740 ) where
2741 I: Iterator<Item = &'a DynModifierElement>,
2742 {
2743 let mut scratch = RECONCILE_SCRATCH
2746 .try_with(|scratch| std::mem::take(&mut *scratch.borrow_mut()))
2747 .unwrap_or_default();
2748 self.reconcile(elements, context, &mut scratch);
2749 scratch.elements.clear();
2750 scratch.final_slots.clear();
2751 let _ = RECONCILE_SCRATCH.try_with(|slot| *slot.borrow_mut() = scratch);
2752 }
2753
2754 fn reconcile<'a, I>(
2755 &mut self,
2756 elements: I,
2757 context: &mut dyn ModifierNodeContext,
2758 scratch: &mut ReconcileScratch,
2759 ) where
2760 I: Iterator<Item = &'a DynModifierElement>,
2761 {
2762 let old_len = self.entries.len();
2763 let mut fast_path_failed_at: Option<usize> = None;
2764 let mut elements_count = 0;
2765
2766 scratch.elements.clear();
2767
2768 for (idx, element) in elements.enumerate() {
2769 elements_count = idx + 1;
2770 if fast_path_failed_at.is_none() && idx < old_len {
2771 if update_entry_in_place(&mut self.entries[idx], element, context) {
2772 continue;
2773 }
2774 fast_path_failed_at = Some(idx);
2775 }
2776 scratch.elements.push(element.clone());
2777 }
2778
2779 if fast_path_failed_at.is_none() && scratch.elements.is_empty() {
2780 if elements_count < self.entries.len() {
2781 for entry in self.entries.drain(elements_count..) {
2782 request_auto_invalidations(context, entry.capabilities);
2783 detach_node_tree(&mut **entry.node.borrow_mut());
2784 }
2785 }
2786 self.sync_chain_links();
2787 return;
2788 }
2789
2790 self.rebuild_tail(fast_path_failed_at.unwrap_or(old_len), context, scratch);
2791 }
2792
2793 fn rebuild_tail(
2797 &mut self,
2798 fail_idx: usize,
2799 context: &mut dyn ModifierNodeContext,
2800 scratch: &mut ReconcileScratch,
2801 ) {
2802 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
2803 let processed_entries_len = self.entries.len();
2804 let old_len = old_entries.len();
2805
2806 scratch.old_used.clear();
2807 scratch.old_used.resize(old_len, false);
2808
2809 scratch.match_order.clear();
2810 scratch.match_order.resize(old_len, None);
2811
2812 let index = EntryIndex::build(&old_entries);
2813
2814 let new_elements_count = scratch.elements.len();
2815 scratch.final_slots.clear();
2816 scratch.final_slots.reserve(new_elements_count);
2817
2818 for (new_pos, element) in scratch.elements.drain(..).enumerate() {
2819 let fresh = reconcile_element(
2820 element,
2821 new_pos,
2822 (&mut old_entries, &index),
2823 (&mut scratch.old_used, &mut scratch.match_order),
2824 context,
2825 );
2826 scratch.final_slots.push(fresh);
2827 }
2828
2829 for (i, entry) in old_entries.into_iter().enumerate() {
2830 match scratch.match_order[i] {
2831 Some(pos) if scratch.old_used[i] => scratch.final_slots[pos] = Some(entry),
2832 _ => {
2833 request_auto_invalidations(context, entry.capabilities);
2834 detach_node_tree(&mut **entry.node.borrow_mut());
2835 }
2836 }
2837 }
2838
2839 self.entries.reserve(scratch.final_slots.len());
2840 for slot in scratch.final_slots.drain(..) {
2841 if let Some(entry) = slot {
2842 self.entries.push(entry);
2843 } else {
2844 log::error!("modifier reconciliation produced an empty final slot");
2845 }
2846 }
2847
2848 debug_assert_eq!(
2849 self.entries.len(),
2850 processed_entries_len + new_elements_count
2851 );
2852 self.sync_chain_links();
2853 }
2854
2855 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
2859 where
2860 I: IntoIterator<Item = DynModifierElement>,
2861 {
2862 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
2863 self.update_from_slice(&collected, context);
2864 }
2865
2866 pub fn reset(&mut self) {
2869 for entry in &mut self.entries {
2870 reset_node_tree(&mut **entry.node.borrow_mut());
2871 }
2872 }
2873
2874 pub fn detach_all(&mut self) {
2876 for entry in std::mem::take(&mut self.entries) {
2877 detach_node_tree(&mut **entry.node.borrow_mut());
2878 {
2879 let node_borrow = entry.node.borrow();
2880 let state = node_borrow.node_state();
2881 state.set_capabilities(NodeCapabilities::empty());
2882 }
2883 }
2884 self.aggregated_capabilities = NodeCapabilities::empty();
2885 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2886 self.ordered_nodes.clear();
2887 self.sync_chain_links();
2888 }
2889
2890 pub fn len(&self) -> usize {
2891 self.entries.len()
2892 }
2893
2894 pub fn is_empty(&self) -> bool {
2895 self.entries.is_empty()
2896 }
2897
2898 pub fn capabilities(&self) -> NodeCapabilities {
2900 self.aggregated_capabilities
2901 }
2902
2903 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
2905 self.aggregated_capabilities.contains(capability)
2906 }
2907
2908 pub fn head(&self) -> ModifierChainNodeRef<'_> {
2910 self.make_node_ref(NodeLink::Head)
2911 }
2912
2913 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
2915 self.make_node_ref(NodeLink::Tail)
2916 }
2917
2918 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
2920 ModifierChainIter::forward(self)
2921 }
2922
2923 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
2925 ModifierChainIter::backward(self)
2926 }
2927
2928 pub fn for_each_forward<F>(&self, mut f: F)
2930 where
2931 F: FnMut(ModifierChainNodeRef<'_>),
2932 {
2933 for node in self.head_to_tail() {
2934 f(node);
2935 }
2936 }
2937
2938 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
2940 where
2941 F: FnMut(ModifierChainNodeRef<'_>),
2942 {
2943 if mask.is_empty() {
2944 self.for_each_forward(f);
2945 return;
2946 }
2947
2948 if !self.head().aggregate_child_capabilities().intersects(mask) {
2949 return;
2950 }
2951
2952 for node in self.head_to_tail() {
2953 if node.kind_set().intersects(mask) {
2954 f(node);
2955 }
2956 }
2957 }
2958
2959 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
2961 where
2962 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
2963 {
2964 self.for_each_forward_matching(mask, |node_ref| {
2965 node_ref.with_node(|node| f(node_ref.clone(), node));
2966 });
2967 }
2968
2969 pub fn for_each_backward<F>(&self, mut f: F)
2971 where
2972 F: FnMut(ModifierChainNodeRef<'_>),
2973 {
2974 for node in self.tail_to_head() {
2975 f(node);
2976 }
2977 }
2978
2979 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
2981 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
2982 node as *const dyn ModifierNode as *const ()
2983 }
2984
2985 let target = node_data_ptr(node);
2986 for (index, entry) in self.entries.iter().enumerate() {
2987 if node_data_ptr(&**entry.node.borrow()) == target {
2988 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
2989 }
2990 }
2991
2992 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
2993 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
2994 return None;
2995 }
2996 let matches_target = match link {
2997 NodeLink::Head => node_data_ptr(self.head_sentinel.as_ref()) == target,
2998 NodeLink::Tail => node_data_ptr(self.tail_sentinel.as_ref()) == target,
2999 NodeLink::Entry(path) => {
3000 let node_borrow = self.entries[path.entry()].node.borrow();
3001 node_data_ptr(&**node_borrow) == target
3002 }
3003 };
3004 if matches_target {
3005 Some(self.make_node_ref(*link))
3006 } else {
3007 None
3008 }
3009 })
3010 }
3011
3012 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
3015 self.entries.get(index).and_then(|entry| {
3016 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
3017 boxed_node.as_any().downcast_ref::<N>()
3018 })
3019 .ok()
3020 })
3021 }
3022
3023 pub fn node_mut<N: ModifierNode + 'static>(
3026 &self,
3027 index: usize,
3028 ) -> Option<std::cell::RefMut<'_, N>> {
3029 self.entries.get(index).and_then(|entry| {
3030 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
3031 boxed_node.as_any_mut().downcast_mut::<N>()
3032 })
3033 .ok()
3034 })
3035 }
3036
3037 pub fn get_node_rc(&self, index: usize) -> Option<Rc<RefCell<Box<dyn ModifierNode>>>> {
3040 self.entries.get(index).map(|entry| Rc::clone(&entry.node))
3041 }
3042
3043 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
3045 self.aggregated_capabilities
3046 .contains(NodeCapabilities::for_invalidation(kind))
3047 }
3048
3049 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
3051 where
3052 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
3053 {
3054 for index in 0..self.ordered_nodes.len() {
3055 let (link, cached_caps, _agg) = self.ordered_nodes[index];
3056 match link {
3057 NodeLink::Head => {
3058 f(self.head_sentinel.as_mut(), cached_caps);
3059 }
3060 NodeLink::Tail => {
3061 f(self.tail_sentinel.as_mut(), cached_caps);
3062 }
3063 NodeLink::Entry(path) => {
3064 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
3065 if path.delegates().is_empty() {
3066 f(&mut **node_borrow, cached_caps);
3067 } else {
3068 let mut current: &mut dyn ModifierNode = &mut **node_borrow;
3069 for &delegate_index in path.delegates() {
3070 if let Some(delegate) =
3071 nth_delegate_mut(current, delegate_index as usize)
3072 {
3073 current = delegate;
3074 } else {
3075 return;
3076 }
3077 }
3078 f(current, cached_caps);
3079 }
3080 }
3081 }
3082 }
3083 }
3084
3085 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
3086 ModifierChainNodeRef {
3087 chain: self,
3088 link,
3089 cached_capabilities: None,
3090 cached_aggregate_child: None,
3091 }
3092 }
3093
3094 fn make_node_ref_with_caps(
3095 &self,
3096 link: NodeLink,
3097 caps: NodeCapabilities,
3098 aggregate_child: NodeCapabilities,
3099 ) -> ModifierChainNodeRef<'_> {
3100 ModifierChainNodeRef {
3101 chain: self,
3102 link,
3103 cached_capabilities: Some(caps),
3104 cached_aggregate_child: Some(aggregate_child),
3105 }
3106 }
3107
3108 fn sync_chain_links(&mut self) {
3109 self.rebuild_ordered_nodes();
3110
3111 self.head_sentinel.node_state().set_parent_link(None);
3112 self.tail_sentinel.node_state().set_child_link(None);
3113
3114 if self.ordered_nodes.is_empty() {
3115 self.head_sentinel
3116 .node_state()
3117 .set_child_link(Some(NodeLink::Tail));
3118 self.tail_sentinel
3119 .node_state()
3120 .set_parent_link(Some(NodeLink::Head));
3121 self.aggregated_capabilities = NodeCapabilities::empty();
3122 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
3123 self.head_sentinel
3124 .node_state()
3125 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3126 self.tail_sentinel
3127 .node_state()
3128 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3129 return;
3130 }
3131
3132 let mut previous = NodeLink::Head;
3133 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
3134 match &previous {
3135 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
3136 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
3137 NodeLink::Entry(path) => {
3138 let node_borrow = self.entries[path.entry()].node.borrow();
3139 if path.delegates().is_empty() {
3140 node_borrow.node_state().set_child_link(Some(link));
3141 } else {
3142 let mut current: &dyn ModifierNode = &**node_borrow;
3143 for &delegate_index in path.delegates() {
3144 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3145 current = delegate;
3146 }
3147 }
3148 current.node_state().set_child_link(Some(link));
3149 }
3150 }
3151 }
3152 match &link {
3153 NodeLink::Head => self
3154 .head_sentinel
3155 .node_state()
3156 .set_parent_link(Some(previous)),
3157 NodeLink::Tail => self
3158 .tail_sentinel
3159 .node_state()
3160 .set_parent_link(Some(previous)),
3161 NodeLink::Entry(path) => {
3162 let node_borrow = self.entries[path.entry()].node.borrow();
3163 if path.delegates().is_empty() {
3164 node_borrow.node_state().set_parent_link(Some(previous));
3165 } else {
3166 let mut current: &dyn ModifierNode = &**node_borrow;
3167 for &delegate_index in path.delegates() {
3168 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3169 current = delegate;
3170 }
3171 }
3172 current.node_state().set_parent_link(Some(previous));
3173 }
3174 }
3175 }
3176 previous = link;
3177 }
3178
3179 match &previous {
3180 NodeLink::Head => self
3181 .head_sentinel
3182 .node_state()
3183 .set_child_link(Some(NodeLink::Tail)),
3184 NodeLink::Tail => self
3185 .tail_sentinel
3186 .node_state()
3187 .set_child_link(Some(NodeLink::Tail)),
3188 NodeLink::Entry(path) => {
3189 let node_borrow = self.entries[path.entry()].node.borrow();
3190 if path.delegates().is_empty() {
3191 node_borrow
3192 .node_state()
3193 .set_child_link(Some(NodeLink::Tail));
3194 } else {
3195 let mut current: &dyn ModifierNode = &**node_borrow;
3196 for &delegate_index in path.delegates() {
3197 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3198 current = delegate;
3199 }
3200 }
3201 current.node_state().set_child_link(Some(NodeLink::Tail));
3202 }
3203 }
3204 }
3205 self.tail_sentinel
3206 .node_state()
3207 .set_parent_link(Some(previous));
3208 self.tail_sentinel.node_state().set_child_link(None);
3209
3210 let mut aggregate = NodeCapabilities::empty();
3211 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
3212 aggregate |= *cached_caps;
3213 *cached_aggregate = aggregate;
3214 match link {
3215 NodeLink::Head => {
3216 self.head_sentinel
3217 .node_state()
3218 .set_aggregate_child_capabilities(aggregate);
3219 }
3220 NodeLink::Tail => {
3221 self.tail_sentinel
3222 .node_state()
3223 .set_aggregate_child_capabilities(aggregate);
3224 }
3225 NodeLink::Entry(path) => {
3226 let node_borrow = self.entries[path.entry()].node.borrow();
3227 let state = if path.delegates().is_empty() {
3228 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 }
3235 }
3236 current.node_state()
3237 };
3238 state.set_aggregate_child_capabilities(aggregate);
3239 }
3240 }
3241 }
3242
3243 self.aggregated_capabilities = aggregate;
3244 self.head_aggregate_child_capabilities = aggregate;
3245 self.head_sentinel
3246 .node_state()
3247 .set_aggregate_child_capabilities(aggregate);
3248 self.tail_sentinel
3249 .node_state()
3250 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3251 }
3252
3253 fn rebuild_ordered_nodes(&mut self) {
3254 self.ordered_nodes.clear();
3255 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
3256 for (index, entry) in self.entries.iter().enumerate() {
3257 let node_borrow = entry.node.borrow();
3258 Self::enumerate_link_order(
3259 &**node_borrow,
3260 index,
3261 &mut path_buf,
3262 0,
3263 &mut self.ordered_nodes,
3264 );
3265 }
3266 }
3267
3268 fn enumerate_link_order(
3269 node: &dyn ModifierNode,
3270 entry: usize,
3271 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
3272 path_len: usize,
3273 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
3274 ) {
3275 let caps = node.node_state().capabilities();
3276 out.push((
3277 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
3278 caps,
3279 NodeCapabilities::empty(),
3280 ));
3281 let mut delegate_index = 0usize;
3282 node.for_each_delegate(&mut |child| {
3283 if path_len < MAX_DELEGATE_DEPTH {
3284 path_buf[path_len] = delegate_index;
3285 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
3286 }
3287 delegate_index += 1;
3288 });
3289 }
3290}
3291
3292impl<'a> ModifierChainNodeRef<'a> {
3293 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
3294 match &self.link {
3295 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
3296 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
3297 NodeLink::Entry(path) => {
3298 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3299 if path.delegates().is_empty() {
3300 f(node_borrow.node_state())
3301 } else {
3302 let mut current: &dyn ModifierNode = &**node_borrow;
3303 for &delegate_index in path.delegates() {
3304 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3305 current = delegate;
3306 } else {
3307 return f(node_borrow.node_state());
3308 }
3309 }
3310 f(current.node_state())
3311 }
3312 }
3313 }
3314 }
3315
3316 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
3319 match &self.link {
3320 NodeLink::Head => None,
3321 NodeLink::Tail => None,
3322 NodeLink::Entry(path) => {
3323 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3324 if path.delegates().is_empty() {
3325 Some(f(&**node_borrow))
3326 } else {
3327 let mut current: &dyn ModifierNode = &**node_borrow;
3328 for &delegate_index in path.delegates() {
3329 current = nth_delegate(current, delegate_index as usize)?;
3330 }
3331 Some(f(current))
3332 }
3333 }
3334 }
3335 }
3336
3337 #[inline]
3339 pub fn parent(&self) -> Option<Self> {
3340 self.with_state(NodeState::parent_link)
3341 .map(|link| self.chain.make_node_ref(link))
3342 }
3343
3344 #[inline]
3346 pub fn child(&self) -> Option<Self> {
3347 self.with_state(NodeState::child_link)
3348 .map(|link| self.chain.make_node_ref(link))
3349 }
3350
3351 #[inline]
3353 pub fn kind_set(&self) -> NodeCapabilities {
3354 if let Some(caps) = self.cached_capabilities {
3355 return caps;
3356 }
3357 match &self.link {
3358 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
3359 NodeLink::Entry(_) => self.with_state(NodeState::capabilities),
3360 }
3361 }
3362
3363 pub fn entry_index(&self) -> Option<usize> {
3365 match &self.link {
3366 NodeLink::Entry(path) => Some(path.entry()),
3367 _ => None,
3368 }
3369 }
3370
3371 pub fn delegate_depth(&self) -> usize {
3373 match &self.link {
3374 NodeLink::Entry(path) => path.delegates().len(),
3375 _ => 0,
3376 }
3377 }
3378
3379 #[inline]
3381 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
3382 if let Some(agg) = self.cached_aggregate_child {
3383 return agg;
3384 }
3385 if self.is_tail() {
3386 NodeCapabilities::empty()
3387 } else {
3388 self.with_state(NodeState::aggregate_child_capabilities)
3389 }
3390 }
3391
3392 pub fn is_head(&self) -> bool {
3394 matches!(self.link, NodeLink::Head)
3395 }
3396
3397 pub fn is_tail(&self) -> bool {
3399 matches!(self.link, NodeLink::Tail)
3400 }
3401
3402 pub fn is_sentinel(&self) -> bool {
3404 matches!(self.link, NodeLink::Head | NodeLink::Tail)
3405 }
3406
3407 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
3409 !mask.is_empty() && self.kind_set().intersects(mask)
3410 }
3411
3412 pub fn visit_descendants<F>(self, include_self: bool, mut f: F)
3414 where
3415 F: FnMut(ModifierChainNodeRef<'a>),
3416 {
3417 let mut current = if include_self {
3418 Some(self)
3419 } else {
3420 self.child()
3421 };
3422 while let Some(node) = current {
3423 if node.is_tail() {
3424 break;
3425 }
3426 if !node.is_sentinel() {
3427 f(node.clone());
3428 }
3429 current = node.child();
3430 }
3431 }
3432
3433 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3435 where
3436 F: FnMut(ModifierChainNodeRef<'a>),
3437 {
3438 if mask.is_empty() {
3439 self.visit_descendants(include_self, f);
3440 return;
3441 }
3442
3443 if !self.aggregate_child_capabilities().intersects(mask) {
3444 return;
3445 }
3446
3447 self.visit_descendants(include_self, |node| {
3448 if node.kind_set().intersects(mask) {
3449 f(node);
3450 }
3451 });
3452 }
3453
3454 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
3456 where
3457 F: FnMut(ModifierChainNodeRef<'a>),
3458 {
3459 let mut current = if include_self {
3460 Some(self)
3461 } else {
3462 self.parent()
3463 };
3464 while let Some(node) = current {
3465 if node.is_head() {
3466 break;
3467 }
3468 f(node.clone());
3469 current = node.parent();
3470 }
3471 }
3472
3473 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3475 where
3476 F: FnMut(ModifierChainNodeRef<'a>),
3477 {
3478 if mask.is_empty() {
3479 self.visit_ancestors(include_self, f);
3480 return;
3481 }
3482
3483 self.visit_ancestors(include_self, |node| {
3484 if node.kind_set().intersects(mask) {
3485 f(node);
3486 }
3487 });
3488 }
3489}
3490
3491#[cfg(test)]
3492#[path = "tests/modifier_tests.rs"]
3493mod tests;