resource management

This commit is contained in:
2025-07-07 10:05:23 -05:00
parent 5fabd1a8ab
commit 3d995671cd
7 changed files with 77 additions and 82 deletions
+7 -11
View File
@@ -1,22 +1,18 @@
use std::sync::{Arc, Mutex}; use std::sync::Arc;
use crate::{component, extensions::Extension, widget::Widget}; use crate::{component, extensions::Extension, widget::Widget, Screen};
pub struct IdExtension(Mutex<Vec<Arc<Widget>>>); pub struct IdExtension(pub Arc<Screen>);
impl Extension for Arc<IdExtension> { impl Extension for Arc<IdExtension> {}
fn init(&mut self, widgets: &Vec<Arc<Widget>>) {
self.0.lock().unwrap().append(&mut widgets.clone());
}
}
impl IdExtension { impl IdExtension {
pub fn new() -> Arc<Self> { pub fn new(screen: Arc<Screen>) -> Arc<Self> {
Arc::new(Self(Mutex::new(Vec::new()))) Arc::new(IdExtension(screen))
} }
pub fn get_element(self: &Arc<IdExtension>, id: usize) -> Option<Arc<Widget>> { pub fn get_element(self: &Arc<IdExtension>, id: usize) -> Option<Arc<Widget>> {
for elem in self.0.lock().unwrap().iter() { for elem in self.0.widgets.lock().unwrap().iter() {
if let Some(current_id) = elem.get::<Id>() { if let Some(current_id) = elem.get::<Id>() {
if current_id.0 == id { if current_id.0 == id {
return Some(elem.clone()); return Some(elem.clone());
+3 -2
View File
@@ -1,7 +1,7 @@
pub mod id; pub mod id;
pub mod resources;
pub mod tick; pub mod tick;
pub mod velocity; pub mod velocity;
pub mod resources;
use std::{ use std::{
any::{type_name, Any}, any::{type_name, Any},
@@ -12,10 +12,11 @@ use std::{
use crate::{ use crate::{
render_scope::RenderScope, render_scope::RenderScope,
widget::{Component, Widget}, widget::{Component, Widget},
Screen,
}; };
pub trait Extension { pub trait Extension {
fn init(&mut self, _widgets: &Vec<Arc<Widget>>) {} fn init(&mut self, _screen: Arc<Screen>) {}
fn render_widget(&mut self, _scope: &mut RenderScope, _widget: &Arc<Widget>) {} fn render_widget(&mut self, _scope: &mut RenderScope, _widget: &Arc<Widget>) {}
} }
+16 -10
View File
@@ -1,16 +1,22 @@
use crate::{event, widget::Component}; use std::sync::{Arc, Mutex};
#[derive(Debug, Clone)] #[derive(Clone)]
pub struct Resource<T>(pub T); pub struct VecResource<T>(Arc<Mutex<Box<dyn FnMut(&T) + Send + Sync>>>);
impl<T: Send + Sync + 'static> Component for Resource<T> { impl<T: Send + Sync + 'static> VecResource<T> {
fn as_any(&self) -> &dyn std::any::Any { pub fn new() -> Self {
self Self(Arc::new(Mutex::new(Box::new(|_| {}))))
} }
fn as_any_mut(&mut self) -> &mut dyn std::any::Any { pub fn iterate<F: FnMut(&T) + Send + Sync + 'static>(&self, f: F) {
self *self.0.lock().unwrap() = Box::new(f);
}
pub fn push(&self, e: T) {
let i = self.0.clone();
std::thread::spawn(move || {
(i.lock().unwrap())(&e);
});
} }
} }
event!(ResourceUpdate);
+4 -5
View File
@@ -1,20 +1,19 @@
use std::{fmt::Debug, sync::Arc}; use std::{fmt::Debug, sync::Arc};
use crate::event; use crate::extensions::Extension;
use crate::extensions::Handler; use crate::extensions::Handler;
use crate::{extensions::Extension, widget::Widget}; use crate::{event, Screen};
pub struct TickExtension(pub u16); pub struct TickExtension(pub u16);
impl Extension for TickExtension { impl Extension for TickExtension {
fn init(&mut self, widgets: &Vec<Arc<Widget>>) { fn init(&mut self, screen: Arc<Screen>) {
let rate_dur = 1000 / self.0 as u64; let rate_dur = 1000 / self.0 as u64;
std::thread::spawn({ std::thread::spawn({
let widgets = widgets.clone();
move || { move || {
let mut tick = 0; let mut tick = 0;
loop { loop {
for w in &widgets { for w in screen.widgets.lock().unwrap().iter() {
if let Some(on_tick) = w.get::<Handler<TickEvent>>() { if let Some(on_tick) = w.get::<Handler<TickEvent>>() {
on_tick.call(&w, &TickEvent(tick)) on_tick.call(&w, &TickEvent(tick))
} }
+3 -3
View File
@@ -5,6 +5,7 @@ use crate::{
extensions::Extension, extensions::Extension,
style::{Position, Transform}, style::{Position, Transform},
widget::Widget, widget::Widget,
Screen,
}; };
pub struct VelocityExtension; pub struct VelocityExtension;
@@ -42,13 +43,12 @@ impl VelocityExtension {
} }
impl Extension for VelocityExtension { impl Extension for VelocityExtension {
fn init(&mut self, widgets: &Vec<Arc<Widget>>) { fn init(&mut self, screen: Arc<Screen>) {
std::thread::spawn({ std::thread::spawn({
let widgets = widgets.clone();
move || { move || {
let mut tick = 0; let mut tick = 0;
loop { loop {
for widget in &widgets { for widget in screen.widgets.lock().unwrap().iter() {
Self::apply_velocity_xy(tick, widget); Self::apply_velocity_xy(tick, widget);
} }
if tick > 1000 { if tick > 1000 {
+23 -19
View File
@@ -16,8 +16,8 @@ pub mod utils;
pub mod widget; pub mod widget;
pub struct Screen { pub struct Screen {
pub widgets: Vec<Arc<Widget>>, pub widgets: Mutex<Vec<Arc<Widget>>>,
extensions: Vec<Arc<Mutex<Box<dyn Extension>>>>, extensions: Mutex<Vec<Arc<Mutex<Box<dyn Extension + Send + Sync>>>>>,
} }
event!(RenderWrapperEvent(*mut RenderScope)); event!(RenderWrapperEvent(*mut RenderScope));
@@ -32,29 +32,33 @@ unsafe impl Send for RenderWrapperEvent {}
unsafe impl Sync for RenderWrapperEvent {} unsafe impl Sync for RenderWrapperEvent {}
impl Screen { impl Screen {
pub fn new() -> Screen { pub fn new() -> Arc<Self> {
Screen { Arc::new(Self {
widgets: Vec::new(), widgets: Mutex::new(Vec::new()),
extensions: Vec::new(), extensions: Mutex::new(Vec::new()),
} })
} }
pub fn draw<E: Element + 'static>(&mut self, element: E) -> &Arc<Widget> { pub fn draw<E: Element + 'static>(self: &Arc<Self>, element: E) -> Arc<Widget> {
self.widgets.push(Arc::new(Widget::new(Box::new(element)))); let w = Arc::new(Widget::new(Box::new(element)));
self.widgets.last().unwrap() self.widgets.lock().unwrap().push(w.clone());
w
} }
pub fn extension<E: Extension + 'static>(&mut self, ext: E) { pub fn extension<E: Extension + Send + Sync + 'static>(self: &Arc<Self>, ext: E) {
self.extensions.push(Arc::new(Mutex::new(Box::new(ext)))); self.extensions
.lock()
.unwrap()
.push(Arc::new(Mutex::new(Box::new(ext))));
} }
pub fn run(&mut self) -> std::io::Result<()> { pub fn run(self: &Arc<Self>) -> std::io::Result<()> {
for elem in &mut self.widgets { for elem in self.widgets.lock().unwrap().iter() {
elem.component(Transform::new()); elem.component(Transform::new());
} }
for ext in &self.extensions { for ext in self.extensions.lock().unwrap().iter() {
ext.lock().unwrap().init(&self.widgets); ext.lock().unwrap().init(self.clone());
} }
utils::hide_cursor()?; utils::hide_cursor()?;
@@ -65,13 +69,13 @@ impl Screen {
} }
} }
pub fn render(&self) -> std::io::Result<()> { pub fn render(self: &Arc<Self>) -> std::io::Result<()> {
let mut scope = RenderScope::new(); let mut scope = RenderScope::new();
let (w, h) = crossterm::terminal::size().unwrap(); let (w, h) = crossterm::terminal::size().unwrap();
scope.set_parent_size(w, h); scope.set_parent_size(w, h);
utils::clear()?; utils::clear()?;
for elem in &self.widgets { for elem in self.widgets.lock().unwrap().iter() {
if let Some(wrapper) = elem.get::<Handler<RenderWrapperEvent>>() { if let Some(wrapper) = elem.get::<Handler<RenderWrapperEvent>>() {
wrapper.call(elem, &RenderWrapperEvent(&mut scope)); wrapper.call(elem, &RenderWrapperEvent(&mut scope));
} else { } else {
@@ -80,7 +84,7 @@ impl Screen {
scope.set_transform(&t); scope.set_transform(&t);
} }
for ext in &self.extensions { for ext in self.extensions.lock().unwrap().iter() {
ext.lock().unwrap().render_widget(&mut scope, elem); ext.lock().unwrap().render_widget(&mut scope, elem);
} }
+20 -31
View File
@@ -1,10 +1,7 @@
use osui::{ use osui::{
elements::{ elements::grid::VGrid,
div::Div,
grid::{HGrid, VGrid},
},
extensions::{ extensions::{
resources::Resource, resources::VecResource,
tick::{TickEvent, TickExtension}, tick::{TickEvent, TickExtension},
Handler, Handler,
}, },
@@ -13,43 +10,35 @@ use osui::{
}; };
fn main() { fn main() {
let mut screen = Screen::new(); let screen = Screen::new();
screen.extension(TickExtension(10)); screen.extension(TickExtension(10));
let container = Div::new(0xffff00); let items = <VecResource<&str>>::new();
let vgrid = VGrid::new(0x000000, 0);
screen screen
.draw(container.clone()) .draw(vgrid.clone())
.component(Transform::center().dimensions(70, 11)); .component(Transform::center())
.component(Handler::new({
let vgrid = VGrid::new(0x0000ff, 1); let items = items.clone();
move |_, e: &TickEvent| {
container.draw(screen.draw(vgrid.clone()).component(Transform::center())); if e.0 == 1 {
items.push("Hello?");
for _ in 1..6 {
let row = HGrid::new(0xff00ff, 1);
let row_widget = vgrid.draw(
screen
.draw(row.clone())
.component(Resource(Vec::<&str>::from(["Test"])))
.component(Handler::new(|w, t: &TickEvent| {
if t.0 >= 10 {
let mut res = w.get::<Resource<Vec<&str>>>().unwrap();
res.0.push("Hello World");
w.set_component(res);
} }
})), }
); }));
for i in row_widget.get::<Resource<Vec<&str>>>().unwrap().0 { items.iterate({
row.draw( let screen = screen.clone();
move |i| {
vgrid.draw(
screen screen
.draw((i.to_string(), 0xff0000)) .draw((i.to_string(), 0xff0000))
.component(Transform::new()), .component(Transform::new()),
); );
} }
} });
screen.run().unwrap(); screen.run().unwrap();
} }