105 lines
3.2 KiB
Rust
105 lines
3.2 KiB
Rust
use crate::length::ScaleLength;
|
|
use super::*;
|
|
|
|
function! {
|
|
/// `box`: Layouts content into a box.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct BoxFunc {
|
|
body: SyntaxTree,
|
|
width: Option<ScaleLength>,
|
|
height: Option<ScaleLength>,
|
|
}
|
|
|
|
parse(header, body, state, f) {
|
|
Self {
|
|
body: parse_maybe_body(body, state, f).unwrap_or(SyntaxTree::new()),
|
|
width: header.args.key.get::<ScaleLength>("width", f),
|
|
height: header.args.key.get::<ScaleLength>("height", f),
|
|
}
|
|
}
|
|
|
|
layout(self, ctx, f) {
|
|
ctx.spaces.truncate(1);
|
|
ctx.repeat = false;
|
|
|
|
self.width.with(|v| {
|
|
let length = v.raw_scaled(ctx.base.x);
|
|
ctx.base.x = length;
|
|
ctx.spaces[0].size.x = length;
|
|
ctx.spaces[0].expansion.horizontal = true;
|
|
});
|
|
|
|
self.height.with(|v| {
|
|
let length = v.raw_scaled(ctx.base.y);
|
|
ctx.base.y = length;
|
|
ctx.spaces[0].size.y = length;
|
|
ctx.spaces[0].expansion.vertical = true;
|
|
});
|
|
|
|
let layouted = layout(&self.body, ctx).await;
|
|
let layout = layouted.output.into_iter().next().unwrap();
|
|
f.extend(layouted.feedback);
|
|
|
|
vec![Add(layout)]
|
|
}
|
|
}
|
|
|
|
function! {
|
|
/// `align`: Aligns content along the layouting axes.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
pub struct AlignFunc {
|
|
body: Option<SyntaxTree>,
|
|
aligns: SpanVec<SpecAlign>,
|
|
h: Option<Spanned<SpecAlign>>,
|
|
v: Option<Spanned<SpecAlign>>,
|
|
}
|
|
|
|
parse(header, body, state, f) {
|
|
Self {
|
|
body: parse_maybe_body(body, state, f),
|
|
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].size;
|
|
|
|
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 {
|
|
Some(body) => {
|
|
let layouted = layout(body, ctx).await;
|
|
f.extend(layouted.feedback);
|
|
vec![AddMultiple(layouted.output)]
|
|
}
|
|
None => vec![SetAlignment(ctx.align)],
|
|
}
|
|
}
|
|
}
|