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