semi working state management
This commit is contained in:
@@ -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
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user