diff --git a/macros/src/emit.rs b/macros/src/emit.rs index e61c26e..b943e1c 100644 --- a/macros/src/emit.rs +++ b/macros/src/emit.rs @@ -146,14 +146,33 @@ fn emit_node_scope(node: &RsxNode) -> TokenStream { fn emit_node(node: &RsxNode) -> TokenStream { match node { - RsxNode::Text { text, deps } => { + RsxNode::Text { + text, + deps, + plugins, + } => { let deps_emit = emit_deps(deps); - quote! { - scope.view(Arc::new({ - #deps_emit - move |ctx| ctx.draw_text(Point { x: 0, y: 0 }, &format!(#text)) - })); + if plugins.len() == 0 { + quote! { + scope.view(Arc::new({ + #deps_emit + move |ctx| ctx.draw_text(Point { x: 0, y: 0 }, &format!(#text)) + })); + } + } else { + let plugins_emit = emit_plugins(plugins); + + quote! { + scope.view_wrapped(Arc::new({ + #deps_emit + move |ctx| ctx.draw_text(Point { x: 0, y: 0 }, &format!(#text)) + }), std::sync::Arc::new(|ctx, view| { + let area = ctx.allocate(ctx.area.x, ctx.area.y, ctx.area.width, ctx.area.height); + ctx.draw_view(area, view.clone()); + #plugins_emit + })); + } } } diff --git a/macros/src/parse.rs b/macros/src/parse.rs index 2da9553..cc1c3ed 100644 --- a/macros/src/parse.rs +++ b/macros/src/parse.rs @@ -41,7 +41,11 @@ pub struct RsxProp { /// AST node representing different RSX constructs pub enum RsxNode { /// String literal: `"text"` - Text { text: LitStr, deps: Vec }, + Text { + plugins: Vec, + text: LitStr, + deps: Vec, + }, /// Expression node: `{expr}` Expr(Expr), /// Component instantiation: `Component { prop: value, ... }` @@ -212,6 +216,8 @@ impl Parse for RsxNode { }); } + let plugins = parse_plugins(input)?; + // "%$dep for $pat in $expr { $rsx }" if input.peek(LitStr) { let text = input.parse()?; @@ -229,16 +235,19 @@ impl Parse for RsxNode { .collect(), ); - return Ok(RsxNode::Text { text, deps }); + return Ok(RsxNode::Text { + text, + deps, + plugins, + }); } - parse_component_invocation(input) + parse_component_invocation(input, plugins) } } /// Parses Path or Path { ... } into RsxNode::Component. -fn parse_component_invocation(input: ParseStream) -> Result { - let plugins = parse_plugins(input)?; +fn parse_component_invocation(input: ParseStream, plugins: Vec) -> Result { let path: Path = input.parse()?; if !input.peek(Brace) { diff --git a/src/component/scope.rs b/src/component/scope.rs index 6ac0926..bfe5ec7 100644 --- a/src/component/scope.rs +++ b/src/component/scope.rs @@ -10,7 +10,7 @@ use crate::{engine::CommandExecutor, View, ViewWrapper}; use super::{context::Context, ComponentImpl}; /// A scope groups child components and manages their rendering -/// +/// /// Scopes form the hierarchical structure of a component tree. /// Each scope contains references to its child components and their /// optional view wrappers (for layout/styling). @@ -31,7 +31,7 @@ impl Scope { } /// Adds a child component to this scope - /// + /// /// The view_wrapper is optional and can be used for layout or styling. pub fn child( self: &Arc, @@ -53,4 +53,13 @@ impl Scope { self.children.lock().unwrap().push((ctx, None)); } + + /// Adds a view directly to this scope + pub fn view_wrapped(self: &Arc, view: View, view_wrapper: ViewWrapper) { + let ctx = Context::new(view, self.executor.clone()); + + ctx.refresh(); + + self.children.lock().unwrap().push((ctx, Some(view_wrapper))); + } }