From 327f14d9edd977ae5ad3d89b8e57d96f24eb6bd0 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sun, 27 Jul 2025 02:35:36 +0200 Subject: [PATCH] semi working state management --- src/dependency.rs | 58 ++++++++++++++++++++++++ src/elements/state.rs | 100 ++++++++++++++++++++++++++---------------- src/lib.rs | 1 + src/main.rs | 20 ++++++--- 4 files changed, 135 insertions(+), 44 deletions(-) create mode 100644 src/dependency.rs diff --git a/src/dependency.rs b/src/dependency.rs new file mode 100644 index 0000000..8e599a3 --- /dev/null +++ b/src/dependency.rs @@ -0,0 +1,58 @@ +use std::sync::Arc; + +use crate::{widget::Element}; + +pub trait DependencyHandler: std::fmt::Debug + Send + Sync { + fn add(&self); + fn check(&self) -> bool; +} + +pub struct Dependency { + handlers: Vec>, + element: T, + element_reset: Box T + Send + Sync>, +} + +impl Dependency { + pub fn new T + Send + Sync + 'static>(mut f: F) -> Self { + Self { + handlers: Vec::new(), + element: f(), + element_reset: Box::new(f), + } + } + + pub fn auto_reset(&mut self) { + for i in &self.handlers { + if i.check() { + self.element = (self.element_reset)(); + } + } + } + + pub fn add(mut self, dep: D) -> Self { + dep.add(); + self.handlers.push(Arc::new(dep)); + self + } +} + +impl Element for Dependency { + fn render(&mut self, scope: &mut crate::render_scope::RenderScope) { + self.element.render(scope); + self.auto_reset(); + } + + fn after_render(&mut self, scope: &crate::render_scope::RenderScope) { + self.element.after_render(scope); + self.auto_reset(); + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } +} diff --git a/src/elements/state.rs b/src/elements/state.rs index cdbff7b..79c4343 100644 --- a/src/elements/state.rs +++ b/src/elements/state.rs @@ -1,16 +1,20 @@ -use crate::{render_scope::RenderScope, widget::Element}; -use std::sync::{Arc, Mutex}; +use std::ops::{Deref, DerefMut}; +use crate::dependency::DependencyHandler; + +#[derive(Debug)] pub struct State { pub value: *mut T, - dependents: Mutex>>>, + dependencies: *mut usize, + changed: *mut usize, // set to dependencies when the value is changed } -pub fn use_state(mut v: T) -> Arc> { - Arc::new(State { +pub fn use_state(mut v: T) -> State { + State { value: &mut v, - dependents: Mutex::new(Vec::new()), - }) + dependencies: &mut 0, + changed: &mut 0, + } } impl State { @@ -19,50 +23,72 @@ impl State { *self.value = v; } - for d in self.dependents.lock().unwrap().iter() { - let mut d = d.lock().unwrap(); - d.0 = (d.1)(); - } + self.change(); } - pub fn draw Box + 'static + Send + Sync>( - self: &Arc, - mut element: F, - ) -> Arc> { - let d = Arc::new(Mutex::new(StateDependency((element)(), Box::new(element)))); - self.dependents.lock().unwrap().push(d.clone()); - d + pub fn change(&self) { + unsafe { + *self.changed = *self.dependencies; + } } } -pub struct StateDependency( - Box, - pub Box Box + Send + Sync>, -); - -impl<'a> Element for Arc> { - fn render(&mut self, scope: &mut RenderScope) { - self.lock().unwrap().0.render(scope); +impl DependencyHandler for State { + fn check(&self) -> bool { + unsafe { + let i = *self.changed > 0; + if i { + *self.changed -= 1; + } + i + } } - fn after_render(&mut self, scope: &RenderScope) { - self.lock().unwrap().0.after_render(scope); - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self + fn add(&self) { + unsafe { + *self.dependencies += 1; + } } } impl std::fmt::Display for State { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - unsafe { &*self.value }.fmt(f) + write!(f, "{}", unsafe { &*self.value }) } } unsafe impl Send for State {} unsafe impl Sync for State {} + +impl Deref for State { + type Target = T; + fn deref(&self) -> &Self::Target { + unsafe { &*self.value } + } +} + +impl DerefMut for State { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { + self.change(); + + &mut *self.value + } + } +} + +impl Clone for State { + fn clone(&self) -> Self { + Self { + value: self.value, + dependencies: self.dependencies, + changed: self.changed, + } + } + + fn clone_from(&mut self, source: &Self) { + self.changed = source.changed; + self.dependencies = source.dependencies; + self.value = source.value; + } +} diff --git a/src/lib.rs b/src/lib.rs index 3318b90..a1d827a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ use crate::{ widget::{Element, Widget}, }; +pub mod dependency; pub mod elements; pub mod extensions; pub mod macros; diff --git a/src/main.rs b/src/main.rs index 8a90309..ff572c2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,23 @@ -use osui::{elements::state::use_state, Screen}; +use osui::{dependency::Dependency, elements::state::use_state, style::Transform, Screen}; fn main() -> std::io::Result<()> { let screen = Screen::new(); let count = use_state(0); - screen.draw(count.draw({ - let count = count.clone(); - move || Box::new(format!("Count: {count}")) - })); + screen + .draw( + Dependency::new({ + let count = count.clone(); + move || format!("{count}") + }) + .add(count.clone()), + ) + .component(Transform::center()); std::thread::spawn(move || loop { - std::thread::sleep(std::time::Duration::from_millis(500)); - count.set(unsafe { *count.value } + 1); + std::thread::sleep(std::time::Duration::from_millis(900)); + let c = (*count).clone(); + count.set(c + 1); }); screen.run()