Widget Tree

The UI is represented as a tree of widgets.

Structure

Root
├── Column
│   ├── Text ("Title")
│   ├── Row
│   │   ├── Button ("OK")
│   │   └── Button ("Cancel")
│   └── Text ("Footer")

Building Trees

let tree = Column::new()
    .child(Text::new("Title"))
    .child(
        Row::new()
            .child(Button::new("OK"))
            .child(Button::new("Cancel"))
    )
    .child(Text::new("Footer"));

Traversal

Depth-First

fn visit_all(widget: &dyn Widget) {
    // Process current
    println!("Widget: {:?}", widget.type_id());

    // Process children
    for child in widget.children() {
        visit_all(child.as_ref());
    }
}

Finding by Selector

fn find_by_test_id<'a>(widget: &'a dyn Widget, id: &str) -> Option<&'a dyn Widget> {
    if widget.test_id() == Some(id) {
        return Some(widget);
    }
    for child in widget.children() {
        if let Some(found) = find_by_test_id(child.as_ref(), id) {
            return Some(found);
        }
    }
    None
}

Lifecycle

PhaseDirectionAction
MeasureBottom-upLeaf→Root size computation
LayoutTop-downRoot→Leaf positioning
PaintAnyEmit draw commands
EventTop-downRoute to target

Children Access

// Immutable access
fn children(&self) -> &[Box<dyn Widget>];

// Mutable access (for layout)
fn children_mut(&mut self) -> &mut [Box<dyn Widget>];

Verified Test

#[test]
fn test_widget_tree() {
    use presentar_widgets::{Column, Button};
    use presentar_core::Widget;

    let tree = Column::new()
        .child(Button::new("A"))
        .child(Button::new("B"));

    assert_eq!(tree.children().len(), 2);
}