diff --git a/examples/hello_world.rs b/examples/hello_world.rs index f81be34..a3e1aea 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -8,7 +8,7 @@ pub fn main() { #[component] fn App(cx: &Arc) -> View { rsx! { - impl my_center(11, 1) + impl size_auto, center, redraw Card { content: "Hello World".to_string() } } .view(&cx) @@ -23,9 +23,3 @@ fn Card(cx: &Arc, content: String) -> View { } .view(&cx) } - -fn my_center(ctx: &mut DrawContext, view: View, w: u16, h: u16) { - let (x, y) = ((ctx.area.width - w) / 2, (ctx.area.height - h) / 2); - let area = ctx.allocate(x, y, w, h); - ctx.draw_view(area, view); -} diff --git a/macros/src/emit.rs b/macros/src/emit.rs index e861b20..e61c26e 100644 --- a/macros/src/emit.rs +++ b/macros/src/emit.rs @@ -57,9 +57,9 @@ fn emit_plugins(deps: &[ViewPlugin]) -> TokenStream { .map(|d| { let path = &d.path; if let Some(args) = &d.args { - quote!( #path(ctx, view #(,#args)*); ) + quote!( #path(ctx, &view #(,#args)*); ) } else { - quote!( #path(ctx, view); ) + quote!( #path(ctx, &view); ) } }) .collect() @@ -194,7 +194,11 @@ fn emit_node(node: &RsxNode) -> TokenStream { let plugins_emit = emit_plugins(plugins); quote! { - scope.child(#component_expr, Some(std::sync::Arc::new(|ctx, view| {#plugins_emit}))); + scope.child(#component_expr, Some(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/src/lib.rs b/src/lib.rs index f0a73e3..3b76b8b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,16 +43,18 @@ use crate::render::DrawContext; pub mod component; pub mod engine; pub mod frontend; -pub mod render; pub mod hooks; +pub mod render; +pub mod view_plugins; pub mod prelude { //! Prelude module - Re-exports commonly used items for convenience pub use crate::component::{context::*, scope::*, *}; pub use crate::engine::*; pub use crate::frontend::*; - pub use crate::render::*; pub use crate::hooks::*; + pub use crate::render::*; + pub use crate::view_plugins::*; pub use crate::{sleep, Error, Result, View, ViewWrapper}; pub use crossterm; pub use osui_macros::{component, rsx}; diff --git a/src/render.rs b/src/render.rs index 0c75837..91d3a65 100644 --- a/src/render.rs +++ b/src/render.rs @@ -18,7 +18,7 @@ pub enum DrawInstruction { } /// Represents the dimensions of a drawable area -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct Size { /// Width in terminal columns pub width: u16, @@ -27,7 +27,7 @@ pub struct Size { } /// Represents a position in 2D space -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct Point { /// X coordinate (column) pub x: u16, @@ -36,7 +36,7 @@ pub struct Point { } /// Represents a rectangular area with position and dimensions -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct Area { /// X coordinate (column) of the top-left corner pub x: u16, @@ -68,8 +68,8 @@ impl DrawContext { Self { area, allocated: Area { - x: u16::MAX, - y: u16::MAX, + x: 0, + y: 0, width: 0, height: 0, }, @@ -80,10 +80,10 @@ impl DrawContext { /// Allocates space within the drawable area and returns the allocated area /// Updates the allocated bounds to include this allocation pub fn allocate(&mut self, x: u16, y: u16, width: u16, height: u16) -> Area { - self.allocated.x = self.allocated.x.min(x); - self.allocated.y = self.allocated.y.min(y); - self.allocated.width = self.allocated.width.max(width); - self.allocated.height = self.allocated.height.max(height); + self.allocated.x = x; + self.allocated.y = y; + self.allocated.width = width; + self.allocated.height = height; Area { x, @@ -108,4 +108,9 @@ impl DrawContext { pub fn draw_view(&mut self, area: Area, view: View) { self.drawing.push(DrawInstruction::View(area, view)); } + + /// Clears drawing + pub fn clear(&mut self) { + self.drawing.clear(); + } } diff --git a/src/view_plugins.rs b/src/view_plugins.rs new file mode 100644 index 0000000..843e3a6 --- /dev/null +++ b/src/view_plugins.rs @@ -0,0 +1,41 @@ +use crate::{ + render::{DrawContext, DrawInstruction}, + View, +}; + +pub fn x_center(ctx: &mut DrawContext, _view: &View) { + ctx.allocated.y = (ctx.area.height - ctx.allocated.height) / 2; +} + +pub fn y_center(ctx: &mut DrawContext, _view: &View) { + ctx.allocated.y = (ctx.area.height - ctx.allocated.height) / 2; +} + +pub fn center(ctx: &mut DrawContext, _view: &View) { + ctx.allocated.x = (ctx.area.width - ctx.allocated.width) / 2; + ctx.allocated.y = (ctx.area.height - ctx.allocated.height) / 2; +} + +pub fn size_auto(ctx: &mut DrawContext, _view: &View) { + for i in &ctx.drawing { + match i { + DrawInstruction::Text(_, text) => { + ctx.allocated.width = text.len() as u16; + ctx.allocated.height = 1; + } + DrawInstruction::View(area, view) => { + let mut c = DrawContext::new(area.clone()); + view(&mut c); + size_auto(&mut c, view); + ctx.allocated.width = c.allocated.width; + ctx.allocated.height = c.allocated.height; + } + DrawInstruction::Child(_, _) => {} + } + } +} + +pub fn redraw(ctx: &mut DrawContext, view: &View) { + ctx.clear(); + ctx.draw_view(ctx.allocated.clone(), view.clone()); +}