diff --git a/src/elements/div.rs b/src/elements/div.rs index 02b9748..f9a193b 100644 --- a/src/elements/div.rs +++ b/src/elements/div.rs @@ -20,12 +20,20 @@ impl Div { } impl Element for Div { - fn render(&mut self, scope: &mut crate::render_scope::RenderScope) { + fn render( + &mut self, + scope: &mut crate::render_scope::RenderScope, + _: &crate::extensions::Context, + ) { let (width, height) = scope.get_size_or(self.size.0, self.size.1); scope.use_area(width, height); } - fn after_render(&mut self, scope: &mut crate::render_scope::RenderScope) { + fn after_render( + &mut self, + scope: &mut crate::render_scope::RenderScope, + ctx: &crate::extensions::Context, + ) { let mut transform = scope.get_transform().clone(); let (w, h) = scope.get_parent_size(); scope.set_parent_size(transform.width, transform.height); @@ -43,7 +51,8 @@ impl Element for Div { if let Some(t) = elem.get() { scope.set_transform(&t); } - elem.get_elem().render(scope); + elem.get_elem().render(scope, ctx); + ctx.render(elem, scope); if let Some(t) = elem.get() { scope.set_transform(&t); } @@ -54,7 +63,8 @@ impl Element for Div { t.y += transform.y + transform.py; scope.draw(); - elem.get_elem().after_render(scope); + elem.get_elem().after_render(scope, ctx); + ctx.after_render(elem, scope); } scope.set_parent_size(w, h); self.size = (transform.width, transform.height); diff --git a/src/elements/flex.rs b/src/elements/flex.rs index 06e3737..160b42d 100644 --- a/src/elements/flex.rs +++ b/src/elements/flex.rs @@ -38,12 +38,20 @@ impl FlexCol { } impl Element for FlexRow { - fn render(&mut self, scope: &mut crate::render_scope::RenderScope) { + fn render( + &mut self, + scope: &mut crate::render_scope::RenderScope, + _: &crate::extensions::Context, + ) { let (width, height) = scope.get_size_or(self.size.0, self.size.1); scope.use_area(width, height); } - fn after_render(&mut self, scope: &mut crate::render_scope::RenderScope) { + fn after_render( + &mut self, + scope: &mut crate::render_scope::RenderScope, + ctx: &crate::extensions::Context, + ) { let mut transform = scope.get_transform().clone(); let (w, h) = scope.get_parent_size(); scope.set_parent_size(transform.width, transform.height); @@ -62,7 +70,8 @@ impl Element for FlexRow { if let Some(t) = elem.get() { scope.set_transform(&t); } - elem.get_elem().render(scope); + elem.get_elem().render(scope, ctx); + ctx.render(elem, scope); if let Some(t) = elem.get() { scope.set_transform(&t); } @@ -77,7 +86,8 @@ impl Element for FlexRow { scope.draw(); - elem.get_elem().after_render(scope); + elem.get_elem().after_render(scope, ctx); + ctx.after_render(elem, scope); } scope.set_parent_size(w, h); self.size = (transform.width, transform.height); @@ -98,12 +108,20 @@ impl Element for FlexRow { } impl Element for FlexCol { - fn render(&mut self, scope: &mut crate::render_scope::RenderScope) { + fn render( + &mut self, + scope: &mut crate::render_scope::RenderScope, + _: &crate::extensions::Context, + ) { let (width, height) = scope.get_size_or(self.size.0, self.size.1); scope.use_area(width, height); } - fn after_render(&mut self, scope: &mut crate::render_scope::RenderScope) { + fn after_render( + &mut self, + scope: &mut crate::render_scope::RenderScope, + ctx: &crate::extensions::Context, + ) { let mut transform = scope.get_transform().clone(); let (w, h) = scope.get_parent_size(); scope.set_parent_size(transform.width, transform.height); @@ -122,7 +140,8 @@ impl Element for FlexCol { if let Some(t) = elem.get() { scope.set_transform(&t); } - elem.get_elem().render(scope); + elem.get_elem().render(scope, ctx); + ctx.render(elem, scope); if let Some(t) = elem.get() { scope.set_transform(&t); } @@ -137,7 +156,8 @@ impl Element for FlexCol { scope.draw(); - elem.get_elem().after_render(scope); + elem.get_elem().after_render(scope, ctx); + ctx.after_render(elem, scope); } scope.set_parent_size(w, h); self.size = (transform.width, transform.height); diff --git a/src/elements/heading.rs b/src/elements/heading.rs index 9e432f1..d4dd1e8 100644 --- a/src/elements/heading.rs +++ b/src/elements/heading.rs @@ -24,7 +24,11 @@ impl Heading { } impl Element for Heading { - fn render(&mut self, scope: &mut crate::prelude::RenderScope) { + fn render( + &mut self, + scope: &mut crate::prelude::RenderScope, + _: &crate::extensions::Context, + ) { let mut s = String::new(); for element in &self.children { if element.get::().is_some() { diff --git a/src/elements/input.rs b/src/elements/input.rs index 0561798..5c5eb4d 100644 --- a/src/elements/input.rs +++ b/src/elements/input.rs @@ -11,7 +11,11 @@ pub struct Input { } impl Element for Input { - fn render(&mut self, scope: &mut crate::prelude::RenderScope) { + fn render( + &mut self, + scope: &mut crate::prelude::RenderScope, + _: &crate::extensions::Context, + ) { let s = self.state.get(); scope.draw_text(0, 0, &s); if let Some(c) = s.chars().nth(self.cursor) { diff --git a/src/elements/mod.rs b/src/elements/mod.rs index 68ec01e..58ee1fc 100644 --- a/src/elements/mod.rs +++ b/src/elements/mod.rs @@ -13,7 +13,11 @@ pub use paginator::*; use crate::Element; impl Element for String { - fn render(&mut self, scope: &mut crate::render_scope::RenderScope) { + fn render( + &mut self, + scope: &mut crate::render_scope::RenderScope, + _: &crate::extensions::Context, + ) { scope.draw_text(0, 0, self); } @@ -25,17 +29,3 @@ impl Element for String { self } } - -impl Element for (String, u32) { - fn render(&mut self, scope: &mut crate::render_scope::RenderScope) { - scope.draw_text_colored(0, 0, &self.0, self.1); - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } -} diff --git a/src/elements/paginator.rs b/src/elements/paginator.rs index da7de57..f9ef1d9 100644 --- a/src/elements/paginator.rs +++ b/src/elements/paginator.rs @@ -24,12 +24,20 @@ impl Paginator { } impl Element for Paginator { - fn render(&mut self, scope: &mut crate::render_scope::RenderScope) { + fn render( + &mut self, + scope: &mut crate::render_scope::RenderScope, + _: &crate::extensions::Context, + ) { let (width, height) = scope.get_size_or(self.size.0, self.size.1); scope.use_area(width, height); } - fn after_render(&mut self, scope: &mut crate::render_scope::RenderScope) { + fn after_render( + &mut self, + scope: &mut crate::render_scope::RenderScope, + ctx: &crate::extensions::Context, + ) { if let Some(elem) = self.children.get(self.index) { if elem.get::().is_some() { return; @@ -46,7 +54,7 @@ impl Element for Paginator { if let Some(t) = elem.get() { scope.set_transform(&t); } - elem.get_elem().render(scope); + elem.get_elem().render(scope, ctx); if let Some(t) = elem.get() { scope.set_transform(&t); } @@ -57,7 +65,8 @@ impl Element for Paginator { t.y += transform.y + transform.py; scope.draw(); - elem.get_elem().after_render(scope); + elem.get_elem().after_render(scope, ctx); + ctx.after_render(elem, scope); scope.set_parent_size(w, h); self.size = (transform.width, transform.height); diff --git a/src/extensions/input_handling.rs b/src/extensions/input_handling.rs index 8939812..94156a6 100644 --- a/src/extensions/input_handling.rs +++ b/src/extensions/input_handling.rs @@ -1,9 +1,9 @@ -use crate::extensions::{Extension, ExtensionContext}; +use crate::extensions::{Extension, Context}; pub struct InputExtension; impl Extension for InputExtension { - fn init(&mut self, ctx: &ExtensionContext) { + fn init(&mut self, ctx: &Context) { let ctx = ctx.clone(); crossterm::terminal::enable_raw_mode().unwrap(); std::thread::spawn(move || loop { diff --git a/src/extensions/mod.rs b/src/extensions/mod.rs index f6abdc5..cf22386 100644 --- a/src/extensions/mod.rs +++ b/src/extensions/mod.rs @@ -21,10 +21,17 @@ use crate::{ }; pub trait Extension { - fn init(&mut self, _ctx: &ExtensionContext) {} - fn event(&mut self, _ctx: &ExtensionContext, _event: &dyn Event) {} + fn init(&mut self, _ctx: &Context) {} + fn event(&mut self, _ctx: &Context, _event: &dyn Event) {} fn on_close(&mut self) {} - fn render_widget(&mut self, _scope: &mut RenderScope, _widget: &Arc) {} + fn render_widget(&mut self, _ctx: &Context, _scope: &mut RenderScope, _widget: &Arc) {} + fn after_render_widget( + &mut self, + _ctx: &Context, + _scope: &mut RenderScope, + _widget: &Arc, + ) { + } } pub trait Event: Send + Sync { @@ -32,7 +39,7 @@ pub trait Event: Send + Sync { } #[derive(Clone)] -pub struct ExtensionContext { +pub struct Context { screen: Arc, } @@ -71,7 +78,7 @@ impl<'a> dyn Event + 'a { } } -impl ExtensionContext { +impl Context { pub fn new(screen: Arc) -> Self { Self { screen } } @@ -108,4 +115,16 @@ impl ExtensionContext { } components } + + pub fn render(&self, w: &Arc, scope: &mut RenderScope) { + for ext in self.screen.extensions.lock().unwrap().iter() { + ext.lock().unwrap().render_widget(self, scope, w); + } + } + + pub fn after_render(&self, w: &Arc, scope: &mut RenderScope) { + for ext in self.screen.extensions.lock().unwrap().iter() { + ext.lock().unwrap().after_render_widget(self, scope, w); + } + } } diff --git a/src/extensions/tick.rs b/src/extensions/tick.rs index f48ce61..9f6701e 100644 --- a/src/extensions/tick.rs +++ b/src/extensions/tick.rs @@ -1,14 +1,14 @@ use std::fmt::Debug; use crate::event; -use crate::extensions::{Extension, ExtensionContext}; +use crate::extensions::{Context, Extension}; pub struct TickExtension(pub u16); event!(TickEvent(pub u32)); impl Extension for TickExtension { - fn init(&mut self, ctx: &ExtensionContext) { + fn init(&mut self, ctx: &Context) { let ctx = ctx.clone(); let rate_dur = 1000 / self.0 as u64; std::thread::spawn({ diff --git a/src/extensions/velocity.rs b/src/extensions/velocity.rs index 799f8a0..13fae15 100644 --- a/src/extensions/velocity.rs +++ b/src/extensions/velocity.rs @@ -42,7 +42,7 @@ impl VelocityExtension { } impl Extension for VelocityExtension { - fn init(&mut self, ctx: &super::ExtensionContext) { + fn init(&mut self, ctx: &super::Context) { let ctx = ctx.clone(); std::thread::spawn({ move || { diff --git a/src/lib.rs b/src/lib.rs index c82b1cb..0d2e386 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,7 +33,7 @@ use std::sync::{Arc, Mutex}; use crate::{ extensions::{Extension, Handler}, - prelude::ExtensionContext, + prelude::Context, render_scope::RenderScope, widget::{BoxedElement, DynWidget, Element, StaticWidget, Widget, WidgetLoad}, }; @@ -159,7 +159,7 @@ impl Screen { /// /// This method blocks and repeatedly renders the screen at a fixed interval. pub fn run(self: &Arc) -> std::io::Result<()> { - let ctx = ExtensionContext::new(self.clone()); + let ctx = Context::new(self.clone()); for ext in self.extensions.lock().unwrap().iter() { ext.lock().unwrap().init(&ctx); @@ -168,7 +168,7 @@ impl Screen { utils::hide_cursor()?; while *self.running.lock().unwrap() { - self.render()?; + self.render(&ctx)?; std::thread::sleep(std::time::Duration::from_millis(28)); } @@ -178,7 +178,7 @@ impl Screen { /// Renders all widgets and applies extensions. /// /// This method is called internally by `run`. - pub fn render(self: &Arc) -> std::io::Result<()> { + pub fn render(self: &Arc, ctx: &Context) -> std::io::Result<()> { let mut scope = RenderScope::new(); let (w, h) = crossterm::terminal::size().unwrap(); scope.set_parent_size(w, h); @@ -186,9 +186,6 @@ impl Screen { utils::clear()?; for elem in self.widgets.lock().unwrap().iter() { if elem.get::().is_some() || elem.get::().is_some() { - for ext in self.extensions.lock().unwrap().iter() { - ext.lock().unwrap().render_widget(&mut scope, elem); - } elem.auto_refresh(); continue; } @@ -206,17 +203,17 @@ impl Screen { } for ext in self.extensions.lock().unwrap().iter() { - ext.lock().unwrap().render_widget(&mut scope, elem); + ext.lock().unwrap().render_widget(ctx, &mut scope, elem); } - elem.get_elem().render(&mut scope); + elem.get_elem().render(&mut scope, ctx); if let Some(t) = elem.get() { scope.set_transform(&t); } scope.draw(); - elem.get_elem().after_render(&mut scope); + elem.get_elem().after_render(&mut scope, ctx); } elem.auto_refresh(); diff --git a/src/widget.rs b/src/widget.rs index 2a2de8e..b155ae3 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -31,11 +31,11 @@ pub type BoxedComponent = Box; pub trait Element: Send + Sync { /// Called to perform rendering for the element. #[allow(unused)] - fn render(&mut self, scope: &mut RenderScope) {} + fn render(&mut self, scope: &mut RenderScope, ctx: &crate::extensions::Context) {} /// Called after rendering, for follow-up logic or cleanup. #[allow(unused)] - fn after_render(&mut self, scope: &mut RenderScope) {} + fn after_render(&mut self, scope: &mut RenderScope, ctx: &crate::extensions::Context) {} /// Called to draw child widgets, if any. #[allow(unused)]