tuirealm-orx-tree

Crates.iotuirealm-orx-tree
lib.rstuirealm-orx-tree
version0.2.0
created_at2025-12-02 18:11:38.565505+00
updated_at2025-12-08 11:51:12.94912+00
descriptionTree Component for TUIRealm with orx-tree
homepage
repositoryhttps://github.com/hasezoey/tuirealm-orx-tree
max_upload_size
id1962343
size148,966
hasezoey (hasezoey)

documentation

README

TUIRealm Tree Component via orx-tree

Build status crates.io dependency status MSRV

A Tree Component for tuirealm via orx-tree.

MSRV & Policy

The current MSRV is 1.88.

The MSRV Policy is to base it on the highest required by tuirealm and orx-tree.

Vs tui-realm-treeview

The Biggest most differential difference is the backing tree implementation. tui-realm-treeview uses orange-trees, which is key-value based, and access is done via id(which is just find) or find, whereas tuirealm-orx-tree uses orx-tree, which only has values (to the user) and access is based on NodeIdx(pointers) or find.

Other differniating factors as of writing are:

  • In tuirealm-orx-tree, node value is responsible for drawing its data
    • This makes it possible to customize indicators (open/closed/loading/error, etc)
  • Thanks to orx-tree, the tree / node API more versatile
    • Especially not having the need to walk through the entire tree for getting a single node (NodeIdx are pointers)
  • tui-realm-treeview did not have a built-in way to display a message when the tree is empty (ex. still loading)
  • tui-realm-treeview did not have a way to properly handle Page-Up / Page-Down, instead only had fixed "scroll steps" (regardless of display size)

Most of my issues with tui-realm-treeview can be found in this issue.

Usage

Documentation can be found in docs.rs.

A full demo can be found in examples/filesystem.

The most basic points:

type TreeView = tuirealm_orx_tree::component::TreeView<String>;

#[derive(Debug, MockComponent)]
struct OurComponent {
  component: TreeView
}

impl OurComponent {
    fn new() -> Self {
        Self {
            component: TreeView::default()
                .background(Color::Reset)
                .foreground(Color::White)
                .border(
                    Borders::default()
                        .color(Color::LightBlue)
                        .modifiers(BorderType::Rounded),
                )
                .indent_size(2)
                .scroll_step_horizontal(NonZeroUsize::new(2).unwrap())
                .empty_tree_text("Loading...")
                .title(" Library ", Alignment::Left)
                .highlight_color(Color::Yellow)
                .highlight_symbol(">"),
        }
    }
}

impl Component<Msg, NoUserEvent> for OurComponent {
    fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
        let result = match ev {
            // selection
            Event::Keyboard(KeyEvent {
                code: Key::Left,
                modifiers: KeyModifiers::NONE,
            }) => self.perform(Cmd::Move(Direction::Left)),
            Event::Keyboard(KeyEvent {
                code: Key::Right,
                modifiers: KeyModifiers::NONE,
            }) => self.perform(Cmd::Move(Direction::Right)),
            Event::Keyboard(KeyEvent {
                code: Key::Down,
                modifiers: KeyModifiers::NONE,
            }) => self.perform(Cmd::Move(Direction::Down)),
            Event::Keyboard(KeyEvent {
                code: Key::Up,
                modifiers: KeyModifiers::NONE,
            }) => self.perform(Cmd::Move(Direction::Up)),
            // etc...
            _ => CmdResult::None,
        };
        match result {
            CmdResult::None => None,
            _ => Some(Msg::ForceRedraw)
        }
    }
}
Commit count: 0

cargo fmt