summaryrefslogtreecommitdiff
path: root/src/library/layout.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/library/layout.rs')
-rw-r--r--src/library/layout.rs165
1 files changed, 67 insertions, 98 deletions
diff --git a/src/library/layout.rs b/src/library/layout.rs
index 7d989555..ed936816 100644
--- a/src/library/layout.rs
+++ b/src/library/layout.rs
@@ -2,88 +2,100 @@ use crate::length::ScaleLength;
use super::*;
function! {
- /// `align`: Aligns content along the layouting axes.
+ /// `box`: Layouts content into a box.
#[derive(Debug, Clone, PartialEq)]
- pub struct AlignFunc {
- body: Option<SyntaxModel>,
- map: PosAxisMap<AlignmentValue>,
+ pub struct BoxFunc {
+ body: SyntaxModel,
+ width: Option<ScaleLength>,
+ height: Option<ScaleLength>,
+ debug: Option<bool>,
}
parse(header, body, ctx, f) {
- AlignFunc {
- body: body!(opt: body, ctx, f),
- map: PosAxisMap::parse::<AxisKey>(&mut f.diagnostics, &mut header.args),
+ BoxFunc {
+ body: body!(opt: body, ctx, f).unwrap_or(SyntaxModel::new()),
+ width: header.args.key.get::<ScaleLength>("width", f),
+ height: header.args.key.get::<ScaleLength>("height", f),
+ debug: header.args.key.get::<bool>("debug", f),
}
}
layout(self, ctx, f) {
- ctx.base = ctx.spaces[0].dimensions;
+ ctx.repeat = false;
+ ctx.spaces.truncate(1);
- let map = self.map.dedup(&mut f.diagnostics, ctx.axes, |alignment| {
- alignment.axis().map(|s| s.to_generic(ctx.axes))
+ if let Some(debug) = self.debug {
+ ctx.debug = debug;
+ }
+
+ self.width.with(|v| {
+ let length = v.raw_scaled(ctx.base.x);
+ ctx.base.x = length;
+ ctx.spaces[0].dimensions.x = length;
+ ctx.spaces[0].expansion.horizontal = true;
});
- for &axis in &[Primary, Secondary] {
- if let Some(Spanned { v: alignment, span }) = map.get_spanned(axis) {
- if let Some(generic) = alignment.to_generic(ctx.axes, axis) {
- *ctx.alignment.get_mut(axis) = generic;
- } else {
- error!(
- @f, span,
- "invalid alignment `{}` for {} axis", alignment, axis,
- );
- }
- }
- }
+ self.height.with(|v| {
+ let length = v.raw_scaled(ctx.base.y);
+ ctx.base.y = length;
+ ctx.spaces[0].dimensions.y = length;
+ ctx.spaces[0].expansion.vertical = true;
+ });
- match &self.body {
- Some(body) => {
- let layouted = layout(body, ctx).await;
- f.extend(layouted.feedback);
- vec![AddMultiple(layouted.output)]
- }
- None => vec![SetAlignment(ctx.alignment)],
- }
+ let layouted = layout(&self.body, ctx).await;
+ let layout = layouted.output.into_iter().next().unwrap();
+ f.extend(layouted.feedback);
+
+ vec![Add(layout)]
}
}
function! {
- /// `direction`: Sets the directions of the layouting axes.
+ /// `align`: Aligns content along the layouting axes.
#[derive(Debug, Clone, PartialEq)]
- pub struct DirectionFunc {
- name_span: Span,
+ pub struct AlignFunc {
body: Option<SyntaxModel>,
- map: PosAxisMap<Direction>,
+ aligns: Vec<Spanned<SpecAlign>>,
+ h: Option<Spanned<SpecAlign>>,
+ v: Option<Spanned<SpecAlign>>,
}
parse(header, body, ctx, f) {
- DirectionFunc {
- name_span: header.name.span,
+ AlignFunc {
body: body!(opt: body, ctx, f),
- map: PosAxisMap::parse::<AxisKey>(&mut f.diagnostics, &mut header.args),
+ aligns: header.args.pos.all::<Spanned<SpecAlign>>().collect(),
+ h: header.args.key.get::<Spanned<SpecAlign>>("horizontal", f),
+ v: header.args.key.get::<Spanned<SpecAlign>>("vertical", f),
}
}
layout(self, ctx, f) {
ctx.base = ctx.spaces[0].dimensions;
- let map = self.map.dedup(&mut f.diagnostics, ctx.axes, |direction| {
- Some(direction.axis().to_generic(ctx.axes))
- });
-
- let mut axes = ctx.axes;
-
- map.with(Primary, |&dir| axes.primary = dir);
- map.with(Secondary, |&dir| axes.secondary = dir);
-
- if axes.primary.axis() == axes.secondary.axis() {
- error!(
- @f, self.name_span,
- "invalid aligned primary and secondary axes: `{}`, `{}`",
- ctx.axes.primary, ctx.axes.secondary,
- );
- } else {
- ctx.axes = axes;
+ let axes = ctx.axes;
+ let all = self.aligns.iter()
+ .map(|align| {
+ let spec = align.v.axis().unwrap_or(axes.primary.axis());
+ (spec, align)
+ })
+ .chain(self.h.iter().map(|align| (Horizontal, align)))
+ .chain(self.v.iter().map(|align| (Vertical, align)));
+
+ let mut had = [false; 2];
+ for (axis, align) in all {
+ if align.v.axis().map(|a| a != axis).unwrap_or(false) {
+ error!(
+ @f, align.span,
+ "invalid alignment {} for {} axis", align.v, axis,
+ );
+ } else if had[axis as usize] {
+ error!(@f, align.span, "duplicate alignment for {} axis", axis);
+ } else {
+ had[axis as usize] = true;
+ let gen_axis = axis.to_generic(ctx.axes);
+ let gen_align = align.v.to_generic(ctx.axes);
+ *ctx.align.get_mut(gen_axis) = gen_align;
+ }
}
match &self.body {
@@ -92,50 +104,7 @@ function! {
f.extend(layouted.feedback);
vec![AddMultiple(layouted.output)]
}
- None => vec![SetAxes(ctx.axes)],
- }
- }
-}
-
-function! {
- /// `box`: Layouts content into a box.
- #[derive(Debug, Clone, PartialEq)]
- pub struct BoxFunc {
- body: SyntaxModel,
- extents: AxisMap<ScaleLength>,
- debug: Option<bool>,
- }
-
- parse(header, body, ctx, f) {
- BoxFunc {
- body: body!(opt: body, ctx, f).unwrap_or(SyntaxModel::new()),
- extents: AxisMap::parse::<ExtentKey>(&mut f.diagnostics, &mut header.args.key),
- debug: header.args.key.get::<bool>(&mut f.diagnostics, "debug"),
+ None => vec![SetAlignment(ctx.align)],
}
}
-
- layout(self, ctx, f) {
- ctx.repeat = false;
- ctx.spaces.truncate(1);
-
- if let Some(debug) = self.debug {
- ctx.debug = debug;
- }
-
- let map = self.extents.dedup(&mut f.diagnostics, ctx.axes);
- for &axis in &[Horizontal, Vertical] {
- if let Some(scale) = map.get(axis) {
- let length = scale.raw_scaled(ctx.base.get(axis));
- *ctx.base.get_mut(axis) = length;
- *ctx.spaces[0].dimensions.get_mut(axis) = length;
- *ctx.spaces[0].expansion.get_mut(axis) = true;
- }
- }
-
- let layouted = layout(&self.body, ctx).await;
- let layout = layouted.output.into_iter().next().unwrap();
- f.extend(layouted.feedback);
-
- vec![Add(layout)]
- }
}