1use accesskit::{Node as NodeData, NodeId as LocalNodeId, Tree as TreeData, TreeId, TreeUpdate};
7use alloc::{vec, vec::Vec};
8use core::fmt;
9use hashbrown::{HashMap, HashSet};
10
11use crate::node::{Node, NodeId, NodeState, ParentAndIndex};
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
14#[repr(transparent)]
15pub(crate) struct TreeIndex(pub(crate) u32);
16
17#[derive(Clone, Debug, Default)]
18struct TreeIndexMap {
19 id_to_index: HashMap<TreeId, TreeIndex>,
20 index_to_id: HashMap<TreeIndex, TreeId>,
21 next: u32,
22}
23
24impl TreeIndexMap {
25 fn get_index(&mut self, id: TreeId) -> TreeIndex {
26 *self.id_to_index.entry(id).or_insert_with(|| {
27 let tree_index = TreeIndex(self.next);
28 self.next += 1;
29 self.index_to_id.insert(tree_index, id);
30 tree_index
31 })
32 }
33
34 fn get_id(&self, index: TreeIndex) -> Option<TreeId> {
35 self.index_to_id.get(&index).copied()
36 }
37}
38
39#[derive(Clone, Debug)]
41pub(crate) struct SubtreeState {
42 pub(crate) root: NodeId,
43 pub(crate) focus: NodeId,
44}
45
46#[derive(Clone, Debug)]
47pub struct State {
48 pub(crate) nodes: HashMap<NodeId, NodeState>,
49 pub(crate) data: TreeData,
50 pub(crate) root: NodeId,
51 pub(crate) focus: NodeId,
52 is_host_focused: bool,
53 pub(crate) subtrees: HashMap<TreeId, SubtreeState>,
54 pub(crate) graft_parents: HashMap<TreeId, NodeId>,
55 tree_index_map: TreeIndexMap,
56}
57
58#[derive(Default)]
59struct InternalChanges {
60 added_node_ids: HashSet<NodeId>,
61 updated_node_ids: HashSet<NodeId>,
62 removed_node_ids: HashSet<NodeId>,
63}
64
65impl State {
66 fn validate_global(&self) {
67 if !self.nodes.contains_key(&self.root) {
68 panic!("Root ID {:?} is not in the node list", self.data.root);
69 }
70 if !self.nodes.contains_key(&self.focus) {
71 panic!(
72 "Focused ID {:?} is not in the node list",
73 self.focus.to_components().0
74 );
75 }
76 }
77
78 fn compute_effective_focus(&self) -> NodeId {
82 let Some(root_subtree) = self.subtrees.get(&TreeId::ROOT) else {
83 return self.focus;
84 };
85
86 let mut current_focus = root_subtree.focus;
87 loop {
88 let Some(node_state) = self.nodes.get(¤t_focus) else {
89 break;
90 };
91 let Some(subtree_id) = node_state.data.tree_id() else {
92 break;
93 };
94 let subtree = self.subtrees.get(&subtree_id).unwrap_or_else(|| {
95 panic!(
96 "Focus is on graft node {:?} but subtree {:?} does not exist. \
97 Graft nodes cannot be focused without their subtree.",
98 current_focus.to_components().0,
99 subtree_id
100 );
101 });
102 current_focus = subtree.focus;
103 }
104 current_focus
105 }
106
107 fn update(
108 &mut self,
109 update: TreeUpdate,
110 is_host_focused: bool,
111 mut changes: Option<&mut InternalChanges>,
112 ) {
113 let tree_index = self.tree_index_map.get_index(update.tree_id);
114 let map_id = |id: LocalNodeId| NodeId::new(id, tree_index);
115
116 let mut unreachable = HashSet::new();
117 let mut seen_child_ids = HashSet::new();
118
119 let tree_id = update.tree_id;
120 if tree_id != TreeId::ROOT {
121 let subtree_exists = self.subtrees.contains_key(&tree_id);
122 if update.tree.is_some() && !self.graft_parents.contains_key(&tree_id) {
123 panic!(
124 "Cannot push subtree {:?}: no graft node exists for this tree. \
125 Push the graft node (with tree_id property set) before pushing the subtree.",
126 tree_id
127 );
128 }
129 if !subtree_exists && update.tree.is_none() {
130 panic!(
131 "Cannot update subtree {:?}: subtree does not exist. \
132 The first update for a subtree must include tree data.",
133 tree_id
134 );
135 }
136 }
137
138 let new_tree_root = if let Some(tree) = update.tree {
139 let new_root = map_id(tree.root);
140 if tree_id == TreeId::ROOT {
141 if tree.root != self.data.root {
142 unreachable.insert(self.root);
143 }
144 self.root = new_root;
145 self.data = tree;
146 } else if let Some(subtree) = self.subtrees.get(&tree_id) {
147 if subtree.root != new_root {
148 unreachable.insert(subtree.root);
149 }
150 }
151 Some(new_root)
152 } else {
153 None
154 };
155
156 let root = new_tree_root
157 .map(|r| r.to_components().0)
158 .unwrap_or_else(|| {
159 self.subtrees
160 .get(&tree_id)
161 .map(|s| s.root.to_components().0)
162 .unwrap_or(self.data.root)
163 });
164
165 let mut pending_nodes: HashMap<NodeId, _> = HashMap::new();
166 let mut pending_children = HashMap::new();
167 let mut pending_grafts: HashMap<TreeId, NodeId> = HashMap::new();
168 let mut grafts_to_remove: HashSet<TreeId> = HashSet::new();
169
170 fn record_graft(
171 pending_grafts: &mut HashMap<TreeId, NodeId>,
172 subtree_id: TreeId,
173 graft_node_id: NodeId,
174 ) {
175 if subtree_id == TreeId::ROOT {
176 panic!("Cannot graft the root tree");
177 }
178 if let Some(existing_graft) = pending_grafts.get(&subtree_id) {
179 panic!(
180 "Subtree {:?} already has a graft parent {:?}, cannot assign to {:?}",
181 subtree_id,
182 existing_graft.to_components().0,
183 graft_node_id.to_components().0
184 );
185 }
186 pending_grafts.insert(subtree_id, graft_node_id);
187 }
188
189 fn add_node(
190 nodes: &mut HashMap<NodeId, NodeState>,
191 pending_grafts: &mut HashMap<TreeId, NodeId>,
192 changes: &mut Option<&mut InternalChanges>,
193 parent_and_index: Option<ParentAndIndex>,
194 id: NodeId,
195 data: NodeData,
196 ) {
197 if let Some(subtree_id) = data.tree_id() {
198 if !data.children().is_empty() {
199 panic!(
200 "Node {:?} has both tree_id and children. \
201 A graft node's only child comes from its subtree.",
202 id.to_components().0
203 );
204 }
205 record_graft(pending_grafts, subtree_id, id);
206 }
207 let state = NodeState {
208 parent_and_index,
209 data,
210 };
211 nodes.insert(id, state);
212 if let Some(changes) = changes {
213 changes.added_node_ids.insert(id);
214 }
215 }
216
217 for (local_node_id, node_data) in update.nodes {
218 let node_id = map_id(local_node_id);
219 unreachable.remove(&node_id);
220
221 for (child_index, child_id) in node_data.children().iter().enumerate() {
222 let mapped_child_id = map_id(*child_id);
223 if !seen_child_ids.insert(mapped_child_id) {
224 panic!("TreeUpdate includes duplicate child {:?}", child_id);
225 }
226 unreachable.remove(&mapped_child_id);
227 let parent_and_index = ParentAndIndex(node_id, child_index);
228 if let Some(child_state) = self.nodes.get_mut(&mapped_child_id) {
229 if child_state.parent_and_index != Some(parent_and_index) {
230 child_state.parent_and_index = Some(parent_and_index);
231 if let Some(changes) = &mut changes {
232 changes.updated_node_ids.insert(mapped_child_id);
233 }
234 }
235 } else if let Some(child_data) = pending_nodes.remove(&mapped_child_id) {
236 add_node(
237 &mut self.nodes,
238 &mut pending_grafts,
239 &mut changes,
240 Some(parent_and_index),
241 mapped_child_id,
242 child_data,
243 );
244 } else {
245 pending_children.insert(mapped_child_id, parent_and_index);
246 }
247 }
248
249 if let Some(node_state) = self.nodes.get_mut(&node_id) {
250 if local_node_id == root {
251 node_state.parent_and_index = None;
252 }
253 for child_id in node_state.data.children().iter() {
254 let mapped_existing_child_id = map_id(*child_id);
255 if !seen_child_ids.contains(&mapped_existing_child_id) {
256 unreachable.insert(mapped_existing_child_id);
257 }
258 }
259 if node_state.data != node_data {
260 if node_data.tree_id().is_some() && !node_data.children().is_empty() {
261 panic!(
262 "Node {:?} has both tree_id and children. \
263 A graft node's only child comes from its subtree.",
264 node_id.to_components().0
265 );
266 }
267 let old_tree_id = node_state.data.tree_id();
268 let new_tree_id = node_data.tree_id();
269 if old_tree_id != new_tree_id {
270 if let Some(old_subtree_id) = old_tree_id {
271 grafts_to_remove.insert(old_subtree_id);
272 }
273 if let Some(new_subtree_id) = new_tree_id {
274 record_graft(&mut pending_grafts, new_subtree_id, node_id);
275 }
276 }
277 node_state.data.clone_from(&node_data);
278 if let Some(changes) = &mut changes {
279 changes.updated_node_ids.insert(node_id);
280 }
281 }
282 } else if let Some(parent_and_index) = pending_children.remove(&node_id) {
283 add_node(
284 &mut self.nodes,
285 &mut pending_grafts,
286 &mut changes,
287 Some(parent_and_index),
288 node_id,
289 node_data,
290 );
291 } else if local_node_id == root {
292 add_node(
293 &mut self.nodes,
294 &mut pending_grafts,
295 &mut changes,
296 None,
297 node_id,
298 node_data,
299 );
300 } else {
301 pending_nodes.insert(node_id, node_data);
302 }
303 }
304
305 if !pending_nodes.is_empty() {
306 panic!(
307 "TreeUpdate includes {} nodes which are neither in the current tree nor a child of another node from the update: {}",
308 pending_nodes.len(),
309 ShortNodeList(&pending_nodes)
310 );
311 }
312 if !pending_children.is_empty() {
313 panic!(
314 "TreeUpdate's nodes include {} children ids which are neither in the current tree nor the ID of another node from the update: {}",
315 pending_children.len(),
316 ShortNodeList(&pending_children)
317 );
318 }
319
320 let tree_focus = map_id(update.focus);
321 if let Some(new_root) = new_tree_root {
322 self.subtrees.insert(
323 tree_id,
324 SubtreeState {
325 root: new_root,
326 focus: tree_focus,
327 },
328 );
329 } else if let Some(subtree) = self.subtrees.get_mut(&tree_id) {
330 subtree.focus = tree_focus;
331 } else if tree_id == TreeId::ROOT {
332 self.subtrees.insert(
333 tree_id,
334 SubtreeState {
335 root: self.root,
336 focus: tree_focus,
337 },
338 );
339 }
340
341 self.is_host_focused = is_host_focused;
342
343 if !unreachable.is_empty() {
344 fn traverse_unreachable(
345 nodes: &mut HashMap<NodeId, NodeState>,
346 grafts_to_remove: &mut HashSet<TreeId>,
347 changes: &mut Option<&mut InternalChanges>,
348 seen_child_ids: &HashSet<NodeId>,
349 new_tree_root: Option<NodeId>,
350 id: NodeId,
351 ) {
352 if let Some(changes) = changes {
353 changes.removed_node_ids.insert(id);
354 }
355 let node = nodes.remove(&id).unwrap();
356 if let Some(subtree_id) = node.data.tree_id() {
357 grafts_to_remove.insert(subtree_id);
358 }
359 let (_, tree_index) = id.to_components();
360 for child_id in node.data.children().iter() {
361 let child_node_id = NodeId::new(*child_id, tree_index);
362 if !seen_child_ids.contains(&child_node_id)
363 && new_tree_root != Some(child_node_id)
364 {
365 traverse_unreachable(
366 nodes,
367 grafts_to_remove,
368 changes,
369 seen_child_ids,
370 new_tree_root,
371 child_node_id,
372 );
373 }
374 }
375 }
376
377 for id in unreachable {
378 traverse_unreachable(
379 &mut self.nodes,
380 &mut grafts_to_remove,
381 &mut changes,
382 &seen_child_ids,
383 new_tree_root,
384 id,
385 );
386 }
387 }
388
389 fn traverse_subtree(
390 nodes: &mut HashMap<NodeId, NodeState>,
391 subtrees_to_remove: &mut Vec<TreeId>,
392 subtrees_queued: &mut HashSet<TreeId>,
393 changes: &mut Option<&mut InternalChanges>,
394 id: NodeId,
395 ) {
396 let Some(node) = nodes.remove(&id) else {
397 return;
398 };
399 if let Some(changes) = changes {
400 changes.removed_node_ids.insert(id);
401 }
402 if let Some(nested_subtree_id) = node.data.tree_id() {
403 if subtrees_queued.insert(nested_subtree_id) {
404 subtrees_to_remove.push(nested_subtree_id);
405 }
406 }
407 let (_, tree_index) = id.to_components();
408 for child_id in node.data.children().iter() {
409 traverse_subtree(
410 nodes,
411 subtrees_to_remove,
412 subtrees_queued,
413 changes,
414 NodeId::new(*child_id, tree_index),
415 );
416 }
417 }
418
419 let mut subtrees_queued: HashSet<TreeId> = grafts_to_remove;
420 let mut subtrees_to_remove: Vec<TreeId> = subtrees_queued.iter().copied().collect();
421 let mut i = 0;
422 while i < subtrees_to_remove.len() {
423 let subtree_id = subtrees_to_remove[i];
424 i += 1;
425
426 if self.graft_parents.remove(&subtree_id).is_none() {
427 continue;
428 }
429
430 if pending_grafts.contains_key(&subtree_id) {
431 continue;
432 }
433 if let Some(subtree) = self.subtrees.remove(&subtree_id) {
434 traverse_subtree(
435 &mut self.nodes,
436 &mut subtrees_to_remove,
437 &mut subtrees_queued,
438 &mut changes,
439 subtree.root,
440 );
441 }
442 }
443
444 for (subtree_id, node_id) in pending_grafts {
445 if let Some(&existing_graft) = self.graft_parents.get(&subtree_id) {
446 panic!(
447 "Subtree {:?} already has a graft parent {:?}, cannot assign to {:?}",
448 subtree_id,
449 existing_graft.to_components().0,
450 node_id.to_components().0
451 );
452 }
453 self.graft_parents.insert(subtree_id, node_id);
454 if let Some(subtree) = self.subtrees.get(&subtree_id) {
455 let subtree_root_id = subtree.root;
456 if let Some(root_state) = self.nodes.get_mut(&subtree_root_id) {
457 root_state.parent_and_index = Some(ParentAndIndex(node_id, 0));
458 if let Some(changes) = &mut changes {
459 if !changes.added_node_ids.contains(&subtree_root_id) {
460 changes.updated_node_ids.insert(subtree_root_id);
461 }
462 }
463 }
464 }
465 }
466
467 if let Some(new_root_id) = new_tree_root {
468 if let Some(&graft_node_id) = self.graft_parents.get(&tree_id) {
469 if let Some(root_state) = self.nodes.get_mut(&new_root_id) {
470 root_state.parent_and_index = Some(ParentAndIndex(graft_node_id, 0));
471 if let Some(changes) = &mut changes {
472 if !changes.added_node_ids.contains(&new_root_id) {
473 changes.updated_node_ids.insert(new_root_id);
474 }
475 }
476 }
477 }
478 }
479
480 self.focus = self.compute_effective_focus();
481
482 self.validate_global();
483 }
484
485 fn update_host_focus_state(
486 &mut self,
487 is_host_focused: bool,
488 changes: Option<&mut InternalChanges>,
489 ) {
490 let (focus, _) = self.focus.to_components();
491 let update = TreeUpdate {
492 nodes: vec![],
493 tree: None,
494 tree_id: TreeId::ROOT,
495 focus,
496 };
497 self.update(update, is_host_focused, changes);
498 }
499
500 pub fn has_node(&self, id: NodeId) -> bool {
501 self.nodes.contains_key(&id)
502 }
503
504 pub fn node_by_id(&self, id: NodeId) -> Option<Node<'_>> {
505 self.nodes.get(&id).map(|node_state| Node {
506 tree_state: self,
507 id,
508 state: node_state,
509 })
510 }
511
512 pub fn root_id(&self) -> NodeId {
513 self.root
514 }
515
516 pub fn root(&self) -> Node<'_> {
517 self.node_by_id(self.root_id()).unwrap()
518 }
519
520 pub fn subtree_root(&self, tree_id: TreeId) -> Option<NodeId> {
522 self.subtrees.get(&tree_id).map(|s| s.root)
523 }
524
525 pub fn is_host_focused(&self) -> bool {
526 self.is_host_focused
527 }
528
529 pub fn focus_id_in_tree(&self) -> NodeId {
530 self.focus
531 }
532
533 pub fn focus_in_tree(&self) -> Node<'_> {
534 self.node_by_id(self.focus_id_in_tree()).unwrap()
535 }
536
537 pub fn focus_id(&self) -> Option<NodeId> {
538 self.is_host_focused.then_some(self.focus)
539 }
540
541 pub fn focus(&self) -> Option<Node<'_>> {
542 self.focus_id().map(|id| {
543 let focused = self.node_by_id(id).unwrap();
544 focused.active_descendant().unwrap_or(focused)
545 })
546 }
547
548 pub fn active_dialog(&self) -> Option<Node<'_>> {
549 let mut node = self.focus();
550 while let Some(candidate) = node {
551 if candidate.is_dialog() {
552 return Some(candidate);
553 }
554 node = candidate.parent();
555 }
556 None
557 }
558
559 pub fn toolkit_name(&self) -> Option<&str> {
560 self.data.toolkit_name.as_deref()
561 }
562
563 pub fn toolkit_version(&self) -> Option<&str> {
564 self.data.toolkit_version.as_deref()
565 }
566
567 pub fn locate_node(&self, node_id: NodeId) -> Option<(LocalNodeId, TreeId)> {
568 if !self.has_node(node_id) {
569 return None;
570 }
571 let (local_id, tree_index) = node_id.to_components();
572 self.tree_index_map
573 .get_id(tree_index)
574 .map(|tree_id| (local_id, tree_id))
575 }
576}
577
578pub trait ChangeHandler {
579 fn node_added(&mut self, node: &Node);
580 fn node_updated(&mut self, old_node: &Node, new_node: &Node);
581 fn focus_moved(&mut self, old_node: Option<&Node>, new_node: Option<&Node>);
582 fn node_removed(&mut self, node: &Node);
583}
584
585#[derive(Debug)]
586pub struct Tree {
587 state: State,
588 next_state: State,
589}
590
591impl Tree {
592 pub fn new(mut initial_state: TreeUpdate, is_host_focused: bool) -> Self {
593 let Some(tree) = initial_state.tree.take() else {
594 panic!(
595 "Tried to initialize the accessibility tree without a root tree. TreeUpdate::tree must be Some."
596 );
597 };
598 if initial_state.tree_id != TreeId::ROOT {
599 panic!("Cannot initialize with a subtree. TreeUpdate::tree_id must be TreeId::ROOT.");
600 }
601 let mut tree_index_map = TreeIndexMap::default();
602 let tree_index = tree_index_map.get_index(initial_state.tree_id);
603 let mut state = State {
604 nodes: HashMap::new(),
605 root: NodeId::new(tree.root, tree_index),
606 data: tree,
607 focus: NodeId::new(initial_state.focus, tree_index),
608 is_host_focused,
609 subtrees: HashMap::new(),
610 graft_parents: HashMap::new(),
611 tree_index_map,
612 };
613 state.update(initial_state, is_host_focused, None);
614 Self {
615 next_state: state.clone(),
616 state,
617 }
618 }
619
620 pub fn update_and_process_changes(
621 &mut self,
622 update: TreeUpdate,
623 handler: &mut impl ChangeHandler,
624 ) {
625 let mut changes = InternalChanges::default();
626 self.next_state
627 .update(update, self.state.is_host_focused, Some(&mut changes));
628 self.process_changes(changes, handler);
629 }
630
631 pub fn update_host_focus_state_and_process_changes(
632 &mut self,
633 is_host_focused: bool,
634 handler: &mut impl ChangeHandler,
635 ) {
636 let mut changes = InternalChanges::default();
637 self.next_state
638 .update_host_focus_state(is_host_focused, Some(&mut changes));
639 self.process_changes(changes, handler);
640 }
641
642 fn process_changes(&mut self, changes: InternalChanges, handler: &mut impl ChangeHandler) {
643 for id in &changes.added_node_ids {
644 let node = self.next_state.node_by_id(*id).unwrap();
645 handler.node_added(&node);
646 }
647 for id in &changes.updated_node_ids {
648 let old_node = self.state.node_by_id(*id).unwrap();
649 let new_node = self.next_state.node_by_id(*id).unwrap();
650 handler.node_updated(&old_node, &new_node);
651 }
652 let old_focus = self.state.focus();
653 let new_focus = self.next_state.focus();
654 if old_focus.as_ref().map(|n| n.id()) != new_focus.as_ref().map(|n| n.id()) {
655 if let Some(old_node) = &old_focus {
656 let id = old_node.id();
657 if !changes.updated_node_ids.contains(&id)
658 && !changes.removed_node_ids.contains(&id)
659 {
660 if let Some(old_node_new_version) = self.next_state.node_by_id(id) {
661 handler.node_updated(old_node, &old_node_new_version);
662 }
663 }
664 }
665 if let Some(new_node) = &new_focus {
666 let id = new_node.id();
667 if !changes.added_node_ids.contains(&id) && !changes.updated_node_ids.contains(&id)
668 {
669 if let Some(new_node_old_version) = self.state.node_by_id(id) {
670 handler.node_updated(&new_node_old_version, new_node);
671 }
672 }
673 }
674 handler.focus_moved(old_focus.as_ref(), new_focus.as_ref());
675 }
676 for id in &changes.removed_node_ids {
677 let node = self.state.node_by_id(*id).unwrap();
678 handler.node_removed(&node);
679 }
680 for id in changes.added_node_ids {
681 self.state
682 .nodes
683 .insert(id, self.next_state.nodes.get(&id).unwrap().clone());
684 }
685 for id in changes.updated_node_ids {
686 self.state
687 .nodes
688 .get_mut(&id)
689 .unwrap()
690 .clone_from(self.next_state.nodes.get(&id).unwrap());
691 }
692 for id in changes.removed_node_ids {
693 self.state.nodes.remove(&id);
694 }
695 if self.state.data != self.next_state.data {
696 self.state.data.clone_from(&self.next_state.data);
697 }
698 self.state.root = self.next_state.root;
699 self.state.focus = self.next_state.focus;
700 self.state.is_host_focused = self.next_state.is_host_focused;
701 self.state.subtrees.clone_from(&self.next_state.subtrees);
702 self.state
703 .graft_parents
704 .clone_from(&self.next_state.graft_parents);
705 self.state
706 .tree_index_map
707 .clone_from(&self.next_state.tree_index_map);
708 }
709
710 pub fn state(&self) -> &State {
711 &self.state
712 }
713}
714
715struct ShortNodeList<'a, T>(&'a HashMap<NodeId, T>);
716
717impl<T> fmt::Display for ShortNodeList<'_, T> {
718 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
719 write!(f, "[")?;
720 let mut iter = self.0.iter();
721 for i in 0..10 {
722 let Some((id, _)) = iter.next() else {
723 break;
724 };
725 if i != 0 {
726 write!(f, ", ")?;
727 }
728 write!(f, "{:?}", id.to_components().0)?;
729 }
730 if iter.next().is_some() {
731 write!(f, " ...")?;
732 }
733 write!(f, "]")
734 }
735}
736
737#[cfg(test)]
738mod tests {
739 use accesskit::{Node, NodeId as LocalNodeId, Role, Tree, TreeId, TreeUpdate, Uuid};
740 use alloc::{vec, vec::Vec};
741
742 use super::{TreeIndex, TreeIndexMap};
743 use crate::node::NodeId;
744
745 struct NoOpHandler;
746 impl super::ChangeHandler for NoOpHandler {
747 fn node_added(&mut self, _: &crate::Node) {}
748 fn node_updated(&mut self, _: &crate::Node, _: &crate::Node) {}
749 fn focus_moved(&mut self, _: Option<&crate::Node>, _: Option<&crate::Node>) {}
750 fn node_removed(&mut self, _: &crate::Node) {}
751 }
752
753 fn node_id(n: u64) -> NodeId {
754 NodeId::new(LocalNodeId(n), TreeIndex(0))
755 }
756
757 #[test]
758 fn tree_index_map_assigns_sequential_indices() {
759 let mut map = TreeIndexMap::default();
760 let id1 = TreeId::ROOT;
761 let id2 = TreeId(Uuid::from_u128(1));
762 let id3 = TreeId(Uuid::from_u128(2));
763
764 let index1 = map.get_index(id1);
765 let index2 = map.get_index(id2);
766 let index3 = map.get_index(id3);
767
768 assert_eq!(index1, TreeIndex(0));
769 assert_eq!(index2, TreeIndex(1));
770 assert_eq!(index3, TreeIndex(2));
771 }
772
773 #[test]
774 fn tree_index_map_returns_same_index_for_same_id() {
775 let mut map = TreeIndexMap::default();
776 let id = TreeId::ROOT;
777
778 let index1 = map.get_index(id);
779 let index2 = map.get_index(id);
780
781 assert_eq!(index1, index2);
782 }
783
784 #[test]
785 fn tree_index_map_get_id_returns_correct_id() {
786 let mut map = TreeIndexMap::default();
787 let id1 = TreeId::ROOT;
788 let id2 = TreeId(Uuid::from_u128(1));
789
790 let index1 = map.get_index(id1);
791 let index2 = map.get_index(id2);
792
793 assert_eq!(map.get_id(index1), Some(id1));
794 assert_eq!(map.get_id(index2), Some(id2));
795 }
796
797 #[test]
798 fn tree_index_map_get_id_returns_none_for_unknown_index() {
799 let map = TreeIndexMap::default();
800 assert_eq!(map.get_id(TreeIndex(0)), None);
801 assert_eq!(map.get_id(TreeIndex(999)), None);
802 }
803
804 #[test]
805 fn init_tree_with_root_node() {
806 let update = TreeUpdate {
807 nodes: vec![(LocalNodeId(0), Node::new(Role::Window))],
808 tree: Some(Tree::new(LocalNodeId(0))),
809 tree_id: TreeId::ROOT,
810 focus: LocalNodeId(0),
811 };
812 let tree = super::Tree::new(update, false);
813 assert_eq!(node_id(0), tree.state().root().id());
814 assert_eq!(Role::Window, tree.state().root().role());
815 assert!(tree.state().root().parent().is_none());
816 }
817
818 #[test]
819 #[should_panic(
820 expected = "Cannot initialize with a subtree. TreeUpdate::tree_id must be TreeId::ROOT."
821 )]
822 fn init_tree_with_non_root_tree_id_panics() {
823 let update = TreeUpdate {
824 nodes: vec![(LocalNodeId(0), Node::new(Role::Window))],
825 tree: Some(Tree::new(LocalNodeId(0))),
826 tree_id: TreeId(Uuid::from_u128(1)),
827 focus: LocalNodeId(0),
828 };
829 let _ = super::Tree::new(update, false);
830 }
831
832 #[test]
833 fn root_node_has_children() {
834 let update = TreeUpdate {
835 nodes: vec![
836 (LocalNodeId(0), {
837 let mut node = Node::new(Role::Window);
838 node.set_children(vec![LocalNodeId(1), LocalNodeId(2)]);
839 node
840 }),
841 (LocalNodeId(1), Node::new(Role::Button)),
842 (LocalNodeId(2), Node::new(Role::Button)),
843 ],
844 tree: Some(Tree::new(LocalNodeId(0))),
845 tree_id: TreeId::ROOT,
846 focus: LocalNodeId(0),
847 };
848 let tree = super::Tree::new(update, false);
849 let state = tree.state();
850 assert_eq!(
851 node_id(0),
852 state.node_by_id(node_id(1)).unwrap().parent().unwrap().id()
853 );
854 assert_eq!(
855 node_id(0),
856 state.node_by_id(node_id(2)).unwrap().parent().unwrap().id()
857 );
858 assert_eq!(2, state.root().children().count());
859 }
860
861 #[test]
862 fn add_child_to_root_node() {
863 let root_node = Node::new(Role::Window);
864 let first_update = TreeUpdate {
865 nodes: vec![(LocalNodeId(0), root_node.clone())],
866 tree: Some(Tree::new(LocalNodeId(0))),
867 tree_id: TreeId::ROOT,
868 focus: LocalNodeId(0),
869 };
870 let mut tree = super::Tree::new(first_update, false);
871 assert_eq!(0, tree.state().root().children().count());
872 let second_update = TreeUpdate {
873 nodes: vec![
874 (LocalNodeId(0), {
875 let mut node = root_node;
876 node.push_child(LocalNodeId(1));
877 node
878 }),
879 (LocalNodeId(1), Node::new(Role::RootWebArea)),
880 ],
881 tree: None,
882 tree_id: TreeId::ROOT,
883 focus: LocalNodeId(0),
884 };
885 struct Handler {
886 got_new_child_node: bool,
887 got_updated_root_node: bool,
888 }
889 fn unexpected_change() {
890 panic!("expected only new child node and updated root node");
891 }
892 impl super::ChangeHandler for Handler {
893 fn node_added(&mut self, node: &crate::Node) {
894 if node.id() == node_id(1) {
895 self.got_new_child_node = true;
896 return;
897 }
898 unexpected_change();
899 }
900 fn node_updated(&mut self, old_node: &crate::Node, new_node: &crate::Node) {
901 if new_node.id() == node_id(0)
902 && old_node.data().children().is_empty()
903 && new_node.data().children() == [LocalNodeId(1)]
904 {
905 self.got_updated_root_node = true;
906 return;
907 }
908 unexpected_change();
909 }
910 fn focus_moved(
911 &mut self,
912 _old_node: Option<&crate::Node>,
913 _new_node: Option<&crate::Node>,
914 ) {
915 unexpected_change();
916 }
917 fn node_removed(&mut self, _node: &crate::Node) {
918 unexpected_change();
919 }
920 }
921 let mut handler = Handler {
922 got_new_child_node: false,
923 got_updated_root_node: false,
924 };
925 tree.update_and_process_changes(second_update, &mut handler);
926 assert!(handler.got_new_child_node);
927 assert!(handler.got_updated_root_node);
928 let state = tree.state();
929 assert_eq!(1, state.root().children().count());
930 assert_eq!(node_id(1), state.root().children().next().unwrap().id());
931 assert_eq!(
932 node_id(0),
933 state.node_by_id(node_id(1)).unwrap().parent().unwrap().id()
934 );
935 }
936
937 #[test]
938 fn remove_child_from_root_node() {
939 let root_node = Node::new(Role::Window);
940 let first_update = TreeUpdate {
941 nodes: vec![
942 (LocalNodeId(0), {
943 let mut node = root_node.clone();
944 node.push_child(LocalNodeId(1));
945 node
946 }),
947 (LocalNodeId(1), Node::new(Role::RootWebArea)),
948 ],
949 tree: Some(Tree::new(LocalNodeId(0))),
950 tree_id: TreeId::ROOT,
951 focus: LocalNodeId(0),
952 };
953 let mut tree = super::Tree::new(first_update, false);
954 assert_eq!(1, tree.state().root().children().count());
955 let second_update = TreeUpdate {
956 nodes: vec![(LocalNodeId(0), root_node)],
957 tree: None,
958 tree_id: TreeId::ROOT,
959 focus: LocalNodeId(0),
960 };
961 struct Handler {
962 got_updated_root_node: bool,
963 got_removed_child_node: bool,
964 }
965 fn unexpected_change() {
966 panic!("expected only removed child node and updated root node");
967 }
968 impl super::ChangeHandler for Handler {
969 fn node_added(&mut self, _node: &crate::Node) {
970 unexpected_change();
971 }
972 fn node_updated(&mut self, old_node: &crate::Node, new_node: &crate::Node) {
973 if new_node.id() == node_id(0)
974 && old_node.data().children() == [LocalNodeId(1)]
975 && new_node.data().children().is_empty()
976 {
977 self.got_updated_root_node = true;
978 return;
979 }
980 unexpected_change();
981 }
982 fn focus_moved(
983 &mut self,
984 _old_node: Option<&crate::Node>,
985 _new_node: Option<&crate::Node>,
986 ) {
987 unexpected_change();
988 }
989 fn node_removed(&mut self, node: &crate::Node) {
990 if node.id() == node_id(1) {
991 self.got_removed_child_node = true;
992 return;
993 }
994 unexpected_change();
995 }
996 }
997 let mut handler = Handler {
998 got_updated_root_node: false,
999 got_removed_child_node: false,
1000 };
1001 tree.update_and_process_changes(second_update, &mut handler);
1002 assert!(handler.got_updated_root_node);
1003 assert!(handler.got_removed_child_node);
1004 assert_eq!(0, tree.state().root().children().count());
1005 assert!(tree.state().node_by_id(node_id(1)).is_none());
1006 }
1007
1008 #[test]
1009 fn move_focus_between_siblings() {
1010 let first_update = TreeUpdate {
1011 nodes: vec![
1012 (LocalNodeId(0), {
1013 let mut node = Node::new(Role::Window);
1014 node.set_children(vec![LocalNodeId(1), LocalNodeId(2)]);
1015 node
1016 }),
1017 (LocalNodeId(1), Node::new(Role::Button)),
1018 (LocalNodeId(2), Node::new(Role::Button)),
1019 ],
1020 tree: Some(Tree::new(LocalNodeId(0))),
1021 tree_id: TreeId::ROOT,
1022 focus: LocalNodeId(1),
1023 };
1024 let mut tree = super::Tree::new(first_update, true);
1025 assert!(tree.state().node_by_id(node_id(1)).unwrap().is_focused());
1026 let second_update = TreeUpdate {
1027 nodes: vec![],
1028 tree: None,
1029 tree_id: TreeId::ROOT,
1030 focus: LocalNodeId(2),
1031 };
1032 struct Handler {
1033 got_old_focus_node_update: bool,
1034 got_new_focus_node_update: bool,
1035 got_focus_change: bool,
1036 }
1037 fn unexpected_change() {
1038 panic!("expected only focus change");
1039 }
1040 impl super::ChangeHandler for Handler {
1041 fn node_added(&mut self, _node: &crate::Node) {
1042 unexpected_change();
1043 }
1044 fn node_updated(&mut self, old_node: &crate::Node, new_node: &crate::Node) {
1045 if old_node.id() == node_id(1)
1046 && new_node.id() == node_id(1)
1047 && old_node.is_focused()
1048 && !new_node.is_focused()
1049 {
1050 self.got_old_focus_node_update = true;
1051 return;
1052 }
1053 if old_node.id() == node_id(2)
1054 && new_node.id() == node_id(2)
1055 && !old_node.is_focused()
1056 && new_node.is_focused()
1057 {
1058 self.got_new_focus_node_update = true;
1059 return;
1060 }
1061 unexpected_change();
1062 }
1063 fn focus_moved(
1064 &mut self,
1065 old_node: Option<&crate::Node>,
1066 new_node: Option<&crate::Node>,
1067 ) {
1068 if let (Some(old_node), Some(new_node)) = (old_node, new_node) {
1069 if old_node.id() == node_id(1) && new_node.id() == node_id(2) {
1070 self.got_focus_change = true;
1071 return;
1072 }
1073 }
1074 unexpected_change();
1075 }
1076 fn node_removed(&mut self, _node: &crate::Node) {
1077 unexpected_change();
1078 }
1079 }
1080 let mut handler = Handler {
1081 got_old_focus_node_update: false,
1082 got_new_focus_node_update: false,
1083 got_focus_change: false,
1084 };
1085 tree.update_and_process_changes(second_update, &mut handler);
1086 assert!(handler.got_old_focus_node_update);
1087 assert!(handler.got_new_focus_node_update);
1088 assert!(handler.got_focus_change);
1089 assert!(tree.state().node_by_id(node_id(2)).unwrap().is_focused());
1090 assert!(!tree.state().node_by_id(node_id(1)).unwrap().is_focused());
1091 }
1092
1093 #[test]
1094 fn update_node() {
1095 let child_node = Node::new(Role::Button);
1096 let first_update = TreeUpdate {
1097 nodes: vec![
1098 (LocalNodeId(0), {
1099 let mut node = Node::new(Role::Window);
1100 node.set_children(vec![LocalNodeId(1)]);
1101 node
1102 }),
1103 (LocalNodeId(1), {
1104 let mut node = child_node.clone();
1105 node.set_label("foo");
1106 node
1107 }),
1108 ],
1109 tree: Some(Tree::new(LocalNodeId(0))),
1110 tree_id: TreeId::ROOT,
1111 focus: LocalNodeId(0),
1112 };
1113 let mut tree = super::Tree::new(first_update, false);
1114 assert_eq!(
1115 Some("foo".into()),
1116 tree.state().node_by_id(node_id(1)).unwrap().label()
1117 );
1118 let second_update = TreeUpdate {
1119 nodes: vec![(LocalNodeId(1), {
1120 let mut node = child_node;
1121 node.set_label("bar");
1122 node
1123 })],
1124 tree: None,
1125 tree_id: TreeId::ROOT,
1126 focus: LocalNodeId(0),
1127 };
1128 struct Handler {
1129 got_updated_child_node: bool,
1130 }
1131 fn unexpected_change() {
1132 panic!("expected only updated child node");
1133 }
1134 impl super::ChangeHandler for Handler {
1135 fn node_added(&mut self, _node: &crate::Node) {
1136 unexpected_change();
1137 }
1138 fn node_updated(&mut self, old_node: &crate::Node, new_node: &crate::Node) {
1139 if new_node.id() == node_id(1)
1140 && old_node.label() == Some("foo".into())
1141 && new_node.label() == Some("bar".into())
1142 {
1143 self.got_updated_child_node = true;
1144 return;
1145 }
1146 unexpected_change();
1147 }
1148 fn focus_moved(
1149 &mut self,
1150 _old_node: Option<&crate::Node>,
1151 _new_node: Option<&crate::Node>,
1152 ) {
1153 unexpected_change();
1154 }
1155 fn node_removed(&mut self, _node: &crate::Node) {
1156 unexpected_change();
1157 }
1158 }
1159 let mut handler = Handler {
1160 got_updated_child_node: false,
1161 };
1162 tree.update_and_process_changes(second_update, &mut handler);
1163 assert!(handler.got_updated_child_node);
1164 assert_eq!(
1165 Some("bar".into()),
1166 tree.state().node_by_id(node_id(1)).unwrap().label()
1167 );
1168 }
1169
1170 #[test]
1175 fn no_change_update() {
1176 let update = TreeUpdate {
1177 nodes: vec![
1178 (LocalNodeId(0), {
1179 let mut node = Node::new(Role::Window);
1180 node.set_children(vec![LocalNodeId(1)]);
1181 node
1182 }),
1183 (LocalNodeId(1), {
1184 let mut node = Node::new(Role::Button);
1185 node.set_label("foo");
1186 node
1187 }),
1188 ],
1189 tree: Some(Tree::new(LocalNodeId(0))),
1190 tree_id: TreeId::ROOT,
1191 focus: LocalNodeId(0),
1192 };
1193 let mut tree = super::Tree::new(update.clone(), false);
1194 struct Handler;
1195 fn unexpected_change() {
1196 panic!("expected no changes");
1197 }
1198 impl super::ChangeHandler for Handler {
1199 fn node_added(&mut self, _node: &crate::Node) {
1200 unexpected_change();
1201 }
1202 fn node_updated(&mut self, _old_node: &crate::Node, _new_node: &crate::Node) {
1203 unexpected_change();
1204 }
1205 fn focus_moved(
1206 &mut self,
1207 _old_node: Option<&crate::Node>,
1208 _new_node: Option<&crate::Node>,
1209 ) {
1210 unexpected_change();
1211 }
1212 fn node_removed(&mut self, _node: &crate::Node) {
1213 unexpected_change();
1214 }
1215 }
1216 let mut handler = Handler {};
1217 tree.update_and_process_changes(update, &mut handler);
1218 }
1219
1220 #[test]
1221 fn move_node() {
1222 struct Handler {
1223 got_updated_root: bool,
1224 got_updated_child: bool,
1225 got_removed_container: bool,
1226 }
1227
1228 fn unexpected_change() {
1229 panic!("expected only updated root and removed container");
1230 }
1231
1232 impl super::ChangeHandler for Handler {
1233 fn node_added(&mut self, _node: &crate::Node) {
1234 unexpected_change();
1235 }
1236 fn node_updated(&mut self, old_node: &crate::Node, new_node: &crate::Node) {
1237 if new_node.id() == node_id(0)
1238 && old_node.child_ids().collect::<Vec<NodeId>>() == vec![node_id(1)]
1239 && new_node.child_ids().collect::<Vec<NodeId>>() == vec![node_id(2)]
1240 {
1241 self.got_updated_root = true;
1242 return;
1243 }
1244 if new_node.id() == node_id(2)
1245 && old_node.parent_id() == Some(node_id(1))
1246 && new_node.parent_id() == Some(node_id(0))
1247 {
1248 self.got_updated_child = true;
1249 return;
1250 }
1251 unexpected_change();
1252 }
1253 fn focus_moved(
1254 &mut self,
1255 _old_node: Option<&crate::Node>,
1256 _new_node: Option<&crate::Node>,
1257 ) {
1258 unexpected_change();
1259 }
1260 fn node_removed(&mut self, node: &crate::Node) {
1261 if node.id() == node_id(1) {
1262 self.got_removed_container = true;
1263 return;
1264 }
1265 unexpected_change();
1266 }
1267 }
1268
1269 let mut root = Node::new(Role::Window);
1270 root.set_children([LocalNodeId(1)]);
1271 let mut container = Node::new(Role::GenericContainer);
1272 container.set_children([LocalNodeId(2)]);
1273 let update = TreeUpdate {
1274 nodes: vec![
1275 (LocalNodeId(0), root.clone()),
1276 (LocalNodeId(1), container),
1277 (LocalNodeId(2), Node::new(Role::Button)),
1278 ],
1279 tree: Some(Tree::new(LocalNodeId(0))),
1280 tree_id: TreeId::ROOT,
1281 focus: LocalNodeId(0),
1282 };
1283 let mut tree = crate::Tree::new(update, false);
1284 root.set_children([LocalNodeId(2)]);
1285 let mut handler = Handler {
1286 got_updated_root: false,
1287 got_updated_child: false,
1288 got_removed_container: false,
1289 };
1290 tree.update_and_process_changes(
1291 TreeUpdate {
1292 nodes: vec![(LocalNodeId(0), root)],
1293 tree: None,
1294 tree_id: TreeId::ROOT,
1295 focus: LocalNodeId(0),
1296 },
1297 &mut handler,
1298 );
1299 assert!(handler.got_updated_root);
1300 assert!(handler.got_updated_child);
1301 assert!(handler.got_removed_container);
1302 assert_eq!(
1303 tree.state()
1304 .node_by_id(node_id(0))
1305 .unwrap()
1306 .child_ids()
1307 .collect::<Vec<NodeId>>(),
1308 vec![node_id(2)]
1309 );
1310 assert!(tree.state().node_by_id(node_id(1)).is_none());
1311 assert_eq!(
1312 tree.state().node_by_id(node_id(2)).unwrap().parent_id(),
1313 Some(node_id(0))
1314 );
1315 }
1316
1317 fn subtree_id() -> TreeId {
1318 TreeId(Uuid::from_u128(1))
1319 }
1320
1321 #[test]
1322 fn graft_node_tracks_subtree() {
1323 let update = TreeUpdate {
1324 nodes: vec![
1325 (LocalNodeId(0), {
1326 let mut node = Node::new(Role::Window);
1327 node.set_children(vec![LocalNodeId(1)]);
1328 node
1329 }),
1330 (LocalNodeId(1), {
1331 let mut node = Node::new(Role::GenericContainer);
1332 node.set_tree_id(subtree_id());
1333 node
1334 }),
1335 ],
1336 tree: Some(Tree::new(LocalNodeId(0))),
1337 tree_id: TreeId::ROOT,
1338 focus: LocalNodeId(0),
1339 };
1340 let tree = super::Tree::new(update, false);
1341 assert_eq!(
1342 tree.state().graft_parents.get(&subtree_id()),
1343 Some(&node_id(1))
1344 );
1345 }
1346
1347 #[test]
1348 #[should_panic(expected = "already has a graft parent")]
1349 fn duplicate_graft_parent_panics() {
1350 let update = TreeUpdate {
1351 nodes: vec![
1352 (LocalNodeId(0), {
1353 let mut node = Node::new(Role::Window);
1354 node.set_children(vec![LocalNodeId(1), LocalNodeId(2)]);
1355 node
1356 }),
1357 (LocalNodeId(1), {
1358 let mut node = Node::new(Role::GenericContainer);
1359 node.set_tree_id(subtree_id());
1360 node
1361 }),
1362 (LocalNodeId(2), {
1363 let mut node = Node::new(Role::GenericContainer);
1364 node.set_tree_id(subtree_id());
1365 node
1366 }),
1367 ],
1368 tree: Some(Tree::new(LocalNodeId(0))),
1369 tree_id: TreeId::ROOT,
1370 focus: LocalNodeId(0),
1371 };
1372 let _ = super::Tree::new(update, false);
1373 }
1374
1375 #[test]
1376 fn reparent_subtree_by_removing_old_graft() {
1377 let update = TreeUpdate {
1378 nodes: vec![
1379 (LocalNodeId(0), {
1380 let mut node = Node::new(Role::Window);
1381 node.set_children(vec![LocalNodeId(1), LocalNodeId(2)]);
1382 node
1383 }),
1384 (LocalNodeId(1), {
1385 let mut node = Node::new(Role::GenericContainer);
1386 node.set_tree_id(subtree_id());
1387 node
1388 }),
1389 (LocalNodeId(2), Node::new(Role::GenericContainer)),
1390 ],
1391 tree: Some(Tree::new(LocalNodeId(0))),
1392 tree_id: TreeId::ROOT,
1393 focus: LocalNodeId(0),
1394 };
1395 let mut tree = super::Tree::new(update, false);
1396 assert_eq!(
1397 tree.state().graft_parents.get(&subtree_id()),
1398 Some(&node_id(1))
1399 );
1400
1401 let update = TreeUpdate {
1402 nodes: vec![
1403 (LocalNodeId(0), {
1404 let mut node = Node::new(Role::Window);
1405 node.set_children(vec![LocalNodeId(2)]);
1406 node
1407 }),
1408 (LocalNodeId(2), {
1409 let mut node = Node::new(Role::GenericContainer);
1410 node.set_tree_id(subtree_id());
1411 node
1412 }),
1413 ],
1414 tree: None,
1415 tree_id: TreeId::ROOT,
1416 focus: LocalNodeId(0),
1417 };
1418 tree.update_and_process_changes(update, &mut NoOpHandler);
1419 assert_eq!(
1420 tree.state().graft_parents.get(&subtree_id()),
1421 Some(&node_id(2))
1422 );
1423 }
1424
1425 #[test]
1426 fn reparent_subtree_by_clearing_old_graft_tree_id() {
1427 let update = TreeUpdate {
1428 nodes: vec![
1429 (LocalNodeId(0), {
1430 let mut node = Node::new(Role::Window);
1431 node.set_children(vec![LocalNodeId(1), LocalNodeId(2)]);
1432 node
1433 }),
1434 (LocalNodeId(1), {
1435 let mut node = Node::new(Role::GenericContainer);
1436 node.set_tree_id(subtree_id());
1437 node
1438 }),
1439 (LocalNodeId(2), Node::new(Role::GenericContainer)),
1440 ],
1441 tree: Some(Tree::new(LocalNodeId(0))),
1442 tree_id: TreeId::ROOT,
1443 focus: LocalNodeId(0),
1444 };
1445 let mut tree = super::Tree::new(update, false);
1446 assert_eq!(
1447 tree.state().graft_parents.get(&subtree_id()),
1448 Some(&node_id(1))
1449 );
1450
1451 let update = TreeUpdate {
1452 nodes: vec![
1453 (LocalNodeId(1), Node::new(Role::GenericContainer)),
1454 (LocalNodeId(2), {
1455 let mut node = Node::new(Role::GenericContainer);
1456 node.set_tree_id(subtree_id());
1457 node
1458 }),
1459 ],
1460 tree: None,
1461 tree_id: TreeId::ROOT,
1462 focus: LocalNodeId(0),
1463 };
1464 tree.update_and_process_changes(update, &mut NoOpHandler);
1465 assert_eq!(
1466 tree.state().graft_parents.get(&subtree_id()),
1467 Some(&node_id(2))
1468 );
1469 }
1470
1471 #[test]
1472 #[should_panic(expected = "already has a graft parent")]
1473 fn duplicate_graft_parent_on_update_panics() {
1474 let update = TreeUpdate {
1475 nodes: vec![
1476 (LocalNodeId(0), {
1477 let mut node = Node::new(Role::Window);
1478 node.set_children(vec![LocalNodeId(1), LocalNodeId(2)]);
1479 node
1480 }),
1481 (LocalNodeId(1), {
1482 let mut node = Node::new(Role::GenericContainer);
1483 node.set_tree_id(subtree_id());
1484 node
1485 }),
1486 (LocalNodeId(2), Node::new(Role::GenericContainer)),
1487 ],
1488 tree: Some(Tree::new(LocalNodeId(0))),
1489 tree_id: TreeId::ROOT,
1490 focus: LocalNodeId(0),
1491 };
1492 let mut tree = super::Tree::new(update, false);
1493
1494 let update = TreeUpdate {
1495 nodes: vec![(LocalNodeId(2), {
1496 let mut node = Node::new(Role::GenericContainer);
1497 node.set_tree_id(subtree_id());
1498 node
1499 })],
1500 tree: None,
1501 tree_id: TreeId::ROOT,
1502 focus: LocalNodeId(0),
1503 };
1504 tree.update_and_process_changes(update, &mut NoOpHandler);
1505 }
1506
1507 #[test]
1508 #[should_panic(expected = "Cannot graft the root tree")]
1509 fn graft_root_tree_panics() {
1510 let update = TreeUpdate {
1511 nodes: vec![
1512 (LocalNodeId(0), {
1513 let mut node = Node::new(Role::Window);
1514 node.set_children(vec![LocalNodeId(1)]);
1515 node
1516 }),
1517 (LocalNodeId(1), {
1518 let mut node = Node::new(Role::GenericContainer);
1519 node.set_tree_id(TreeId::ROOT);
1520 node
1521 }),
1522 ],
1523 tree: Some(Tree::new(LocalNodeId(0))),
1524 tree_id: TreeId::ROOT,
1525 focus: LocalNodeId(0),
1526 };
1527 let _ = super::Tree::new(update, false);
1528 }
1529
1530 #[test]
1531 #[should_panic(expected = "Cannot graft the root tree")]
1532 fn graft_root_tree_on_update_panics() {
1533 let update = TreeUpdate {
1534 nodes: vec![
1535 (LocalNodeId(0), {
1536 let mut node = Node::new(Role::Window);
1537 node.set_children(vec![LocalNodeId(1)]);
1538 node
1539 }),
1540 (LocalNodeId(1), Node::new(Role::GenericContainer)),
1541 ],
1542 tree: Some(Tree::new(LocalNodeId(0))),
1543 tree_id: TreeId::ROOT,
1544 focus: LocalNodeId(0),
1545 };
1546 let mut tree = super::Tree::new(update, false);
1547
1548 let update = TreeUpdate {
1549 nodes: vec![(LocalNodeId(1), {
1550 let mut node = Node::new(Role::GenericContainer);
1551 node.set_tree_id(TreeId::ROOT);
1552 node
1553 })],
1554 tree: None,
1555 tree_id: TreeId::ROOT,
1556 focus: LocalNodeId(0),
1557 };
1558 tree.update_and_process_changes(update, &mut NoOpHandler);
1559 }
1560
1561 fn subtree_node_id(id: u64) -> NodeId {
1562 NodeId::new(LocalNodeId(id), TreeIndex(1))
1563 }
1564
1565 #[test]
1566 fn subtree_root_parent_is_graft_when_graft_exists_first() {
1567 let update = TreeUpdate {
1568 nodes: vec![
1569 (LocalNodeId(0), {
1570 let mut node = Node::new(Role::Window);
1571 node.set_children(vec![LocalNodeId(1)]);
1572 node
1573 }),
1574 (LocalNodeId(1), {
1575 let mut node = Node::new(Role::GenericContainer);
1576 node.set_tree_id(subtree_id());
1577 node
1578 }),
1579 ],
1580 tree: Some(Tree::new(LocalNodeId(0))),
1581 tree_id: TreeId::ROOT,
1582 focus: LocalNodeId(0),
1583 };
1584 let mut tree = super::Tree::new(update, false);
1585
1586 let subtree_update = TreeUpdate {
1587 nodes: vec![(LocalNodeId(0), Node::new(Role::Document))],
1588 tree: Some(Tree::new(LocalNodeId(0))),
1589 tree_id: subtree_id(),
1590 focus: LocalNodeId(0),
1591 };
1592 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
1593
1594 let subtree_root = tree.state().node_by_id(subtree_node_id(0)).unwrap();
1595 assert_eq!(subtree_root.parent_id(), Some(node_id(1)));
1596
1597 let graft_node = tree.state().node_by_id(node_id(1)).unwrap();
1598 let children: Vec<_> = graft_node.child_ids().collect();
1599 assert_eq!(children.len(), 1);
1600 assert_eq!(children[0], subtree_node_id(0));
1601 }
1602
1603 #[test]
1604 #[should_panic(expected = "no graft node exists for this tree")]
1605 fn subtree_push_without_graft_panics() {
1606 let update = TreeUpdate {
1607 nodes: vec![(LocalNodeId(0), Node::new(Role::Window))],
1608 tree: Some(Tree::new(LocalNodeId(0))),
1609 tree_id: TreeId::ROOT,
1610 focus: LocalNodeId(0),
1611 };
1612 let mut tree = super::Tree::new(update, false);
1613
1614 let subtree_update = TreeUpdate {
1615 nodes: vec![(LocalNodeId(0), Node::new(Role::Document))],
1616 tree: Some(Tree::new(LocalNodeId(0))),
1617 tree_id: subtree_id(),
1618 focus: LocalNodeId(0),
1619 };
1620 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
1621 }
1622
1623 #[test]
1624 #[should_panic(expected = "subtree does not exist")]
1625 fn subtree_update_without_tree_data_panics() {
1626 let update = TreeUpdate {
1627 nodes: vec![
1628 (LocalNodeId(0), {
1629 let mut node = Node::new(Role::Window);
1630 node.set_children(vec![LocalNodeId(1)]);
1631 node
1632 }),
1633 (LocalNodeId(1), {
1634 let mut node = Node::new(Role::GenericContainer);
1635 node.set_tree_id(subtree_id());
1636 node
1637 }),
1638 ],
1639 tree: Some(Tree::new(LocalNodeId(0))),
1640 tree_id: TreeId::ROOT,
1641 focus: LocalNodeId(0),
1642 };
1643 let mut tree = super::Tree::new(update, false);
1644
1645 let subtree_update = TreeUpdate {
1646 nodes: vec![(LocalNodeId(0), Node::new(Role::Document))],
1647 tree: None,
1648 tree_id: subtree_id(),
1649 focus: LocalNodeId(0),
1650 };
1651 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
1652 }
1653
1654 #[test]
1655 fn subtree_nodes_removed_when_graft_removed() {
1656 let update = TreeUpdate {
1657 nodes: vec![
1658 (LocalNodeId(0), {
1659 let mut node = Node::new(Role::Window);
1660 node.set_children(vec![LocalNodeId(1)]);
1661 node
1662 }),
1663 (LocalNodeId(1), {
1664 let mut node = Node::new(Role::GenericContainer);
1665 node.set_tree_id(subtree_id());
1666 node
1667 }),
1668 ],
1669 tree: Some(Tree::new(LocalNodeId(0))),
1670 tree_id: TreeId::ROOT,
1671 focus: LocalNodeId(0),
1672 };
1673 let mut tree = super::Tree::new(update, false);
1674
1675 let subtree_update = TreeUpdate {
1676 nodes: vec![
1677 (LocalNodeId(0), {
1678 let mut node = Node::new(Role::Document);
1679 node.set_children(vec![LocalNodeId(1)]);
1680 node
1681 }),
1682 (LocalNodeId(1), {
1683 let mut node = Node::new(Role::GenericContainer);
1684 node.set_tree_id(nested_subtree_id());
1685 node
1686 }),
1687 ],
1688 tree: Some(Tree::new(LocalNodeId(0))),
1689 tree_id: subtree_id(),
1690 focus: LocalNodeId(0),
1691 };
1692 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
1693
1694 let nested_update = TreeUpdate {
1695 nodes: vec![
1696 (LocalNodeId(0), {
1697 let mut node = Node::new(Role::Document);
1698 node.set_children(vec![LocalNodeId(1)]);
1699 node
1700 }),
1701 (LocalNodeId(1), Node::new(Role::Paragraph)),
1702 ],
1703 tree: Some(Tree::new(LocalNodeId(0))),
1704 tree_id: nested_subtree_id(),
1705 focus: LocalNodeId(0),
1706 };
1707 tree.update_and_process_changes(nested_update, &mut NoOpHandler);
1708
1709 assert!(tree.state().node_by_id(subtree_node_id(0)).is_some());
1710 assert!(tree.state().node_by_id(subtree_node_id(1)).is_some());
1711 assert!(tree.state().node_by_id(nested_subtree_node_id(0)).is_some());
1712 assert!(tree.state().node_by_id(nested_subtree_node_id(1)).is_some());
1713
1714 let update = TreeUpdate {
1715 nodes: vec![(LocalNodeId(0), {
1716 let mut node = Node::new(Role::Window);
1717 node.set_children(vec![]);
1718 node
1719 })],
1720 tree: None,
1721 tree_id: TreeId::ROOT,
1722 focus: LocalNodeId(0),
1723 };
1724 tree.update_and_process_changes(update, &mut NoOpHandler);
1725
1726 assert!(tree.state().node_by_id(subtree_node_id(0)).is_none());
1727 assert!(tree.state().node_by_id(subtree_node_id(1)).is_none());
1728 assert!(tree.state().node_by_id(nested_subtree_node_id(0)).is_none());
1729 assert!(tree.state().node_by_id(nested_subtree_node_id(1)).is_none());
1730 assert!(tree.state().subtrees.get(&subtree_id()).is_none());
1731 assert!(tree.state().subtrees.get(&nested_subtree_id()).is_none());
1732 }
1733
1734 #[test]
1735 fn subtree_nodes_removed_when_graft_tree_id_cleared() {
1736 let update = TreeUpdate {
1737 nodes: vec![
1738 (LocalNodeId(0), {
1739 let mut node = Node::new(Role::Window);
1740 node.set_children(vec![LocalNodeId(1)]);
1741 node
1742 }),
1743 (LocalNodeId(1), {
1744 let mut node = Node::new(Role::GenericContainer);
1745 node.set_tree_id(subtree_id());
1746 node
1747 }),
1748 ],
1749 tree: Some(Tree::new(LocalNodeId(0))),
1750 tree_id: TreeId::ROOT,
1751 focus: LocalNodeId(0),
1752 };
1753 let mut tree = super::Tree::new(update, false);
1754
1755 let subtree_update = TreeUpdate {
1756 nodes: vec![
1757 (LocalNodeId(0), {
1758 let mut node = Node::new(Role::Document);
1759 node.set_children(vec![LocalNodeId(1)]);
1760 node
1761 }),
1762 (LocalNodeId(1), Node::new(Role::Paragraph)),
1763 ],
1764 tree: Some(Tree::new(LocalNodeId(0))),
1765 tree_id: subtree_id(),
1766 focus: LocalNodeId(0),
1767 };
1768 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
1769
1770 assert!(tree.state().node_by_id(subtree_node_id(0)).is_some());
1771 assert!(tree.state().node_by_id(subtree_node_id(1)).is_some());
1772
1773 let update = TreeUpdate {
1774 nodes: vec![(LocalNodeId(1), Node::new(Role::GenericContainer))],
1775 tree: None,
1776 tree_id: TreeId::ROOT,
1777 focus: LocalNodeId(0),
1778 };
1779 tree.update_and_process_changes(update, &mut NoOpHandler);
1780
1781 assert!(tree.state().node_by_id(subtree_node_id(0)).is_none());
1782 assert!(tree.state().node_by_id(subtree_node_id(1)).is_none());
1783 assert!(tree.state().subtrees.get(&subtree_id()).is_none());
1784 }
1785
1786 #[test]
1787 fn graft_node_has_no_children_when_subtree_not_pushed() {
1788 let update = TreeUpdate {
1789 nodes: vec![
1790 (LocalNodeId(0), {
1791 let mut node = Node::new(Role::Window);
1792 node.set_children(vec![LocalNodeId(1)]);
1793 node
1794 }),
1795 (LocalNodeId(1), {
1796 let mut node = Node::new(Role::GenericContainer);
1797 node.set_tree_id(subtree_id());
1798 node
1799 }),
1800 ],
1801 tree: Some(Tree::new(LocalNodeId(0))),
1802 tree_id: TreeId::ROOT,
1803 focus: LocalNodeId(0),
1804 };
1805 let tree = super::Tree::new(update, false);
1806
1807 let graft_node = tree.state().node_by_id(node_id(1)).unwrap();
1808 assert_eq!(graft_node.child_ids().count(), 0);
1809 assert_eq!(graft_node.children().count(), 0);
1810 }
1811
1812 #[test]
1813 #[should_panic(expected = "has both tree_id")]
1814 fn graft_node_with_children_panics() {
1815 let update = TreeUpdate {
1816 nodes: vec![
1817 (LocalNodeId(0), {
1818 let mut node = Node::new(Role::Window);
1819 node.set_children(vec![LocalNodeId(1)]);
1820 node
1821 }),
1822 (LocalNodeId(1), {
1823 let mut node = Node::new(Role::GenericContainer);
1824 node.set_tree_id(subtree_id());
1825 node.set_children(vec![LocalNodeId(2)]);
1826 node
1827 }),
1828 (LocalNodeId(2), Node::new(Role::Button)),
1829 ],
1830 tree: Some(Tree::new(LocalNodeId(0))),
1831 tree_id: TreeId::ROOT,
1832 focus: LocalNodeId(0),
1833 };
1834 super::Tree::new(update, false);
1835 }
1836
1837 #[test]
1838 fn node_added_called_when_subtree_pushed() {
1839 struct Handler {
1840 added_nodes: Vec<NodeId>,
1841 }
1842 impl super::ChangeHandler for Handler {
1843 fn node_added(&mut self, node: &crate::Node) {
1844 self.added_nodes.push(node.id());
1845 }
1846 fn node_updated(&mut self, _: &crate::Node, _: &crate::Node) {}
1847 fn focus_moved(&mut self, _: Option<&crate::Node>, _: Option<&crate::Node>) {}
1848 fn node_removed(&mut self, _: &crate::Node) {}
1849 }
1850
1851 let update = TreeUpdate {
1852 nodes: vec![
1853 (LocalNodeId(0), {
1854 let mut node = Node::new(Role::Window);
1855 node.set_children(vec![LocalNodeId(1)]);
1856 node
1857 }),
1858 (LocalNodeId(1), {
1859 let mut node = Node::new(Role::GenericContainer);
1860 node.set_tree_id(subtree_id());
1861 node
1862 }),
1863 ],
1864 tree: Some(Tree::new(LocalNodeId(0))),
1865 tree_id: TreeId::ROOT,
1866 focus: LocalNodeId(0),
1867 };
1868 let mut tree = super::Tree::new(update, false);
1869
1870 let mut handler = Handler {
1871 added_nodes: Vec::new(),
1872 };
1873
1874 let subtree_update = TreeUpdate {
1875 nodes: vec![
1876 (LocalNodeId(0), {
1877 let mut node = Node::new(Role::Document);
1878 node.set_children(vec![LocalNodeId(1), LocalNodeId(2)]);
1879 node
1880 }),
1881 (LocalNodeId(1), Node::new(Role::Paragraph)),
1882 (LocalNodeId(2), Node::new(Role::Button)),
1883 ],
1884 tree: Some(Tree::new(LocalNodeId(0))),
1885 tree_id: subtree_id(),
1886 focus: LocalNodeId(0),
1887 };
1888 tree.update_and_process_changes(subtree_update, &mut handler);
1889
1890 assert_eq!(handler.added_nodes.len(), 3,);
1891 assert!(handler.added_nodes.contains(&subtree_node_id(0)),);
1892 assert!(handler.added_nodes.contains(&subtree_node_id(1)),);
1893 assert!(handler.added_nodes.contains(&subtree_node_id(2)),);
1894 }
1895
1896 #[test]
1897 fn node_removed_called_when_graft_removed() {
1898 struct Handler {
1899 removed_nodes: Vec<NodeId>,
1900 }
1901 impl super::ChangeHandler for Handler {
1902 fn node_added(&mut self, _: &crate::Node) {}
1903 fn node_updated(&mut self, _: &crate::Node, _: &crate::Node) {}
1904 fn focus_moved(&mut self, _: Option<&crate::Node>, _: Option<&crate::Node>) {}
1905 fn node_removed(&mut self, node: &crate::Node) {
1906 self.removed_nodes.push(node.id());
1907 }
1908 }
1909
1910 let update = TreeUpdate {
1911 nodes: vec![
1912 (LocalNodeId(0), {
1913 let mut node = Node::new(Role::Window);
1914 node.set_children(vec![LocalNodeId(1)]);
1915 node
1916 }),
1917 (LocalNodeId(1), {
1918 let mut node = Node::new(Role::GenericContainer);
1919 node.set_tree_id(subtree_id());
1920 node
1921 }),
1922 ],
1923 tree: Some(Tree::new(LocalNodeId(0))),
1924 tree_id: TreeId::ROOT,
1925 focus: LocalNodeId(0),
1926 };
1927 let mut tree = super::Tree::new(update, false);
1928
1929 let subtree_update = TreeUpdate {
1930 nodes: vec![
1931 (LocalNodeId(0), {
1932 let mut node = Node::new(Role::Document);
1933 node.set_children(vec![LocalNodeId(1)]);
1934 node
1935 }),
1936 (LocalNodeId(1), Node::new(Role::Paragraph)),
1937 ],
1938 tree: Some(Tree::new(LocalNodeId(0))),
1939 tree_id: subtree_id(),
1940 focus: LocalNodeId(0),
1941 };
1942 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
1943
1944 assert!(tree.state().node_by_id(subtree_node_id(0)).is_some());
1945 assert!(tree.state().node_by_id(subtree_node_id(1)).is_some());
1946
1947 let mut handler = Handler {
1948 removed_nodes: Vec::new(),
1949 };
1950
1951 let update = TreeUpdate {
1952 nodes: vec![(LocalNodeId(0), {
1953 let mut node = Node::new(Role::Window);
1954 node.set_children(vec![]);
1955 node
1956 })],
1957 tree: None,
1958 tree_id: TreeId::ROOT,
1959 focus: LocalNodeId(0),
1960 };
1961 tree.update_and_process_changes(update, &mut handler);
1962
1963 assert!(handler.removed_nodes.contains(&node_id(1)),);
1964 assert!(handler.removed_nodes.contains(&subtree_node_id(0)),);
1965 assert!(handler.removed_nodes.contains(&subtree_node_id(1)),);
1966 assert_eq!(handler.removed_nodes.len(), 3,);
1967 }
1968
1969 #[test]
1970 fn node_updated_called_when_subtree_reparented() {
1971 struct Handler {
1972 updated_nodes: Vec<NodeId>,
1973 }
1974 impl super::ChangeHandler for Handler {
1975 fn node_added(&mut self, _: &crate::Node) {}
1976 fn node_updated(&mut self, _old: &crate::Node, new: &crate::Node) {
1977 self.updated_nodes.push(new.id());
1978 }
1979 fn focus_moved(&mut self, _: Option<&crate::Node>, _: Option<&crate::Node>) {}
1980 fn node_removed(&mut self, _: &crate::Node) {}
1981 }
1982
1983 let update = TreeUpdate {
1984 nodes: vec![
1985 (LocalNodeId(0), {
1986 let mut node = Node::new(Role::Window);
1987 node.set_children(vec![LocalNodeId(1), LocalNodeId(2)]);
1988 node
1989 }),
1990 (LocalNodeId(1), {
1991 let mut node = Node::new(Role::GenericContainer);
1992 node.set_tree_id(subtree_id());
1993 node
1994 }),
1995 (LocalNodeId(2), Node::new(Role::GenericContainer)),
1996 ],
1997 tree: Some(Tree::new(LocalNodeId(0))),
1998 tree_id: TreeId::ROOT,
1999 focus: LocalNodeId(0),
2000 };
2001 let mut tree = super::Tree::new(update, false);
2002
2003 let subtree_update = TreeUpdate {
2004 nodes: vec![(LocalNodeId(0), Node::new(Role::Document))],
2005 tree: Some(Tree::new(LocalNodeId(0))),
2006 tree_id: subtree_id(),
2007 focus: LocalNodeId(0),
2008 };
2009 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
2010
2011 let subtree_root = tree.state().node_by_id(subtree_node_id(0)).unwrap();
2012 assert_eq!(subtree_root.parent().unwrap().id(), node_id(1));
2013
2014 let mut handler = Handler {
2015 updated_nodes: Vec::new(),
2016 };
2017
2018 let update = TreeUpdate {
2019 nodes: vec![
2020 (LocalNodeId(1), Node::new(Role::GenericContainer)),
2021 (LocalNodeId(2), {
2022 let mut node = Node::new(Role::GenericContainer);
2023 node.set_tree_id(subtree_id());
2024 node
2025 }),
2026 ],
2027 tree: None,
2028 tree_id: TreeId::ROOT,
2029 focus: LocalNodeId(0),
2030 };
2031 tree.update_and_process_changes(update, &mut handler);
2032
2033 assert!(handler.updated_nodes.contains(&subtree_node_id(0)),);
2034
2035 let subtree_root = tree.state().node_by_id(subtree_node_id(0)).unwrap();
2036 assert_eq!(subtree_root.parent().unwrap().id(), node_id(2));
2037 }
2038
2039 #[test]
2040 fn focus_moved_called_when_focus_moves_to_subtree() {
2041 struct Handler {
2042 focus_moves: Vec<(Option<NodeId>, Option<NodeId>)>,
2043 }
2044 impl super::ChangeHandler for Handler {
2045 fn node_added(&mut self, _: &crate::Node) {}
2046 fn node_updated(&mut self, _: &crate::Node, _: &crate::Node) {}
2047 fn focus_moved(&mut self, old: Option<&crate::Node>, new: Option<&crate::Node>) {
2048 self.focus_moves
2049 .push((old.map(|n| n.id()), new.map(|n| n.id())));
2050 }
2051 fn node_removed(&mut self, _: &crate::Node) {}
2052 }
2053
2054 let update = TreeUpdate {
2055 nodes: vec![
2056 (LocalNodeId(0), {
2057 let mut node = Node::new(Role::Window);
2058 node.set_children(vec![LocalNodeId(1)]);
2059 node
2060 }),
2061 (LocalNodeId(1), {
2062 let mut node = Node::new(Role::GenericContainer);
2063 node.set_tree_id(subtree_id());
2064 node
2065 }),
2066 ],
2067 tree: Some(Tree::new(LocalNodeId(0))),
2068 tree_id: TreeId::ROOT,
2069 focus: LocalNodeId(0),
2070 };
2071 let mut tree = super::Tree::new(update, true);
2072
2073 let subtree_update = TreeUpdate {
2074 nodes: vec![
2075 (LocalNodeId(0), {
2076 let mut node = Node::new(Role::Document);
2077 node.set_children(vec![LocalNodeId(1)]);
2078 node
2079 }),
2080 (LocalNodeId(1), Node::new(Role::Button)),
2081 ],
2082 tree: Some(Tree::new(LocalNodeId(0))),
2083 tree_id: subtree_id(),
2084 focus: LocalNodeId(0),
2085 };
2086 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
2087
2088 let mut handler = Handler {
2089 focus_moves: Vec::new(),
2090 };
2091
2092 let update = TreeUpdate {
2093 nodes: vec![],
2094 tree: None,
2095 tree_id: TreeId::ROOT,
2096 focus: LocalNodeId(1),
2097 };
2098 tree.update_and_process_changes(update, &mut handler);
2099
2100 assert_eq!(handler.focus_moves.len(), 1,);
2101 let (old_focus, new_focus) = &handler.focus_moves[0];
2102 assert_eq!(*old_focus, Some(node_id(0)),);
2103 assert_eq!(*new_focus, Some(subtree_node_id(0)),);
2104 }
2105
2106 #[test]
2107 fn focus_moved_called_when_subtree_focus_changes() {
2108 struct Handler {
2109 focus_moves: Vec<(Option<NodeId>, Option<NodeId>)>,
2110 }
2111 impl super::ChangeHandler for Handler {
2112 fn node_added(&mut self, _: &crate::Node) {}
2113 fn node_updated(&mut self, _: &crate::Node, _: &crate::Node) {}
2114 fn focus_moved(&mut self, old: Option<&crate::Node>, new: Option<&crate::Node>) {
2115 self.focus_moves
2116 .push((old.map(|n| n.id()), new.map(|n| n.id())));
2117 }
2118 fn node_removed(&mut self, _: &crate::Node) {}
2119 }
2120
2121 let update = TreeUpdate {
2122 nodes: vec![
2123 (LocalNodeId(0), {
2124 let mut node = Node::new(Role::Window);
2125 node.set_children(vec![LocalNodeId(1)]);
2126 node
2127 }),
2128 (LocalNodeId(1), {
2129 let mut node = Node::new(Role::GenericContainer);
2130 node.set_tree_id(subtree_id());
2131 node
2132 }),
2133 ],
2134 tree: Some(Tree::new(LocalNodeId(0))),
2135 tree_id: TreeId::ROOT,
2136 focus: LocalNodeId(0),
2137 };
2138 let mut tree = super::Tree::new(update, true);
2139
2140 let subtree_update = TreeUpdate {
2141 nodes: vec![
2142 (LocalNodeId(0), {
2143 let mut node = Node::new(Role::Document);
2144 node.set_children(vec![LocalNodeId(1)]);
2145 node
2146 }),
2147 (LocalNodeId(1), Node::new(Role::Button)),
2148 ],
2149 tree: Some(Tree::new(LocalNodeId(0))),
2150 tree_id: subtree_id(),
2151 focus: LocalNodeId(0),
2152 };
2153 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
2154
2155 let root_update = TreeUpdate {
2156 nodes: vec![],
2157 tree: None,
2158 tree_id: TreeId::ROOT,
2159 focus: LocalNodeId(1),
2160 };
2161 tree.update_and_process_changes(root_update, &mut NoOpHandler);
2162
2163 let mut handler = Handler {
2164 focus_moves: Vec::new(),
2165 };
2166
2167 let subtree_update = TreeUpdate {
2168 nodes: vec![],
2169 tree: None,
2170 tree_id: subtree_id(),
2171 focus: LocalNodeId(1),
2172 };
2173 tree.update_and_process_changes(subtree_update, &mut handler);
2174
2175 assert_eq!(handler.focus_moves.len(), 1,);
2176 let (old_focus, new_focus) = &handler.focus_moves[0];
2177 assert_eq!(*old_focus, Some(subtree_node_id(0)),);
2178 assert_eq!(*new_focus, Some(subtree_node_id(1)),);
2179 }
2180
2181 fn nested_subtree_id() -> TreeId {
2182 TreeId(Uuid::from_u128(2))
2183 }
2184
2185 fn nested_subtree_node_id(n: u64) -> NodeId {
2186 NodeId::new(LocalNodeId(n), TreeIndex(2))
2187 }
2188
2189 #[test]
2190 fn nested_subtree_focus_follows_graft_chain() {
2191 let update = TreeUpdate {
2192 nodes: vec![
2193 (LocalNodeId(0), {
2194 let mut node = Node::new(Role::Window);
2195 node.set_children(vec![LocalNodeId(1)]);
2196 node
2197 }),
2198 (LocalNodeId(1), {
2199 let mut node = Node::new(Role::GenericContainer);
2200 node.set_tree_id(subtree_id());
2201 node
2202 }),
2203 ],
2204 tree: Some(Tree::new(LocalNodeId(0))),
2205 tree_id: TreeId::ROOT,
2206 focus: LocalNodeId(0),
2207 };
2208 let mut tree = super::Tree::new(update, true);
2209
2210 let subtree_update = TreeUpdate {
2211 nodes: vec![
2212 (LocalNodeId(0), {
2213 let mut node = Node::new(Role::Document);
2214 node.set_children(vec![LocalNodeId(1)]);
2215 node
2216 }),
2217 (LocalNodeId(1), {
2218 let mut node = Node::new(Role::GenericContainer);
2219 node.set_tree_id(nested_subtree_id());
2220 node
2221 }),
2222 ],
2223 tree: Some(Tree::new(LocalNodeId(0))),
2224 tree_id: subtree_id(),
2225 focus: LocalNodeId(0),
2226 };
2227 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
2228
2229 let nested_update = TreeUpdate {
2230 nodes: vec![
2231 (LocalNodeId(0), {
2232 let mut node = Node::new(Role::Group);
2233 node.set_children(vec![LocalNodeId(1)]);
2234 node
2235 }),
2236 (LocalNodeId(1), Node::new(Role::Button)),
2237 ],
2238 tree: Some(Tree::new(LocalNodeId(0))),
2239 tree_id: nested_subtree_id(),
2240 focus: LocalNodeId(1),
2241 };
2242 tree.update_and_process_changes(nested_update, &mut NoOpHandler);
2243
2244 let update = TreeUpdate {
2245 nodes: vec![],
2246 tree: None,
2247 tree_id: TreeId::ROOT,
2248 focus: LocalNodeId(1),
2249 };
2250 tree.update_and_process_changes(update, &mut NoOpHandler);
2251
2252 let update = TreeUpdate {
2253 nodes: vec![],
2254 tree: None,
2255 tree_id: subtree_id(),
2256 focus: LocalNodeId(1),
2257 };
2258 tree.update_and_process_changes(update, &mut NoOpHandler);
2259
2260 assert_eq!(tree.state().focus_id(), Some(nested_subtree_node_id(1)),);
2261 }
2262
2263 #[test]
2264 fn nested_subtree_focus_update_changes_effective_focus() {
2265 let update = TreeUpdate {
2266 nodes: vec![
2267 (LocalNodeId(0), {
2268 let mut node = Node::new(Role::Window);
2269 node.set_children(vec![LocalNodeId(1)]);
2270 node
2271 }),
2272 (LocalNodeId(1), {
2273 let mut node = Node::new(Role::GenericContainer);
2274 node.set_tree_id(subtree_id());
2275 node
2276 }),
2277 ],
2278 tree: Some(Tree::new(LocalNodeId(0))),
2279 tree_id: TreeId::ROOT,
2280 focus: LocalNodeId(0),
2281 };
2282 let mut tree = super::Tree::new(update, true);
2283
2284 let subtree_update = TreeUpdate {
2285 nodes: vec![
2286 (LocalNodeId(0), {
2287 let mut node = Node::new(Role::Document);
2288 node.set_children(vec![LocalNodeId(1)]);
2289 node
2290 }),
2291 (LocalNodeId(1), {
2292 let mut node = Node::new(Role::GenericContainer);
2293 node.set_tree_id(nested_subtree_id());
2294 node
2295 }),
2296 ],
2297 tree: Some(Tree::new(LocalNodeId(0))),
2298 tree_id: subtree_id(),
2299 focus: LocalNodeId(1),
2300 };
2301 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
2302
2303 let nested_update = TreeUpdate {
2304 nodes: vec![
2305 (LocalNodeId(0), {
2306 let mut node = Node::new(Role::Group);
2307 node.set_children(vec![LocalNodeId(1), LocalNodeId(2)]);
2308 node
2309 }),
2310 (LocalNodeId(1), Node::new(Role::Button)),
2311 (LocalNodeId(2), Node::new(Role::Button)),
2312 ],
2313 tree: Some(Tree::new(LocalNodeId(0))),
2314 tree_id: nested_subtree_id(),
2315 focus: LocalNodeId(1),
2316 };
2317 tree.update_and_process_changes(nested_update, &mut NoOpHandler);
2318
2319 let root_update = TreeUpdate {
2320 nodes: vec![],
2321 tree: None,
2322 tree_id: TreeId::ROOT,
2323 focus: LocalNodeId(1),
2324 };
2325 tree.update_and_process_changes(root_update, &mut NoOpHandler);
2326
2327 assert_eq!(tree.state().focus_id(), Some(nested_subtree_node_id(1)));
2328
2329 let update = TreeUpdate {
2330 nodes: vec![],
2331 tree: None,
2332 tree_id: nested_subtree_id(),
2333 focus: LocalNodeId(2),
2334 };
2335 tree.update_and_process_changes(update, &mut NoOpHandler);
2336
2337 assert_eq!(tree.state().focus_id(), Some(nested_subtree_node_id(2)),);
2338 }
2339
2340 #[test]
2341 #[should_panic(expected = "Graft nodes cannot be focused without their subtree")]
2342 fn removing_nested_subtree_while_intermediate_focus_on_graft_panics() {
2343 let update = TreeUpdate {
2344 nodes: vec![
2345 (LocalNodeId(0), {
2346 let mut node = Node::new(Role::Window);
2347 node.set_children(vec![LocalNodeId(1)]);
2348 node
2349 }),
2350 (LocalNodeId(1), {
2351 let mut node = Node::new(Role::GenericContainer);
2352 node.set_tree_id(subtree_id());
2353 node
2354 }),
2355 ],
2356 tree: Some(Tree::new(LocalNodeId(0))),
2357 tree_id: TreeId::ROOT,
2358 focus: LocalNodeId(1),
2359 };
2360 let mut tree = super::Tree::new(update, true);
2361
2362 let subtree_update = TreeUpdate {
2363 nodes: vec![
2364 (LocalNodeId(0), {
2365 let mut node = Node::new(Role::Document);
2366 node.set_children(vec![LocalNodeId(1)]);
2367 node
2368 }),
2369 (LocalNodeId(1), {
2370 let mut node = Node::new(Role::GenericContainer);
2371 node.set_tree_id(nested_subtree_id());
2372 node
2373 }),
2374 ],
2375 tree: Some(Tree::new(LocalNodeId(0))),
2376 tree_id: subtree_id(),
2377 focus: LocalNodeId(1),
2378 };
2379 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
2380
2381 let nested_update = TreeUpdate {
2382 nodes: vec![(LocalNodeId(0), Node::new(Role::Button))],
2383 tree: Some(Tree::new(LocalNodeId(0))),
2384 tree_id: nested_subtree_id(),
2385 focus: LocalNodeId(0),
2386 };
2387 tree.update_and_process_changes(nested_update, &mut NoOpHandler);
2388
2389 let update = TreeUpdate {
2390 nodes: vec![(LocalNodeId(1), Node::new(Role::GenericContainer))],
2391 tree: None,
2392 tree_id: subtree_id(),
2393 focus: LocalNodeId(1),
2394 };
2395 tree.update_and_process_changes(update, &mut NoOpHandler);
2396 }
2397
2398 #[test]
2399 fn nested_subtree_root_lookup_for_focus_only_update() {
2400 let update = TreeUpdate {
2401 nodes: vec![
2402 (LocalNodeId(0), {
2403 let mut node = Node::new(Role::Window);
2404 node.set_children(vec![LocalNodeId(1)]);
2405 node
2406 }),
2407 (LocalNodeId(1), {
2408 let mut node = Node::new(Role::GenericContainer);
2409 node.set_tree_id(subtree_id());
2410 node
2411 }),
2412 ],
2413 tree: Some(Tree::new(LocalNodeId(0))),
2414 tree_id: TreeId::ROOT,
2415 focus: LocalNodeId(0),
2416 };
2417 let mut tree = super::Tree::new(update, true);
2418
2419 let subtree_update = TreeUpdate {
2420 nodes: vec![
2421 (LocalNodeId(0), {
2422 let mut node = Node::new(Role::Document);
2423 node.set_children(vec![LocalNodeId(1), LocalNodeId(2)]);
2424 node
2425 }),
2426 (LocalNodeId(1), {
2427 let mut node = Node::new(Role::GenericContainer);
2428 node.set_tree_id(nested_subtree_id());
2429 node
2430 }),
2431 (LocalNodeId(2), Node::new(Role::Button)),
2432 ],
2433 tree: Some(Tree::new(LocalNodeId(0))),
2434 tree_id: subtree_id(),
2435 focus: LocalNodeId(0),
2436 };
2437 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
2438
2439 let nested_update = TreeUpdate {
2440 nodes: vec![
2441 (LocalNodeId(0), {
2442 let mut node = Node::new(Role::Group);
2443 node.set_children(vec![LocalNodeId(1)]);
2444 node
2445 }),
2446 (LocalNodeId(1), Node::new(Role::Button)),
2447 ],
2448 tree: Some(Tree::new(LocalNodeId(0))),
2449 tree_id: nested_subtree_id(),
2450 focus: LocalNodeId(0),
2451 };
2452 tree.update_and_process_changes(nested_update, &mut NoOpHandler);
2453
2454 let update = TreeUpdate {
2455 nodes: vec![],
2456 tree: None,
2457 tree_id: subtree_id(),
2458 focus: LocalNodeId(2),
2459 };
2460 tree.update_and_process_changes(update, &mut NoOpHandler);
2461
2462 assert_eq!(
2463 tree.state().subtrees.get(&subtree_id()).unwrap().focus,
2464 subtree_node_id(2),
2465 );
2466 }
2467
2468 #[test]
2469 fn subtree_root_change_updates_graft_and_parent() {
2470 struct Handler {
2471 updated_nodes: Vec<NodeId>,
2472 added_nodes: Vec<NodeId>,
2473 removed_nodes: Vec<NodeId>,
2474 }
2475 impl super::ChangeHandler for Handler {
2476 fn node_added(&mut self, node: &crate::Node) {
2477 self.added_nodes.push(node.id());
2478 }
2479 fn node_updated(&mut self, _old: &crate::Node, new: &crate::Node) {
2480 self.updated_nodes.push(new.id());
2481 }
2482 fn focus_moved(&mut self, _: Option<&crate::Node>, _: Option<&crate::Node>) {}
2483 fn node_removed(&mut self, node: &crate::Node) {
2484 self.removed_nodes.push(node.id());
2485 }
2486 }
2487
2488 let update = TreeUpdate {
2489 nodes: vec![
2490 (LocalNodeId(0), {
2491 let mut node = Node::new(Role::Window);
2492 node.set_children(vec![LocalNodeId(1)]);
2493 node
2494 }),
2495 (LocalNodeId(1), {
2496 let mut node = Node::new(Role::GenericContainer);
2497 node.set_tree_id(subtree_id());
2498 node
2499 }),
2500 ],
2501 tree: Some(Tree::new(LocalNodeId(0))),
2502 tree_id: TreeId::ROOT,
2503 focus: LocalNodeId(0),
2504 };
2505 let mut tree = super::Tree::new(update, false);
2506
2507 let subtree_update = TreeUpdate {
2508 nodes: vec![
2509 (LocalNodeId(0), {
2510 let mut node = Node::new(Role::Document);
2511 node.set_children(vec![LocalNodeId(1)]);
2512 node
2513 }),
2514 (LocalNodeId(1), Node::new(Role::Paragraph)),
2515 ],
2516 tree: Some(Tree::new(LocalNodeId(0))),
2517 tree_id: subtree_id(),
2518 focus: LocalNodeId(0),
2519 };
2520 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
2521
2522 let mut handler = Handler {
2523 updated_nodes: Vec::new(),
2524 added_nodes: Vec::new(),
2525 removed_nodes: Vec::new(),
2526 };
2527
2528 let subtree_update = TreeUpdate {
2529 nodes: vec![
2530 (LocalNodeId(2), {
2531 let mut node = Node::new(Role::Article);
2532 node.set_children(vec![LocalNodeId(3)]);
2533 node
2534 }),
2535 (LocalNodeId(3), Node::new(Role::Button)),
2536 ],
2537 tree: Some(Tree::new(LocalNodeId(2))),
2538 tree_id: subtree_id(),
2539 focus: LocalNodeId(2),
2540 };
2541 tree.update_and_process_changes(subtree_update, &mut handler);
2542
2543 let graft_node = tree.state().node_by_id(node_id(1)).unwrap();
2544 let children: Vec<_> = graft_node.child_ids().collect();
2545 assert_eq!(children.len(), 1);
2546 assert_eq!(children[0], subtree_node_id(2));
2547
2548 let new_subtree_root = tree.state().node_by_id(subtree_node_id(2)).unwrap();
2549 assert_eq!(new_subtree_root.parent_id(), Some(node_id(1)));
2550 assert_eq!(new_subtree_root.role(), Role::Article);
2551
2552 assert!(tree.state().node_by_id(subtree_node_id(0)).is_none());
2553 assert!(tree.state().node_by_id(subtree_node_id(1)).is_none());
2554
2555 assert!(tree.state().node_by_id(subtree_node_id(2)).is_some());
2556 assert!(tree.state().node_by_id(subtree_node_id(3)).is_some());
2557
2558 assert!(handler.removed_nodes.contains(&subtree_node_id(0)),);
2559 assert!(handler.removed_nodes.contains(&subtree_node_id(1)),);
2560 assert!(handler.added_nodes.contains(&subtree_node_id(2)),);
2561 assert!(handler.added_nodes.contains(&subtree_node_id(3)),);
2562 }
2563
2564 #[test]
2565 fn subtree_root_change_to_existing_child() {
2566 struct Handler {
2567 updated_nodes: Vec<NodeId>,
2568 added_nodes: Vec<NodeId>,
2569 removed_nodes: Vec<NodeId>,
2570 }
2571 impl super::ChangeHandler for Handler {
2572 fn node_added(&mut self, node: &crate::Node) {
2573 self.added_nodes.push(node.id());
2574 }
2575 fn node_updated(&mut self, _old: &crate::Node, new: &crate::Node) {
2576 self.updated_nodes.push(new.id());
2577 }
2578 fn focus_moved(&mut self, _: Option<&crate::Node>, _: Option<&crate::Node>) {}
2579 fn node_removed(&mut self, node: &crate::Node) {
2580 self.removed_nodes.push(node.id());
2581 }
2582 }
2583
2584 let update = TreeUpdate {
2585 nodes: vec![
2586 (LocalNodeId(0), {
2587 let mut node = Node::new(Role::Window);
2588 node.set_children(vec![LocalNodeId(1)]);
2589 node
2590 }),
2591 (LocalNodeId(1), {
2592 let mut node = Node::new(Role::GenericContainer);
2593 node.set_tree_id(subtree_id());
2594 node
2595 }),
2596 ],
2597 tree: Some(Tree::new(LocalNodeId(0))),
2598 tree_id: TreeId::ROOT,
2599 focus: LocalNodeId(0),
2600 };
2601 let mut tree = super::Tree::new(update, false);
2602
2603 let subtree_update = TreeUpdate {
2604 nodes: vec![
2605 (LocalNodeId(0), {
2606 let mut node = Node::new(Role::Document);
2607 node.set_children(vec![LocalNodeId(1)]);
2608 node
2609 }),
2610 (LocalNodeId(1), {
2611 let mut node = Node::new(Role::Article);
2612 node.set_children(vec![LocalNodeId(2)]);
2613 node
2614 }),
2615 (LocalNodeId(2), Node::new(Role::Paragraph)),
2616 ],
2617 tree: Some(Tree::new(LocalNodeId(0))),
2618 tree_id: subtree_id(),
2619 focus: LocalNodeId(0),
2620 };
2621 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
2622
2623 let graft_node = tree.state().node_by_id(node_id(1)).unwrap();
2624 assert_eq!(graft_node.child_ids().next(), Some(subtree_node_id(0)));
2625
2626 let old_root = tree.state().node_by_id(subtree_node_id(0)).unwrap();
2627 assert_eq!(old_root.role(), Role::Document);
2628 assert_eq!(old_root.parent_id(), Some(node_id(1)));
2629
2630 let child = tree.state().node_by_id(subtree_node_id(1)).unwrap();
2631 assert_eq!(child.role(), Role::Article);
2632 assert_eq!(child.parent_id(), Some(subtree_node_id(0)));
2633
2634 let grandchild = tree.state().node_by_id(subtree_node_id(2)).unwrap();
2635 assert_eq!(grandchild.parent_id(), Some(subtree_node_id(1)));
2636
2637 let mut handler = Handler {
2638 updated_nodes: Vec::new(),
2639 added_nodes: Vec::new(),
2640 removed_nodes: Vec::new(),
2641 };
2642
2643 let subtree_update = TreeUpdate {
2644 nodes: vec![
2645 (LocalNodeId(1), {
2646 let mut node = Node::new(Role::Article);
2647 node.set_children(vec![LocalNodeId(2)]);
2648 node
2649 }),
2650 (LocalNodeId(2), Node::new(Role::Paragraph)),
2651 ],
2652 tree: Some(Tree::new(LocalNodeId(1))),
2653 tree_id: subtree_id(),
2654 focus: LocalNodeId(1),
2655 };
2656 tree.update_and_process_changes(subtree_update, &mut handler);
2657
2658 let graft_node = tree.state().node_by_id(node_id(1)).unwrap();
2659 let children: Vec<_> = graft_node.child_ids().collect();
2660 assert_eq!(children.len(), 1);
2661 assert_eq!(children[0], subtree_node_id(1));
2662
2663 let new_root = tree.state().node_by_id(subtree_node_id(1)).unwrap();
2664 assert_eq!(new_root.parent_id(), Some(node_id(1)));
2665 assert_eq!(new_root.role(), Role::Article);
2666
2667 assert!(tree.state().node_by_id(subtree_node_id(0)).is_none(),);
2668
2669 let grandchild = tree.state().node_by_id(subtree_node_id(2)).unwrap();
2670 assert_eq!(grandchild.parent_id(), Some(subtree_node_id(1)));
2671
2672 assert!(handler.removed_nodes.contains(&subtree_node_id(0)),);
2673 assert!(handler.updated_nodes.contains(&subtree_node_id(1)),);
2674 assert!(!handler.added_nodes.contains(&subtree_node_id(1)),);
2675 assert!(!handler.added_nodes.contains(&subtree_node_id(2)),);
2676 }
2677
2678 #[test]
2679 fn subtree_root_change_to_new_parent_of_old_root() {
2680 struct Handler {
2681 updated_nodes: Vec<NodeId>,
2682 added_nodes: Vec<NodeId>,
2683 removed_nodes: Vec<NodeId>,
2684 }
2685 impl super::ChangeHandler for Handler {
2686 fn node_added(&mut self, node: &crate::Node) {
2687 self.added_nodes.push(node.id());
2688 }
2689 fn node_updated(&mut self, _old: &crate::Node, new: &crate::Node) {
2690 self.updated_nodes.push(new.id());
2691 }
2692 fn focus_moved(&mut self, _: Option<&crate::Node>, _: Option<&crate::Node>) {}
2693 fn node_removed(&mut self, node: &crate::Node) {
2694 self.removed_nodes.push(node.id());
2695 }
2696 }
2697
2698 let update = TreeUpdate {
2699 nodes: vec![
2700 (LocalNodeId(0), {
2701 let mut node = Node::new(Role::Window);
2702 node.set_children(vec![LocalNodeId(1)]);
2703 node
2704 }),
2705 (LocalNodeId(1), {
2706 let mut node = Node::new(Role::GenericContainer);
2707 node.set_tree_id(subtree_id());
2708 node
2709 }),
2710 ],
2711 tree: Some(Tree::new(LocalNodeId(0))),
2712 tree_id: TreeId::ROOT,
2713 focus: LocalNodeId(0),
2714 };
2715 let mut tree = super::Tree::new(update, false);
2716
2717 let subtree_update = TreeUpdate {
2718 nodes: vec![
2719 (LocalNodeId(0), {
2720 let mut node = Node::new(Role::Document);
2721 node.set_children(vec![LocalNodeId(1)]);
2722 node
2723 }),
2724 (LocalNodeId(1), Node::new(Role::Paragraph)),
2725 ],
2726 tree: Some(Tree::new(LocalNodeId(0))),
2727 tree_id: subtree_id(),
2728 focus: LocalNodeId(0),
2729 };
2730 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
2731
2732 let mut handler = Handler {
2733 updated_nodes: Vec::new(),
2734 added_nodes: Vec::new(),
2735 removed_nodes: Vec::new(),
2736 };
2737
2738 let subtree_update = TreeUpdate {
2739 nodes: vec![
2740 (LocalNodeId(2), {
2741 let mut node = Node::new(Role::Article);
2742 node.set_children(vec![LocalNodeId(0)]);
2743 node
2744 }),
2745 (LocalNodeId(0), {
2746 let mut node = Node::new(Role::Document);
2747 node.set_children(vec![LocalNodeId(1)]);
2748 node
2749 }),
2750 (LocalNodeId(1), Node::new(Role::Paragraph)),
2751 ],
2752 tree: Some(Tree::new(LocalNodeId(2))),
2753 tree_id: subtree_id(),
2754 focus: LocalNodeId(2),
2755 };
2756 tree.update_and_process_changes(subtree_update, &mut handler);
2757
2758 let graft_node = tree.state().node_by_id(node_id(1)).unwrap();
2759 let children: Vec<_> = graft_node.child_ids().collect();
2760 assert_eq!(children.len(), 1);
2761 assert_eq!(children[0], subtree_node_id(2));
2762
2763 let new_root = tree.state().node_by_id(subtree_node_id(2)).unwrap();
2764 assert_eq!(new_root.parent_id(), Some(node_id(1)));
2765 assert_eq!(new_root.role(), Role::Article);
2766
2767 let old_root = tree.state().node_by_id(subtree_node_id(0)).unwrap();
2768 assert_eq!(old_root.parent_id(), Some(subtree_node_id(2)));
2769 assert_eq!(old_root.role(), Role::Document);
2770
2771 let grandchild = tree.state().node_by_id(subtree_node_id(1)).unwrap();
2772 assert_eq!(grandchild.parent_id(), Some(subtree_node_id(0)));
2773
2774 assert!(handler.added_nodes.contains(&subtree_node_id(2)));
2775 assert!(handler.updated_nodes.contains(&subtree_node_id(0)));
2776 assert!(!handler.removed_nodes.contains(&subtree_node_id(0)));
2777 assert!(!handler.removed_nodes.contains(&subtree_node_id(1)));
2778 }
2779
2780 #[test]
2781 fn subtree_update_without_tree_preserves_root() {
2782 struct Handler {
2783 updated_nodes: Vec<NodeId>,
2784 added_nodes: Vec<NodeId>,
2785 removed_nodes: Vec<NodeId>,
2786 }
2787 impl super::ChangeHandler for Handler {
2788 fn node_added(&mut self, node: &crate::Node) {
2789 self.added_nodes.push(node.id());
2790 }
2791 fn node_updated(&mut self, _old: &crate::Node, new: &crate::Node) {
2792 self.updated_nodes.push(new.id());
2793 }
2794 fn focus_moved(&mut self, _: Option<&crate::Node>, _: Option<&crate::Node>) {}
2795 fn node_removed(&mut self, node: &crate::Node) {
2796 self.removed_nodes.push(node.id());
2797 }
2798 }
2799
2800 let update = TreeUpdate {
2801 nodes: vec![
2802 (LocalNodeId(0), {
2803 let mut node = Node::new(Role::Window);
2804 node.set_children(vec![LocalNodeId(1)]);
2805 node
2806 }),
2807 (LocalNodeId(1), {
2808 let mut node = Node::new(Role::GenericContainer);
2809 node.set_tree_id(subtree_id());
2810 node
2811 }),
2812 ],
2813 tree: Some(Tree::new(LocalNodeId(0))),
2814 tree_id: TreeId::ROOT,
2815 focus: LocalNodeId(0),
2816 };
2817 let mut tree = super::Tree::new(update, false);
2818
2819 let subtree_update = TreeUpdate {
2820 nodes: vec![
2821 (LocalNodeId(0), {
2822 let mut node = Node::new(Role::Document);
2823 node.set_children(vec![LocalNodeId(1)]);
2824 node
2825 }),
2826 (LocalNodeId(1), {
2827 let mut node = Node::new(Role::Paragraph);
2828 node.set_label("original");
2829 node
2830 }),
2831 ],
2832 tree: Some(Tree::new(LocalNodeId(0))),
2833 tree_id: subtree_id(),
2834 focus: LocalNodeId(0),
2835 };
2836 tree.update_and_process_changes(subtree_update, &mut NoOpHandler);
2837
2838 let mut handler = Handler {
2839 updated_nodes: Vec::new(),
2840 added_nodes: Vec::new(),
2841 removed_nodes: Vec::new(),
2842 };
2843
2844 let subtree_update = TreeUpdate {
2845 nodes: vec![(LocalNodeId(1), {
2846 let mut node = Node::new(Role::Paragraph);
2847 node.set_label("modified");
2848 node
2849 })],
2850 tree: None,
2851 tree_id: subtree_id(),
2852 focus: LocalNodeId(0),
2853 };
2854 tree.update_and_process_changes(subtree_update, &mut handler);
2855
2856 let subtree_root = tree.state().node_by_id(subtree_node_id(0)).unwrap();
2857 assert_eq!(subtree_root.role(), Role::Document);
2858 assert_eq!(subtree_root.parent_id(), Some(node_id(1)));
2859
2860 let graft_node = tree.state().node_by_id(node_id(1)).unwrap();
2861 assert_eq!(graft_node.child_ids().next(), Some(subtree_node_id(0)));
2862
2863 let child = tree.state().node_by_id(subtree_node_id(1)).unwrap();
2864 assert_eq!(child.label().as_deref(), Some("modified"));
2865
2866 assert!(handler.removed_nodes.is_empty(),);
2867 assert!(handler.added_nodes.is_empty());
2868 assert!(handler.updated_nodes.contains(&subtree_node_id(1)),);
2869 assert!(!handler.updated_nodes.contains(&subtree_node_id(0)),);
2870 }
2871
2872 #[test]
2873 fn focus_returns_focused_node() {
2874 let update = TreeUpdate {
2875 nodes: vec![
2876 (LocalNodeId(0), {
2877 let mut node = Node::new(Role::Window);
2878 node.set_children(vec![LocalNodeId(1)]);
2879 node
2880 }),
2881 (LocalNodeId(1), Node::new(Role::Button)),
2882 ],
2883 tree: Some(Tree::new(LocalNodeId(0))),
2884 tree_id: TreeId::ROOT,
2885 focus: LocalNodeId(1),
2886 };
2887 let tree = super::Tree::new(update, true);
2888 assert_eq!(tree.state().focus().unwrap().id(), node_id(1));
2889 }
2890
2891 #[test]
2892 fn focus_returns_active_descendant() {
2893 let update = TreeUpdate {
2894 nodes: vec![
2895 (LocalNodeId(0), {
2896 let mut node = Node::new(Role::Window);
2897 node.set_children(vec![LocalNodeId(1)]);
2898 node
2899 }),
2900 (LocalNodeId(1), {
2901 let mut node = Node::new(Role::ListBox);
2902 node.set_children(vec![LocalNodeId(2)]);
2903 node.set_active_descendant(LocalNodeId(2));
2904 node
2905 }),
2906 (LocalNodeId(2), Node::new(Role::ListBoxOption)),
2907 ],
2908 tree: Some(Tree::new(LocalNodeId(0))),
2909 tree_id: TreeId::ROOT,
2910 focus: LocalNodeId(1),
2911 };
2912 let tree = super::Tree::new(update, true);
2913 assert_eq!(tree.state().focus().unwrap().id(), node_id(2));
2914 }
2915
2916 #[test]
2917 fn focus_moved_when_active_descendant_changes() {
2918 let update = TreeUpdate {
2919 nodes: vec![
2920 (LocalNodeId(0), {
2921 let mut node = Node::new(Role::Window);
2922 node.set_children(vec![LocalNodeId(1)]);
2923 node
2924 }),
2925 (LocalNodeId(1), {
2926 let mut node = Node::new(Role::ListBox);
2927 node.set_children(vec![LocalNodeId(2), LocalNodeId(3)]);
2928 node.set_active_descendant(LocalNodeId(2));
2929 node
2930 }),
2931 (LocalNodeId(2), Node::new(Role::ListBoxOption)),
2932 (LocalNodeId(3), Node::new(Role::ListBoxOption)),
2933 ],
2934 tree: Some(Tree::new(LocalNodeId(0))),
2935 tree_id: TreeId::ROOT,
2936 focus: LocalNodeId(1),
2937 };
2938 let mut tree = super::Tree::new(update, true);
2939
2940 struct Handler {
2941 focus_moved_called: bool,
2942 old_focus: Option<NodeId>,
2943 new_focus: Option<NodeId>,
2944 }
2945 impl super::ChangeHandler for Handler {
2946 fn node_added(&mut self, _: &crate::Node) {}
2947 fn node_updated(&mut self, _: &crate::Node, _: &crate::Node) {}
2948 fn focus_moved(&mut self, old: Option<&crate::Node>, new: Option<&crate::Node>) {
2949 self.focus_moved_called = true;
2950 self.old_focus = old.map(|n| n.id());
2951 self.new_focus = new.map(|n| n.id());
2952 }
2953 fn node_removed(&mut self, _: &crate::Node) {}
2954 }
2955
2956 let mut handler = Handler {
2957 focus_moved_called: false,
2958 old_focus: None,
2959 new_focus: None,
2960 };
2961
2962 let update = TreeUpdate {
2963 nodes: vec![(LocalNodeId(1), {
2964 let mut node = Node::new(Role::ListBox);
2965 node.set_children(vec![LocalNodeId(2), LocalNodeId(3)]);
2966 node.set_active_descendant(LocalNodeId(3));
2967 node
2968 })],
2969 tree: None,
2970 tree_id: TreeId::ROOT,
2971 focus: LocalNodeId(1),
2972 };
2973 tree.update_and_process_changes(update, &mut handler);
2974
2975 assert!(handler.focus_moved_called);
2976 assert_eq!(handler.old_focus, Some(node_id(2)));
2977 assert_eq!(handler.new_focus, Some(node_id(3)));
2978 }
2979}