semi working state management

This commit is contained in:
2025-07-27 02:35:36 +02:00
parent 0878cad01c
commit 327f14d9ed
4 changed files with 135 additions and 44 deletions
+58
View File
@@ -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<T: Element> {
handlers: Vec<std::sync::Arc<dyn DependencyHandler>>,
element: T,
element_reset: Box<dyn FnMut() -> T + Send + Sync>,
}
impl<T: Element> Dependency<T> {
pub fn new<F: FnMut() -> 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<D: DependencyHandler + 'static>(mut self, dep: D) -> Self {
dep.add();
self.handlers.push(Arc::new(dep));
self
}
}
impl<T: Element + 'static> Element for Dependency<T> {
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
}
}
+63 -37
View File
@@ -1,16 +1,20 @@
use crate::{render_scope::RenderScope, widget::Element}; use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex};
use crate::dependency::DependencyHandler;
#[derive(Debug)]
pub struct State<T> { pub struct State<T> {
pub value: *mut T, pub value: *mut T,
dependents: Mutex<Vec<Arc<Mutex<StateDependency>>>>, dependencies: *mut usize,
changed: *mut usize, // set to dependencies when the value is changed
} }
pub fn use_state<T>(mut v: T) -> Arc<State<T>> { pub fn use_state<T>(mut v: T) -> State<T> {
Arc::new(State { State {
value: &mut v, value: &mut v,
dependents: Mutex::new(Vec::new()), dependencies: &mut 0,
}) changed: &mut 0,
}
} }
impl<T> State<T> { impl<T> State<T> {
@@ -19,50 +23,72 @@ impl<T> State<T> {
*self.value = v; *self.value = v;
} }
for d in self.dependents.lock().unwrap().iter() { self.change();
let mut d = d.lock().unwrap();
d.0 = (d.1)();
}
} }
pub fn draw<F: FnMut() -> Box<dyn Element> + 'static + Send + Sync>( pub fn change(&self) {
self: &Arc<Self>, unsafe {
mut element: F, *self.changed = *self.dependencies;
) -> Arc<Mutex<StateDependency>> { }
let d = Arc::new(Mutex::new(StateDependency((element)(), Box::new(element))));
self.dependents.lock().unwrap().push(d.clone());
d
} }
} }
pub struct StateDependency( impl<T: std::fmt::Debug> DependencyHandler for State<T> {
Box<dyn Element>, fn check(&self) -> bool {
pub Box<dyn FnMut() -> Box<dyn Element> + Send + Sync>, unsafe {
); let i = *self.changed > 0;
if i {
impl<'a> Element for Arc<Mutex<StateDependency>> { *self.changed -= 1;
fn render(&mut self, scope: &mut RenderScope) { }
self.lock().unwrap().0.render(scope); i
}
} }
fn after_render(&mut self, scope: &RenderScope) { fn add(&self) {
self.lock().unwrap().0.after_render(scope); unsafe {
} *self.dependencies += 1;
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
} }
} }
impl<T: std::fmt::Display> std::fmt::Display for State<T> { impl<T: std::fmt::Display> std::fmt::Display for State<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
unsafe { &*self.value }.fmt(f) write!(f, "{}", unsafe { &*self.value })
} }
} }
unsafe impl<T> Send for State<T> {} unsafe impl<T> Send for State<T> {}
unsafe impl<T> Sync for State<T> {} unsafe impl<T> Sync for State<T> {}
impl<T> Deref for State<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.value }
}
}
impl<T> DerefMut for State<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe {
self.change();
&mut *self.value
}
}
}
impl<T> Clone for State<T> {
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;
}
}
+1
View File
@@ -7,6 +7,7 @@ use crate::{
widget::{Element, Widget}, widget::{Element, Widget},
}; };
pub mod dependency;
pub mod elements; pub mod elements;
pub mod extensions; pub mod extensions;
pub mod macros; pub mod macros;
+13 -7
View File
@@ -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<()> { fn main() -> std::io::Result<()> {
let screen = Screen::new(); let screen = Screen::new();
let count = use_state(0); let count = use_state(0);
screen.draw(count.draw({ screen
let count = count.clone(); .draw(
move || Box::new(format!("Count: {count}")) Dependency::new({
})); let count = count.clone();
move || format!("{count}")
})
.add(count.clone()),
)
.component(Transform::center());
std::thread::spawn(move || loop { std::thread::spawn(move || loop {
std::thread::sleep(std::time::Duration::from_millis(500)); std::thread::sleep(std::time::Duration::from_millis(900));
count.set(unsafe { *count.value } + 1); let c = (*count).clone();
count.set(c + 1);
}); });
screen.run() screen.run()