accesskit_consumer/
tree.rs

1// Copyright 2021 The AccessKit Authors. All rights reserved.
2// Licensed under the Apache License, Version 2.0 (found in
3// the LICENSE-APACHE file) or the MIT license (found in
4// the LICENSE-MIT file), at your option.
5
6use 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    // Verify that if an update consists entirely of node data and tree data
721    // that's the same as before, no changes are reported. This is useful
722    // for a provider that constructs a fresh tree every time, such as
723    // an immediate-mode GUI.
724    #[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}