144 lines
3.3 KiB
Markdown
144 lines
3.3 KiB
Markdown
WARNING this library is purely GLM4.7/Opus4.5 generated.
|
|
Its based on a real production code that was not yet decoupled into a library.
|
|
This library is core concept extracted for no_std usage.
|
|
For more info visit: https://gitlab.com/filipriec/komp_ac_client
|
|
# pages-tui
|
|
|
|
Type-safe TUI page routing with single-generic orchestration.
|
|
|
|
## Features
|
|
|
|
| Feature | Description |
|
|
|---------|-------------|
|
|
| (none) | Pure `no_std` + heapless. No allocator required. |
|
|
| `alloc` | Enables dynamic allocation (Vec, Box, HashMap). |
|
|
| `std` | Full std support (implies `alloc`). |
|
|
|
|
### Default: Pure `no_std` Heapless
|
|
|
|
```toml
|
|
[dependencies]
|
|
pages-tui = "0.2"
|
|
```
|
|
|
|
No allocator needed! Uses `heapless` collections with const generic capacities.
|
|
|
|
### With Allocation
|
|
|
|
```toml
|
|
[dependencies]
|
|
pages-tui = { version = "0.2", features = ["alloc"] }
|
|
```
|
|
|
|
Uses `Vec`, `Box`, `HashMap` for dynamic sizing and trait objects.
|
|
|
|
### With Full Std
|
|
|
|
```toml
|
|
[dependencies]
|
|
pages-tui = { version = "0.2", features = ["std"] }
|
|
```
|
|
|
|
## Usage
|
|
|
|
Define your page as an enum that implements the `Page` trait:
|
|
|
|
```rust
|
|
use pages_tui::prelude::*;
|
|
|
|
#[derive(Debug, Clone)]
|
|
enum MyPage {
|
|
Home { counter: i32 },
|
|
Settings { dark_mode: bool },
|
|
}
|
|
|
|
impl Page for MyPage {
|
|
type Focus = MyFocus;
|
|
type Action = MyAction;
|
|
type Event = MyEvent;
|
|
|
|
fn targets(&self) -> &[Self::Focus] {
|
|
match self {
|
|
MyPage::Home { .. } => &[MyFocus::Button(0)],
|
|
MyPage::Settings { .. } => &[MyFocus::Toggle],
|
|
}
|
|
}
|
|
|
|
fn handle(&mut self, focus: &Self::Focus, action: Self::Action)
|
|
-> Result<Option<Self::Event>, ComponentError>
|
|
{
|
|
// Handle actions...
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
// Create orchestrator with single generic
|
|
let mut app: Orchestrator<MyPage> = Orchestrator::new();
|
|
|
|
// Register pages
|
|
app.register(MyPage::Home { counter: 0 });
|
|
app.register(MyPage::Settings { dark_mode: false });
|
|
|
|
// Navigate (associated data is ignored for lookup)
|
|
app.navigate_to(MyPage::Home { counter: 999 }).unwrap();
|
|
```
|
|
|
|
## Capacity Configuration (no_std)
|
|
|
|
In `no_std` mode without `alloc`, configure capacities via const generics:
|
|
|
|
```rust
|
|
// Orchestrator<Page, PAGES, HISTORY, FOCUS, BINDINGS, MODES, EVENTS>
|
|
let mut app: Orchestrator<MyPage, 8, 16, 16, 32, 8, 8> = Orchestrator::new();
|
|
```
|
|
|
|
| Generic | Default | Description |
|
|
|---------|---------|-------------|
|
|
| `PAGES` | 8 | Maximum registered pages |
|
|
| `HISTORY` | 16 | Navigation history depth |
|
|
| `FOCUS` | 16 | Focus targets per page |
|
|
| `BINDINGS` | 32 | Key bindings |
|
|
| `MODES` | 8 | Mode stack depth |
|
|
| `EVENTS` | 8 | Pending event buffer |
|
|
|
|
With `alloc`, these limits don't apply.
|
|
|
|
## API Differences
|
|
|
|
### `process_frame` Return Type
|
|
|
|
```rust
|
|
// With alloc: returns Vec<Event>
|
|
let events: Vec<MyEvent> = app.process_frame(key)?;
|
|
|
|
// Without alloc: returns Option<Event>
|
|
let event: Option<MyEvent> = app.process_frame(key)?;
|
|
```
|
|
|
|
### EventBus
|
|
|
|
```rust
|
|
// With alloc: register handlers via Box<dyn EventHandler>
|
|
app.event_bus_mut().register(Box::new(my_handler));
|
|
|
|
// Without alloc: poll pending events
|
|
for event in app.event_bus_mut().drain() {
|
|
// handle event
|
|
}
|
|
```
|
|
|
|
### Custom Handlers (alloc only)
|
|
|
|
```rust
|
|
#[cfg(feature = "alloc")]
|
|
{
|
|
app.set_action_resolver(MyResolver);
|
|
app.set_command_handler(MyHandler);
|
|
app.set_state_coordinator(MyCoordinator);
|
|
}
|
|
```
|
|
|
|
## License
|
|
|
|
MIT OR Apache-2.0
|