// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 //! Assign the Element::item_index on each elements use std::rc::Rc; use crate::object_tree::{Component, ElementRc}; /// The item indices are generated and assigned to the ElementRc's item_index for each /// element in the component. The indices are local to the component. /// /// For sub-components the structure of the tree becomes a little complicated, which is best /// illustrated using an example: /// ```slint /// SubCompo := Rectangle { Image {} } /// MainCompo := Window { /// TouchArea {} /// SubCompo {} /// Text { /// Path {} /// } /// } /// ``` /// The item tree for `MainCompo` with its local indices is as follows: /// 0: Window (children: 3, children_offset: 1, parent_index: 0) /// 1: TouchArea (children: 0, children_offset: X, parent_index: 0) /// 2: Rectangle (children: 1, children_offset: 4, parent_index: 0) // SubCompo's root element /// 3: Text (children: 1, children_offset: 5, parent_index: 0) /// 4: Image (children: 0, children_offset: X, parent_index: 2) // SubCompo's child(ren) /// 5: Path (children: 0, children_offset: X, parent_index: 3) pub fn generate_item_indices(component: &Rc) { // In order to create the local indices like in the above example (0-5) we use the same function // that is also used for building the item tree. It recurses into all sub-components, but we skip // them, by checking if the SubComponentState is true. // The immediate children of for example the Window element are emitted first. When a sub-component // is encountered (like `SubCompo`) the root element is emitted, but the children later. This simulates // the structure as if the SubCompo was inlined, but it also means that the local item indices must be // counted continuously. crate::generator::build_item_tree(component, &false, &mut Helper { current_item_index: 0 }); for p in component.popup_windows.borrow().iter() { generate_item_indices(&p.component) } for c in component.menu_item_tree.borrow().iter() { generate_item_indices(c); } } struct Helper { current_item_index: u32, } impl crate::generator::ItemTreeBuilder for Helper { // true when not at the root type SubComponentState = bool; fn push_repeated_item( &mut self, item: &ElementRc, _repeater_count: u32, _parent_index: u32, component_state: &Self::SubComponentState, ) { if !component_state { item.borrow().item_index.set(self.current_item_index).unwrap(); if let crate::langtype::ElementType::Component(c) = &item.borrow().base_type { generate_item_indices(c); } } self.current_item_index += 1; } fn push_native_item( &mut self, item: &ElementRc, children_offset: u32, _parent_index: u32, component_state: &Self::SubComponentState, ) { if !component_state { item.borrow().item_index.set(self.current_item_index).unwrap(); item.borrow().item_index_of_first_children.set(children_offset as _).unwrap(); } self.current_item_index += 1; } fn enter_component( &mut self, item: &ElementRc, _sub_component: &Rc, children_offset: u32, component_state: &Self::SubComponentState, ) -> Self::SubComponentState { if !component_state { item.borrow().item_index.set(self.current_item_index).unwrap(); item.borrow().item_index_of_first_children.set(children_offset as _).unwrap(); } true } fn enter_component_children( &mut self, _item: &ElementRc, _repeater_count: u32, _component_state: &Self::SubComponentState, _sub_component_state: &Self::SubComponentState, ) { } }