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 theElementtrait, 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., aStaticWidgetorDynWidget) and want to display it.Rsx::draw_parentuses this internally for non-NoRenderRootwidgets.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
Stateor 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_dyncovers 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 theExtensiontrait. -
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 anErrif 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
mainfunction.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 anErron terminal failure. - Behavior:
- Clears the terminal.
- Initializes a new
RenderScopewith the current terminal dimensions. - Iterates through all widgets in
screen.widgets:- If a widget has
NoRenderorNoRenderRootcomponents, it's skipped for direct rendering by the screen (its parent is responsible for rendering it). - Otherwise, it applies the widget's
StyleandTransformto theRenderScope. - Calls
Extension::render_widgetfor each extension. - Calls
Element::renderon the widget's root element. - Draws the
RenderScopeto the terminal. - Calls
Element::after_renderon 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()?;