use std::sync::Arc; use crate::component::{context::Context, scope::Scope}; use crate::{render::Point, state::HookDependency, View}; pub trait ToRsx { fn to_rsx(&self) -> Rsx; } #[derive(Clone)] pub enum RsxScope { Static(Arc) + Send + Sync>), Dynamic( Arc) + Send + Sync>, Vec>, ), Child(Rsx), } #[derive(Clone)] pub struct Rsx(Vec); impl Rsx { pub fn new() -> Self { Self(Vec::new()) } pub fn static_scope) + Send + Sync + 'static>(&mut self, scope: F) { self.0.push(RsxScope::Static(Arc::new(scope))); } pub fn dynamic_scope) + Send + Sync + 'static>( &mut self, drawer: F, dependencies: Vec>, ) { self.0 .push(RsxScope::Dynamic(Arc::new(drawer), dependencies)); } pub fn child(&mut self, child: R) { self.0.push(RsxScope::Child(child.to_rsx())); } pub fn generate_children(&self, context: &Arc) { let executor = context.get_executor(); for scope in &self.0 { match scope { RsxScope::Static(scope_fn) => { let scope = Scope::new(executor.clone()); (scope_fn)(&scope); context.add_scope(scope) } RsxScope::Dynamic(drawer, dependencies) => { let drawer = drawer.clone(); context.dyn_scope( move |c| drawer(c), &dependencies.iter().map(|d| d.as_ref()).collect::>(), ); } RsxScope::Child(child) => child.generate_children(context), } } } pub fn view(&self, context: &Arc) -> View { let context = context.clone(); self.generate_children(&context); Arc::new({ move |ctx| { context.draw_children(ctx); } }) } } impl ToRsx for &Rsx { fn to_rsx(&self) -> Rsx { Rsx(self.0.clone()) } } impl ToRsx for T { fn to_rsx(&self) -> Rsx { let s = self.to_string(); Rsx(vec![RsxScope::Static(Arc::new(move |scope| { let s = s.clone(); scope.view(Arc::new(move |ctx| ctx.draw_text(Point { x: 0, y: 0 }, &s))) }))]) } }