From 0878cad01cd68013e1397d7e2f12dccc6967b681 Mon Sep 17 00:00:00 2001
From: Leo dev
Date: Sat, 26 Jul 2025 00:26:30 +0200
Subject: [PATCH] Simple state management
---
README.md | 14 +++++++++
src/elements/mod.rs | 1 +
src/elements/state.rs | 68 +++++++++++++++++++++++++++++++++++++++++++
src/main.rs | 48 +++++++-----------------------
4 files changed, 94 insertions(+), 37 deletions(-)
create mode 100644 src/elements/state.rs
diff --git a/README.md b/README.md
index 6355cb6..157a9d4 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,20 @@
OSUI is a customizable terminal user interface (TUI) library written in Rust. It provides a set of components and rsx to build interactive command-line interfaces with ease.
+```rust
+use osui::{style::Transform, Screen};
+
+fn main() -> std::io::Result<()> {
+ let screen = Screen::new();
+
+ screen
+ .draw(format!("Hello, World"))
+ .component(Transform::center());
+
+ screen.run()
+}
+```
+
## [Documentation](https://osui.netlify.app/docs)
## Features
diff --git a/src/elements/mod.rs b/src/elements/mod.rs
index f397332..f87b784 100644
--- a/src/elements/mod.rs
+++ b/src/elements/mod.rs
@@ -1,5 +1,6 @@
pub mod div;
pub mod grid;
+pub mod state;
use crate::Element;
diff --git a/src/elements/state.rs b/src/elements/state.rs
new file mode 100644
index 0000000..cdbff7b
--- /dev/null
+++ b/src/elements/state.rs
@@ -0,0 +1,68 @@
+use crate::{render_scope::RenderScope, widget::Element};
+use std::sync::{Arc, Mutex};
+
+pub struct State {
+ pub value: *mut T,
+ dependents: Mutex>>>,
+}
+
+pub fn use_state(mut v: T) -> Arc> {
+ Arc::new(State {
+ value: &mut v,
+ dependents: Mutex::new(Vec::new()),
+ })
+}
+
+impl State {
+ 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 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 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);
+ }
+
+ 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 std::fmt::Display for State {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ unsafe { &*self.value }.fmt(f)
+ }
+}
+
+unsafe impl Send for State {}
+unsafe impl Sync for State {}
diff --git a/src/main.rs b/src/main.rs
index d1f4041..8a90309 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -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 = >::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()
}