From 48232880269e81928fe840895dd90bd3cbbb56a0 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Mon, 23 Dec 2024 13:58:49 +0100 Subject: [PATCH] Added component --- Cargo.toml | 2 +- src/examples.rs | 30 ++++++++++++++------ src/lib.rs | 30 +++++++++++++++++--- src/macros.rs | 12 ++++---- src/main.rs | 5 ++-- src/rsx.rs | 38 ++++++++----------------- src/ui/mod.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++---- 7 files changed, 136 insertions(+), 54 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 504e10c..c6bc165 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,4 +26,4 @@ lazy_static = "1.4" paste = "1.0.15" dyn-clone = "1.0.17" flume = "=0.10.12" -osui-element = "0.1.14" +osui-element = "0.1.23" diff --git a/src/examples.rs b/src/examples.rs index 4b129b0..15d5989 100644 --- a/src/examples.rs +++ b/src/examples.rs @@ -1,7 +1,8 @@ pub mod counter_example { use crate::prelude::*; - pub fn app() -> Element { + #[component] + pub fn App() -> Element { let count = State::new(0); rsx! { @@ -31,7 +32,9 @@ pub mod counter_example { pub mod todo_example { use crate::prelude::*; - pub fn app() -> Element { + + #[component] + pub fn App() -> Element { let todo = vec!["Todo", "Hovering", "Completed", "Foo", "Bar"]; rsx! { @@ -83,7 +86,8 @@ pub mod todo_example { pub mod login_example { use crate::prelude::*; - pub fn app() -> Element { + #[component] + pub fn App() -> Element { rsx! { @SetStyle(styling()) @@ -91,13 +95,21 @@ pub mod login_example { let root = document.get_root::
(); root.children.set_index(1); }, "username: " } - input { class: "input", id: "psw", on_click: fn(psw: &mut Input, _, document) { - if let Some(usr) = document.get_element_by_id::("usr") { - document.draw(rsx! { - text { static "Username: {}\nPassword: {}", usr.text, psw.text } - }); - } + + input { class: "input", id: "psw", on_click: fn(_, _, document) { + let root = document.get_root::
(); + root.children.set_index(2); }, "password: " } + + button { class: "input", on_click: fn(_, _, document) { + if let Some(usr) = document.get_element_by_id::("usr") { + if let Some(psw) = document.get_element_by_id::("psw") { + document.draw(rsx! { + text { static "Username: {}\nPassword: {}", usr.text, psw.text } + }); + } + } + }, "Submit" } } } diff --git a/src/lib.rs b/src/lib.rs index d131c3a..ae30531 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,10 +9,26 @@ //! //! ```rust //! use osui::prelude::*; +//! +//! #[component] +//! pub fn App() -> Element { +//! let count = State::new(0); //! -//! launch(rsx! { -//! text { "Hello, World!" } -//! }); +//! rsx! { +//! button { +//! class: "btn", +//! +//! on_click: fn(_, _, _) @count { +//! count += 1; +//! }, +//! +//! "The current count is: {count}" +//! } +//! } +//! } +//! fn main() { +//! launch!(App); +//! } //! ``` //! //! ## Modules @@ -42,9 +58,10 @@ pub mod prelude { pub use crate::ui::Instruction::*; pub use crate::ui::Number::{Auto, Center}; pub use crate::{self as osui, css, ersx, launch, rsx, ui::*, Handler}; - pub use crate::{style, Document, State}; + pub use crate::{style, Component, Document, State}; pub use crate::{Children, Element, ElementCore, ElementWidget}; pub use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind}; + pub use osui_element::component; pub fn sleep(ms: u64) { std::thread::sleep(std::time::Duration::from_millis(ms)); } @@ -77,6 +94,11 @@ pub trait ElementWidget: ElementCore + std::fmt::Debug { } } +pub trait Component: std::fmt::Debug { + type Element; + fn create_element(self) -> Self::Element; +} + ////////////////////////////////////////////////////////////////////////////////////////////////// /// Structs ////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/macros.rs b/src/macros.rs index 0984680..da8547f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,18 +1,18 @@ #[macro_export] macro_rules! launch { - ($expr:expr) => { - let mut element = $expr; + ($elem:path) => { + let mut element = <$elem>::default().create_element(); let mut document = $crate::Document::with_elem(&mut element); while document.run() { - element = $expr; + element = <$elem>::default().create_element(); } }; - ($expr:expr, $css:expr) => { - let mut element = $expr; + ($elem:path, $css:expr) => { + let mut element = <$elem>::default().create_element(); let mut document = $crate::Document::with_elem(&mut element); document.set_css($css); while document.run() { - element = $expr; + element = <$elem>::default().create_element(); } }; } diff --git a/src/main.rs b/src/main.rs index 87b503d..8e0f9c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,4 @@ -use osui::{examples::*, launch}; - +use osui::{examples::login_example::App, prelude::*}; fn main() { - launch!(login_example::app()); + launch!(App); } diff --git a/src/rsx.rs b/src/rsx.rs index 18a0b9f..6ad8eda 100644 --- a/src/rsx.rs +++ b/src/rsx.rs @@ -17,12 +17,8 @@ macro_rules! parse_rsx_param { osui::parse_rsx_param!($elem, $($rest)*); }; - ($elem:expr, static $text:expr) => { - $elem.children.set_static_force(format!($text)) - }; - - ($elem:expr, static $text:expr, $($inner:tt)*) => { - $elem.children.set_static_force(format!($text, $($inner)*)) + ($elem:expr, static $text:literal $($other:tt)*) => { + $elem.children = $crate::Children::StaticText(format!($text $($other)*)); }; ($elem:expr, for ($($for:tt)*) $code:block $($rest:tt)*) => { @@ -85,39 +81,29 @@ macro_rules! parse_rsx_param { }; ($elem:expr, $elem_path:path { $($inner:tt)* } $($rest:tt)*) => { - if $elem.children.is_none() {$elem.children = $crate::Children::Children(Vec::new(), 0)} if let $crate::Children::Children(children, _) = &mut $elem.children { - children.push(osui::ersx!($elem_path { $($inner)* })); + children.push($crate::ersx!($elem_path { $($inner)* })); + } else { + $elem.children = $crate::Children::Children(vec![$crate::ersx!($elem_path { $($inner)* })], 0) } osui::parse_rsx_param!($elem, $($rest)*) }; - ($elem:expr, $text:expr) => { - $elem.children.set_text_force(std::sync::Arc::new(move || format!($text))) + ($elem:expr, $text:literal $($other:tt)*) => { + $elem.children = $crate::Children::Text( + std::sync::Arc::new(move || format!($text $($other)*)) + ); }; - ($elem:expr, $text:expr, $($inner:tt)*) => { - $elem.children.set_text_force(std::sync::Arc::new(move || format!($text, $($inner)*))) - }; - - ($elem:expr, ) => {}; - ($elem:expr) => {}; + ($elem:expr,) => {}; } #[macro_export] macro_rules! ersx { ($elem:path { $($inner:tt)* }) => {{ - #[allow(unused_mut)] - let mut elem = $elem(); + let mut elem = <$elem>::default(); $crate::parse_rsx_param!(elem, $($inner)*); - elem - }}; - - ($elem:path as $t:ty { $($inner:tt)* }) => {{ - #[allow(unused_mut)] - let mut elem = paste::paste!{$elem::<$t>}(); - $crate::parse_rsx_param!(elem, $($inner)*); - elem + elem.create_element() }}; } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 68b170c..f6d0e14 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -7,10 +7,9 @@ pub mod styles; pub use styles::*; use crate::prelude::*; -use osui_element::{elem_fn, element}; +use osui_element::element; #[element] -#[elem_fn] #[derive(Default, Debug)] pub struct Text {} @@ -20,13 +19,22 @@ impl ElementWidget for Text<'_> { } } +#[component] +pub fn text<'a>(class: &'a str, id: &'a str, children: Children, style: Style) -> Box> { + Box::new(Text { + class: self.class, + id: self.id, + children: self.children, + style: self.style, + }) +} + #[derive(Debug)] pub enum Instruction { SetStyle(Css), } #[element] -#[elem_fn] #[derive(Default, Debug)] pub struct Div { pub instructions: Vec, @@ -84,8 +92,24 @@ impl ElementWidget for Div<'_> { } } +#[component] +pub fn div<'a>( + class: &'a str, + id: &'a str, + children: Children, + style: Style, + instructions: Vec, +) -> Box> { + Box::new(Div { + children: self.children, + class: self.class, + id: self.id, + style: self.style, + instructions: self.instructions, + }) +} + #[element] -#[elem_fn] #[derive(Default, Debug)] pub struct Button { pub on_click: Handler>, @@ -117,8 +141,26 @@ impl ElementWidget for Button<'_> { } } +#[component] +pub fn button<'a>( + class: &'a str, + id: &'a str, + children: Children, + style: Style, + on_click: Handler>, + on_hover: Handler>, +) -> Box> { + Box::new(Button { + class: self.class, + id: self.id, + children: self.children, + on_click: self.on_click.clone(), + on_hover: self.on_hover.clone(), + style: self.style, + }) +} + #[element] -#[elem_fn] #[derive(Default, Debug)] pub struct Input { pub on_click: Handler>, @@ -165,3 +207,24 @@ impl ElementWidget for Input<'_> { } } } + +#[component] +pub fn input<'a>( + class: &'a str, + id: &'a str, + placeholder: &'a str, + text: String, + children: Children, + style: Style, + on_click: Handler>, +) -> Box> { + Box::new(Input { + class: self.class, + id: self.id, + children: self.children, + style: self.style, + on_click: self.on_click, + placeholder: self.placeholder, + text: self.text, + }) +}