diff --git a/src/lib.rs b/src/lib.rs index ae30531..961ff8d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ //! //! ```rust //! use osui::prelude::*; -//! +//! //! #[component] //! pub fn App() -> Element { //! let count = State::new(0); @@ -17,11 +17,11 @@ //! rsx! { //! button { //! class: "btn", -//! +//! //! on_click: fn(_, _, _) @count { //! count += 1; //! }, -//! +//! //! "The current count is: {count}" //! } //! } @@ -86,7 +86,7 @@ pub trait ElementCore { pub trait ElementWidget: ElementCore + std::fmt::Debug { fn render(&self, writer: &mut Writer); - fn event(&mut self, event: crossterm::event::Event, document: &Document) { + fn event(&mut self, event: crossterm::event::Event, document: &mut Document) { _ = (event, document) } fn initialize(&mut self, document: &mut Document) { @@ -103,11 +103,11 @@ pub trait Component: std::fmt::Debug { /// Structs ////////////////////////////////////////////////////////////////////////////////////////////////// -pub struct Handler(pub Arc>); +pub struct Handler(pub Arc>); pub struct Document { element: *mut Element, - running: *mut Option, + running: Option, pub css: ui::Css, } @@ -142,23 +142,15 @@ impl Document { pub fn with_elem(element: &mut Element) -> Document { Document { element, - running: &mut None, + running: None, css: HashMap::new(), } } - pub fn exit(&self) { - if !self.running.is_null() { - unsafe { - *self.running = Some(false); - } - } + pub fn exit(&mut self) { + self.running = Some(false); } - pub fn restart(&self) { - if !self.running.is_null() { - unsafe { - *self.running = Some(true); - } - } + pub fn restart(&mut self) { + self.running = Some(true); } pub fn get_root(&self) -> &mut Box { unsafe { &mut *(self.element as *mut Element as *mut Box) } @@ -195,13 +187,17 @@ impl Document { pub fn set_css(&mut self, css: ui::Css) { self.css = css; } - pub fn draw(&self, element: Element) { + pub fn clear_css(&mut self) { + self.css.clear(); + } + pub fn draw(&mut self, element: Element) { unsafe { *self.element = element; + (*self.element).initialize(self); } } pub fn run(&mut self) -> bool { - unsafe { *self.running = None } + self.running = None; let element = unsafe { &mut *self.element }; element.initialize(self); @@ -212,7 +208,7 @@ impl Document { crossterm::terminal::enable_raw_mode().unwrap(); utils::clear(); - while unsafe { *self.running } == None { + while self.running == None { self.render(); element.event(crossterm::event::read().unwrap(), self); } @@ -221,7 +217,7 @@ impl Document { crossterm::terminal::disable_raw_mode().unwrap(); utils::clear(); - unsafe { (*self.running).unwrap() } + self.running.unwrap() } } @@ -326,12 +322,12 @@ impl Children { impl Handler { pub fn new(handler_fn: F) -> Handler where - F: FnMut(&mut T, crossterm::event::Event, &Document) + 'static, + F: FnMut(&mut T, crossterm::event::Event, &mut Document) + 'static, { Handler(Arc::new(Mutex::new(handler_fn))) } - pub fn call(&self, s: &mut T, event: Event, document: &Document) { + pub fn call(&self, s: &mut T, event: Event, document: &mut Document) { let mut o = self.0.lock().unwrap(); o(s, event, document); } @@ -460,7 +456,7 @@ impl Writer { impl Default for Handler { fn default() -> Self { Handler(Arc::new(Mutex::new( - |_: &mut T, _: crossterm::event::Event, _: &Document| {}, + |_: &mut T, _: crossterm::event::Event, _: &mut Document| {}, ))) } } diff --git a/src/main.rs b/src/main.rs index 8e0f9c9..f127dda 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,42 @@ -use osui::{examples::login_example::App, prelude::*}; +use osui::{examples, prelude::*}; fn main() { launch!(App); } + +#[component] +pub fn App() { + rsx! { + @SetStyle(app_style()) + + text { static "Select an example" } + + button { class: "example", on_click: fn(_, _, document) { + document.clear_css(); + document.draw(examples::counter_example::App::default().create_element()); + }, static "Counter" } + + button { class: "example", on_click: fn(_, _, document) { + document.clear_css(); + document.draw(examples::todo_example::App::default().create_element()); + }, static "Todo" } + + button { class: "example", on_click: fn(_, _, document) { + document.clear_css(); + document.draw(examples::login_example::App::default().create_element()); + }, static "Login" } + } +} + +pub fn app_style() -> Css { + css! { + "example" { + outline: true, + y: Auto, + x: 0 px, + } + "example": "hover" { + color: Blue, + outline_color: Red, + } + } +} diff --git a/src/rsx.rs b/src/rsx.rs index 6ad8eda..b180b0d 100644 --- a/src/rsx.rs +++ b/src/rsx.rs @@ -16,6 +16,10 @@ macro_rules! parse_rsx_param { $elem.instructions.push($($i)::+($($inner)*)); osui::parse_rsx_param!($elem, $($rest)*); }; + ($elem:expr, @ $($i:ident)::+ $($rest:tt)*) => { + $elem.instructions.push($($i)::+); + osui::parse_rsx_param!($elem, $($rest)*); + }; ($elem:expr, static $text:literal $($other:tt)*) => { $elem.children = $crate::Children::StaticText(format!($text $($other)*)); diff --git a/src/ui/mod.rs b/src/ui/mod.rs index f6d0e14..c0562c9 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -52,7 +52,7 @@ impl ElementWidget for Div<'_> { } } - fn event(&mut self, event: Event, document: &Document) { + fn event(&mut self, event: Event, document: &mut Document) { if let (Some((child, i)), l) = self.children.get_child_idx() { match event { Event::Key(k) => match k.code { @@ -121,7 +121,7 @@ impl ElementWidget for Button<'_> { writer.write(&self.children.get_text()); } - fn event(&mut self, event: Event, document: &Document) { + fn event(&mut self, event: Event, document: &mut Document) { match event { Event::Key(key) => { if key.code == KeyCode::Enter { @@ -187,7 +187,7 @@ impl ElementWidget for Input<'_> { } } - fn event(&mut self, event: crossterm::event::Event, document: &Document) { + fn event(&mut self, event: crossterm::event::Event, document: &mut Document) { match event { Event::Key(k) => match k.code { KeyCode::Backspace => {