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