i_slint_core/
item_tree.rs

1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4// cSpell: ignore xffff
5
6//! This module contains the ItemTree and code that helps navigating it
7
8use crate::accessibility::{
9    AccessibilityAction, AccessibleStringProperty, SupportedAccessibilityAction,
10};
11use crate::items::{AccessibleRole, ItemRef, ItemVTable};
12use crate::layout::{LayoutInfo, Orientation};
13use crate::lengths::{ItemTransform, LogicalPoint, LogicalRect};
14use crate::slice::Slice;
15use crate::window::WindowAdapterRc;
16use crate::SharedString;
17use alloc::vec::Vec;
18use core::ops::ControlFlow;
19use core::pin::Pin;
20use vtable::*;
21
22#[repr(C)]
23#[derive(Debug, Clone, Copy)]
24/// A range of indices
25pub struct IndexRange {
26    /// Start index
27    pub start: usize,
28    /// Index one past the last index
29    pub end: usize,
30}
31
32impl From<core::ops::Range<usize>> for IndexRange {
33    fn from(r: core::ops::Range<usize>) -> Self {
34        Self { start: r.start, end: r.end }
35    }
36}
37impl From<IndexRange> for core::ops::Range<usize> {
38    fn from(r: IndexRange) -> Self {
39        Self { start: r.start, end: r.end }
40    }
41}
42
43/// A ItemTree is representing an unit that is allocated together
44#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
45#[vtable]
46#[repr(C)]
47pub struct ItemTreeVTable {
48    /// Visit the children of the item at index `index`.
49    /// Note that the root item is at index 0, so passing 0 would visit the item under root (the children of root).
50    /// If you want to visit the root item, you need to pass -1 as an index.
51    pub visit_children_item: extern "C" fn(
52        core::pin::Pin<VRef<ItemTreeVTable>>,
53        index: isize,
54        order: TraversalOrder,
55        visitor: VRefMut<ItemVisitorVTable>,
56    ) -> VisitChildrenResult,
57
58    /// Return a reference to an item using the given index
59    pub get_item_ref: extern "C" fn(
60        core::pin::Pin<VRef<ItemTreeVTable>>,
61        index: u32,
62    ) -> core::pin::Pin<VRef<ItemVTable>>,
63
64    /// Return the range of indices below the dynamic `ItemTreeNode` at `index`
65    pub get_subtree_range:
66        extern "C" fn(core::pin::Pin<VRef<ItemTreeVTable>>, index: u32) -> IndexRange,
67
68    /// Return the `ItemTreeRc` at `subindex` below the dynamic `ItemTreeNode` at `index`
69    pub get_subtree: extern "C" fn(
70        core::pin::Pin<VRef<ItemTreeVTable>>,
71        index: u32,
72        subindex: usize,
73        result: &mut vtable::VWeak<ItemTreeVTable, Dyn>,
74    ),
75
76    /// Return the item tree that is defined by this `ItemTree`.
77    /// The return value is an item weak because it can be null if there is no parent.
78    /// And the return value is passed by &mut because ItemWeak has a destructor
79    pub get_item_tree: extern "C" fn(core::pin::Pin<VRef<ItemTreeVTable>>) -> Slice<ItemTreeNode>,
80
81    /// Return the node this ItemTree is a part of in the parent ItemTree.
82    ///
83    /// The return value is an item weak because it can be null if there is no parent.
84    /// And the return value is passed by &mut because ItemWeak has a destructor
85    /// Note that the returned value will typically point to a repeater node, which is
86    /// strictly speaking not an Item at all!
87    pub parent_node: extern "C" fn(core::pin::Pin<VRef<ItemTreeVTable>>, result: &mut ItemWeak),
88
89    /// This embeds this ItemTree into the item tree of another ItemTree
90    ///
91    /// Returns `true` if this ItemTree was embedded into the `parent`
92    /// at `parent_item_tree_index`.
93    pub embed_component: extern "C" fn(
94        core::pin::Pin<VRef<ItemTreeVTable>>,
95        parent: &VWeak<ItemTreeVTable>,
96        parent_item_tree_index: u32,
97    ) -> bool,
98
99    /// Return the index of the current subtree or usize::MAX if this is not a subtree
100    pub subtree_index: extern "C" fn(core::pin::Pin<VRef<ItemTreeVTable>>) -> usize,
101
102    /// Returns the layout info for the root of the ItemTree
103    pub layout_info: extern "C" fn(core::pin::Pin<VRef<ItemTreeVTable>>, Orientation) -> LayoutInfo,
104
105    /// Returns the item's geometry (relative to its parent item)
106    pub item_geometry:
107        extern "C" fn(core::pin::Pin<VRef<ItemTreeVTable>>, item_index: u32) -> LogicalRect,
108
109    /// Returns the accessible role for a given item
110    pub accessible_role:
111        extern "C" fn(core::pin::Pin<VRef<ItemTreeVTable>>, item_index: u32) -> AccessibleRole,
112
113    /// Returns the accessible property via the `result`. Returns true if such a property exists.
114    pub accessible_string_property: extern "C" fn(
115        core::pin::Pin<VRef<ItemTreeVTable>>,
116        item_index: u32,
117        what: AccessibleStringProperty,
118        result: &mut SharedString,
119    ) -> bool,
120
121    /// Executes an accessibility action.
122    pub accessibility_action: extern "C" fn(
123        core::pin::Pin<VRef<ItemTreeVTable>>,
124        item_index: u32,
125        action: &AccessibilityAction,
126    ),
127
128    /// Returns the supported accessibility actions.
129    pub supported_accessibility_actions: extern "C" fn(
130        core::pin::Pin<VRef<ItemTreeVTable>>,
131        item_index: u32,
132    ) -> SupportedAccessibilityAction,
133
134    /// Add the `ElementName::id` entries of the given item
135    pub item_element_infos: extern "C" fn(
136        core::pin::Pin<VRef<ItemTreeVTable>>,
137        item_index: u32,
138        result: &mut SharedString,
139    ) -> bool,
140
141    /// Returns a Window, creating a fresh one if `do_create` is true.
142    pub window_adapter: extern "C" fn(
143        core::pin::Pin<VRef<ItemTreeVTable>>,
144        do_create: bool,
145        result: &mut Option<WindowAdapterRc>,
146    ),
147
148    /// in-place destructor (for VRc)
149    pub drop_in_place: unsafe extern "C" fn(VRefMut<ItemTreeVTable>) -> vtable::Layout,
150
151    /// dealloc function (for VRc)
152    pub dealloc: unsafe extern "C" fn(&ItemTreeVTable, ptr: *mut u8, layout: vtable::Layout),
153}
154
155#[cfg(test)]
156pub(crate) use ItemTreeVTable_static;
157
158/// Alias for `vtable::VRef<ItemTreeVTable>` which represent a pointer to a `dyn ItemTree` with
159/// the associated vtable
160pub type ItemTreeRef<'a> = vtable::VRef<'a, ItemTreeVTable>;
161
162/// Type alias to the commonly used `Pin<VRef<ItemTreeVTable>>>`
163pub type ItemTreeRefPin<'a> = core::pin::Pin<ItemTreeRef<'a>>;
164
165/// Type alias to the commonly used VRc<ItemTreeVTable, Dyn>>
166pub type ItemTreeRc = vtable::VRc<ItemTreeVTable, Dyn>;
167/// Type alias to the commonly used VWeak<ItemTreeVTable, Dyn>>
168pub type ItemTreeWeak = vtable::VWeak<ItemTreeVTable, Dyn>;
169
170/// Call init() on the ItemVTable for each item of the ItemTree.
171pub fn register_item_tree(item_tree_rc: &ItemTreeRc, window_adapter: Option<WindowAdapterRc>) {
172    let c = vtable::VRc::borrow_pin(item_tree_rc);
173    let item_tree = c.as_ref().get_item_tree();
174    item_tree.iter().enumerate().for_each(|(tree_index, node)| {
175        let tree_index = tree_index as u32;
176        if let ItemTreeNode::Item { .. } = &node {
177            let item = ItemRc::new(item_tree_rc.clone(), tree_index);
178            c.as_ref().get_item_ref(tree_index).as_ref().init(&item);
179        }
180    });
181    if let Some(adapter) = window_adapter.as_ref().and_then(|a| a.internal(crate::InternalToken)) {
182        adapter.register_item_tree();
183    }
184}
185
186/// Free the backend graphics resources allocated by the ItemTree's items.
187pub fn unregister_item_tree<Base>(
188    base: core::pin::Pin<&Base>,
189    item_tree: ItemTreeRef,
190    item_array: &[vtable::VOffset<Base, ItemVTable, vtable::AllowPin>],
191    window_adapter: &WindowAdapterRc,
192) {
193    window_adapter.renderer().free_graphics_resources(
194        item_tree,
195        &mut item_array.iter().map(|item| item.apply_pin(base)),
196    ).expect("Fatal error encountered when freeing graphics resources while destroying Slint component");
197    if let Some(w) = window_adapter.internal(crate::InternalToken) {
198        w.unregister_item_tree(item_tree, &mut item_array.iter().map(|item| item.apply_pin(base)));
199    }
200}
201
202fn find_sibling_outside_repeater(
203    component: &ItemTreeRc,
204    comp_ref_pin: Pin<VRef<ItemTreeVTable>>,
205    index: u32,
206    sibling_step: &dyn Fn(&crate::item_tree::ItemTreeNodeArray, u32) -> Option<u32>,
207    subtree_child: &dyn Fn(usize, usize) -> usize,
208) -> Option<ItemRc> {
209    assert_ne!(index, 0);
210
211    let item_tree = crate::item_tree::ItemTreeNodeArray::new(&comp_ref_pin);
212
213    let mut current_sibling = index;
214    loop {
215        current_sibling = sibling_step(&item_tree, current_sibling)?;
216
217        if let Some(node) = step_into_node(
218            component,
219            &comp_ref_pin,
220            current_sibling,
221            &item_tree,
222            subtree_child,
223            &core::convert::identity,
224        ) {
225            return Some(node);
226        }
227    }
228}
229
230fn step_into_node(
231    component: &ItemTreeRc,
232    comp_ref_pin: &Pin<VRef<ItemTreeVTable>>,
233    node_index: u32,
234    item_tree: &crate::item_tree::ItemTreeNodeArray,
235    subtree_child: &dyn Fn(usize, usize) -> usize,
236    wrap_around: &dyn Fn(ItemRc) -> ItemRc,
237) -> Option<ItemRc> {
238    match item_tree.get(node_index).expect("Invalid index passed to item tree") {
239        crate::item_tree::ItemTreeNode::Item { .. } => {
240            Some(ItemRc::new(component.clone(), node_index))
241        }
242        crate::item_tree::ItemTreeNode::DynamicTree { index, .. } => {
243            let range = comp_ref_pin.as_ref().get_subtree_range(*index);
244            let component_index = subtree_child(range.start, range.end);
245            let mut child_instance = Default::default();
246            comp_ref_pin.as_ref().get_subtree(*index, component_index, &mut child_instance);
247            child_instance
248                .upgrade()
249                .map(|child_instance| wrap_around(ItemRc::new(child_instance, 0)))
250        }
251    }
252}
253
254pub enum ParentItemTraversalMode {
255    FindAllParents,
256    StopAtPopups,
257}
258
259/// A ItemRc is holding a reference to a ItemTree containing the item, and the index of this item
260#[repr(C)]
261#[derive(Clone, Debug)]
262pub struct ItemRc {
263    item_tree: vtable::VRc<ItemTreeVTable>,
264    index: u32,
265}
266
267impl ItemRc {
268    /// Create an ItemRc from a ItemTree and an index
269    pub fn new(item_tree: vtable::VRc<ItemTreeVTable>, index: u32) -> Self {
270        Self { item_tree, index }
271    }
272
273    pub fn is_root_item_of(&self, item_tree: &VRc<ItemTreeVTable>) -> bool {
274        self.index == 0 && VRc::ptr_eq(&self.item_tree, item_tree)
275    }
276
277    /// Return a `Pin<ItemRef<'a>>`
278    pub fn borrow<'a>(&'a self) -> Pin<ItemRef<'a>> {
279        #![allow(unsafe_code)]
280        let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
281        let result = comp_ref_pin.as_ref().get_item_ref(self.index);
282        // Safety: we can expand the lifetime of the ItemRef because we know it lives for at least the
283        // lifetime of the ItemTree, which is 'a.  Pin::as_ref removes the lifetime, but we can just put it back.
284        unsafe { core::mem::transmute::<Pin<ItemRef<'_>>, Pin<ItemRef<'a>>>(result) }
285    }
286
287    /// Returns a `VRcMapped` of this item, to conveniently access specialized item API.
288    pub fn downcast<T: HasStaticVTable<ItemVTable>>(&self) -> Option<VRcMapped<ItemTreeVTable, T>> {
289        #![allow(unsafe_code)]
290        let item = self.borrow();
291        ItemRef::downcast_pin::<T>(item)?;
292
293        Some(vtable::VRc::map_dyn(self.item_tree.clone(), |comp_ref_pin| {
294            let result = comp_ref_pin.as_ref().get_item_ref(self.index);
295            // Safety: we can expand the lifetime of the ItemRef because we know it lives for at least the
296            // lifetime of the ItemTree, which is 'a.  Pin::as_ref removes the lifetime, but we can just put it back.
297            let item =
298                unsafe { core::mem::transmute::<Pin<ItemRef<'_>>, Pin<ItemRef<'_>>>(result) };
299            ItemRef::downcast_pin::<T>(item).unwrap()
300        }))
301    }
302
303    pub fn downgrade(&self) -> ItemWeak {
304        ItemWeak { item_tree: VRc::downgrade(&self.item_tree), index: self.index }
305    }
306
307    /// Return the parent Item in the item tree.
308    ///
309    /// If the item is a the root on its Window or PopupWindow, then the parent is None.
310    pub fn parent_item(&self, find_mode: ParentItemTraversalMode) -> Option<ItemRc> {
311        let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
312        let item_tree = crate::item_tree::ItemTreeNodeArray::new(&comp_ref_pin);
313
314        if let Some(parent_index) = item_tree.parent(self.index) {
315            return Some(ItemRc::new(self.item_tree.clone(), parent_index));
316        }
317
318        let mut r = ItemWeak::default();
319        comp_ref_pin.as_ref().parent_node(&mut r);
320        let parent = r.upgrade()?;
321        let comp_ref_pin = vtable::VRc::borrow_pin(&parent.item_tree);
322        let item_tree_array = crate::item_tree::ItemTreeNodeArray::new(&comp_ref_pin);
323        if let Some(ItemTreeNode::DynamicTree { parent_index, .. }) =
324            item_tree_array.get(parent.index())
325        {
326            // parent_node returns the repeater node, go up one more level!
327            Some(ItemRc::new(parent.item_tree.clone(), *parent_index))
328        } else {
329            // the Item was most likely a PopupWindow and we don't want to return the item for the purpose of this call
330            // (eg, focus/geometry/...)
331            match find_mode {
332                ParentItemTraversalMode::FindAllParents => Some(parent),
333                ParentItemTraversalMode::StopAtPopups => None,
334            }
335        }
336    }
337
338    /// Returns true if this item is visible from the root of the item tree. Note that this will return
339    /// false for `Clip` elements with the `clip` property evaluating to true.
340    pub fn is_visible(&self) -> bool {
341        let (clip, geometry) = self.absolute_clip_rect_and_geometry();
342        let clip = clip.to_box2d();
343        let geometry = geometry.to_box2d();
344        !clip.is_empty()
345            && clip.max.x >= geometry.min.x
346            && clip.max.y >= geometry.min.y
347            && clip.min.x <= geometry.max.x
348            && clip.min.y <= geometry.max.y
349    }
350
351    /// Returns the clip rect that applies to this item (in window coordinates) as well as the
352    /// item's (unclipped) geometry (also in window coordinates).
353    fn absolute_clip_rect_and_geometry(&self) -> (LogicalRect, LogicalRect) {
354        let (mut clip, parent_geometry) =
355            self.parent_item(ParentItemTraversalMode::StopAtPopups).map_or_else(
356                || {
357                    (
358                        LogicalRect::from_size((crate::Coord::MAX, crate::Coord::MAX).into()),
359                        Default::default(),
360                    )
361                },
362                |parent| parent.absolute_clip_rect_and_geometry(),
363            );
364
365        let geometry = self.geometry().translate(parent_geometry.origin.to_vector());
366
367        let item = self.borrow();
368        if item.as_ref().clips_children() {
369            clip = geometry.intersection(&clip).unwrap_or_default();
370        }
371
372        (clip, geometry)
373    }
374
375    pub fn is_accessible(&self) -> bool {
376        let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
377        let item_tree = crate::item_tree::ItemTreeNodeArray::new(&comp_ref_pin);
378
379        if let Some(n) = &item_tree.get(self.index) {
380            match n {
381                ItemTreeNode::Item { is_accessible, .. } => *is_accessible,
382                ItemTreeNode::DynamicTree { .. } => false,
383            }
384        } else {
385            false
386        }
387    }
388
389    pub fn accessible_role(&self) -> crate::items::AccessibleRole {
390        let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
391        comp_ref_pin.as_ref().accessible_role(self.index)
392    }
393
394    pub fn accessible_string_property(
395        &self,
396        what: crate::accessibility::AccessibleStringProperty,
397    ) -> Option<SharedString> {
398        let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
399        let mut result = Default::default();
400        let ok = comp_ref_pin.as_ref().accessible_string_property(self.index, what, &mut result);
401        ok.then_some(result)
402    }
403
404    pub fn accessible_action(&self, action: &crate::accessibility::AccessibilityAction) {
405        let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
406        comp_ref_pin.as_ref().accessibility_action(self.index, action);
407    }
408
409    pub fn supported_accessibility_actions(&self) -> SupportedAccessibilityAction {
410        let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
411        comp_ref_pin.as_ref().supported_accessibility_actions(self.index)
412    }
413
414    pub fn element_count(&self) -> Option<usize> {
415        let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
416        let mut result = SharedString::new();
417        comp_ref_pin
418            .as_ref()
419            .item_element_infos(self.index, &mut result)
420            .then(|| result.as_str().split("/").count())
421    }
422
423    pub fn element_type_names_and_ids(
424        &self,
425        element_index: usize,
426    ) -> Option<Vec<(SharedString, SharedString)>> {
427        let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
428        let mut result = SharedString::new();
429        comp_ref_pin.as_ref().item_element_infos(self.index, &mut result).then(|| {
430            result
431                .as_str()
432                .split("/")
433                .nth(element_index)
434                .unwrap()
435                .split(";")
436                .map(|encoded_elem_info| {
437                    let mut decoder = encoded_elem_info.split(',');
438                    let type_name = decoder.next().unwrap().into();
439                    let id = decoder.next().map(Into::into).unwrap_or_default();
440                    (type_name, id)
441                })
442                .collect()
443        })
444    }
445
446    pub fn geometry(&self) -> LogicalRect {
447        let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
448        comp_ref_pin.as_ref().item_geometry(self.index)
449    }
450
451    pub fn bounding_rect(
452        &self,
453        geometry: &LogicalRect,
454        window_adapter: &WindowAdapterRc,
455    ) -> LogicalRect {
456        self.borrow().as_ref().bounding_rect(window_adapter, self, *geometry)
457    }
458
459    /// Returns an absolute position of `p` in the parent item coordinate system
460    /// (does not add this item's x and y)
461    pub fn map_to_window(&self, p: LogicalPoint) -> LogicalPoint {
462        let mut current = self.clone();
463        let mut result = p;
464        while let Some(parent) = current.parent_item(ParentItemTraversalMode::StopAtPopups) {
465            let geometry = parent.geometry();
466            result += geometry.origin.to_vector();
467            current = parent.clone();
468        }
469        result
470    }
471
472    /// Returns an absolute position of `p` in the `ItemTree`'s coordinate system
473    /// (does not add this item's x and y)
474    pub fn map_to_item_tree(
475        &self,
476        p: LogicalPoint,
477        item_tree: &vtable::VRc<ItemTreeVTable>,
478    ) -> LogicalPoint {
479        let mut current = self.clone();
480        let mut result = p;
481        if current.is_root_item_of(item_tree) {
482            return result;
483        }
484        while let Some(parent) = current.parent_item(ParentItemTraversalMode::StopAtPopups) {
485            if parent.is_root_item_of(item_tree) {
486                break;
487            }
488            let geometry = parent.geometry();
489            result += geometry.origin.to_vector();
490            current = parent.clone();
491        }
492        result
493    }
494
495    /// Return the index of the item within the ItemTree
496    pub fn index(&self) -> u32 {
497        self.index
498    }
499    /// Returns a reference to the ItemTree holding this item
500    pub fn item_tree(&self) -> &vtable::VRc<ItemTreeVTable> {
501        &self.item_tree
502    }
503
504    fn find_child(
505        &self,
506        child_access: &dyn Fn(&crate::item_tree::ItemTreeNodeArray, u32) -> Option<u32>,
507        child_step: &dyn Fn(&crate::item_tree::ItemTreeNodeArray, u32) -> Option<u32>,
508        subtree_child: &dyn Fn(usize, usize) -> usize,
509    ) -> Option<Self> {
510        let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
511        let item_tree = crate::item_tree::ItemTreeNodeArray::new(&comp_ref_pin);
512
513        let mut current_child_index = child_access(&item_tree, self.index())?;
514        loop {
515            if let Some(item) = step_into_node(
516                self.item_tree(),
517                &comp_ref_pin,
518                current_child_index,
519                &item_tree,
520                subtree_child,
521                &core::convert::identity,
522            ) {
523                return Some(item);
524            }
525            current_child_index = child_step(&item_tree, current_child_index)?;
526        }
527    }
528
529    /// The first child Item of this Item
530    pub fn first_child(&self) -> Option<Self> {
531        self.find_child(
532            &|item_tree, index| item_tree.first_child(index),
533            &|item_tree, index| item_tree.next_sibling(index),
534            &|start, _| start,
535        )
536    }
537
538    /// The last child Item of this Item
539    pub fn last_child(&self) -> Option<Self> {
540        self.find_child(
541            &|item_tree, index| item_tree.last_child(index),
542            &|item_tree, index| item_tree.previous_sibling(index),
543            &|_, end| end.wrapping_sub(1),
544        )
545    }
546
547    fn find_sibling(
548        &self,
549        sibling_step: &dyn Fn(&crate::item_tree::ItemTreeNodeArray, u32) -> Option<u32>,
550        subtree_step: &dyn Fn(usize) -> usize,
551        subtree_child: &dyn Fn(usize, usize) -> usize,
552    ) -> Option<Self> {
553        let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
554        if self.index == 0 {
555            let mut parent_item = Default::default();
556            comp_ref_pin.as_ref().parent_node(&mut parent_item);
557            let current_component_subtree_index = comp_ref_pin.as_ref().subtree_index();
558            if let Some(parent_item) = parent_item.upgrade() {
559                let parent = parent_item.item_tree();
560                let parent_ref_pin = vtable::VRc::borrow_pin(parent);
561                let parent_item_index = parent_item.index();
562                let parent_item_tree = crate::item_tree::ItemTreeNodeArray::new(&parent_ref_pin);
563
564                let subtree_index = match parent_item_tree.get(parent_item_index)? {
565                    crate::item_tree::ItemTreeNode::Item { .. } => {
566                        // Popups can trigger this case!
567                        return None;
568                    }
569                    crate::item_tree::ItemTreeNode::DynamicTree { index, .. } => *index,
570                };
571
572                let next_subtree_index = subtree_step(current_component_subtree_index);
573
574                // Get next subtree from repeater!
575                let mut next_subtree_instance = Default::default();
576                parent_ref_pin.as_ref().get_subtree(
577                    subtree_index,
578                    next_subtree_index,
579                    &mut next_subtree_instance,
580                );
581                if let Some(next_subtree_instance) = next_subtree_instance.upgrade() {
582                    return Some(ItemRc::new(next_subtree_instance, 0));
583                }
584
585                // We need to leave the repeater:
586                find_sibling_outside_repeater(
587                    parent,
588                    parent_ref_pin,
589                    parent_item_index,
590                    sibling_step,
591                    subtree_child,
592                )
593            } else {
594                None // At root if the item tree
595            }
596        } else {
597            find_sibling_outside_repeater(
598                self.item_tree(),
599                comp_ref_pin,
600                self.index(),
601                sibling_step,
602                subtree_child,
603            )
604        }
605    }
606
607    /// The previous sibling of this Item
608    pub fn previous_sibling(&self) -> Option<Self> {
609        self.find_sibling(
610            &|item_tree, index| item_tree.previous_sibling(index),
611            &|index| index.wrapping_sub(1),
612            &|_, end| end.wrapping_sub(1),
613        )
614    }
615
616    /// The next sibling of this Item
617    pub fn next_sibling(&self) -> Option<Self> {
618        self.find_sibling(
619            &|item_tree, index| item_tree.next_sibling(index),
620            &|index| index.saturating_add(1),
621            &|start, _| start,
622        )
623    }
624
625    fn move_focus(
626        &self,
627        focus_step: &dyn Fn(&crate::item_tree::ItemTreeNodeArray, u32) -> Option<u32>,
628        subtree_step: &dyn Fn(ItemRc) -> Option<ItemRc>,
629        subtree_child: &dyn Fn(usize, usize) -> usize,
630        step_in: &dyn Fn(ItemRc) -> ItemRc,
631        step_out: &dyn Fn(&crate::item_tree::ItemTreeNodeArray, u32) -> Option<u32>,
632    ) -> Self {
633        let mut component = self.item_tree().clone();
634        let mut comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
635        let mut item_tree = crate::item_tree::ItemTreeNodeArray::new(&comp_ref_pin);
636
637        let mut to_focus = self.index();
638
639        'in_tree: loop {
640            if let Some(next) = focus_step(&item_tree, to_focus) {
641                if let Some(item) = step_into_node(
642                    &component,
643                    &comp_ref_pin,
644                    next,
645                    &item_tree,
646                    subtree_child,
647                    step_in,
648                ) {
649                    return item;
650                }
651                to_focus = next;
652                // Loop: We stepped into an empty repeater!
653            } else {
654                // Step out of this component:
655                let mut root = ItemRc::new(component, 0);
656                if let Some(item) = subtree_step(root.clone()) {
657                    // Next component inside same repeater
658                    return step_in(item);
659                }
660
661                // Step out of the repeater
662                let root_component = root.item_tree();
663                let root_comp_ref = vtable::VRc::borrow_pin(root_component);
664                let mut parent_node = Default::default();
665                root_comp_ref.as_ref().parent_node(&mut parent_node);
666
667                while let Some(parent) = parent_node.upgrade() {
668                    // .. not at the root of the item tree:
669                    component = parent.item_tree().clone();
670                    comp_ref_pin = vtable::VRc::borrow_pin(&component);
671                    item_tree = crate::item_tree::ItemTreeNodeArray::new(&comp_ref_pin);
672
673                    let index = parent.index();
674
675                    if !matches!(item_tree.get(index), Some(ItemTreeNode::DynamicTree { .. })) {
676                        // That was not a repeater (eg, a popup window)
677                        break;
678                    }
679
680                    if let Some(next) = step_out(&item_tree, index) {
681                        if let Some(item) = step_into_node(
682                            parent.item_tree(),
683                            &comp_ref_pin,
684                            next,
685                            &item_tree,
686                            subtree_child,
687                            step_in,
688                        ) {
689                            // Step into a dynamic node
690                            return item;
691                        } else {
692                            // The dynamic node was empty, proceed in normal tree
693                            to_focus = parent.index();
694                            continue 'in_tree; // Find a node in the current (parent!) tree
695                        }
696                    }
697
698                    root = ItemRc::new(component.clone(), 0);
699                    if let Some(item) = subtree_step(root.clone()) {
700                        return step_in(item);
701                    }
702
703                    // Go up one more level:
704                    let root_component = root.item_tree();
705                    let root_comp_ref = vtable::VRc::borrow_pin(root_component);
706                    parent_node = Default::default();
707                    root_comp_ref.as_ref().parent_node(&mut parent_node);
708                }
709
710                // Loop around after hitting the root node:
711                return step_in(root);
712            }
713        }
714    }
715
716    /// Move tab focus to the previous item:
717    pub fn previous_focus_item(&self) -> Self {
718        self.move_focus(
719            &|item_tree, index| {
720                crate::item_focus::default_previous_in_local_focus_chain(index, item_tree)
721            },
722            &|root| root.previous_sibling(),
723            &|_, end| end.wrapping_sub(1),
724            &|root| {
725                let mut current = root;
726                loop {
727                    if let Some(next) = current.last_child() {
728                        current = next;
729                    } else {
730                        return current;
731                    }
732                }
733            },
734            &|item_tree, index| item_tree.parent(index),
735        )
736    }
737
738    /// Move tab focus to the next item:
739    pub fn next_focus_item(&self) -> Self {
740        self.move_focus(
741            &|item_tree, index| {
742                crate::item_focus::default_next_in_local_focus_chain(index, item_tree)
743            },
744            &|root| root.next_sibling(),
745            &|start, _| start,
746            &core::convert::identity,
747            &|item_tree, index| crate::item_focus::step_out_of_node(index, item_tree),
748        )
749    }
750
751    pub fn window_adapter(&self) -> Option<WindowAdapterRc> {
752        let comp_ref_pin = vtable::VRc::borrow_pin(&self.item_tree);
753        let mut result = None;
754        comp_ref_pin.as_ref().window_adapter(false, &mut result);
755        result
756    }
757
758    /// Visit the children of this element and call the visitor to each of them, until the visitor returns [`ControlFlow::Break`].
759    /// When the visitor breaks, the function returns the value. If it doesn't break, the function returns None.
760    fn visit_descendants_impl<R>(
761        &self,
762        visitor: &mut impl FnMut(&ItemRc) -> ControlFlow<R>,
763    ) -> Option<R> {
764        let mut result = None;
765
766        let mut actual_visitor = |item_tree: &ItemTreeRc,
767                                  index: u32,
768                                  _item_pin: core::pin::Pin<ItemRef>|
769         -> VisitChildrenResult {
770            let item_rc = ItemRc::new(item_tree.clone(), index);
771
772            match visitor(&item_rc) {
773                ControlFlow::Continue(_) => {
774                    if let Some(x) = item_rc.visit_descendants_impl(visitor) {
775                        result = Some(x);
776                        return VisitChildrenResult::abort(index, 0);
777                    }
778                }
779                ControlFlow::Break(x) => {
780                    result = Some(x);
781                    return VisitChildrenResult::abort(index, 0);
782                }
783            }
784
785            VisitChildrenResult::CONTINUE
786        };
787        vtable::new_vref!(let mut actual_visitor : VRefMut<ItemVisitorVTable> for ItemVisitor = &mut actual_visitor);
788
789        VRc::borrow_pin(self.item_tree()).as_ref().visit_children_item(
790            self.index() as isize,
791            TraversalOrder::BackToFront,
792            actual_visitor,
793        );
794
795        result
796    }
797
798    /// Visit the children of this element and call the visitor to each of them, until the visitor returns [`ControlFlow::Break`].
799    /// When the visitor breaks, the function returns the value. If it doesn't break, the function returns None.
800    pub fn visit_descendants<R>(
801        &self,
802        mut visitor: impl FnMut(&ItemRc) -> ControlFlow<R>,
803    ) -> Option<R> {
804        self.visit_descendants_impl(&mut visitor)
805    }
806
807    /// Returns the transform to apply to children to map them into the local coordinate space of this item.
808    /// Typically this is None, but rotation for example may return Some.
809    pub fn children_transform(&self) -> Option<ItemTransform> {
810        self.downcast::<crate::items::Rotate>().map(|rotate_item| {
811            let origin = euclid::Vector2D::<f32, crate::lengths::LogicalPx>::from_lengths(
812                rotate_item.as_pin_ref().rotation_origin_x().cast(),
813                rotate_item.as_pin_ref().rotation_origin_y().cast(),
814            );
815            ItemTransform::translation(-origin.x, -origin.y)
816                .cast()
817                .then_rotate(euclid::Angle {
818                    radians: rotate_item.as_pin_ref().rotation_angle().to_radians(),
819                })
820                .then_translate(origin)
821        })
822    }
823}
824
825impl PartialEq for ItemRc {
826    fn eq(&self, other: &Self) -> bool {
827        VRc::ptr_eq(&self.item_tree, &other.item_tree) && self.index == other.index
828    }
829}
830
831impl Eq for ItemRc {}
832
833/// A Weak reference to an item that can be constructed from an ItemRc.
834#[derive(Clone, Default)]
835#[repr(C)]
836pub struct ItemWeak {
837    item_tree: crate::item_tree::ItemTreeWeak,
838    index: u32,
839}
840
841impl ItemWeak {
842    pub fn upgrade(&self) -> Option<ItemRc> {
843        self.item_tree.upgrade().map(|c| ItemRc::new(c, self.index))
844    }
845}
846
847impl PartialEq for ItemWeak {
848    fn eq(&self, other: &Self) -> bool {
849        VWeak::ptr_eq(&self.item_tree, &other.item_tree) && self.index == other.index
850    }
851}
852
853impl Eq for ItemWeak {}
854
855#[repr(u8)]
856#[derive(Debug, Copy, Clone, Eq, PartialEq)]
857pub enum TraversalOrder {
858    BackToFront,
859    FrontToBack,
860}
861
862/// The return value of the ItemTree::visit_children_item function
863///
864/// Represents something like `enum { Continue, Aborted{aborted_at_item: isize} }`.
865/// But this is just wrapping a int because it is easier to use ffi with isize than
866/// complex enum.
867///
868/// -1 means the visitor will continue
869/// otherwise this is the index of the item that aborted the visit.
870#[repr(transparent)]
871#[derive(Copy, Clone, Eq, PartialEq)]
872pub struct VisitChildrenResult(u64);
873impl VisitChildrenResult {
874    /// The result used for a visitor that want to continue the visit
875    pub const CONTINUE: Self = Self(u64::MAX);
876
877    /// Returns a result that means that the visitor must stop, and convey the item that caused the abort
878    pub fn abort(item_index: u32, index_within_repeater: usize) -> Self {
879        assert!(index_within_repeater < u32::MAX as usize);
880        Self(item_index as u64 | (index_within_repeater as u64) << 32)
881    }
882    /// True if the visitor wants to abort the visit
883    pub fn has_aborted(&self) -> bool {
884        self.0 != Self::CONTINUE.0
885    }
886    pub fn aborted_index(&self) -> Option<usize> {
887        if self.0 != Self::CONTINUE.0 {
888            Some((self.0 & 0xffff_ffff) as usize)
889        } else {
890            None
891        }
892    }
893    pub fn aborted_indexes(&self) -> Option<(usize, usize)> {
894        if self.0 != Self::CONTINUE.0 {
895            Some(((self.0 & 0xffff_ffff) as usize, (self.0 >> 32) as usize))
896        } else {
897            None
898        }
899    }
900}
901impl core::fmt::Debug for VisitChildrenResult {
902    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
903        if self.0 == Self::CONTINUE.0 {
904            write!(f, "CONTINUE")
905        } else {
906            write!(f, "({},{})", (self.0 & 0xffff_ffff) as usize, (self.0 >> 32) as usize)
907        }
908    }
909}
910
911/// The item tree is an array of ItemTreeNode representing a static tree of items
912/// within a ItemTree.
913#[repr(u8)]
914#[derive(Debug)]
915pub enum ItemTreeNode {
916    /// Static item
917    Item {
918        /// True when the item has accessibility properties attached
919        is_accessible: bool,
920
921        /// number of children
922        children_count: u32,
923
924        /// index of the first children within the item tree
925        children_index: u32,
926
927        /// The index of the parent item (not valid for the root)
928        parent_index: u32,
929
930        /// The index in the extra item_array
931        item_array_index: u32,
932    },
933    /// A placeholder for many instance of item in their own ItemTree which
934    /// are instantiated according to a model.
935    DynamicTree {
936        /// the index which is passed in the visit_dynamic callback.
937        index: u32,
938
939        /// The index of the parent item (not valid for the root)
940        parent_index: u32,
941    },
942}
943
944impl ItemTreeNode {
945    pub fn parent_index(&self) -> u32 {
946        match self {
947            ItemTreeNode::Item { parent_index, .. } => *parent_index,
948            ItemTreeNode::DynamicTree { parent_index, .. } => *parent_index,
949        }
950    }
951}
952
953/// The `ItemTreeNodeArray` provides tree walking code for the physical ItemTree stored in
954/// a `ItemTree` without stitching any inter-ItemTree links together!
955pub struct ItemTreeNodeArray<'a> {
956    node_array: &'a [ItemTreeNode],
957}
958
959impl<'a> ItemTreeNodeArray<'a> {
960    /// Create a new `ItemTree` from its raw data.
961    pub fn new(comp_ref_pin: &'a Pin<VRef<'a, ItemTreeVTable>>) -> Self {
962        Self { node_array: comp_ref_pin.as_ref().get_item_tree().as_slice() }
963    }
964
965    /// Get a ItemTreeNode
966    pub fn get(&self, index: u32) -> Option<&ItemTreeNode> {
967        self.node_array.get(index as usize)
968    }
969
970    /// Get the parent of a node, returns `None` if this is the root node of this item tree.
971    pub fn parent(&self, index: u32) -> Option<u32> {
972        let index = index as usize;
973        (index < self.node_array.len() && index != 0).then(|| self.node_array[index].parent_index())
974    }
975
976    /// Returns the next sibling or `None` if this is the last sibling.
977    pub fn next_sibling(&self, index: u32) -> Option<u32> {
978        if let Some(parent_index) = self.parent(index) {
979            match self.node_array[parent_index as usize] {
980                ItemTreeNode::Item { children_index, children_count, .. } => {
981                    (index < (children_count + children_index - 1)).then_some(index + 1)
982                }
983                ItemTreeNode::DynamicTree { .. } => {
984                    unreachable!("Parent in same item tree is a repeater.")
985                }
986            }
987        } else {
988            None // No parent, so we have no siblings either:-)
989        }
990    }
991
992    /// Returns the previous sibling or `None` if this is the first sibling.
993    pub fn previous_sibling(&self, index: u32) -> Option<u32> {
994        if let Some(parent_index) = self.parent(index) {
995            match self.node_array[parent_index as usize] {
996                ItemTreeNode::Item { children_index, .. } => {
997                    (index > children_index).then_some(index - 1)
998                }
999                ItemTreeNode::DynamicTree { .. } => {
1000                    unreachable!("Parent in same item tree is a repeater.")
1001                }
1002            }
1003        } else {
1004            None // No parent, so we have no siblings either:-)
1005        }
1006    }
1007
1008    /// Returns the first child or `None` if this are no children or the `index`
1009    /// points to a `DynamicTree`.
1010    pub fn first_child(&self, index: u32) -> Option<u32> {
1011        match self.node_array.get(index as usize)? {
1012            ItemTreeNode::Item { children_index, children_count, .. } => {
1013                (*children_count != 0).then_some(*children_index as _)
1014            }
1015            ItemTreeNode::DynamicTree { .. } => None,
1016        }
1017    }
1018
1019    /// Returns the last child or `None` if this are no children or the `index`
1020    /// points to an `DynamicTree`.
1021    pub fn last_child(&self, index: u32) -> Option<u32> {
1022        match self.node_array.get(index as usize)? {
1023            ItemTreeNode::Item { children_index, children_count, .. } => {
1024                if *children_count != 0 {
1025                    Some(*children_index + *children_count - 1)
1026                } else {
1027                    None
1028                }
1029            }
1030            ItemTreeNode::DynamicTree { .. } => None,
1031        }
1032    }
1033
1034    /// Returns the number of nodes in the `ItemTreeNodeArray`
1035    pub fn node_count(&self) -> usize {
1036        self.node_array.len()
1037    }
1038}
1039
1040impl<'a> From<&'a [ItemTreeNode]> for ItemTreeNodeArray<'a> {
1041    fn from(item_tree: &'a [ItemTreeNode]) -> Self {
1042        Self { node_array: item_tree }
1043    }
1044}
1045
1046#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
1047#[vtable]
1048#[repr(C)]
1049/// Object to be passed in visit_item_children method of the ItemTree.
1050pub struct ItemVisitorVTable {
1051    /// Called for each child of the visited item
1052    ///
1053    /// The `item_tree` parameter is the ItemTree in which the item live which might not be the same
1054    /// as the parent's ItemTree.
1055    /// `index` is to be used again in the visit_item_children function of the ItemTree (the one passed as parameter)
1056    /// and `item` is a reference to the item itself
1057    visit_item: extern "C" fn(
1058        VRefMut<ItemVisitorVTable>,
1059        item_tree: &VRc<ItemTreeVTable, vtable::Dyn>,
1060        index: u32,
1061        item: Pin<VRef<ItemVTable>>,
1062    ) -> VisitChildrenResult,
1063    /// Destructor
1064    drop: extern "C" fn(VRefMut<ItemVisitorVTable>),
1065}
1066
1067/// Type alias to `vtable::VRefMut<ItemVisitorVTable>`
1068pub type ItemVisitorRefMut<'a> = vtable::VRefMut<'a, ItemVisitorVTable>;
1069
1070impl<T: FnMut(&ItemTreeRc, u32, Pin<ItemRef>) -> VisitChildrenResult> ItemVisitor for T {
1071    fn visit_item(
1072        &mut self,
1073        item_tree: &ItemTreeRc,
1074        index: u32,
1075        item: Pin<ItemRef>,
1076    ) -> VisitChildrenResult {
1077        self(item_tree, index, item)
1078    }
1079}
1080pub enum ItemVisitorResult<State> {
1081    Continue(State),
1082    Abort,
1083}
1084
1085/// Visit each items recursively
1086///
1087/// The state parameter returned by the visitor is passed to each child.
1088///
1089/// Returns the index of the item that cancelled, or -1 if nobody cancelled
1090pub fn visit_items<State>(
1091    item_tree: &ItemTreeRc,
1092    order: TraversalOrder,
1093    mut visitor: impl FnMut(&ItemTreeRc, Pin<ItemRef>, u32, &State) -> ItemVisitorResult<State>,
1094    state: State,
1095) -> VisitChildrenResult {
1096    visit_internal(item_tree, order, &mut visitor, -1, &state)
1097}
1098
1099fn visit_internal<State>(
1100    item_tree: &ItemTreeRc,
1101    order: TraversalOrder,
1102    visitor: &mut impl FnMut(&ItemTreeRc, Pin<ItemRef>, u32, &State) -> ItemVisitorResult<State>,
1103    index: isize,
1104    state: &State,
1105) -> VisitChildrenResult {
1106    let mut actual_visitor =
1107        |item_tree: &ItemTreeRc, index: u32, item: Pin<ItemRef>| -> VisitChildrenResult {
1108            match visitor(item_tree, item, index, state) {
1109                ItemVisitorResult::Continue(state) => {
1110                    visit_internal(item_tree, order, visitor, index as isize, &state)
1111                }
1112
1113                ItemVisitorResult::Abort => VisitChildrenResult::abort(index, 0),
1114            }
1115        };
1116    vtable::new_vref!(let mut actual_visitor : VRefMut<ItemVisitorVTable> for ItemVisitor = &mut actual_visitor);
1117    VRc::borrow_pin(item_tree).as_ref().visit_children_item(index, order, actual_visitor)
1118}
1119
1120/// Visit the children within an array of ItemTreeNode
1121///
1122/// The dynamic visitor is called for the dynamic nodes, its signature is
1123/// `fn(base: &Base, visitor: vtable::VRefMut<ItemVisitorVTable>, dyn_index: usize)`
1124///
1125/// FIXME: the design of this use lots of indirection and stack frame in recursive functions
1126/// Need to check if the compiler is able to optimize away some of it.
1127/// Possibly we should generate code that directly call the visitor instead
1128pub fn visit_item_tree<Base>(
1129    base: Pin<&Base>,
1130    item_tree: &ItemTreeRc,
1131    item_tree_array: &[ItemTreeNode],
1132    index: isize,
1133    order: TraversalOrder,
1134    mut visitor: vtable::VRefMut<ItemVisitorVTable>,
1135    visit_dynamic: impl Fn(
1136        Pin<&Base>,
1137        TraversalOrder,
1138        vtable::VRefMut<ItemVisitorVTable>,
1139        u32,
1140    ) -> VisitChildrenResult,
1141) -> VisitChildrenResult {
1142    let mut visit_at_index = |idx: u32| -> VisitChildrenResult {
1143        match &item_tree_array[idx as usize] {
1144            ItemTreeNode::Item { .. } => {
1145                let item = crate::items::ItemRc::new(item_tree.clone(), idx);
1146                visitor.visit_item(item_tree, idx, item.borrow())
1147            }
1148            ItemTreeNode::DynamicTree { index, .. } => {
1149                if let Some(sub_idx) =
1150                    visit_dynamic(base, order, visitor.borrow_mut(), *index).aborted_index()
1151                {
1152                    VisitChildrenResult::abort(idx, sub_idx)
1153                } else {
1154                    VisitChildrenResult::CONTINUE
1155                }
1156            }
1157        }
1158    };
1159    if index == -1 {
1160        visit_at_index(0)
1161    } else {
1162        match &item_tree_array[index as usize] {
1163            ItemTreeNode::Item { children_index, children_count, .. } => {
1164                for c in 0..*children_count {
1165                    let idx = match order {
1166                        TraversalOrder::BackToFront => *children_index + c,
1167                        TraversalOrder::FrontToBack => *children_index + *children_count - c - 1,
1168                    };
1169                    let maybe_abort_index = visit_at_index(idx);
1170                    if maybe_abort_index.has_aborted() {
1171                        return maybe_abort_index;
1172                    }
1173                }
1174            }
1175            ItemTreeNode::DynamicTree { .. } => panic!("should not be called with dynamic items"),
1176        };
1177        VisitChildrenResult::CONTINUE
1178    }
1179}
1180
1181#[cfg(feature = "ffi")]
1182pub(crate) mod ffi {
1183    #![allow(unsafe_code)]
1184
1185    use super::*;
1186    use core::ffi::c_void;
1187
1188    /// Call init() on the ItemVTable of each item in the item array.
1189    #[unsafe(no_mangle)]
1190    pub unsafe extern "C" fn slint_register_item_tree(
1191        item_tree_rc: &ItemTreeRc,
1192        window_handle: *const crate::window::ffi::WindowAdapterRcOpaque,
1193    ) {
1194        let window_adapter = (window_handle as *const WindowAdapterRc).as_ref().cloned();
1195        super::register_item_tree(item_tree_rc, window_adapter)
1196    }
1197
1198    /// Free the backend graphics resources allocated in the item array.
1199    #[unsafe(no_mangle)]
1200    pub unsafe extern "C" fn slint_unregister_item_tree(
1201        component: ItemTreeRefPin,
1202        item_array: Slice<vtable::VOffset<u8, ItemVTable, vtable::AllowPin>>,
1203        window_handle: *const crate::window::ffi::WindowAdapterRcOpaque,
1204    ) {
1205        let window_adapter = &*(window_handle as *const WindowAdapterRc);
1206        super::unregister_item_tree(
1207            core::pin::Pin::new_unchecked(&*(component.as_ptr() as *const u8)),
1208            core::pin::Pin::into_inner(component),
1209            item_array.as_slice(),
1210            window_adapter,
1211        )
1212    }
1213
1214    /// Expose `crate::item_tree::visit_item_tree` to C++
1215    ///
1216    /// Safety: Assume a correct implementation of the item_tree array
1217    #[unsafe(no_mangle)]
1218    pub unsafe extern "C" fn slint_visit_item_tree(
1219        item_tree: &ItemTreeRc,
1220        item_tree_array: Slice<ItemTreeNode>,
1221        index: isize,
1222        order: TraversalOrder,
1223        visitor: VRefMut<ItemVisitorVTable>,
1224        visit_dynamic: extern "C" fn(
1225            base: *const c_void,
1226            order: TraversalOrder,
1227            visitor: vtable::VRefMut<ItemVisitorVTable>,
1228            dyn_index: u32,
1229        ) -> VisitChildrenResult,
1230    ) -> VisitChildrenResult {
1231        crate::item_tree::visit_item_tree(
1232            VRc::as_pin_ref(item_tree),
1233            item_tree,
1234            item_tree_array.as_slice(),
1235            index,
1236            order,
1237            visitor,
1238            |a, b, c, d| visit_dynamic(a.get_ref() as *const vtable::Dyn as *const c_void, b, c, d),
1239        )
1240    }
1241}
1242
1243#[cfg(test)]
1244mod tests {
1245    use super::*;
1246    use std::vec;
1247
1248    struct TestItemTree {
1249        parent_component: Option<ItemTreeRc>,
1250        item_tree: Vec<ItemTreeNode>,
1251        subtrees: std::cell::RefCell<Vec<Vec<vtable::VRc<ItemTreeVTable, TestItemTree>>>>,
1252        subtree_index: usize,
1253    }
1254
1255    impl ItemTree for TestItemTree {
1256        fn visit_children_item(
1257            self: core::pin::Pin<&Self>,
1258            _1: isize,
1259            _2: crate::item_tree::TraversalOrder,
1260            _3: vtable::VRefMut<crate::item_tree::ItemVisitorVTable>,
1261        ) -> crate::item_tree::VisitChildrenResult {
1262            unimplemented!("Not needed for this test")
1263        }
1264
1265        fn get_item_ref(
1266            self: core::pin::Pin<&Self>,
1267            _1: u32,
1268        ) -> core::pin::Pin<vtable::VRef<'_, super::ItemVTable>> {
1269            unimplemented!("Not needed for this test")
1270        }
1271
1272        fn get_item_tree(self: core::pin::Pin<&Self>) -> Slice<'_, ItemTreeNode> {
1273            Slice::from_slice(&self.get_ref().item_tree)
1274        }
1275
1276        fn parent_node(self: core::pin::Pin<&Self>, result: &mut ItemWeak) {
1277            if let Some(parent_item) = self.parent_component.clone() {
1278                *result =
1279                    ItemRc::new(parent_item.clone(), self.item_tree[0].parent_index()).downgrade();
1280            }
1281        }
1282
1283        fn embed_component(
1284            self: core::pin::Pin<&Self>,
1285            _parent_component: &ItemTreeWeak,
1286            _item_tree_index: u32,
1287        ) -> bool {
1288            false
1289        }
1290
1291        fn layout_info(self: core::pin::Pin<&Self>, _1: Orientation) -> LayoutInfo {
1292            unimplemented!("Not needed for this test")
1293        }
1294
1295        fn subtree_index(self: core::pin::Pin<&Self>) -> usize {
1296            self.subtree_index
1297        }
1298
1299        fn get_subtree_range(self: core::pin::Pin<&Self>, subtree_index: u32) -> IndexRange {
1300            (0..self.subtrees.borrow()[subtree_index as usize].len()).into()
1301        }
1302
1303        fn get_subtree(
1304            self: core::pin::Pin<&Self>,
1305            subtree_index: u32,
1306            component_index: usize,
1307            result: &mut ItemTreeWeak,
1308        ) {
1309            if let Some(vrc) = self.subtrees.borrow()[subtree_index as usize].get(component_index) {
1310                *result = vtable::VRc::downgrade(&vtable::VRc::into_dyn(vrc.clone()))
1311            }
1312        }
1313
1314        fn accessible_role(self: Pin<&Self>, _: u32) -> AccessibleRole {
1315            unimplemented!("Not needed for this test")
1316        }
1317
1318        fn accessible_string_property(
1319            self: Pin<&Self>,
1320            _: u32,
1321            _: AccessibleStringProperty,
1322            _: &mut SharedString,
1323        ) -> bool {
1324            false
1325        }
1326
1327        fn item_element_infos(self: Pin<&Self>, _: u32, _: &mut SharedString) -> bool {
1328            false
1329        }
1330
1331        fn window_adapter(
1332            self: Pin<&Self>,
1333            _do_create: bool,
1334            _result: &mut Option<WindowAdapterRc>,
1335        ) {
1336            unimplemented!("Not needed for this test")
1337        }
1338
1339        fn item_geometry(self: Pin<&Self>, _: u32) -> LogicalRect {
1340            unimplemented!("Not needed for this test")
1341        }
1342
1343        fn accessibility_action(self: core::pin::Pin<&Self>, _: u32, _: &AccessibilityAction) {
1344            unimplemented!("Not needed for this test")
1345        }
1346
1347        fn supported_accessibility_actions(
1348            self: core::pin::Pin<&Self>,
1349            _: u32,
1350        ) -> SupportedAccessibilityAction {
1351            unimplemented!("Not needed for this test")
1352        }
1353    }
1354
1355    crate::item_tree::ItemTreeVTable_static!(static TEST_COMPONENT_VT for TestItemTree);
1356
1357    fn create_one_node_component() -> VRc<ItemTreeVTable, vtable::Dyn> {
1358        let component = VRc::new(TestItemTree {
1359            parent_component: None,
1360            item_tree: vec![ItemTreeNode::Item {
1361                is_accessible: false,
1362                children_count: 0,
1363                children_index: 1,
1364                parent_index: 0,
1365                item_array_index: 0,
1366            }],
1367            subtrees: std::cell::RefCell::new(vec![]),
1368            subtree_index: usize::MAX,
1369        });
1370        VRc::into_dyn(component)
1371    }
1372
1373    #[test]
1374    fn test_tree_traversal_one_node_structure() {
1375        let component = create_one_node_component();
1376
1377        let item = ItemRc::new(component.clone(), 0);
1378
1379        assert!(item.first_child().is_none());
1380        assert!(item.last_child().is_none());
1381        assert!(item.previous_sibling().is_none());
1382        assert!(item.next_sibling().is_none());
1383    }
1384
1385    #[test]
1386    fn test_tree_traversal_one_node_forward_focus() {
1387        let component = create_one_node_component();
1388
1389        let item = ItemRc::new(component.clone(), 0);
1390
1391        // Wrap the focus around:
1392        assert_eq!(item.next_focus_item(), item);
1393    }
1394
1395    #[test]
1396    fn test_tree_traversal_one_node_backward_focus() {
1397        let component = create_one_node_component();
1398
1399        let item = ItemRc::new(component.clone(), 0);
1400
1401        // Wrap the focus around:
1402        assert_eq!(item.previous_focus_item(), item);
1403    }
1404
1405    fn create_children_nodes() -> VRc<ItemTreeVTable, vtable::Dyn> {
1406        let component = VRc::new(TestItemTree {
1407            parent_component: None,
1408            item_tree: vec![
1409                ItemTreeNode::Item {
1410                    is_accessible: false,
1411                    children_count: 3,
1412                    children_index: 1,
1413                    parent_index: 0,
1414                    item_array_index: 0,
1415                },
1416                ItemTreeNode::Item {
1417                    is_accessible: false,
1418                    children_count: 0,
1419                    children_index: 4,
1420                    parent_index: 0,
1421                    item_array_index: 1,
1422                },
1423                ItemTreeNode::Item {
1424                    is_accessible: false,
1425                    children_count: 0,
1426                    children_index: 4,
1427                    parent_index: 0,
1428                    item_array_index: 2,
1429                },
1430                ItemTreeNode::Item {
1431                    is_accessible: false,
1432                    children_count: 0,
1433                    children_index: 4,
1434                    parent_index: 0,
1435                    item_array_index: 3,
1436                },
1437            ],
1438            subtrees: std::cell::RefCell::new(vec![]),
1439            subtree_index: usize::MAX,
1440        });
1441        VRc::into_dyn(component)
1442    }
1443
1444    #[test]
1445    fn test_tree_traversal_children_nodes_structure() {
1446        let component = create_children_nodes();
1447
1448        // Examine root node:
1449        let item = ItemRc::new(component.clone(), 0);
1450        assert!(item.previous_sibling().is_none());
1451        assert!(item.next_sibling().is_none());
1452
1453        let fc = item.first_child().unwrap();
1454        assert_eq!(fc.index(), 1);
1455        assert!(VRc::ptr_eq(fc.item_tree(), item.item_tree()));
1456
1457        let fcn = fc.next_sibling().unwrap();
1458        assert_eq!(fcn.index(), 2);
1459
1460        let lc = item.last_child().unwrap();
1461        assert_eq!(lc.index(), 3);
1462        assert!(VRc::ptr_eq(lc.item_tree(), item.item_tree()));
1463
1464        let lcp = lc.previous_sibling().unwrap();
1465        assert!(VRc::ptr_eq(lcp.item_tree(), item.item_tree()));
1466        assert_eq!(lcp.index(), 2);
1467
1468        // Examine first child:
1469        assert!(fc.first_child().is_none());
1470        assert!(fc.last_child().is_none());
1471        assert!(fc.previous_sibling().is_none());
1472        assert_eq!(fc.parent_item(ParentItemTraversalMode::StopAtPopups).unwrap(), item);
1473
1474        // Examine item between first and last child:
1475        assert_eq!(fcn, lcp);
1476        assert_eq!(lcp.parent_item(ParentItemTraversalMode::StopAtPopups).unwrap(), item);
1477        assert_eq!(fcn.previous_sibling().unwrap(), fc);
1478        assert_eq!(fcn.next_sibling().unwrap(), lc);
1479
1480        // Examine last child:
1481        assert!(lc.first_child().is_none());
1482        assert!(lc.last_child().is_none());
1483        assert!(lc.next_sibling().is_none());
1484        assert_eq!(lc.parent_item(ParentItemTraversalMode::StopAtPopups).unwrap(), item);
1485    }
1486
1487    #[test]
1488    fn test_tree_traversal_children_nodes_forward_focus() {
1489        let component = create_children_nodes();
1490
1491        let item = ItemRc::new(component.clone(), 0);
1492        let fc = item.first_child().unwrap();
1493        let fcn = fc.next_sibling().unwrap();
1494        let lc = item.last_child().unwrap();
1495
1496        let mut cursor = item.clone();
1497
1498        cursor = cursor.next_focus_item();
1499        assert_eq!(cursor, fc);
1500
1501        cursor = cursor.next_focus_item();
1502        assert_eq!(cursor, fcn);
1503
1504        cursor = cursor.next_focus_item();
1505        assert_eq!(cursor, lc);
1506
1507        cursor = cursor.next_focus_item();
1508        assert_eq!(cursor, item);
1509    }
1510
1511    #[test]
1512    fn test_tree_traversal_children_nodes_backward_focus() {
1513        let component = create_children_nodes();
1514
1515        let item = ItemRc::new(component.clone(), 0);
1516        let fc = item.first_child().unwrap();
1517        let fcn = fc.next_sibling().unwrap();
1518        let lc = item.last_child().unwrap();
1519
1520        let mut cursor = item.clone();
1521
1522        cursor = cursor.previous_focus_item();
1523        assert_eq!(cursor, lc);
1524
1525        cursor = cursor.previous_focus_item();
1526        assert_eq!(cursor, fcn);
1527
1528        cursor = cursor.previous_focus_item();
1529        assert_eq!(cursor, fc);
1530
1531        cursor = cursor.previous_focus_item();
1532        assert_eq!(cursor, item);
1533    }
1534
1535    fn create_empty_subtree() -> VRc<ItemTreeVTable, vtable::Dyn> {
1536        let component = vtable::VRc::new(TestItemTree {
1537            parent_component: None,
1538            item_tree: vec![
1539                ItemTreeNode::Item {
1540                    is_accessible: false,
1541                    children_count: 1,
1542                    children_index: 1,
1543                    parent_index: 0,
1544                    item_array_index: 0,
1545                },
1546                ItemTreeNode::DynamicTree { index: 0, parent_index: 0 },
1547            ],
1548            subtrees: std::cell::RefCell::new(vec![vec![]]),
1549            subtree_index: usize::MAX,
1550        });
1551        vtable::VRc::into_dyn(component)
1552    }
1553
1554    #[test]
1555    fn test_tree_traversal_empty_subtree_structure() {
1556        let component = create_empty_subtree();
1557
1558        // Examine root node:
1559        let item = ItemRc::new(component.clone(), 0);
1560        assert!(item.previous_sibling().is_none());
1561        assert!(item.next_sibling().is_none());
1562        assert!(item.first_child().is_none());
1563        assert!(item.last_child().is_none());
1564
1565        // Wrap the focus around:
1566        assert!(item.previous_focus_item() == item);
1567        assert!(item.next_focus_item() == item);
1568    }
1569
1570    #[test]
1571    fn test_tree_traversal_empty_subtree_forward_focus() {
1572        let component = create_empty_subtree();
1573
1574        // Examine root node:
1575        let item = ItemRc::new(component.clone(), 0);
1576
1577        assert!(item.next_focus_item() == item);
1578    }
1579
1580    #[test]
1581    fn test_tree_traversal_empty_subtree_backward_focus() {
1582        let component = create_empty_subtree();
1583
1584        // Examine root node:
1585        let item = ItemRc::new(component.clone(), 0);
1586
1587        assert!(item.previous_focus_item() == item);
1588    }
1589
1590    fn create_item_subtree_item() -> VRc<ItemTreeVTable, vtable::Dyn> {
1591        let component = VRc::new(TestItemTree {
1592            parent_component: None,
1593            item_tree: vec![
1594                ItemTreeNode::Item {
1595                    is_accessible: false,
1596                    children_count: 3,
1597                    children_index: 1,
1598                    parent_index: 0,
1599                    item_array_index: 0,
1600                },
1601                ItemTreeNode::Item {
1602                    is_accessible: false,
1603                    children_count: 0,
1604                    children_index: 4,
1605                    parent_index: 0,
1606                    item_array_index: 0,
1607                },
1608                ItemTreeNode::DynamicTree { index: 0, parent_index: 0 },
1609                ItemTreeNode::Item {
1610                    is_accessible: false,
1611                    children_count: 0,
1612                    children_index: 4,
1613                    parent_index: 0,
1614                    item_array_index: 0,
1615                },
1616            ],
1617            subtrees: std::cell::RefCell::new(vec![]),
1618            subtree_index: usize::MAX,
1619        });
1620
1621        component.as_pin_ref().subtrees.replace(vec![vec![VRc::new(TestItemTree {
1622            parent_component: Some(VRc::into_dyn(component.clone())),
1623            item_tree: vec![ItemTreeNode::Item {
1624                is_accessible: false,
1625                children_count: 0,
1626                children_index: 1,
1627                parent_index: 2,
1628                item_array_index: 0,
1629            }],
1630            subtrees: std::cell::RefCell::new(vec![]),
1631            subtree_index: 0,
1632        })]]);
1633
1634        VRc::into_dyn(component)
1635    }
1636
1637    #[test]
1638    fn test_tree_traversal_item_subtree_item_structure() {
1639        let component = create_item_subtree_item();
1640
1641        // Examine root node:
1642        let item = ItemRc::new(component.clone(), 0);
1643        assert!(item.previous_sibling().is_none());
1644        assert!(item.next_sibling().is_none());
1645
1646        let fc = item.first_child().unwrap();
1647        assert!(VRc::ptr_eq(fc.item_tree(), item.item_tree()));
1648        assert_eq!(fc.index(), 1);
1649
1650        let lc = item.last_child().unwrap();
1651        assert!(VRc::ptr_eq(lc.item_tree(), item.item_tree()));
1652        assert_eq!(lc.index(), 3);
1653
1654        let fcn = fc.next_sibling().unwrap();
1655        let lcp = lc.previous_sibling().unwrap();
1656
1657        assert_eq!(fcn, lcp);
1658        assert!(!VRc::ptr_eq(fcn.item_tree(), item.item_tree()));
1659
1660        let last = fcn.next_sibling().unwrap();
1661        assert_eq!(last, lc);
1662
1663        let first = lcp.previous_sibling().unwrap();
1664        assert_eq!(first, fc);
1665    }
1666
1667    #[test]
1668    fn test_tree_traversal_item_subtree_item_forward_focus() {
1669        let component = create_item_subtree_item();
1670
1671        let item = ItemRc::new(component.clone(), 0);
1672        let fc = item.first_child().unwrap();
1673        let lc = item.last_child().unwrap();
1674        let fcn = fc.next_sibling().unwrap();
1675
1676        let mut cursor = item.clone();
1677
1678        cursor = cursor.next_focus_item();
1679        assert_eq!(cursor, fc);
1680
1681        cursor = cursor.next_focus_item();
1682        assert_eq!(cursor, fcn);
1683
1684        cursor = cursor.next_focus_item();
1685        assert_eq!(cursor, lc);
1686
1687        cursor = cursor.next_focus_item();
1688        assert_eq!(cursor, item);
1689    }
1690
1691    #[test]
1692    fn test_tree_traversal_item_subtree_item_backward_focus() {
1693        let component = create_item_subtree_item();
1694
1695        let item = ItemRc::new(component.clone(), 0);
1696        let fc = item.first_child().unwrap();
1697        let lc = item.last_child().unwrap();
1698        let fcn = fc.next_sibling().unwrap();
1699
1700        let mut cursor = item.clone();
1701
1702        cursor = cursor.previous_focus_item();
1703        assert_eq!(cursor, lc);
1704
1705        cursor = cursor.previous_focus_item();
1706        assert_eq!(cursor, fcn);
1707
1708        cursor = cursor.previous_focus_item();
1709        assert_eq!(cursor, fc);
1710
1711        cursor = cursor.previous_focus_item();
1712        assert_eq!(cursor, item);
1713    }
1714
1715    fn create_nested_subtrees() -> VRc<ItemTreeVTable, vtable::Dyn> {
1716        let component = VRc::new(TestItemTree {
1717            parent_component: None,
1718            item_tree: vec![
1719                ItemTreeNode::Item {
1720                    is_accessible: false,
1721                    children_count: 3,
1722                    children_index: 1,
1723                    parent_index: 0,
1724                    item_array_index: 0,
1725                },
1726                ItemTreeNode::Item {
1727                    is_accessible: false,
1728                    children_count: 0,
1729                    children_index: 4,
1730                    parent_index: 0,
1731                    item_array_index: 0,
1732                },
1733                ItemTreeNode::DynamicTree { index: 0, parent_index: 0 },
1734                ItemTreeNode::Item {
1735                    is_accessible: false,
1736                    children_count: 0,
1737                    children_index: 4,
1738                    parent_index: 0,
1739                    item_array_index: 0,
1740                },
1741            ],
1742            subtrees: std::cell::RefCell::new(vec![]),
1743            subtree_index: usize::MAX,
1744        });
1745
1746        let sub_component1 = VRc::new(TestItemTree {
1747            parent_component: Some(VRc::into_dyn(component.clone())),
1748            item_tree: vec![
1749                ItemTreeNode::Item {
1750                    is_accessible: false,
1751                    children_count: 1,
1752                    children_index: 1,
1753                    parent_index: 2,
1754                    item_array_index: 0,
1755                },
1756                ItemTreeNode::DynamicTree { index: 0, parent_index: 0 },
1757            ],
1758            subtrees: std::cell::RefCell::new(vec![]),
1759            subtree_index: usize::MAX,
1760        });
1761        let sub_component2 = VRc::new(TestItemTree {
1762            parent_component: Some(VRc::into_dyn(sub_component1.clone())),
1763            item_tree: vec![
1764                ItemTreeNode::Item {
1765                    is_accessible: false,
1766                    children_count: 1,
1767                    children_index: 1,
1768                    parent_index: 1,
1769                    item_array_index: 0,
1770                },
1771                ItemTreeNode::Item {
1772                    is_accessible: false,
1773                    children_count: 0,
1774                    children_index: 2,
1775                    parent_index: 0,
1776                    item_array_index: 0,
1777                },
1778            ],
1779            subtrees: std::cell::RefCell::new(vec![]),
1780            subtree_index: usize::MAX,
1781        });
1782
1783        sub_component1.as_pin_ref().subtrees.replace(vec![vec![sub_component2]]);
1784        component.as_pin_ref().subtrees.replace(vec![vec![sub_component1]]);
1785
1786        VRc::into_dyn(component)
1787    }
1788
1789    #[test]
1790    fn test_tree_traversal_nested_subtrees_structure() {
1791        let component = create_nested_subtrees();
1792
1793        // Examine root node:
1794        let item = ItemRc::new(component.clone(), 0);
1795        assert!(item.previous_sibling().is_none());
1796        assert!(item.next_sibling().is_none());
1797
1798        let fc = item.first_child().unwrap();
1799        assert!(VRc::ptr_eq(fc.item_tree(), item.item_tree()));
1800        assert_eq!(fc.index(), 1);
1801
1802        let lc = item.last_child().unwrap();
1803        assert!(VRc::ptr_eq(lc.item_tree(), item.item_tree()));
1804        assert_eq!(lc.index(), 3);
1805
1806        let fcn = fc.next_sibling().unwrap();
1807        let lcp = lc.previous_sibling().unwrap();
1808
1809        assert_eq!(fcn, lcp);
1810        assert!(!VRc::ptr_eq(fcn.item_tree(), item.item_tree()));
1811
1812        let last = fcn.next_sibling().unwrap();
1813        assert_eq!(last, lc);
1814
1815        let first = lcp.previous_sibling().unwrap();
1816        assert_eq!(first, fc);
1817
1818        // Nested component:
1819        let nested_root = fcn.first_child().unwrap();
1820        assert_eq!(nested_root, fcn.last_child().unwrap());
1821        assert!(nested_root.next_sibling().is_none());
1822        assert!(nested_root.previous_sibling().is_none());
1823        assert!(!VRc::ptr_eq(nested_root.item_tree(), item.item_tree()));
1824        assert!(!VRc::ptr_eq(nested_root.item_tree(), fcn.item_tree()));
1825
1826        let nested_child = nested_root.first_child().unwrap();
1827        assert_eq!(nested_child, nested_root.last_child().unwrap());
1828        assert!(VRc::ptr_eq(nested_root.item_tree(), nested_child.item_tree()));
1829    }
1830
1831    #[test]
1832    fn test_tree_traversal_nested_subtrees_forward_focus() {
1833        let component = create_nested_subtrees();
1834
1835        // Examine root node:
1836        let item = ItemRc::new(component.clone(), 0);
1837        let fc = item.first_child().unwrap();
1838        let fcn = fc.next_sibling().unwrap();
1839        let lc = item.last_child().unwrap();
1840        let nested_root = fcn.first_child().unwrap();
1841        let nested_child = nested_root.first_child().unwrap();
1842
1843        // Focus traversal:
1844        let mut cursor = item.clone();
1845
1846        cursor = cursor.next_focus_item();
1847        assert_eq!(cursor, fc);
1848
1849        cursor = cursor.next_focus_item();
1850        assert_eq!(cursor, fcn);
1851
1852        cursor = cursor.next_focus_item();
1853        assert_eq!(cursor, nested_root);
1854
1855        cursor = cursor.next_focus_item();
1856        assert_eq!(cursor, nested_child);
1857
1858        cursor = cursor.next_focus_item();
1859        assert_eq!(cursor, lc);
1860
1861        cursor = cursor.next_focus_item();
1862        assert_eq!(cursor, item);
1863    }
1864
1865    #[test]
1866    fn test_tree_traversal_nested_subtrees_backward_focus() {
1867        let component = create_nested_subtrees();
1868
1869        // Examine root node:
1870        let item = ItemRc::new(component.clone(), 0);
1871        let fc = item.first_child().unwrap();
1872        let fcn = fc.next_sibling().unwrap();
1873        let lc = item.last_child().unwrap();
1874        let nested_root = fcn.first_child().unwrap();
1875        let nested_child = nested_root.first_child().unwrap();
1876
1877        // Focus traversal:
1878        let mut cursor = item.clone();
1879
1880        cursor = cursor.previous_focus_item();
1881        assert_eq!(cursor, lc);
1882
1883        cursor = cursor.previous_focus_item();
1884        assert_eq!(cursor, nested_child);
1885
1886        cursor = cursor.previous_focus_item();
1887        assert_eq!(cursor, nested_root);
1888
1889        cursor = cursor.previous_focus_item();
1890        assert_eq!(cursor, fcn);
1891
1892        cursor = cursor.previous_focus_item();
1893        assert_eq!(cursor, fc);
1894
1895        cursor = cursor.previous_focus_item();
1896        assert_eq!(cursor, item);
1897    }
1898
1899    fn create_subtrees_item() -> VRc<ItemTreeVTable, vtable::Dyn> {
1900        let component = VRc::new(TestItemTree {
1901            parent_component: None,
1902            item_tree: vec![
1903                ItemTreeNode::Item {
1904                    is_accessible: false,
1905                    children_count: 2,
1906                    children_index: 1,
1907                    parent_index: 0,
1908                    item_array_index: 0,
1909                },
1910                ItemTreeNode::DynamicTree { index: 0, parent_index: 0 },
1911                ItemTreeNode::Item {
1912                    is_accessible: false,
1913                    children_count: 0,
1914                    children_index: 4,
1915                    parent_index: 0,
1916                    item_array_index: 0,
1917                },
1918            ],
1919            subtrees: std::cell::RefCell::new(vec![]),
1920            subtree_index: usize::MAX,
1921        });
1922
1923        component.as_pin_ref().subtrees.replace(vec![vec![
1924            VRc::new(TestItemTree {
1925                parent_component: Some(VRc::into_dyn(component.clone())),
1926                item_tree: vec![ItemTreeNode::Item {
1927                    is_accessible: false,
1928                    children_count: 0,
1929                    children_index: 1,
1930                    parent_index: 1,
1931                    item_array_index: 0,
1932                }],
1933                subtrees: std::cell::RefCell::new(vec![]),
1934                subtree_index: 0,
1935            }),
1936            VRc::new(TestItemTree {
1937                parent_component: Some(VRc::into_dyn(component.clone())),
1938                item_tree: vec![ItemTreeNode::Item {
1939                    is_accessible: false,
1940                    children_count: 0,
1941                    children_index: 1,
1942                    parent_index: 1,
1943                    item_array_index: 0,
1944                }],
1945                subtrees: std::cell::RefCell::new(vec![]),
1946                subtree_index: 1,
1947            }),
1948            VRc::new(TestItemTree {
1949                parent_component: Some(VRc::into_dyn(component.clone())),
1950                item_tree: vec![ItemTreeNode::Item {
1951                    is_accessible: false,
1952                    children_count: 0,
1953                    children_index: 1,
1954                    parent_index: 1,
1955                    item_array_index: 0,
1956                }],
1957                subtrees: std::cell::RefCell::new(vec![]),
1958                subtree_index: 2,
1959            }),
1960        ]]);
1961
1962        VRc::into_dyn(component)
1963    }
1964
1965    #[test]
1966    fn test_tree_traversal_subtrees_item_structure() {
1967        let component = create_subtrees_item();
1968
1969        // Examine root node:
1970        let item = ItemRc::new(component.clone(), 0);
1971        assert!(item.previous_sibling().is_none());
1972        assert!(item.next_sibling().is_none());
1973
1974        let sub1 = item.first_child().unwrap();
1975        assert_eq!(sub1.index(), 0);
1976        assert!(!VRc::ptr_eq(sub1.item_tree(), item.item_tree()));
1977
1978        // assert!(sub1.previous_sibling().is_none());
1979
1980        let sub2 = sub1.next_sibling().unwrap();
1981        assert_eq!(sub2.index(), 0);
1982        assert!(!VRc::ptr_eq(sub1.item_tree(), sub2.item_tree()));
1983        assert!(!VRc::ptr_eq(item.item_tree(), sub2.item_tree()));
1984
1985        assert!(sub2.previous_sibling() == Some(sub1.clone()));
1986
1987        let sub3 = sub2.next_sibling().unwrap();
1988        assert_eq!(sub3.index(), 0);
1989        assert!(!VRc::ptr_eq(sub1.item_tree(), sub2.item_tree()));
1990        assert!(!VRc::ptr_eq(sub2.item_tree(), sub3.item_tree()));
1991        assert!(!VRc::ptr_eq(item.item_tree(), sub3.item_tree()));
1992
1993        assert_eq!(sub3.previous_sibling().unwrap(), sub2.clone());
1994    }
1995
1996    #[test]
1997    fn test_component_item_tree_root_only() {
1998        let nodes = vec![ItemTreeNode::Item {
1999            is_accessible: false,
2000            children_count: 0,
2001            children_index: 1,
2002            parent_index: 0,
2003            item_array_index: 0,
2004        }];
2005
2006        let tree: ItemTreeNodeArray = (nodes.as_slice()).into();
2007
2008        assert_eq!(tree.first_child(0), None);
2009        assert_eq!(tree.last_child(0), None);
2010        assert_eq!(tree.previous_sibling(0), None);
2011        assert_eq!(tree.next_sibling(0), None);
2012        assert_eq!(tree.parent(0), None);
2013    }
2014
2015    #[test]
2016    fn test_component_item_tree_one_child() {
2017        let nodes = vec![
2018            ItemTreeNode::Item {
2019                is_accessible: false,
2020                children_count: 1,
2021                children_index: 1,
2022                parent_index: 0,
2023                item_array_index: 0,
2024            },
2025            ItemTreeNode::Item {
2026                is_accessible: false,
2027                children_count: 0,
2028                children_index: 2,
2029                parent_index: 0,
2030                item_array_index: 0,
2031            },
2032        ];
2033
2034        let tree: ItemTreeNodeArray = (nodes.as_slice()).into();
2035
2036        assert_eq!(tree.first_child(0), Some(1));
2037        assert_eq!(tree.last_child(0), Some(1));
2038        assert_eq!(tree.previous_sibling(0), None);
2039        assert_eq!(tree.next_sibling(0), None);
2040        assert_eq!(tree.parent(0), None);
2041        assert_eq!(tree.previous_sibling(1), None);
2042        assert_eq!(tree.next_sibling(1), None);
2043        assert_eq!(tree.parent(1), Some(0));
2044    }
2045
2046    #[test]
2047    fn test_component_item_tree_tree_children() {
2048        let nodes = vec![
2049            ItemTreeNode::Item {
2050                is_accessible: false,
2051                children_count: 3,
2052                children_index: 1,
2053                parent_index: 0,
2054                item_array_index: 0,
2055            },
2056            ItemTreeNode::Item {
2057                is_accessible: false,
2058                children_count: 0,
2059                children_index: 4,
2060                parent_index: 0,
2061                item_array_index: 0,
2062            },
2063            ItemTreeNode::Item {
2064                is_accessible: false,
2065                children_count: 0,
2066                children_index: 4,
2067                parent_index: 0,
2068                item_array_index: 0,
2069            },
2070            ItemTreeNode::Item {
2071                is_accessible: false,
2072                children_count: 0,
2073                children_index: 4,
2074                parent_index: 0,
2075                item_array_index: 0,
2076            },
2077        ];
2078
2079        let tree: ItemTreeNodeArray = (nodes.as_slice()).into();
2080
2081        assert_eq!(tree.first_child(0), Some(1));
2082        assert_eq!(tree.last_child(0), Some(3));
2083        assert_eq!(tree.previous_sibling(0), None);
2084        assert_eq!(tree.next_sibling(0), None);
2085        assert_eq!(tree.parent(0), None);
2086
2087        assert_eq!(tree.previous_sibling(1), None);
2088        assert_eq!(tree.next_sibling(1), Some(2));
2089        assert_eq!(tree.parent(1), Some(0));
2090
2091        assert_eq!(tree.previous_sibling(2), Some(1));
2092        assert_eq!(tree.next_sibling(2), Some(3));
2093        assert_eq!(tree.parent(2), Some(0));
2094
2095        assert_eq!(tree.previous_sibling(3), Some(2));
2096        assert_eq!(tree.next_sibling(3), None);
2097        assert_eq!(tree.parent(3), Some(0));
2098    }
2099}