diff options
| author | Laurenz <laurmaedje@gmail.com> | 2020-08-03 16:01:23 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2020-08-03 16:04:55 +0200 |
| commit | dbfb3d2ced91e56314dfabbb4df9a338926c0a7a (patch) | |
| tree | 678264cb18f8abc81ebe28077f5aef2df4e5a4bd /src/layout/stack.rs | |
| parent | 5a8f2fb73ddafba9fdbe952385ae2676126183ae (diff) | |
Formatting, documentation and small improvements 🧽
Diffstat (limited to 'src/layout/stack.rs')
| -rw-r--r-- | src/layout/stack.rs | 122 |
1 files changed, 58 insertions, 64 deletions
diff --git a/src/layout/stack.rs b/src/layout/stack.rs index 28da74b7..62f2c976 100644 --- a/src/layout/stack.rs +++ b/src/layout/stack.rs @@ -1,11 +1,9 @@ -//! The stack layouter arranges boxes along the secondary layouting axis. +//! Arranging boxes into a stack along the secondary axis. //! -//! Individual layouts can be aligned at origin / center / end on both axes and -//! these alignments are with respect to the growable layout space and not the -//! total possible size. -//! -//! This means that a later layout can have influence on the position of an -//! earlier one. Consider, for example, the following code: +//! Individual layouts can be aligned at `Start`, `Center` or `End` along both +//! axes. These alignments are with respect to the size of the finished layout +//! and not the total usable size. This means that a later layout can have +//! influence on the position of an earlier one. Consider the following example. //! ```typst //! [align: right][A word.] //! [align: left][A sentence with a couple more words.] @@ -25,38 +23,35 @@ use crate::geom::Value4; use super::*; /// Performs the stack layouting. -#[derive(Debug)] pub struct StackLayouter { - /// The context for layouting. ctx: StackContext, - /// The output layouts. layouts: MultiLayout, - /// The currently active layout space. + /// The in-progress space. space: Space, } /// The context for stack layouting. #[derive(Debug, Clone)] pub struct StackContext { - /// The spaces to layout in. + /// The spaces to layout into. pub spaces: LayoutSpaces, - /// The initial layouting axes, which can be updated by the - /// [`StackLayouter::set_axes`] method. + /// The initial layouting axes, which can be updated through `set_axes`. pub axes: LayoutAxes, - /// Which alignment to set on the resulting layout. This affects how it will - /// be positioned in a parent box. + /// The alignment of the _resulting_ layout. This does not effect the line + /// layouting itself, but rather how the finished layout will be positioned + /// in a parent layout. pub align: LayoutAlign, - /// Whether to have repeated spaces or to use only the first and only once. + /// Whether to spill over into copies of the last space or finish layouting + /// when the last space is used up. pub repeat: bool, } /// A layout space composed of subspaces which can have different axes and /// alignments. -#[derive(Debug)] struct Space { - /// The index of this space in the list of spaces. + /// The index of this space in `ctx.spaces`. index: usize, - /// Whether to add the layout for this space even if it would be empty. + /// Whether to include a layout for this space even if it would be empty. hard: bool, /// The so-far accumulated layouts. layouts: Vec<(LayoutAxes, BoxLayout)>, @@ -66,18 +61,20 @@ struct Space { usable: Size, /// The specialized extra-needed size to affect the size at all. extra: Size, - /// The rulers of a space dictate which alignments for new boxes are still - /// allowed and which require a new space to be started. + /// Dictate which alignments for new boxes are still allowed and which + /// require a new space to be started. For example, after an `End`-aligned + /// item, no `Start`-aligned one can follow. rulers: Value4<GenAlign>, - /// The last added spacing if the last added thing was spacing. + /// The spacing state. This influences how new spacing is handled, e.g. hard + /// spacing may override soft spacing. last_spacing: LastSpacing, } impl StackLayouter { /// Create a new stack layouter. - pub fn new(ctx: StackContext) -> StackLayouter { + pub fn new(ctx: StackContext) -> Self { let space = ctx.spaces[0]; - StackLayouter { + Self { ctx, layouts: MultiLayout::new(), space: Space::new(0, true, space.usable()), @@ -87,8 +84,8 @@ impl StackLayouter { /// Add a layout to the stack. pub fn add(&mut self, layout: BoxLayout) { // If the alignment cannot be fitted in this space, finish it. - // TODO: Issue warning for non-fitting alignment in - // non-repeating context. + // TODO: Issue warning for non-fitting alignment in non-repeating + // context. if !self.update_rulers(layout.align) && self.ctx.repeat { self.finish_space(true); } @@ -116,14 +113,14 @@ impl StackLayouter { /// Add multiple layouts to the stack. /// - /// This function simply calls `add` repeatedly for each layout. + /// This is equivalent to calling `add` repeatedly for each layout. pub fn add_multiple(&mut self, layouts: MultiLayout) { for layout in layouts { self.add(layout); } } - /// Add secondary spacing to the stack. + /// Add spacing to the stack. pub fn add_spacing(&mut self, mut spacing: f64, kind: SpacingKind) { match kind { // A hard space is simply an empty box. @@ -133,11 +130,14 @@ impl StackLayouter { let size = Size::with_y(spacing); self.update_metrics(size); - self.space.layouts.push((self.ctx.axes, BoxLayout { - size: size.specialized(self.ctx.axes), - align: LayoutAlign::new(Start, Start), - elements: LayoutElements::new(), - })); + self.space.layouts.push(( + self.ctx.axes, + BoxLayout { + size: size.specialized(self.ctx.axes), + align: LayoutAlign::new(Start, Start), + elements: LayoutElements::new(), + } + )); self.space.last_spacing = LastSpacing::Hard; } @@ -158,8 +158,6 @@ impl StackLayouter { } } - /// Update the size metrics to reflect that a layout or spacing with the - /// given generalized size has been added. fn update_metrics(&mut self, added: Size) { let axes = self.ctx.axes; @@ -177,31 +175,29 @@ impl StackLayouter { *self.space.usable.secondary_mut(axes) -= added.y; } - /// Update the rulers to account for the new layout. Returns true if a - /// space break is necessary. + /// Returns true if a space break is necessary. fn update_rulers(&mut self, align: LayoutAlign) -> bool { let allowed = self.is_fitting_alignment(align); if allowed { - *self.space.rulers.get_mut(self.ctx.axes.secondary, Start) - = align.secondary; + *self.space.rulers.get_mut(self.ctx.axes.secondary, Start) = + align.secondary; } allowed } - /// Whether a layout with the given alignment can still be layouted in the - /// active space. - pub fn is_fitting_alignment(&mut self, align: LayoutAlign) -> bool { + /// Whether a layout with the given alignment can still be layouted into the + /// active space or a space break is necessary. + pub(crate) fn is_fitting_alignment(&mut self, align: LayoutAlign) -> bool { self.is_fitting_axis(self.ctx.axes.primary, align.primary) && self.is_fitting_axis(self.ctx.axes.secondary, align.secondary) } - /// Whether the given alignment is still allowed according to the rulers. fn is_fitting_axis(&mut self, dir: Dir, align: GenAlign) -> bool { align >= *self.space.rulers.get_mut(dir, Start) - && align <= self.space.rulers.get_mut(dir, End).inv() + && align <= self.space.rulers.get_mut(dir, End).inv() } - /// Change the layouting axes used by this layouter. + /// Update the layouting axes. pub fn set_axes(&mut self, axes: LayoutAxes) { // Forget the spacing because it is not relevant anymore. if axes.secondary != self.ctx.axes.secondary { @@ -211,10 +207,10 @@ impl StackLayouter { self.ctx.axes = axes; } - /// Change the layouting spaces to use. + /// Update the layouting spaces. /// /// If `replace_empty` is true, the current space is replaced if there are - /// no boxes laid into it yet. Otherwise, only the followup spaces are + /// no boxes laid out into it yet. Otherwise, the followup spaces are /// replaced. pub fn set_spaces(&mut self, spaces: LayoutSpaces, replace_empty: bool) { if replace_empty && self.space_is_empty() { @@ -234,13 +230,13 @@ impl StackLayouter { if space.usable().fits(size) { self.finish_space(true); self.start_space(start + index, true); - return; + break; } } } - /// The remaining unpadded, unexpanding spaces. If a function is laid out - /// into these spaces, it will fit into this stack. + /// The remaining inner spaces. If something is laid out into these spaces, + /// it will fit into this stack. pub fn remaining(&self) -> LayoutSpaces { let size = self.usable(); @@ -251,7 +247,7 @@ impl StackLayouter { }]; for space in &self.ctx.spaces[self.next_space()..] { - spaces.push(space.usable_space()); + spaces.push(space.inner()); } spaces @@ -264,17 +260,17 @@ impl StackLayouter { .specialized(self.ctx.axes) } - /// Whether the current layout space (not subspace) is empty. + /// Whether the current layout space is empty. pub fn space_is_empty(&self) -> bool { self.space.size == Size::ZERO && self.space.layouts.is_empty() } - /// Whether the current layout space is the last is the followup list. + /// Whether the current layout space is the last in the followup list. pub fn space_is_last(&self) -> bool { self.space.index == self.ctx.spaces.len() - 1 } - /// Compute the finished list of boxes. + /// Finish everything up and return the final collection of boxes. pub fn finish(mut self) -> MultiLayout { if self.space.hard || !self.space_is_empty() { self.finish_space(false); @@ -282,7 +278,7 @@ impl StackLayouter { self.layouts } - /// Finish the current space and start a new one. + /// Finish active current space and start a new one. pub fn finish_space(&mut self, hard: bool) { let space = self.ctx.spaces[self.space.index]; @@ -322,8 +318,8 @@ impl StackLayouter { // layout uses up space from the origin to the end. Thus, it reduces // the usable space for following layouts at it's origin by its // extent along the secondary axis. - *bound.get_mut(axes.secondary, Start) - += axes.secondary.factor() * layout.size.secondary(*axes); + *bound.get_mut(axes.secondary, Start) += + axes.secondary.factor() * layout.size.secondary(*axes); } // ------------------------------------------------------------------ // @@ -351,8 +347,8 @@ impl StackLayouter { // We reduce the bounding box of this layout at it's end by the // accumulated secondary extent of all layouts we have seen so far, // which are the layouts after this one since we iterate reversed. - *bound.get_mut(axes.secondary, End) - -= axes.secondary.factor() * extent.y; + *bound.get_mut(axes.secondary, End) -= + axes.secondary.factor() * extent.y; // Then, we add this layout's secondary extent to the accumulator. let size = layout.size.generalized(*axes); @@ -395,21 +391,19 @@ impl StackLayouter { self.start_space(self.next_space(), hard) } - /// Start a new space with the given index. fn start_space(&mut self, index: usize, hard: bool) { let space = self.ctx.spaces[index]; self.space = Space::new(index, hard, space.usable()); } - /// The index of the next space. fn next_space(&self) -> usize { (self.space.index + 1).min(self.ctx.spaces.len() - 1) } } impl Space { - fn new(index: usize, hard: bool, usable: Size) -> Space { - Space { + fn new(index: usize, hard: bool, usable: Size) -> Self { + Self { index, hard, layouts: vec![], |
