working divs

This commit is contained in:
2025-07-05 04:40:05 -05:00
parent cec25c02d5
commit ec963707a1
8 changed files with 155 additions and 61 deletions
+56 -12
View File
@@ -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 struct Div {
pub children: Vec<Arc<Widget>>, transform: Mutex<RawTransform>,
color: u32,
} }
impl Element for Div { impl Element for Arc<Div> {
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 { fn as_any(&self) -> &dyn std::any::Any {
self self
} }
@@ -18,14 +32,44 @@ impl Element for Div {
} }
impl Div { impl Div {
pub fn new() -> Self { pub fn new(color: u32) -> Arc<Self> {
Div { Arc::new(Div {
children: Vec::new(), transform: Mutex::new(RawTransform::new()),
} color,
})
} }
pub fn draw<E: Element + 'static>(&mut self, element: E) -> &Arc<Widget> { pub fn draw(self: &Arc<Self>, element: &Arc<Widget>) -> Arc<Self> {
self.children.push(Arc::new(Widget::new(Box::new(element)))); let r2 = self.clone();
self.children.last().unwrap() 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
} }
} }
+8 -22
View File
@@ -3,7 +3,7 @@ pub mod tick;
pub mod velocity; pub mod velocity;
use std::{ use std::{
any::{Any, TypeId}, any::Any,
fmt::Debug, fmt::Debug,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
@@ -23,12 +23,9 @@ pub trait Event: Send + Sync {
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Handler( pub struct Handler<E: Event>(Arc<Mutex<dyn FnMut(&Arc<Widget>, &E) + Send + Sync>>);
Arc<Mutex<dyn FnMut(&Arc<Widget>, &dyn Event) + Send + Sync>>,
TypeId,
);
impl Component for Handler { impl<E: Event + 'static> Component for Handler<E> {
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self
} }
@@ -38,28 +35,17 @@ impl Component for Handler {
} }
} }
impl Handler { impl<E: Event + 'static> Handler<E> {
pub fn new<E: Event + 'static, F: FnMut(&Arc<Widget>, &E) + Send + Sync + 'static>( pub fn new<F: FnMut(&Arc<Widget>, &E) + Send + Sync + 'static>(f: F) -> Handler<E> {
mut f: F, Handler(Arc::new(Mutex::new(f)))
) -> Handler {
Handler(
Arc::new(Mutex::new(move |w: &Arc<Widget>, e: &dyn Event| {
if let Some(e) = e.as_any().downcast_ref::<E>() {
f(w, e)
}
})),
TypeId::of::<E>(),
)
} }
pub fn call<E: Event>(&self, w: &Arc<Widget>, e: &E) { pub fn call(&self, w: &Arc<Widget>, e: &E) {
if e.as_any().type_id() == self.1 {
(self.0.lock().unwrap())(w, e) (self.0.lock().unwrap())(w, e)
} }
}
} }
impl Debug for Handler { impl<T: Event> Debug for Handler<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Handler") write!(f, "Handler")
} }
+1 -1
View File
@@ -15,7 +15,7 @@ impl Extension for TickExtension {
let mut tick = 0; let mut tick = 0;
loop { loop {
for w in &widgets { for w in &widgets {
if let Some(on_tick) = w.get::<Handler>() { if let Some(on_tick) = w.get::<Handler<TickEvent>>() {
on_tick.call(&w, &TickEvent(tick)) on_tick.call(&w, &TickEvent(tick))
} }
} }
+20 -1
View File
@@ -1,7 +1,7 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use crate::{ use crate::{
extensions::Extension, extensions::{Extension, Handler},
render_scope::RenderScope, render_scope::RenderScope,
style::Transform, style::Transform,
widget::{Element, Widget}, widget::{Element, Widget},
@@ -20,6 +20,17 @@ pub struct Screen {
extensions: Vec<Arc<Mutex<Box<dyn Extension>>>>, extensions: Vec<Arc<Mutex<Box<dyn Extension>>>>,
} }
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 { impl Screen {
pub fn new() -> Screen { pub fn new() -> Screen {
Screen { Screen {
@@ -56,9 +67,14 @@ impl Screen {
pub fn render(&self) -> std::io::Result<()> { pub fn render(&self) -> std::io::Result<()> {
let mut scope = RenderScope::new(); let mut scope = RenderScope::new();
let (w, h) = crossterm::terminal::size().unwrap();
scope.set_parent_size(w, h);
utils::clear()?; utils::clear()?;
for elem in &self.widgets { for elem in &self.widgets {
if let Some(wrapper) = elem.get::<Handler<RenderWrapperEvent>>() {
wrapper.call(elem, &RenderWrapperEvent(&mut scope));
} else {
scope.clear(); scope.clear();
if let Some(t) = elem.get() { if let Some(t) = elem.get() {
scope.set_transform(&t); scope.set_transform(&t);
@@ -74,6 +90,9 @@ impl Screen {
scope.set_transform(&t); scope.set_transform(&t);
} }
scope.draw(); scope.draw();
elem.0.lock().unwrap().after_render(&scope);
}
} }
Ok(()) Ok(())
} }
+11 -11
View File
@@ -1,9 +1,6 @@
use osui::{ use osui::{
extensions::{ elements::div::Div,
id::{Id, IdExtension}, extensions::{id::IdExtension, tick::TickExtension},
tick::{TickEvent, TickExtension},
Handler,
},
style::Transform, style::Transform,
Screen, Screen,
}; };
@@ -14,14 +11,17 @@ fn main() {
screen.extension(document.clone()); screen.extension(document.clone());
screen.extension(TickExtension(10)); screen.extension(TickExtension(10));
let my_div = Div::new(0xff0000);
screen
.draw(my_div.clone())
.component(Transform::center().dimensions(21, 3));
my_div.draw(
screen screen
.draw(format!("Hello, World!")) .draw(format!("Hello, World!"))
.component(Handler::new(move |w, e: &TickEvent| { .component(Transform::center()),
if e.0 == 30 { );
w.set_component(Transform::center());
}
}))
.component(Id(69));
screen.run().unwrap(); screen.run().unwrap();
} }
+38 -1
View File
@@ -1,13 +1,17 @@
use std::fmt::Debug;
use crate::{ use crate::{
style::{RawTransform, Transform}, style::{RawTransform, Transform},
utils::{self, hex_ansi_bg}, utils::{self, hex_ansi_bg},
}; };
#[derive(Clone)]
enum RenderMethod { enum RenderMethod {
Text(String), Text(String),
Rectangle(u16, u16, u32), Rectangle(u16, u16, u32),
} }
#[derive(Clone)]
pub struct RenderScope { pub struct RenderScope {
transform: RawTransform, transform: RawTransform,
render_stack: Vec<RenderMethod>, render_stack: Vec<RenderMethod>,
@@ -26,7 +30,6 @@ impl RenderScope {
} }
pub fn set_transform(&mut self, transform: &Transform) { 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_dimensions(&mut self.transform);
transform.use_position(self.parent_width, self.parent_height, &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) (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) { pub fn get_parent_size(&self) -> (u16, u16) {
(self.parent_width, self.parent_height) (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")
}
} }
+6
View File
@@ -1,5 +1,6 @@
use crate::component; use crate::component;
#[derive(Clone)]
pub struct RawTransform { pub struct RawTransform {
pub x: u16, pub x: u16,
pub y: u16, pub y: u16,
@@ -57,6 +58,11 @@ impl Transform {
self self
} }
pub fn right(mut self) -> Self {
self.x = Position::End;
self
}
pub fn margin(mut self, x: i32, y: i32) -> Self { pub fn margin(mut self, x: i32, y: i32) -> Self {
self.mx = x; self.mx = x;
self.my = y; self.my = y;
+2
View File
@@ -12,6 +12,8 @@ pub type BoxedComponent = Box<dyn Component + Send + Sync>;
pub trait Element: Send + Sync { pub trait Element: Send + Sync {
#[allow(unused)] #[allow(unused)]
fn render(&mut self, scope: &mut RenderScope) {} 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(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any; fn as_any_mut(&mut self) -> &mut dyn Any;
} }