typst_library/layout/dir.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
use ecow::EcoString;
use crate::foundations::{func, scope, ty, Repr};
use crate::layout::{Axis, Side};
/// The four directions into which content can be laid out.
///
/// Possible values are:
/// - `{ltr}`: Left to right.
/// - `{rtl}`: Right to left.
/// - `{ttb}`: Top to bottom.
/// - `{btt}`: Bottom to top.
///
/// These values are available globally and
/// also in the direction type's scope, so you can write either of the following
/// two:
/// ```example
/// #stack(dir: rtl)[A][B][C]
/// #stack(dir: direction.rtl)[A][B][C]
/// ```
#[ty(scope, name = "direction")]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum Dir {
/// Left to right.
LTR,
/// Right to left.
RTL,
/// Top to bottom.
TTB,
/// Bottom to top.
BTT,
}
impl Dir {
/// Whether this direction points into the positive coordinate direction.
///
/// The positive directions are left-to-right and top-to-bottom.
pub const fn is_positive(self) -> bool {
match self {
Self::LTR | Self::TTB => true,
Self::RTL | Self::BTT => false,
}
}
}
#[scope]
impl Dir {
pub const LTR: Self = Self::LTR;
pub const RTL: Self = Self::RTL;
pub const TTB: Self = Self::TTB;
pub const BTT: Self = Self::BTT;
/// The axis this direction belongs to, either `{"horizontal"}` or
/// `{"vertical"}`.
///
/// ```example
/// #ltr.axis() \
/// #ttb.axis()
/// ```
#[func]
pub const fn axis(self) -> Axis {
match self {
Self::LTR | Self::RTL => Axis::X,
Self::TTB | Self::BTT => Axis::Y,
}
}
/// The start point of this direction, as an alignment.
///
/// ```example
/// #ltr.start() \
/// #rtl.start() \
/// #ttb.start() \
/// #btt.start()
/// ```
#[func]
pub const fn start(self) -> Side {
match self {
Self::LTR => Side::Left,
Self::RTL => Side::Right,
Self::TTB => Side::Top,
Self::BTT => Side::Bottom,
}
}
/// The end point of this direction, as an alignment.
///
/// ```example
/// #ltr.end() \
/// #rtl.end() \
/// #ttb.end() \
/// #btt.end()
/// ```
#[func]
pub const fn end(self) -> Side {
match self {
Self::LTR => Side::Right,
Self::RTL => Side::Left,
Self::TTB => Side::Bottom,
Self::BTT => Side::Top,
}
}
/// The inverse direction.
///
/// ```example
/// #ltr.inv() \
/// #rtl.inv() \
/// #ttb.inv() \
/// #btt.inv()
/// ```
#[func(title = "Inverse")]
pub const fn inv(self) -> Dir {
match self {
Self::LTR => Self::RTL,
Self::RTL => Self::LTR,
Self::TTB => Self::BTT,
Self::BTT => Self::TTB,
}
}
}
impl Repr for Dir {
fn repr(&self) -> EcoString {
match self {
Self::LTR => "ltr".into(),
Self::RTL => "rtl".into(),
Self::TTB => "ttb".into(),
Self::BTT => "btt".into(),
}
}
}