pub struct ElementTree<A> { /* private fields */ }Expand description
Retained element tree produced by reconciliation.
Element and widget IDs are monotonically allocated within one tree and start at one. Storage uses a hash map, so iteration order is unspecified. Relationship fields are not automatically repaired when callers use the low-level mutation/removal APIs.
§Examples
use ailloli_ui_runtime::element::{ElementKind, ElementTree};
let mut tree = ElementTree::<()>::new();
let root = tree.create_element(ElementKind::Empty, None, None);
assert_eq!(tree.root(), Some(root));
assert!(tree.get(root).unwrap().dirty.layout);Implementations§
Source§impl<A> ElementTree<A>
Provides the operations defined for ElementTree<A>.
impl<A> ElementTree<A>
Provides the operations defined for ElementTree<A>.
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates an empty tree with zeroed ID counters and diagnostics.
§Examples
use ailloli_ui_runtime::element::ElementTree;
let tree = ElementTree::<()>::new();
assert!(tree.root().is_none());
assert_eq!(tree.iter_elements().count(), 0);Sourcepub fn root(&self) -> Option<ElementId>
pub fn root(&self) -> Option<ElementId>
Returns the first element ever created as the retained root.
None means no element has yet been created. Low-level
Self::remove_element does not clear this field, so removing the root
can leave a stale Some(id); reconciliation owns normal root lifetime.
§Examples
use ailloli_ui_runtime::element::{ElementKind, ElementTree};
let mut tree = ElementTree::<()>::new();
let id = tree.create_element(ElementKind::Empty, None, None);
assert_eq!(tree.root(), Some(id));Sourcepub fn get(&self, id: ElementId) -> Option<&Element<A>>
pub fn get(&self, id: ElementId) -> Option<&Element<A>>
Borrows an element by ID, returning None for unknown or removed IDs.
§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::element::ElementTree;
let tree = ElementTree::<()> ::new();
assert!(tree.get(ElementId(1)).is_none());Sourcepub fn get_mut(&mut self, id: ElementId) -> Option<&mut Element<A>>
pub fn get_mut(&mut self, id: ElementId) -> Option<&mut Element<A>>
Mutably borrows an element by ID.
Direct edits can bypass revision, cache, parent/child, and diagnostic
invariants. None is returned for unknown or removed IDs.
§Examples
use ailloli_ui_runtime::element::{ElementKind, ElementTree, Key};
let mut tree = ElementTree::<()>::new();
let id = tree.create_element(ElementKind::Empty, None, None);
tree.get_mut(id).unwrap().key = Some(Key::Static("root"));
assert_eq!(tree.get(id).unwrap().key, Some(Key::Static("root")));Sourcepub fn create_element(
&mut self,
kind: ElementKind<A>,
key: Option<Key>,
parent: Option<ElementId>,
) -> ElementId
pub fn create_element( &mut self, kind: ElementKind<A>, key: Option<Key>, parent: Option<ElementId>, ) -> ElementId
Allocates and inserts one dirty retained element.
Element and widget counters are incremented independently and the new
IDs start at one. The first inserted element becomes root; later
insertions do not change it. The element starts layout+paint dirty with
layout/topology revisions 1, no cached layout/bounds, default view
metadata, and caller-supplied parent stored verbatim. It is not
automatically added to the parent’s child list.
§Panics
Panics before changing either counter if either u64 identifier space
is exhausted. Identifiers are never wrapped or silently reused.
§Examples
use ailloli_ui_runtime::element::{ElementKind, ElementTree, Key};
let mut tree = ElementTree::<()>::new();
let id = tree.create_element(ElementKind::Empty, Some(Key::U64(9)), None);
let element = tree.get(id).unwrap();
assert_eq!(id.0, 1);
assert_eq!(element.key, Some(Key::U64(9)));Sourcepub fn set_children(&mut self, parent: ElementId, children: Vec<ElementId>)
pub fn set_children(&mut self, parent: ElementId, children: Vec<ElementId>)
Replaces a parent’s ordered direct-child IDs when the vector differs.
A real change increments topology and layout revisions with wrapping but
reserves zero as a sentinel, clears the layout cache key, marks layout
and paint dirty, and requests commit. Equal vectors and unknown parent
IDs are no-ops. This method does not update each child’s parent, reject
duplicates, or verify that IDs exist.
§Examples
use ailloli_ui_runtime::element::{ElementKind, ElementTree};
let mut tree = ElementTree::<()>::new();
let parent = tree.create_element(ElementKind::Empty, None, None);
let child = tree.create_element(ElementKind::Empty, None, Some(parent));
tree.set_children(parent, vec![child]);
assert_eq!(tree.children_of(parent), &[child]);Sourcepub fn children_of(&self, parent: ElementId) -> &[ElementId]
pub fn children_of(&self, parent: ElementId) -> &[ElementId]
Borrows direct-child IDs in retained order.
Unknown parent IDs return a shared empty slice, making missing and childless parents indistinguishable through this accessor.
§Examples
use ailloli_ui_core::ElementId;
use ailloli_ui_runtime::element::ElementTree;
let tree = ElementTree::<()>::new();
assert_eq!(tree.children_of(ElementId(99)), &[]);Sourcepub fn parent_of(&self, id: ElementId) -> Option<ElementId>
pub fn parent_of(&self, id: ElementId) -> Option<ElementId>
Returns an element’s stored parent ID.
None represents an unknown element, a root, or a detached element.
This accessor does not verify that the returned parent still exists.
§Examples
use ailloli_ui_runtime::element::{ElementKind, ElementTree};
let mut tree = ElementTree::<()>::new();
let parent = tree.create_element(ElementKind::Empty, None, None);
let child = tree.create_element(ElementKind::Empty, None, Some(parent));
assert_eq!(tree.parent_of(child), Some(parent));Sourcepub fn is_ancestor_of(&self, ancestor: ElementId, descendant: ElementId) -> bool
pub fn is_ancestor_of(&self, ancestor: ElementId, descendant: ElementId) -> bool
Returns true if ancestor is an ancestor of descendant (inclusive).
Equal IDs return true even if no such element exists. Otherwise the
method follows stored parent pointers until None; malformed parent
cycles that do not contain ancestor cause an infinite loop.
§Examples
use ailloli_ui_runtime::element::{ElementKind, ElementTree};
let mut tree = ElementTree::<()>::new();
let root = tree.create_element(ElementKind::Empty, None, None);
let child = tree.create_element(ElementKind::Empty, None, Some(root));
assert!(tree.is_ancestor_of(root, child));
assert!(!tree.is_ancestor_of(child, root));Sourcepub fn set_layout(&mut self, id: ElementId, layout: LayoutResult)
pub fn set_layout(&mut self, id: ElementId, layout: LayoutResult)
Stores a layout and clears only layout and paint dirty flags.
Unknown IDs are ignored. This low-level setter leaves input dirtiness,
cache identity, layout-change/commit flags, and committed bounds
untouched; normal layout should use crate::layout::LayoutEngine.
§Examples
use ailloli_ui_runtime::element::{ElementKind, ElementTree};
use ailloli_ui_runtime::layout::LayoutResult;
let mut tree = ElementTree::<()>::new();
let id = tree.create_element(ElementKind::Empty, None, None);
tree.set_layout(id, LayoutResult::empty());
assert!(tree.get(id).unwrap().layout.is_some());
assert!(!tree.get(id).unwrap().dirty.layout);Sourcepub fn set_view_metadata(
&mut self,
id: ElementId,
flex_item: FlexItemStyle,
size_hint: LayoutSizeHint,
)
pub fn set_view_metadata( &mut self, id: ElementId, flex_item: FlexItemStyle, size_hint: LayoutSizeHint, )
Replaces flex-item and declarative size metadata without invalidation.
Unknown IDs are ignored. Reconciliation separately invalidates the element before using this helper.
§Examples
use ailloli_ui_core::style::{FlexItemStyle, LayoutSizeHint};
use ailloli_ui_runtime::element::{ElementKind, ElementTree};
let mut tree = ElementTree::<()>::new();
let id = tree.create_element(ElementKind::Empty, None, None);
let flex = FlexItemStyle { flex_grow: 2.0, ..Default::default() };
tree.set_view_metadata(id, flex, LayoutSizeHint::default());
assert_eq!(tree.get(id).unwrap().flex_item.flex_grow, 2.0);Sourcepub fn set_layout_debug(&mut self, id: ElementId, debug: LayoutDebugInfo)
pub fn set_layout_debug(&mut self, id: ElementId, debug: LayoutDebugInfo)
Stores developer-tooling layout data for an existing element.
Unknown IDs are ignored and no dirty/revision state changes.
§Examples
use ailloli_ui_core::{Constraints, Size};
use ailloli_ui_runtime::layout::LayoutDebugInfo;
let debug = LayoutDebugInfo {
constraints_in: Constraints::tight(1.0, 2.0),
constraints_final: None,
layout_size: Size::new(1.0, 2.0),
};
assert_eq!(debug.layout_size.h, 2.0);Sourcepub fn remove_element(&mut self, id: ElementId) -> Option<Element<A>>
pub fn remove_element(&mut self, id: ElementId) -> Option<Element<A>>
Removes and returns exactly one element.
A removal diagnostic is recorded even when the ID is absent. This low-level operation does not recurse, unlink parent/children, clear the root field, or remove runtime state. Reconciliation uses a private subtree-aware path for normal deletion.
§Examples
use ailloli_ui_runtime::element::{ElementKind, ElementTree};
let mut tree = ElementTree::<()>::new();
let id = tree.create_element(ElementKind::Empty, None, None);
assert_eq!(tree.remove_element(id).unwrap().id, id);
assert!(tree.get(id).is_none());
assert_eq!(tree.root(), Some(id)); // low-level root reference is unchangedSourcepub fn iter_elements(&self) -> impl Iterator<Item = (ElementId, &Element<A>)>
pub fn iter_elements(&self) -> impl Iterator<Item = (ElementId, &Element<A>)>
Iterates all stored elements as (id, reference) pairs.
Hash-map order is unspecified and may differ across runs. The iterator borrows the tree and allocates nothing.
§Examples
use ailloli_ui_runtime::element::{ElementKind, ElementTree};
let mut tree = ElementTree::<()>::new();
tree.create_element(ElementKind::Empty, None, None);
tree.create_element(ElementKind::Empty, None, None);
assert_eq!(tree.iter_elements().count(), 2);Sourcepub fn diagnostics(&self) -> ElementTreeDiagnosticsSnapshot
pub fn diagnostics(&self) -> ElementTreeDiagnosticsSnapshot
Returns a point-in-time copy of saturating per-element work counters.
Reading diagnostics does not clear them.
§Examples
use ailloli_ui_runtime::element::ElementTree;
let tree = ElementTree::<()>::new();
assert!(tree.diagnostics().elements.is_empty());Sourcepub fn resolve_element_by_view_key(
&self,
key: &str,
) -> Result<ElementId, ViewKeyResolveError>
pub fn resolve_element_by_view_key( &self, key: &str, ) -> Result<ElementId, ViewKeyResolveError>
Resolves a unique view key in the window (at most one element per key).
Owned Key::String and borrowed Key::Static values compare by text;
Key::U64 values are ignored. Missing and duplicate matches return
typed errors. Scanning is O(number_of_elements) and allocates a vector
of matching IDs; hash-map iteration does not affect a unique result.
§Errors
Returns ViewKeyResolveError::Missing for zero matches and
ViewKeyResolveError::Duplicate with the exact count for two or more.
§Examples
use ailloli_ui_runtime::element::{ElementKind, ElementTree, Key, ViewKeyResolveError};
let mut tree = ElementTree::<()>::new();
let id = tree.create_element(ElementKind::Empty, Some(Key::Static("search")), None);
assert_eq!(tree.resolve_element_by_view_key("search"), Ok(id));
assert!(matches!(tree.resolve_element_by_view_key("missing"),
Err(ViewKeyResolveError::Missing { .. })));