Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

TreeView

Layer: organism · Path: src/organisms/tree_view.rs · Exports: tree_view::{TreeItem, TreeView}

A hierarchy of TreeNode cells (Unity / O3DE Tree View), bound to a &mut usize selection. The tree is a flat list of TreeItems carrying their own depth; the view renders them as nested rows, hiding descendants of collapsed nodes. Expand/collapse state lives in egui memory; clicking an expandable node toggles it. show returns the index clicked, if any.

Design

  • Purpose / when to use — scene hierarchies, file trees, any depth-indented selectable list. (Wrap in a ScrollArea for scrolling — the view itself does not scroll.)

  • Anatomy — a loop over the flat items, each rendered as a TreeNode (.depth(item.depth), .selected(*selected == i), keyed (id, "node", i), optional glyph, .expandable(is_open) when the item is expandable). Descendants of a collapsed node (deeper depth) are skipped via a collapse_until threshold.

  • Variants / states

    StateHow
    leafTreeItem::new(label) with no .expanded(...)
    expandable.expanded(open) — marks it toggleable, seeds default open state
    open / collapsedtracked in a HashSet<usize> in egui memory
    selected*selected == i
    depth.depth(n) — indentation level
  • Tokens / layout consumed — themed indentation/visuals via the TreeNode cell (no direct token use here).

  • Accessibility — click a row to select; clicking an expandable node both selects and toggles it.

API

TreeView<'a>

MethodEffect
TreeView::new(selected: &'a mut usize) -> SelfBind to a selection index; default id Id::new("tree_view").
.items(impl IntoIterator<Item = TreeItem>) -> SelfSet the flat item list (order + depth define the tree).
.id_source(id: impl Hash) -> SelfKey for the persisted expand/collapse set.
.show(ui) -> Option<usize>Render; returns the clicked index, writes *selected, persists expansion.

TreeItem

One row of the tree.

MethodEffect
TreeItem::new(label: impl Into<String>) -> SelfNew leaf at depth = 0, no icon, not expandable.
.depth(depth: usize) -> SelfIndentation level (defines nesting).
.icon(glyph: &'static str) -> SelfLeading glyph.
.expanded(open: bool) -> SelfMark expandable; open seeds the first-frame open state.

Usage

#![allow(unused)]
fn main() {
use ouroboros_ui::organisms::{TreeView, TreeItem};
use ouroboros_ui::egui_phosphor::light;

let mut sel = 0usize;
TreeView::new(&mut sel)
    .items([
        TreeItem::new("Scene").icon(light::FOLDER).expanded(true),
        TreeItem::new("Player").depth(1).icon(light::CUBE),
    ])
    .show(ui);
}
#![allow(unused)]
fn main() {
// realistic — scene hierarchy, persisted selection (from storybook)
use ouroboros_ui::organisms::{TreeView, TreeItem};
use ouroboros_ui::egui_phosphor::light;

let id = egui::Id::new("treeview_demo");
let mut sel = ui.data(|d| d.get_temp::<usize>(id).unwrap_or(1));
TreeView::new(&mut sel)
    .items([
        TreeItem::new("Scene").icon(light::FOLDER).expanded(true),
        TreeItem::new("Player").depth(1).icon(light::CUBE),
        TreeItem::new("Camera").depth(1).icon(light::CUBE),
        TreeItem::new("Environment").depth(1).icon(light::FOLDER).expanded(false),
    ])
    .show(ui);
ui.data_mut(|d| d.insert_temp(id, sel));
}

Composition

Composes TreeNode cells (one per visible row). It never paints — see guards.

Notes

  • Flat model — the tree is a flat Vec<TreeItem> where depth encodes nesting; a collapsed expandable node hides every following item with greater depth (the collapse_until threshold) until depth returns to its level.
  • State ownership — selection is the consumer’s &mut usize (persist it yourself). Expand/collapse is a HashSet<usize> in egui memory keyed by id_source; on the first frame it seeds from each item’s .expanded(true) default. Indices in the set are positional — reordering items shifts which nodes are “open”.
  • Distinct trees need distinct id_source (default is the literal "tree_view").
  • No internal scrolling — wrap in a ScrollArea if the tree can overflow.