docs/development/item-tree.md
Note for AI coding assistants (agents): When to load this document: Working on
internal/core/item_tree.rs, component instantiation, event handling, focus management, or understanding how compiled/interpreted Slint runs at runtime. For general build commands and project structure, see/AGENTS.md.
The item tree is Slint's runtime representation of UI components:
ItemTreeVTable interface| File | Purpose |
|---|---|
internal/core/item_tree.rs | ItemTree trait, ItemRc/ItemWeak, traversal |
internal/core/items.rs | ItemVTable, built-in item definitions |
internal/core/item_focus.rs | Focus chain traversal functions |
internal/core/item_rendering.rs | ItemCache, rendering infrastructure |
internal/core/window.rs | WindowInner, input handling |
internal/interpreter/dynamic_item_tree.rs | Runtime ItemTree for interpreter |
Items are stored as a flat array with parent/child indices:
pub enum ItemTreeNode {
Item {
is_accessible: bool, // Has accessibility info
children_count: u32, // Number of children
children_index: u32, // Index of first child
parent_index: u32, // Parent's index
item_array_index: u32, // Index in item storage
},
DynamicTree {
index: u32, // Repeater index
parent_index: u32,
},
}
DynamicTree nodes represent repeaters (dynamic content)pub struct ItemRc {
item_tree: VRc<ItemTreeVTable>, // Containing tree
index: u32, // Index within tree
}
Navigation methods:
parent_item() - Get parent (with optional popup boundary)first_child() / last_child() - First/last childnext_sibling() / previous_sibling() - Siblingsvisit_descendants() - Visit all descendantsItemRc::downgrade()ItemRc via .upgrade()The virtual function table all component trees implement:
| Function | Purpose |
|---|---|
visit_children_item | Traverse children with visitor pattern |
get_item_ref | Get item at index |
get_item_tree | Get static tree structure |
parent_node | Get parent item reference |
layout_info | Get layout constraints |
item_geometry | Get item position/size |
window_adapter | Get/create window adapter |
Both paths implement the same ItemTreeVTable:
| Aspect | Compiled | Interpreted |
|---|---|---|
| Tree structure | Compile-time array | ItemTreeDescription |
| Properties | Struct fields | Dynamic offsets |
| Bindings | Generated code | Runtime evaluation |
| VTable | Static | dynamic_item_tree.rs |
Interpreter key types:
ItemTreeDescription<'id> - Component metadataItemTreeBox<'id> - Instance containerInstanceRef<'a, 'id> - Runtime instance accesspub enum TraversalOrder {
BackToFront, // Rendering (background → foreground)
FrontToBack, // Hit testing (foreground → background)
}
pub struct VisitChildrenResult(u64);
impl VisitChildrenResult {
pub const CONTINUE: Self; // Keep traversing
pub fn abort(index, repeater_index) -> Self; // Stop here
}
| Purpose | Order | Notes |
|---|---|---|
| Rendering | BackToFront | Draw base layers first |
| Hit testing | FrontToBack | Top-most item wins |
| Tab focus | Forward | First child → next sibling |
| Shift+Tab | Backward | Previous sibling → parent |
Focus traversal functions in item_focus.rs:
// Next item in tab order
pub fn default_next_in_local_focus_chain(index, item_tree) -> Option<u32>
// Previous item in tab order
pub fn default_previous_in_local_focus_chain(index, item_tree) -> Option<u32>
// Step out to sibling or parent's sibling
pub fn step_out_of_node(index, item_tree) -> Option<u32>
Focus on ItemRc:
next_focus_item() - Tab key navigationprevious_focus_item() - Shift+Tab navigation// Interpreter path
pub fn instantiate(
description: Rc<ItemTreeDescription>,
parent_ctx: Option<ErasedItemTreeBoxWeak>,
root: Option<ErasedItemTreeBoxWeak>,
window_options: Option<&WindowOptions>,
globals: GlobalStorage,
) -> DynamicComponentVRc
pub enum WindowOptions {
CreateNewWindow, // New window
UseExistingWindow(WindowAdapterRc), // Attach to existing
Embed { parent_item_tree, parent_item_tree_index }, // Sub-component
}
ItemTreeBox wrapperregister_item_tree() to init itemspub fn unregister_item_tree(base, item_tree, item_array, window_adapter)
Each item type implements ItemVTable:
| Function | Purpose |
|---|---|
init() | Initialize after allocation |
layout_info() | Return size constraints |
input_event() | Handle mouse/touch |
input_event_filter_before_children() | Filter events before children |
key_event() | Handle keyboard |
focus_event() | Handle focus changes |
render() | Draw the item |
bounding_rect() | Get bounds |
Repeaters create dynamic subtrees:
DynamicTree node in parent treeget_subtree_range() returns count of instancesget_subtree() retrieves specific instanceItemTreeRcinternal/core/items.rs or new fileItem trait with required methodsItemVTable registrationbuiltins.slintinternal/renderers/*/)children_index and parent_indexitem_focus.rs functionsinput_event_filter_before_childrenItemVisitorVTablevisit_item_tree() with your visitorDynamicTree nodes for repeatersItemTreeVTable# Run interpreter tests (exercises dynamic item tree)
cargo test -p test-driver-interpreter
# Run Rust API tests
cargo test -p test-driver-rust
# Visual inspection
cargo run -p gallery