diff options
| author | Laurenz <laurmaedje@gmail.com> | 2020-10-06 13:13:18 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2020-10-06 13:13:18 +0200 |
| commit | c6a6870978226f2c6e3b258a6270cc0dcde58c72 (patch) | |
| tree | e3e75fad9055c6af5f747026e7c0146b4d035d09 /src/layout/primitive.rs | |
| parent | 5a7a32a9bafbcc69077e7766451310ab5ece62bf (diff) | |
Rename secondary/primary to main/cross ✏
Diffstat (limited to 'src/layout/primitive.rs')
| -rw-r--r-- | src/layout/primitive.rs | 380 |
1 files changed, 231 insertions, 149 deletions
diff --git a/src/layout/primitive.rs b/src/layout/primitive.rs index 64cd1dff..9070c972 100644 --- a/src/layout/primitive.rs +++ b/src/layout/primitive.rs @@ -2,30 +2,6 @@ use std::fmt::{self, Display, Formatter}; -/// Specifies the directions into which content is laid out. -/// -/// The primary component defines into which direction text and lines flow and the -/// secondary into which paragraphs and pages grow. -pub type LayoutSystem = Gen2<Dir>; - -impl Default for LayoutSystem { - fn default() -> Self { - Self::new(Dir::LTR, Dir::TTB) - } -} - -/// Specifies where to align a layout in a parent container. -pub type LayoutAlign = Gen2<GenAlign>; - -impl Default for LayoutAlign { - fn default() -> Self { - Self::new(GenAlign::Start, GenAlign::Start) - } -} - -/// Whether to expand a layout to an area's full size or shrink it to fit its content. -pub type LayoutExpansion = Spec2<bool>; - /// The four directions into which content can be laid out. #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum Dir { @@ -66,25 +42,30 @@ impl Dir { if self.is_positive() { 1.0 } else { -1.0 } } - /// The inverse direction. - pub fn inv(self) -> Self { - match self { - Self::LTR => Self::RTL, - Self::RTL => Self::LTR, - Self::TTB => Self::BTT, - Self::BTT => Self::TTB, - } - } - /// The side of this direction the alignment identifies. /// /// `Center` alignment is treated the same as `Start` alignment. pub fn side(self, align: GenAlign) -> Side { - match if align == GenAlign::End { self.inv() } else { self } { + let start = match self { Self::LTR => Side::Left, Self::RTL => Side::Right, Self::TTB => Side::Top, Self::BTT => Side::Bottom, + }; + + match align { + GenAlign::Start | GenAlign::Center => start, + GenAlign::End => start.inv(), + } + } + + /// The inverse direction. + pub fn inv(self) -> Self { + match self { + Self::LTR => Self::RTL, + Self::RTL => Self::LTR, + Self::TTB => Self::BTT, + Self::BTT => Self::TTB, } } } @@ -100,27 +81,159 @@ impl Display for Dir { } } +/// Convert a type into its generic representation. +/// +/// The generic representation deals with main and cross axes while the specific +/// representation deals with horizontal and vertical axes. +/// +/// See also [`ToSpec`] for the inverse conversion. +/// +/// [`ToSpec`]: trait.ToSpec.html +pub trait ToGen { + /// The generic version of this type. + type Output; + + /// The generic version of this type based on the current directions. + fn to_gen(self, dirs: Gen2<Dir>) -> Self::Output; +} + +/// Convert a type into its specific representation. +/// +/// The specific representation deals with horizontal and vertical axes while +/// the generic representation deals with main and cross axes. +/// +/// See also [`ToGen`] for the inverse conversion. +/// +/// [`ToGen`]: trait.ToGen.html +pub trait ToSpec { + /// The specific version of this type. + type Output; + + /// The specific version of this type based on the current directions. + fn to_spec(self, dirs: Gen2<Dir>) -> Self::Output; +} + +/// A generic container with two components for the two generic axes. +#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)] +pub struct Gen2<T> { + /// The main component. + pub main: T, + /// The cross component. + pub cross: T, +} + +impl<T> Gen2<T> { + /// Create a new instance from the two components. + pub fn new(main: T, cross: T) -> Self { + Self { main, cross } + } + + /// Return the component for the specified generic axis. + pub fn get(self, axis: GenAxis) -> T { + match axis { + GenAxis::Main => self.main, + GenAxis::Cross => self.cross, + } + } + + /// Borrow the component for the specified generic axis mutably. + pub fn get_mut(&mut self, axis: GenAxis) -> &mut T { + match axis { + GenAxis::Main => &mut self.main, + GenAxis::Cross => &mut self.cross, + } + } +} + +impl<T> ToSpec for Gen2<T> { + type Output = Spec2<T>; + + fn to_spec(self, dirs: Gen2<Dir>) -> Self::Output { + match dirs.main.axis() { + SpecAxis::Horizontal => Spec2::new(self.main, self.cross), + SpecAxis::Vertical => Spec2::new(self.cross, self.main), + } + } +} + +/// A generic container with two components for the two specific axes. +#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)] +pub struct Spec2<T> { + /// The horizontal component. + pub horizontal: T, + /// The vertical component. + pub vertical: T, +} + +impl<T> Spec2<T> { + /// Create a new instance from the two components. + pub fn new(horizontal: T, vertical: T) -> Self { + Self { horizontal, vertical } + } + + /// Return the component for the given specific axis. + pub fn get(self, axis: SpecAxis) -> T { + match axis { + SpecAxis::Horizontal => self.horizontal, + SpecAxis::Vertical => self.vertical, + } + } + + /// Borrow the component for the given specific axis mutably. + pub fn get_mut(&mut self, axis: SpecAxis) -> &mut T { + match axis { + SpecAxis::Horizontal => &mut self.horizontal, + SpecAxis::Vertical => &mut self.vertical, + } + } +} + +impl<T> ToGen for Spec2<T> { + type Output = Gen2<T>; + + fn to_gen(self, dirs: Gen2<Dir>) -> Self::Output { + match dirs.main.axis() { + SpecAxis::Horizontal => Gen2::new(self.horizontal, self.vertical), + SpecAxis::Vertical => Gen2::new(self.vertical, self.horizontal), + } + } +} + /// The two generic layouting axes. #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum GenAxis { - /// The primary layouting direction into which text and lines flow. - Primary, - /// The secondary layouting direction into which paragraphs grow. - Secondary, + /// The axis pages and paragraphs are set along. + Main, + /// The axis words and lines are set along. + Cross, } impl GenAxis { - /// The specific version of this axis in the given layout system. - pub fn to_spec(self, sys: LayoutSystem) -> SpecAxis { - sys.get(self).axis() + /// The other axis. + pub fn other(self) -> Self { + match self { + Self::Main => Self::Cross, + Self::Cross => Self::Main, + } + } +} + +impl ToSpec for GenAxis { + type Output = SpecAxis; + + fn to_spec(self, dirs: Gen2<Dir>) -> Self::Output { + match self { + Self::Main => dirs.main.axis(), + Self::Cross => dirs.cross.axis(), + } } } impl Display for GenAxis { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.pad(match self { - Self::Primary => "primary", - Self::Secondary => "secondary", + Self::Main => "main", + Self::Cross => "cross", }) } } @@ -128,19 +241,31 @@ impl Display for GenAxis { /// The two specific layouting axes. #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum SpecAxis { - /// The horizontal layouting axis. - Horizontal, /// The vertical layouting axis. Vertical, + /// The horizontal layouting axis. + Horizontal, } impl SpecAxis { - /// The generic version of this axis in the given layout system. - pub fn to_gen(self, sys: LayoutSystem) -> GenAxis { - if self == sys.primary.axis() { - GenAxis::Primary + /// The other axis. + pub fn other(self) -> Self { + match self { + Self::Horizontal => Self::Vertical, + Self::Vertical => Self::Horizontal, + } + } +} + +impl ToGen for SpecAxis { + type Output = GenAxis; + + fn to_gen(self, dirs: Gen2<Dir>) -> Self::Output { + if self == dirs.main.axis() { + GenAxis::Main } else { - GenAxis::Secondary + debug_assert_eq!(self, dirs.cross.axis()); + GenAxis::Cross } } } @@ -148,8 +273,8 @@ impl SpecAxis { impl Display for SpecAxis { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.pad(match self { - Self::Horizontal => "horizontal", Self::Vertical => "vertical", + Self::Horizontal => "horizontal", }) } } @@ -173,6 +298,12 @@ impl GenAlign { } } +impl Default for GenAlign { + fn default() -> Self { + Self::Start + } +} + impl Display for GenAlign { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.pad(match self { @@ -207,21 +338,36 @@ impl SpecAlign { } } - /// The generic version of this alignment in the given layout system. - pub fn to_gen(self, sys: LayoutSystem) -> GenAlign { - let get = |spec: SpecAxis, positive: GenAlign| { - if sys.get(spec.to_gen(sys)).is_positive() { - positive + /// The inverse alignment. + pub fn inv(self) -> Self { + match self { + Self::Left => Self::Right, + Self::Right => Self::Left, + Self::Top => Self::Bottom, + Self::Bottom => Self::Top, + Self::Center => Self::Center, + } + } +} + +impl ToGen for SpecAlign { + type Output = GenAlign; + + fn to_gen(self, dirs: Gen2<Dir>) -> Self::Output { + let dirs = dirs.to_spec(dirs); + let get = |dir: Dir, at_positive_start| { + if dir.is_positive() == at_positive_start { + GenAlign::Start } else { - positive.inv() + GenAlign::End } }; match self { - Self::Left => get(SpecAxis::Horizontal, GenAlign::Start), - Self::Right => get(SpecAxis::Horizontal, GenAlign::End), - Self::Top => get(SpecAxis::Vertical, GenAlign::Start), - Self::Bottom => get(SpecAxis::Vertical, GenAlign::End), + Self::Left => get(dirs.horizontal, true), + Self::Right => get(dirs.horizontal, false), + Self::Top => get(dirs.vertical, true), + Self::Bottom => get(dirs.vertical, false), Self::Center => GenAlign::Center, } } @@ -239,91 +385,6 @@ impl Display for SpecAlign { } } -/// A side of a container. -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub enum Side { - Left, - Top, - Right, - Bottom, -} - -impl Side { - /// The opposite side. - pub fn inv(self) -> Self { - match self { - Self::Left => Self::Right, - Self::Top => Self::Bottom, - Self::Right => Self::Left, - Self::Bottom => Self::Top, - } - } -} - -/// A generic container with two components for the two generic axes. -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)] -pub struct Gen2<T> { - /// The primary component. - pub primary: T, - /// The secondary component. - pub secondary: T, -} - -impl<T> Gen2<T> { - /// Create a new instance from the two components. - pub fn new(primary: T, secondary: T) -> Self { - Self { primary, secondary } - } - - /// Return the component for the specified generic axis. - pub fn get(self, axis: GenAxis) -> T { - match axis { - GenAxis::Primary => self.primary, - GenAxis::Secondary => self.secondary, - } - } - - /// Borrow the component for the specified generic axis mutably. - pub fn get_mut(&mut self, axis: GenAxis) -> &mut T { - match axis { - GenAxis::Primary => &mut self.primary, - GenAxis::Secondary => &mut self.secondary, - } - } -} - -/// A generic container with two components for the two specific axes. -#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)] -pub struct Spec2<T> { - /// The horizontal component. - pub horizontal: T, - /// The vertical component. - pub vertical: T, -} - -impl<T> Spec2<T> { - /// Create a new instance from the two components. - pub fn new(horizontal: T, vertical: T) -> Self { - Self { horizontal, vertical } - } - - /// Return the component for the given specific axis. - pub fn get(self, axis: SpecAxis) -> T { - match axis { - SpecAxis::Horizontal => self.horizontal, - SpecAxis::Vertical => self.vertical, - } - } - - /// Borrow the component for the given specific axis mutably. - pub fn get_mut(&mut self, axis: SpecAxis) -> &mut T { - match axis { - SpecAxis::Horizontal => &mut self.horizontal, - SpecAxis::Vertical => &mut self.vertical, - } - } -} - /// A generic container with left, top, right and bottom components. #[derive(Debug, Default, Copy, Clone, Eq, PartialEq)] pub struct Sides<T> { @@ -360,8 +421,8 @@ impl<T> Sides<T> { pub fn get(self, side: Side) -> T { match side { Side::Left => self.left, - Side::Right => self.right, Side::Top => self.top, + Side::Right => self.right, Side::Bottom => self.bottom, } } @@ -370,9 +431,30 @@ impl<T> Sides<T> { pub fn get_mut(&mut self, side: Side) -> &mut T { match side { Side::Left => &mut self.left, - Side::Right => &mut self.right, Side::Top => &mut self.top, + Side::Right => &mut self.right, Side::Bottom => &mut self.bottom, } } } + +/// A side of a container. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum Side { + Left, + Top, + Right, + Bottom, +} + +impl Side { + /// The opposite side. + pub fn inv(self) -> Self { + match self { + Self::Left => Self::Right, + Self::Top => Self::Bottom, + Self::Right => Self::Left, + Self::Bottom => Self::Top, + } + } +} |
