Skip to main content
Version: 0.1.1

osui::widget

The widget module defines the fundamental traits and types that constitute OSUI's widget system. It provides the building blocks (Element, Component) and the containers (Widget, StaticWidget, DynWidget) necessary to create and manage the UI tree.

Element Trait

The core trait for anything that can be rendered in the UI. Elements are responsible for their own rendering logic and can define hooks for lifecycle events and child rendering.

pub trait Element: Send + Sync {
/// Called to perform rendering for the element. Elements draw their own content here.
#[allow(unused)]
fn render(
&mut self,
scope: &mut RenderScope,
render_context: &crate::render_scope::RenderContext,
) {}

/// Called after rendering, for follow-up logic or cleanup.
/// Container elements typically trigger rendering of their children here.
#[allow(unused)]
fn after_render(
&mut self,
scope: &mut RenderScope,
render_context: &crate::render_scope::RenderContext,
) {}

/// Called by a parent widget to add a child to this element.
#[allow(unused)]
fn draw_child(&mut self, element: &Arc<Widget>) {}

/// Called to handle events for this element.
#[allow(unused)]
fn event(&mut self, event: &dyn Event) {}

/// Returns `true` if this element is a "ghost" element.
/// Ghost elements primarily serve as layout or logical containers and do not draw themselves.
fn is_ghost(&mut self) -> bool { false }

/// Returns a type-erased reference to this object for downcasting.
fn as_any(&self) -> &dyn Any;

/// Returns a mutable type-erased reference to this object for downcasting.
fn as_any_mut(&mut self) -> &mut dyn Any;
}

Component Trait

An optional trait for state or metadata attached to widgets. Components are dynamic extensions to a widget's behavior or data, stored in a HashMap by TypeId.

pub trait Component: Send + Sync {
/// Returns a type-erased reference to this object for downcasting.
fn as_any(&self) -> &dyn Any;
/// Returns a mutable type-erased reference to this object for downcasting.
fn as_any_mut(&mut self) -> &mut dyn Any;
}

BoxedElement

Type alias for a boxed, trait-object Element. pub type BoxedElement = Box<dyn Element + Send + Sync>;

BoxedComponent

Type alias for a boxed, trait-object Component. pub type BoxedComponent = Box<dyn Component + Send + Sync>;

WidgetLoad

A temporary container for a widget during initial construction. It holds the root BoxedElement and any associated BoxedComponents.

pub struct WidgetLoad(BoxedElement, HashMap<TypeId, BoxedComponent>);

Associated Methods

WidgetLoad::new<E: Element + 'static>(e: E) -> Self

Creates a new WidgetLoad with a given root Element.

Arguments:

  • e: The element to wrap.

Example:

use osui::prelude::*;
let wl = WidgetLoad::new(String::from("Hello"));

WidgetLoad::component<C: Component + 'static>(mut self, c: C) -> Self

Attaches a component to the WidgetLoad. If a component of the same type already exists, it is not replaced. Use set_component for replacement.

Arguments:

  • c: The component to attach.

Returns: self, for chaining.

Example:

use osui::prelude::*;
let wl = WidgetLoad::new(Div::new()).component(Transform::new().dimensions(10, 10));

WidgetLoad::set_component<C: Component + 'static>(mut self, c: C) -> Self

Replaces any existing component of the same type with the new component.

Arguments:

  • c: The component to set.

Returns: self, for chaining.

Example:

use osui::prelude::*;
let wl = WidgetLoad::new(Div::new())
.component(Transform::new().x(5)) // Adds first transform
.set_component(Transform::new().x(10)); // Replaces with new transform

WidgetLoad::get<C: Component + 'static + Clone>(&self) -> Option<C>

Attempts to retrieve a component of the given type from the WidgetLoad. Requires the component to be Clone.

Returns: Some(C) if found, None otherwise.

Example:

use osui::prelude::*;
let wl = WidgetLoad::new(Div::new()).component(Transform::new().x(5));
let transform: Option<Transform> = wl.get(); // transform will be Some(Transform { x: Const(5), ... })

StaticWidget

A widget with fixed content and no dynamic behavior. It holds a Mutex wrapped BoxedElement and a Mutex wrapped HashMap of components.

pub struct StaticWidget {
element: Mutex<BoxedElement>,
components: Mutex<HashMap<TypeId, BoxedComponent>>,
focused: Mutex<bool>,
}

Associated Methods

StaticWidget::new(e: BoxedElement) -> Self

Creates a new StaticWidget from a BoxedElement.

StaticWidget::component<C: Component + 'static>(&self, c: C)

Attaches a component. If a component of the same type exists, it's not replaced.

StaticWidget::set_component<C: Component + 'static>(&self, c: C)

Replaces any existing component of the same type.

StaticWidget::get<C: Component + 'static + Clone>(&self) -> Option<C>

Retrieves a cloned component of the specified type.

DynWidget

A widget with dynamic content and dependency tracking. It can be rebuilt using a provided FnMut() function when dependencies change, enabling reactive updates.

