Version 0.1.1

This commit is contained in:
2025-08-10 14:14:04 -05:00
parent 54b9cba486
commit b4891d4795
39 changed files with 4587 additions and 0 deletions
@@ -0,0 +1,96 @@
# `osui::elements::paginator`
The `Paginator` element is a container that manages a collection of child widgets, displaying only one child at a time. It provides built-in logic to navigate between these "pages" using keyboard events (specifically, `Tab` and `Shift+Tab`).
## `Paginator` Struct
```rust
pub struct Paginator {
children: Vec<Arc<Widget>>, // The list of pages/children
size: (u16, u16), // Internal tracking of the Paginator's calculated size
index: usize, // The index of the currently displayed child
}
```
### Associated Methods
#### `Paginator::new() -> Self`
Creates a new `Paginator` instance with no children and an initial `index` of `0`.
**Example:**
```rust
use osui::prelude::*;
let my_paginator = Paginator::new();
```
### `Element` Trait Implementation
#### `render(&mut self, scope: &mut RenderScope, _: &RenderContext)`
This method primarily focuses on setting the `RenderScope`'s area based on its calculated size. It does not draw any visual elements for the `Paginator` itself, acting as a "ghost" element.
#### `after_render(&mut self, scope: &mut RenderScope, render_context: &RenderContext)`
This is the core rendering logic for `Paginator`:
1. It checks if `self.index` points to a valid child in `self.children`.
2. If a child exists at the current `index`, it prepares a `RenderScope` (cloning its own `RawTransform`).
3. It sets the `RenderScope`'s `parent_size` to its own (Paginator's) determined `width` and `height`, so the child lays out correctly within the Paginator's bounds.
4. It creates a `DivRenderer` helper to manage the child's positioning.
5. It calls `scope.render_widget` for *only the currently active child widget*.
6. After the child is rendered, it restores the original `parent_size` to the `RenderScope`.
7. It updates its internal `self.size` to reflect the size of the currently displayed child (plus any accumulated size from `DivRenderer`).
#### `event(&mut self, event: &dyn Event)`
This method handles keyboard events for navigation:
1. It listens for `crossterm::event::Event::Key` events.
2. If `KeyCode::Tab` is pressed:
* It increments `self.index`. If `self.index` goes beyond the last child, it wraps around to `0`.
3. If `KeyCode::BackTab` (Shift+Tab) is pressed:
* It decrements `self.index`. If `self.index` goes below `0`, it wraps around to the last child.
These index changes will trigger a re-render in the next frame, displaying the new page.
#### `is_ghost(&mut self) -> bool`
Returns `true`. `Paginator` is a "ghost" element because it is a logical container that controls which of its children is visible, but it does not draw itself. Any styling applied to the `Paginator` widget will apply to the area it manages.
#### `draw_child(&mut self, element: &Arc<Widget>)`
This method is called when a widget is declared as a child of this `Paginator` in `rsx!`.
1. It adds the `element` to its internal `children` `Vec`.
2. It injects a `NoRenderRoot` component into the child to ensure the main `Screen` rendering loop doesn't render it directly (the `Paginator` handles rendering the active child).
#### `as_any(&self) -> &dyn std::any::Any` / `as_any_mut(&mut self) -> &mut dyn std::any::Any`
Standard implementations for downcasting.
## Usage in `rsx!`
The direct children of a `Paginator` element become its pages. You can use any other element (e.g., `Div`, `FlexCol`) as a page container.
```rust
use osui::prelude::*;
rsx! {
// Paginator often needs explicit dimensions to define the space for its pages
@Transform::new().dimensions(60, 20).center();
@Style { background: Background::Solid(0x222222) }; // Optional background for the paginator's area
Paginator {
// Page 1: Simple text and instructions
FlexCol {
"Welcome to the first page!"
"Press TAB to go to the next page."
}
// Page 2: Contains an input field
FlexCol {
"This is the second page."
"Type something here:"
@Transform::new().dimensions(30, 1);
@Style { background: Background::Outline(0x555555) };
Input { }
}
// Page 3: A heading
FlexCol {
Heading { "The End" }
"This is the last page. Shift+TAB to go back."
}
}
}
```
`Paginator` is useful for organizing complex UIs into logical sections, preventing clutter, and improving user experience by allowing easy navigation between distinct views.