133 lines
3.4 KiB
Rust
133 lines
3.4 KiB
Rust
// path_from_the_root: examples/simple.rs
|
|
//
|
|
// Simple example that works with any feature configuration.
|
|
//
|
|
// Run with alloc: cargo run --example simple --features alloc
|
|
// Run without alloc: cargo run --example simple
|
|
|
|
use pages_tui::prelude::*;
|
|
|
|
// =============================================================================
|
|
// Types
|
|
// =============================================================================
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
pub enum Focus {
|
|
Item(usize),
|
|
}
|
|
|
|
impl FocusId for Focus {}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub enum Act {
|
|
Select,
|
|
Up,
|
|
Down,
|
|
}
|
|
|
|
impl Action for Act {}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum Evt {
|
|
Selected(usize),
|
|
}
|
|
|
|
// =============================================================================
|
|
// Pages
|
|
// =============================================================================
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum AppPage {
|
|
List { cursor: usize },
|
|
Detail { item_id: usize },
|
|
}
|
|
|
|
// Static focus targets
|
|
const LIST_FOCUS: &[Focus] = &[Focus::Item(0), Focus::Item(1), Focus::Item(2)];
|
|
const DETAIL_FOCUS: &[Focus] = &[Focus::Item(0)];
|
|
|
|
impl Page for AppPage {
|
|
type Focus = Focus;
|
|
type Action = Act;
|
|
type Event = Evt;
|
|
|
|
fn targets(&self) -> &[Self::Focus] {
|
|
match self {
|
|
AppPage::List { .. } => LIST_FOCUS,
|
|
AppPage::Detail { .. } => DETAIL_FOCUS,
|
|
}
|
|
}
|
|
|
|
fn handle(
|
|
&mut self,
|
|
focus: &Self::Focus,
|
|
action: Self::Action,
|
|
) -> Result<Option<Self::Event>, ComponentError> {
|
|
match (self, action) {
|
|
(AppPage::List { cursor }, Act::Select) => {
|
|
if let Focus::Item(idx) = focus {
|
|
*cursor = *idx;
|
|
return Ok(Some(Evt::Selected(*idx)));
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
// =============================================================================
|
|
// Main
|
|
// =============================================================================
|
|
|
|
fn main() {
|
|
// Works with both alloc and no_std!
|
|
// Default capacities are used, override with const generics if needed:
|
|
// Orchestrator::<AppPage, 4, 8, 8, 16, 4, 4>::new()
|
|
let mut app: Orchestrator<AppPage> = Orchestrator::new();
|
|
|
|
// Register pages
|
|
app.register(AppPage::List { cursor: 0 });
|
|
app.register(AppPage::Detail { item_id: 0 });
|
|
|
|
// Bind keys
|
|
app.bind(Key::enter(), Act::Select);
|
|
app.bind(Key::up(), Act::Up);
|
|
app.bind(Key::down(), Act::Down);
|
|
|
|
// Navigate to list
|
|
app.navigate_to(AppPage::List { cursor: 0 }).unwrap();
|
|
|
|
// Process a key
|
|
#[cfg(feature = "alloc")]
|
|
{
|
|
let events = app.process_frame(Key::enter()).unwrap();
|
|
for e in events {
|
|
println!("Event: {:?}", e);
|
|
}
|
|
}
|
|
|
|
#[cfg(not(feature = "alloc"))]
|
|
{
|
|
if let Ok(Some(e)) = app.process_frame(Key::enter()) {
|
|
// In no_std, you'd handle this differently
|
|
let _ = e;
|
|
}
|
|
}
|
|
|
|
// Check current page
|
|
match app.current() {
|
|
Some(AppPage::List { cursor }) => {
|
|
println!("On list page, cursor at {}", cursor);
|
|
}
|
|
Some(AppPage::Detail { item_id }) => {
|
|
println!("On detail page for item {}", item_id);
|
|
}
|
|
None => {
|
|
println!("No page");
|
|
}
|
|
}
|
|
|
|
println!("✅ Simple example complete");
|
|
}
|