diff options
Diffstat (limited to 'src/library/layout.rs')
| -rw-r--r-- | src/library/layout.rs | 165 |
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)] - } } |
