From e2e1a466f448430f4cd3dd2b35247507b0afe5ec Mon Sep 17 00:00:00 2001 From: Leo dev Date: Fri, 17 Jan 2025 02:28:54 +0100 Subject: [PATCH] state management --- src/console.rs | 7 ++-- src/lib.rs | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 26 +++++++++++---- src/rsx.rs | 13 ++++++++ 4 files changed, 122 insertions(+), 11 deletions(-) create mode 100644 src/rsx.rs diff --git a/src/console.rs b/src/console.rs index eae8a4e..c97b909 100644 --- a/src/console.rs +++ b/src/console.rs @@ -1,4 +1,4 @@ -use crate::Frame; +use crate::{Element, Frame}; pub struct Console(Frame); @@ -25,10 +25,7 @@ pub fn end() -> crate::Result<()> { } impl Console { - pub fn draw(&self, mut f: F) -> crate::Result<()> - where - F: FnMut(&Frame) -> crate::Result<()>, - { + pub fn draw(&self, f: Element) -> crate::Result<()> { crate::utils::clear()?; f(&self.0) } diff --git a/src/lib.rs b/src/lib.rs index 1cf0f6e..cfd7c26 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,12 @@ pub mod console; +pub mod rsx; pub mod utils; pub mod widgets; pub use std::io::Result; +pub type Element = std::sync::Arc crate::Result<()>>; + pub trait Widget { fn render(&self) -> String; } @@ -25,6 +28,8 @@ pub struct Frame { pub area: Area, } +pub struct State(*mut T); + impl Frame { pub fn draw(&self, w: &W, mut props: Area) -> Result<()> where @@ -141,3 +146,85 @@ impl Default for Area { } } } + +impl std::fmt::Display for State { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", unsafe { &*self.0 }) + } +} + +impl std::fmt::Debug for State { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "State({:?})", unsafe { &*self.0 }) + } +} + +//// State ops //// + +impl + Clone> std::ops::Add for State { + type Output = T; + + fn add(self, rhs: T) -> Self::Output { + unsafe { + let lhs = &mut *self.0; + lhs.clone() + rhs + } + } +} + +impl + Clone> std::ops::Sub for State { + type Output = T; + + fn sub(self, rhs: T) -> Self::Output { + unsafe { + let lhs = &mut *self.0; + lhs.clone() - rhs + } + } +} + +impl + Clone> std::ops::Div for State { + type Output = T; + + fn div(self, rhs: T) -> Self::Output { + unsafe { + let lhs = &mut *self.0; + lhs.clone() / rhs + } + } +} + +impl std::ops::AddAssign for State { + fn add_assign(&mut self, rhs: T) { + unsafe { *self.0 += rhs } + } +} + +impl std::ops::SubAssign for State { + fn sub_assign(&mut self, rhs: T) { + unsafe { *self.0 -= rhs } + } +} + +impl std::ops::Deref for State { + type Target = T; + fn deref(&self) -> &Self::Target { + unsafe { &*self.0 } + } +} + +impl std::ops::DerefMut for State { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { &mut *self.0 } + } +} + +impl State { + pub fn copy_state(&self) -> Self { + Self(self.0) + } +} + +pub fn use_state(v: T) -> State { + State(Box::into_raw(Box::new(v))) +} diff --git a/src/main.rs b/src/main.rs index 44c41c1..0865a9c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,14 +3,28 @@ use osui::*; fn main() -> osui::Result<()> { let con = console::init()?; + let (ui, count) = app(); + loop { - con.draw(|frame| -> Result<()> { - frame.draw(&"testing", Area::center())?; - frame.draw(&"\x1b[32mX\x1b[0m", Area::center_x())?; - frame.draw(&"\x1b[31mY\x1b[0m", Area::center_y())?; - Ok(()) - })?; + let count = count.copy_state(); + let mut count1 = count.copy_state(); + con.draw(std::sync::Arc::clone(&ui))?; + + console::read()?; + count1 += 1; } console::end() } + +pub fn app() -> (Element, State) { + let count = use_state(0); + let count1 = count.copy_state(); + + ( + rsx! { + "{count}" + }, + count1, + ) +} diff --git a/src/rsx.rs b/src/rsx.rs new file mode 100644 index 0000000..fc10634 --- /dev/null +++ b/src/rsx.rs @@ -0,0 +1,13 @@ +#[macro_export] +macro_rules! rsx { + ($($e:literal)*) => { + std::sync::Arc::new( + move |frame: &$crate::Frame| -> $crate::Result<()> { + $( + frame.draw(&format!($e), Area::center())?; + )* + Ok(()) + } + ) + }; +}