pub struct DynWidget {
element: Mutex<BoxedElement>,
components: Mutex<HashMap<TypeId, BoxedComponent>>,
load: Mutex<Box<dyn FnMut() -> WidgetLoad + Send + Sync>>, // The closure that rebuilds the widget
dependencies: Mutex<Vec<Box<dyn DependencyHandler>>>, // Tracked dependencies
injection: Mutex<Option<Box<dyn FnMut(WidgetLoad) -> WidgetLoad + Send + Sync>>>, // For runtime modification
focused: Mutex<bool>,
}

Associated Methods

DynWidget::new<F: FnMut() -> WidgetLoad + 'static + Send + Sync>(mut e: F) -> Self

Creates a new DynWidget from a closure that returns a WidgetLoad. The closure is immediately executed once to initialize the widget's content.

DynWidget::inject<F: FnMut(WidgetLoad) -> WidgetLoad + 'static + Send + Sync>(&self, f: F)

Replaces or modifies the widget's structure on subsequent reloads and initializations. The provided closure takes the WidgetLoad generated by the load closure and returns a modified WidgetLoad. This is useful for dynamically adding components or wrapping elements. It triggers an immediate refresh().

DynWidget::refresh(&self)

Forces the widget to rebuild its content by re-evaluating the original load function. If an injection closure is present, it's applied after the load function. This method updates the internal element and components.

DynWidget::auto_refresh(&self)

Checks if any registered dependencies have changed (via DependencyHandler::check()). If so, it calls self.refresh(). This method is called automatically by the Screen in its rendering loop for DynWidgets.

DynWidget::dependency<D: DependencyHandler + 'static>(&self, d: D)

Adds a dependency to this widget. When d signals a change, the widget will auto_refresh(). The add() method of the DependencyHandler is called.

DynWidget::dependency_box(&self, d: Box<dyn DependencyHandler>)

Adds a boxed dependency. Similar to dependency but takes a Box<dyn DependencyHandler>.

DynWidget::component<C: Component + 'static>(&self, c: C)

Attaches a component. If a component of the same type exists, it's not replaced.

DynWidget::set_component<C: Component + 'static>(&self, c: C)

Replaces any existing component of the same type.

DynWidget::get<C: Component + 'static + Clone>(&self) -> Option<C>

Retrieves a cloned component of the specified type.

Widget (Enum)

A reference-counted wrapper around either a static or dynamic widget. Arc<Widget> is the standard way to store and pass around widgets in the UI tree.

pub enum Widget {
Static(StaticWidget),
Dynamic(DynWidget),
}

Associated Methods

Widget::new_static(e: BoxedElement) -> Self

Creates a new Widget::Static from a BoxedElement.

Widget::new_dyn<F: FnMut() -> WidgetLoad + 'static + Send + Sync>(e: F) -> Self

Creates a new Widget::Dynamic from a closure that returns a WidgetLoad.

Widget::is_focused(&self) -> bool

Returns true if the widget currently has focus. Focus is managed by extensions like RelativeFocusExtension.

Widget::is_ghost(&self) -> bool

Delegates to the underlying Element::is_ghost(). Returns true if the element is primarily a layout container.

Widget::set_focused(&self, f: bool)

Sets the focus status of the widget. This method is usually called by focus management extensions.

Widget::get_elem(&self) -> MutexGuard<BoxedElement>

Provides a MutexGuard for mutable access to the underlying BoxedElement. Use with caution to avoid deadlocks.

Widget::after_render(&self)

Internal: Calls after_render hooks for the underlying element and extensions.

Widget::component<C: Component + 'static>(self: &Arc<Self>, c: C) -> &Arc<Self>

Attaches a component to the widget. If a component of the same type already exists, it is not replaced. Returns self for chaining.

Widget::set_component<C: Component + 'static>(self: &Arc<Self>, c: C) -> &Arc<Self>

Replaces any existing component of the same type with the new component. Returns self for chaining.

Widget::get<C: Component + 'static + Clone>(&self) -> Option<C>

Retrieves a cloned component of the specified type from the widget's component map.

Widget::inject<F: FnMut(WidgetLoad) -> WidgetLoad + 'static + Send + Sync>(self: &Arc<Self>, mut f: F)

Injects a modification closure into a DynWidget. For StaticWidgets, it applies the modification directly to its components. This allows runtime structural changes to widgets.

Widget::refresh(self: &Arc<Self>)

Forces a DynWidget to rebuild its content. Does nothing for StaticWidgets.

Widget::auto_refresh(self: &Arc<Self>)

Triggers auto_refresh on a DynWidget (checking and rebuilding if dependencies changed). Does nothing for StaticWidgets.

Widget::dependency<D: DependencyHandler + 'static>(self: &Arc<Self>, d: D) -> &Arc<Self>

Adds a dependency to a DynWidget. Does nothing for StaticWidgets. Returns self for chaining.

Widget::dependency_box(self: &Arc<Self>, d: Box<dyn DependencyHandler>) -> &Arc<Self>

Adds a boxed dependency to a DynWidget. Does nothing for StaticWidgets. Returns self for chaining.

Widget::event<E: Event + Clone + 'static>(self: &Arc<Self>, e: &E)

Dispatches an event to the widget. If the widget has a Handler<E> component, its callback is invoked. If the widget is focused, its underlying Element::event method is also called.