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,
29 Draw,
31 PointerInput,
33 Semantics,
35 Focus,
37}
38
39pub trait ModifierNodeContext {
41 fn invalidate(&mut self, _kind: InvalidationKind) {}
43
44 fn request_update(&mut self) {}
47
48 fn node_id(&self) -> Option<cranpose_core::NodeId> {
51 None
52 }
53
54 fn push_active_capabilities(&mut self, _capabilities: NodeCapabilities) {}
56
57 fn pop_active_capabilities(&mut self) {}
59
60 fn density(&self) -> f32 {
65 1.0
66 }
67}
68
69#[derive(Default, Debug, Clone)]
78pub struct BasicModifierNodeContext {
79 invalidations: ModifierInvalidations,
80 update_requested: bool,
81 active_capabilities: smallvec::SmallVec<[NodeCapabilities; 4]>,
84 node_id: Option<cranpose_core::NodeId>,
85}
86
87impl BasicModifierNodeContext {
88 pub fn new() -> Self {
90 Self::default()
91 }
92
93 pub fn for_node(
96 node_id: Option<cranpose_core::NodeId>,
97 invalidations: ModifierInvalidations,
98 ) -> Self {
99 Self {
100 invalidations,
101 node_id,
102 ..Self::default()
103 }
104 }
105
106 pub fn invalidations(&self) -> &[ModifierInvalidation] {
110 &self.invalidations
111 }
112
113 pub fn clear_invalidations(&mut self) {
115 self.invalidations.clear();
116 }
117
118 pub fn take_invalidations(&mut self) -> ModifierInvalidations {
120 std::mem::take(&mut self.invalidations)
121 }
122
123 pub fn update_requested(&self) -> bool {
126 self.update_requested
127 }
128
129 pub fn take_update_requested(&mut self) -> bool {
131 std::mem::take(&mut self.update_requested)
132 }
133
134 pub fn set_node_id(&mut self, id: Option<cranpose_core::NodeId>) {
136 self.node_id = id;
137 }
138
139 fn push_invalidation(&mut self, kind: InvalidationKind) {
140 let mut capabilities = self.current_capabilities();
141 capabilities.insert(NodeCapabilities::for_invalidation(kind));
142 if let Some(existing) = self
143 .invalidations
144 .iter_mut()
145 .find(|entry| entry.kind() == kind)
146 {
147 let updated = existing.capabilities() | capabilities;
148 *existing = ModifierInvalidation::new(kind, updated);
149 } else {
150 self.invalidations
151 .push(ModifierInvalidation::new(kind, capabilities));
152 }
153 }
154
155 fn current_capabilities(&self) -> NodeCapabilities {
156 self.active_capabilities
157 .last()
158 .copied()
159 .unwrap_or_else(NodeCapabilities::empty)
160 }
161}
162
163impl ModifierNodeContext for BasicModifierNodeContext {
164 fn invalidate(&mut self, kind: InvalidationKind) {
165 self.push_invalidation(kind);
166 }
167
168 fn request_update(&mut self) {
169 self.update_requested = true;
170 }
171
172 fn push_active_capabilities(&mut self, capabilities: NodeCapabilities) {
173 self.active_capabilities.push(capabilities);
174 }
175
176 fn pop_active_capabilities(&mut self) {
177 self.active_capabilities.pop();
178 }
179
180 fn node_id(&self) -> Option<cranpose_core::NodeId> {
181 self.node_id
182 }
183}
184
185const MAX_DELEGATE_DEPTH: usize = 3;
186
187#[derive(Copy, Clone, Debug, PartialEq, Eq)]
188pub(crate) struct NodePath {
189 entry: u32,
192 delegate_buf: [u8; MAX_DELEGATE_DEPTH],
193 delegate_len: u8,
194}
195
196impl NodePath {
197 #[inline]
198 fn root(entry: usize) -> Self {
199 debug_assert!(entry <= u32::MAX as usize, "chain entry exceeds u32 range");
200 Self {
201 entry: entry as u32,
202 delegate_buf: [0; MAX_DELEGATE_DEPTH],
203 delegate_len: 0,
204 }
205 }
206
207 #[inline]
208 fn from_slice(entry: usize, path: &[usize]) -> Self {
209 debug_assert!(
210 path.len() <= MAX_DELEGATE_DEPTH,
211 "delegate depth {} exceeds MAX_DELEGATE_DEPTH {}",
212 path.len(),
213 MAX_DELEGATE_DEPTH
214 );
215 debug_assert!(
216 path.iter().all(|&i| i <= u8::MAX as usize),
217 "delegate index exceeds u8 range"
218 );
219 let mut delegate_buf = [0u8; MAX_DELEGATE_DEPTH];
220 for (i, &v) in path.iter().enumerate().take(MAX_DELEGATE_DEPTH) {
221 delegate_buf[i] = v as u8;
222 }
223 Self {
224 delegate_buf,
225 delegate_len: path.len().min(MAX_DELEGATE_DEPTH) as u8,
226 ..Self::root(entry)
227 }
228 }
229
230 #[inline]
231 fn entry(&self) -> usize {
232 self.entry as usize
233 }
234
235 #[inline]
236 fn delegates(&self) -> &[u8] {
237 &self.delegate_buf[..self.delegate_len as usize]
238 }
239}
240
241#[derive(Copy, Clone, Debug, PartialEq, Eq)]
242pub(crate) enum NodeLink {
243 Head,
244 Tail,
245 Entry(NodePath),
246}
247
248#[derive(Debug)]
254pub struct NodeState {
255 aggregate_child_capabilities: Cell<NodeCapabilities>,
256 capabilities: Cell<NodeCapabilities>,
257 parent: Cell<Option<NodeLink>>,
258 child: Cell<Option<NodeLink>>,
259 attached: Cell<bool>,
260 is_sentinel: bool,
261}
262
263impl Default for NodeState {
264 fn default() -> Self {
265 Self::new()
266 }
267}
268
269impl NodeState {
270 pub const fn new() -> Self {
272 Self {
273 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
274 capabilities: Cell::new(NodeCapabilities::empty()),
275 parent: Cell::new(None),
276 child: Cell::new(None),
277 attached: Cell::new(false),
278 is_sentinel: false,
279 }
280 }
281
282 pub const fn sentinel() -> Self {
285 Self {
286 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
287 capabilities: Cell::new(NodeCapabilities::empty()),
288 parent: Cell::new(None),
289 child: Cell::new(None),
290 attached: Cell::new(true),
291 is_sentinel: true,
292 }
293 }
294
295 pub fn set_capabilities(&self, capabilities: NodeCapabilities) {
298 self.capabilities.set(capabilities);
299 }
300
301 #[inline]
303 pub fn capabilities(&self) -> NodeCapabilities {
304 self.capabilities.get()
305 }
306
307 pub fn set_aggregate_child_capabilities(&self, capabilities: NodeCapabilities) {
310 self.aggregate_child_capabilities.set(capabilities);
311 }
312
313 #[inline]
316 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
317 self.aggregate_child_capabilities.get()
318 }
319
320 pub(crate) fn set_parent_link(&self, parent: Option<NodeLink>) {
321 self.parent.set(parent);
322 }
323
324 #[inline]
325 pub(crate) fn parent_link(&self) -> Option<NodeLink> {
326 self.parent.get()
327 }
328
329 pub(crate) fn set_child_link(&self, child: Option<NodeLink>) {
330 self.child.set(child);
331 }
332
333 #[inline]
334 pub(crate) fn child_link(&self) -> Option<NodeLink> {
335 self.child.get()
336 }
337
338 pub fn set_attached(&self, attached: bool) {
340 self.attached.set(attached);
341 }
342
343 pub fn is_attached(&self) -> bool {
346 self.attached.get()
347 }
348
349 pub fn is_sentinel(&self) -> bool {
352 self.is_sentinel
353 }
354}
355
356pub trait DelegatableNode {
358 fn node_state(&self) -> &NodeState;
361 fn aggregate_child_capabilities(&self) -> NodeCapabilities {
363 self.node_state().aggregate_child_capabilities()
364 }
365}
366
367pub trait ModifierNode: Any + DelegatableNode {
425 fn on_attach(&mut self, _context: &mut dyn ModifierNodeContext) {}
428
429 fn on_detach(&mut self) {}
432
433 fn on_reset(&mut self) {}
436
437 fn as_draw_node(&self) -> Option<&dyn DrawModifierNode> {
439 None
440 }
441
442 fn as_draw_node_mut(&mut self) -> Option<&mut dyn DrawModifierNode> {
444 None
445 }
446
447 fn as_pointer_input_node(&self) -> Option<&dyn PointerInputNode> {
449 None
450 }
451
452 fn as_pointer_input_node_mut(&mut self) -> Option<&mut dyn PointerInputNode> {
454 None
455 }
456
457 fn as_semantics_node(&self) -> Option<&dyn SemanticsNode> {
459 None
460 }
461
462 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn SemanticsNode> {
464 None
465 }
466
467 fn as_focus_node(&self) -> Option<&dyn FocusNode> {
469 None
470 }
471
472 fn as_focus_node_mut(&mut self) -> Option<&mut dyn FocusNode> {
474 None
475 }
476
477 fn as_layout_node(&self) -> Option<&dyn LayoutModifierNode> {
479 None
480 }
481
482 fn as_layout_node_mut(&mut self) -> Option<&mut dyn LayoutModifierNode> {
484 None
485 }
486
487 fn for_each_delegate<'b>(&'b self, _visitor: &mut dyn FnMut(&'b dyn ModifierNode)) {}
489
490 fn for_each_delegate_mut<'b>(&'b mut self, _visitor: &mut dyn FnMut(&'b mut dyn ModifierNode)) {
492 }
493}
494
495pub trait LayoutModifierNode: ModifierNode {
501 fn measure(
523 &self,
524 _context: &mut dyn ModifierNodeContext,
525 measurable: &dyn Measurable,
526 constraints: Constraints,
527 ) -> cranpose_ui_layout::LayoutModifierMeasureResult {
528 let placeable = measurable.measure(constraints);
529 cranpose_ui_layout::LayoutModifierMeasureResult::with_size(Size {
530 width: placeable.width(),
531 height: placeable.height(),
532 })
533 }
534
535 fn measure_hold(
542 &self,
543 _density: f32,
544 _constraints: Constraints,
545 _size: Size,
546 _wrapped: cranpose_ui_layout::WrappedHold,
547 ) -> Option<cranpose_ui_layout::ConstraintsHold> {
548 None
549 }
550
551 fn min_intrinsic_width(&self, measurable: &dyn Measurable, height: f32, _density: f32) -> f32 {
554 measurable.min_intrinsic_width(height)
555 }
556
557 fn max_intrinsic_width(&self, measurable: &dyn Measurable, height: f32, _density: f32) -> f32 {
560 measurable.max_intrinsic_width(height)
561 }
562
563 fn min_intrinsic_height(&self, measurable: &dyn Measurable, width: f32, _density: f32) -> f32 {
566 measurable.min_intrinsic_height(width)
567 }
568
569 fn max_intrinsic_height(&self, measurable: &dyn Measurable, width: f32, _density: f32) -> f32 {
572 measurable.max_intrinsic_height(width)
573 }
574}
575
576pub trait DrawModifierNode: ModifierNode {
583 fn create_draw_closure(&self) -> Option<NodeDrawClosure> {
594 None
595 }
596
597 fn create_behind_draw_closure(&self) -> Option<NodeDrawClosure> {
602 None
603 }
604}
605
606pub type NodeDrawClosure = Rc<dyn Fn(&mut cranpose_ui_graphics::DrawScopeDefault)>;
611
612pub trait PointerInputNode: ModifierNode {
618 fn on_pointer_event(
621 &mut self,
622 _context: &mut dyn ModifierNodeContext,
623 _event: &PointerEvent,
624 ) -> bool {
625 false
626 }
627
628 fn hit_test(&self, _x: f32, _y: f32) -> bool {
631 true
632 }
633
634 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
636 None
637 }
638
639 fn layout_size_sink(&self) -> Option<Rc<Cell<Size>>> {
652 None
653 }
654}
655
656pub trait SemanticsNode: ModifierNode {
662 fn merge_semantics(&self, _config: &mut SemanticsConfiguration) {}
664
665 fn reach(&self) -> SemanticsReach {
672 SemanticsReach::merged_by(self, true)
673 }
674}
675
676#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
681pub struct SemanticsReach {
682 pub is_modal: bool,
684 pub hidden: bool,
686 pub merges_live_state: bool,
690}
691
692impl SemanticsReach {
693 pub fn merged_by(node: &(impl SemanticsNode + ?Sized), merges_live_state: bool) -> Self {
696 let mut config = SemanticsConfiguration::default();
697 node.merge_semantics(&mut config);
698 Self {
699 is_modal: config.is_modal,
700 hidden: config.hidden,
701 merges_live_state,
702 }
703 }
704
705 pub fn union(self, other: Self) -> Self {
707 Self {
708 is_modal: self.is_modal || other.is_modal,
709 hidden: self.hidden || other.hidden,
710 merges_live_state: self.merges_live_state || other.merges_live_state,
711 }
712 }
713}
714
715#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
719pub enum ToggleableState {
720 On,
722 Off,
724 Indeterminate,
726}
727
728impl From<bool> for ToggleableState {
729 fn from(on: bool) -> Self {
730 if on { Self::On } else { Self::Off }
731 }
732}
733
734#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
739pub enum FocusState {
740 Active,
742 ActiveParent,
744 Captured,
748 #[default]
751 Inactive,
752}
753
754impl FocusState {
755 pub fn is_focused(self) -> bool {
757 matches!(self, FocusState::Active | FocusState::Captured)
758 }
759
760 pub fn has_focus(self) -> bool {
762 matches!(
763 self,
764 FocusState::Active | FocusState::ActiveParent | FocusState::Captured
765 )
766 }
767
768 pub fn is_captured(self) -> bool {
770 matches!(self, FocusState::Captured)
771 }
772}
773
774pub trait FocusNode: ModifierNode {
779 fn focus_state(&self) -> FocusState;
781
782 fn on_focus_changed(&mut self, _context: &mut dyn ModifierNodeContext, _state: FocusState) {}
784}
785
786#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
797pub enum SemanticsWidgetRole {
798 Button,
800 Checkbox,
802 Switch,
804 RadioButton,
806 Tab,
808 Image,
810 DropdownList,
813 ValuePicker,
816 Header,
821 Dialog,
825 Link,
828 SearchField,
831 ProgressBar,
834 ToggleButton,
837 Alert,
840 Toolbar,
843 Menu,
845 MenuItem,
847 TabBar,
850 List,
852 ListItem,
854 RadioGroup,
856}
857
858#[derive(Clone, Copy, Debug, PartialEq)]
866pub struct ProgressBarRangeInfo {
867 pub current: f32,
869 pub start: f32,
871 pub end: f32,
873 pub steps: u32,
876}
877
878impl ProgressBarRangeInfo {
879 pub fn new(current: f32, start: f32, end: f32, steps: u32) -> Self {
882 Self {
883 current,
884 start,
885 end,
886 steps,
887 }
888 }
889
890 pub fn fraction(&self) -> f32 {
892 let span = self.end - self.start;
893 if span.abs() < f32::EPSILON {
894 return 0.0;
895 }
896 ((self.current - self.start) / span).clamp(0.0, 1.0)
897 }
898
899 pub fn step(&self) -> f32 {
902 let span = self.end - self.start;
903 if self.steps == 0 {
904 span / 10.0
905 } else {
906 span / (self.steps as f32 + 1.0)
907 }
908 }
909}
910
911#[derive(Clone, Copy, Debug, PartialEq, Eq)]
914pub struct CollectionInfo {
915 pub rows: usize,
917 pub columns: usize,
919}
920
921#[derive(Clone, Copy, Debug, PartialEq)]
934pub struct ScrollAxisRange {
935 pub value: f32,
938 pub max_value: f32,
940 pub reverse: bool,
943 pub content_padding_start: f32,
945 pub content_padding_end: f32,
947}
948
949impl ScrollAxisRange {
950 pub fn new(value: f32, max_value: f32, reverse: bool) -> Self {
953 Self {
954 value,
955 max_value,
956 reverse,
957 content_padding_start: 0.0,
958 content_padding_end: 0.0,
959 }
960 }
961
962 pub fn with_content_padding(self, start: f32, end: f32) -> Self {
965 Self {
966 content_padding_start: start,
967 content_padding_end: end,
968 ..self
969 }
970 }
971
972 pub fn can_scroll_forward(&self) -> bool {
974 self.value < self.max_value
975 }
976
977 pub fn can_scroll_backward(&self) -> bool {
979 self.value > 0.0
980 }
981}
982
983#[derive(Clone)]
989pub struct SemanticsScrollBy {
990 handler: Rc<dyn Fn(f32, f32) -> bool>,
991}
992
993impl SemanticsScrollBy {
994 pub fn new(handler: impl Fn(f32, f32) -> bool + 'static) -> Self {
997 Self {
998 handler: Rc::new(handler),
999 }
1000 }
1001
1002 pub fn invoke(&self, dx: f32, dy: f32) -> bool {
1005 (self.handler)(dx, dy)
1006 }
1007}
1008
1009impl fmt::Debug for SemanticsScrollBy {
1010 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1011 f.debug_struct("SemanticsScrollBy").finish_non_exhaustive()
1012 }
1013}
1014
1015impl PartialEq for SemanticsScrollBy {
1016 fn eq(&self, _other: &Self) -> bool {
1017 true
1018 }
1019}
1020
1021impl Eq for SemanticsScrollBy {}
1022
1023#[derive(Clone)]
1029pub struct SemanticsScrollToIndex {
1030 handler: Rc<dyn Fn(usize) -> bool>,
1031}
1032
1033impl SemanticsScrollToIndex {
1034 pub fn new(handler: impl Fn(usize) -> bool + 'static) -> Self {
1037 Self {
1038 handler: Rc::new(handler),
1039 }
1040 }
1041
1042 pub fn invoke(&self, index: usize) -> bool {
1044 (self.handler)(index)
1045 }
1046}
1047
1048impl fmt::Debug for SemanticsScrollToIndex {
1049 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1050 f.debug_struct("SemanticsScrollToIndex")
1051 .finish_non_exhaustive()
1052 }
1053}
1054
1055impl PartialEq for SemanticsScrollToIndex {
1056 fn eq(&self, _other: &Self) -> bool {
1057 true
1058 }
1059}
1060
1061impl Eq for SemanticsScrollToIndex {}
1062
1063#[derive(Clone)]
1069pub struct SemanticsSetProgress {
1070 handler: Rc<dyn Fn(f32) -> bool>,
1071}
1072
1073impl SemanticsSetProgress {
1074 pub fn new(handler: impl Fn(f32) -> bool + 'static) -> Self {
1077 Self {
1078 handler: Rc::new(handler),
1079 }
1080 }
1081
1082 pub fn invoke(&self, value: f32) -> bool {
1085 (self.handler)(value)
1086 }
1087}
1088
1089impl fmt::Debug for SemanticsSetProgress {
1090 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1091 f.debug_struct("SemanticsSetProgress")
1092 .finish_non_exhaustive()
1093 }
1094}
1095
1096#[derive(Clone)]
1100pub struct SemanticsSetText(Rc<dyn Fn(&str) -> bool>);
1101
1102impl SemanticsSetText {
1103 pub fn new(handler: impl Fn(&str) -> bool + 'static) -> Self {
1105 Self(Rc::new(handler))
1106 }
1107
1108 pub fn invoke(&self, text: &str) -> bool {
1110 (self.0)(text)
1111 }
1112}
1113
1114impl fmt::Debug for SemanticsSetText {
1115 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1116 f.write_str("SemanticsSetText")
1117 }
1118}
1119
1120#[derive(Clone)]
1126pub struct SemanticsSetSelection(Rc<dyn Fn(usize, usize) -> bool>);
1127
1128impl SemanticsSetSelection {
1129 pub fn new(handler: impl Fn(usize, usize) -> bool + 'static) -> Self {
1132 Self(Rc::new(handler))
1133 }
1134
1135 pub fn invoke(&self, anchor: usize, focus: usize) -> bool {
1138 (self.0)(anchor, focus)
1139 }
1140}
1141
1142impl fmt::Debug for SemanticsSetSelection {
1143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1144 f.write_str("SemanticsSetSelection")
1145 }
1146}
1147
1148#[derive(Clone)]
1151pub struct SemanticsExpand(Rc<dyn Fn() -> bool>);
1152
1153impl SemanticsExpand {
1154 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1156 Self(Rc::new(handler))
1157 }
1158
1159 pub fn invoke(&self) -> bool {
1161 (self.0)()
1162 }
1163}
1164
1165impl fmt::Debug for SemanticsExpand {
1166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1167 f.write_str("SemanticsExpand")
1168 }
1169}
1170
1171#[derive(Clone)]
1175pub struct SemanticsLongClick(Rc<dyn Fn() -> bool>);
1176
1177impl SemanticsLongClick {
1178 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1180 Self(Rc::new(handler))
1181 }
1182
1183 pub fn invoke(&self) -> bool {
1185 (self.0)()
1186 }
1187}
1188
1189impl fmt::Debug for SemanticsLongClick {
1190 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1191 f.write_str("SemanticsLongClick")
1192 }
1193}
1194
1195impl PartialEq for SemanticsLongClick {
1196 fn eq(&self, _other: &Self) -> bool {
1197 true
1198 }
1199}
1200
1201impl PartialEq for SemanticsExpand {
1202 fn eq(&self, _other: &Self) -> bool {
1203 true
1204 }
1205}
1206
1207#[derive(Clone)]
1211pub struct SemanticsDismiss(Rc<dyn Fn() -> bool>);
1212
1213impl SemanticsDismiss {
1214 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1216 Self(Rc::new(handler))
1217 }
1218
1219 pub fn invoke(&self) -> bool {
1221 (self.0)()
1222 }
1223}
1224
1225impl fmt::Debug for SemanticsDismiss {
1226 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1227 f.write_str("SemanticsDismiss")
1228 }
1229}
1230
1231impl PartialEq for SemanticsDismiss {
1232 fn eq(&self, _other: &Self) -> bool {
1233 true
1234 }
1235}
1236
1237impl PartialEq for SemanticsSetText {
1238 fn eq(&self, _other: &Self) -> bool {
1239 true
1240 }
1241}
1242
1243impl PartialEq for SemanticsSetSelection {
1244 fn eq(&self, _other: &Self) -> bool {
1245 true
1246 }
1247}
1248
1249#[derive(Clone)]
1255pub struct SemanticsMagicTap(Rc<dyn Fn() -> bool>);
1256
1257impl SemanticsMagicTap {
1258 pub fn new(handler: impl Fn() -> bool + 'static) -> Self {
1260 Self(Rc::new(handler))
1261 }
1262
1263 pub fn invoke(&self) -> bool {
1265 (self.0)()
1266 }
1267}
1268
1269impl fmt::Debug for SemanticsMagicTap {
1270 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1271 f.write_str("SemanticsMagicTap")
1272 }
1273}
1274
1275impl PartialEq for SemanticsMagicTap {
1276 fn eq(&self, _other: &Self) -> bool {
1277 true
1278 }
1279}
1280
1281impl PartialEq for SemanticsSetProgress {
1282 fn eq(&self, _other: &Self) -> bool {
1283 true
1284 }
1285}
1286
1287impl Eq for SemanticsSetProgress {}
1288
1289#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1296pub enum LiveRegionMode {
1297 Polite,
1299 Assertive,
1302}
1303
1304#[derive(Clone)]
1311pub struct SemanticsCustomAction {
1312 pub label: String,
1314 handler: Rc<dyn Fn()>,
1315}
1316
1317impl SemanticsCustomAction {
1318 pub fn new(label: impl Into<String>, handler: impl Fn() + 'static) -> Self {
1320 Self {
1321 label: label.into(),
1322 handler: Rc::new(handler),
1323 }
1324 }
1325
1326 pub fn invoke(&self) {
1328 (self.handler)();
1329 }
1330}
1331
1332impl fmt::Debug for SemanticsCustomAction {
1333 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1334 f.debug_struct("SemanticsCustomAction")
1335 .field("label", &self.label)
1336 .finish_non_exhaustive()
1337 }
1338}
1339
1340impl PartialEq for SemanticsCustomAction {
1341 fn eq(&self, other: &Self) -> bool {
1342 self.label == other.label
1343 }
1344}
1345
1346impl Eq for SemanticsCustomAction {}
1347
1348#[derive(Clone, Debug, PartialEq)]
1363pub struct CanvasSemanticsNode {
1364 pub key: u64,
1371 pub bounds: cranpose_ui_graphics::Rect,
1373 pub label: String,
1375 pub role: Option<SemanticsWidgetRole>,
1377 pub state_description: Option<String>,
1381 pub on_click_label: Option<String>,
1384 pub clickable: bool,
1386 pub selected: Option<bool>,
1388 pub toggled: Option<ToggleableState>,
1390 pub enabled: bool,
1392 pub custom_actions: Vec<SemanticsCustomAction>,
1394}
1395
1396impl Default for CanvasSemanticsNode {
1397 fn default() -> Self {
1398 Self {
1399 key: 0,
1400 bounds: cranpose_ui_graphics::Rect {
1401 x: 0.0,
1402 y: 0.0,
1403 width: 0.0,
1404 height: 0.0,
1405 },
1406 label: String::new(),
1407 role: None,
1408 state_description: None,
1409 on_click_label: None,
1410 clickable: false,
1411 selected: None,
1412 toggled: None,
1413 enabled: true,
1414 custom_actions: Vec::new(),
1415 }
1416 }
1417}
1418
1419impl CanvasSemanticsNode {
1420 pub fn control(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1422 Self {
1423 key,
1424 bounds,
1425 label: label.into(),
1426 clickable: true,
1427 ..Self::default()
1428 }
1429 }
1430
1431 pub fn text(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1433 Self {
1434 key,
1435 bounds,
1436 label: label.into(),
1437 ..Self::default()
1438 }
1439 }
1440
1441 pub fn with_role(mut self, role: SemanticsWidgetRole) -> Self {
1443 self.role = Some(role);
1444 self
1445 }
1446
1447 pub fn with_state_description(mut self, state: impl Into<String>) -> Self {
1449 self.state_description = Some(state.into());
1450 self
1451 }
1452
1453 pub fn with_click_label(mut self, label: impl Into<String>) -> Self {
1456 self.on_click_label = Some(label.into());
1457 self.clickable = true;
1458 self
1459 }
1460
1461 pub fn with_selected(mut self, selected: bool) -> Self {
1463 self.selected = Some(selected);
1464 self
1465 }
1466
1467 pub fn with_toggled(mut self, toggled: impl Into<ToggleableState>) -> Self {
1469 self.toggled = Some(toggled.into());
1470 self
1471 }
1472
1473 pub fn with_enabled(mut self, enabled: bool) -> Self {
1475 self.enabled = enabled;
1476 self
1477 }
1478
1479 pub fn with_custom_action(mut self, action: SemanticsCustomAction) -> Self {
1481 self.custom_actions.push(action);
1482 self
1483 }
1484}
1485
1486#[derive(Clone, Debug, PartialEq)]
1488pub struct SemanticsConfiguration {
1489 pub content_description: Option<String>,
1491 pub state_description: Option<String>,
1493 pub on_click_label: Option<String>,
1495 pub on_click: Option<SemanticsCustomAction>,
1498 pub on_long_click: Option<SemanticsLongClick>,
1501 pub on_long_click_label: Option<String>,
1504 pub on_magic_tap: Option<SemanticsMagicTap>,
1508 pub on_magic_tap_label: Option<String>,
1511 pub input_labels: Vec<String>,
1515 pub language: Option<String>,
1519 pub role: Option<SemanticsWidgetRole>,
1521 pub selected: Option<bool>,
1523 pub toggled: Option<ToggleableState>,
1526 pub enabled: bool,
1528 pub is_clickable: bool,
1530 pub is_editable_text: bool,
1532 pub multiline: bool,
1534 pub text: Option<String>,
1537 pub text_selection: Option<crate::text::TextRange>,
1539 pub custom_actions: Vec<SemanticsCustomAction>,
1541 pub canvas_children: Vec<CanvasSemanticsNode>,
1544 pub is_modal: bool,
1547 pub hidden: bool,
1551 pub merge_descendants: bool,
1555 pub selectable_group: bool,
1559 pub pane_title: Option<String>,
1562 pub error: Option<String>,
1565 pub hint_text: Option<String>,
1568 pub password: bool,
1571 pub traversal_index: f32,
1575 pub test_tag: Option<String>,
1578 pub live_region: Option<LiveRegionMode>,
1581 pub progress: Option<ProgressBarRangeInfo>,
1584 pub set_progress: Option<SemanticsSetProgress>,
1587 pub set_text: Option<SemanticsSetText>,
1590 pub set_selection: Option<SemanticsSetSelection>,
1593 pub expand: Option<SemanticsExpand>,
1596 pub dismiss: Option<SemanticsDismiss>,
1600 pub collapse: Option<SemanticsExpand>,
1603 pub vertical_scroll: Option<ScrollAxisRange>,
1606 pub horizontal_scroll: Option<ScrollAxisRange>,
1609 pub scroll_by: Option<SemanticsScrollBy>,
1612 pub scroll_to_index: Option<SemanticsScrollToIndex>,
1616 pub collection: Option<CollectionInfo>,
1618}
1619
1620impl Default for SemanticsConfiguration {
1621 fn default() -> Self {
1622 Self {
1623 content_description: None,
1624 state_description: None,
1625 on_click_label: None,
1626 on_click: None,
1627 on_long_click: None,
1628 on_long_click_label: None,
1629 on_magic_tap: None,
1630 on_magic_tap_label: None,
1631 input_labels: Vec::new(),
1632 language: None,
1633 role: None,
1634 selected: None,
1635 toggled: None,
1636 enabled: true,
1637 is_clickable: false,
1638 is_editable_text: false,
1639 multiline: false,
1640 text: None,
1641 text_selection: None,
1642 custom_actions: Vec::new(),
1643 canvas_children: Vec::new(),
1644 is_modal: false,
1645 hidden: false,
1646 merge_descendants: false,
1647 selectable_group: false,
1648 pane_title: None,
1649 error: None,
1650 hint_text: None,
1651 password: false,
1652 traversal_index: 0.0,
1653 test_tag: None,
1654 live_region: None,
1655 progress: None,
1656 set_progress: None,
1657 set_text: None,
1658 set_selection: None,
1659 expand: None,
1660 dismiss: None,
1661 collapse: None,
1662 vertical_scroll: None,
1663 horizontal_scroll: None,
1664 scroll_by: None,
1665 scroll_to_index: None,
1666 collection: None,
1667 }
1668 }
1669}
1670
1671pub type SemanticsSpec = SemanticsConfiguration;
1680
1681impl SemanticsConfiguration {
1682 pub fn new() -> Self {
1685 Self::default()
1686 }
1687
1688 pub fn content_description(mut self, name: impl Into<String>) -> Self {
1691 self.content_description = Some(name.into());
1692 self
1693 }
1694
1695 pub fn test_tag(mut self, tag: impl Into<String>) -> Self {
1698 self.test_tag = Some(tag.into());
1699 self
1700 }
1701
1702 pub fn state_description(mut self, state: impl Into<String>) -> Self {
1705 self.state_description = Some(state.into());
1706 self
1707 }
1708
1709 pub fn clickable(mut self) -> Self {
1711 self.is_clickable = true;
1712 self
1713 }
1714
1715 pub fn on_click(mut self, label: impl Into<String>, action: impl Fn() + 'static) -> Self {
1718 self.on_click = Some(SemanticsCustomAction::new(label, action));
1719 self
1720 }
1721
1722 pub fn on_long_click(
1726 mut self,
1727 label: impl Into<String>,
1728 action: impl Fn() -> bool + 'static,
1729 ) -> Self {
1730 self.on_long_click_label = Some(label.into());
1731 self.on_long_click = Some(SemanticsLongClick::new(action));
1732 self
1733 }
1734
1735 pub fn on_magic_tap(
1739 mut self,
1740 label: impl Into<String>,
1741 action: impl Fn() -> bool + 'static,
1742 ) -> Self {
1743 self.on_magic_tap_label = Some(label.into());
1744 self.on_magic_tap = Some(SemanticsMagicTap::new(action));
1745 self
1746 }
1747
1748 pub fn input_labels<S: Into<String>>(mut self, labels: impl IntoIterator<Item = S>) -> Self {
1751 self.input_labels = labels.into_iter().map(Into::into).collect();
1752 self
1753 }
1754
1755 pub fn language(mut self, tag: impl Into<String>) -> Self {
1758 self.language = Some(tag.into());
1759 self
1760 }
1761
1762 pub fn toggled(mut self, toggled: impl Into<ToggleableState>) -> Self {
1765 self.toggled = Some(toggled.into());
1766 self
1767 }
1768
1769 pub fn selected(mut self, selected: bool) -> Self {
1772 self.selected = Some(selected);
1773 self
1774 }
1775
1776 pub fn role(mut self, role: SemanticsWidgetRole) -> Self {
1778 self.role = Some(role);
1779 self
1780 }
1781
1782 pub fn heading(self) -> Self {
1785 self.role(SemanticsWidgetRole::Header)
1786 }
1787
1788 pub fn error(mut self, message: impl Into<String>) -> Self {
1790 self.error = Some(message.into());
1791 self
1792 }
1793
1794 pub fn hint_text(mut self, hint: impl Into<String>) -> Self {
1796 self.hint_text = Some(hint.into());
1797 self
1798 }
1799
1800 pub fn password(mut self) -> Self {
1802 self.password = true;
1803 self
1804 }
1805
1806 pub fn pane_title(mut self, title: impl Into<String>) -> Self {
1809 self.pane_title = Some(title.into());
1810 self
1811 }
1812
1813 pub fn traversal_index(mut self, index: f32) -> Self {
1816 self.traversal_index = index;
1817 self
1818 }
1819
1820 pub fn hidden(mut self) -> Self {
1823 self.hidden = true;
1824 self
1825 }
1826
1827 pub fn merge_descendants(mut self) -> Self {
1830 self.merge_descendants = true;
1831 self
1832 }
1833
1834 pub fn selectable_group(mut self) -> Self {
1837 self.selectable_group = true;
1838 self
1839 }
1840
1841 pub fn live_region(mut self, mode: LiveRegionMode) -> Self {
1844 self.live_region = Some(mode);
1845 self
1846 }
1847 pub fn merge(&mut self, other: &SemanticsConfiguration) {
1851 if let Some(description) = &other.content_description {
1852 self.content_description = Some(description.clone());
1853 }
1854 if let Some(state) = &other.state_description {
1855 self.state_description = Some(state.clone());
1856 }
1857 if let Some(label) = &other.on_click_label {
1858 self.on_click_label = Some(label.clone());
1859 }
1860 if let Some(label) = &other.on_long_click_label {
1861 self.on_long_click_label = Some(label.clone());
1862 }
1863 if let Some(label) = &other.on_magic_tap_label {
1864 self.on_magic_tap_label = Some(label.clone());
1865 }
1866 if !other.input_labels.is_empty() {
1867 self.input_labels.clone_from(&other.input_labels);
1868 }
1869 if let Some(language) = &other.language {
1870 self.language = Some(language.clone());
1871 }
1872 if let Some(role) = other.role {
1873 self.role = Some(role);
1874 }
1875 if let Some(selected) = other.selected {
1876 self.selected = Some(selected);
1877 }
1878 if let Some(toggled) = other.toggled {
1879 self.toggled = Some(toggled);
1880 }
1881 self.enabled &= other.enabled;
1882 self.is_clickable |= other.is_clickable;
1883 self.is_editable_text |= other.is_editable_text;
1884 self.multiline |= other.multiline;
1885 if let Some(text) = &other.text {
1886 self.text = Some(text.clone());
1887 }
1888 self.is_modal |= other.is_modal;
1889 self.hidden |= other.hidden;
1890 self.merge_descendants |= other.merge_descendants;
1891 self.selectable_group |= other.selectable_group;
1892 self.password |= other.password;
1893 if other.traversal_index != 0.0 {
1894 self.traversal_index = other.traversal_index;
1895 }
1896 if let Some(live_region) = other.live_region {
1897 self.live_region = Some(live_region);
1898 }
1899 self.merge_words(other);
1900 self.merge_actions(other);
1901 self.merge_ranges(other);
1902 }
1903
1904 fn merge_words(&mut self, other: &SemanticsConfiguration) {
1905 if let Some(title) = &other.pane_title {
1906 self.pane_title = Some(title.clone());
1907 }
1908 if let Some(error) = &other.error {
1909 self.error = Some(error.clone());
1910 }
1911 if let Some(hint) = &other.hint_text {
1912 self.hint_text = Some(hint.clone());
1913 }
1914 if let Some(tag) = &other.test_tag {
1915 self.test_tag = Some(tag.clone());
1916 }
1917 }
1918
1919 fn merge_actions(&mut self, other: &SemanticsConfiguration) {
1920 if let Some(on_click) = &other.on_click {
1921 self.on_click = Some(on_click.clone());
1922 }
1923 self.custom_actions
1924 .extend(other.custom_actions.iter().cloned());
1925 self.canvas_children
1926 .extend(other.canvas_children.iter().cloned());
1927 if let Some(set_progress) = &other.set_progress {
1928 self.set_progress = Some(set_progress.clone());
1929 }
1930 if let Some(set_text) = &other.set_text {
1931 self.set_text = Some(set_text.clone());
1932 }
1933 if let Some(set_selection) = &other.set_selection {
1934 self.set_selection = Some(set_selection.clone());
1935 }
1936 if let Some(expand) = &other.expand {
1937 self.expand = Some(expand.clone());
1938 }
1939 if let Some(collapse) = &other.collapse {
1940 self.collapse = Some(collapse.clone());
1941 }
1942 if let Some(dismiss) = &other.dismiss {
1943 self.dismiss = Some(dismiss.clone());
1944 }
1945 if let Some(long_click) = &other.on_long_click {
1946 self.on_long_click = Some(long_click.clone());
1947 }
1948 if let Some(magic_tap) = &other.on_magic_tap {
1949 self.on_magic_tap = Some(magic_tap.clone());
1950 }
1951 if let Some(scroll_by) = &other.scroll_by {
1952 self.scroll_by = Some(scroll_by.clone());
1953 }
1954 if let Some(scroll_to_index) = &other.scroll_to_index {
1955 self.scroll_to_index = Some(scroll_to_index.clone());
1956 }
1957 }
1958
1959 fn merge_ranges(&mut self, other: &SemanticsConfiguration) {
1960 if let Some(selection) = other.text_selection {
1961 self.text_selection = Some(selection);
1962 }
1963 if let Some(progress) = other.progress {
1964 self.progress = Some(progress);
1965 }
1966 if let Some(range) = other.vertical_scroll {
1967 self.vertical_scroll = Some(range);
1968 }
1969 if let Some(range) = other.horizontal_scroll {
1970 self.horizontal_scroll = Some(range);
1971 }
1972 if let Some(collection) = other.collection {
1973 self.collection = Some(collection);
1974 }
1975 }
1976
1977 pub fn is_activatable(&self) -> bool {
1980 self.is_clickable || self.on_click_label.is_some() || self.on_click.is_some()
1981 }
1982}
1983
1984impl fmt::Debug for dyn ModifierNode {
1985 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1986 f.debug_struct("ModifierNode").finish_non_exhaustive()
1987 }
1988}
1989
1990impl dyn ModifierNode {
1991 pub fn as_any(&self) -> &dyn Any {
1993 self
1994 }
1995
1996 pub fn as_any_mut(&mut self) -> &mut dyn Any {
1998 self
1999 }
2000}
2001
2002pub trait ModifierNodeElement: fmt::Debug + Hash + PartialEq + 'static {
2005 type Node: ModifierNode;
2007
2008 fn create(&self) -> Self::Node;
2010
2011 fn update(&self, node: &mut Self::Node);
2013
2014 fn key(&self) -> Option<u64> {
2016 None
2017 }
2018
2019 fn inspector_name(&self) -> &'static str {
2021 type_name::<Self>()
2022 }
2023
2024 fn inspector_properties(&self, _inspector: &mut dyn FnMut(&'static str, String)) {}
2026
2027 fn capabilities(&self) -> NodeCapabilities {
2030 NodeCapabilities::default()
2031 }
2032
2033 fn always_update(&self) -> bool {
2039 false
2040 }
2041
2042 fn auto_invalidate_on_update(&self) -> bool {
2045 true
2046 }
2047
2048 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
2055 None
2056 }
2057
2058 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2065 Vec::new()
2066 }
2067}
2068
2069#[derive(Clone, Copy, PartialEq, Eq, Hash)]
2071pub struct NodeCapabilities(u32);
2072
2073impl NodeCapabilities {
2074 pub const NONE: Self = Self(0);
2076 pub const LAYOUT: Self = Self(1 << 0);
2078 pub const DRAW: Self = Self(1 << 1);
2080 pub const POINTER_INPUT: Self = Self(1 << 2);
2082 pub const SEMANTICS: Self = Self(1 << 3);
2084 pub const MODIFIER_LOCALS: Self = Self(1 << 4);
2086 pub const FOCUS: Self = Self(1 << 5);
2088 pub const WINDOW_ROOT: Self = Self(1 << 6);
2092 pub const KEY_INPUT: Self = Self(1 << 7);
2094
2095 pub const fn empty() -> Self {
2097 Self::NONE
2098 }
2099
2100 pub const fn contains(self, other: Self) -> bool {
2102 (self.0 & other.0) == other.0
2103 }
2104
2105 pub const fn intersects(self, other: Self) -> bool {
2107 (self.0 & other.0) != 0
2108 }
2109
2110 pub fn insert(&mut self, other: Self) {
2112 self.0 |= other.0;
2113 }
2114
2115 pub const fn bits(self) -> u32 {
2117 self.0
2118 }
2119
2120 pub const fn is_empty(self) -> bool {
2122 self.0 == 0
2123 }
2124
2125 pub const fn for_invalidation(kind: InvalidationKind) -> Self {
2127 match kind {
2128 InvalidationKind::Layout => Self::LAYOUT,
2129 InvalidationKind::Draw => Self::DRAW,
2130 InvalidationKind::PointerInput => Self::POINTER_INPUT,
2131 InvalidationKind::Semantics => Self::SEMANTICS,
2132 InvalidationKind::Focus => Self::FOCUS,
2133 }
2134 }
2135}
2136
2137impl Default for NodeCapabilities {
2138 fn default() -> Self {
2139 Self::NONE
2140 }
2141}
2142
2143impl fmt::Debug for NodeCapabilities {
2144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2145 f.debug_struct("NodeCapabilities")
2146 .field("layout", &self.contains(Self::LAYOUT))
2147 .field("draw", &self.contains(Self::DRAW))
2148 .field("pointer_input", &self.contains(Self::POINTER_INPUT))
2149 .field("semantics", &self.contains(Self::SEMANTICS))
2150 .field("modifier_locals", &self.contains(Self::MODIFIER_LOCALS))
2151 .field("focus", &self.contains(Self::FOCUS))
2152 .field("window_root", &self.contains(Self::WINDOW_ROOT))
2153 .field("key_input", &self.contains(Self::KEY_INPUT))
2154 .finish()
2155 }
2156}
2157
2158impl BitOr for NodeCapabilities {
2159 type Output = Self;
2160
2161 fn bitor(self, rhs: Self) -> Self::Output {
2162 Self(self.0 | rhs.0)
2163 }
2164}
2165
2166impl BitOrAssign for NodeCapabilities {
2167 fn bitor_assign(&mut self, rhs: Self) {
2168 self.0 |= rhs.0;
2169 }
2170}
2171
2172pub type ModifierInvalidations = smallvec::SmallVec<[ModifierInvalidation; 5]>;
2175
2176#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2178pub struct ModifierInvalidation {
2179 kind: InvalidationKind,
2180 capabilities: NodeCapabilities,
2181}
2182
2183impl ModifierInvalidation {
2184 pub const fn new(kind: InvalidationKind, capabilities: NodeCapabilities) -> Self {
2186 Self { kind, capabilities }
2187 }
2188
2189 pub const fn kind(self) -> InvalidationKind {
2191 self.kind
2192 }
2193
2194 pub const fn capabilities(self) -> NodeCapabilities {
2196 self.capabilities
2197 }
2198}
2199
2200pub trait AnyModifierElement: fmt::Debug {
2202 fn node_type(&self) -> TypeId;
2204
2205 fn element_type(&self) -> TypeId;
2207
2208 fn create_node(&self) -> Rc<RefCell<dyn ModifierNode>>;
2210
2211 fn can_update_node(&self, node: &dyn ModifierNode) -> bool;
2213
2214 fn update_node(&self, node: &mut dyn ModifierNode);
2216
2217 fn key(&self) -> Option<u64>;
2219
2220 fn capabilities(&self) -> NodeCapabilities {
2222 NodeCapabilities::default()
2223 }
2224
2225 fn hash_code(&self) -> u64;
2227
2228 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool;
2230
2231 fn inspector_name(&self) -> &'static str;
2233
2234 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String));
2236
2237 fn requires_update(&self) -> bool;
2239
2240 fn auto_invalidates_on_update(&self) -> bool;
2243
2244 fn update_invalidation_kind(&self) -> Option<InvalidationKind>;
2246
2247 fn provides_composition_locals(&self) -> bool {
2249 false
2250 }
2251
2252 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2254 Vec::new()
2255 }
2256
2257 fn as_any(&self) -> &dyn Any;
2259}
2260
2261struct TypedModifierElement<E: ModifierNodeElement> {
2262 element: E,
2263 hash: Cell<Option<u64>>,
2267 provides_locals: bool,
2268}
2269
2270impl<E: ModifierNodeElement> TypedModifierElement<E> {
2271 fn new(element: E) -> Self {
2272 let provides_locals = !element.provided_composition_locals().is_empty();
2273 Self {
2274 element,
2275 hash: Cell::new(None),
2276 provides_locals,
2277 }
2278 }
2279}
2280
2281impl<E> fmt::Debug for TypedModifierElement<E>
2282where
2283 E: ModifierNodeElement,
2284{
2285 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2286 f.debug_struct("TypedModifierElement")
2287 .field("type", &type_name::<E>())
2288 .finish()
2289 }
2290}
2291
2292impl<E> AnyModifierElement for TypedModifierElement<E>
2293where
2294 E: ModifierNodeElement,
2295{
2296 fn node_type(&self) -> TypeId {
2297 TypeId::of::<E::Node>()
2298 }
2299
2300 fn element_type(&self) -> TypeId {
2301 TypeId::of::<E>()
2302 }
2303
2304 fn create_node(&self) -> Rc<RefCell<dyn ModifierNode>> {
2305 Rc::new(RefCell::new(self.element.create()))
2306 }
2307
2308 fn can_update_node(&self, node: &dyn ModifierNode) -> bool {
2309 node.as_any().is::<E::Node>()
2310 }
2311
2312 fn update_node(&self, node: &mut dyn ModifierNode) {
2313 if let Some(typed) = node.as_any_mut().downcast_mut::<E::Node>() {
2314 self.element.update(typed);
2315 }
2316 }
2317
2318 fn key(&self) -> Option<u64> {
2319 self.element.key()
2320 }
2321
2322 fn capabilities(&self) -> NodeCapabilities {
2323 self.element.capabilities()
2324 }
2325
2326 fn provides_composition_locals(&self) -> bool {
2327 self.provides_locals
2328 }
2329
2330 fn provided_composition_locals(&self) -> Vec<ProvidedValue> {
2331 self.element.provided_composition_locals()
2332 }
2333
2334 fn hash_code(&self) -> u64 {
2335 if let Some(hash) = self.hash.get() {
2336 return hash;
2337 }
2338 let mut hasher = default::new();
2339 self.element.hash(&mut hasher);
2340 let hash = hasher.finish();
2341 self.hash.set(Some(hash));
2342 hash
2343 }
2344
2345 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool {
2346 other
2347 .as_any()
2348 .downcast_ref::<Self>()
2349 .is_some_and(|typed| typed.element == self.element)
2350 }
2351
2352 fn inspector_name(&self) -> &'static str {
2353 self.element.inspector_name()
2354 }
2355
2356 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String)) {
2357 self.element.inspector_properties(visitor);
2358 }
2359
2360 fn requires_update(&self) -> bool {
2361 self.element.always_update()
2362 }
2363
2364 fn auto_invalidates_on_update(&self) -> bool {
2365 self.element.auto_invalidate_on_update()
2366 }
2367
2368 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
2369 self.element.update_invalidation_kind()
2370 }
2371
2372 fn as_any(&self) -> &dyn Any {
2373 self
2374 }
2375}
2376
2377fn request_update_auto_invalidations(
2378 element: &dyn AnyModifierElement,
2379 context: &mut dyn ModifierNodeContext,
2380 capabilities: NodeCapabilities,
2381) {
2382 if let Some(kind) = element.update_invalidation_kind() {
2383 let capabilities = NodeCapabilities::for_invalidation(kind);
2384 context.push_active_capabilities(capabilities);
2385 context.invalidate(kind);
2386 context.pop_active_capabilities();
2387 } else if element.auto_invalidates_on_update() {
2388 request_auto_invalidations(context, capabilities);
2389 }
2390}
2391
2392pub fn modifier_element<E: ModifierNodeElement>(element: E) -> DynModifierElement {
2395 Rc::new(TypedModifierElement::new(element))
2396}
2397
2398pub type DynModifierElement = Rc<dyn AnyModifierElement>;
2400
2401#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2402enum TraversalDirection {
2403 Forward,
2404 Backward,
2405}
2406
2407pub struct ModifierChainIter<'a> {
2412 chain: &'a ModifierNodeChain,
2413 cursor: usize,
2414 remaining: usize,
2415 direction: TraversalDirection,
2416}
2417
2418impl<'a> ModifierChainIter<'a> {
2419 fn forward(chain: &'a ModifierNodeChain) -> Self {
2420 Self {
2421 chain,
2422 cursor: 0,
2423 remaining: chain.ordered_nodes.len(),
2424 direction: TraversalDirection::Forward,
2425 }
2426 }
2427
2428 fn backward(chain: &'a ModifierNodeChain) -> Self {
2429 let len = chain.ordered_nodes.len();
2430 Self {
2431 chain,
2432 cursor: len.wrapping_sub(1),
2433 remaining: len,
2434 direction: TraversalDirection::Backward,
2435 }
2436 }
2437}
2438
2439impl<'a> Iterator for ModifierChainIter<'a> {
2440 type Item = ModifierChainNodeRef<'a>;
2441
2442 #[inline]
2443 fn next(&mut self) -> Option<Self::Item> {
2444 if self.remaining == 0 {
2445 return None;
2446 }
2447 let (link, caps, agg) = self.chain.ordered_nodes[self.cursor];
2448 let node_ref = self.chain.make_node_ref_with_caps(link, caps, agg);
2449 self.remaining -= 1;
2450 match self.direction {
2451 TraversalDirection::Forward => self.cursor += 1,
2452 TraversalDirection::Backward => self.cursor = self.cursor.wrapping_sub(1),
2453 }
2454 Some(node_ref)
2455 }
2456
2457 #[inline]
2458 fn size_hint(&self) -> (usize, Option<usize>) {
2459 (self.remaining, Some(self.remaining))
2460 }
2461}
2462
2463impl ExactSizeIterator for ModifierChainIter<'_> {}
2464impl std::iter::FusedIterator for ModifierChainIter<'_> {}
2465
2466#[derive(Debug)]
2470struct ModifierNodeEntry {
2471 key: Option<u64>,
2472 element: DynModifierElement,
2473 node: Rc<RefCell<dyn ModifierNode>>,
2474 capabilities: NodeCapabilities,
2475}
2476
2477impl ModifierNodeEntry {
2478 fn new(
2479 key: Option<u64>,
2480 element: DynModifierElement,
2481 node: Rc<RefCell<dyn ModifierNode>>,
2482 capabilities: NodeCapabilities,
2483 ) -> Self {
2484 let entry = Self {
2485 key,
2486 element,
2487 node,
2488 capabilities,
2489 };
2490 entry
2491 .node
2492 .borrow()
2493 .node_state()
2494 .set_capabilities(entry.capabilities);
2495 entry
2496 }
2497}
2498
2499fn visit_node_tree_mut(
2500 node: &mut dyn ModifierNode,
2501 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
2502) {
2503 visitor(node);
2504 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
2505}
2506
2507fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
2508 let mut current = 0usize;
2509 let mut result: Option<&dyn ModifierNode> = None;
2510 node.for_each_delegate(&mut |child| {
2511 if result.is_none() && current == target {
2512 result = Some(child);
2513 }
2514 current += 1;
2515 });
2516 result
2517}
2518
2519fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
2520 let mut current = 0usize;
2521 let mut result: Option<&mut dyn ModifierNode> = None;
2522 node.for_each_delegate_mut(&mut |child| {
2523 if result.is_none() && current == target {
2524 result = Some(child);
2525 }
2526 current += 1;
2527 });
2528 result
2529}
2530
2531fn with_node_context<F, R>(
2532 node: &mut dyn ModifierNode,
2533 context: &mut dyn ModifierNodeContext,
2534 f: F,
2535) -> R
2536where
2537 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
2538{
2539 context.push_active_capabilities(node.node_state().capabilities());
2540 let result = f(node, context);
2541 context.pop_active_capabilities();
2542 result
2543}
2544
2545fn request_auto_invalidations(
2546 context: &mut dyn ModifierNodeContext,
2547 capabilities: NodeCapabilities,
2548) {
2549 if capabilities.is_empty() {
2550 return;
2551 }
2552
2553 context.push_active_capabilities(capabilities);
2554
2555 if capabilities.contains(NodeCapabilities::LAYOUT) {
2556 context.invalidate(InvalidationKind::Layout);
2557 }
2558 if capabilities.contains(NodeCapabilities::DRAW) {
2559 context.invalidate(InvalidationKind::Draw);
2560 }
2561 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
2562 context.invalidate(InvalidationKind::PointerInput);
2563 }
2564 if capabilities.contains(NodeCapabilities::SEMANTICS) {
2565 context.invalidate(InvalidationKind::Semantics);
2566 }
2567 if capabilities.contains(NodeCapabilities::FOCUS) {
2568 context.invalidate(InvalidationKind::Focus);
2569 }
2570
2571 context.pop_active_capabilities();
2572}
2573
2574fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
2575 visit_node_tree_mut(node, &mut |n| {
2576 if !n.node_state().is_attached() {
2577 n.node_state().set_attached(true);
2578 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
2579 }
2580 });
2581}
2582
2583fn reset_node_tree(node: &mut dyn ModifierNode) {
2584 visit_node_tree_mut(node, &mut |n| n.on_reset());
2585}
2586
2587fn detach_node_tree(node: &mut dyn ModifierNode) {
2588 visit_node_tree_mut(node, &mut |n| {
2589 if n.node_state().is_attached() {
2590 n.on_detach();
2591 n.node_state().set_attached(false);
2592 }
2593 n.node_state().set_parent_link(None);
2594 n.node_state().set_child_link(None);
2595 n.node_state()
2596 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2597 });
2598}
2599
2600pub struct ModifierNodeChain {
2607 entries: Vec<ModifierNodeEntry>,
2608 aggregated_capabilities: NodeCapabilities,
2609 head_aggregate_child_capabilities: NodeCapabilities,
2610 head_sentinel: SentinelNode,
2611 tail_sentinel: SentinelNode,
2612 ordered_nodes: Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
2613 attached: bool,
2617 links_cleared: bool,
2620}
2621
2622#[derive(Default)]
2626struct ReconcileScratch {
2627 old_used: Vec<bool>,
2628 match_order: Vec<Option<usize>>,
2629 final_slots: Vec<Option<ModifierNodeEntry>>,
2630 elements: Vec<DynModifierElement>,
2631}
2632
2633thread_local! {
2634 static RECONCILE_SCRATCH: std::cell::RefCell<ReconcileScratch> =
2635 std::cell::RefCell::default();
2636}
2637
2638struct SentinelNode {
2639 state: NodeState,
2640}
2641
2642impl SentinelNode {
2643 fn new() -> Self {
2644 Self {
2645 state: NodeState::sentinel(),
2646 }
2647 }
2648}
2649
2650impl DelegatableNode for SentinelNode {
2651 fn node_state(&self) -> &NodeState {
2652 &self.state
2653 }
2654}
2655
2656impl ModifierNode for SentinelNode {}
2657
2658#[derive(Clone)]
2662pub struct ModifierChainNodeRef<'a> {
2663 chain: &'a ModifierNodeChain,
2664 link: NodeLink,
2665 cached_capabilities: Option<NodeCapabilities>,
2666 cached_aggregate_child: Option<NodeCapabilities>,
2667}
2668
2669impl Default for ModifierNodeChain {
2670 fn default() -> Self {
2671 Self::new()
2672 }
2673}
2674
2675struct EntryIndex {
2676 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2677 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
2678 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
2679}
2680
2681struct EntryMatchQuery<'a> {
2682 element_type: TypeId,
2683 node_type: TypeId,
2684 key: Option<u64>,
2685 hash_code: u64,
2686 element: &'a DynModifierElement,
2687}
2688
2689impl EntryIndex {
2690 fn build(entries: &[ModifierNodeEntry]) -> Self {
2691 let mut keyed = HashMap::default();
2692 let mut hashed = HashMap::default();
2693 let mut typed = HashMap::default();
2694
2695 for (i, entry) in entries.iter().enumerate() {
2696 let (element_type, node_type) =
2697 (entry.element.element_type(), entry.element.node_type());
2698 if let Some(key_value) = entry.key {
2699 keyed
2700 .entry((element_type, node_type, key_value))
2701 .or_insert_with(Vec::new)
2702 .push(i);
2703 } else {
2704 hashed
2705 .entry((element_type, node_type, entry.element.hash_code()))
2706 .or_insert_with(Vec::new)
2707 .push(i);
2708 typed
2709 .entry((element_type, node_type))
2710 .or_insert_with(Vec::new)
2711 .push(i);
2712 }
2713 }
2714
2715 Self {
2716 keyed,
2717 hashed,
2718 typed,
2719 }
2720 }
2721
2722 fn find_match(
2723 &self,
2724 entries: &[ModifierNodeEntry],
2725 used: &[bool],
2726 query: EntryMatchQuery<'_>,
2727 ) -> Option<usize> {
2728 if let Some(key_value) = query.key {
2729 if let Some(candidates) =
2730 self.keyed
2731 .get(&(query.element_type, query.node_type, key_value))
2732 {
2733 for &i in candidates {
2734 if !used[i] {
2735 return Some(i);
2736 }
2737 }
2738 }
2739 } else {
2740 if let Some(candidates) =
2741 self.hashed
2742 .get(&(query.element_type, query.node_type, query.hash_code))
2743 {
2744 for &i in candidates {
2745 if !used[i]
2746 && entries[i]
2747 .element
2748 .as_ref()
2749 .equals_element(query.element.as_ref())
2750 {
2751 return Some(i);
2752 }
2753 }
2754 }
2755
2756 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
2757 for &i in candidates {
2758 if !used[i] {
2759 return Some(i);
2760 }
2761 }
2762 }
2763 }
2764
2765 None
2766 }
2767}
2768
2769#[derive(Clone, Copy, PartialEq, Eq)]
2771enum InPlace {
2772 LinksHold,
2774 Relink,
2777}
2778
2779fn update_entry_in_place(
2784 entry: &mut ModifierNodeEntry,
2785 element: &DynModifierElement,
2786 context: &mut dyn ModifierNodeContext,
2787) -> Option<InPlace> {
2788 if entry.element.element_type() != element.element_type()
2789 || entry.element.node_type() != element.node_type()
2790 || entry.key != element.key()
2791 || !element.can_update_node(&*entry.node.borrow())
2792 {
2793 return None;
2794 }
2795 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2796 let capabilities = element.capabilities();
2797 let mut outcome = if capabilities == entry.capabilities {
2798 InPlace::LinksHold
2799 } else {
2800 InPlace::Relink
2801 };
2802 if !same_element || element.requires_update() {
2803 element.update_node(&mut *entry.node.borrow_mut());
2804 entry.element = element.clone();
2805 request_update_auto_invalidations(element.as_ref(), context, capabilities);
2806 entry
2807 .node
2808 .borrow()
2809 .for_each_delegate(&mut |_| outcome = InPlace::Relink);
2810 }
2811 entry.capabilities = capabilities;
2812 entry
2813 .node
2814 .borrow()
2815 .node_state()
2816 .set_capabilities(capabilities);
2817 Some(outcome)
2818}
2819
2820fn fresh_entry(
2823 element: DynModifierElement,
2824 context: &mut dyn ModifierNodeContext,
2825 attach: bool,
2826) -> ModifierNodeEntry {
2827 let capabilities = element.capabilities();
2828 let entry = ModifierNodeEntry::new(
2829 element.key(),
2830 element.clone(),
2831 element.create_node(),
2832 capabilities,
2833 );
2834 if attach {
2835 attach_node_tree(&mut *entry.node.borrow_mut(), context);
2836 }
2837 element.update_node(&mut *entry.node.borrow_mut());
2838 request_auto_invalidations(context, capabilities);
2839 entry
2840}
2841
2842fn reconcile_element(
2847 element: DynModifierElement,
2848 new_pos: usize,
2849 (old_entries, index): (&mut [ModifierNodeEntry], &EntryIndex),
2850 (used, match_order): (&mut [bool], &mut [Option<usize>]),
2851 context: &mut dyn ModifierNodeContext,
2852 attach: bool,
2853) -> Option<ModifierNodeEntry> {
2854 let element_type = element.element_type();
2855 let node_type = element.node_type();
2856 let key = element.key();
2857 let hash_code = if key.is_none() {
2859 element.hash_code()
2860 } else {
2861 0
2862 };
2863 let capabilities = element.capabilities();
2864 let Some(idx) = index.find_match(
2865 old_entries,
2866 used,
2867 EntryMatchQuery {
2868 element_type,
2869 node_type,
2870 key,
2871 hash_code,
2872 element: &element,
2873 },
2874 ) else {
2875 return Some(fresh_entry(element, context, attach));
2876 };
2877 let entry = &mut old_entries[idx];
2878 if !element.can_update_node(&*entry.node.borrow()) {
2879 return Some(fresh_entry(element, context, attach));
2880 }
2881
2882 used[idx] = true;
2883 match_order[idx] = Some(new_pos);
2884 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2885 if !same_element || element.requires_update() {
2886 element.update_node(&mut *entry.node.borrow_mut());
2887 entry.element = element;
2888 request_update_auto_invalidations(entry.element.as_ref(), context, capabilities);
2889 }
2890 if idx != new_pos {
2891 request_auto_invalidations(context, capabilities);
2892 }
2893 entry.key = key;
2894 entry.capabilities = capabilities;
2895 entry
2896 .node
2897 .borrow()
2898 .node_state()
2899 .set_capabilities(capabilities);
2900 None
2901}
2902
2903impl ModifierNodeChain {
2904 pub fn new() -> Self {
2906 let mut chain = Self::detached();
2907 chain.attached = true;
2908 chain
2909 }
2910
2911 pub fn detached() -> Self {
2914 let mut chain = Self {
2915 entries: Vec::new(),
2916 aggregated_capabilities: NodeCapabilities::empty(),
2917 head_aggregate_child_capabilities: NodeCapabilities::empty(),
2918 head_sentinel: SentinelNode::new(),
2919 tail_sentinel: SentinelNode::new(),
2920 ordered_nodes: Vec::new(),
2921 attached: false,
2922 links_cleared: false,
2923 };
2924 chain.sync_chain_links();
2925 chain
2926 }
2927
2928 pub fn detach_nodes(&mut self) {
2930 if !self.attached {
2931 return;
2932 }
2933 self.attached = false;
2934 for entry in &self.entries {
2935 detach_node_tree(&mut *entry.node.borrow_mut());
2936 }
2937 self.links_cleared = !self.entries.is_empty();
2938 }
2939
2940 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
2942 if self.attached {
2943 return;
2944 }
2945 self.attached = true;
2946 for entry in &self.entries {
2947 attach_node_tree(&mut *entry.node.borrow_mut(), context);
2948 }
2949 }
2950
2951 pub fn repair_chain(&mut self) {
2954 if self.links_cleared {
2955 self.sync_chain_links();
2956 }
2957 }
2958
2959 pub fn update_from_slice(
2965 &mut self,
2966 elements: &[DynModifierElement],
2967 context: &mut dyn ModifierNodeContext,
2968 ) {
2969 self.update_from_ref_iter(elements.iter(), context);
2970 }
2971
2972 pub fn update_entries_in_place<'a, I>(
2978 &mut self,
2979 elements: I,
2980 element_count: usize,
2981 in_place: impl Fn(TypeId) -> bool,
2982 context: &mut dyn ModifierNodeContext,
2983 ) -> bool
2984 where
2985 I: Iterator<Item = &'a DynModifierElement>,
2986 {
2987 if element_count != self.entries.len() {
2988 return false;
2989 }
2990 let mut relink = false;
2991 let updated = self
2992 .entries
2993 .iter_mut()
2994 .zip(elements)
2995 .filter(|(_, element)| in_place(element.element_type()))
2996 .all(
2997 |(entry, element)| match update_entry_in_place(entry, element, context) {
2998 Some(outcome) => {
2999 relink |= outcome == InPlace::Relink;
3000 true
3001 }
3002 None => false,
3003 },
3004 );
3005 if relink {
3006 self.sync_chain_links();
3007 }
3008 updated
3009 }
3010
3011 pub fn update_from_ref_iter<'a, I>(
3014 &mut self,
3015 elements: I,
3016 context: &mut dyn ModifierNodeContext,
3017 ) where
3018 I: Iterator<Item = &'a DynModifierElement>,
3019 {
3020 let mut scratch = RECONCILE_SCRATCH
3023 .try_with(|scratch| std::mem::take(&mut *scratch.borrow_mut()))
3024 .unwrap_or_default();
3025 self.reconcile(elements, context, &mut scratch);
3026 scratch.elements.clear();
3027 scratch.final_slots.clear();
3028 let _ = RECONCILE_SCRATCH.try_with(|slot| *slot.borrow_mut() = scratch);
3029 }
3030
3031 fn reconcile<'a, I>(
3032 &mut self,
3033 elements: I,
3034 context: &mut dyn ModifierNodeContext,
3035 scratch: &mut ReconcileScratch,
3036 ) where
3037 I: Iterator<Item = &'a DynModifierElement>,
3038 {
3039 let old_len = self.entries.len();
3040 let mut fast_path_failed_at: Option<usize> = None;
3041 let mut elements_count = 0;
3042 let mut relink = self.links_cleared;
3045
3046 scratch.elements.clear();
3047
3048 for (idx, element) in elements.enumerate() {
3049 elements_count = idx + 1;
3050 if fast_path_failed_at.is_none() && idx < old_len {
3051 if let Some(outcome) =
3052 update_entry_in_place(&mut self.entries[idx], element, context)
3053 {
3054 relink |= outcome == InPlace::Relink;
3055 continue;
3056 }
3057 fast_path_failed_at = Some(idx);
3058 }
3059 scratch.elements.push(element.clone());
3060 }
3061
3062 if fast_path_failed_at.is_none() && scratch.elements.is_empty() {
3063 if elements_count < self.entries.len() {
3064 for entry in self.entries.drain(elements_count..) {
3065 request_auto_invalidations(context, entry.capabilities);
3066 detach_node_tree(&mut *entry.node.borrow_mut());
3067 }
3068 relink = true;
3069 }
3070 if relink {
3071 self.sync_chain_links();
3072 }
3073 return;
3074 }
3075
3076 self.rebuild_tail(fast_path_failed_at.unwrap_or(old_len), context, scratch);
3077 }
3078
3079 fn rebuild_tail(
3083 &mut self,
3084 fail_idx: usize,
3085 context: &mut dyn ModifierNodeContext,
3086 scratch: &mut ReconcileScratch,
3087 ) {
3088 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
3089 let processed_entries_len = self.entries.len();
3090 let old_len = old_entries.len();
3091
3092 scratch.old_used.clear();
3093 scratch.old_used.resize(old_len, false);
3094
3095 scratch.match_order.clear();
3096 scratch.match_order.resize(old_len, None);
3097
3098 let index = EntryIndex::build(&old_entries);
3099
3100 let new_elements_count = scratch.elements.len();
3101 scratch.final_slots.clear();
3102 scratch.final_slots.reserve(new_elements_count);
3103
3104 for (new_pos, element) in scratch.elements.drain(..).enumerate() {
3105 let fresh = reconcile_element(
3106 element,
3107 new_pos,
3108 (&mut old_entries, &index),
3109 (&mut scratch.old_used, &mut scratch.match_order),
3110 context,
3111 self.attached,
3112 );
3113 scratch.final_slots.push(fresh);
3114 }
3115
3116 for (i, entry) in old_entries.into_iter().enumerate() {
3117 match scratch.match_order[i] {
3118 Some(pos) if scratch.old_used[i] => scratch.final_slots[pos] = Some(entry),
3119 _ => {
3120 request_auto_invalidations(context, entry.capabilities);
3121 detach_node_tree(&mut *entry.node.borrow_mut());
3122 }
3123 }
3124 }
3125
3126 self.entries.reserve_exact(scratch.final_slots.len());
3130 for slot in scratch.final_slots.drain(..) {
3131 if let Some(entry) = slot {
3132 self.entries.push(entry);
3133 } else {
3134 log::error!("modifier reconciliation produced an empty final slot");
3135 }
3136 }
3137
3138 debug_assert_eq!(
3139 self.entries.len(),
3140 processed_entries_len + new_elements_count
3141 );
3142 self.sync_chain_links();
3143 }
3144
3145 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
3149 where
3150 I: IntoIterator<Item = DynModifierElement>,
3151 {
3152 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
3153 self.update_from_slice(&collected, context);
3154 }
3155
3156 pub fn reset(&mut self) {
3159 for entry in &mut self.entries {
3160 reset_node_tree(&mut *entry.node.borrow_mut());
3161 }
3162 }
3163
3164 pub fn detach_all(&mut self) {
3166 for entry in std::mem::take(&mut self.entries) {
3167 detach_node_tree(&mut *entry.node.borrow_mut());
3168 {
3169 let node_borrow = entry.node.borrow();
3170 let state = node_borrow.node_state();
3171 state.set_capabilities(NodeCapabilities::empty());
3172 }
3173 }
3174 self.aggregated_capabilities = NodeCapabilities::empty();
3175 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
3176 self.ordered_nodes.clear();
3177 self.sync_chain_links();
3178 }
3179
3180 pub fn len(&self) -> usize {
3182 self.entries.len()
3183 }
3184
3185 pub fn is_empty(&self) -> bool {
3187 self.entries.is_empty()
3188 }
3189
3190 pub fn capabilities(&self) -> NodeCapabilities {
3192 self.aggregated_capabilities
3193 }
3194
3195 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
3197 self.aggregated_capabilities.contains(capability)
3198 }
3199
3200 pub fn head(&self) -> ModifierChainNodeRef<'_> {
3202 self.make_node_ref(NodeLink::Head)
3203 }
3204
3205 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
3207 self.make_node_ref(NodeLink::Tail)
3208 }
3209
3210 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
3212 ModifierChainIter::forward(self)
3213 }
3214
3215 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
3217 ModifierChainIter::backward(self)
3218 }
3219
3220 pub fn for_each_forward<F>(&self, mut f: F)
3222 where
3223 F: FnMut(ModifierChainNodeRef<'_>),
3224 {
3225 for node in self.head_to_tail() {
3226 f(node);
3227 }
3228 }
3229
3230 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
3232 where
3233 F: FnMut(ModifierChainNodeRef<'_>),
3234 {
3235 if mask.is_empty() {
3236 self.for_each_forward(f);
3237 return;
3238 }
3239
3240 if !self.head().aggregate_child_capabilities().intersects(mask) {
3241 return;
3242 }
3243
3244 for node in self.head_to_tail() {
3245 if node.kind_set().intersects(mask) {
3246 f(node);
3247 }
3248 }
3249 }
3250
3251 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
3253 where
3254 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
3255 {
3256 self.for_each_forward_matching(mask, |node_ref| {
3257 node_ref.with_node(|node| f(node_ref.clone(), node));
3258 });
3259 }
3260
3261 pub fn for_each_backward<F>(&self, mut f: F)
3263 where
3264 F: FnMut(ModifierChainNodeRef<'_>),
3265 {
3266 for node in self.tail_to_head() {
3267 f(node);
3268 }
3269 }
3270
3271 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
3273 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
3274 node as *const dyn ModifierNode as *const ()
3275 }
3276
3277 let target = node_data_ptr(node);
3278 for (index, entry) in self.entries.iter().enumerate() {
3279 if node_data_ptr(&*entry.node.borrow()) == target {
3280 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
3281 }
3282 }
3283
3284 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
3285 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
3286 return None;
3287 }
3288 let matches_target = match link {
3289 NodeLink::Head => node_data_ptr(&self.head_sentinel) == target,
3290 NodeLink::Tail => node_data_ptr(&self.tail_sentinel) == target,
3291 NodeLink::Entry(path) => {
3292 let node_borrow = self.entries[path.entry()].node.borrow();
3293 node_data_ptr(&*node_borrow) == target
3294 }
3295 };
3296 if matches_target {
3297 Some(self.make_node_ref(*link))
3298 } else {
3299 None
3300 }
3301 })
3302 }
3303
3304 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
3307 self.entries.get(index).and_then(|entry| {
3308 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
3309 boxed_node.as_any().downcast_ref::<N>()
3310 })
3311 .ok()
3312 })
3313 }
3314
3315 pub fn node_mut<N: ModifierNode + 'static>(
3318 &self,
3319 index: usize,
3320 ) -> Option<std::cell::RefMut<'_, N>> {
3321 self.entries.get(index).and_then(|entry| {
3322 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
3323 boxed_node.as_any_mut().downcast_mut::<N>()
3324 })
3325 .ok()
3326 })
3327 }
3328
3329 pub fn get_node_rc(&self, index: usize) -> Option<&Rc<RefCell<dyn ModifierNode>>> {
3332 self.entries.get(index).map(|entry| &entry.node)
3333 }
3334
3335 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
3337 self.aggregated_capabilities
3338 .contains(NodeCapabilities::for_invalidation(kind))
3339 }
3340
3341 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
3343 where
3344 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
3345 {
3346 for index in 0..self.ordered_nodes.len() {
3347 let (link, cached_caps, _agg) = self.ordered_nodes[index];
3348 match link {
3349 NodeLink::Head => {
3350 f(&mut self.head_sentinel, cached_caps);
3351 }
3352 NodeLink::Tail => {
3353 f(&mut self.tail_sentinel, cached_caps);
3354 }
3355 NodeLink::Entry(path) => {
3356 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
3357 if path.delegates().is_empty() {
3358 f(&mut *node_borrow, cached_caps);
3359 } else {
3360 let mut current: &mut dyn ModifierNode = &mut *node_borrow;
3361 for &delegate_index in path.delegates() {
3362 if let Some(delegate) =
3363 nth_delegate_mut(current, delegate_index as usize)
3364 {
3365 current = delegate;
3366 } else {
3367 return;
3368 }
3369 }
3370 f(current, cached_caps);
3371 }
3372 }
3373 }
3374 }
3375 }
3376
3377 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
3378 ModifierChainNodeRef {
3379 chain: self,
3380 link,
3381 cached_capabilities: None,
3382 cached_aggregate_child: None,
3383 }
3384 }
3385
3386 fn make_node_ref_with_caps(
3387 &self,
3388 link: NodeLink,
3389 caps: NodeCapabilities,
3390 aggregate_child: NodeCapabilities,
3391 ) -> ModifierChainNodeRef<'_> {
3392 ModifierChainNodeRef {
3393 chain: self,
3394 link,
3395 cached_capabilities: Some(caps),
3396 cached_aggregate_child: Some(aggregate_child),
3397 }
3398 }
3399
3400 fn sync_chain_links(&mut self) {
3401 self.links_cleared = false;
3402 self.rebuild_ordered_nodes();
3403
3404 self.head_sentinel.node_state().set_parent_link(None);
3405 self.tail_sentinel.node_state().set_child_link(None);
3406
3407 if self.ordered_nodes.is_empty() {
3408 self.head_sentinel
3409 .node_state()
3410 .set_child_link(Some(NodeLink::Tail));
3411 self.tail_sentinel
3412 .node_state()
3413 .set_parent_link(Some(NodeLink::Head));
3414 self.aggregated_capabilities = NodeCapabilities::empty();
3415 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
3416 self.head_sentinel
3417 .node_state()
3418 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3419 self.tail_sentinel
3420 .node_state()
3421 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3422 return;
3423 }
3424
3425 let mut previous = NodeLink::Head;
3426 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
3427 match &previous {
3428 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
3429 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
3430 NodeLink::Entry(path) => {
3431 let node_borrow = self.entries[path.entry()].node.borrow();
3432 if path.delegates().is_empty() {
3433 node_borrow.node_state().set_child_link(Some(link));
3434 } else {
3435 let mut current: &dyn ModifierNode = &*node_borrow;
3436 for &delegate_index in path.delegates() {
3437 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3438 current = delegate;
3439 }
3440 }
3441 current.node_state().set_child_link(Some(link));
3442 }
3443 }
3444 }
3445 match &link {
3446 NodeLink::Head => self
3447 .head_sentinel
3448 .node_state()
3449 .set_parent_link(Some(previous)),
3450 NodeLink::Tail => self
3451 .tail_sentinel
3452 .node_state()
3453 .set_parent_link(Some(previous)),
3454 NodeLink::Entry(path) => {
3455 let node_borrow = self.entries[path.entry()].node.borrow();
3456 if path.delegates().is_empty() {
3457 node_borrow.node_state().set_parent_link(Some(previous));
3458 } else {
3459 let mut current: &dyn ModifierNode = &*node_borrow;
3460 for &delegate_index in path.delegates() {
3461 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3462 current = delegate;
3463 }
3464 }
3465 current.node_state().set_parent_link(Some(previous));
3466 }
3467 }
3468 }
3469 previous = link;
3470 }
3471
3472 match &previous {
3473 NodeLink::Head => self
3474 .head_sentinel
3475 .node_state()
3476 .set_child_link(Some(NodeLink::Tail)),
3477 NodeLink::Tail => self
3478 .tail_sentinel
3479 .node_state()
3480 .set_child_link(Some(NodeLink::Tail)),
3481 NodeLink::Entry(path) => {
3482 let node_borrow = self.entries[path.entry()].node.borrow();
3483 if path.delegates().is_empty() {
3484 node_borrow
3485 .node_state()
3486 .set_child_link(Some(NodeLink::Tail));
3487 } else {
3488 let mut current: &dyn ModifierNode = &*node_borrow;
3489 for &delegate_index in path.delegates() {
3490 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3491 current = delegate;
3492 }
3493 }
3494 current.node_state().set_child_link(Some(NodeLink::Tail));
3495 }
3496 }
3497 }
3498 self.tail_sentinel
3499 .node_state()
3500 .set_parent_link(Some(previous));
3501 self.tail_sentinel.node_state().set_child_link(None);
3502
3503 let mut aggregate = NodeCapabilities::empty();
3504 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
3505 aggregate |= *cached_caps;
3506 *cached_aggregate = aggregate;
3507 match link {
3508 NodeLink::Head => {
3509 self.head_sentinel
3510 .node_state()
3511 .set_aggregate_child_capabilities(aggregate);
3512 }
3513 NodeLink::Tail => {
3514 self.tail_sentinel
3515 .node_state()
3516 .set_aggregate_child_capabilities(aggregate);
3517 }
3518 NodeLink::Entry(path) => {
3519 let node_borrow = self.entries[path.entry()].node.borrow();
3520 let state = if path.delegates().is_empty() {
3521 node_borrow.node_state()
3522 } else {
3523 let mut current: &dyn ModifierNode = &*node_borrow;
3524 for &delegate_index in path.delegates() {
3525 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3526 current = delegate;
3527 }
3528 }
3529 current.node_state()
3530 };
3531 state.set_aggregate_child_capabilities(aggregate);
3532 }
3533 }
3534 }
3535
3536 self.aggregated_capabilities = aggregate;
3537 self.head_aggregate_child_capabilities = aggregate;
3538 self.head_sentinel
3539 .node_state()
3540 .set_aggregate_child_capabilities(aggregate);
3541 self.tail_sentinel
3542 .node_state()
3543 .set_aggregate_child_capabilities(NodeCapabilities::empty());
3544 }
3545
3546 fn rebuild_ordered_nodes(&mut self) {
3547 self.ordered_nodes.clear();
3548 self.ordered_nodes.reserve_exact(self.entries.len());
3550 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
3551 for (index, entry) in self.entries.iter().enumerate() {
3552 let node_borrow = entry.node.borrow();
3553 Self::enumerate_link_order(
3554 &*node_borrow,
3555 index,
3556 &mut path_buf,
3557 0,
3558 &mut self.ordered_nodes,
3559 );
3560 }
3561 }
3562
3563 fn enumerate_link_order(
3564 node: &dyn ModifierNode,
3565 entry: usize,
3566 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
3567 path_len: usize,
3568 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
3569 ) {
3570 let caps = node.node_state().capabilities();
3571 out.push((
3572 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
3573 caps,
3574 NodeCapabilities::empty(),
3575 ));
3576 let mut delegate_index = 0usize;
3577 node.for_each_delegate(&mut |child| {
3578 if path_len < MAX_DELEGATE_DEPTH {
3579 path_buf[path_len] = delegate_index;
3580 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
3581 }
3582 delegate_index += 1;
3583 });
3584 }
3585}
3586
3587impl<'a> ModifierChainNodeRef<'a> {
3588 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
3589 match &self.link {
3590 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
3591 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
3592 NodeLink::Entry(path) => {
3593 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3594 if path.delegates().is_empty() {
3595 f(node_borrow.node_state())
3596 } else {
3597 let mut current: &dyn ModifierNode = &*node_borrow;
3598 for &delegate_index in path.delegates() {
3599 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
3600 current = delegate;
3601 } else {
3602 return f(node_borrow.node_state());
3603 }
3604 }
3605 f(current.node_state())
3606 }
3607 }
3608 }
3609 }
3610
3611 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
3614 match &self.link {
3615 NodeLink::Head => None,
3616 NodeLink::Tail => None,
3617 NodeLink::Entry(path) => {
3618 let node_borrow = self.chain.entries[path.entry()].node.borrow();
3619 if path.delegates().is_empty() {
3620 Some(f(&*node_borrow))
3621 } else {
3622 let mut current: &dyn ModifierNode = &*node_borrow;
3623 for &delegate_index in path.delegates() {
3624 current = nth_delegate(current, delegate_index as usize)?;
3625 }
3626 Some(f(current))
3627 }
3628 }
3629 }
3630 }
3631
3632 #[inline]
3634 pub fn parent(&self) -> Option<Self> {
3635 self.with_state(NodeState::parent_link)
3636 .map(|link| self.chain.make_node_ref(link))
3637 }
3638
3639 #[inline]
3641 pub fn child(&self) -> Option<Self> {
3642 self.with_state(NodeState::child_link)
3643 .map(|link| self.chain.make_node_ref(link))
3644 }
3645
3646 #[inline]
3648 pub fn kind_set(&self) -> NodeCapabilities {
3649 if let Some(caps) = self.cached_capabilities {
3650 return caps;
3651 }
3652 match &self.link {
3653 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
3654 NodeLink::Entry(_) => self.with_state(NodeState::capabilities),
3655 }
3656 }
3657
3658 pub fn entry_index(&self) -> Option<usize> {
3660 match &self.link {
3661 NodeLink::Entry(path) => Some(path.entry()),
3662 _ => None,
3663 }
3664 }
3665
3666 pub fn delegate_depth(&self) -> usize {
3668 match &self.link {
3669 NodeLink::Entry(path) => path.delegates().len(),
3670 _ => 0,
3671 }
3672 }
3673
3674 #[inline]
3676 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
3677 if let Some(agg) = self.cached_aggregate_child {
3678 return agg;
3679 }
3680 if self.is_tail() {
3681 NodeCapabilities::empty()
3682 } else {
3683 self.with_state(NodeState::aggregate_child_capabilities)
3684 }
3685 }
3686
3687 pub fn is_head(&self) -> bool {
3689 matches!(self.link, NodeLink::Head)
3690 }
3691
3692 pub fn is_tail(&self) -> bool {
3694 matches!(self.link, NodeLink::Tail)
3695 }
3696
3697 pub fn is_sentinel(&self) -> bool {
3699 matches!(self.link, NodeLink::Head | NodeLink::Tail)
3700 }
3701
3702 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
3704 !mask.is_empty() && self.kind_set().intersects(mask)
3705 }
3706
3707 pub fn visit_descendants<F>(self, include_self: bool, mut f: F)
3709 where
3710 F: FnMut(ModifierChainNodeRef<'a>),
3711 {
3712 let mut current = if include_self {
3713 Some(self)
3714 } else {
3715 self.child()
3716 };
3717 while let Some(node) = current {
3718 if node.is_tail() {
3719 break;
3720 }
3721 if !node.is_sentinel() {
3722 f(node.clone());
3723 }
3724 current = node.child();
3725 }
3726 }
3727
3728 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3730 where
3731 F: FnMut(ModifierChainNodeRef<'a>),
3732 {
3733 if mask.is_empty() {
3734 self.visit_descendants(include_self, f);
3735 return;
3736 }
3737
3738 if !self.aggregate_child_capabilities().intersects(mask) {
3739 return;
3740 }
3741
3742 self.visit_descendants(include_self, |node| {
3743 if node.kind_set().intersects(mask) {
3744 f(node);
3745 }
3746 });
3747 }
3748
3749 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
3751 where
3752 F: FnMut(ModifierChainNodeRef<'a>),
3753 {
3754 let mut current = if include_self {
3755 Some(self)
3756 } else {
3757 self.parent()
3758 };
3759 while let Some(node) = current {
3760 if node.is_head() {
3761 break;
3762 }
3763 f(node.clone());
3764 current = node.parent();
3765 }
3766 }
3767
3768 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
3770 where
3771 F: FnMut(ModifierChainNodeRef<'a>),
3772 {
3773 if mask.is_empty() {
3774 self.visit_ancestors(include_self, f);
3775 return;
3776 }
3777
3778 self.visit_ancestors(include_self, |node| {
3779 if node.kind_set().intersects(mask) {
3780 f(node);
3781 }
3782 });
3783 }
3784}
3785
3786#[cfg(test)]
3787#[path = "tests/modifier_tests.rs"]
3788mod tests;