mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Refine and rename layouting types 🛀
This commit is contained in:
parent
ff107cf3e7
commit
f549914ff8
@ -12,13 +12,7 @@ mod macros;
|
|||||||
/// Useful imports for creating your own functions.
|
/// Useful imports for creating your own functions.
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::func::{Scope, ParseFunc, LayoutFunc, Command, Commands};
|
pub use crate::func::{Scope, ParseFunc, LayoutFunc, Command, Commands};
|
||||||
pub use crate::layout::{
|
pub use crate::layout::prelude::*;
|
||||||
layout_tree, Layout, MultiLayout,
|
|
||||||
LayoutContext, LayoutSpace, LayoutSpaces, LayoutExpansion,
|
|
||||||
LayoutAxes, Axis, GenericAxisKind, SpecificAxisKind,
|
|
||||||
LayoutAlignment, Alignment,
|
|
||||||
SpacingKind, LayoutResult,
|
|
||||||
};
|
|
||||||
pub use crate::syntax::{
|
pub use crate::syntax::{
|
||||||
parse, ParseContext, ParseResult,
|
parse, ParseContext, ParseResult,
|
||||||
SyntaxTree, FuncCall, FuncArgs, PosArg, KeyArg,
|
SyntaxTree, FuncCall, FuncArgs, PosArg, KeyArg,
|
||||||
@ -107,7 +101,7 @@ pub enum Command<'a> {
|
|||||||
|
|
||||||
Add(Layout),
|
Add(Layout),
|
||||||
AddMultiple(MultiLayout),
|
AddMultiple(MultiLayout),
|
||||||
AddSpacing(Size, SpacingKind, GenericAxisKind),
|
AddSpacing(Size, SpacingKind, GenericAxis),
|
||||||
|
|
||||||
FinishLine,
|
FinishLine,
|
||||||
FinishRun,
|
FinishRun,
|
||||||
@ -149,13 +143,13 @@ impl Scope {
|
|||||||
/// Associate the given name with a type that is parseable into a function.
|
/// Associate the given name with a type that is parseable into a function.
|
||||||
pub fn add<F>(&mut self, name: &str)
|
pub fn add<F>(&mut self, name: &str)
|
||||||
where F: ParseFunc<Meta=()> + LayoutFunc + 'static {
|
where F: ParseFunc<Meta=()> + LayoutFunc + 'static {
|
||||||
self.add_with_metadata::<F, ()>(name, ());
|
self.add_with_metadata::<F>(name, ());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a parseable type with additional metadata that is given to the
|
/// Add a parseable type with additional metadata that is given to the
|
||||||
/// parser (other than the default of `()`).
|
/// parser (other than the default of `()`).
|
||||||
pub fn add_with_metadata<F, T>(&mut self, name: &str, metadata: T)
|
pub fn add_with_metadata<F>(&mut self, name: &str, metadata: <F as ParseFunc>::Meta)
|
||||||
where F: ParseFunc<Meta=T> + LayoutFunc + 'static, T: 'static + Clone {
|
where F: ParseFunc + LayoutFunc + 'static {
|
||||||
self.parsers.insert(
|
self.parsers.insert(
|
||||||
name.to_owned(),
|
name.to_owned(),
|
||||||
Box::new(move |a, b, c| {
|
Box::new(move |a, b, c| {
|
||||||
|
@ -13,6 +13,20 @@ mod flex;
|
|||||||
mod stack;
|
mod stack;
|
||||||
mod text;
|
mod text;
|
||||||
|
|
||||||
|
/// Common types for layouting.
|
||||||
|
pub mod prelude {
|
||||||
|
pub use super::{
|
||||||
|
layout_tree, LayoutResult,
|
||||||
|
MultiLayout, Layout, LayoutContext, LayoutSpaces, LayoutSpace,
|
||||||
|
LayoutExpansion, LayoutAxes, GenericAxis, SpecificAxis, Direction,
|
||||||
|
LayoutAlignment, Alignment, SpacingKind,
|
||||||
|
};
|
||||||
|
pub use GenericAxis::*;
|
||||||
|
pub use SpecificAxis::*;
|
||||||
|
pub use Direction::*;
|
||||||
|
pub use Alignment::*;
|
||||||
|
}
|
||||||
|
|
||||||
/// Different kinds of layouters (fully re-exported).
|
/// Different kinds of layouters (fully re-exported).
|
||||||
pub mod layouters {
|
pub mod layouters {
|
||||||
pub use super::tree::layout_tree;
|
pub use super::tree::layout_tree;
|
||||||
@ -23,6 +37,7 @@ pub mod layouters {
|
|||||||
|
|
||||||
pub use self::actions::{LayoutAction, LayoutActions};
|
pub use self::actions::{LayoutAction, LayoutActions};
|
||||||
pub use self::layouters::*;
|
pub use self::layouters::*;
|
||||||
|
pub use self::prelude::*;
|
||||||
|
|
||||||
/// The result type for layouting.
|
/// The result type for layouting.
|
||||||
pub type LayoutResult<T> = crate::TypesetResult<T>;
|
pub type LayoutResult<T> = crate::TypesetResult<T>;
|
||||||
@ -56,6 +71,34 @@ impl Layout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Layout components that can be serialized.
|
||||||
|
pub trait Serialize {
|
||||||
|
/// Serialize the data structure into an output writable.
|
||||||
|
fn serialize<W: Write>(&self, f: &mut W) -> io::Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for Layout {
|
||||||
|
fn serialize<W: Write>(&self, f: &mut W) -> io::Result<()> {
|
||||||
|
writeln!(f, "{:.4} {:.4}", self.dimensions.x.to_pt(), self.dimensions.y.to_pt())?;
|
||||||
|
writeln!(f, "{}", self.actions.len())?;
|
||||||
|
for action in &self.actions {
|
||||||
|
action.serialize(f)?;
|
||||||
|
writeln!(f)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for MultiLayout {
|
||||||
|
fn serialize<W: Write>(&self, f: &mut W) -> io::Result<()> {
|
||||||
|
writeln!(f, "{}", self.len())?;
|
||||||
|
for layout in self {
|
||||||
|
layout.serialize(f)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The general context for layouting.
|
/// The general context for layouting.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct LayoutContext<'a, 'p> {
|
pub struct LayoutContext<'a, 'p> {
|
||||||
@ -66,12 +109,16 @@ pub struct LayoutContext<'a, 'p> {
|
|||||||
pub style: &'a LayoutStyle,
|
pub style: &'a LayoutStyle,
|
||||||
/// The spaces to layout in.
|
/// The spaces to layout in.
|
||||||
pub spaces: LayoutSpaces,
|
pub spaces: LayoutSpaces,
|
||||||
|
/// Whether to repeat the last space or quit with an error if more space
|
||||||
|
/// would be needed.
|
||||||
|
pub repeat: bool,
|
||||||
/// The initial axes along which content is laid out.
|
/// The initial axes along which content is laid out.
|
||||||
pub axes: LayoutAxes,
|
pub axes: LayoutAxes,
|
||||||
/// The alignment of the finished layout.
|
/// The alignment of the finished layout.
|
||||||
pub alignment: LayoutAlignment,
|
pub alignment: LayoutAlignment,
|
||||||
/// Whether this layouting process handles the top-level pages.
|
/// Whether the layout that is to be created will be nested in a parent
|
||||||
pub top_level: bool,
|
/// container.
|
||||||
|
pub nested: bool,
|
||||||
/// Whether to debug render a box around the layout.
|
/// Whether to debug render a box around the layout.
|
||||||
pub debug: bool,
|
pub debug: bool,
|
||||||
}
|
}
|
||||||
@ -89,7 +136,7 @@ pub struct LayoutSpace {
|
|||||||
/// Whether to expand the dimensions of the resulting layout to the full
|
/// 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
|
/// dimensions of this space or to shrink them to fit the content for the
|
||||||
/// horizontal and vertical axis.
|
/// horizontal and vertical axis.
|
||||||
pub expand: LayoutExpansion,
|
pub expansion: LayoutExpansion,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutSpace {
|
impl LayoutSpace {
|
||||||
@ -109,7 +156,7 @@ impl LayoutSpace {
|
|||||||
LayoutSpace {
|
LayoutSpace {
|
||||||
dimensions: self.usable(),
|
dimensions: self.usable(),
|
||||||
padding: SizeBox::ZERO,
|
padding: SizeBox::ZERO,
|
||||||
expand: LayoutExpansion::new(false, false),
|
expansion: LayoutExpansion::new(false, false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,195 +177,125 @@ impl LayoutExpansion {
|
|||||||
/// The axes along which the content is laid out.
|
/// The axes along which the content is laid out.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct LayoutAxes {
|
pub struct LayoutAxes {
|
||||||
pub primary: Axis,
|
pub primary: Direction,
|
||||||
pub secondary: Axis,
|
pub secondary: Direction,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutAxes {
|
impl LayoutAxes {
|
||||||
pub fn new(primary: Axis, secondary: Axis) -> LayoutAxes {
|
pub fn new(primary: Direction, secondary: Direction) -> LayoutAxes {
|
||||||
if primary.is_horizontal() == secondary.is_horizontal() {
|
if primary.axis() == secondary.axis() {
|
||||||
panic!("LayoutAxes::new: invalid parallel axes {:?} and {:?}", primary, secondary);
|
panic!("LayoutAxes::new: invalid aligned axes {:?} and {:?}",
|
||||||
|
primary, secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
LayoutAxes { primary, secondary }
|
LayoutAxes { primary, secondary }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the specified generic axis.
|
/// Return the direction of the specified generic axis.
|
||||||
pub fn generic(&self, axis: GenericAxisKind) -> Axis {
|
pub fn get_generic(self, axis: GenericAxis) -> Direction {
|
||||||
match axis {
|
match axis {
|
||||||
GenericAxisKind::Primary => self.primary,
|
Primary => self.primary,
|
||||||
GenericAxisKind::Secondary => self.secondary,
|
Secondary => self.secondary,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the specified specific axis.
|
/// Return the direction of the specified specific axis.
|
||||||
pub fn specific(&self, axis: SpecificAxisKind) -> Axis {
|
pub fn get_specific(self, axis: SpecificAxis) -> Direction {
|
||||||
self.generic(axis.generic(*self))
|
self.get_generic(axis.to_generic(self))
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the generic axis kind which is the horizontal axis.
|
|
||||||
pub fn horizontal(&self) -> GenericAxisKind {
|
|
||||||
match self.primary.is_horizontal() {
|
|
||||||
true => GenericAxisKind::Primary,
|
|
||||||
false => GenericAxisKind::Secondary,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the generic axis kind which is the vertical axis.
|
|
||||||
pub fn vertical(&self) -> GenericAxisKind {
|
|
||||||
self.horizontal().inv()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the specific axis kind which is the primary axis.
|
|
||||||
pub fn primary(&self) -> SpecificAxisKind {
|
|
||||||
match self.primary.is_horizontal() {
|
|
||||||
true => SpecificAxisKind::Horizontal,
|
|
||||||
false => SpecificAxisKind::Vertical,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the specific axis kind which is the secondary axis.
|
|
||||||
pub fn secondary(&self) -> SpecificAxisKind {
|
|
||||||
self.primary().inv()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the generic alignment corresponding to left-alignment.
|
|
||||||
pub fn left(&self) -> Alignment {
|
|
||||||
let positive = match self.primary.is_horizontal() {
|
|
||||||
true => self.primary.is_positive(),
|
|
||||||
false => self.secondary.is_positive(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if positive { Alignment::Origin } else { Alignment::End }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the generic alignment corresponding to right-alignment.
|
|
||||||
pub fn right(&self) -> Alignment {
|
|
||||||
self.left().inv()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the generic alignment corresponding to top-alignment.
|
|
||||||
pub fn top(&self) -> Alignment {
|
|
||||||
let positive = match self.primary.is_horizontal() {
|
|
||||||
true => self.secondary.is_positive(),
|
|
||||||
false => self.primary.is_positive(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if positive { Alignment::Origin } else { Alignment::End }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the generic alignment corresponding to bottom-alignment.
|
|
||||||
pub fn bottom(&self) -> Alignment {
|
|
||||||
self.top().inv()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LayoutAxes {
|
/// The two generic layouting axes.
|
||||||
fn default() -> LayoutAxes {
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
LayoutAxes {
|
pub enum GenericAxis {
|
||||||
primary: Axis::LeftToRight,
|
Primary,
|
||||||
secondary: Axis::TopToBottom,
|
Secondary,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenericAxis {
|
||||||
|
/// The specific version of this axis in the given system of axes.
|
||||||
|
pub fn to_specific(self, axes: LayoutAxes) -> SpecificAxis {
|
||||||
|
axes.get_generic(self).axis()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The other axis.
|
||||||
|
pub fn inv(self) -> GenericAxis {
|
||||||
|
match self {
|
||||||
|
Primary => Secondary,
|
||||||
|
Secondary => Primary,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The two specific layouting axes.
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
pub enum SpecificAxis {
|
||||||
|
Horizontal,
|
||||||
|
Vertical,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpecificAxis {
|
||||||
|
/// The generic version of this axis in the given system of axes.
|
||||||
|
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Directions along which content is laid out.
|
/// Directions along which content is laid out.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum Axis {
|
pub enum Direction {
|
||||||
LeftToRight,
|
LeftToRight,
|
||||||
RightToLeft,
|
RightToLeft,
|
||||||
TopToBottom,
|
TopToBottom,
|
||||||
BottomToTop,
|
BottomToTop,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Axis {
|
impl Direction {
|
||||||
/// Whether this is a horizontal axis.
|
/// The specific axis this direction belongs to.
|
||||||
pub fn is_horizontal(&self) -> bool {
|
pub fn axis(self) -> SpecificAxis {
|
||||||
match self {
|
match self {
|
||||||
Axis::LeftToRight | Axis::RightToLeft => true,
|
LeftToRight | RightToLeft => Horizontal,
|
||||||
Axis::TopToBottom | Axis::BottomToTop => false,
|
TopToBottom | BottomToTop => Vertical,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this axis points into the positive coordinate direction.
|
/// Whether this axis points into the positive coordinate direction.
|
||||||
pub fn is_positive(&self) -> bool {
|
pub fn is_positive(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Axis::LeftToRight | Axis::TopToBottom => true,
|
LeftToRight | TopToBottom => true,
|
||||||
Axis::RightToLeft | Axis::BottomToTop => false,
|
RightToLeft | BottomToTop => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The inverse axis.
|
/// The inverse axis.
|
||||||
pub fn inv(&self) -> Axis {
|
pub fn inv(self) -> Direction {
|
||||||
match self {
|
match self {
|
||||||
Axis::LeftToRight => Axis::RightToLeft,
|
LeftToRight => RightToLeft,
|
||||||
Axis::RightToLeft => Axis::LeftToRight,
|
RightToLeft => LeftToRight,
|
||||||
Axis::TopToBottom => Axis::BottomToTop,
|
TopToBottom => BottomToTop,
|
||||||
Axis::BottomToTop => Axis::TopToBottom,
|
BottomToTop => TopToBottom,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The direction factor for this axis.
|
/// The factor for this direction.
|
||||||
///
|
///
|
||||||
/// - 1 if the axis is positive.
|
/// - `1` if the direction is positive.
|
||||||
/// - -1 if the axis is negative.
|
/// - `-1` if the direction is negative.
|
||||||
pub fn factor(&self) -> i32 {
|
pub fn factor(self) -> i32 {
|
||||||
if self.is_positive() { 1 } else { -1 }
|
if self.is_positive() { 1 } else { -1 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The two generic kinds of layouting axes.
|
/// Where to align a layout in a container.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum GenericAxisKind {
|
|
||||||
Primary,
|
|
||||||
Secondary,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GenericAxisKind {
|
|
||||||
/// The specific version of this axis in the given system of axes.
|
|
||||||
pub fn specific(&self, axes: LayoutAxes) -> SpecificAxisKind {
|
|
||||||
match self {
|
|
||||||
GenericAxisKind::Primary => axes.primary(),
|
|
||||||
GenericAxisKind::Secondary => axes.secondary(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The other axis.
|
|
||||||
pub fn inv(&self) -> GenericAxisKind {
|
|
||||||
match self {
|
|
||||||
GenericAxisKind::Primary => GenericAxisKind::Secondary,
|
|
||||||
GenericAxisKind::Secondary => GenericAxisKind::Primary,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The two specific kinds of layouting axes.
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub enum SpecificAxisKind {
|
|
||||||
Horizontal,
|
|
||||||
Vertical,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SpecificAxisKind {
|
|
||||||
/// The generic version of this axis in the given system of axes.
|
|
||||||
pub fn generic(&self, axes: LayoutAxes) -> GenericAxisKind {
|
|
||||||
match self {
|
|
||||||
SpecificAxisKind::Horizontal => axes.horizontal(),
|
|
||||||
SpecificAxisKind::Vertical => axes.vertical(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The other axis.
|
|
||||||
pub fn inv(&self) -> SpecificAxisKind {
|
|
||||||
match self {
|
|
||||||
SpecificAxisKind::Horizontal => SpecificAxisKind::Vertical,
|
|
||||||
SpecificAxisKind::Vertical => SpecificAxisKind::Horizontal,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The place to put a layout in a container.
|
|
||||||
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
||||||
pub struct LayoutAlignment {
|
pub struct LayoutAlignment {
|
||||||
pub primary: Alignment,
|
pub primary: Alignment,
|
||||||
pub secondary: Alignment,
|
pub secondary: Alignment,
|
||||||
@ -328,6 +305,14 @@ impl LayoutAlignment {
|
|||||||
pub fn new(primary: Alignment, secondary: Alignment) -> LayoutAlignment {
|
pub fn new(primary: Alignment, secondary: Alignment) -> LayoutAlignment {
|
||||||
LayoutAlignment { primary, secondary }
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Where to align content.
|
/// Where to align content.
|
||||||
@ -340,21 +325,15 @@ pub enum Alignment {
|
|||||||
|
|
||||||
impl Alignment {
|
impl Alignment {
|
||||||
/// The inverse alignment.
|
/// The inverse alignment.
|
||||||
pub fn inv(&self) -> Alignment {
|
pub fn inv(self) -> Alignment {
|
||||||
match self {
|
match self {
|
||||||
Alignment::Origin => Alignment::End,
|
Origin => End,
|
||||||
Alignment::Center => Alignment::Center,
|
Center => Center,
|
||||||
Alignment::End => Alignment::Origin,
|
End => Origin,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Alignment {
|
|
||||||
fn default() -> Alignment {
|
|
||||||
Alignment::Origin
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whitespace between boxes with different interaction properties.
|
/// Whitespace between boxes with different interaction properties.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum SpacingKind {
|
pub enum SpacingKind {
|
||||||
@ -380,38 +359,10 @@ enum LastSpacing {
|
|||||||
|
|
||||||
impl LastSpacing {
|
impl LastSpacing {
|
||||||
/// The size of the soft space if this is a soft space or zero otherwise.
|
/// The size of the soft space if this is a soft space or zero otherwise.
|
||||||
fn soft_or_zero(&self) -> Size {
|
fn soft_or_zero(self) -> Size {
|
||||||
match self {
|
match self {
|
||||||
LastSpacing::Soft(space, _) => *space,
|
LastSpacing::Soft(space, _) => space,
|
||||||
_ => Size::ZERO,
|
_ => Size::ZERO,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Layout components that can be serialized.
|
|
||||||
pub trait Serialize {
|
|
||||||
/// Serialize the data structure into an output writable.
|
|
||||||
fn serialize<W: Write>(&self, f: &mut W) -> io::Result<()>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for Layout {
|
|
||||||
fn serialize<W: Write>(&self, f: &mut W) -> io::Result<()> {
|
|
||||||
writeln!(f, "{:.4} {:.4}", self.dimensions.x.to_pt(), self.dimensions.y.to_pt())?;
|
|
||||||
writeln!(f, "{}", self.actions.len())?;
|
|
||||||
for action in &self.actions {
|
|
||||||
action.serialize(f)?;
|
|
||||||
writeln!(f)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for MultiLayout {
|
|
||||||
fn serialize<W: Write>(&self, f: &mut W) -> io::Result<()> {
|
|
||||||
writeln!(f, "{}", self.len())?;
|
|
||||||
for layout in self {
|
|
||||||
layout.serialize(f)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -125,13 +125,13 @@ impl StackLayouter {
|
|||||||
// A hard space is simply an empty box.
|
// A hard space is simply an empty box.
|
||||||
SpacingKind::Hard => {
|
SpacingKind::Hard => {
|
||||||
// Reduce the spacing such that it definitely fits.
|
// Reduce the spacing such that it definitely fits.
|
||||||
spacing.min_eq(self.space.usable.secondary(self.ctx.axes));
|
spacing.min_eq(self.space.usable.get_secondary(self.ctx.axes));
|
||||||
let dimensions = Size2D::with_y(spacing);
|
let dimensions = Size2D::with_y(spacing);
|
||||||
|
|
||||||
self.update_metrics(dimensions);
|
self.update_metrics(dimensions);
|
||||||
self.space.layouts.push((self.ctx.axes, Layout {
|
self.space.layouts.push((self.ctx.axes, Layout {
|
||||||
dimensions: dimensions.specialized(self.ctx.axes),
|
dimensions: dimensions.specialized(self.ctx.axes),
|
||||||
alignment: LayoutAlignment::default(),
|
alignment: LayoutAlignment::new(Origin, Origin),
|
||||||
actions: vec![]
|
actions: vec![]
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -169,9 +169,9 @@ impl StackLayouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the given alignment is still allowed according to the rulers.
|
/// Whether the given alignment is still allowed according to the rulers.
|
||||||
fn alignment_allowed(&mut self, axis: Axis, alignment: Alignment) -> bool {
|
fn alignment_allowed(&mut self, direction: Direction, alignment: Alignment) -> bool {
|
||||||
alignment >= *self.space.rulers.get(axis)
|
alignment >= *self.space.rulers.get(direction)
|
||||||
&& alignment <= self.space.rulers.get(axis.inv()).inv()
|
&& alignment <= self.space.rulers.get(direction.inv()).inv()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the size metrics to reflect that a layout or spacing with the
|
/// Update the size metrics to reflect that a layout or spacing with the
|
||||||
@ -190,7 +190,7 @@ impl StackLayouter {
|
|||||||
|
|
||||||
self.space.size = size.specialized(axes);
|
self.space.size = size.specialized(axes);
|
||||||
self.space.extra = extra.specialized(axes);
|
self.space.extra = extra.specialized(axes);
|
||||||
*self.space.usable.secondary_mut(axes) -= dimensions.y;
|
*self.space.usable.get_secondary_mut(axes) -= dimensions.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change the layouting axes used by this layouter.
|
/// Change the layouting axes used by this layouter.
|
||||||
@ -231,7 +231,7 @@ impl StackLayouter {
|
|||||||
let mut spaces = smallvec![LayoutSpace {
|
let mut spaces = smallvec![LayoutSpace {
|
||||||
dimensions,
|
dimensions,
|
||||||
padding: SizeBox::ZERO,
|
padding: SizeBox::ZERO,
|
||||||
expand: LayoutExpansion::new(false, false),
|
expansion: LayoutExpansion::new(false, false),
|
||||||
}];
|
}];
|
||||||
|
|
||||||
for space in &self.ctx.spaces[self.next_space()..] {
|
for space in &self.ctx.spaces[self.next_space()..] {
|
||||||
@ -243,7 +243,7 @@ impl StackLayouter {
|
|||||||
|
|
||||||
/// The usable size along the primary axis.
|
/// The usable size along the primary axis.
|
||||||
pub fn primary_usable(&self) -> Size {
|
pub fn primary_usable(&self) -> Size {
|
||||||
self.space.usable.primary(self.ctx.axes)
|
self.space.usable.get_primary(self.ctx.axes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the current layout space (not subspace) is empty.
|
/// Whether the current layout space (not subspace) is empty.
|
||||||
@ -274,8 +274,8 @@ impl StackLayouter {
|
|||||||
// expand if necessary.)
|
// expand if necessary.)
|
||||||
|
|
||||||
let usable = space.usable();
|
let usable = space.usable();
|
||||||
if space.expand.horizontal { self.space.size.x = usable.x; }
|
if space.expansion.horizontal { self.space.size.x = usable.x; }
|
||||||
if space.expand.vertical { self.space.size.y = usable.y; }
|
if space.expansion.vertical { self.space.size.y = usable.y; }
|
||||||
|
|
||||||
let dimensions = self.space.size.padded(space.padding);
|
let dimensions = self.space.size.padded(space.padding);
|
||||||
|
|
||||||
@ -304,8 +304,8 @@ impl StackLayouter {
|
|||||||
// layout uses up space from the origin to the end. Thus, it reduces
|
// 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
|
// the usable space for following layouts at it's origin by its
|
||||||
// extent along the secondary axis.
|
// extent along the secondary axis.
|
||||||
*bound.get_mut(*axes, GenericAxisKind::Secondary, Alignment::Origin)
|
*bound.get_mut(*axes, Secondary, Origin)
|
||||||
+= axes.secondary.factor() * layout.dimensions.secondary(*axes);
|
+= axes.secondary.factor() * layout.dimensions.get_secondary(*axes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------ //
|
// ------------------------------------------------------------------ //
|
||||||
@ -315,7 +315,7 @@ impl StackLayouter {
|
|||||||
// The `x` field stores the maximal primary extent in one axis-aligned
|
// The `x` field stores the maximal primary extent in one axis-aligned
|
||||||
// run, while the `y` fields stores the accumulated secondary extent.
|
// run, while the `y` fields stores the accumulated secondary extent.
|
||||||
let mut extent = Size2D::ZERO;
|
let mut extent = Size2D::ZERO;
|
||||||
let mut rotated = false;
|
let mut rotation = Vertical;
|
||||||
|
|
||||||
for (bound, entry) in bounds.iter_mut().zip(&self.space.layouts).rev() {
|
for (bound, entry) in bounds.iter_mut().zip(&self.space.layouts).rev() {
|
||||||
let (axes, layout) = entry;
|
let (axes, layout) = entry;
|
||||||
@ -324,17 +324,16 @@ impl StackLayouter {
|
|||||||
// (`extent.x`) dictates how much secondary extent the whole run
|
// (`extent.x`) dictates how much secondary extent the whole run
|
||||||
// had. This value is thus stored in `extent.y`. The primary extent
|
// had. This value is thus stored in `extent.y`. The primary extent
|
||||||
// is reset for this new axis-aligned run.
|
// is reset for this new axis-aligned run.
|
||||||
let is_horizontal = axes.secondary.is_horizontal();
|
if rotation != axes.secondary.axis() {
|
||||||
if is_horizontal != rotated {
|
|
||||||
extent.y = extent.x;
|
extent.y = extent.x;
|
||||||
extent.x = Size::ZERO;
|
extent.x = Size::ZERO;
|
||||||
rotated = is_horizontal;
|
rotation = axes.secondary.axis();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We reduce the bounding box of this layout at it's end by the
|
// 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,
|
// accumulated secondary extent of all layouts we have seen so far,
|
||||||
// which are the layouts after this one since we iterate reversed.
|
// which are the layouts after this one since we iterate reversed.
|
||||||
*bound.get_mut(*axes, GenericAxisKind::Secondary, Alignment::End)
|
*bound.get_mut(*axes, Secondary, End)
|
||||||
-= axes.secondary.factor() * extent.y;
|
-= axes.secondary.factor() * extent.y;
|
||||||
|
|
||||||
// Then, we add this layout's secondary extent to the accumulator.
|
// Then, we add this layout's secondary extent to the accumulator.
|
||||||
@ -404,10 +403,10 @@ impl Space {
|
|||||||
usable,
|
usable,
|
||||||
extra: Size2D::ZERO,
|
extra: Size2D::ZERO,
|
||||||
rulers: Rulers {
|
rulers: Rulers {
|
||||||
top: Alignment::Origin,
|
top: Origin,
|
||||||
bottom: Alignment::Origin,
|
bottom: Origin,
|
||||||
left: Alignment::Origin,
|
left: Origin,
|
||||||
right: Alignment::Origin,
|
right: Origin,
|
||||||
},
|
},
|
||||||
last_spacing: LastSpacing::Hard,
|
last_spacing: LastSpacing::Hard,
|
||||||
}
|
}
|
||||||
@ -415,12 +414,12 @@ impl Space {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Rulers {
|
impl Rulers {
|
||||||
fn get(&mut self, axis: Axis) -> &mut Alignment {
|
fn get(&mut self, direction: Direction) -> &mut Alignment {
|
||||||
match axis {
|
match direction {
|
||||||
Axis::TopToBottom => &mut self.top,
|
TopToBottom => &mut self.top,
|
||||||
Axis::BottomToTop => &mut self.bottom,
|
BottomToTop => &mut self.bottom,
|
||||||
Axis::LeftToRight => &mut self.left,
|
LeftToRight => &mut self.left,
|
||||||
Axis::RightToLeft => &mut self.right,
|
RightToLeft => &mut self.right,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,13 +76,10 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn layout_func(&mut self, func: &FuncCall) -> LayoutResult<()> {
|
fn layout_func(&mut self, func: &FuncCall) -> LayoutResult<()> {
|
||||||
let spaces = self.stack.remaining();
|
|
||||||
|
|
||||||
let commands = func.0.layout(LayoutContext {
|
let commands = func.0.layout(LayoutContext {
|
||||||
loader: self.ctx.loader,
|
|
||||||
style: &self.style,
|
style: &self.style,
|
||||||
spaces,
|
spaces: self.stack.remaining(),
|
||||||
top_level: false,
|
nested: true,
|
||||||
debug: true,
|
debug: true,
|
||||||
.. self.ctx
|
.. self.ctx
|
||||||
})?;
|
})?;
|
||||||
@ -103,8 +100,8 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
|
|||||||
Add(layout) => self.stack.add(layout)?,
|
Add(layout) => self.stack.add(layout)?,
|
||||||
AddMultiple(layouts) => self.stack.add_multiple(layouts)?,
|
AddMultiple(layouts) => self.stack.add_multiple(layouts)?,
|
||||||
AddSpacing(space, kind, axis) => match axis {
|
AddSpacing(space, kind, axis) => match axis {
|
||||||
GenericAxisKind::Primary => {},
|
Primary => {},
|
||||||
GenericAxisKind::Secondary => self.stack.add_spacing(space, kind),
|
Secondary => self.stack.add_spacing(space, kind),
|
||||||
}
|
}
|
||||||
|
|
||||||
FinishLine => {},
|
FinishLine => {},
|
||||||
@ -114,8 +111,8 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
|
|||||||
|
|
||||||
SetTextStyle(style) => self.style.text = style,
|
SetTextStyle(style) => self.style.text = style,
|
||||||
SetPageStyle(style) => {
|
SetPageStyle(style) => {
|
||||||
if !self.ctx.top_level {
|
if self.ctx.nested {
|
||||||
error!("the page style cannot only be altered from a top-level context");
|
error!("page style cannot be altered in nested context");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.style.page = style;
|
self.style.page = style;
|
||||||
@ -123,7 +120,7 @@ impl<'a, 'p> TreeLayouter<'a, 'p> {
|
|||||||
LayoutSpace {
|
LayoutSpace {
|
||||||
dimensions: style.dimensions,
|
dimensions: style.dimensions,
|
||||||
padding: style.margins,
|
padding: style.margins,
|
||||||
expand: LayoutExpansion::new(true, true),
|
expansion: LayoutExpansion::new(true, true),
|
||||||
}
|
}
|
||||||
], true);
|
], true);
|
||||||
}
|
}
|
||||||
|
10
src/lib.rs
10
src/lib.rs
@ -91,6 +91,7 @@ impl<'p> Typesetter<'p> {
|
|||||||
|
|
||||||
/// Layout a syntax tree and return the produced layout.
|
/// Layout a syntax tree and return the produced layout.
|
||||||
pub fn layout(&self, tree: &SyntaxTree) -> LayoutResult<MultiLayout> {
|
pub fn layout(&self, tree: &SyntaxTree) -> LayoutResult<MultiLayout> {
|
||||||
|
use crate::layout::prelude::*;
|
||||||
Ok(layout_tree(
|
Ok(layout_tree(
|
||||||
&tree,
|
&tree,
|
||||||
LayoutContext {
|
LayoutContext {
|
||||||
@ -98,12 +99,13 @@ impl<'p> Typesetter<'p> {
|
|||||||
style: &self.style,
|
style: &self.style,
|
||||||
spaces: smallvec![LayoutSpace {
|
spaces: smallvec![LayoutSpace {
|
||||||
dimensions: self.style.page.dimensions,
|
dimensions: self.style.page.dimensions,
|
||||||
expand: LayoutExpansion::new(true, true),
|
|
||||||
padding: self.style.page.margins,
|
padding: self.style.page.margins,
|
||||||
|
expansion: LayoutExpansion::new(true, true),
|
||||||
}],
|
}],
|
||||||
axes: LayoutAxes::default(),
|
repeat: true,
|
||||||
alignment: LayoutAlignment::default(),
|
axes: LayoutAxes::new(LeftToRight, TopToBottom),
|
||||||
top_level: true,
|
alignment: LayoutAlignment::new(Origin, Origin),
|
||||||
|
nested: false,
|
||||||
debug: false,
|
debug: false,
|
||||||
},
|
},
|
||||||
)?)
|
)?)
|
||||||
|
@ -34,20 +34,20 @@ function! {
|
|||||||
|
|
||||||
let map = self.map.dedup(|key, alignment| {
|
let map = self.map.dedup(|key, alignment| {
|
||||||
let axis = match key {
|
let axis = match key {
|
||||||
Key::First => alignment.axis(axes, GenericAxisKind::Primary),
|
Key::First => alignment.axis(axes, Primary),
|
||||||
Key::Second => alignment.axis(axes, GenericAxisKind::Secondary),
|
Key::Second => alignment.axis(axes, Secondary),
|
||||||
Key::Axis(AxisKey::Primary) => GenericAxisKind::Primary,
|
Key::Axis(AxisKey::Primary) => Primary,
|
||||||
Key::Axis(AxisKey::Secondary) => GenericAxisKind::Secondary,
|
Key::Axis(AxisKey::Secondary) => Secondary,
|
||||||
Key::Axis(AxisKey::Horizontal) => axes.horizontal(),
|
Key::Axis(AxisKey::Horizontal) => Horizontal.to_generic(axes),
|
||||||
Key::Axis(AxisKey::Vertical) => axes.vertical(),
|
Key::Axis(AxisKey::Vertical) => Vertical.to_generic(axes),
|
||||||
};
|
};
|
||||||
|
|
||||||
let alignment = alignment.generic(axes, axis)?;
|
let alignment = alignment.to_generic(axes, axis)?;
|
||||||
Ok((axis, alignment))
|
Ok((axis, alignment))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
map.with(GenericAxisKind::Primary, |&val| ctx.alignment.primary = val);
|
map.with(Primary, |&val| ctx.alignment.primary = val);
|
||||||
map.with(GenericAxisKind::Secondary, |&val| ctx.alignment.secondary = val);
|
map.with(Secondary, |&val| ctx.alignment.secondary = val);
|
||||||
|
|
||||||
match &self.body {
|
match &self.body {
|
||||||
Some(body) => vec![AddMultiple(layout_tree(&body, ctx)?)],
|
Some(body) => vec![AddMultiple(layout_tree(&body, ctx)?)],
|
||||||
|
@ -21,15 +21,13 @@ function! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
layout(self, mut ctx) {
|
layout(self, mut ctx) {
|
||||||
use SpecificAxisKind::*;
|
|
||||||
|
|
||||||
ctx.debug = self.debug;
|
ctx.debug = self.debug;
|
||||||
let space = &mut ctx.spaces[0];
|
let space = &mut ctx.spaces[0];
|
||||||
|
|
||||||
self.map.apply_with(ctx.axes, |axis, p| {
|
self.map.apply_with(ctx.axes, |axis, p| {
|
||||||
let entity = match axis {
|
let entity = match axis {
|
||||||
Horizontal => { space.expand.horizontal = true; &mut space.dimensions.x },
|
Horizontal => { space.expansion.horizontal = true; &mut space.dimensions.x },
|
||||||
Vertical => { space.expand.vertical = true; &mut space.dimensions.y },
|
Vertical => { space.expansion.vertical = true; &mut space.dimensions.y },
|
||||||
};
|
};
|
||||||
|
|
||||||
*entity = p.concretize(*entity)
|
*entity = p.concretize(*entity)
|
||||||
|
@ -5,25 +5,25 @@ use super::keys::AxisKey;
|
|||||||
function! {
|
function! {
|
||||||
/// `direction`: Sets the directions of the layouting axes.
|
/// `direction`: Sets the directions of the layouting axes.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct Direction {
|
pub struct DirectionChange {
|
||||||
body: Option<SyntaxTree>,
|
body: Option<SyntaxTree>,
|
||||||
map: ConsistentMap<AxisKey, Axis>,
|
map: ConsistentMap<AxisKey, Direction>,
|
||||||
}
|
}
|
||||||
|
|
||||||
parse(args, body, ctx) {
|
parse(args, body, ctx) {
|
||||||
let mut map = ConsistentMap::new();
|
let mut map = ConsistentMap::new();
|
||||||
|
|
||||||
map.add_opt_span(AxisKey::Primary, args.get_pos_opt::<Axis>()?)?;
|
map.add_opt_span(AxisKey::Primary, args.get_pos_opt::<Direction>()?)?;
|
||||||
map.add_opt_span(AxisKey::Secondary, args.get_pos_opt::<Axis>()?)?;
|
map.add_opt_span(AxisKey::Secondary, args.get_pos_opt::<Direction>()?)?;
|
||||||
|
|
||||||
for arg in args.keys() {
|
for arg in args.keys() {
|
||||||
let axis = AxisKey::from_ident(&arg.v.key)?;
|
let axis = AxisKey::from_ident(&arg.v.key)?;
|
||||||
let value = Axis::from_expr(arg.v.value)?;
|
let value = Direction::from_expr(arg.v.value)?;
|
||||||
|
|
||||||
map.add(axis, value)?;
|
map.add(axis, value)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Direction {
|
DirectionChange {
|
||||||
body: parse!(optional: body, ctx),
|
body: parse!(optional: body, ctx),
|
||||||
map,
|
map,
|
||||||
}
|
}
|
||||||
@ -34,17 +34,17 @@ function! {
|
|||||||
|
|
||||||
let map = self.map.dedup(|key, &direction| {
|
let map = self.map.dedup(|key, &direction| {
|
||||||
Ok((match key {
|
Ok((match key {
|
||||||
AxisKey::Primary => GenericAxisKind::Primary,
|
AxisKey::Primary => Primary,
|
||||||
AxisKey::Secondary => GenericAxisKind::Secondary,
|
AxisKey::Secondary => Secondary,
|
||||||
AxisKey::Horizontal => axes.horizontal(),
|
AxisKey::Horizontal => Horizontal.to_generic(axes),
|
||||||
AxisKey::Vertical => axes.vertical(),
|
AxisKey::Vertical => Vertical.to_generic(axes),
|
||||||
}, direction))
|
}, direction))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
map.with(GenericAxisKind::Primary, |&val| ctx.axes.primary = val);
|
map.with(Primary, |&val| ctx.axes.primary = val);
|
||||||
map.with(GenericAxisKind::Secondary, |&val| ctx.axes.secondary = val);
|
map.with(Secondary, |&val| ctx.axes.secondary = val);
|
||||||
|
|
||||||
if ctx.axes.primary.is_horizontal() == ctx.axes.secondary.is_horizontal() {
|
if ctx.axes.primary.axis() == ctx.axes.secondary.axis() {
|
||||||
error!(
|
error!(
|
||||||
"aligned primary and secondary axes: `{}`, `{}`",
|
"aligned primary and secondary axes: `{}`, `{}`",
|
||||||
format!("{:?}", ctx.axes.primary).to_lowercase(),
|
format!("{:?}", ctx.axes.primary).to_lowercase(),
|
||||||
|
@ -39,33 +39,26 @@ pub enum AxisKey {
|
|||||||
|
|
||||||
impl AxisKey {
|
impl AxisKey {
|
||||||
/// The generic version of this axis key in the given system of axes.
|
/// The generic version of this axis key in the given system of axes.
|
||||||
pub fn generic(&self, axes: LayoutAxes) -> GenericAxisKind {
|
pub fn to_generic(self, axes: LayoutAxes) -> GenericAxis {
|
||||||
match self {
|
match self {
|
||||||
AxisKey::Primary => GenericAxisKind::Primary,
|
AxisKey::Primary => Primary,
|
||||||
AxisKey::Secondary => GenericAxisKind::Secondary,
|
AxisKey::Secondary => Secondary,
|
||||||
AxisKey::Vertical => axes.vertical(),
|
AxisKey::Vertical => Vertical.to_generic(axes),
|
||||||
AxisKey::Horizontal => axes.horizontal(),
|
AxisKey::Horizontal => Horizontal.to_generic(axes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The specific version of this axis key in the given system of axes.
|
/// The specific version of this axis key in the given system of axes.
|
||||||
pub fn specific(&self, axes: LayoutAxes) -> SpecificAxisKind {
|
pub fn to_specific(self, axes: LayoutAxes) -> SpecificAxis {
|
||||||
match self {
|
match self {
|
||||||
AxisKey::Primary => axes.primary(),
|
AxisKey::Primary => Primary.to_specific(axes),
|
||||||
AxisKey::Secondary => axes.secondary(),
|
AxisKey::Secondary => Secondary.to_specific(axes),
|
||||||
AxisKey::Vertical => SpecificAxisKind::Vertical,
|
AxisKey::Vertical => Vertical,
|
||||||
AxisKey::Horizontal => SpecificAxisKind::Horizontal,
|
AxisKey::Horizontal => Horizontal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kind!(AxisKey, "axis",
|
|
||||||
"horizontal" => AxisKey::Horizontal,
|
|
||||||
"vertical" => AxisKey::Vertical,
|
|
||||||
"primary" => AxisKey::Primary,
|
|
||||||
"secondary" => AxisKey::Secondary,
|
|
||||||
);
|
|
||||||
|
|
||||||
/// An argument key which describes a target alignment.
|
/// An argument key which describes a target alignment.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum AlignmentKey {
|
pub enum AlignmentKey {
|
||||||
@ -81,29 +74,35 @@ pub enum AlignmentKey {
|
|||||||
impl AlignmentKey {
|
impl AlignmentKey {
|
||||||
/// The generic axis this alignment key corresopnds to in the given system
|
/// The generic axis this alignment key corresopnds to in the given system
|
||||||
/// of layouting axes. Falls back to `default` if the alignment is generic.
|
/// of layouting axes. Falls back to `default` if the alignment is generic.
|
||||||
pub fn axis(&self, axes: LayoutAxes, default: GenericAxisKind) -> GenericAxisKind {
|
pub fn axis(self, axes: LayoutAxes, default: GenericAxis) -> GenericAxis {
|
||||||
use AlignmentKey::*;
|
use AlignmentKey::*;
|
||||||
match self {
|
match self {
|
||||||
Origin | Center | End => default,
|
Origin | Center | End => default,
|
||||||
Left | Right => axes.horizontal(),
|
Left | Right => Horizontal.to_generic(axes),
|
||||||
Top | Bottom => axes.vertical(),
|
Top | Bottom => Vertical.to_generic(axes),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The generic version of this alignment in the given system of layouting
|
/// The generic version of this alignment in the given system of layouting
|
||||||
/// axes. Returns an error if the alignment is invalid for the given axis.
|
/// axes.
|
||||||
pub fn generic(&self, axes: LayoutAxes, axis: GenericAxisKind) -> LayoutResult<Alignment> {
|
///
|
||||||
use AlignmentKey::*;
|
/// Returns an error if the alignment is invalid for the given axis.
|
||||||
|
pub fn to_generic(self, axes: LayoutAxes, axis: GenericAxis) -> LayoutResult<Alignment> {
|
||||||
|
let specific = axis.to_specific(axes);
|
||||||
|
|
||||||
|
Ok(match (self, specific) {
|
||||||
|
(AlignmentKey::Origin, _) => Origin,
|
||||||
|
(AlignmentKey::Center, _) => Center,
|
||||||
|
(AlignmentKey::End, _) => End,
|
||||||
|
|
||||||
|
(AlignmentKey::Left, Horizontal) | (AlignmentKey::Top, Vertical) => {
|
||||||
|
if axes.get_specific(specific).is_positive() { Origin } else { End }
|
||||||
|
}
|
||||||
|
|
||||||
|
(AlignmentKey::Right, Horizontal) | (AlignmentKey::Bottom, Vertical) => {
|
||||||
|
if axes.get_specific(specific).is_positive() { End } else { Origin }
|
||||||
|
}
|
||||||
|
|
||||||
let horizontal = axis == axes.horizontal();
|
|
||||||
Ok(match self {
|
|
||||||
Origin => Alignment::Origin,
|
|
||||||
Center => Alignment::Center,
|
|
||||||
End => Alignment::End,
|
|
||||||
Left if horizontal => axes.left(),
|
|
||||||
Right if horizontal => axes.right(),
|
|
||||||
Top if !horizontal => axes.top(),
|
|
||||||
Bottom if !horizontal => axes.bottom(),
|
|
||||||
_ => error!(
|
_ => error!(
|
||||||
"invalid alignment `{}` for {} axis",
|
"invalid alignment `{}` for {} axis",
|
||||||
format!("{:?}", self).to_lowercase(),
|
format!("{:?}", self).to_lowercase(),
|
||||||
@ -114,31 +113,20 @@ impl AlignmentKey {
|
|||||||
|
|
||||||
/// The specific version of this alignment in the given system of layouting
|
/// The specific version of this alignment in the given system of layouting
|
||||||
/// axes.
|
/// axes.
|
||||||
pub fn specific(&self, axes: LayoutAxes, axis: SpecificAxisKind) -> AlignmentKey {
|
pub fn to_specific(self, axes: LayoutAxes, axis: SpecificAxis) -> AlignmentKey {
|
||||||
use AlignmentKey::*;
|
use AlignmentKey::*;
|
||||||
use SpecificAxisKind::*;
|
|
||||||
|
|
||||||
let positive = axes.specific(axis).is_positive();
|
let positive = axes.get_specific(axis).is_positive();
|
||||||
match (self, axis, positive) {
|
match (self, axis, positive) {
|
||||||
(Origin, Horizontal, true) | (End, Horizontal, false) => Left,
|
(Origin, Horizontal, true) | (End, Horizontal, false) => Left,
|
||||||
(End, Horizontal, true) | (Origin, Horizontal, false) => Right,
|
(End, Horizontal, true) | (Origin, Horizontal, false) => Right,
|
||||||
(Origin, Vertical, true) | (End, Vertical, false) => Top,
|
(Origin, Vertical, true) | (End, Vertical, false) => Top,
|
||||||
(End, Vertical, true) | (Origin, Vertical, false) => Bottom,
|
(End, Vertical, true) | (Origin, Vertical, false) => Bottom,
|
||||||
_ => *self,
|
_ => self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kind!(AlignmentKey, "alignment",
|
|
||||||
"left" => AlignmentKey::Left,
|
|
||||||
"top" => AlignmentKey::Top,
|
|
||||||
"right" => AlignmentKey::Right,
|
|
||||||
"bottom" => AlignmentKey::Bottom,
|
|
||||||
"origin" => AlignmentKey::Origin,
|
|
||||||
"center" => AlignmentKey::Center,
|
|
||||||
"end" => AlignmentKey::End,
|
|
||||||
);
|
|
||||||
|
|
||||||
/// An argument key which identifies a margin or padding target.
|
/// An argument key which identifies a margin or padding target.
|
||||||
///
|
///
|
||||||
/// A is the used axis type.
|
/// A is the used axis type.
|
||||||
@ -152,30 +140,47 @@ pub enum PaddingKey<A> {
|
|||||||
AxisAligned(A, AlignmentKey),
|
AxisAligned(A, AlignmentKey),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kind!(AxisKey, "axis",
|
||||||
|
"horizontal" | "h" => AxisKey::Horizontal,
|
||||||
|
"vertical" | "v" => AxisKey::Vertical,
|
||||||
|
"primary" | "p" => AxisKey::Primary,
|
||||||
|
"secondary" | "s" => AxisKey::Secondary,
|
||||||
|
);
|
||||||
|
|
||||||
|
kind!(AlignmentKey, "alignment",
|
||||||
|
"left" => AlignmentKey::Left,
|
||||||
|
"top" => AlignmentKey::Top,
|
||||||
|
"right" => AlignmentKey::Right,
|
||||||
|
"bottom" => AlignmentKey::Bottom,
|
||||||
|
"origin" => AlignmentKey::Origin,
|
||||||
|
"center" => AlignmentKey::Center,
|
||||||
|
"end" => AlignmentKey::End,
|
||||||
|
);
|
||||||
|
|
||||||
kind!(PaddingKey<AxisKey>, "axis or side",
|
kind!(PaddingKey<AxisKey>, "axis or side",
|
||||||
"horizontal" => PaddingKey::Axis(AxisKey::Horizontal),
|
"horizontal" | "h" => PaddingKey::Axis(AxisKey::Horizontal),
|
||||||
"vertical" => PaddingKey::Axis(AxisKey::Vertical),
|
"vertical" | "v" => PaddingKey::Axis(AxisKey::Vertical),
|
||||||
"primary" => PaddingKey::Axis(AxisKey::Primary),
|
"primary" | "p" => PaddingKey::Axis(AxisKey::Primary),
|
||||||
"secondary" => PaddingKey::Axis(AxisKey::Secondary),
|
"secondary" | "s" => PaddingKey::Axis(AxisKey::Secondary),
|
||||||
|
|
||||||
"left" => PaddingKey::AxisAligned(AxisKey::Horizontal, AlignmentKey::Left),
|
"left" => PaddingKey::AxisAligned(AxisKey::Horizontal, AlignmentKey::Left),
|
||||||
"right" => PaddingKey::AxisAligned(AxisKey::Horizontal, AlignmentKey::Right),
|
"right" => PaddingKey::AxisAligned(AxisKey::Horizontal, AlignmentKey::Right),
|
||||||
"top" => PaddingKey::AxisAligned(AxisKey::Vertical, AlignmentKey::Top),
|
"top" => PaddingKey::AxisAligned(AxisKey::Vertical, AlignmentKey::Top),
|
||||||
"bottom" => PaddingKey::AxisAligned(AxisKey::Vertical, AlignmentKey::Bottom),
|
"bottom" => PaddingKey::AxisAligned(AxisKey::Vertical, AlignmentKey::Bottom),
|
||||||
|
|
||||||
"primary-origin" => PaddingKey::AxisAligned(AxisKey::Primary, AlignmentKey::Origin),
|
"primary-origin" => PaddingKey::AxisAligned(AxisKey::Primary, AlignmentKey::Origin),
|
||||||
"primary-end" => PaddingKey::AxisAligned(AxisKey::Primary, AlignmentKey::End),
|
"primary-end" => PaddingKey::AxisAligned(AxisKey::Primary, AlignmentKey::End),
|
||||||
"secondary-origin" => PaddingKey::AxisAligned(AxisKey::Secondary, AlignmentKey::Origin),
|
"secondary-origin" => PaddingKey::AxisAligned(AxisKey::Secondary, AlignmentKey::Origin),
|
||||||
"secondary-end" => PaddingKey::AxisAligned(AxisKey::Secondary, AlignmentKey::End),
|
"secondary-end" => PaddingKey::AxisAligned(AxisKey::Secondary, AlignmentKey::End),
|
||||||
"horizontal-origin" => PaddingKey::AxisAligned(AxisKey::Horizontal, AlignmentKey::Origin),
|
"horizontal-origin" => PaddingKey::AxisAligned(AxisKey::Horizontal, AlignmentKey::Origin),
|
||||||
"horizontal-end" => PaddingKey::AxisAligned(AxisKey::Horizontal, AlignmentKey::End),
|
"horizontal-end" => PaddingKey::AxisAligned(AxisKey::Horizontal, AlignmentKey::End),
|
||||||
"vertical-origin" => PaddingKey::AxisAligned(AxisKey::Vertical, AlignmentKey::Origin),
|
"vertical-origin" => PaddingKey::AxisAligned(AxisKey::Vertical, AlignmentKey::Origin),
|
||||||
"vertical-end" => PaddingKey::AxisAligned(AxisKey::Vertical, AlignmentKey::End),
|
"vertical-end" => PaddingKey::AxisAligned(AxisKey::Vertical, AlignmentKey::End),
|
||||||
);
|
);
|
||||||
|
|
||||||
kind!(Axis, "direction",
|
kind!(Direction, "direction",
|
||||||
"ltr" => Axis::LeftToRight,
|
"left-to-right" | "ltr" => LeftToRight,
|
||||||
"rtl" => Axis::RightToLeft,
|
"right-to-left" | "rtl" => RightToLeft,
|
||||||
"ttb" => Axis::TopToBottom,
|
"top-to-bottom" | "ttb" => TopToBottom,
|
||||||
"btt" => Axis::BottomToTop,
|
"bottom-to-top" | "btt" => BottomToTop,
|
||||||
);
|
);
|
||||||
|
@ -84,10 +84,11 @@ impl<E: ExpressionKind + Copy> ExtentMap<E> {
|
|||||||
|
|
||||||
for arg in args.keys() {
|
for arg in args.keys() {
|
||||||
let key = match arg.v.key.v.0.as_str() {
|
let key = match arg.v.key.v.0.as_str() {
|
||||||
"width" | "w" => AxisKey::Horizontal,
|
"width" | "w" => AxisKey::Horizontal,
|
||||||
"height" | "h" => AxisKey::Vertical,
|
"height" | "h" => AxisKey::Vertical,
|
||||||
"primary-size" | "ps" => AxisKey::Primary,
|
"primary-size" | "ps" => AxisKey::Primary,
|
||||||
"secondary-size" | "ss" => AxisKey::Secondary,
|
"secondary-size" | "ss" => AxisKey::Secondary,
|
||||||
|
|
||||||
_ => if enforce {
|
_ => if enforce {
|
||||||
error!("expected dimension")
|
error!("expected dimension")
|
||||||
} else {
|
} else {
|
||||||
@ -111,22 +112,22 @@ impl<E: ExpressionKind + Copy> ExtentMap<E> {
|
|||||||
size: F
|
size: F
|
||||||
) -> LayoutResult<()> where F: Fn(&E) -> Size {
|
) -> LayoutResult<()> where F: Fn(&E) -> Size {
|
||||||
let map = self.dedup(axes)?;
|
let map = self.dedup(axes)?;
|
||||||
map.with(SpecificAxisKind::Horizontal, |val| dimensions.x = size(val));
|
map.with(Horizontal, |val| dimensions.x = size(val));
|
||||||
map.with(SpecificAxisKind::Vertical, |val| dimensions.y = size(val));
|
map.with(Vertical, |val| dimensions.y = size(val));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Map from any axis key to the specific axis kind.
|
/// Map from any axis key to the specific axis kind.
|
||||||
pub fn apply_with<F>(&self, axes: LayoutAxes, mut f: F) -> LayoutResult<()>
|
pub fn apply_with<F>(&self, axes: LayoutAxes, mut f: F) -> LayoutResult<()>
|
||||||
where F: FnMut(SpecificAxisKind, &E) {
|
where F: FnMut(SpecificAxis, &E) {
|
||||||
for (&key, value) in self.dedup(axes)?.iter() {
|
for (&key, value) in self.dedup(axes)?.iter() {
|
||||||
f(key, value);
|
f(key, value);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dedup(&self, axes: LayoutAxes) -> LayoutResult<ConsistentMap<SpecificAxisKind, E>> {
|
fn dedup(&self, axes: LayoutAxes) -> LayoutResult<ConsistentMap<SpecificAxis, E>> {
|
||||||
self.0.dedup(|key, &val| Ok((key.specific(axes), val)))
|
self.0.dedup(|key, &val| Ok((key.to_specific(axes), val)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,17 +166,17 @@ impl PaddingMap {
|
|||||||
let map = self.0.dedup(|key, &val| {
|
let map = self.0.dedup(|key, &val| {
|
||||||
Ok((match key {
|
Ok((match key {
|
||||||
All => All,
|
All => All,
|
||||||
Axis(axis) => Axis(axis.specific(axes)),
|
Axis(axis) => Axis(axis.to_specific(axes)),
|
||||||
AxisAligned(axis, alignment) => {
|
AxisAligned(axis, alignment) => {
|
||||||
let axis = axis.specific(axes);
|
let axis = axis.to_specific(axes);
|
||||||
AxisAligned(axis, alignment.specific(axes, axis))
|
AxisAligned(axis, alignment.to_specific(axes, axis))
|
||||||
}
|
}
|
||||||
}, val))
|
}, val))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
map.with(All, |&val| padding.set_all(val));
|
map.with(All, |&val| padding.set_all(val));
|
||||||
map.with(Axis(SpecificAxisKind::Horizontal), |&val| padding.set_horizontal(val));
|
map.with(Axis(Horizontal), |&val| padding.set_horizontal(val));
|
||||||
map.with(Axis(SpecificAxisKind::Vertical), |&val| padding.set_vertical(val));
|
map.with(Axis(Vertical), |&val| padding.set_vertical(val));
|
||||||
|
|
||||||
for (key, &val) in map.iter() {
|
for (key, &val) in map.iter() {
|
||||||
if let AxisAligned(_, alignment) = key {
|
if let AxisAligned(_, alignment) = key {
|
||||||
|
@ -19,7 +19,7 @@ pub fn std() -> Scope {
|
|||||||
|
|
||||||
std.add::<Align>("align");
|
std.add::<Align>("align");
|
||||||
std.add::<Boxed>("box");
|
std.add::<Boxed>("box");
|
||||||
std.add::<Direction>("direction");
|
std.add::<DirectionChange>("direction");
|
||||||
std.add::<PageSize>("page.size");
|
std.add::<PageSize>("page.size");
|
||||||
std.add::<PageMargins>("page.margins");
|
std.add::<PageMargins>("page.margins");
|
||||||
|
|
||||||
@ -30,10 +30,10 @@ pub fn std() -> Scope {
|
|||||||
|
|
||||||
std.add::<FontSize>("font.size");
|
std.add::<FontSize>("font.size");
|
||||||
|
|
||||||
std.add_with_metadata::<Spacing, Option<AxisKey>>("spacing", None);
|
std.add_with_metadata::<Spacing>("spacing", None);
|
||||||
|
|
||||||
for (name, key) in &[("h", AxisKey::Horizontal), ("v", AxisKey::Vertical)] {
|
for (name, key) in &[("h", AxisKey::Horizontal), ("v", AxisKey::Vertical)] {
|
||||||
std.add_with_metadata::<Spacing, Option<AxisKey>>(name, Some(*key));
|
std.add_with_metadata::<Spacing>(name, Some(*key));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, class) in &[
|
for (name, class) in &[
|
||||||
@ -41,7 +41,7 @@ pub fn std() -> Scope {
|
|||||||
("italic", FontClass::Italic),
|
("italic", FontClass::Italic),
|
||||||
("mono", FontClass::Monospace),
|
("mono", FontClass::Monospace),
|
||||||
] {
|
] {
|
||||||
std.add_with_metadata::<StyleChange, FontClass>(name, class.clone());
|
std.add_with_metadata::<StyleChange>(name, class.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
std
|
std
|
||||||
@ -152,7 +152,7 @@ function! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
layout(self, ctx) {
|
layout(self, ctx) {
|
||||||
let axis = self.axis.generic(ctx.axes);
|
let axis = self.axis.to_generic(ctx.axes);
|
||||||
let spacing = self.spacing.concretize(ctx.style.text.font_size);
|
let spacing = self.spacing.concretize(ctx.style.text.font_size);
|
||||||
vec![AddSpacing(spacing, SpacingKind::Hard, axis)]
|
vec![AddSpacing(spacing, SpacingKind::Hard, axis)]
|
||||||
}
|
}
|
||||||
|
46
src/size.rs
46
src/size.rs
@ -5,8 +5,7 @@ use std::iter::Sum;
|
|||||||
use std::ops::*;
|
use std::ops::*;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crate::layout::{LayoutAxes, Axis, GenericAxisKind, LayoutAlignment, Alignment};
|
use crate::layout::prelude::*;
|
||||||
|
|
||||||
|
|
||||||
/// A general spacing type.
|
/// A general spacing type.
|
||||||
#[derive(Copy, Clone, PartialEq, PartialOrd)]
|
#[derive(Copy, Clone, PartialEq, PartialOrd)]
|
||||||
@ -59,11 +58,10 @@ impl Size {
|
|||||||
/// Set this size to the minimum of itself and the other size.
|
/// Set this size to the minimum of itself and the other size.
|
||||||
pub fn min_eq(&mut self, other: Size) { *self = self.min(other); }
|
pub fn min_eq(&mut self, other: Size) { *self = self.min(other); }
|
||||||
|
|
||||||
/// The anchor position along the given axis for an item with the given
|
/// The anchor position along the given direction for an item with the given
|
||||||
/// alignment in a container with this size.
|
/// alignment in a container with this size.
|
||||||
pub fn anchor(self, alignment: Alignment, axis: Axis) -> Size {
|
pub fn anchor(self, alignment: Alignment, direction: Direction) -> Size {
|
||||||
use Alignment::*;
|
match (direction.is_positive(), alignment) {
|
||||||
match (axis.is_positive(), alignment) {
|
|
||||||
(true, Origin) | (false, End) => Size::ZERO,
|
(true, Origin) | (false, End) => Size::ZERO,
|
||||||
(_, Center) => self / 2,
|
(_, Center) => self / 2,
|
||||||
(true, End) | (false, Origin) => self,
|
(true, End) | (false, Origin) => self,
|
||||||
@ -120,23 +118,23 @@ impl Size2D {
|
|||||||
pub fn with_all(s: Size) -> Size2D { Size2D { x: s, y: s } }
|
pub fn with_all(s: Size) -> Size2D { Size2D { x: s, y: s } }
|
||||||
|
|
||||||
/// Access the primary size of this specialized 2D-size.
|
/// Access the primary size of this specialized 2D-size.
|
||||||
pub fn primary(self, axes: LayoutAxes) -> Size {
|
pub fn get_primary(self, axes: LayoutAxes) -> Size {
|
||||||
if axes.primary.is_horizontal() { self.x } else { self.y }
|
if axes.primary.axis() == Horizontal { self.x } else { self.y }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the primary size of this specialized 2D-size mutably.
|
/// Access the primary size of this specialized 2D-size mutably.
|
||||||
pub fn primary_mut(&mut self, axes: LayoutAxes) -> &mut Size {
|
pub fn get_primary_mut(&mut self, axes: LayoutAxes) -> &mut Size {
|
||||||
if axes.primary.is_horizontal() { &mut self.x } else { &mut self.y }
|
if axes.primary.axis() == Horizontal { &mut self.x } else { &mut self.y }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the secondary size of this specialized 2D-size.
|
/// Access the secondary size of this specialized 2D-size.
|
||||||
pub fn secondary(self, axes: LayoutAxes) -> Size {
|
pub fn get_secondary(self, axes: LayoutAxes) -> Size {
|
||||||
if axes.primary.is_horizontal() { self.y } else { self.x }
|
if axes.primary.axis() == Horizontal { self.y } else { self.x }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the secondary size of this specialized 2D-size mutably.
|
/// Access the secondary size of this specialized 2D-size mutably.
|
||||||
pub fn secondary_mut(&mut self, axes: LayoutAxes) -> &mut Size {
|
pub fn get_secondary_mut(&mut self, axes: LayoutAxes) -> &mut Size {
|
||||||
if axes.primary.is_horizontal() { &mut self.y } else { &mut self.x }
|
if axes.primary.axis() == Horizontal { &mut self.y } else { &mut self.x }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the generalized version of a `Size2D` dependent on the layouting
|
/// Returns the generalized version of a `Size2D` dependent on the layouting
|
||||||
@ -144,9 +142,9 @@ impl Size2D {
|
|||||||
/// - `x` describes the primary axis instead of the horizontal one.
|
/// - `x` describes the primary axis instead of the horizontal one.
|
||||||
/// - `y` describes the secondary axis instead of the vertical one.
|
/// - `y` describes the secondary axis instead of the vertical one.
|
||||||
pub fn generalized(self, axes: LayoutAxes) -> Size2D {
|
pub fn generalized(self, axes: LayoutAxes) -> Size2D {
|
||||||
match axes.primary.is_horizontal() {
|
match axes.primary.axis() {
|
||||||
true => self,
|
Horizontal => self,
|
||||||
false => Size2D { x: self.y, y: self.x },
|
Vertical => Size2D { x: self.y, y: self.x },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,19 +247,19 @@ impl SizeBox {
|
|||||||
/// alignment.
|
/// alignment.
|
||||||
pub fn get_mut(&mut self,
|
pub fn get_mut(&mut self,
|
||||||
axes: LayoutAxes,
|
axes: LayoutAxes,
|
||||||
axis: GenericAxisKind,
|
axis: GenericAxis,
|
||||||
alignment: Alignment,
|
alignment: Alignment,
|
||||||
) -> &mut Size {
|
) -> &mut Size {
|
||||||
let mut normalized = axes.generic(axis);
|
let mut normalized = axes.get_generic(axis);
|
||||||
if alignment == Alignment::End {
|
if alignment == End {
|
||||||
normalized = normalized.inv();
|
normalized = normalized.inv();
|
||||||
}
|
}
|
||||||
|
|
||||||
match normalized {
|
match normalized {
|
||||||
Axis::LeftToRight => &mut self.left,
|
LeftToRight => &mut self.left,
|
||||||
Axis::RightToLeft => &mut self.right,
|
RightToLeft => &mut self.right,
|
||||||
Axis::TopToBottom => &mut self.top,
|
TopToBottom => &mut self.top,
|
||||||
Axis::BottomToTop => &mut self.bottom,
|
BottomToTop => &mut self.bottom,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user