diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-10-28 16:51:57 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-10-28 16:51:57 +0200 |
| commit | d1ecb7e52eb2ab7ac4fde89bdc1c615d92ae3c7b (patch) | |
| tree | ab1d61bd5b3cc197a51cfe210cd1949a1fdba029 /src | |
| parent | 5c534fb42881b508175dd25129f62e604bdae403 (diff) | |
Add `move` function
Diffstat (limited to 'src')
| -rw-r--r-- | src/library/layout.rs | 44 | ||||
| -rw-r--r-- | src/library/mod.rs | 5 |
2 files changed, 46 insertions, 3 deletions
diff --git a/src/library/layout.rs b/src/library/layout.rs index f7fb2882..e5650664 100644 --- a/src/library/layout.rs +++ b/src/library/layout.rs @@ -143,7 +143,7 @@ pub fn v(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { } /// `box`: Place content in a rectangular box. -pub fn boxed(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { +pub fn box_(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { let width = args.named("width")?; let height = args.named("height")?; let fill = args.named("fill")?; @@ -191,6 +191,48 @@ pub fn pad(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { }))) } +/// `move`: Move content without affecting layout. +pub fn move_(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { + #[derive(Debug, Hash)] + struct MoveNode { + offset: Spec<Option<Linear>>, + child: ShapeNode, + } + + impl InlineLevel for MoveNode { + fn layout(&self, ctx: &mut LayoutContext, space: Length, base: Size) -> Frame { + let offset = Point::new( + self.offset.x.map(|x| x.resolve(base.w)).unwrap_or_default(), + self.offset.y.map(|y| y.resolve(base.h)).unwrap_or_default(), + ); + + let mut frame = self.child.layout(ctx, space, base); + for (point, _) in &mut frame.children { + *point += offset; + } + + frame + } + } + + let x = args.named("x")?; + let y = args.named("y")?; + let body: Template = args.expect("body")?; + + Ok(Value::Template(Template::from_inline(move |style| { + MoveNode { + offset: Spec::new(x, y), + child: ShapeNode { + shape: ShapeKind::Rect, + width: None, + height: None, + fill: None, + child: Some(body.to_stack(style).pack()), + }, + } + }))) +} + /// `stack`: Stack children along an axis. pub fn stack(_: &mut EvalContext, args: &mut Args) -> TypResult<Value> { enum Child { diff --git a/src/library/mod.rs b/src/library/mod.rs index ac2085eb..6d3de11d 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -20,7 +20,7 @@ use crate::diag::{At, TypResult}; use crate::eval::{Args, Array, EvalContext, Scope, Str, Template, Value}; use crate::font::{FontFamily, FontStretch, FontStyle, FontWeight, VerticalFontMetric}; use crate::geom::*; -use crate::layout::{BlockLevel, Spacing}; +use crate::layout::{BlockLevel, Frame, InlineLevel, LayoutContext, Spacing}; use crate::style::Style; use crate::syntax::{Span, Spanned}; @@ -43,9 +43,10 @@ pub fn new() -> Scope { std.def_func("h", h); std.def_func("v", v); std.def_func("align", align); - std.def_func("box", boxed); + std.def_func("box", box_); std.def_func("block", block); std.def_func("pad", pad); + std.def_func("move", move_); std.def_func("stack", stack); std.def_func("grid", grid); |
