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
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:
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:
- It checks if
self.indexpoints to a valid child inself.children. - If a child exists at the current
index, it prepares aRenderScope(cloning its ownRawTransform). - It sets the
RenderScope'sparent_sizeto its own (Paginator's) determinedwidthandheight, so the child lays out correctly within the Paginator's bounds. - It creates a
DivRendererhelper to manage the child's positioning. - It calls
scope.render_widgetfor only the currently active child widget. - After the child is rendered, it restores the original
parent_sizeto theRenderScope. - It updates its internal
self.sizeto reflect the size of the currently displayed child (plus any accumulated size fromDivRenderer).
event(&mut self, event: &dyn Event)
This method handles keyboard events for navigation:
- It listens for
crossterm::event::Event::Keyevents. - If
KeyCode::Tabis pressed:- It increments
self.index. Ifself.indexgoes beyond the last child, it wraps around to0.
- It increments
- If
KeyCode::BackTab(Shift+Tab) is pressed:- It decrements
self.index. Ifself.indexgoes below0, it wraps around to the last child. These index changes will trigger a re-render in the next frame, displaying the new page.
- It decrements
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!.
- It adds the
elementto its internalchildrenVec. - It injects a
NoRenderRootcomponent into the child to ensure the mainScreenrendering loop doesn't render it directly (thePaginatorhandles 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.
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.