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::{collections::map::HashMap, hash::default};
18pub use cranpose_ui_graphics::{DrawScope, Size};
19pub use cranpose_ui_layout::{Constraints, Measurable};
20
21use crate::nodes::input::types::PointerEvent;
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
26pub enum InvalidationKind {
27 Layout,
28 Draw,
29 PointerInput,
30 Semantics,
31 Focus,
32}
33
34pub trait ModifierNodeContext {
36 fn invalidate(&mut self, _kind: InvalidationKind) {}
38
39 fn request_update(&mut self) {}
42
43 fn node_id(&self) -> Option<cranpose_core::NodeId> {
46 None
47 }
48
49 fn push_active_capabilities(&mut self, _capabilities: NodeCapabilities) {}
51
52 fn pop_active_capabilities(&mut self) {}
54}
55
56#[derive(Default, Debug, Clone)]
65pub struct BasicModifierNodeContext {
66 invalidations: Vec<ModifierInvalidation>,
67 update_requested: bool,
68 active_capabilities: Vec<NodeCapabilities>,
69 node_id: Option<cranpose_core::NodeId>,
70}
71
72impl BasicModifierNodeContext {
73 pub fn new() -> Self {
75 Self::default()
76 }
77
78 pub fn invalidations(&self) -> &[ModifierInvalidation] {
82 &self.invalidations
83 }
84
85 pub fn clear_invalidations(&mut self) {
87 self.invalidations.clear();
88 }
89
90 pub fn take_invalidations(&mut self) -> Vec<ModifierInvalidation> {
92 std::mem::take(&mut self.invalidations)
93 }
94
95 pub fn update_requested(&self) -> bool {
98 self.update_requested
99 }
100
101 pub fn take_update_requested(&mut self) -> bool {
103 std::mem::take(&mut self.update_requested)
104 }
105
106 pub fn set_node_id(&mut self, id: Option<cranpose_core::NodeId>) {
108 self.node_id = id;
109 }
110
111 fn push_invalidation(&mut self, kind: InvalidationKind) {
112 let mut capabilities = self.current_capabilities();
113 capabilities.insert(NodeCapabilities::for_invalidation(kind));
114 if let Some(existing) = self
115 .invalidations
116 .iter_mut()
117 .find(|entry| entry.kind() == kind)
118 {
119 let updated = existing.capabilities() | capabilities;
120 *existing = ModifierInvalidation::new(kind, updated);
121 } else {
122 self.invalidations
123 .push(ModifierInvalidation::new(kind, capabilities));
124 }
125 }
126
127 fn current_capabilities(&self) -> NodeCapabilities {
128 self.active_capabilities
129 .last()
130 .copied()
131 .unwrap_or_else(NodeCapabilities::empty)
132 }
133}
134
135impl ModifierNodeContext for BasicModifierNodeContext {
136 fn invalidate(&mut self, kind: InvalidationKind) {
137 self.push_invalidation(kind);
138 }
139
140 fn request_update(&mut self) {
141 self.update_requested = true;
142 }
143
144 fn push_active_capabilities(&mut self, capabilities: NodeCapabilities) {
145 self.active_capabilities.push(capabilities);
146 }
147
148 fn pop_active_capabilities(&mut self) {
149 self.active_capabilities.pop();
150 }
151
152 fn node_id(&self) -> Option<cranpose_core::NodeId> {
153 self.node_id
154 }
155}
156
157const MAX_DELEGATE_DEPTH: usize = 3;
161
162#[derive(Copy, Clone, Debug, PartialEq, Eq)]
163pub(crate) struct NodePath {
164 entry: usize,
165 delegate_buf: [u8; MAX_DELEGATE_DEPTH],
166 delegate_len: u8,
167}
168
169impl NodePath {
170 #[inline]
171 fn root(entry: usize) -> Self {
172 Self {
173 entry,
174 delegate_buf: [0; MAX_DELEGATE_DEPTH],
175 delegate_len: 0,
176 }
177 }
178
179 #[inline]
180 fn from_slice(entry: usize, path: &[usize]) -> Self {
181 debug_assert!(
182 path.len() <= MAX_DELEGATE_DEPTH,
183 "delegate depth {} exceeds MAX_DELEGATE_DEPTH {}",
184 path.len(),
185 MAX_DELEGATE_DEPTH
186 );
187 debug_assert!(
188 path.iter().all(|&i| i <= u8::MAX as usize),
189 "delegate index exceeds u8 range"
190 );
191 let mut delegate_buf = [0u8; MAX_DELEGATE_DEPTH];
192 for (i, &v) in path.iter().enumerate().take(MAX_DELEGATE_DEPTH) {
193 delegate_buf[i] = v as u8;
194 }
195 Self {
196 entry,
197 delegate_buf,
198 delegate_len: path.len().min(MAX_DELEGATE_DEPTH) as u8,
199 }
200 }
201
202 #[inline]
203 fn entry(&self) -> usize {
204 self.entry
205 }
206
207 #[inline]
208 fn delegates(&self) -> &[u8] {
209 &self.delegate_buf[..self.delegate_len as usize]
210 }
211}
212
213#[derive(Copy, Clone, Debug, PartialEq, Eq)]
214pub(crate) enum NodeLink {
215 Head,
216 Tail,
217 Entry(NodePath),
218}
219
220#[derive(Debug)]
226pub struct NodeState {
227 aggregate_child_capabilities: Cell<NodeCapabilities>,
228 capabilities: Cell<NodeCapabilities>,
229 parent: RefCell<Option<NodeLink>>,
230 child: RefCell<Option<NodeLink>>,
231 attached: Cell<bool>,
232 is_sentinel: bool,
233}
234
235impl Default for NodeState {
236 fn default() -> Self {
237 Self::new()
238 }
239}
240
241impl NodeState {
242 pub const fn new() -> Self {
243 Self {
244 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
245 capabilities: Cell::new(NodeCapabilities::empty()),
246 parent: RefCell::new(None),
247 child: RefCell::new(None),
248 attached: Cell::new(false),
249 is_sentinel: false,
250 }
251 }
252
253 pub const fn sentinel() -> Self {
254 Self {
255 aggregate_child_capabilities: Cell::new(NodeCapabilities::empty()),
256 capabilities: Cell::new(NodeCapabilities::empty()),
257 parent: RefCell::new(None),
258 child: RefCell::new(None),
259 attached: Cell::new(true),
260 is_sentinel: true,
261 }
262 }
263
264 pub fn set_capabilities(&self, capabilities: NodeCapabilities) {
265 self.capabilities.set(capabilities);
266 }
267
268 #[inline]
269 pub fn capabilities(&self) -> NodeCapabilities {
270 self.capabilities.get()
271 }
272
273 pub fn set_aggregate_child_capabilities(&self, capabilities: NodeCapabilities) {
274 self.aggregate_child_capabilities.set(capabilities);
275 }
276
277 #[inline]
278 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
279 self.aggregate_child_capabilities.get()
280 }
281
282 pub(crate) fn set_parent_link(&self, parent: Option<NodeLink>) {
283 *self.parent.borrow_mut() = parent;
284 }
285
286 #[inline]
287 pub(crate) fn parent_link(&self) -> Option<NodeLink> {
288 *self.parent.borrow()
289 }
290
291 pub(crate) fn set_child_link(&self, child: Option<NodeLink>) {
292 *self.child.borrow_mut() = child;
293 }
294
295 #[inline]
296 pub(crate) fn child_link(&self) -> Option<NodeLink> {
297 *self.child.borrow()
298 }
299
300 pub fn set_attached(&self, attached: bool) {
301 self.attached.set(attached);
302 }
303
304 pub fn is_attached(&self) -> bool {
305 self.attached.get()
306 }
307
308 pub fn is_sentinel(&self) -> bool {
309 self.is_sentinel
310 }
311}
312
313pub trait DelegatableNode {
315 fn node_state(&self) -> &NodeState;
316 fn aggregate_child_capabilities(&self) -> NodeCapabilities {
317 self.node_state().aggregate_child_capabilities()
318 }
319}
320
321pub trait ModifierNode: Any + DelegatableNode {
379 fn on_attach(&mut self, _context: &mut dyn ModifierNodeContext) {}
380
381 fn on_detach(&mut self) {}
382
383 fn on_reset(&mut self) {}
384
385 fn as_draw_node(&self) -> Option<&dyn DrawModifierNode> {
387 None
388 }
389
390 fn as_draw_node_mut(&mut self) -> Option<&mut dyn DrawModifierNode> {
392 None
393 }
394
395 fn as_pointer_input_node(&self) -> Option<&dyn PointerInputNode> {
397 None
398 }
399
400 fn as_pointer_input_node_mut(&mut self) -> Option<&mut dyn PointerInputNode> {
402 None
403 }
404
405 fn as_semantics_node(&self) -> Option<&dyn SemanticsNode> {
407 None
408 }
409
410 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn SemanticsNode> {
412 None
413 }
414
415 fn as_focus_node(&self) -> Option<&dyn FocusNode> {
417 None
418 }
419
420 fn as_focus_node_mut(&mut self) -> Option<&mut dyn FocusNode> {
422 None
423 }
424
425 fn as_layout_node(&self) -> Option<&dyn LayoutModifierNode> {
427 None
428 }
429
430 fn as_layout_node_mut(&mut self) -> Option<&mut dyn LayoutModifierNode> {
432 None
433 }
434
435 fn for_each_delegate<'b>(&'b self, _visitor: &mut dyn FnMut(&'b dyn ModifierNode)) {}
437
438 fn for_each_delegate_mut<'b>(&'b mut self, _visitor: &mut dyn FnMut(&'b mut dyn ModifierNode)) {
440 }
441}
442
443pub trait LayoutModifierNode: ModifierNode {
449 fn measure(
471 &self,
472 _context: &mut dyn ModifierNodeContext,
473 measurable: &dyn Measurable,
474 constraints: Constraints,
475 ) -> cranpose_ui_layout::LayoutModifierMeasureResult {
476 let placeable = measurable.measure(constraints);
477 cranpose_ui_layout::LayoutModifierMeasureResult::with_size(Size {
478 width: placeable.width(),
479 height: placeable.height(),
480 })
481 }
482
483 fn min_intrinsic_width(&self, _measurable: &dyn Measurable, _height: f32) -> f32 {
485 0.0
486 }
487
488 fn max_intrinsic_width(&self, _measurable: &dyn Measurable, _height: f32) -> f32 {
490 0.0
491 }
492
493 fn min_intrinsic_height(&self, _measurable: &dyn Measurable, _width: f32) -> f32 {
495 0.0
496 }
497
498 fn max_intrinsic_height(&self, _measurable: &dyn Measurable, _width: f32) -> f32 {
500 0.0
501 }
502}
503
504pub trait DrawModifierNode: ModifierNode {
512 fn draw(&self, _draw_scope: &mut dyn DrawScope) {}
521
522 fn create_draw_closure(&self) -> Option<NodeDrawClosure> {
533 None
534 }
535
536 fn create_behind_draw_closure(&self) -> Option<NodeDrawClosure> {
541 None
542 }
543}
544
545pub type NodeDrawClosure = Rc<dyn Fn(&mut cranpose_ui_graphics::DrawScopeDefault)>;
550
551pub trait PointerInputNode: ModifierNode {
557 fn on_pointer_event(
560 &mut self,
561 _context: &mut dyn ModifierNodeContext,
562 _event: &PointerEvent,
563 ) -> bool {
564 false
565 }
566
567 fn hit_test(&self, _x: f32, _y: f32) -> bool {
570 true
571 }
572
573 fn pointer_input_handler(&self) -> Option<Rc<dyn Fn(PointerEvent)>> {
575 None
576 }
577
578 fn layout_size_sink(&self) -> Option<Rc<Cell<Size>>> {
591 None
592 }
593}
594
595pub trait SemanticsNode: ModifierNode {
601 fn merge_semantics(&self, _config: &mut SemanticsConfiguration) {}
603}
604
605#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
610pub enum FocusState {
611 Active,
613 ActiveParent,
615 Captured,
619 #[default]
622 Inactive,
623}
624
625impl FocusState {
626 pub fn is_focused(self) -> bool {
628 matches!(self, FocusState::Active | FocusState::Captured)
629 }
630
631 pub fn has_focus(self) -> bool {
633 matches!(
634 self,
635 FocusState::Active | FocusState::ActiveParent | FocusState::Captured
636 )
637 }
638
639 pub fn is_captured(self) -> bool {
641 matches!(self, FocusState::Captured)
642 }
643}
644
645pub trait FocusNode: ModifierNode {
650 fn focus_state(&self) -> FocusState;
652
653 fn on_focus_changed(&mut self, _context: &mut dyn ModifierNodeContext, _state: FocusState) {}
655}
656
657#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
668pub enum SemanticsWidgetRole {
669 Button,
670 Checkbox,
671 Switch,
672 RadioButton,
673 Tab,
674 Image,
675 Header,
680 Dialog,
684}
685
686#[derive(Clone, Copy, Debug, PartialEq)]
694pub struct ProgressBarRangeInfo {
695 pub current: f32,
696 pub start: f32,
697 pub end: f32,
698 pub steps: u32,
701}
702
703impl ProgressBarRangeInfo {
704 pub fn new(current: f32, start: f32, end: f32, steps: u32) -> Self {
705 Self {
706 current,
707 start,
708 end,
709 steps,
710 }
711 }
712
713 pub fn fraction(&self) -> f32 {
715 let span = self.end - self.start;
716 if span.abs() < f32::EPSILON {
717 return 0.0;
718 }
719 ((self.current - self.start) / span).clamp(0.0, 1.0)
720 }
721
722 pub fn step(&self) -> f32 {
725 let span = self.end - self.start;
726 if self.steps == 0 {
727 span / 10.0
728 } else {
729 span / (self.steps as f32 + 1.0)
730 }
731 }
732}
733
734#[derive(Clone, Copy, Debug, PartialEq, Eq)]
739pub struct CollectionInfo {
740 pub rows: usize,
741 pub columns: usize,
742}
743
744#[derive(Clone, Copy, Debug, PartialEq)]
750pub struct ScrollAxisRange {
751 pub value: f32,
752 pub max_value: f32,
753 pub reverse: bool,
754}
755
756impl ScrollAxisRange {
757 pub fn new(value: f32, max_value: f32, reverse: bool) -> Self {
758 Self {
759 value,
760 max_value,
761 reverse,
762 }
763 }
764
765 pub fn can_scroll_forward(&self) -> bool {
766 self.value < self.max_value
767 }
768
769 pub fn can_scroll_backward(&self) -> bool {
770 self.value > 0.0
771 }
772}
773
774#[derive(Clone)]
780pub struct SemanticsScrollBy {
781 handler: Rc<dyn Fn(f32, f32) -> bool>,
782}
783
784impl SemanticsScrollBy {
785 pub fn new(handler: impl Fn(f32, f32) -> bool + 'static) -> Self {
786 Self {
787 handler: Rc::new(handler),
788 }
789 }
790
791 pub fn invoke(&self, dx: f32, dy: f32) -> bool {
792 (self.handler)(dx, dy)
793 }
794}
795
796impl fmt::Debug for SemanticsScrollBy {
797 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
798 f.debug_struct("SemanticsScrollBy").finish_non_exhaustive()
799 }
800}
801
802impl PartialEq for SemanticsScrollBy {
805 fn eq(&self, _other: &Self) -> bool {
806 true
807 }
808}
809
810impl Eq for SemanticsScrollBy {}
811
812#[derive(Clone)]
818pub struct SemanticsSetProgress {
819 handler: Rc<dyn Fn(f32) -> bool>,
820}
821
822impl SemanticsSetProgress {
823 pub fn new(handler: impl Fn(f32) -> bool + 'static) -> Self {
824 Self {
825 handler: Rc::new(handler),
826 }
827 }
828
829 pub fn invoke(&self, value: f32) -> bool {
830 (self.handler)(value)
831 }
832}
833
834impl fmt::Debug for SemanticsSetProgress {
835 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
836 f.debug_struct("SemanticsSetProgress")
837 .finish_non_exhaustive()
838 }
839}
840
841#[derive(Clone)]
845pub struct SemanticsSetText(Rc<dyn Fn(&str) -> bool>);
846
847impl SemanticsSetText {
848 pub fn new(handler: impl Fn(&str) -> bool + 'static) -> Self {
849 Self(Rc::new(handler))
850 }
851
852 pub fn invoke(&self, text: &str) -> bool {
853 (self.0)(text)
854 }
855}
856
857impl fmt::Debug for SemanticsSetText {
858 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
859 f.write_str("SemanticsSetText")
860 }
861}
862
863impl PartialEq for SemanticsSetText {
864 fn eq(&self, _other: &Self) -> bool {
865 true
866 }
867}
868
869impl PartialEq for SemanticsSetProgress {
874 fn eq(&self, _other: &Self) -> bool {
875 true
876 }
877}
878
879impl Eq for SemanticsSetProgress {}
880
881#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
888pub enum LiveRegionMode {
889 Polite,
891 Assertive,
894}
895
896#[derive(Clone)]
903pub struct SemanticsCustomAction {
904 pub label: String,
906 handler: Rc<dyn Fn()>,
907}
908
909impl SemanticsCustomAction {
910 pub fn new(label: impl Into<String>, handler: impl Fn() + 'static) -> Self {
911 Self {
912 label: label.into(),
913 handler: Rc::new(handler),
914 }
915 }
916
917 pub fn invoke(&self) {
918 (self.handler)();
919 }
920}
921
922impl fmt::Debug for SemanticsCustomAction {
923 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
924 f.debug_struct("SemanticsCustomAction")
925 .field("label", &self.label)
926 .finish_non_exhaustive()
927 }
928}
929
930impl PartialEq for SemanticsCustomAction {
940 fn eq(&self, other: &Self) -> bool {
941 self.label == other.label
942 }
943}
944
945impl Eq for SemanticsCustomAction {}
946
947#[derive(Clone, Debug, PartialEq)]
962pub struct CanvasSemanticsNode {
963 pub key: u64,
970 pub bounds: cranpose_ui_graphics::Rect,
972 pub label: String,
973 pub role: Option<SemanticsWidgetRole>,
974 pub state_description: Option<String>,
978 pub on_click_label: Option<String>,
981 pub clickable: bool,
982 pub selected: Option<bool>,
984 pub toggled: Option<bool>,
986 pub enabled: bool,
987 pub custom_actions: Vec<SemanticsCustomAction>,
988}
989
990impl Default for CanvasSemanticsNode {
991 fn default() -> Self {
992 Self {
993 key: 0,
994 bounds: cranpose_ui_graphics::Rect {
995 x: 0.0,
996 y: 0.0,
997 width: 0.0,
998 height: 0.0,
999 },
1000 label: String::new(),
1001 role: None,
1002 state_description: None,
1003 on_click_label: None,
1004 clickable: false,
1005 selected: None,
1006 toggled: None,
1007 enabled: true,
1008 custom_actions: Vec::new(),
1009 }
1010 }
1011}
1012
1013impl CanvasSemanticsNode {
1014 pub fn control(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1016 Self {
1017 key,
1018 bounds,
1019 label: label.into(),
1020 clickable: true,
1021 ..Self::default()
1022 }
1023 }
1024
1025 pub fn text(key: u64, bounds: cranpose_ui_graphics::Rect, label: impl Into<String>) -> Self {
1027 Self {
1028 key,
1029 bounds,
1030 label: label.into(),
1031 ..Self::default()
1032 }
1033 }
1034
1035 pub fn with_role(mut self, role: SemanticsWidgetRole) -> Self {
1036 self.role = Some(role);
1037 self
1038 }
1039
1040 pub fn with_state_description(mut self, state: impl Into<String>) -> Self {
1041 self.state_description = Some(state.into());
1042 self
1043 }
1044
1045 pub fn with_click_label(mut self, label: impl Into<String>) -> Self {
1046 self.on_click_label = Some(label.into());
1047 self.clickable = true;
1048 self
1049 }
1050
1051 pub fn with_selected(mut self, selected: bool) -> Self {
1052 self.selected = Some(selected);
1053 self
1054 }
1055
1056 pub fn with_toggled(mut self, toggled: bool) -> Self {
1057 self.toggled = Some(toggled);
1058 self
1059 }
1060
1061 pub fn with_enabled(mut self, enabled: bool) -> Self {
1062 self.enabled = enabled;
1063 self
1064 }
1065
1066 pub fn with_custom_action(mut self, action: SemanticsCustomAction) -> Self {
1067 self.custom_actions.push(action);
1068 self
1069 }
1070}
1071
1072#[derive(Clone, Debug, PartialEq)]
1074pub struct SemanticsConfiguration {
1075 pub content_description: Option<String>,
1076 pub state_description: Option<String>,
1078 pub on_click_label: Option<String>,
1080 pub role: Option<SemanticsWidgetRole>,
1082 pub selected: Option<bool>,
1083 pub toggled: Option<bool>,
1084 pub enabled: bool,
1085 pub is_clickable: bool,
1086 pub is_editable_text: bool,
1087 pub text: Option<String>,
1090 pub text_selection: Option<crate::text::TextRange>,
1091 pub custom_actions: Vec<SemanticsCustomAction>,
1092 pub canvas_children: Vec<CanvasSemanticsNode>,
1095 pub is_modal: bool,
1098 pub hidden: bool,
1102 pub merge_descendants: bool,
1106 pub selectable_group: bool,
1110 pub pane_title: Option<String>,
1113 pub live_region: Option<LiveRegionMode>,
1116 pub progress: Option<ProgressBarRangeInfo>,
1119 pub set_progress: Option<SemanticsSetProgress>,
1122 pub set_text: Option<SemanticsSetText>,
1125 pub vertical_scroll: Option<ScrollAxisRange>,
1128 pub horizontal_scroll: Option<ScrollAxisRange>,
1131 pub scroll_by: Option<SemanticsScrollBy>,
1134 pub collection: Option<CollectionInfo>,
1136}
1137
1138impl Default for SemanticsConfiguration {
1139 fn default() -> Self {
1140 Self {
1141 content_description: None,
1142 state_description: None,
1143 on_click_label: None,
1144 role: None,
1145 selected: None,
1146 toggled: None,
1147 enabled: true,
1148 is_clickable: false,
1149 is_editable_text: false,
1150 text: None,
1151 text_selection: None,
1152 custom_actions: Vec::new(),
1153 canvas_children: Vec::new(),
1154 is_modal: false,
1155 hidden: false,
1156 merge_descendants: false,
1157 selectable_group: false,
1158 pane_title: None,
1159 live_region: None,
1160 progress: None,
1161 set_progress: None,
1162 set_text: None,
1163 vertical_scroll: None,
1164 horizontal_scroll: None,
1165 scroll_by: None,
1166 collection: None,
1167 }
1168 }
1169}
1170
1171impl SemanticsConfiguration {
1172 pub fn merge(&mut self, other: &SemanticsConfiguration) {
1173 if let Some(description) = &other.content_description {
1174 self.content_description = Some(description.clone());
1175 }
1176 if let Some(state) = &other.state_description {
1177 self.state_description = Some(state.clone());
1178 }
1179 if let Some(label) = &other.on_click_label {
1180 self.on_click_label = Some(label.clone());
1181 }
1182 if let Some(role) = other.role {
1183 self.role = Some(role);
1184 }
1185 if let Some(selected) = other.selected {
1186 self.selected = Some(selected);
1187 }
1188 if let Some(toggled) = other.toggled {
1189 self.toggled = Some(toggled);
1190 }
1191 self.enabled &= other.enabled;
1192 self.is_clickable |= other.is_clickable;
1193 self.is_editable_text |= other.is_editable_text;
1194 if let Some(text) = &other.text {
1195 self.text = Some(text.clone());
1196 }
1197 if let Some(selection) = other.text_selection {
1198 self.text_selection = Some(selection);
1199 }
1200 self.custom_actions
1201 .extend(other.custom_actions.iter().cloned());
1202 self.canvas_children
1203 .extend(other.canvas_children.iter().cloned());
1204 self.is_modal |= other.is_modal;
1205 self.hidden |= other.hidden;
1206 self.merge_descendants |= other.merge_descendants;
1207 self.selectable_group |= other.selectable_group;
1208 if let Some(title) = &other.pane_title {
1209 self.pane_title = Some(title.clone());
1210 }
1211 if let Some(live_region) = other.live_region {
1212 self.live_region = Some(live_region);
1213 }
1214 if let Some(set_progress) = &other.set_progress {
1215 self.set_progress = Some(set_progress.clone());
1216 }
1217 if let Some(set_text) = &other.set_text {
1218 self.set_text = Some(set_text.clone());
1219 }
1220 if let Some(progress) = other.progress {
1221 self.progress = Some(progress);
1222 }
1223 if let Some(range) = other.vertical_scroll {
1224 self.vertical_scroll = Some(range);
1225 }
1226 if let Some(range) = other.horizontal_scroll {
1227 self.horizontal_scroll = Some(range);
1228 }
1229 if let Some(scroll_by) = &other.scroll_by {
1230 self.scroll_by = Some(scroll_by.clone());
1231 }
1232 if let Some(collection) = other.collection {
1233 self.collection = Some(collection);
1234 }
1235 }
1236
1237 pub fn is_activatable(&self) -> bool {
1240 self.is_clickable || self.on_click_label.is_some()
1241 }
1242}
1243
1244impl fmt::Debug for dyn ModifierNode {
1245 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1246 f.debug_struct("ModifierNode").finish_non_exhaustive()
1247 }
1248}
1249
1250impl dyn ModifierNode {
1251 pub fn as_any(&self) -> &dyn Any {
1252 self
1253 }
1254
1255 pub fn as_any_mut(&mut self) -> &mut dyn Any {
1256 self
1257 }
1258}
1259
1260pub trait ModifierNodeElement: fmt::Debug + Hash + PartialEq + 'static {
1263 type Node: ModifierNode;
1264
1265 fn create(&self) -> Self::Node;
1267
1268 fn update(&self, node: &mut Self::Node);
1270
1271 fn key(&self) -> Option<u64> {
1273 None
1274 }
1275
1276 fn inspector_name(&self) -> &'static str {
1278 type_name::<Self>()
1279 }
1280
1281 fn inspector_properties(&self, _inspector: &mut dyn FnMut(&'static str, String)) {}
1283
1284 fn capabilities(&self) -> NodeCapabilities {
1287 NodeCapabilities::default()
1288 }
1289
1290 fn always_update(&self) -> bool {
1296 false
1297 }
1298
1299 fn auto_invalidate_on_update(&self) -> bool {
1302 true
1303 }
1304
1305 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
1312 None
1313 }
1314}
1315
1316#[derive(Clone, Copy, PartialEq, Eq, Hash)]
1318pub struct NodeCapabilities(u32);
1319
1320impl NodeCapabilities {
1321 pub const NONE: Self = Self(0);
1323 pub const LAYOUT: Self = Self(1 << 0);
1325 pub const DRAW: Self = Self(1 << 1);
1327 pub const POINTER_INPUT: Self = Self(1 << 2);
1329 pub const SEMANTICS: Self = Self(1 << 3);
1331 pub const MODIFIER_LOCALS: Self = Self(1 << 4);
1333 pub const FOCUS: Self = Self(1 << 5);
1335
1336 pub const fn empty() -> Self {
1338 Self::NONE
1339 }
1340
1341 pub const fn contains(self, other: Self) -> bool {
1343 (self.0 & other.0) == other.0
1344 }
1345
1346 pub const fn intersects(self, other: Self) -> bool {
1348 (self.0 & other.0) != 0
1349 }
1350
1351 pub fn insert(&mut self, other: Self) {
1353 self.0 |= other.0;
1354 }
1355
1356 pub const fn bits(self) -> u32 {
1358 self.0
1359 }
1360
1361 pub const fn is_empty(self) -> bool {
1363 self.0 == 0
1364 }
1365
1366 pub const fn for_invalidation(kind: InvalidationKind) -> Self {
1368 match kind {
1369 InvalidationKind::Layout => Self::LAYOUT,
1370 InvalidationKind::Draw => Self::DRAW,
1371 InvalidationKind::PointerInput => Self::POINTER_INPUT,
1372 InvalidationKind::Semantics => Self::SEMANTICS,
1373 InvalidationKind::Focus => Self::FOCUS,
1374 }
1375 }
1376}
1377
1378impl Default for NodeCapabilities {
1379 fn default() -> Self {
1380 Self::NONE
1381 }
1382}
1383
1384impl fmt::Debug for NodeCapabilities {
1385 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1386 f.debug_struct("NodeCapabilities")
1387 .field("layout", &self.contains(Self::LAYOUT))
1388 .field("draw", &self.contains(Self::DRAW))
1389 .field("pointer_input", &self.contains(Self::POINTER_INPUT))
1390 .field("semantics", &self.contains(Self::SEMANTICS))
1391 .field("modifier_locals", &self.contains(Self::MODIFIER_LOCALS))
1392 .field("focus", &self.contains(Self::FOCUS))
1393 .finish()
1394 }
1395}
1396
1397impl BitOr for NodeCapabilities {
1398 type Output = Self;
1399
1400 fn bitor(self, rhs: Self) -> Self::Output {
1401 Self(self.0 | rhs.0)
1402 }
1403}
1404
1405impl BitOrAssign for NodeCapabilities {
1406 fn bitor_assign(&mut self, rhs: Self) {
1407 self.0 |= rhs.0;
1408 }
1409}
1410
1411#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1413pub struct ModifierInvalidation {
1414 kind: InvalidationKind,
1415 capabilities: NodeCapabilities,
1416}
1417
1418impl ModifierInvalidation {
1419 pub const fn new(kind: InvalidationKind, capabilities: NodeCapabilities) -> Self {
1421 Self { kind, capabilities }
1422 }
1423
1424 pub const fn kind(self) -> InvalidationKind {
1426 self.kind
1427 }
1428
1429 pub const fn capabilities(self) -> NodeCapabilities {
1431 self.capabilities
1432 }
1433}
1434
1435pub trait AnyModifierElement: fmt::Debug {
1437 fn node_type(&self) -> TypeId;
1438
1439 fn element_type(&self) -> TypeId;
1440
1441 fn create_node(&self) -> Box<dyn ModifierNode>;
1442
1443 fn can_update_node(&self, node: &dyn ModifierNode) -> bool;
1444
1445 fn update_node(&self, node: &mut dyn ModifierNode);
1446
1447 fn key(&self) -> Option<u64>;
1448
1449 fn capabilities(&self) -> NodeCapabilities {
1450 NodeCapabilities::default()
1451 }
1452
1453 fn hash_code(&self) -> u64;
1454
1455 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool;
1456
1457 fn inspector_name(&self) -> &'static str;
1458
1459 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String));
1460
1461 fn requires_update(&self) -> bool;
1462
1463 fn auto_invalidates_on_update(&self) -> bool;
1464
1465 fn update_invalidation_kind(&self) -> Option<InvalidationKind>;
1466
1467 fn as_any(&self) -> &dyn Any;
1468}
1469
1470struct TypedModifierElement<E: ModifierNodeElement> {
1471 element: E,
1472 cached_hash: u64,
1473}
1474
1475impl<E: ModifierNodeElement> TypedModifierElement<E> {
1476 fn new(element: E) -> Self {
1477 let mut hasher = default::new();
1478 element.hash(&mut hasher);
1479 Self {
1480 element,
1481 cached_hash: hasher.finish(),
1482 }
1483 }
1484}
1485
1486impl<E> fmt::Debug for TypedModifierElement<E>
1487where
1488 E: ModifierNodeElement,
1489{
1490 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1491 f.debug_struct("TypedModifierElement")
1492 .field("type", &type_name::<E>())
1493 .finish()
1494 }
1495}
1496
1497impl<E> AnyModifierElement for TypedModifierElement<E>
1498where
1499 E: ModifierNodeElement,
1500{
1501 fn node_type(&self) -> TypeId {
1502 TypeId::of::<E::Node>()
1503 }
1504
1505 fn element_type(&self) -> TypeId {
1506 TypeId::of::<E>()
1507 }
1508
1509 fn create_node(&self) -> Box<dyn ModifierNode> {
1510 Box::new(self.element.create())
1511 }
1512
1513 fn can_update_node(&self, node: &dyn ModifierNode) -> bool {
1514 node.as_any().is::<E::Node>()
1515 }
1516
1517 fn update_node(&self, node: &mut dyn ModifierNode) {
1518 if let Some(typed) = node.as_any_mut().downcast_mut::<E::Node>() {
1519 self.element.update(typed);
1520 }
1521 }
1522
1523 fn key(&self) -> Option<u64> {
1524 self.element.key()
1525 }
1526
1527 fn capabilities(&self) -> NodeCapabilities {
1528 self.element.capabilities()
1529 }
1530
1531 fn hash_code(&self) -> u64 {
1532 self.cached_hash
1533 }
1534
1535 fn equals_element(&self, other: &dyn AnyModifierElement) -> bool {
1536 other
1537 .as_any()
1538 .downcast_ref::<Self>()
1539 .map(|typed| typed.element == self.element)
1540 .unwrap_or(false)
1541 }
1542
1543 fn inspector_name(&self) -> &'static str {
1544 self.element.inspector_name()
1545 }
1546
1547 fn record_inspector_properties(&self, visitor: &mut dyn FnMut(&'static str, String)) {
1548 self.element.inspector_properties(visitor);
1549 }
1550
1551 fn requires_update(&self) -> bool {
1552 self.element.always_update()
1553 }
1554
1555 fn auto_invalidates_on_update(&self) -> bool {
1556 self.element.auto_invalidate_on_update()
1557 }
1558
1559 fn update_invalidation_kind(&self) -> Option<InvalidationKind> {
1560 self.element.update_invalidation_kind()
1561 }
1562
1563 fn as_any(&self) -> &dyn Any {
1564 self
1565 }
1566}
1567
1568fn request_update_auto_invalidations(
1569 element: &dyn AnyModifierElement,
1570 context: &mut dyn ModifierNodeContext,
1571 capabilities: NodeCapabilities,
1572) {
1573 if let Some(kind) = element.update_invalidation_kind() {
1574 let capabilities = NodeCapabilities::for_invalidation(kind);
1575 context.push_active_capabilities(capabilities);
1576 context.invalidate(kind);
1577 context.pop_active_capabilities();
1578 } else if element.auto_invalidates_on_update() {
1579 request_auto_invalidations(context, capabilities);
1580 }
1581}
1582
1583pub fn modifier_element<E: ModifierNodeElement>(element: E) -> DynModifierElement {
1586 Rc::new(TypedModifierElement::new(element))
1587}
1588
1589pub type DynModifierElement = Rc<dyn AnyModifierElement>;
1591
1592#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1593enum TraversalDirection {
1594 Forward,
1595 Backward,
1596}
1597
1598pub struct ModifierChainIter<'a> {
1603 chain: &'a ModifierNodeChain,
1604 cursor: usize,
1605 remaining: usize,
1606 direction: TraversalDirection,
1607}
1608
1609impl<'a> ModifierChainIter<'a> {
1610 fn forward(chain: &'a ModifierNodeChain) -> Self {
1611 Self {
1612 chain,
1613 cursor: 0,
1614 remaining: chain.ordered_nodes.len(),
1615 direction: TraversalDirection::Forward,
1616 }
1617 }
1618
1619 fn backward(chain: &'a ModifierNodeChain) -> Self {
1620 let len = chain.ordered_nodes.len();
1621 Self {
1622 chain,
1623 cursor: len.wrapping_sub(1),
1624 remaining: len,
1625 direction: TraversalDirection::Backward,
1626 }
1627 }
1628}
1629
1630impl<'a> Iterator for ModifierChainIter<'a> {
1631 type Item = ModifierChainNodeRef<'a>;
1632
1633 #[inline]
1634 fn next(&mut self) -> Option<Self::Item> {
1635 if self.remaining == 0 {
1636 return None;
1637 }
1638 let (link, caps, agg) = self.chain.ordered_nodes[self.cursor];
1639 let node_ref = self.chain.make_node_ref_with_caps(link, caps, agg);
1640 self.remaining -= 1;
1641 match self.direction {
1642 TraversalDirection::Forward => self.cursor += 1,
1643 TraversalDirection::Backward => self.cursor = self.cursor.wrapping_sub(1),
1644 }
1645 Some(node_ref)
1646 }
1647
1648 #[inline]
1649 fn size_hint(&self) -> (usize, Option<usize>) {
1650 (self.remaining, Some(self.remaining))
1651 }
1652}
1653
1654impl<'a> ExactSizeIterator for ModifierChainIter<'a> {}
1655impl<'a> std::iter::FusedIterator for ModifierChainIter<'a> {}
1656
1657#[derive(Debug)]
1658struct ModifierNodeEntry {
1659 element_type: TypeId,
1660 node_type: TypeId,
1661 key: Option<u64>,
1662 hash_code: u64,
1663 element: DynModifierElement,
1664 node: Rc<RefCell<Box<dyn ModifierNode>>>,
1665 capabilities: NodeCapabilities,
1666}
1667
1668impl ModifierNodeEntry {
1669 fn new(
1670 element_type: TypeId,
1671 node_type: TypeId,
1672 key: Option<u64>,
1673 element: DynModifierElement,
1674 node: Box<dyn ModifierNode>,
1675 hash_code: u64,
1676 capabilities: NodeCapabilities,
1677 ) -> Self {
1678 let node_rc = Rc::new(RefCell::new(node));
1679 let entry = Self {
1680 element_type,
1681 node_type,
1682 key,
1683 hash_code,
1684 element,
1685 node: Rc::clone(&node_rc),
1686 capabilities,
1687 };
1688 entry
1689 .node
1690 .borrow()
1691 .node_state()
1692 .set_capabilities(entry.capabilities);
1693 entry
1694 }
1695}
1696
1697fn visit_node_tree_mut(
1698 node: &mut dyn ModifierNode,
1699 visitor: &mut dyn FnMut(&mut dyn ModifierNode),
1700) {
1701 visitor(node);
1702 node.for_each_delegate_mut(&mut |child| visit_node_tree_mut(child, visitor));
1703}
1704
1705fn nth_delegate(node: &dyn ModifierNode, target: usize) -> Option<&dyn ModifierNode> {
1706 let mut current = 0usize;
1707 let mut result: Option<&dyn ModifierNode> = None;
1708 node.for_each_delegate(&mut |child| {
1709 if result.is_none() && current == target {
1710 result = Some(child);
1711 }
1712 current += 1;
1713 });
1714 result
1715}
1716
1717fn nth_delegate_mut(node: &mut dyn ModifierNode, target: usize) -> Option<&mut dyn ModifierNode> {
1718 let mut current = 0usize;
1719 let mut result: Option<&mut dyn ModifierNode> = None;
1720 node.for_each_delegate_mut(&mut |child| {
1721 if result.is_none() && current == target {
1722 result = Some(child);
1723 }
1724 current += 1;
1725 });
1726 result
1727}
1728
1729fn with_node_context<F, R>(
1730 node: &mut dyn ModifierNode,
1731 context: &mut dyn ModifierNodeContext,
1732 f: F,
1733) -> R
1734where
1735 F: FnOnce(&mut dyn ModifierNode, &mut dyn ModifierNodeContext) -> R,
1736{
1737 context.push_active_capabilities(node.node_state().capabilities());
1738 let result = f(node, context);
1739 context.pop_active_capabilities();
1740 result
1741}
1742
1743fn request_auto_invalidations(
1744 context: &mut dyn ModifierNodeContext,
1745 capabilities: NodeCapabilities,
1746) {
1747 if capabilities.is_empty() {
1748 return;
1749 }
1750
1751 context.push_active_capabilities(capabilities);
1752
1753 if capabilities.contains(NodeCapabilities::LAYOUT) {
1754 context.invalidate(InvalidationKind::Layout);
1755 }
1756 if capabilities.contains(NodeCapabilities::DRAW) {
1757 context.invalidate(InvalidationKind::Draw);
1758 }
1759 if capabilities.contains(NodeCapabilities::POINTER_INPUT) {
1760 context.invalidate(InvalidationKind::PointerInput);
1761 }
1762 if capabilities.contains(NodeCapabilities::SEMANTICS) {
1763 context.invalidate(InvalidationKind::Semantics);
1764 }
1765 if capabilities.contains(NodeCapabilities::FOCUS) {
1766 context.invalidate(InvalidationKind::Focus);
1767 }
1768
1769 context.pop_active_capabilities();
1770}
1771
1772fn attach_node_tree(node: &mut dyn ModifierNode, context: &mut dyn ModifierNodeContext) {
1780 visit_node_tree_mut(node, &mut |n| {
1781 if !n.node_state().is_attached() {
1782 n.node_state().set_attached(true);
1783 with_node_context(n, context, |node, ctx| node.on_attach(ctx));
1784 }
1785 });
1786}
1787
1788fn reset_node_tree(node: &mut dyn ModifierNode) {
1789 visit_node_tree_mut(node, &mut |n| n.on_reset());
1790}
1791
1792fn detach_node_tree(node: &mut dyn ModifierNode) {
1793 visit_node_tree_mut(node, &mut |n| {
1794 if n.node_state().is_attached() {
1795 n.on_detach();
1796 n.node_state().set_attached(false);
1797 }
1798 n.node_state().set_parent_link(None);
1799 n.node_state().set_child_link(None);
1800 n.node_state()
1801 .set_aggregate_child_capabilities(NodeCapabilities::empty());
1802 });
1803}
1804
1805pub struct ModifierNodeChain {
1812 entries: Vec<ModifierNodeEntry>,
1813 aggregated_capabilities: NodeCapabilities,
1814 head_aggregate_child_capabilities: NodeCapabilities,
1815 head_sentinel: Box<SentinelNode>,
1816 tail_sentinel: Box<SentinelNode>,
1817 ordered_nodes: Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
1818 scratch_old_used: Vec<bool>,
1819 scratch_match_order: Vec<Option<usize>>,
1820 scratch_final_slots: Vec<Option<ModifierNodeEntry>>,
1821 scratch_elements: Vec<DynModifierElement>,
1822}
1823
1824struct SentinelNode {
1825 state: NodeState,
1826}
1827
1828impl SentinelNode {
1829 fn new() -> Self {
1830 Self {
1831 state: NodeState::sentinel(),
1832 }
1833 }
1834}
1835
1836impl DelegatableNode for SentinelNode {
1837 fn node_state(&self) -> &NodeState {
1838 &self.state
1839 }
1840}
1841
1842impl ModifierNode for SentinelNode {}
1843
1844#[derive(Clone)]
1845pub struct ModifierChainNodeRef<'a> {
1846 chain: &'a ModifierNodeChain,
1847 link: NodeLink,
1848 cached_capabilities: Option<NodeCapabilities>,
1849 cached_aggregate_child: Option<NodeCapabilities>,
1850}
1851
1852impl Default for ModifierNodeChain {
1853 fn default() -> Self {
1854 Self::new()
1855 }
1856}
1857
1858struct EntryIndex {
1863 keyed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
1864 hashed: HashMap<(TypeId, TypeId, u64), Vec<usize>>,
1865 typed: HashMap<(TypeId, TypeId), Vec<usize>>,
1866}
1867
1868struct EntryMatchQuery<'a> {
1869 element_type: TypeId,
1870 node_type: TypeId,
1871 key: Option<u64>,
1872 hash_code: u64,
1873 element: &'a DynModifierElement,
1874}
1875
1876impl EntryIndex {
1877 fn build(entries: &[ModifierNodeEntry]) -> Self {
1878 let mut keyed = HashMap::default();
1879 let mut hashed = HashMap::default();
1880 let mut typed = HashMap::default();
1881
1882 for (i, entry) in entries.iter().enumerate() {
1883 if let Some(key_value) = entry.key {
1884 keyed
1885 .entry((entry.element_type, entry.node_type, key_value))
1886 .or_insert_with(Vec::new)
1887 .push(i);
1888 } else {
1889 hashed
1890 .entry((entry.element_type, entry.node_type, entry.hash_code))
1891 .or_insert_with(Vec::new)
1892 .push(i);
1893 typed
1894 .entry((entry.element_type, entry.node_type))
1895 .or_insert_with(Vec::new)
1896 .push(i);
1897 }
1898 }
1899
1900 Self {
1901 keyed,
1902 hashed,
1903 typed,
1904 }
1905 }
1906
1907 fn find_match(
1908 &self,
1909 entries: &[ModifierNodeEntry],
1910 used: &[bool],
1911 query: EntryMatchQuery<'_>,
1912 ) -> Option<usize> {
1913 if let Some(key_value) = query.key {
1914 if let Some(candidates) =
1915 self.keyed
1916 .get(&(query.element_type, query.node_type, key_value))
1917 {
1918 for &i in candidates {
1919 if !used[i] {
1920 return Some(i);
1921 }
1922 }
1923 }
1924 } else {
1925 if let Some(candidates) =
1926 self.hashed
1927 .get(&(query.element_type, query.node_type, query.hash_code))
1928 {
1929 for &i in candidates {
1930 if !used[i]
1931 && entries[i]
1932 .element
1933 .as_ref()
1934 .equals_element(query.element.as_ref())
1935 {
1936 return Some(i);
1937 }
1938 }
1939 }
1940
1941 if let Some(candidates) = self.typed.get(&(query.element_type, query.node_type)) {
1942 for &i in candidates {
1943 if !used[i] {
1944 return Some(i);
1945 }
1946 }
1947 }
1948 }
1949
1950 None
1951 }
1952}
1953
1954impl ModifierNodeChain {
1955 pub fn new() -> Self {
1956 let mut chain = Self {
1957 entries: Vec::new(),
1958 aggregated_capabilities: NodeCapabilities::empty(),
1959 head_aggregate_child_capabilities: NodeCapabilities::empty(),
1960 head_sentinel: Box::new(SentinelNode::new()),
1961 tail_sentinel: Box::new(SentinelNode::new()),
1962 ordered_nodes: Vec::new(),
1963 scratch_old_used: Vec::new(),
1964 scratch_match_order: Vec::new(),
1965 scratch_final_slots: Vec::new(),
1966 scratch_elements: Vec::new(),
1967 };
1968 chain.sync_chain_links();
1969 chain
1970 }
1971
1972 pub fn detach_nodes(&mut self) {
1974 for entry in &self.entries {
1975 detach_node_tree(&mut **entry.node.borrow_mut());
1976 }
1977 }
1978
1979 pub fn attach_nodes(&mut self, context: &mut dyn ModifierNodeContext) {
1981 for entry in &self.entries {
1982 attach_node_tree(&mut **entry.node.borrow_mut(), context);
1983 }
1984 }
1985
1986 pub fn repair_chain(&mut self) {
1989 self.sync_chain_links();
1990 }
1991
1992 pub fn update_from_slice(
1998 &mut self,
1999 elements: &[DynModifierElement],
2000 context: &mut dyn ModifierNodeContext,
2001 ) {
2002 self.update_from_ref_iter(elements.iter(), context);
2003 }
2004
2005 pub fn update_from_ref_iter<'a, I>(
2010 &mut self,
2011 elements: I,
2012 context: &mut dyn ModifierNodeContext,
2013 ) where
2014 I: Iterator<Item = &'a DynModifierElement>,
2015 {
2016 let old_len = self.entries.len();
2017 let mut fast_path_failed_at: Option<usize> = None;
2018 let mut elements_count = 0;
2019
2020 self.scratch_elements.clear();
2021
2022 for (idx, element) in elements.enumerate() {
2023 elements_count = idx + 1;
2024
2025 if fast_path_failed_at.is_none() && idx < old_len {
2026 let entry = &mut self.entries[idx];
2027 let same_type = entry.element_type == element.element_type();
2028 let same_node_type = entry.node_type == element.node_type();
2029 let same_key = entry.key == element.key();
2030 let same_hash = entry.hash_code == element.hash_code();
2031
2032 let positional_update = element.requires_update();
2033 if same_type && same_node_type && same_key && (same_hash || positional_update) {
2034 let can_update_node = {
2035 let node_borrow = entry.node.borrow();
2036 element.can_update_node(&**node_borrow)
2037 };
2038 if !can_update_node {
2039 fast_path_failed_at = Some(idx);
2040 self.scratch_elements.push(element.clone());
2041 continue;
2042 }
2043
2044 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2045 let capabilities = element.capabilities();
2046
2047 {
2048 let node_borrow = entry.node.borrow();
2049 if !node_borrow.node_state().is_attached() {
2050 drop(node_borrow);
2051 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2052 }
2053 }
2054
2055 let needs_update = !same_element || element.requires_update();
2056 if needs_update {
2057 element.update_node(&mut **entry.node.borrow_mut());
2058 entry.element = element.clone();
2059 entry.hash_code = element.hash_code();
2060 request_update_auto_invalidations(element.as_ref(), context, capabilities);
2061 }
2062
2063 entry.capabilities = capabilities;
2064 entry
2065 .node
2066 .borrow()
2067 .node_state()
2068 .set_capabilities(capabilities);
2069 continue;
2070 }
2071 fast_path_failed_at = Some(idx);
2072 }
2073
2074 self.scratch_elements.push(element.clone());
2075 }
2076
2077 if fast_path_failed_at.is_none() && self.scratch_elements.is_empty() {
2078 if elements_count < self.entries.len() {
2079 for entry in self.entries.drain(elements_count..) {
2080 request_auto_invalidations(context, entry.capabilities);
2081 detach_node_tree(&mut **entry.node.borrow_mut());
2082 }
2083 }
2084 self.sync_chain_links();
2085 return;
2086 }
2087
2088 let fail_idx = fast_path_failed_at.unwrap_or(old_len);
2089
2090 let mut old_entries: Vec<ModifierNodeEntry> = self.entries.drain(fail_idx..).collect();
2091 let processed_entries_len = self.entries.len();
2092 let old_len = old_entries.len();
2093
2094 self.scratch_old_used.clear();
2095 self.scratch_old_used.resize(old_len, false);
2096
2097 self.scratch_match_order.clear();
2098 self.scratch_match_order.resize(old_len, None);
2099
2100 let index = EntryIndex::build(&old_entries);
2101
2102 let new_elements_count = self.scratch_elements.len();
2103 self.scratch_final_slots.clear();
2104 self.scratch_final_slots.reserve(new_elements_count);
2105
2106 for (new_pos, element) in self.scratch_elements.drain(..).enumerate() {
2107 self.scratch_final_slots.push(None);
2108 let element_type = element.element_type();
2109 let node_type = element.node_type();
2110 let key = element.key();
2111 let hash_code = element.hash_code();
2112 let capabilities = element.capabilities();
2113
2114 let matched_idx = index.find_match(
2115 &old_entries,
2116 &self.scratch_old_used,
2117 EntryMatchQuery {
2118 element_type,
2119 node_type,
2120 key,
2121 hash_code,
2122 element: &element,
2123 },
2124 );
2125
2126 if let Some(idx) = matched_idx {
2127 let entry = &mut old_entries[idx];
2128 let can_update_node = {
2129 let node_borrow = entry.node.borrow();
2130 element.can_update_node(&**node_borrow)
2131 };
2132 if !can_update_node {
2133 let replacement = ModifierNodeEntry::new(
2134 element_type,
2135 node_type,
2136 key,
2137 element.clone(),
2138 element.create_node(),
2139 hash_code,
2140 capabilities,
2141 );
2142 attach_node_tree(&mut **replacement.node.borrow_mut(), context);
2143 element.update_node(&mut **replacement.node.borrow_mut());
2144 request_auto_invalidations(context, capabilities);
2145 self.scratch_final_slots[new_pos] = Some(replacement);
2146 continue;
2147 }
2148
2149 self.scratch_old_used[idx] = true;
2150 self.scratch_match_order[idx] = Some(new_pos);
2151 let moved = idx != new_pos;
2152
2153 let same_element = entry.element.as_ref().equals_element(element.as_ref());
2154
2155 {
2156 let node_borrow = entry.node.borrow();
2157 if !node_borrow.node_state().is_attached() {
2158 drop(node_borrow);
2159 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2160 }
2161 }
2162
2163 let needs_update = !same_element || element.requires_update();
2164 if needs_update {
2165 element.update_node(&mut **entry.node.borrow_mut());
2166 entry.element = element;
2167 entry.hash_code = hash_code;
2168 request_update_auto_invalidations(
2169 entry.element.as_ref(),
2170 context,
2171 capabilities,
2172 );
2173 }
2174 if moved {
2175 request_auto_invalidations(context, capabilities);
2176 }
2177
2178 entry.key = key;
2179 entry.element_type = element_type;
2180 entry.node_type = node_type;
2181 entry.capabilities = capabilities;
2182 entry
2183 .node
2184 .borrow()
2185 .node_state()
2186 .set_capabilities(capabilities);
2187 } else {
2188 let entry = ModifierNodeEntry::new(
2189 element_type,
2190 node_type,
2191 key,
2192 element.clone(),
2193 element.create_node(),
2194 hash_code,
2195 capabilities,
2196 );
2197 attach_node_tree(&mut **entry.node.borrow_mut(), context);
2198 element.update_node(&mut **entry.node.borrow_mut());
2199 request_auto_invalidations(context, capabilities);
2200 self.scratch_final_slots[new_pos] = Some(entry);
2201 }
2202 }
2203
2204 for (i, entry) in old_entries.into_iter().enumerate() {
2205 if self.scratch_old_used[i] {
2206 if let Some(pos) = self.scratch_match_order[i] {
2207 self.scratch_final_slots[pos] = Some(entry);
2208 } else {
2209 request_auto_invalidations(context, entry.capabilities);
2210 detach_node_tree(&mut **entry.node.borrow_mut());
2211 }
2212 } else {
2213 request_auto_invalidations(context, entry.capabilities);
2214 detach_node_tree(&mut **entry.node.borrow_mut());
2215 }
2216 }
2217
2218 self.entries.reserve(self.scratch_final_slots.len());
2219 for slot in self.scratch_final_slots.drain(..) {
2220 if let Some(entry) = slot {
2221 self.entries.push(entry);
2222 } else {
2223 log::error!("modifier reconciliation produced an empty final slot");
2224 }
2225 }
2226
2227 debug_assert_eq!(
2228 self.entries.len(),
2229 processed_entries_len + new_elements_count
2230 );
2231 self.sync_chain_links();
2232 }
2233
2234 pub fn update<I>(&mut self, elements: I, context: &mut dyn ModifierNodeContext)
2238 where
2239 I: IntoIterator<Item = DynModifierElement>,
2240 {
2241 let collected: Vec<DynModifierElement> = elements.into_iter().collect();
2242 self.update_from_slice(&collected, context);
2243 }
2244
2245 pub fn reset(&mut self) {
2248 for entry in &mut self.entries {
2249 reset_node_tree(&mut **entry.node.borrow_mut());
2250 }
2251 }
2252
2253 pub fn detach_all(&mut self) {
2255 for entry in std::mem::take(&mut self.entries) {
2256 detach_node_tree(&mut **entry.node.borrow_mut());
2257 {
2258 let node_borrow = entry.node.borrow();
2259 let state = node_borrow.node_state();
2260 state.set_capabilities(NodeCapabilities::empty());
2261 }
2262 }
2263 self.aggregated_capabilities = NodeCapabilities::empty();
2264 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2265 self.ordered_nodes.clear();
2266 self.sync_chain_links();
2267 }
2268
2269 pub fn len(&self) -> usize {
2270 self.entries.len()
2271 }
2272
2273 pub fn is_empty(&self) -> bool {
2274 self.entries.is_empty()
2275 }
2276
2277 pub fn capabilities(&self) -> NodeCapabilities {
2279 self.aggregated_capabilities
2280 }
2281
2282 pub fn has_capability(&self, capability: NodeCapabilities) -> bool {
2284 self.aggregated_capabilities.contains(capability)
2285 }
2286
2287 pub fn head(&self) -> ModifierChainNodeRef<'_> {
2289 self.make_node_ref(NodeLink::Head)
2290 }
2291
2292 pub fn tail(&self) -> ModifierChainNodeRef<'_> {
2294 self.make_node_ref(NodeLink::Tail)
2295 }
2296
2297 pub fn head_to_tail(&self) -> ModifierChainIter<'_> {
2299 ModifierChainIter::forward(self)
2300 }
2301
2302 pub fn tail_to_head(&self) -> ModifierChainIter<'_> {
2304 ModifierChainIter::backward(self)
2305 }
2306
2307 pub fn for_each_forward<F>(&self, mut f: F)
2309 where
2310 F: FnMut(ModifierChainNodeRef<'_>),
2311 {
2312 for node in self.head_to_tail() {
2313 f(node);
2314 }
2315 }
2316
2317 pub fn for_each_forward_matching<F>(&self, mask: NodeCapabilities, mut f: F)
2319 where
2320 F: FnMut(ModifierChainNodeRef<'_>),
2321 {
2322 if mask.is_empty() {
2323 self.for_each_forward(f);
2324 return;
2325 }
2326
2327 if !self.head().aggregate_child_capabilities().intersects(mask) {
2328 return;
2329 }
2330
2331 for node in self.head_to_tail() {
2332 if node.kind_set().intersects(mask) {
2333 f(node);
2334 }
2335 }
2336 }
2337
2338 pub fn for_each_node_with_capability<F>(&self, mask: NodeCapabilities, mut f: F)
2340 where
2341 F: FnMut(ModifierChainNodeRef<'_>, &dyn ModifierNode),
2342 {
2343 self.for_each_forward_matching(mask, |node_ref| {
2344 node_ref.with_node(|node| f(node_ref.clone(), node));
2345 });
2346 }
2347
2348 pub fn for_each_backward<F>(&self, mut f: F)
2350 where
2351 F: FnMut(ModifierChainNodeRef<'_>),
2352 {
2353 for node in self.tail_to_head() {
2354 f(node);
2355 }
2356 }
2357
2358 pub fn find_node_ref(&self, node: &dyn ModifierNode) -> Option<ModifierChainNodeRef<'_>> {
2360 fn node_data_ptr(node: &dyn ModifierNode) -> *const () {
2361 node as *const dyn ModifierNode as *const ()
2362 }
2363
2364 let target = node_data_ptr(node);
2365 for (index, entry) in self.entries.iter().enumerate() {
2366 if node_data_ptr(&**entry.node.borrow()) == target {
2367 return Some(self.make_node_ref(NodeLink::Entry(NodePath::root(index))));
2368 }
2369 }
2370
2371 self.ordered_nodes.iter().find_map(|(link, _caps, _agg)| {
2372 if matches!(link, NodeLink::Entry(path) if path.delegates().is_empty()) {
2373 return None;
2374 }
2375 let matches_target = match link {
2376 NodeLink::Head => node_data_ptr(self.head_sentinel.as_ref()) == target,
2377 NodeLink::Tail => node_data_ptr(self.tail_sentinel.as_ref()) == target,
2378 NodeLink::Entry(path) => {
2379 let node_borrow = self.entries[path.entry()].node.borrow();
2380 node_data_ptr(&**node_borrow) == target
2381 }
2382 };
2383 if matches_target {
2384 Some(self.make_node_ref(*link))
2385 } else {
2386 None
2387 }
2388 })
2389 }
2390
2391 pub fn node<N: ModifierNode + 'static>(&self, index: usize) -> Option<std::cell::Ref<'_, N>> {
2394 self.entries.get(index).and_then(|entry| {
2395 std::cell::Ref::filter_map(entry.node.borrow(), |boxed_node| {
2396 boxed_node.as_any().downcast_ref::<N>()
2397 })
2398 .ok()
2399 })
2400 }
2401
2402 pub fn node_mut<N: ModifierNode + 'static>(
2405 &self,
2406 index: usize,
2407 ) -> Option<std::cell::RefMut<'_, N>> {
2408 self.entries.get(index).and_then(|entry| {
2409 std::cell::RefMut::filter_map(entry.node.borrow_mut(), |boxed_node| {
2410 boxed_node.as_any_mut().downcast_mut::<N>()
2411 })
2412 .ok()
2413 })
2414 }
2415
2416 pub fn get_node_rc(&self, index: usize) -> Option<Rc<RefCell<Box<dyn ModifierNode>>>> {
2419 self.entries.get(index).map(|entry| Rc::clone(&entry.node))
2420 }
2421
2422 pub fn has_nodes_for_invalidation(&self, kind: InvalidationKind) -> bool {
2424 self.aggregated_capabilities
2425 .contains(NodeCapabilities::for_invalidation(kind))
2426 }
2427
2428 pub fn visit_nodes_mut<F>(&mut self, mut f: F)
2430 where
2431 F: FnMut(&mut dyn ModifierNode, NodeCapabilities),
2432 {
2433 for index in 0..self.ordered_nodes.len() {
2434 let (link, cached_caps, _agg) = self.ordered_nodes[index];
2435 match link {
2436 NodeLink::Head => {
2437 f(self.head_sentinel.as_mut(), cached_caps);
2438 }
2439 NodeLink::Tail => {
2440 f(self.tail_sentinel.as_mut(), cached_caps);
2441 }
2442 NodeLink::Entry(path) => {
2443 let mut node_borrow = self.entries[path.entry()].node.borrow_mut();
2444 if path.delegates().is_empty() {
2445 f(&mut **node_borrow, cached_caps);
2446 } else {
2447 let mut current: &mut dyn ModifierNode = &mut **node_borrow;
2448 for &delegate_index in path.delegates() {
2449 if let Some(delegate) =
2450 nth_delegate_mut(current, delegate_index as usize)
2451 {
2452 current = delegate;
2453 } else {
2454 return;
2455 }
2456 }
2457 f(current, cached_caps);
2458 }
2459 }
2460 }
2461 }
2462 }
2463
2464 fn make_node_ref(&self, link: NodeLink) -> ModifierChainNodeRef<'_> {
2465 ModifierChainNodeRef {
2466 chain: self,
2467 link,
2468 cached_capabilities: None,
2469 cached_aggregate_child: None,
2470 }
2471 }
2472
2473 fn make_node_ref_with_caps(
2474 &self,
2475 link: NodeLink,
2476 caps: NodeCapabilities,
2477 aggregate_child: NodeCapabilities,
2478 ) -> ModifierChainNodeRef<'_> {
2479 ModifierChainNodeRef {
2480 chain: self,
2481 link,
2482 cached_capabilities: Some(caps),
2483 cached_aggregate_child: Some(aggregate_child),
2484 }
2485 }
2486
2487 fn sync_chain_links(&mut self) {
2488 self.rebuild_ordered_nodes();
2489
2490 self.head_sentinel.node_state().set_parent_link(None);
2491 self.tail_sentinel.node_state().set_child_link(None);
2492
2493 if self.ordered_nodes.is_empty() {
2494 self.head_sentinel
2495 .node_state()
2496 .set_child_link(Some(NodeLink::Tail));
2497 self.tail_sentinel
2498 .node_state()
2499 .set_parent_link(Some(NodeLink::Head));
2500 self.aggregated_capabilities = NodeCapabilities::empty();
2501 self.head_aggregate_child_capabilities = NodeCapabilities::empty();
2502 self.head_sentinel
2503 .node_state()
2504 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2505 self.tail_sentinel
2506 .node_state()
2507 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2508 return;
2509 }
2510
2511 let mut previous = NodeLink::Head;
2512 for (link, _caps, _agg) in self.ordered_nodes.iter().copied() {
2513 match &previous {
2514 NodeLink::Head => self.head_sentinel.node_state().set_child_link(Some(link)),
2515 NodeLink::Tail => self.tail_sentinel.node_state().set_child_link(Some(link)),
2516 NodeLink::Entry(path) => {
2517 let node_borrow = self.entries[path.entry()].node.borrow();
2518 if path.delegates().is_empty() {
2519 node_borrow.node_state().set_child_link(Some(link));
2520 } else {
2521 let mut current: &dyn ModifierNode = &**node_borrow;
2522 for &delegate_index in path.delegates() {
2523 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
2524 current = delegate;
2525 }
2526 }
2527 current.node_state().set_child_link(Some(link));
2528 }
2529 }
2530 }
2531 match &link {
2532 NodeLink::Head => self
2533 .head_sentinel
2534 .node_state()
2535 .set_parent_link(Some(previous)),
2536 NodeLink::Tail => self
2537 .tail_sentinel
2538 .node_state()
2539 .set_parent_link(Some(previous)),
2540 NodeLink::Entry(path) => {
2541 let node_borrow = self.entries[path.entry()].node.borrow();
2542 if path.delegates().is_empty() {
2543 node_borrow.node_state().set_parent_link(Some(previous));
2544 } else {
2545 let mut current: &dyn ModifierNode = &**node_borrow;
2546 for &delegate_index in path.delegates() {
2547 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
2548 current = delegate;
2549 }
2550 }
2551 current.node_state().set_parent_link(Some(previous));
2552 }
2553 }
2554 }
2555 previous = link;
2556 }
2557
2558 match &previous {
2559 NodeLink::Head => self
2560 .head_sentinel
2561 .node_state()
2562 .set_child_link(Some(NodeLink::Tail)),
2563 NodeLink::Tail => self
2564 .tail_sentinel
2565 .node_state()
2566 .set_child_link(Some(NodeLink::Tail)),
2567 NodeLink::Entry(path) => {
2568 let node_borrow = self.entries[path.entry()].node.borrow();
2569 if path.delegates().is_empty() {
2570 node_borrow
2571 .node_state()
2572 .set_child_link(Some(NodeLink::Tail));
2573 } else {
2574 let mut current: &dyn ModifierNode = &**node_borrow;
2575 for &delegate_index in path.delegates() {
2576 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
2577 current = delegate;
2578 }
2579 }
2580 current.node_state().set_child_link(Some(NodeLink::Tail));
2581 }
2582 }
2583 }
2584 self.tail_sentinel
2585 .node_state()
2586 .set_parent_link(Some(previous));
2587 self.tail_sentinel.node_state().set_child_link(None);
2588
2589 let mut aggregate = NodeCapabilities::empty();
2590 for (link, cached_caps, cached_aggregate) in self.ordered_nodes.iter_mut().rev() {
2591 aggregate |= *cached_caps;
2592 *cached_aggregate = aggregate;
2593 match link {
2594 NodeLink::Head => {
2595 self.head_sentinel
2596 .node_state()
2597 .set_aggregate_child_capabilities(aggregate);
2598 }
2599 NodeLink::Tail => {
2600 self.tail_sentinel
2601 .node_state()
2602 .set_aggregate_child_capabilities(aggregate);
2603 }
2604 NodeLink::Entry(path) => {
2605 let node_borrow = self.entries[path.entry()].node.borrow();
2606 let state = if path.delegates().is_empty() {
2607 node_borrow.node_state()
2608 } else {
2609 let mut current: &dyn ModifierNode = &**node_borrow;
2610 for &delegate_index in path.delegates() {
2611 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
2612 current = delegate;
2613 }
2614 }
2615 current.node_state()
2616 };
2617 state.set_aggregate_child_capabilities(aggregate);
2618 }
2619 }
2620 }
2621
2622 self.aggregated_capabilities = aggregate;
2623 self.head_aggregate_child_capabilities = aggregate;
2624 self.head_sentinel
2625 .node_state()
2626 .set_aggregate_child_capabilities(aggregate);
2627 self.tail_sentinel
2628 .node_state()
2629 .set_aggregate_child_capabilities(NodeCapabilities::empty());
2630 }
2631
2632 fn rebuild_ordered_nodes(&mut self) {
2633 self.ordered_nodes.clear();
2634 let mut path_buf = [0usize; MAX_DELEGATE_DEPTH];
2635 for (index, entry) in self.entries.iter().enumerate() {
2636 let node_borrow = entry.node.borrow();
2637 Self::enumerate_link_order(
2638 &**node_borrow,
2639 index,
2640 &mut path_buf,
2641 0,
2642 &mut self.ordered_nodes,
2643 );
2644 }
2645 }
2646
2647 fn enumerate_link_order(
2648 node: &dyn ModifierNode,
2649 entry: usize,
2650 path_buf: &mut [usize; MAX_DELEGATE_DEPTH],
2651 path_len: usize,
2652 out: &mut Vec<(NodeLink, NodeCapabilities, NodeCapabilities)>,
2653 ) {
2654 let caps = node.node_state().capabilities();
2655 out.push((
2656 NodeLink::Entry(NodePath::from_slice(entry, &path_buf[..path_len])),
2657 caps,
2658 NodeCapabilities::empty(),
2659 ));
2660 let mut delegate_index = 0usize;
2661 node.for_each_delegate(&mut |child| {
2662 if path_len < MAX_DELEGATE_DEPTH {
2663 path_buf[path_len] = delegate_index;
2664 Self::enumerate_link_order(child, entry, path_buf, path_len + 1, out);
2665 }
2666 delegate_index += 1;
2667 });
2668 }
2669}
2670
2671impl<'a> ModifierChainNodeRef<'a> {
2672 fn with_state<R>(&self, f: impl FnOnce(&NodeState) -> R) -> R {
2673 match &self.link {
2674 NodeLink::Head => f(self.chain.head_sentinel.node_state()),
2675 NodeLink::Tail => f(self.chain.tail_sentinel.node_state()),
2676 NodeLink::Entry(path) => {
2677 let node_borrow = self.chain.entries[path.entry()].node.borrow();
2678 if path.delegates().is_empty() {
2679 f(node_borrow.node_state())
2680 } else {
2681 let mut current: &dyn ModifierNode = &**node_borrow;
2682 for &delegate_index in path.delegates() {
2683 if let Some(delegate) = nth_delegate(current, delegate_index as usize) {
2684 current = delegate;
2685 } else {
2686 return f(node_borrow.node_state());
2687 }
2688 }
2689 f(current.node_state())
2690 }
2691 }
2692 }
2693 }
2694
2695 pub fn with_node<R>(&self, f: impl FnOnce(&dyn ModifierNode) -> R) -> Option<R> {
2698 match &self.link {
2699 NodeLink::Head => None,
2700 NodeLink::Tail => None,
2701 NodeLink::Entry(path) => {
2702 let node_borrow = self.chain.entries[path.entry()].node.borrow();
2703 if path.delegates().is_empty() {
2704 Some(f(&**node_borrow))
2705 } else {
2706 let mut current: &dyn ModifierNode = &**node_borrow;
2707 for &delegate_index in path.delegates() {
2708 current = nth_delegate(current, delegate_index as usize)?;
2709 }
2710 Some(f(current))
2711 }
2712 }
2713 }
2714 }
2715
2716 #[inline]
2718 pub fn parent(&self) -> Option<Self> {
2719 self.with_state(|state| state.parent_link())
2720 .map(|link| self.chain.make_node_ref(link))
2721 }
2722
2723 #[inline]
2725 pub fn child(&self) -> Option<Self> {
2726 self.with_state(|state| state.child_link())
2727 .map(|link| self.chain.make_node_ref(link))
2728 }
2729
2730 #[inline]
2732 pub fn kind_set(&self) -> NodeCapabilities {
2733 if let Some(caps) = self.cached_capabilities {
2734 return caps;
2735 }
2736 match &self.link {
2737 NodeLink::Head | NodeLink::Tail => NodeCapabilities::empty(),
2738 NodeLink::Entry(_) => self.with_state(|state| state.capabilities()),
2739 }
2740 }
2741
2742 pub fn entry_index(&self) -> Option<usize> {
2744 match &self.link {
2745 NodeLink::Entry(path) => Some(path.entry()),
2746 _ => None,
2747 }
2748 }
2749
2750 pub fn delegate_depth(&self) -> usize {
2752 match &self.link {
2753 NodeLink::Entry(path) => path.delegates().len(),
2754 _ => 0,
2755 }
2756 }
2757
2758 #[inline]
2760 pub fn aggregate_child_capabilities(&self) -> NodeCapabilities {
2761 if let Some(agg) = self.cached_aggregate_child {
2762 return agg;
2763 }
2764 if self.is_tail() {
2765 NodeCapabilities::empty()
2766 } else {
2767 self.with_state(|state| state.aggregate_child_capabilities())
2768 }
2769 }
2770
2771 pub fn is_head(&self) -> bool {
2773 matches!(self.link, NodeLink::Head)
2774 }
2775
2776 pub fn is_tail(&self) -> bool {
2778 matches!(self.link, NodeLink::Tail)
2779 }
2780
2781 pub fn is_sentinel(&self) -> bool {
2783 matches!(self.link, NodeLink::Head | NodeLink::Tail)
2784 }
2785
2786 pub fn has_capability(&self, mask: NodeCapabilities) -> bool {
2788 !mask.is_empty() && self.kind_set().intersects(mask)
2789 }
2790
2791 pub fn visit_descendants<F>(self, include_self: bool, mut f: F)
2793 where
2794 F: FnMut(ModifierChainNodeRef<'a>),
2795 {
2796 let mut current = if include_self {
2797 Some(self)
2798 } else {
2799 self.child()
2800 };
2801 while let Some(node) = current {
2802 if node.is_tail() {
2803 break;
2804 }
2805 if !node.is_sentinel() {
2806 f(node.clone());
2807 }
2808 current = node.child();
2809 }
2810 }
2811
2812 pub fn visit_descendants_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
2814 where
2815 F: FnMut(ModifierChainNodeRef<'a>),
2816 {
2817 if mask.is_empty() {
2818 self.visit_descendants(include_self, f);
2819 return;
2820 }
2821
2822 if !self.aggregate_child_capabilities().intersects(mask) {
2823 return;
2824 }
2825
2826 self.visit_descendants(include_self, |node| {
2827 if node.kind_set().intersects(mask) {
2828 f(node);
2829 }
2830 });
2831 }
2832
2833 pub fn visit_ancestors<F>(self, include_self: bool, mut f: F)
2835 where
2836 F: FnMut(ModifierChainNodeRef<'a>),
2837 {
2838 let mut current = if include_self {
2839 Some(self)
2840 } else {
2841 self.parent()
2842 };
2843 while let Some(node) = current {
2844 if node.is_head() {
2845 break;
2846 }
2847 f(node.clone());
2848 current = node.parent();
2849 }
2850 }
2851
2852 pub fn visit_ancestors_matching<F>(self, include_self: bool, mask: NodeCapabilities, mut f: F)
2854 where
2855 F: FnMut(ModifierChainNodeRef<'a>),
2856 {
2857 if mask.is_empty() {
2858 self.visit_ancestors(include_self, f);
2859 return;
2860 }
2861
2862 self.visit_ancestors(include_self, |node| {
2863 if node.kind_set().intersects(mask) {
2864 f(node);
2865 }
2866 });
2867 }
2868}
2869
2870#[cfg(test)]
2871#[path = "tests/modifier_tests.rs"]
2872mod tests;