# `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. ```rust 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) {} /// 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`. ```rust 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;` ## `BoxedComponent` Type alias for a boxed, trait-object Component. `pub type BoxedComponent = Box;` ## `WidgetLoad` A temporary container for a widget during initial construction. It holds the root `BoxedElement` and any associated `BoxedComponent`s. ```rust pub struct WidgetLoad(BoxedElement, HashMap); ``` ### Associated Methods #### `WidgetLoad::new(e: E) -> Self` Creates a new `WidgetLoad` with a given root `Element`. **Arguments:** * `e`: The element to wrap. **Example:** ```rust use osui::prelude::*; let wl = WidgetLoad::new(String::from("Hello")); ``` #### `WidgetLoad::component(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:** ```rust use osui::prelude::*; let wl = WidgetLoad::new(Div::new()).component(Transform::new().dimensions(10, 10)); ``` #### `WidgetLoad::set_component(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:** ```rust 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(&self) -> Option` 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:** ```rust use osui::prelude::*; let wl = WidgetLoad::new(Div::new()).component(Transform::new().x(5)); let transform: Option = 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. ```rust pub struct StaticWidget { element: Mutex, components: Mutex>, focused: Mutex, } ``` ### Associated Methods #### `StaticWidget::new(e: BoxedElement) -> Self` Creates a new `StaticWidget` from a `BoxedElement`. #### `StaticWidget::component(&self, c: C)` Attaches a component. If a component of the same type exists, it's not replaced. #### `StaticWidget::set_component(&self, c: C)` Replaces any existing component of the same type. #### `StaticWidget::get(&self) -> Option` 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. ```rust pub struct DynWidget { element: Mutex, components: Mutex>, load: Mutex WidgetLoad + Send + Sync>>, // The closure that rebuilds the widget dependencies: Mutex>>, // Tracked dependencies injection: Mutex WidgetLoad + Send + Sync>>>, // For runtime modification focused: Mutex, } ``` ### Associated Methods #### `DynWidget::new 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 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 `DynWidget`s. #### `DynWidget::dependency(&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)` Adds a boxed dependency. Similar to `dependency` but takes a `Box`. #### `DynWidget::component(&self, c: C)` Attaches a component. If a component of the same type exists, it's not replaced. #### `DynWidget::set_component(&self, c: C)` Replaces any existing component of the same type. #### `DynWidget::get(&self) -> Option` Retrieves a cloned component of the specified type. ## `Widget` (Enum) A reference-counted wrapper around either a static or dynamic widget. `Arc` is the standard way to store and pass around widgets in the UI tree. ```rust 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 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` 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(self: &Arc, c: C) -> &Arc` 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(self: &Arc, c: C) -> &Arc` Replaces any existing component of the same type with the new component. Returns `self` for chaining. #### `Widget::get(&self) -> Option` Retrieves a cloned component of the specified type from the widget's component map. #### `Widget::inject WidgetLoad + 'static + Send + Sync>(self: &Arc, mut f: F)` Injects a modification closure into a `DynWidget`. For `StaticWidget`s, it applies the modification directly to its components. This allows runtime structural changes to widgets. #### `Widget::refresh(self: &Arc)` Forces a `DynWidget` to rebuild its content. Does nothing for `StaticWidget`s. #### `Widget::auto_refresh(self: &Arc)` Triggers `auto_refresh` on a `DynWidget` (checking and rebuilding if dependencies changed). Does nothing for `StaticWidget`s. #### `Widget::dependency(self: &Arc, d: D) -> &Arc` Adds a dependency to a `DynWidget`. Does nothing for `StaticWidget`s. Returns `self` for chaining. #### `Widget::dependency_box(self: &Arc, d: Box) -> &Arc` Adds a boxed dependency to a `DynWidget`. Does nothing for `StaticWidget`s. Returns `self` for chaining. #### `Widget::event(self: &Arc, e: &E)` Dispatches an event to the widget. If the widget has a `Handler` component, its callback is invoked. If the widget is focused, its underlying `Element::event` method is also called.