1use accesskit::{Node as NodeData, NodeId, Tree as TreeData, TreeUpdate};
7use alloc::vec;
8use core::fmt;
9use hashbrown::{HashMap, HashSet};
10
11use crate::node::{Node, NodeState, ParentAndIndex};
12
13#[derive(Clone, Debug)]
14pub struct State {
15 pub(crate) nodes: HashMap<NodeId, NodeState>,
16 pub(crate) data: TreeData,
17 pub(crate) focus: NodeId,
18 is_host_focused: bool,
19}
20
21#[derive(Default)]
22struct InternalChanges {
23 added_node_ids: HashSet<NodeId>,
24 updated_node_ids: HashSet<NodeId>,
25 removed_node_ids: HashSet<NodeId>,
26}
27
28impl State {
29 fn validate_global(&self) {
30 if !self.nodes.contains_key(&self.data.root) {
31 panic!("Root ID {:?} is not in the node list", self.data.root);
32 }
33 if !self.nodes.contains_key(&self.focus) {
34 panic!("Focused ID {:?} is not in the node list", self.focus);
35 }
36 }
37
38 fn update(
39 &mut self,
40 update: TreeUpdate,
41 is_host_focused: bool,
42 mut changes: Option<&mut InternalChanges>,
43 ) {
44 let mut unreachable = HashSet::new();
45 let mut seen_child_ids = HashSet::new();
46
47 if let Some(tree) = update.tree {
48 if tree.root != self.data.root {
49 unreachable.insert(self.data.root);
50 }
51 self.data = tree;
52 }
53
54 let root = self.data.root;
55 let mut pending_nodes: HashMap<NodeId, _> = HashMap::new();
56 let mut pending_children = HashMap::new();
57
58 fn add_node(
59 nodes: &mut HashMap<NodeId, NodeState>,
60 changes: &mut Option<&mut InternalChanges>,
61 parent_and_index: Option<ParentAndIndex>,
62 id: NodeId,
63 data: NodeData,
64 ) {
65 let state = NodeState {
66 parent_and_index,
67 data,
68 };
69 nodes.insert(id, state);
70 if let Some(changes) = changes {
71 changes.added_node_ids.insert(id);
72 }
73 }
74
75 for (node_id, node_data) in update.nodes {
76 unreachable.remove(&node_id);
77
78 for (child_index, child_id) in node_data.children().iter().enumerate() {
79 if seen_child_ids.contains(child_id) {
80 panic!("TreeUpdate includes duplicate child {:?}", child_id);
81 }
82 seen_child_ids.insert(*child_id);
83 unreachable.remove(child_id);
84 let parent_and_index = ParentAndIndex(node_id, child_index);
85 if let Some(child_state) = self.nodes.get_mut(child_id) {
86 if child_state.parent_and_index != Some(parent_and_index) {
87 child_state.parent_and_index = Some(parent_and_index);
88 if let Some(changes) = &mut changes {
89 changes.updated_node_ids.insert(*child_id);
90 }
91 }
92 } else if let Some(child_data) = pending_nodes.remove(child_id) {
93 add_node(
94 &mut self.nodes,
95 &mut changes,
96 Some(parent_and_index),
97 *child_id,
98 child_data,
99 );
100 } else {
101 pending_children.insert(*child_id, parent_and_index);
102 }
103 }
104
105 if let Some(node_state) = self.nodes.get_mut(&node_id) {
106 if node_id == root {
107 node_state.parent_and_index = None;
108 }
109 for child_id in node_state.data.children().iter() {
110 if !seen_child_ids.contains(child_id) {
111 unreachable.insert(*child_id);
112 }
113 }
114 if node_state.data != node_data {
115 node_state.data.clone_from(&node_data);
116 if let Some(changes) = &mut changes {
117 changes.updated_node_ids.insert(node_id);
118 }
119 }
120 } else if let Some(parent_and_index) = pending_children.remove(&node_id) {
121 add_node(
122 &mut self.nodes,
123 &mut changes,
124 Some(parent_and_index),
125 node_id,
126 node_data,
127 );
128 } else if node_id == root {
129 add_node(&mut self.nodes, &mut changes, None, node_id, node_data);
130 } else {
131 pending_nodes.insert(node_id, node_data);
132 }
133 }
134
135 if !pending_nodes.is_empty() {
136 panic!("TreeUpdate includes {} nodes which are neither in the current tree nor a child of another node from the update: {}", pending_nodes.len(), ShortNodeList(&pending_nodes));
137 }
138 if !pending_children.is_empty() {
139 panic!("TreeUpdate's nodes include {} children ids which are neither in the current tree nor the ID of another node from the update: {}", pending_children.len(), ShortNodeList(&pending_children));
140 }
141
142 self.focus = update.focus;
143 self.is_host_focused = is_host_focused;
144
145 if !unreachable.is_empty() {
146 fn traverse_unreachable(
147 nodes: &mut HashMap<NodeId, NodeState>,
148 changes: &mut Option<&mut InternalChanges>,
149 seen_child_ids: &HashSet<NodeId>,
150 id: NodeId,
151 ) {
152 if let Some(changes) = changes {
153 changes.removed_node_ids.insert(id);
154 }
155 let node = nodes.remove(&id).unwrap();
156 for child_id in node.data.children().iter() {
157 if !seen_child_ids.contains(child_id) {
158 traverse_unreachable(nodes, changes, seen_child_ids, *child_id);
159 }
160 }
161 }
162
163 for id in unreachable {
164 traverse_unreachable(&mut self.nodes, &mut changes, &seen_child_ids, id);
165 }
166 }
167
168 self.validate_global();
169 }
170
171 fn update_host_focus_state(
172 &mut self,
173 is_host_focused: bool,
174 changes: Option<&mut InternalChanges>,
175 ) {
176 let update = TreeUpdate {
177 nodes: vec![],
178 tree: None,
179 focus: self.focus,
180 };
181 self.update(update, is_host_focused, changes);
182 }
183
184 pub fn has_node(&self, id: NodeId) -> bool {
185 self.nodes.get(&id).is_some()
186 }
187
188 pub fn node_by_id(&self, id: NodeId) -> Option<Node<'_>> {
189 self.nodes.get(&id).map(|node_state| Node {
190 tree_state: self,
191 id,
192 state: node_state,
193 })
194 }
195
196 pub fn root_id(&self) -> NodeId {
197 self.data.root
198 }
199
200 pub fn root(&self) -> Node<'_> {
201 self.node_by_id(self.root_id()).unwrap()
202 }
203
204 pub fn is_host_focused(&self) -> bool {
205 self.is_host_focused
206 }
207
208 pub fn focus_id_in_tree(&self) -> NodeId {
209 self.focus
210 }
211
212 pub fn focus_in_tree(&self) -> Node<'_> {
213 self.node_by_id(self.focus_id_in_tree()).unwrap()
214 }
215
216 pub fn focus_id(&self) -> Option<NodeId> {
217 self.is_host_focused.then_some(self.focus)
218 }
219
220 pub fn focus(&self) -> Option<Node<'_>> {
221 self.focus_id().map(|id| self.node_by_id(id).unwrap())
222 }
223
224 pub fn toolkit_name(&self) -> Option<&str> {
225 self.data.toolkit_name.as_deref()
226 }
227
228 pub fn toolkit_version(&self) -> Option<&str> {
229 self.data.toolkit_version.as_deref()
230 }
231}
232
233pub trait ChangeHandler {
234 fn node_added(&mut self, node: &Node);
235 fn node_updated(&mut self, old_node: &Node, new_node: &Node);
236 fn focus_moved(&mut self, old_node: Option<&Node>, new_node: Option<&Node>);
237 fn node_removed(&mut self, node: &Node);
238}
239
240#[derive(Debug)]
241pub struct Tree {
242 state: State,
243 next_state: State,
244}
245
246impl Tree {
247 pub fn new(mut initial_state: TreeUpdate, is_host_focused: bool) -> Self {
248 let Some(tree) = initial_state.tree.take() else {
249 panic!("Tried to initialize the accessibility tree without a root tree. TreeUpdate::tree must be Some.");
250 };
251 let mut state = State {
252 nodes: HashMap::new(),
253 data: tree,
254 focus: initial_state.focus,
255 is_host_focused,
256 };
257 state.update(initial_state, is_host_focused, None);
258 Self {
259 next_state: state.clone(),
260 state,
261 }
262 }
263
264 pub fn update_and_process_changes(
265 &mut self,
266 update: TreeUpdate,
267 handler: &mut impl ChangeHandler,
268 ) {
269 let mut changes = InternalChanges::default();
270 self.next_state
271 .update(update, self.state.is_host_focused, Some(&mut changes));
272 self.process_changes(changes, handler);
273 }
274
275 pub fn update_host_focus_state_and_process_changes(
276 &mut self,
277 is_host_focused: bool,
278 handler: &mut impl ChangeHandler,
279 ) {
280 let mut changes = InternalChanges::default();
281 self.next_state
282 .update_host_focus_state(is_host_focused, Some(&mut changes));
283 self.process_changes(changes, handler);
284 }
285
286 fn process_changes(&mut self, changes: InternalChanges, handler: &mut impl ChangeHandler) {
287 for id in &changes.added_node_ids {
288 let node = self.next_state.node_by_id(*id).unwrap();
289 handler.node_added(&node);
290 }
291 for id in &changes.updated_node_ids {
292 let old_node = self.state.node_by_id(*id).unwrap();
293 let new_node = self.next_state.node_by_id(*id).unwrap();
294 handler.node_updated(&old_node, &new_node);
295 }
296 if self.state.focus_id() != self.next_state.focus_id() {
297 let old_node = self.state.focus();
298 if let Some(old_node) = &old_node {
299 let id = old_node.id();
300 if !changes.updated_node_ids.contains(&id)
301 && !changes.removed_node_ids.contains(&id)
302 {
303 if let Some(old_node_new_version) = self.next_state.node_by_id(id) {
304 handler.node_updated(old_node, &old_node_new_version);
305 }
306 }
307 }
308 let new_node = self.next_state.focus();
309 if let Some(new_node) = &new_node {
310 let id = new_node.id();
311 if !changes.added_node_ids.contains(&id) && !changes.updated_node_ids.contains(&id)
312 {
313 if let Some(new_node_old_version) = self.state.node_by_id(id) {
314 handler.node_updated(&new_node_old_version, new_node);
315 }
316 }
317 }
318 handler.focus_moved(old_node.as_ref(), new_node.as_ref());
319 }
320 for id in &changes.removed_node_ids {
321 let node = self.state.node_by_id(*id).unwrap();
322 handler.node_removed(&node);
323 }
324 for id in changes.added_node_ids {
325 self.state
326 .nodes
327 .insert(id, self.next_state.nodes.get(&id).unwrap().clone());
328 }
329 for id in changes.updated_node_ids {
330 self.state
331 .nodes
332 .get_mut(&id)
333 .unwrap()
334 .clone_from(self.next_state.nodes.get(&id).unwrap());
335 }
336 for id in changes.removed_node_ids {
337 self.state.nodes.remove(&id);
338 }
339 if self.state.data != self.next_state.data {
340 self.state.data.clone_from(&self.next_state.data);
341 }
342 self.state.focus = self.next_state.focus;
343 self.state.is_host_focused = self.next_state.is_host_focused;
344 }
345
346 pub fn state(&self) -> &State {
347 &self.state
348 }
349}
350
351struct ShortNodeList<'a, T>(&'a HashMap<NodeId, T>);
352
353impl<T> fmt::Display for ShortNodeList<'_, T> {
354 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355 write!(f, "[")?;
356 let mut iter = self.0.iter();
357 for i in 0..10 {
358 let Some((id, _)) = iter.next() else {
359 break;
360 };
361 if i != 0 {
362 write!(f, ", ")?;
363 }
364 write!(f, "{id:?}")?;
365 }
366 if iter.next().is_some() {
367 write!(f, " ...")?;
368 }
369 write!(f, "]")
370 }
371}
372
373#[cfg(test)]
374mod tests {
375 use accesskit::{Node, NodeId, Role, Tree, TreeUpdate};
376 use alloc::{vec, vec::Vec};
377
378 #[test]
379 fn init_tree_with_root_node() {
380 let update = TreeUpdate {
381 nodes: vec![(NodeId(0), Node::new(Role::Window))],
382 tree: Some(Tree::new(NodeId(0))),
383 focus: NodeId(0),
384 };
385 let tree = super::Tree::new(update, false);
386 assert_eq!(NodeId(0), tree.state().root().id());
387 assert_eq!(Role::Window, tree.state().root().role());
388 assert!(tree.state().root().parent().is_none());
389 }
390
391 #[test]
392 fn root_node_has_children() {
393 let update = TreeUpdate {
394 nodes: vec![
395 (NodeId(0), {
396 let mut node = Node::new(Role::Window);
397 node.set_children(vec![NodeId(1), NodeId(2)]);
398 node
399 }),
400 (NodeId(1), Node::new(Role::Button)),
401 (NodeId(2), Node::new(Role::Button)),
402 ],
403 tree: Some(Tree::new(NodeId(0))),
404 focus: NodeId(0),
405 };
406 let tree = super::Tree::new(update, false);
407 let state = tree.state();
408 assert_eq!(
409 NodeId(0),
410 state.node_by_id(NodeId(1)).unwrap().parent().unwrap().id()
411 );
412 assert_eq!(
413 NodeId(0),
414 state.node_by_id(NodeId(2)).unwrap().parent().unwrap().id()
415 );
416 assert_eq!(2, state.root().children().count());
417 }
418
419 #[test]
420 fn add_child_to_root_node() {
421 let root_node = Node::new(Role::Window);
422 let first_update = TreeUpdate {
423 nodes: vec![(NodeId(0), root_node.clone())],
424 tree: Some(Tree::new(NodeId(0))),
425 focus: NodeId(0),
426 };
427 let mut tree = super::Tree::new(first_update, false);
428 assert_eq!(0, tree.state().root().children().count());
429 let second_update = TreeUpdate {
430 nodes: vec![
431 (NodeId(0), {
432 let mut node = root_node;
433 node.push_child(NodeId(1));
434 node
435 }),
436 (NodeId(1), Node::new(Role::RootWebArea)),
437 ],
438 tree: None,
439 focus: NodeId(0),
440 };
441 struct Handler {
442 got_new_child_node: bool,
443 got_updated_root_node: bool,
444 }
445 fn unexpected_change() {
446 panic!("expected only new child node and updated root node");
447 }
448 impl super::ChangeHandler for Handler {
449 fn node_added(&mut self, node: &crate::Node) {
450 if node.id() == NodeId(1) {
451 self.got_new_child_node = true;
452 return;
453 }
454 unexpected_change();
455 }
456 fn node_updated(&mut self, old_node: &crate::Node, new_node: &crate::Node) {
457 if new_node.id() == NodeId(0)
458 && old_node.data().children().is_empty()
459 && new_node.data().children() == [NodeId(1)]
460 {
461 self.got_updated_root_node = true;
462 return;
463 }
464 unexpected_change();
465 }
466 fn focus_moved(
467 &mut self,
468 _old_node: Option<&crate::Node>,
469 _new_node: Option<&crate::Node>,
470 ) {
471 unexpected_change();
472 }
473 fn node_removed(&mut self, _node: &crate::Node) {
474 unexpected_change();
475 }
476 }
477 let mut handler = Handler {
478 got_new_child_node: false,
479 got_updated_root_node: false,
480 };
481 tree.update_and_process_changes(second_update, &mut handler);
482 assert!(handler.got_new_child_node);
483 assert!(handler.got_updated_root_node);
484 let state = tree.state();
485 assert_eq!(1, state.root().children().count());
486 assert_eq!(NodeId(1), state.root().children().next().unwrap().id());
487 assert_eq!(
488 NodeId(0),
489 state.node_by_id(NodeId(1)).unwrap().parent().unwrap().id()
490 );
491 }
492
493 #[test]
494 fn remove_child_from_root_node() {
495 let root_node = Node::new(Role::Window);
496 let first_update = TreeUpdate {
497 nodes: vec![
498 (NodeId(0), {
499 let mut node = root_node.clone();
500 node.push_child(NodeId(1));
501 node
502 }),
503 (NodeId(1), Node::new(Role::RootWebArea)),
504 ],
505 tree: Some(Tree::new(NodeId(0))),
506 focus: NodeId(0),
507 };
508 let mut tree = super::Tree::new(first_update, false);
509 assert_eq!(1, tree.state().root().children().count());
510 let second_update = TreeUpdate {
511 nodes: vec![(NodeId(0), root_node)],
512 tree: None,
513 focus: NodeId(0),
514 };
515 struct Handler {
516 got_updated_root_node: bool,
517 got_removed_child_node: bool,
518 }
519 fn unexpected_change() {
520 panic!("expected only removed child node and updated root node");
521 }
522 impl super::ChangeHandler for Handler {
523 fn node_added(&mut self, _node: &crate::Node) {
524 unexpected_change();
525 }
526 fn node_updated(&mut self, old_node: &crate::Node, new_node: &crate::Node) {
527 if new_node.id() == NodeId(0)
528 && old_node.data().children() == [NodeId(1)]
529 && new_node.data().children().is_empty()
530 {
531 self.got_updated_root_node = true;
532 return;
533 }
534 unexpected_change();
535 }
536 fn focus_moved(
537 &mut self,
538 _old_node: Option<&crate::Node>,
539 _new_node: Option<&crate::Node>,
540 ) {
541 unexpected_change();
542 }
543 fn node_removed(&mut self, node: &crate::Node) {
544 if node.id() == NodeId(1) {
545 self.got_removed_child_node = true;
546 return;
547 }
548 unexpected_change();
549 }
550 }
551 let mut handler = Handler {
552 got_updated_root_node: false,
553 got_removed_child_node: false,
554 };
555 tree.update_and_process_changes(second_update, &mut handler);
556 assert!(handler.got_updated_root_node);
557 assert!(handler.got_removed_child_node);
558 assert_eq!(0, tree.state().root().children().count());
559 assert!(tree.state().node_by_id(NodeId(1)).is_none());
560 }
561
562 #[test]
563 fn move_focus_between_siblings() {
564 let first_update = TreeUpdate {
565 nodes: vec![
566 (NodeId(0), {
567 let mut node = Node::new(Role::Window);
568 node.set_children(vec![NodeId(1), NodeId(2)]);
569 node
570 }),
571 (NodeId(1), Node::new(Role::Button)),
572 (NodeId(2), Node::new(Role::Button)),
573 ],
574 tree: Some(Tree::new(NodeId(0))),
575 focus: NodeId(1),
576 };
577 let mut tree = super::Tree::new(first_update, true);
578 assert!(tree.state().node_by_id(NodeId(1)).unwrap().is_focused());
579 let second_update = TreeUpdate {
580 nodes: vec![],
581 tree: None,
582 focus: NodeId(2),
583 };
584 struct Handler {
585 got_old_focus_node_update: bool,
586 got_new_focus_node_update: bool,
587 got_focus_change: bool,
588 }
589 fn unexpected_change() {
590 panic!("expected only focus change");
591 }
592 impl super::ChangeHandler for Handler {
593 fn node_added(&mut self, _node: &crate::Node) {
594 unexpected_change();
595 }
596 fn node_updated(&mut self, old_node: &crate::Node, new_node: &crate::Node) {
597 if old_node.id() == NodeId(1)
598 && new_node.id() == NodeId(1)
599 && old_node.is_focused()
600 && !new_node.is_focused()
601 {
602 self.got_old_focus_node_update = true;
603 return;
604 }
605 if old_node.id() == NodeId(2)
606 && new_node.id() == NodeId(2)
607 && !old_node.is_focused()
608 && new_node.is_focused()
609 {
610 self.got_new_focus_node_update = true;
611 return;
612 }
613 unexpected_change();
614 }
615 fn focus_moved(
616 &mut self,
617 old_node: Option<&crate::Node>,
618 new_node: Option<&crate::Node>,
619 ) {
620 if let (Some(old_node), Some(new_node)) = (old_node, new_node) {
621 if old_node.id() == NodeId(1) && new_node.id() == NodeId(2) {
622 self.got_focus_change = true;
623 return;
624 }
625 }
626 unexpected_change();
627 }
628 fn node_removed(&mut self, _node: &crate::Node) {
629 unexpected_change();
630 }
631 }
632 let mut handler = Handler {
633 got_old_focus_node_update: false,
634 got_new_focus_node_update: false,
635 got_focus_change: false,
636 };
637 tree.update_and_process_changes(second_update, &mut handler);
638 assert!(handler.got_old_focus_node_update);
639 assert!(handler.got_new_focus_node_update);
640 assert!(handler.got_focus_change);
641 assert!(tree.state().node_by_id(NodeId(2)).unwrap().is_focused());
642 assert!(!tree.state().node_by_id(NodeId(1)).unwrap().is_focused());
643 }
644
645 #[test]
646 fn update_node() {
647 let child_node = Node::new(Role::Button);
648 let first_update = TreeUpdate {
649 nodes: vec![
650 (NodeId(0), {
651 let mut node = Node::new(Role::Window);
652 node.set_children(vec![NodeId(1)]);
653 node
654 }),
655 (NodeId(1), {
656 let mut node = child_node.clone();
657 node.set_label("foo");
658 node
659 }),
660 ],
661 tree: Some(Tree::new(NodeId(0))),
662 focus: NodeId(0),
663 };
664 let mut tree = super::Tree::new(first_update, false);
665 assert_eq!(
666 Some("foo".into()),
667 tree.state().node_by_id(NodeId(1)).unwrap().label()
668 );
669 let second_update = TreeUpdate {
670 nodes: vec![(NodeId(1), {
671 let mut node = child_node;
672 node.set_label("bar");
673 node
674 })],
675 tree: None,
676 focus: NodeId(0),
677 };
678 struct Handler {
679 got_updated_child_node: bool,
680 }
681 fn unexpected_change() {
682 panic!("expected only updated child node");
683 }
684 impl super::ChangeHandler for Handler {
685 fn node_added(&mut self, _node: &crate::Node) {
686 unexpected_change();
687 }
688 fn node_updated(&mut self, old_node: &crate::Node, new_node: &crate::Node) {
689 if new_node.id() == NodeId(1)
690 && old_node.label() == Some("foo".into())
691 && new_node.label() == Some("bar".into())
692 {
693 self.got_updated_child_node = true;
694 return;
695 }
696 unexpected_change();
697 }
698 fn focus_moved(
699 &mut self,
700 _old_node: Option<&crate::Node>,
701 _new_node: Option<&crate::Node>,
702 ) {
703 unexpected_change();
704 }
705 fn node_removed(&mut self, _node: &crate::Node) {
706 unexpected_change();
707 }
708 }
709 let mut handler = Handler {
710 got_updated_child_node: false,
711 };
712 tree.update_and_process_changes(second_update, &mut handler);
713 assert!(handler.got_updated_child_node);
714 assert_eq!(
715 Some("bar".into()),
716 tree.state().node_by_id(NodeId(1)).unwrap().label()
717 );
718 }
719
720 #[test]
725 fn no_change_update() {
726 let update = TreeUpdate {
727 nodes: vec![
728 (NodeId(0), {
729 let mut node = Node::new(Role::Window);
730 node.set_children(vec![NodeId(1)]);
731 node
732 }),
733 (NodeId(1), {
734 let mut node = Node::new(Role::Button);
735 node.set_label("foo");
736 node
737 }),
738 ],
739 tree: Some(Tree::new(NodeId(0))),
740 focus: NodeId(0),
741 };
742 let mut tree = super::Tree::new(update.clone(), false);
743 struct Handler;
744 fn unexpected_change() {
745 panic!("expected no changes");
746 }
747 impl super::ChangeHandler for Handler {
748 fn node_added(&mut self, _node: &crate::Node) {
749 unexpected_change();
750 }
751 fn node_updated(&mut self, _old_node: &crate::Node, _new_node: &crate::Node) {
752 unexpected_change();
753 }
754 fn focus_moved(
755 &mut self,
756 _old_node: Option<&crate::Node>,
757 _new_node: Option<&crate::Node>,
758 ) {
759 unexpected_change();
760 }
761 fn node_removed(&mut self, _node: &crate::Node) {
762 unexpected_change();
763 }
764 }
765 let mut handler = Handler {};
766 tree.update_and_process_changes(update, &mut handler);
767 }
768
769 #[test]
770 fn move_node() {
771 struct Handler {
772 got_updated_root: bool,
773 got_updated_child: bool,
774 got_removed_container: bool,
775 }
776
777 fn unexpected_change() {
778 panic!("expected only updated root and removed container");
779 }
780
781 impl super::ChangeHandler for Handler {
782 fn node_added(&mut self, _node: &crate::Node) {
783 unexpected_change();
784 }
785 fn node_updated(&mut self, old_node: &crate::Node, new_node: &crate::Node) {
786 if new_node.id() == NodeId(0)
787 && old_node.child_ids().collect::<Vec<NodeId>>() == vec![NodeId(1)]
788 && new_node.child_ids().collect::<Vec<NodeId>>() == vec![NodeId(2)]
789 {
790 self.got_updated_root = true;
791 return;
792 }
793 if new_node.id() == NodeId(2)
794 && old_node.parent_id() == Some(NodeId(1))
795 && new_node.parent_id() == Some(NodeId(0))
796 {
797 self.got_updated_child = true;
798 return;
799 }
800 unexpected_change();
801 }
802 fn focus_moved(
803 &mut self,
804 _old_node: Option<&crate::Node>,
805 _new_node: Option<&crate::Node>,
806 ) {
807 unexpected_change();
808 }
809 fn node_removed(&mut self, node: &crate::Node) {
810 if node.id() == NodeId(1) {
811 self.got_removed_container = true;
812 return;
813 }
814 unexpected_change();
815 }
816 }
817
818 let mut root = Node::new(Role::Window);
819 root.set_children([NodeId(1)]);
820 let mut container = Node::new(Role::GenericContainer);
821 container.set_children([NodeId(2)]);
822 let update = TreeUpdate {
823 nodes: vec![
824 (NodeId(0), root.clone()),
825 (NodeId(1), container),
826 (NodeId(2), Node::new(Role::Button)),
827 ],
828 tree: Some(Tree::new(NodeId(0))),
829 focus: NodeId(0),
830 };
831 let mut tree = crate::Tree::new(update, false);
832 root.set_children([NodeId(2)]);
833 let mut handler = Handler {
834 got_updated_root: false,
835 got_updated_child: false,
836 got_removed_container: false,
837 };
838 tree.update_and_process_changes(
839 TreeUpdate {
840 nodes: vec![(NodeId(0), root)],
841 tree: None,
842 focus: NodeId(0),
843 },
844 &mut handler,
845 );
846 assert!(handler.got_updated_root);
847 assert!(handler.got_updated_child);
848 assert!(handler.got_removed_container);
849 assert_eq!(
850 tree.state()
851 .node_by_id(NodeId(0))
852 .unwrap()
853 .child_ids()
854 .collect::<Vec<NodeId>>(),
855 vec![NodeId(2)]
856 );
857 assert!(tree.state().node_by_id(NodeId(1)).is_none());
858 assert_eq!(
859 tree.state().node_by_id(NodeId(2)).unwrap().parent_id(),
860 Some(NodeId(0))
861 );
862 }
863}