Layout and Styling System
OSUI employs a two-phase approach to layout and rendering, driven by Transform and RawTransform structures, and provides expressive tools for styling elements using Style.
The Two-Phase Transform Model
OSUI's layout system resolves abstract positioning and sizing rules into concrete pixel coordinates and dimensions. This is managed by two primary structures:
-
Transform(Configured Layout):- This is the high-level struct that developers interact with.
- It defines abstract rules for position (
Positionenum) and dimension (Dimensionenum), along with explicit margins (mx,my) and padding (px,py). Transforminstances are typically attached to widgets as components using theTransformcomponent or via thetransform!macro.- Examples:
Position::Center,Dimension::Full,Position::Const(10).
// Example Transform definition
component!(Transform {
pub x: Position,
pub y: Position,
pub mx: i32,
pub my: i32,
pub px: u16,
pub py: u16,
pub width: Dimension,
pub height: Dimension,
});- Methods like
center(),bottom(),right(),margin(),padding(), anddimensions()provide a fluent API for configuration.
-
RawTransform(Resolved Layout):- This struct holds the concrete, absolute
u16values forx,y,width,height,px, andpyafter layout calculations have occurred. - It represents the final calculated bounds and offsets for a widget on the virtual screen.
- Developers generally don't manipulate
RawTransformdirectly; it's used internally by theRenderScopeduring the rendering phase.
// Example RawTransform definition
#[derive(Debug, Clone)]
pub struct RawTransform {
pub x: u16,
pub y: u16,
pub width: u16,
pub height: u16,
pub px: u16,
pub py: u16,
} - This struct holds the concrete, absolute
How Resolution Works (use_dimensions, use_position)
When a widget is rendered, its Transform component is used by the RenderScope to resolve its abstract rules into a concrete RawTransform.
-
Transform::use_dimensions(parent_width, parent_height, raw_transform):- This method takes the
parent_widthandparent_height(the available space from the parent container) and updates theraw_transform.widthandraw_transform.heightbased on theDimensionrules. Dimension::Fullwill set the raw dimension to the parent's available size.Dimension::Const(n)will set it ton.Dimension::Contentmeans the dimension will be determined by the content drawn by the element itself (e.g., text length or explicituse_areacalls).
- This method takes the
-
Transform::use_position(parent_width, parent_height, raw_transform):- This method uses the widget's resolved
raw_transform.widthandraw_transform.height(afteruse_dimensions) along withparent_widthandparent_heightto determine the absoluteraw_transform.xandraw_transform.y. Position::Const(n)sets the coordinate ton.Position::Centercalculates the coordinate to center the widget within the parent.Position::Endcalculates the coordinate to align the widget to the end (right/bottom) of the parent.- Margins (
mx,my) are applied as offsets after the base position is calculated.
- This method uses the widget's resolved
This separation allows for a clear definition of layout rules at design time (Transform) and their efficient resolution into precise screen coordinates at runtime (RawTransform).
Styling with Style
The Style component defines the visual appearance of a widget. It primarily controls background and foreground colors.
component!(Style {
pub background: Background,
pub foreground: Option<u32>,
});
pub enum Background {
NoBackground,
Outline(u32),
RoundedOutline(u32),
Solid(u32),
}
background: Defines how the widget's background is rendered.NoBackground: The widget's area is transparent.Outline(color): Draws a simple rectangular outline using the specified 24-bit RGB color.RoundedOutline(color): Draws a rounded rectangular outline.Solid(color): Fills the entire widget area with the specified 24-bit RGB color.
foreground: AnOption<u32>representing the 24-bit RGB color for any text drawn within the widget. IfNone, default terminal foreground color is used.
Usage:
use osui::prelude::*;
// Example: A div with blue background and white text
rsx! {
@Transform::new().dimensions(20, 5).padding(1,1);
@Style { background: Background::Solid(0x0000FF), foreground: Some(0xFFFFFF) };
Div {
"This is a blue box with white text."
}
}
By combining Transform and Style components, developers have precise control over the visual presentation and spatial arrangement of UI elements.