Simple state management

This commit is contained in:
2025-07-26 00:26:30 +02:00
parent 3d995671cd
commit 0878cad01c
4 changed files with 94 additions and 37 deletions
+1
View File
@@ -1,5 +1,6 @@
pub mod div;
pub mod grid;
pub mod state;
use crate::Element;
+68
View File
@@ -0,0 +1,68 @@
use crate::{render_scope::RenderScope, widget::Element};
use std::sync::{Arc, Mutex};
pub struct State<T> {
pub value: *mut T,
dependents: Mutex<Vec<Arc<Mutex<StateDependency>>>>,
}
pub fn use_state<T>(mut v: T) -> Arc<State<T>> {
Arc::new(State {
value: &mut v,
dependents: Mutex::new(Vec::new()),
})
}
impl<T> State<T> {
pub fn set(&self, v: T) {
unsafe {
*self.value = v;
}
for d in self.dependents.lock().unwrap().iter() {
let mut d = d.lock().unwrap();
d.0 = (d.1)();
}
}
pub fn draw<F: FnMut() -> Box<dyn Element> + 'static + Send + Sync>(
self: &Arc<Self>,
mut element: F,
) -> 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(
Box<dyn Element>,
pub Box<dyn FnMut() -> Box<dyn Element> + Send + Sync>,
);
impl<'a> Element for Arc<Mutex<StateDependency>> {
fn render(&mut self, scope: &mut RenderScope) {
self.lock().unwrap().0.render(scope);
}
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
}
}
impl<T: std::fmt::Display> std::fmt::Display for State<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
unsafe { &*self.value }.fmt(f)
}
}
unsafe impl<T> Send for State<T> {}
unsafe impl<T> Sync for State<T> {}
+11 -37
View File
@@ -1,44 +1,18 @@
use osui::{
elements::grid::VGrid,
extensions::{
resources::VecResource,
tick::{TickEvent, TickExtension},
Handler,
},
style::Transform,
Screen,
};
use osui::{elements::state::use_state, Screen};
fn main() {
fn main() -> std::io::Result<()> {
let screen = Screen::new();
screen.extension(TickExtension(10));
let count = use_state(0);
let items = <VecResource<&str>>::new();
screen.draw(count.draw({
let count = count.clone();
move || Box::new(format!("Count: {count}"))
}));
let vgrid = VGrid::new(0x000000, 0);
screen
.draw(vgrid.clone())
.component(Transform::center())
.component(Handler::new({
let items = items.clone();
move |_, e: &TickEvent| {
if e.0 == 1 {
items.push("Hello?");
}
}
}));
items.iterate({
let screen = screen.clone();
move |i| {
vgrid.draw(
screen
.draw((i.to_string(), 0xff0000))
.component(Transform::new()),
);
}
std::thread::spawn(move || loop {
std::thread::sleep(std::time::Duration::from_millis(500));
count.set(unsafe { *count.value } + 1);
});
screen.run().unwrap();
screen.run()
}