diff options
| author | Laurenz <laurmaedje@gmail.com> | 2019-12-09 13:29:04 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2019-12-09 13:29:04 +0100 |
| commit | 7e980224354880cfda1797136a1ff886d6642662 (patch) | |
| tree | c0137dcca82526faa71fd1d980a90c68dac798c8 /src/library | |
| parent | 64f938b449b7ff5e53b6a06ed943bf9dedc1014b (diff) | |
Bad stack layouter 🚑
Diffstat (limited to 'src/library')
| -rw-r--r-- | src/library/boxed.rs | 15 | ||||
| -rw-r--r-- | src/library/direction.rs | 60 | ||||
| -rw-r--r-- | src/library/keys.rs | 9 | ||||
| -rw-r--r-- | src/library/maps.rs | 38 | ||||
| -rw-r--r-- | src/library/mod.rs | 12 |
5 files changed, 113 insertions, 21 deletions
diff --git a/src/library/boxed.rs b/src/library/boxed.rs index 3ec9d001..d3d5b591 100644 --- a/src/library/boxed.rs +++ b/src/library/boxed.rs @@ -6,7 +6,7 @@ function! { #[derive(Debug, PartialEq)] pub struct Boxed { body: SyntaxTree, - map: ExtentMap, + map: ExtentMap<PSize>, } parse(args, body, ctx) { @@ -17,7 +17,18 @@ function! { } layout(self, mut ctx) { - self.map.apply(ctx.axes, &mut ctx.spaces[0].dimensions)?; + use SpecificAxisKind::*; + + let space = &mut ctx.spaces[0]; + self.map.apply_with(ctx.axes, |axis, p| { + let entity = match axis { + Horizontal => { space.expand.0 = true; &mut space.dimensions.x }, + Vertical => { space.expand.1 = true; &mut space.dimensions.y }, + }; + + *entity = p.concretize(*entity) + }); + vec![AddMultiple(layout_tree(&self.body, ctx)?)] } } diff --git a/src/library/direction.rs b/src/library/direction.rs new file mode 100644 index 00000000..3b9956d1 --- /dev/null +++ b/src/library/direction.rs @@ -0,0 +1,60 @@ +use crate::func::prelude::*; +use super::maps::ConsistentMap; +use super::keys::AxisKey; + +function! { + /// `direction`: Sets the directions for the layouting axes. + #[derive(Debug, PartialEq)] + pub struct Direction { + body: Option<SyntaxTree>, + map: ConsistentMap<AxisKey, Axis>, + } + + parse(args, body, ctx) { + let mut map = ConsistentMap::new(); + + map.add_opt_span(AxisKey::Primary, args.get_pos_opt::<Axis>()?)?; + map.add_opt_span(AxisKey::Secondary, args.get_pos_opt::<Axis>()?)?; + + for arg in args.keys() { + let axis = AxisKey::from_ident(&arg.v.key)?; + let value = Axis::from_expr(arg.v.value)?; + + map.add(axis, value)?; + } + + Direction { + body: parse!(optional: body, ctx), + map, + } + } + + layout(self, mut ctx) { + let axes = ctx.axes; + + let map = self.map.dedup(|key, &direction| { + Ok((match key { + AxisKey::Primary => GenericAxisKind::Primary, + AxisKey::Secondary => GenericAxisKind::Secondary, + AxisKey::Horizontal => axes.horizontal(), + AxisKey::Vertical => axes.vertical(), + }, direction)) + })?; + + map.with(GenericAxisKind::Primary, |&val| ctx.axes.primary = val); + map.with(GenericAxisKind::Secondary, |&val| ctx.axes.secondary = val); + + if ctx.axes.primary.is_horizontal() == ctx.axes.secondary.is_horizontal() { + error!( + "aligned primary and secondary axes: `{}`, `{}`", + format!("{:?}", ctx.axes.primary).to_lowercase(), + format!("{:?}", ctx.axes.secondary).to_lowercase(), + ); + } + + match &self.body { + Some(body) => vec![AddMultiple(layout_tree(&body, ctx)?)], + None => vec![Command::SetAxes(ctx.axes)], + } + } +} diff --git a/src/library/keys.rs b/src/library/keys.rs index e74027ec..c7e34839 100644 --- a/src/library/keys.rs +++ b/src/library/keys.rs @@ -66,7 +66,7 @@ kind!(AxisKey, "axis", "secondary" => AxisKey::Secondary, ); -/// An argument key which identifies a target alignment. +/// An argument key which describes a target alignment. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum AlignmentKey { Left, @@ -172,3 +172,10 @@ kind!(PaddingKey<AxisKey>, "axis or side", "vertical-origin" => PaddingKey::AxisAligned(AxisKey::Vertical, AlignmentKey::Origin), "vertical-end" => PaddingKey::AxisAligned(AxisKey::Vertical, AlignmentKey::End), ); + +kind!(Axis, "direction", + "ltr" => Axis::LeftToRight, + "rtl" => Axis::RightToLeft, + "ttb" => Axis::TopToBottom, + "btt" => Axis::BottomToTop, +); diff --git a/src/library/maps.rs b/src/library/maps.rs index 01bde38b..c89d46cb 100644 --- a/src/library/maps.rs +++ b/src/library/maps.rs @@ -72,14 +72,14 @@ impl<K, V> ConsistentMap<K, V> where K: Hash + Eq { /// A map for storing extents along axes. #[derive(Debug, Clone, PartialEq)] -pub struct ExtentMap(ConsistentMap<AxisKey, Size>); +pub struct ExtentMap<E: ExpressionKind + Copy>(ConsistentMap<AxisKey, E>); -impl ExtentMap { +impl<E: ExpressionKind + Copy> ExtentMap<E> { /// Parse an extent map from the function args. /// /// If `enforce` is true other arguments will create an error, otherwise /// they are left intact. - pub fn new(args: &mut FuncArgs, enforce: bool) -> ParseResult<ExtentMap> { + pub fn new(args: &mut FuncArgs, enforce: bool) -> ParseResult<ExtentMap<E>> { let mut map = ConsistentMap::new(); for arg in args.keys() { @@ -96,22 +96,38 @@ impl ExtentMap { } }; - let size = Size::from_expr(arg.v.value)?; - map.add(key, size)?; + let e = E::from_expr(arg.v.value)?; + map.add(key, e)?; } Ok(ExtentMap(map)) } - /// Map from any axis key to the specific axis kind. - pub fn apply(&self, axes: LayoutAxes, dimensions: &mut Size2D) -> LayoutResult<()> { - let map = self.0.dedup(|key, &val| Ok((key.specific(axes), val)))?; - - map.with(SpecificAxisKind::Horizontal, |&val| dimensions.x = val); - map.with(SpecificAxisKind::Vertical, |&val| dimensions.y = val); + /// Apply the extents on the dimensions. + pub fn apply<F>( + &self, + axes: LayoutAxes, + dimensions: &mut Size2D, + size: F + ) -> LayoutResult<()> where F: Fn(&E) -> Size { + let map = self.dedup(axes)?; + map.with(SpecificAxisKind::Horizontal, |val| dimensions.x = size(val)); + map.with(SpecificAxisKind::Vertical, |val| dimensions.y = size(val)); + Ok(()) + } + /// Map from any axis key to the specific axis kind. + pub fn apply_with<F>(&self, axes: LayoutAxes, mut f: F) -> LayoutResult<()> + where F: FnMut(SpecificAxisKind, &E) { + for (&key, value) in self.dedup(axes)?.iter() { + f(key, value); + } Ok(()) } + + fn dedup(&self, axes: LayoutAxes) -> LayoutResult<ConsistentMap<SpecificAxisKind, E>> { + self.0.dedup(|key, &val| Ok((key.specific(axes), val))) + } } /// A map for storing padding at sides. diff --git a/src/library/mod.rs b/src/library/mod.rs index 293f9589..4439f137 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -8,6 +8,7 @@ use maps::*; pub_use_mod!(align); pub_use_mod!(boxed); +pub_use_mod!(direction); pub mod maps; pub mod keys; @@ -19,6 +20,7 @@ pub fn std() -> Scope { std.add::<Align>("align"); std.add::<Boxed>("box"); + std.add::<Direction>("direction"); std.add::<PageSize>("page.size"); std.add::<PageMargins>("page.margins"); @@ -78,7 +80,7 @@ function! { /// `page.size`: Set the size of pages. #[derive(Debug, PartialEq)] pub struct PageSize { - map: ExtentMap, + map: ExtentMap<Size>, } parse(args, body) { @@ -90,7 +92,7 @@ function! { layout(self, ctx) { let mut style = ctx.style.page; - self.map.apply(ctx.axes, &mut style.dimensions)?; + self.map.apply(ctx.axes, &mut style.dimensions, |&s| s)?; vec![SetPageStyle(style)] } } @@ -150,11 +152,7 @@ function! { layout(self, ctx) { let axis = self.axis.generic(ctx.axes); - let spacing = match self.spacing { - FSize::Absolute(size) => size, - FSize::Scaled(scale) => scale * ctx.style.text.font_size, - }; - + let spacing = self.spacing.concretize(ctx.style.text.font_size); vec![AddSpacing(spacing, SpacingKind::Hard, axis)] } } |
