Macros
OSUI provides several declarative macros to simplify common tasks like defining custom events, components, Transform
s, and UI trees.
event!
Macro
Declares a struct that implements the Event
trait, simplifying event type creation for OSUI's reactive system.
Variants
event!(Name)
: Defines a unit struct namedName
.event!(Name { ... })
: Defines a named struct with fields.event!(Name (...))
: Defines a tuple struct.
Usage
use osui::macros::event; // Import the macro
// Unit struct event
event!(Clicked);
// Named struct event with fields
event!(Resized { width: u32, height: u32 });
// Tuple struct event
event!(Moved(u32, u32));
// Example usage
fn main() {
let click_event = Clicked;
let resize_event = Resized { width: 80, height: 24 };
let move_event = Moved(10, 20);
// Events can be dispatched and handled
// (requires an OSUI screen and event context)
}
component!
Macro
Declares a struct that implements the Component
trait, reducing boilerplate when defining new data or behavior extensions for widgets.
Variants
component!(Name)
: Defines a unit struct.component!(Name { ... })
: Defines a named struct with fields.component!(Name (...))
: Defines a tuple struct.
Usage
use osui::macros::component; // Import the macro
// Unit struct component (e.g., a marker for a property)
component!(Focusable);
// Named struct component (e.g., a tooltip message)
component!(Tooltip { text: String });
// Tuple struct component (e.g., a fixed size)
component!(Size(u32, u32));
// Example usage (assuming a widget instance `my_widget`)
// my_widget.component(Focusable);
// my_widget.component(Tooltip { text: "Hello".to_string() });
// my_widget.component(Size(100, 50));
event_handler!
Macro
Creates an event handler closure that safely calls a method on a self
instance. This is particularly useful when you need to register a 'static
event handler that interacts with the current object, often requiring unsafe raw pointers.
Arguments
$self_ty
: The type ofself
(e.g.,Self
or a specific struct name).$self
: The instance variable (usuallyself
) being used.$events
: The event source object, which must have an.on
method (e.g., anEventHandler
wrapper that allows registering closures). This part is not shown in the source, but it implies such an interface.$method
: The method on$self
to call when an event is received.
Safety
This macro uses unsafe
code to cast self
to a raw pointer and dereference it. It is the developer's responsibility to ensure that the self
reference remains valid for the entire lifetime of the generated closure. Incorrect use can lead to use-after-free or other memory safety issues. Use with extreme caution and only when necessary for 'static
lifetimes.
Usage (Conceptual Example)
use osui::prelude::*; // Assuming event_handler! is in prelude or imported
struct MyComponent {
// ... fields
}
impl MyComponent {
// A method to be called by the event handler
fn handle_click(&mut self, _widget: &Arc<Widget>, _event: &Clicked) {
println!("MyComponent was clicked!");
}
fn setup_event_listener(self: &Arc<Self>, some_event_source: &Arc<Widget>) {
// You'd attach a Handler component to `some_event_source`
// which then triggers `self.handle_click`
some_event_source.set_component(Handler::new({
// This is a conceptual expansion of what event_handler! might do
let self_ref = Arc::downgrade(self); // Weak reference for safety
move |widget_arc, event: &Clicked| {
if let Some(strong_self) = self_ref.upgrade() {
// Safe dereference if the component still exists
let mut_self = Arc::get_mut(&mut strong_self).unwrap(); // Requires Arc to be unique
mut_self.handle_click(widget_arc, event);
}
}
}));
}
}
Note: The provided event_handler!
macro in the source code directly converts self
to a raw pointer. The example above shows a safer, Arc
-based approach that's more common in modern Rust GUI frameworks for 'static
closures where the lifetime of self
is not guaranteed. OSUI's Handler
component itself simplifies common patterns, often making direct use of event_handler!
macro unnecessary unless you are working with bare &mut self
on objects whose lifetime is strictly controlled.
transform!
Macro
A convenient macro for constructing a Transform
component with specified properties. It simplifies the setup compared to using Transform::new()
followed by multiple fluent method calls.
Arguments
Takes comma-separated key-value pairs where the key is a public field of Transform
and the value is an expression that can be converted into the field's type (e.g., u16
for Position::Const
, Dimension::Const
).
Usage
use osui::prelude::*; // Imports Transform, Position, Dimension
rsx! {
// Sets x: Const(10), y: Center, width: Full, height: Const(5), px: 1
@transform!(x: 10, y: Center, width: Full, height: 5, px: 1);
Div { "Transformed Div" }
// Minimal transform, only setting width
@transform!(width: 20);
Div { "Width 20" }
}
This macro makes it very concise to apply layout rules directly within your rsx!
syntax.
rsx!
Macro
The primary macro for declaratively defining your OSUI user interface. It provides a JSX-like syntax for nesting elements, attaching components, and specifying dependencies.
Arguments
Takes a sequence of UI elements, potentially nested within curly braces {}
.
Features
- Text Literals: Direct strings (e.g.,
"Hello"
) become text elements. - Element Tags: Element struct names (e.g.,
Div
,Input
) followed by properties and children. - Properties:
field: value
pairs set element properties (e.g.,Heading, smooth: true,
). - Children: Elements nested within
{}
are children of the parent. - Dependencies:
%variable_name
registersvariable_name
(must implementDependencyHandler
) as a dependency for a dynamic widget. - Components:
@ComponentType
or@ComponentType::new(args)
attaches a component to the element. - Static Elements:
static ElementType { ... }
creates aStaticWidget
(no reactivity overhead). - Expansion:
$another_macro => (args)
allows embedding UI generated by other macros/functions.
Usage
use osui::prelude::*;
let my_state_var = use_state("Initial".to_string());
rsx! {
// Simple text
"Welcome to OSUI!"
// Static Div with styling
@Transform::new().dimensions(20, 5);
@Style { background: Background::Solid(0x333333), foreground: Some(0xFFFFFF) };
static Div { "This is a static box." }
// Dynamic Div reacting to `my_state_var`
%my_state_var
Div {
format!("Current state: {}", my_state_var.get())
}
// FlexRow with Heading and Input
FlexRow, gap: 2, {
Heading { "User Input" }
@Transform::new().dimensions(30, 1);
@Style { background: Background::Outline(0xAAAAAA) };
@Focused;
Input { }
}
}
rsx_inner!
Macro
An internal, recursive macro used by rsx!
to parse and build the UI tree. This macro is not intended for direct use by developers. Its definition shows the complex pattern matching used to process the various rsx!
syntax forms.