Large structural changes
This commit is contained in:
+170
-123
@@ -1,175 +1,222 @@
|
||||
#[macro_export]
|
||||
macro_rules! __rsx {
|
||||
() => {
|
||||
(String::new(), Vec::new())
|
||||
};
|
||||
//! # Macros Module
|
||||
//!
|
||||
//! This module defines various macros for creating and manipulating OSUI elements.
|
||||
//! The macros provide a clean and concise syntax for defining UI components and
|
||||
//! handling their parameters, commands, and rendering.
|
||||
|
||||
($p:expr;) => {{
|
||||
(String::new(), vec![$p as Box<dyn osui::Element>])
|
||||
}};
|
||||
($p:expr; $($rest:tt)+) => {{
|
||||
let mut comps: Vec<Box<dyn osui::Element>> = osui::__rsx!($($rest)+).1;
|
||||
comps.insert(0, $p as Box<dyn osui::Element>);
|
||||
(String::new(), comps)
|
||||
}};
|
||||
// Props, With components (PC)
|
||||
($tag:path { $($inner:tt)* }) => {{
|
||||
(String::new(), vec![rsx!($tag {$($inner)*})])
|
||||
}};
|
||||
|
||||
($tag:path { $($inner:tt)* } $($rest:tt)+) => {{
|
||||
let mut comps: Vec<Box<dyn osui::Element>> = osui::__rsx!($($rest)+).1;
|
||||
comps.insert(0, rsx!($tag {$($inner)*}) );
|
||||
(String::new(), comps)
|
||||
}};
|
||||
|
||||
($tag:path { $($inner:tt)* }) => {{
|
||||
(String::new(), vec![rsx!($tag {$($inner)*})])
|
||||
}};
|
||||
|
||||
($tag:path { $($inner:tt)* } $($rest:tt)+) => {{
|
||||
let mut comps: Vec<Box<dyn osui::Element>> = osui::__rsx!($($rest)+).1;
|
||||
comps.insert(0, rsx!($tag {$($inner)*}) );
|
||||
(String::new(), comps)
|
||||
}};
|
||||
|
||||
($text:expr) => {{
|
||||
(format!($text), Vec::new())
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
/// Write OSUI Markup Language directly with rust.
|
||||
macro_rules! rsx {
|
||||
( $tag:path { $($k:ident: $v:expr),*; $($inner:tt)* } ) => {{
|
||||
let mut c = $tag();
|
||||
let a = osui::__rsx!($($inner)*);
|
||||
c.text = a.0;
|
||||
c.children = a.1;
|
||||
$(
|
||||
c.$k = $v;
|
||||
)*
|
||||
c as Box<dyn osui::Element>
|
||||
}};
|
||||
|
||||
( $tag:path { $($k:ident: $v:expr),* } ) => {{
|
||||
let mut c = $tag();
|
||||
$(
|
||||
c.$k = $v;
|
||||
)*
|
||||
c as Box<dyn osui::Element>
|
||||
}};
|
||||
|
||||
( $tag:path { $($inner:tt)* } ) => {{
|
||||
let mut c = $tag();
|
||||
let a = osui::__rsx!($($inner)*);
|
||||
c.text = a.0;
|
||||
c.children = a.1;
|
||||
c as Box<dyn osui::Element>
|
||||
}};
|
||||
|
||||
( $p:expr; ) => {{
|
||||
$p as Box<dyn osui::Element>
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
///```create_frame!(width, height)```
|
||||
/// Macro for defining an OSUI `Element`.
|
||||
///
|
||||
/// Create a frame for rendering multiple components
|
||||
macro_rules! create_frame {
|
||||
($width:expr, $height:expr) => {
|
||||
vec![" ".repeat($width); $height]
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
///```component!{
|
||||
/// This macro generates a new element type with specified parameters and default values.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// element! {
|
||||
/// MyElem {}
|
||||
/// defaults {}
|
||||
/// }```
|
||||
/// // functions (render, update)
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Create a frame for rendering multiple components
|
||||
/// # Parameters
|
||||
/// - `name`: The name of the element type being defined.
|
||||
/// - `inner`: Additional fields or methods for the element.
|
||||
/// - `defaults`: Default values for the element's properties.
|
||||
/// - `functions`: Functions to implement for the element (e.g., rendering, updating).
|
||||
#[macro_export]
|
||||
macro_rules! element {
|
||||
(
|
||||
$(#[$meta:meta])*
|
||||
$name:ident {
|
||||
$( $inner:tt )*
|
||||
}
|
||||
defaults {$( $defaults:tt )*}
|
||||
$( $functions:tt )*
|
||||
) => {
|
||||
#[derive(Debug)]
|
||||
$(#[$meta])*
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct $name {
|
||||
pub x: usize,
|
||||
pub y: usize,
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
pub width: ElementSize,
|
||||
pub height: ElementSize,
|
||||
pub children: Vec<Box<dyn Element>>,
|
||||
pub child: usize,
|
||||
pub text: String,
|
||||
pub style: Style,
|
||||
pub tick_line: std::collections::HashMap<usize, String>,
|
||||
$( $inner )*
|
||||
}
|
||||
|
||||
impl Element for $name {
|
||||
fn get_child(&mut self) -> Option<&mut Box<dyn Element>> {
|
||||
self.children.get_mut(self.child)
|
||||
}
|
||||
fn get_data(&self) -> ElementData {
|
||||
ElementData {
|
||||
x: self.x,
|
||||
y: self.y,
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
style: self.style.clone(),
|
||||
width: self.width.clone(),
|
||||
height: self.height.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_data(&mut self, data: ElementData) {
|
||||
self.x = data.x;
|
||||
self.y = data.y;
|
||||
self.width = data.width;
|
||||
self.height = data.height;
|
||||
self.style = data.style;
|
||||
}
|
||||
|
||||
fn clear_ticks(&mut self) {
|
||||
self.tick_line.clear();
|
||||
fn update_data(&mut self, width: usize, height: usize) {
|
||||
self.width.try_set_size(width);
|
||||
self.height.try_set_size(height);
|
||||
for child in &mut self.children {
|
||||
child.update_data(width, height);
|
||||
}
|
||||
}
|
||||
$( $functions )*
|
||||
}
|
||||
|
||||
impl $name {
|
||||
/// Creates a new instance of the element with default values.
|
||||
pub fn new() -> $name {
|
||||
$name {
|
||||
children: Vec::new(),
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
width: ElementSize::Default(0),
|
||||
height: ElementSize::Default(0),
|
||||
child: 0,
|
||||
text: String::new(),
|
||||
style: Style::default(),
|
||||
tick_line: std::collections::HashMap::new(),
|
||||
$( $defaults )*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_action(&self, tick: usize) -> String {
|
||||
match self.tick_line.get(&tick) {
|
||||
Some(action) => action.clone(),
|
||||
None => String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_action(&mut self, tick: usize, action: &str) {
|
||||
if tick > 99 {
|
||||
self.tick_line.insert(tick-100, action.to_string());
|
||||
} else {
|
||||
self.tick_line.insert(tick, action.to_string());
|
||||
}
|
||||
/// Retrieves a mutable reference to the current child element, if any.
|
||||
///
|
||||
/// # Returns
|
||||
/// An `Option` containing a mutable reference to the child `Element` or `None`.
|
||||
pub fn get_child(&mut self) -> Option<&mut Box<dyn Element>> {
|
||||
self.children.get_mut(self.child)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Macro for creating a command response from a list of commands.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// command!(Update(1), Render(2));
|
||||
/// ```
|
||||
///
|
||||
/// # Parameters
|
||||
/// - A list of commands to be included in the `UpdateResponse::CommandList`.
|
||||
#[macro_export]
|
||||
macro_rules! command {
|
||||
($($cmd:expr),*) => {
|
||||
UpdateResponse::CommandList(vec![$($cmd),*])
|
||||
};
|
||||
}
|
||||
|
||||
/// Macro for parsing parameters and children for an OSUI element.
|
||||
///
|
||||
/// This macro updates the properties of an element based on provided key-value pairs,
|
||||
/// and adds child elements to the parent element.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `elem`: The element being updated.
|
||||
/// - Various key-value pairs, child elements, and text content.
|
||||
#[macro_export]
|
||||
macro_rules! parse_rsx_param {
|
||||
($elem:expr, ) => {};
|
||||
|
||||
($elem:expr, $($k:ident: $v:expr),*) => {
|
||||
$(
|
||||
$elem.$k = $v;
|
||||
)*
|
||||
};
|
||||
|
||||
($elem:expr, $($k:ident: $v:expr),*; $($rest:tt)*) => {
|
||||
$(
|
||||
$elem.$k = $v;
|
||||
)*
|
||||
osui::parse_rsx_param!($elem, $($rest)*);
|
||||
};
|
||||
|
||||
($elem:expr, {$ielem:expr} $($rest:tt)*) => {
|
||||
$elem.children.push($ielem);
|
||||
osui::parse_rsx_param!($elem, $($rest)*);
|
||||
};
|
||||
|
||||
($elem:expr, $($k:ident: $v:expr),*, $text:expr) => {
|
||||
$(
|
||||
$elem.$k = $v;
|
||||
)*
|
||||
$elem.text = format!($text);
|
||||
};
|
||||
|
||||
($elem:expr, $pelem:path { $($inner:tt)* } $($rest:tt)*) => {
|
||||
$elem.children.push(osui::rsx_elem!($pelem { $($inner)* }));
|
||||
osui::parse_rsx_param!($elem, $($rest)*)
|
||||
};
|
||||
|
||||
($elem:expr, $text:expr) => {
|
||||
$elem.text = format!($text);
|
||||
};
|
||||
}
|
||||
|
||||
/// Macro for creating an OSUI element with parsed parameters.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// rsx! {
|
||||
/// text { "Hello, World!" }
|
||||
/// div {
|
||||
/// button { y: 2, "click me" }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This macro provides a clean way to express OSUI elements, functioning like a div that can
|
||||
/// contain multiple components.
|
||||
#[macro_export]
|
||||
macro_rules! rsx_elem {
|
||||
($elem:path { $($inner:tt)* }) => {{
|
||||
let mut elem = $elem();
|
||||
osui::parse_rsx_param!(elem, $($inner)*);
|
||||
elem as Box<dyn osui::Element>
|
||||
}};
|
||||
}
|
||||
|
||||
/// Macro for defining a structured representation of UI elements in OSUI.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// rsx! {
|
||||
/// text { "Hello, World!" }
|
||||
/// div {
|
||||
/// button { y: 2, "click me" }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This macro allows the creation of a root element that can contain other elements.
|
||||
#[macro_export]
|
||||
macro_rules! rsx {
|
||||
($($inner:tt)*) => {{
|
||||
osui::rsx_elem!( osui::ui::div { $($inner)* } )
|
||||
}};
|
||||
}
|
||||
|
||||
/// Macro for defining CSS styles in OSUI.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// css!(Style; color: "red"; background: "white");
|
||||
/// ```
|
||||
///
|
||||
/// This macro creates a new style based on the provided properties, applying default values
|
||||
/// for any unspecified fields.
|
||||
#[macro_export]
|
||||
macro_rules! css {
|
||||
(
|
||||
$style:path;
|
||||
$($inner:tt)*
|
||||
) => {{
|
||||
$style {
|
||||
$($inner)*
|
||||
..Default::default()
|
||||
}
|
||||
}};
|
||||
}
|
||||
Reference in New Issue
Block a user