use std::sync::{Arc, Mutex}; use crate::{ extensions::{Extension, Handler}, render_scope::RenderScope, widget::{Element, Widget, WidgetLoad}, }; pub mod elements; pub mod extensions; pub mod frontend; pub mod macros; pub mod render_scope; pub mod state; pub mod style; pub mod utils; pub mod widget; pub struct Screen { pub widgets: Mutex>>, extensions: Mutex>>>>, } 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() -> Arc { Arc::new(Self { widgets: Mutex::new(Vec::new()), extensions: Mutex::new(Vec::new()), }) } pub fn draw WidgetLoad + 'static + Send + Sync>( self: &Arc, element: F, ) -> Arc { let w = Arc::new(Widget::new(Box::new(element))); self.widgets.lock().unwrap().push(w.clone()); w } pub fn draw_box( self: &Arc, element: Box WidgetLoad + Send + Sync>, ) -> Arc { let w = Arc::new(Widget::new(Box::new(element))); self.widgets.lock().unwrap().push(w.clone()); w } pub fn extension(self: &Arc, ext: E) { self.extensions .lock() .unwrap() .push(Arc::new(Mutex::new(Box::new(ext)))); } pub fn run(self: &Arc) -> std::io::Result<()> { for ext in self.extensions.lock().unwrap().iter() { ext.lock().unwrap().init(self.clone()); } utils::hide_cursor()?; loop { self.render()?; std::thread::sleep(std::time::Duration::from_millis(28)); } } pub fn render(self: &Arc) -> 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.lock().unwrap().iter() { 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.lock().unwrap().iter() { ext.lock().unwrap().render_widget(&mut scope, elem); } elem.0.lock().unwrap().render(&mut scope); if let Some(t) = elem.get() { scope.set_transform(&t); } scope.draw(); elem.0.lock().unwrap().after_render(&mut scope); } elem.auto_refresh(); } Ok(()) } }