From ec963707a17179c9ecc16c76bab2c84b75f13272 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sat, 5 Jul 2025 04:40:05 -0500 Subject: [PATCH] working divs --- src/elements/div.rs | 68 ++++++++++++++++++++++++++++++++++-------- src/extensions/mod.rs | 32 ++++++-------------- src/extensions/tick.rs | 2 +- src/lib.rs | 43 ++++++++++++++++++-------- src/main.rs | 24 +++++++-------- src/render_scope.rs | 39 +++++++++++++++++++++++- src/style.rs | 6 ++++ src/widget.rs | 2 ++ 8 files changed, 155 insertions(+), 61 deletions(-) diff --git a/src/elements/div.rs b/src/elements/div.rs index bdc8273..26a1bd9 100644 --- a/src/elements/div.rs +++ b/src/elements/div.rs @@ -1,13 +1,27 @@ -use std::sync::Arc; +use std::sync::{Arc, Mutex}; -use crate::widget::{Element, Widget}; +use crate::{ + extensions::Handler, + style::RawTransform, + widget::{Element, Widget}, + RenderWrapperEvent, +}; -#[derive(Default)] pub struct Div { - pub children: Vec>, + transform: Mutex, + color: u32, } -impl Element for Div { +impl Element for Arc
{ + fn render(&mut self, scope: &mut crate::render_scope::RenderScope) { + let (w, h) = scope.get_size_or_parent(); + scope.draw_rect(w, h, self.color); + } + + fn after_render(&mut self, scope: &crate::render_scope::RenderScope) { + *self.transform.lock().unwrap() = scope.get_transform().clone(); + } + fn as_any(&self) -> &dyn std::any::Any { self } @@ -18,14 +32,44 @@ impl Element for Div { } impl Div { - pub fn new() -> Self { - Div { - children: Vec::new(), - } + pub fn new(color: u32) -> Arc { + Arc::new(Div { + transform: Mutex::new(RawTransform::new()), + color, + }) } - pub fn draw(&mut self, element: E) -> &Arc { - self.children.push(Arc::new(Widget::new(Box::new(element)))); - self.children.last().unwrap() + pub fn draw(self: &Arc, element: &Arc) -> Arc { + let r2 = self.clone(); + let r = self.clone(); + element.component(Handler::new(move |elem, e: &RenderWrapperEvent| { + let scope = e.get_scope(); + scope.clear(); + + let transform = r2.transform.lock().unwrap(); + + let (w, h) = scope.get_parent_size(); + scope.set_parent_size(transform.width, transform.height); + + if let Some(t) = elem.get() { + scope.set_transform(&t); + } + + elem.0.lock().unwrap().render(scope); + + if let Some(t) = elem.get() { + scope.set_transform(&t); + } + + let elem_transform = scope.get_transform_mut(); + elem_transform.x += transform.x; + elem_transform.y += transform.y; + + scope.draw(); + elem.0.lock().unwrap().after_render(&scope); + + scope.set_parent_size(w, h); + })); + r } } diff --git a/src/extensions/mod.rs b/src/extensions/mod.rs index 1b8db7c..87990b5 100644 --- a/src/extensions/mod.rs +++ b/src/extensions/mod.rs @@ -3,7 +3,7 @@ pub mod tick; pub mod velocity; use std::{ - any::{Any, TypeId}, + any::Any, fmt::Debug, sync::{Arc, Mutex}, }; @@ -23,12 +23,9 @@ pub trait Event: Send + Sync { } #[derive(Clone)] -pub struct Handler( - Arc, &dyn Event) + Send + Sync>>, - TypeId, -); +pub struct Handler(Arc, &E) + Send + Sync>>); -impl Component for Handler { +impl Component for Handler { fn as_any(&self) -> &dyn Any { self } @@ -38,28 +35,17 @@ impl Component for Handler { } } -impl Handler { - pub fn new, &E) + Send + Sync + 'static>( - mut f: F, - ) -> Handler { - Handler( - Arc::new(Mutex::new(move |w: &Arc, e: &dyn Event| { - if let Some(e) = e.as_any().downcast_ref::() { - f(w, e) - } - })), - TypeId::of::(), - ) +impl Handler { + pub fn new, &E) + Send + Sync + 'static>(f: F) -> Handler { + Handler(Arc::new(Mutex::new(f))) } - pub fn call(&self, w: &Arc, e: &E) { - if e.as_any().type_id() == self.1 { - (self.0.lock().unwrap())(w, e) - } + pub fn call(&self, w: &Arc, e: &E) { + (self.0.lock().unwrap())(w, e) } } -impl Debug for Handler { +impl Debug for Handler { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "Handler") } diff --git a/src/extensions/tick.rs b/src/extensions/tick.rs index 4df2bb7..d203f41 100644 --- a/src/extensions/tick.rs +++ b/src/extensions/tick.rs @@ -15,7 +15,7 @@ impl Extension for TickExtension { let mut tick = 0; loop { for w in &widgets { - if let Some(on_tick) = w.get::() { + if let Some(on_tick) = w.get::>() { on_tick.call(&w, &TickEvent(tick)) } } diff --git a/src/lib.rs b/src/lib.rs index 17f246a..fe9ac0e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ use std::sync::{Arc, Mutex}; use crate::{ - extensions::Extension, + extensions::{Extension, Handler}, render_scope::RenderScope, style::Transform, widget::{Element, Widget}, @@ -20,6 +20,17 @@ pub struct Screen { extensions: Vec>>>, } +event!(RenderWrapperEvent(*mut RenderScope)); + +impl RenderWrapperEvent { + pub fn get_scope(&self) -> &mut RenderScope { + unsafe { &mut *self.0 } + } +} + +unsafe impl Send for RenderWrapperEvent {} +unsafe impl Sync for RenderWrapperEvent {} + impl Screen { pub fn new() -> Screen { Screen { @@ -56,24 +67,32 @@ impl Screen { pub fn render(&self) -> std::io::Result<()> { let mut scope = RenderScope::new(); + let (w, h) = crossterm::terminal::size().unwrap(); + scope.set_parent_size(w, h); utils::clear()?; for elem in &self.widgets { - scope.clear(); - if let Some(t) = elem.get() { - scope.set_transform(&t); - } + if let Some(wrapper) = elem.get::>() { + wrapper.call(elem, &RenderWrapperEvent(&mut scope)); + } else { + scope.clear(); + if let Some(t) = elem.get() { + scope.set_transform(&t); + } - for ext in &self.extensions { - ext.lock().unwrap().render_widget(&mut scope, elem); - } + for ext in &self.extensions { + ext.lock().unwrap().render_widget(&mut scope, elem); + } - elem.0.lock().unwrap().render(&mut scope); + elem.0.lock().unwrap().render(&mut scope); - if let Some(t) = elem.get() { - scope.set_transform(&t); + if let Some(t) = elem.get() { + scope.set_transform(&t); + } + scope.draw(); + + elem.0.lock().unwrap().after_render(&scope); } - scope.draw(); } Ok(()) } diff --git a/src/main.rs b/src/main.rs index 079ea15..368060f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,6 @@ use osui::{ - extensions::{ - id::{Id, IdExtension}, - tick::{TickEvent, TickExtension}, - Handler, - }, + elements::div::Div, + extensions::{id::IdExtension, tick::TickExtension}, style::Transform, Screen, }; @@ -14,14 +11,17 @@ fn main() { screen.extension(document.clone()); screen.extension(TickExtension(10)); + let my_div = Div::new(0xff0000); + screen - .draw(format!("Hello, World!")) - .component(Handler::new(move |w, e: &TickEvent| { - if e.0 == 30 { - w.set_component(Transform::center()); - } - })) - .component(Id(69)); + .draw(my_div.clone()) + .component(Transform::center().dimensions(21, 3)); + + my_div.draw( + screen + .draw(format!("Hello, World!")) + .component(Transform::center()), + ); screen.run().unwrap(); } diff --git a/src/render_scope.rs b/src/render_scope.rs index 205c59c..41646f9 100644 --- a/src/render_scope.rs +++ b/src/render_scope.rs @@ -1,13 +1,17 @@ +use std::fmt::Debug; + use crate::{ style::{RawTransform, Transform}, utils::{self, hex_ansi_bg}, }; +#[derive(Clone)] enum RenderMethod { Text(String), Rectangle(u16, u16, u32), } +#[derive(Clone)] pub struct RenderScope { transform: RawTransform, render_stack: Vec, @@ -26,7 +30,6 @@ impl RenderScope { } pub fn set_transform(&mut self, transform: &Transform) { - (self.parent_width, self.parent_height) = crossterm::terminal::size().unwrap(); transform.use_dimensions(&mut self.transform); transform.use_position(self.parent_width, self.parent_height, &mut self.transform); } @@ -76,7 +79,41 @@ impl RenderScope { (self.transform.width, self.transform.height) } + pub fn get_size_or_parent(&self) -> (u16, u16) { + ( + if self.transform.width == 0 { + self.parent_width + } else { + self.transform.width + }, + if self.transform.height == 0 { + self.parent_height + } else { + self.transform.height + }, + ) + } + pub fn get_parent_size(&self) -> (u16, u16) { (self.parent_width, self.parent_height) } + + pub fn set_parent_size(&mut self, width: u16, height: u16) { + self.parent_width = width; + self.parent_height = height; + } + + pub fn get_transform_mut(&mut self) -> &mut RawTransform { + &mut self.transform + } + + pub fn get_transform(&self) -> &RawTransform { + &self.transform + } +} + +impl Debug for RenderScope { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "RenderScope") + } } diff --git a/src/style.rs b/src/style.rs index 4c2b81c..5e3e112 100644 --- a/src/style.rs +++ b/src/style.rs @@ -1,5 +1,6 @@ use crate::component; +#[derive(Clone)] pub struct RawTransform { pub x: u16, pub y: u16, @@ -57,6 +58,11 @@ impl Transform { self } + pub fn right(mut self) -> Self { + self.x = Position::End; + self + } + pub fn margin(mut self, x: i32, y: i32) -> Self { self.mx = x; self.my = y; diff --git a/src/widget.rs b/src/widget.rs index 2584a36..40ec5a4 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -12,6 +12,8 @@ pub type BoxedComponent = Box; pub trait Element: Send + Sync { #[allow(unused)] fn render(&mut self, scope: &mut RenderScope) {} + #[allow(unused)] + fn after_render(&mut self, scope: &RenderScope) {} fn as_any(&self) -> &dyn Any; fn as_any_mut(&mut self) -> &mut dyn Any; }