From 29cfef0a6dfef5820bda339d327638e285aaf4d3 Mon Sep 17 00:00:00 2001 From: Martin Haug Date: Tue, 8 Jun 2021 11:05:09 +0200 Subject: Add a grid layouter --- src/library/grid.rs | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/library/mod.rs | 3 +++ 2 files changed, 79 insertions(+) create mode 100644 src/library/grid.rs (limited to 'src/library') diff --git a/src/library/grid.rs b/src/library/grid.rs new file mode 100644 index 00000000..0aa1fc9d --- /dev/null +++ b/src/library/grid.rs @@ -0,0 +1,76 @@ +use crate::layout::GridNode; + +use super::*; + +/// `stack`: Stack children along an axis. +/// +/// # Positional parameters +/// - Children: variadic, of type `template`. +/// +/// # Named parameters +/// - Column widths: `columns`, of type `Array`. +/// - Row widths: `rows`, of type `Array`. +/// - Gutter: `gutter-vertical` and `gutter-horizontal` for individual track axis or `gutter` for both, of type `Array` respectively. +/// - Stacking direction: `dir`, of type `direction`. +/// +/// # Return value +/// A template that arranges its children along the specified grid cells. +/// +/// # Relevant types and constants +/// - Type `direction` +/// - `ltr` +/// - `rtl` +/// - `ttb` +/// - `btt` +pub fn grid(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { + let cols = args.eat_named::(ctx, "columns").unwrap_or_default(); + let rows = args.eat_named::(ctx, "rows").unwrap_or_default(); + + let gutter = args.eat_named(ctx, "gutter"); + let gutter_vertical = args + .eat_named::(ctx, "gutter-col") + .or_else(|| gutter.clone()) + .unwrap_or_default(); + let gutter_horizontal = args + .eat_named::(ctx, "gutter-row") + .or(gutter) + .unwrap_or_default(); + + let dir = args.eat_named(ctx, "dir"); + let children = args.eat_all::(ctx); + + Value::template("grid", move |ctx| { + let children = + children.iter().map(|child| ctx.exec_template_stack(child).into()).collect(); + ctx.push(GridNode { + dir: dir.unwrap_or_else(|| ctx.state.lang.dir), + children, + gutter: Gen::new(gutter_vertical.clone(), gutter_horizontal.clone()), + tracks: Gen::new(cols.clone(), rows.clone()), + }) + }) +} + +/// A list of [`GridUnit`]s. +#[derive(Default, Debug, Clone, PartialEq, Hash)] +pub struct GridUnits(pub Vec); + +impl GridUnits { + pub fn get(&self, index: usize) -> TrackSizing { + if self.0.is_empty() { + TrackSizing::Auto + } else { + *self.0.get(index).unwrap_or(self.0.last().unwrap()) + } + } +} + +value! { + GridUnits: "array of fractional values, lengths, and the `auto` keyword", + Value::TrackSizing(value) => Self(vec![value]), + Value::Array(values) => Self(values + .into_iter() + .filter_map(|v| v.cast().ok()) + .collect() + ), +} diff --git a/src/library/mod.rs b/src/library/mod.rs index f9e4f68a..8caddc4c 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -6,6 +6,7 @@ mod align; mod basic; mod font; +mod grid; mod image; mod lang; mod math; @@ -20,6 +21,7 @@ pub use self::image::*; pub use align::*; pub use basic::*; pub use font::*; +pub use grid::*; pub use lang::*; pub use math::*; pub use pad::*; @@ -47,6 +49,7 @@ pub fn new() -> Scope { std.def_func("circle", circle); std.def_func("ellipse", ellipse); std.def_func("font", font); + std.def_func("grid", grid); std.def_func("h", h); std.def_func("image", image); std.def_func("lang", lang); -- cgit v1.2.3