Screen
API Reference
The Screen
struct is the central orchestrator of an OSUI application. It manages the UI tree, handles the rendering loop, and coordinates with extensions.
Screen
Struct
pub struct Screen {
pub widgets: Mutex<Vec<Arc<Widget>>>,
// Internal fields for extensions and running state
// extensions: Mutex<Vec<Arc<Mutex<Box<dyn Extension + Send + Sync>>>>>,
// running: Mutex<bool>,
}
widgets
: AMutex
-protected vector holding all top-levelArc<Widget>
instances managed by this screen. These are the root elements of your UI tree.
Screen
Methods
Screen::new()
Creates a new Screen
instance, wrapped in an Arc
for shared ownership.
pub fn new() -> Arc<Self>
-
Returns: An
Arc<Screen>
. -
Usage: The primary way to initialize your OSUI environment.
use osui::prelude::*;
let screen = Screen::new();
Screen::draw<E: Element + 'static + Send + Sync>(self: &Arc<Self>, element: E) -> Arc<Widget>
Draws a static element onto the screen. This creates a new StaticWidget
internally and adds it to the screen's widget list.
pub fn draw<E: Element + 'static + Send + Sync>(self: &Arc<Self>, element: E) -> Arc<Widget>
-
element
: The element to draw. This can be any type that implements theElement
trait, such asString
,Div
,Input
, etc. -
Returns: An
Arc<Widget>
representing the newly created static widget. -
Usage: Ideal for simple, non-reactive elements. Often used as the final step after defining your UI with
rsx!
.use osui::prelude::*;
let screen = Screen::new();
let my_widget = screen.draw(String::from("Hello, OSUI!"));
// Equivalent to: rsx! { "Hello, OSUI!" }.draw(&screen);
Screen::draw_box(self: &Arc<Self>, element: BoxedElement) -> Arc<Widget>
Draws a BoxedElement
(a boxed trait object implementing Element
) as a static widget.
pub fn draw_box(self: &Arc<Self>, element: BoxedElement) -> Arc<Widget>
-
element
: ABox<dyn Element + Send + Sync>
. -
Returns: An
Arc<Widget>
. -
Usage: Useful when you dynamically create a boxed element that you want to add as static content.
use osui::prelude::*;
let screen = Screen::new();
let my_boxed_element: BoxedElement = Box::new(Div::new());
screen.draw_box(my_boxed_element);
Screen::draw_widget(self: &Arc<Self>, widget: Arc<Widget>)
Adds an already existing Arc<Widget>
to the screen's list of top-level widgets.
pub fn draw_widget(self: &Arc<Self>, widget: Arc<Widget>)
-
widget
: TheArc<Widget>
to add. -
Usage: When you've manually constructed an
Arc<Widget>
(e.g., aStaticWidget
orDynWidget
) and want to display it.Rsx::draw_parent
uses this internally for non-NoRenderRoot
widgets.use osui::prelude::*;
let screen = Screen::new();
let my_static_widget = Arc::new(Widget::Static(StaticWidget::new(Box::new(String::from("Manually created widget")))));
screen.draw_widget(my_static_widget);
Screen::draw_dyn<F: FnMut() -> WidgetLoad + 'static + Send + Sync>(self: &Arc<Self>, element: F) -> Arc<Widget>
Draws a dynamic element onto the screen. This element will be re-evaluated when its dependencies change.
pub fn draw_dyn<F: FnMut() -> WidgetLoad + 'static + Send + Sync>(self: &Arc<Self>, element: F) -> Arc<Widget>
-
element
: A closure that returns aWidgetLoad
. This closure encapsulates the logic for creating the widget's initial state and element. -
Returns: An
Arc<Widget>
representing the newly created dynamic widget. -
Usage: For reactive components whose content changes based on
State
or other dynamic factors.use osui::prelude::*;
let screen = Screen::new();
let count = use_state(0);
let my_dyn_widget = screen.draw_dyn({
let count = count.clone();
move || WidgetLoad::new(format!("Count: {}", *count.get()))
});
my_dyn_widget.dependency(count); // Explicitly declare dependency if not using rsx!
Screen::draw_box_dyn(self: &Arc<Self>, element: Box<dyn FnMut() -> WidgetLoad + Send + Sync>) -> Arc<Widget>
Draws a dynamic element from a boxed closure. Similar to draw_dyn
but takes a Box<dyn FnMut() -> WidgetLoad>
.
pub fn draw_box_dyn(self: &Arc<Self>, element: Box<dyn FnMut() -> WidgetLoad + Send + Sync>) -> Arc<Widget>
element
: A boxed closure.- Returns: An
Arc<Widget>
. - Usage: Less common for direct use, as
draw_dyn
covers most cases. Used internally byRsx::create_element
.
Screen::extension<E: Extension + Send + Sync + 'static>(self: &Arc<Self>, ext: E)
Registers an extension with the screen. Extensions receive lifecycle events and can influence rendering.
pub fn extension<E: Extension + Send + Sync + 'static>(self: &Arc<Self>, ext: E)
-
ext
: An instance of a type that implements theExtension
trait. -
Usage: Essential for adding global functionalities like input handling or periodic updates.
use osui::prelude::*;
let screen = Screen::new();
screen.extension(InputExtension); // Enable keyboard input
screen.extension(TickExtension(100)); // Enable 100ms ticks
Screen::run(self: &Arc<Self>) -> std::io::Result<()>
Starts the main rendering loop of the application. This method blocks the current thread until screen.close()
is called.
pub fn run(self: &Arc<Self>) -> std::io::Result<()>
-
Returns:
Ok(())
on successful exit, or anErr
if a terminal operation fails. -
Behavior:
- Calls
init()
on all registered extensions. - Hides the terminal cursor.
- Enters a loop that repeatedly calls
render()
and sleeps for 28ms (approx. 36 FPS). - When the loop exits (due to
close()
being called), it shows the cursor, clears the screen, and callson_close()
on all extensions.
- Calls
-
Usage: The last call in your
main
function.use osui::prelude::*;
let screen = Screen::new();
// ... setup widgets and extensions ...
screen.run()?; // Note the '?' for error propagation
Screen::render(self: &Arc<Self>) -> std::io::Result<()>
Performs a single rendering pass of all widgets on the screen.
pub fn render(self: &Arc<Self>) -> std::io::Result<()>
- Returns:
Ok(())
or anErr
on terminal failure. - Behavior:
- Clears the terminal.
- Initializes a new
RenderScope
with the current terminal dimensions. - Iterates through all widgets in
screen.widgets
:- If a widget has
NoRender
orNoRenderRoot
components, it's skipped for direct rendering by the screen (its parent is responsible for rendering it). - Otherwise, it applies the widget's
Style
andTransform
to theRenderScope
. - Calls
Extension::render_widget
for each extension. - Calls
Element::render
on the widget's root element. - Draws the
RenderScope
to the terminal. - Calls
Element::after_render
on the widget's root element. - Calls
Widget::auto_refresh()
on dynamic widgets to check for state changes.
- If a widget has
- Usage: Primarily called internally by
Screen::run()
. You typically don't need to call this directly unless implementing a custom rendering loop.
Screen::close(self: &Arc<Self>)
Signals the main rendering loop to terminate.
pub fn close(self: &Arc<Self>)
-
Behavior: Sets an internal flag that causes the
Screen::run()
loop to exit on its next iteration. It also performs cleanup: shows the cursor, clears the terminal, and callson_close()
on all registered extensions. -
Usage: Call this from an event handler or other logic to gracefully shut down your application.
use osui::prelude::*;
use crossterm::event::{KeyCode, KeyEvent, Event as CrosstermEvent};
let screen = Screen::new();
screen.extension(InputExtension);
rsx! {
@Handler::new({
let screen = screen.clone();
move |_, e: &CrosstermEvent| {
if let CrosstermEvent::Key(KeyEvent { code: KeyCode::Char('q'), .. }) = e {
screen.close(); // Exit application on 'q'
}
}
});
"Press 'q' to quit"
}.draw(&screen);
screen.run()?;