slint/internal/compiler/passes/generate_item_indices.rs
Tobias Hunger 93f72b8c99
Some checks are pending
autofix.ci / format_fix (push) Waiting to run
autofix.ci / lint_typecheck (push) Waiting to run
CI / files-changed (push) Waiting to run
CI / build_and_test (--exclude bevy-example, ubuntu-22.04, 1.82) (push) Blocked by required conditions
CI / build_and_test (--exclude ffmpeg --exclude gstreamer-player, --exclude bevy-example, windows-2022, 1.82) (push) Blocked by required conditions
CI / build_and_test (--exclude ffmpeg --exclude gstreamer-player, macos-14, stable) (push) Blocked by required conditions
CI / build_and_test (--exclude ffmpeg --exclude gstreamer-player, windows-2022, beta) (push) Blocked by required conditions
CI / build_and_test (--exclude ffmpeg --exclude gstreamer-player, windows-2022, stable) (push) Blocked by required conditions
CI / build_and_test (ubuntu-22.04, nightly) (push) Blocked by required conditions
CI / node_test (macos-14) (push) Blocked by required conditions
CI / node_test (ubuntu-22.04) (push) Blocked by required conditions
CI / node_test (windows-2022) (push) Blocked by required conditions
CI / python_test (macos-14) (push) Blocked by required conditions
CI / python_test (ubuntu-22.04) (push) Blocked by required conditions
CI / python_test (windows-2022) (push) Blocked by required conditions
CI / cpp_test_driver (macos-13) (push) Blocked by required conditions
CI / cpp_test_driver (ubuntu-22.04) (push) Blocked by required conditions
CI / cpp_test_driver (windows-2022) (push) Blocked by required conditions
CI / cpp_cmake (macos-14, 1.82) (push) Blocked by required conditions
CI / cpp_cmake (ubuntu-22.04, stable) (push) Blocked by required conditions
CI / cpp_cmake (windows-2022, nightly) (push) Blocked by required conditions
CI / cpp_package_test (push) Blocked by required conditions
CI / vsce_build_test (push) Blocked by required conditions
CI / mcu (pico-st7789, thumbv6m-none-eabi) (push) Blocked by required conditions
CI / mcu (pico2-st7789, thumbv8m.main-none-eabihf) (push) Blocked by required conditions
CI / mcu (stm32h735g, thumbv7em-none-eabihf) (push) Blocked by required conditions
CI / mcu-embassy (push) Blocked by required conditions
CI / ffi_32bit_build (push) Blocked by required conditions
CI / docs (push) Blocked by required conditions
CI / wasm (push) Blocked by required conditions
CI / wasm_demo (push) Blocked by required conditions
CI / tree-sitter (push) Blocked by required conditions
CI / updater_test (0.3.0) (push) Blocked by required conditions
CI / fmt_test (push) Blocked by required conditions
CI / esp-idf-quick (push) Blocked by required conditions
CI / android (push) Blocked by required conditions
CI / miri (push) Blocked by required conditions
CI / test-figma-inspector (push) Blocked by required conditions
core: Fix the component container
This fixes the contents of the `n`-th repeater inside the
`ComponentContainer` to also show up in the `n`-th repeater *after*
the `ComponentContainer`.

The ComponentContainer is lowered to a Comonent Container and a
dynamic tree node. The tree node is managed manually and I messed
up the repeater indices since there were no entries in the repeater
array for the embedded components. That mad things hard to keep
consistent as components get merged.

This chnages that: It lowers a Component Container to Something like this:

```slint
    ComponentContainer {
        if false: Emtpy {}
    }
```

This way the standard mechanismns make sure we have something to put into
the repeater list and that unscrews the indices, saving a bit of code along
the way.

The inserted repeated node is still marked as `is_component_placeholder`, so
that we can wire it up as needed.
2025-06-05 13:48:16 +02:00

108 lines
3.9 KiB
Rust

// Copyright © SixtyFPS GmbH <info@slint.dev>
// 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<Component>) {
// 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<Component>,
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,
) {
}
}