Added a ElementRenderer trait for element renderers

This commit is contained in:
2025-08-04 12:16:23 -05:00
parent 9868f02c33
commit b363c81a24
3 changed files with 69 additions and 40 deletions
+6
View File
@@ -119,6 +119,12 @@ impl Context {
components components
} }
pub fn render_root(&self, scope: &mut RenderScope) {
for ext in self.screen.extensions.lock().unwrap().iter() {
ext.lock().unwrap().render(self, scope);
}
}
pub fn render(&self, w: &Arc<Widget>, scope: &mut RenderScope) { pub fn render(&self, w: &Arc<Widget>, scope: &mut RenderScope) {
for ext in self.screen.extensions.lock().unwrap().iter() { for ext in self.screen.extensions.lock().unwrap().iter() {
ext.lock().unwrap().render_widget(self, scope, w); ext.lock().unwrap().render_widget(self, scope, w);
+12 -39
View File
@@ -32,8 +32,8 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use crate::{ use crate::{
extensions::{Extension, Handler}, extensions::Extension,
prelude::Context, prelude::{Context, ElementRenderer},
render_scope::RenderScope, render_scope::RenderScope,
widget::{BoxedElement, DynWidget, Element, StaticWidget, Widget, WidgetLoad}, widget::{BoxedElement, DynWidget, Element, StaticWidget, Widget, WidgetLoad},
}; };
@@ -180,47 +180,19 @@ impl Screen {
/// This method is called internally by `run`. /// This method is called internally by `run`.
pub fn render(self: &Arc<Self>, ctx: &Context) -> std::io::Result<()> { pub fn render(self: &Arc<Self>, ctx: &Context) -> std::io::Result<()> {
let mut scope = RenderScope::new(); let mut scope = RenderScope::new();
let mut renderer = ScreenRenderer;
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);
ctx.render_root(&mut scope);
for ext in self.extensions.lock().unwrap().iter() {
ext.lock().unwrap().render(ctx, &mut scope);
}
utils::clear()?; utils::clear()?;
for elem in self.widgets.lock().unwrap().iter() { for widget in self.widgets.lock().unwrap().iter() {
if elem.get::<NoRender>().is_some() || elem.get::<NoRenderRoot>().is_some() { if widget.get::<NoRenderRoot>().is_some() {
elem.auto_refresh(); widget.auto_refresh();
continue; continue;
} }
if let Some(wrapper) = elem.get::<Handler<RenderWrapperEvent>>() { scope.render_widget(&mut renderer, ctx, widget);
wrapper.call(elem, &RenderWrapperEvent(&mut scope));
} else {
scope.clear();
if let Some(style) = elem.get() {
scope.set_style(style);
}
if let Some(t) = elem.get() {
scope.set_transform(&t);
}
for ext in self.extensions.lock().unwrap().iter() {
ext.lock().unwrap().render_widget(ctx, &mut scope, elem);
}
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, ctx);
}
elem.auto_refresh();
} }
Ok(()) Ok(())
} }
@@ -228,13 +200,14 @@ impl Screen {
/// Closes the loop and calls `on_close` in the extensions /// Closes the loop and calls `on_close` in the extensions
pub fn close(self: &Arc<Self>) { pub fn close(self: &Arc<Self>) {
*self.running.lock().unwrap() = false; *self.running.lock().unwrap() = false;
utils::show_cursor().unwrap(); utils::show_cursor().unwrap();
utils::clear().unwrap(); utils::clear().unwrap();
for ext in self.extensions.lock().unwrap().iter() { for ext in self.extensions.lock().unwrap().iter() {
ext.lock().unwrap().on_close(); ext.lock().unwrap().on_close();
} }
} }
} }
struct ScreenRenderer;
impl ElementRenderer for ScreenRenderer {}
+51 -1
View File
@@ -8,13 +8,22 @@
//! //!
//! Used internally by OSUI's layout and rendering system. //! Used internally by OSUI's layout and rendering system.
use std::fmt::Debug; use std::{fmt::Debug, sync::Arc};
use crate::{ use crate::{
prelude::{Context, Handler},
style::{RawTransform, Style, Transform}, style::{RawTransform, Style, Transform},
utils::{self, hex_ansi_bg}, utils::{self, hex_ansi_bg},
widget::Widget,
NoRender, RenderWrapperEvent,
}; };
pub trait ElementRenderer {
/// Called right after the `after_render` function is called
#[allow(unused)]
fn on_after_render(&mut self, scope: &mut RenderScope, widget: &Arc<Widget>) {}
}
/// Represents a single render instruction. /// Represents a single render instruction.
#[derive(Clone)] #[derive(Clone)]
enum RenderMethod { enum RenderMethod {
@@ -291,6 +300,47 @@ impl RenderScope {
pub fn get_style(&mut self) -> &mut Style { pub fn get_style(&mut self) -> &mut Style {
&mut self.style &mut self.style
} }
pub fn render_widget(
&mut self,
renderer: &mut dyn ElementRenderer,
ctx: &Context,
widget: &std::sync::Arc<crate::widget::Widget>,
) -> bool {
if widget.get::<NoRender>().is_some() {
widget.auto_refresh();
return false;
}
if let Some(wrapper) = widget.get::<Handler<RenderWrapperEvent>>() {
wrapper.call(widget, &RenderWrapperEvent(self));
} else {
self.clear();
if let Some(style) = widget.get() {
self.set_style(style);
}
if let Some(t) = widget.get() {
self.set_transform(&t);
}
widget.get_elem().render(self, ctx);
ctx.render(widget, self);
if let Some(t) = widget.get() {
self.set_transform(&t);
}
self.draw();
widget.get_elem().after_render(self, ctx);
ctx.after_render(widget, self);
renderer.on_after_render(self, widget);
}
widget.auto_refresh();
true
}
} }
impl Debug for RenderScope { impl Debug for RenderScope {