summaryrefslogtreecommitdiff
path: root/src/layout/mod.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-01-26 15:51:13 +0100
committerLaurenz <laurmaedje@gmail.com>2020-01-26 15:51:13 +0100
commit20fb4e7c379b79b84d9884d5f2c89d781c5793e2 (patch)
treea1eef90680afa2b43cb1ce0a687c837fd78810e7 /src/layout/mod.rs
parent0a087cd28bbee5fcdffbb9d49b0ba9f413ad7f92 (diff)
Document everything 📜
Diffstat (limited to 'src/layout/mod.rs')
-rw-r--r--src/layout/mod.rs231
1 files changed, 134 insertions, 97 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index f8074524..bcabf7f3 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -1,4 +1,4 @@
-//! The core layouting engine.
+//! Layouting types and engines.
use std::io::{self, Write};
use std::fmt::{self, Display, Formatter};
@@ -6,7 +6,7 @@ use smallvec::SmallVec;
use toddle::query::FontIndex;
use crate::size::{Size, Size2D, SizeBox};
-use self::{GenericAxis::*, SpecificAxis::*, Direction::*, Alignment::*};
+use self::prelude::*;
pub mod line;
pub mod stack;
@@ -15,8 +15,13 @@ pub mod text;
pub_use_mod!(actions);
pub_use_mod!(model);
+/// Basic types used across the layouting engine.
pub mod prelude {
- pub use super::{LayoutSpace, LayoutExpansion, LayoutAxes, LayoutAlignment};
+ pub use super::{
+ LayoutContext, layout, LayoutSpace,
+ Layouted, Commands,
+ LayoutAxes, LayoutAlignment, LayoutExpansion
+ };
pub use super::GenericAxis::{self, *};
pub use super::SpecificAxis::{self, *};
pub use super::Direction::{self, *};
@@ -27,7 +32,7 @@ pub mod prelude {
/// A collection of layouts.
pub type MultiLayout = Vec<Layout>;
-/// A sequence of layouting actions inside a box.
+/// A finished box with content at fixed positions.
#[derive(Debug, Clone)]
pub struct Layout {
/// The size of the box.
@@ -81,10 +86,11 @@ impl Serialize for MultiLayout {
}
}
-/// A possibly stack-allocated vector of layout spaces.
+/// A vector of layout spaces, that is stack allocated as long as it only
+/// contains at most 2 spaces.
pub type LayoutSpaces = SmallVec<[LayoutSpace; 2]>;
-/// Spacial layouting constraints.
+/// The space into which content is laid out.
#[derive(Debug, Copy, Clone)]
pub struct LayoutSpace {
/// The maximum size of the box to layout in.
@@ -92,8 +98,7 @@ pub struct LayoutSpace {
/// Padding that should be respected on each side.
pub padding: SizeBox,
/// Whether to expand the dimensions of the resulting layout to the full
- /// dimensions of this space or to shrink them to fit the content for the
- /// horizontal and vertical axis.
+ /// dimensions of this space or to shrink them to fit the content.
pub expansion: LayoutExpansion,
}
@@ -119,70 +124,12 @@ impl LayoutSpace {
}
}
-/// Whether to fit to content or expand to the space's size.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub struct LayoutExpansion {
- pub horizontal: bool,
- pub vertical: bool,
-}
-
-impl LayoutExpansion {
- pub fn new(horizontal: bool, vertical: bool) -> LayoutExpansion {
- LayoutExpansion { horizontal, vertical }
- }
-
- /// Borrow the specified component mutably.
- pub fn get_mut(&mut self, axis: SpecificAxis) -> &mut bool {
- match axis {
- Horizontal => &mut self.horizontal,
- Vertical => &mut self.vertical,
- }
- }
-}
-
-/// The axes along which the content is laid out.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub struct LayoutAxes {
- pub primary: Direction,
- pub secondary: Direction,
-}
-
-impl LayoutAxes {
- pub fn new(primary: Direction, secondary: Direction) -> LayoutAxes {
- if primary.axis() == secondary.axis() {
- panic!("LayoutAxes::new: invalid aligned axes {:?} and {:?}",
- primary, secondary);
- }
-
- LayoutAxes { primary, secondary }
- }
-
- /// Return the direction of the specified generic axis.
- pub fn get(self, axis: GenericAxis) -> Direction {
- match axis {
- Primary => self.primary,
- Secondary => self.secondary,
- }
- }
-
- /// Borrow the direction of the specified generic axis mutably.
- pub fn get_mut(&mut self, axis: GenericAxis) -> &mut Direction {
- match axis {
- Primary => &mut self.primary,
- Secondary => &mut self.secondary,
- }
- }
-
- /// Return the direction of the specified specific axis.
- pub fn get_specific(self, axis: SpecificAxis) -> Direction {
- self.get(axis.to_generic(self))
- }
-}
-
/// The two generic layouting axes.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum GenericAxis {
+ /// The primary axis along which words are laid out.
Primary,
+ /// The secondary axis along which lines and paragraphs are laid out.
Secondary,
}
@@ -191,14 +138,6 @@ impl GenericAxis {
pub fn to_specific(self, axes: LayoutAxes) -> SpecificAxis {
axes.get(self).axis()
}
-
- /// The other axis.
- pub fn inv(self) -> GenericAxis {
- match self {
- Primary => Secondary,
- Secondary => Primary,
- }
- }
}
impl Display for GenericAxis {
@@ -213,7 +152,9 @@ impl Display for GenericAxis {
/// The two specific layouting axes.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum SpecificAxis {
+ /// The horizontal layouting axis.
Horizontal,
+ /// The vertical layouting axis.
Vertical,
}
@@ -222,14 +163,6 @@ impl SpecificAxis {
pub fn to_generic(self, axes: LayoutAxes) -> GenericAxis {
if self == axes.primary.axis() { Primary } else { Secondary }
}
-
- /// The other axis.
- pub fn inv(self) -> SpecificAxis {
- match self {
- Horizontal => Vertical,
- Vertical => Horizontal,
- }
- }
}
impl Display for SpecificAxis {
@@ -241,8 +174,50 @@ impl Display for SpecificAxis {
}
}
+/// Specifies along which directions content is laid out.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub struct LayoutAxes {
+ /// The primary layouting direction.
+ pub primary: Direction,
+ /// The secondary layouting direction.
+ pub secondary: Direction,
+}
+
+impl LayoutAxes {
+ /// Create a new instance from the two values.
+ ///
+ /// # Panics
+ /// This function panics if the directions are aligned, that is, they are
+ /// on the same axis.
+ pub fn new(primary: Direction, secondary: Direction) -> LayoutAxes {
+ if primary.axis() == secondary.axis() {
+ panic!("LayoutAxes::new: invalid aligned axes \
+ {} and {}", primary, secondary);
+ }
+
+ LayoutAxes { primary, secondary }
+ }
+
+ /// Return the direction of the specified generic axis.
+ pub fn get(self, axis: GenericAxis) -> Direction {
+ match axis {
+ Primary => self.primary,
+ Secondary => self.secondary,
+ }
+ }
+
+ /// Borrow the direction of the specified generic axis mutably.
+ pub fn get_mut(&mut self, axis: GenericAxis) -> &mut Direction {
+ match axis {
+ Primary => &mut self.primary,
+ Secondary => &mut self.secondary,
+ }
+ }
+}
+
/// Directions along which content is laid out.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+#[allow(missing_docs)]
pub enum Direction {
LeftToRight,
RightToLeft,
@@ -260,6 +235,8 @@ impl Direction {
}
/// Whether this axis points into the positive coordinate direction.
+ ///
+ /// The positive directions are left-to-right and top-to-bottom.
pub fn is_positive(self) -> bool {
match self {
LeftToRight | TopToBottom => true,
@@ -267,6 +244,14 @@ impl Direction {
}
}
+ /// The factor for this direction.
+ ///
+ /// - `1` if the direction is positive.
+ /// - `-1` if the direction is negative.
+ pub fn factor(self) -> i32 {
+ if self.is_positive() { 1 } else { -1 }
+ }
+
/// The inverse axis.
pub fn inv(self) -> Direction {
match self {
@@ -276,14 +261,6 @@ impl Direction {
BottomToTop => TopToBottom,
}
}
-
- /// The factor for this direction.
- ///
- /// - `1` if the direction is positive.
- /// - `-1` if the direction is negative.
- pub fn factor(self) -> i32 {
- if self.is_positive() { 1 } else { -1 }
- }
}
impl Display for Direction {
@@ -297,18 +274,29 @@ impl Display for Direction {
}
}
-/// Where to align a layout in a container.
+/// Specifies where to align a layout in a parent container.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct LayoutAlignment {
+ /// The alignment along the primary axis.
pub primary: Alignment,
+ /// The alignment along the secondary axis.
pub secondary: Alignment,
}
impl LayoutAlignment {
+ /// Create a new instance from the two values.
pub fn new(primary: Alignment, secondary: Alignment) -> LayoutAlignment {
LayoutAlignment { primary, secondary }
}
+ /// Return the alignment of the specified generic axis.
+ pub fn get(self, axis: GenericAxis) -> Alignment {
+ match axis {
+ Primary => self.primary,
+ Secondary => self.secondary,
+ }
+ }
+
/// Borrow the alignment of the specified generic axis mutably.
pub fn get_mut(&mut self, axis: GenericAxis) -> &mut Alignment {
match axis {
@@ -321,8 +309,11 @@ impl LayoutAlignment {
/// Where to align content.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Alignment {
+ /// Align content at the start of the axis.
Origin,
+ /// Align content centered on the axis.
Center,
+ /// Align content at the end of the axis.
End,
}
@@ -337,12 +328,53 @@ impl Alignment {
}
}
-/// Whitespace between boxes with different interaction properties.
+/// Specifies whether to expand a layout to the full size of the space it is
+/// laid out in or to shrink it to fit the content.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub struct LayoutExpansion {
+ /// Whether to expand on the horizontal axis.
+ pub horizontal: bool,
+ /// Whether to expand on the vertical axis.
+ pub vertical: bool,
+}
+
+impl LayoutExpansion {
+ /// Create a new instance from the two values.
+ pub fn new(horizontal: bool, vertical: bool) -> LayoutExpansion {
+ LayoutExpansion { horizontal, vertical }
+ }
+
+ /// Return the expansion value for the given specific axis.
+ pub fn get(self, axis: SpecificAxis) -> bool {
+ match axis {
+ Horizontal => self.horizontal,
+ Vertical => self.vertical,
+ }
+ }
+
+ /// Borrow the expansion value for the given specific axis mutably.
+ pub fn get_mut(&mut self, axis: SpecificAxis) -> &mut bool {
+ match axis {
+ Horizontal => &mut self.horizontal,
+ Vertical => &mut self.vertical,
+ }
+ }
+}
+
+/// Defines how a given spacing interacts with (possibly existing) surrounding
+/// spacing.
+///
+/// There are two options for interaction: Hard and soft spacing. Typically,
+/// hard spacing is used when a fixed amount of space needs to be inserted no
+/// matter what. In contrast, soft spacing can be used to insert a default
+/// spacing between e.g. two words or paragraphs that can still be overridden by
+/// a hard space.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum SpacingKind {
- /// A hard space consumes surrounding soft spaces and is always layouted.
+ /// Hard spaces are always laid out and consume surrounding soft space.
Hard,
- /// A soft space consumes surrounding soft spaces with higher value.
+ /// Soft spaces are not laid out if they are touching a hard space and
+ /// consume neighbouring soft spaces with higher levels.
Soft(u32),
}
@@ -357,11 +389,16 @@ impl SpacingKind {
pub const WORD: SpacingKind = SpacingKind::Soft(1);
}
-/// The last appeared spacing.
+/// The spacing kind of the most recently inserted item in a layouting process.
+/// This is not about the last _spacing item_, but the last _item_, which is why
+/// this can be `None`.
#[derive(Debug, Copy, Clone, PartialEq)]
enum LastSpacing {
+ /// The last item was hard spacing.
Hard,
+ /// The last item was soft spacing with the given width and level.
Soft(Size, u32),
+ /// The last item was not spacing.
None,
}