tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5544Rust 88Markdown 11TOML 91926 Definiciones

⎇ main src/style/flex.rs Rust · 203 líneas · 6.8 KB Historia Quién tocó qué crudo

Add support for parsing Taffy style types from string (#929) 70341c9f6 · Nico Burns ·

1//! Style types for Flexbox layout
2use super::{AlignContent, AlignItems, AlignSelf, CoreStyle, Dimension, JustifyContent, LengthPercentage, Style};
3use crate::geometry::Size;
4
5/// The set of styles required for a Flexbox container
6pub trait FlexboxContainerStyle: CoreStyle {
7    /// Which direction does the main axis flow in?
8    #[inline(always)]
9    fn flex_direction(&self) -> FlexDirection {
10        Style::<Self::CustomIdent>::DEFAULT.flex_direction
11    }
12    /// Should elements wrap, or stay in a single line?
13    #[inline(always)]
14    fn flex_wrap(&self) -> FlexWrap {
15        Style::<Self::CustomIdent>::DEFAULT.flex_wrap
16    }
17
18    /// How large should the gaps between items in a grid or flex container be?
19    #[inline(always)]
20    fn gap(&self) -> Size<LengthPercentage> {
21        Style::<Self::CustomIdent>::DEFAULT.gap
22    }
23
24    // Alignment properties
25
26    /// How should content contained within this item be aligned in the cross/block axis
27    #[inline(always)]
28    fn align_content(&self) -> Option<AlignContent> {
29        Style::<Self::CustomIdent>::DEFAULT.align_content
30    }
31    /// How this node's children aligned in the cross/block axis?
32    #[inline(always)]
33    fn align_items(&self) -> Option<AlignItems> {
34        Style::<Self::CustomIdent>::DEFAULT.align_items
35    }
36    /// How this node's children should be aligned in the inline axis
37    #[inline(always)]
38    fn justify_content(&self) -> Option<JustifyContent> {
39        Style::<Self::CustomIdent>::DEFAULT.justify_content
40    }
41}
42
43/// The set of styles required for a Flexbox item (child of a Flexbox container)
44pub trait FlexboxItemStyle: CoreStyle {
45    /// Sets the initial main axis size of the item
46    #[inline(always)]
47    fn flex_basis(&self) -> Dimension {
48        Style::<Self::CustomIdent>::DEFAULT.flex_basis
49    }
50    /// The relative rate at which this item grows when it is expanding to fill space
51    #[inline(always)]
52    fn flex_grow(&self) -> f32 {
53        Style::<Self::CustomIdent>::DEFAULT.flex_grow
54    }
55    /// The relative rate at which this item shrinks when it is contracting to fit into space
56    #[inline(always)]
57    fn flex_shrink(&self) -> f32 {
58        Style::<Self::CustomIdent>::DEFAULT.flex_shrink
59    }
60
61    /// How this node should be aligned in the cross/block axis
62    /// Falls back to the parents [`AlignItems`] if not set
63    #[inline(always)]
64    fn align_self(&self) -> Option<AlignSelf> {
65        Style::<Self::CustomIdent>::DEFAULT.align_self
66    }
67}
68
69use crate::geometry::AbsoluteAxis;
70
71/// Controls whether flex items are forced onto one line or can wrap onto multiple lines.
72///
73/// Defaults to [`FlexWrap::NoWrap`]
74///
75/// [Specification](https://www.w3.org/TR/css-flexbox-1/#flex-wrap-property)
76#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
77#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
78pub enum FlexWrap {
79    /// Items will not wrap and stay on a single line
80    #[default]
81    NoWrap,
82    /// Items will wrap according to this item's [`FlexDirection`]
83    Wrap,
84    /// Items will wrap in the opposite direction to this item's [`FlexDirection`]
85    WrapReverse,
86}
87
88#[cfg(feature = "parse")]
89crate::util::parse::impl_parse_for_keyword_enum!(FlexWrap,
90    "nowrap" => NoWrap,
91    "wrap" => Wrap,
92    "wrap-reverse" => WrapReverse,
93);
94
95/// The direction of the flexbox layout main axis.
96///
97/// There are always two perpendicular layout axes: main (or primary) and cross (or secondary).
98/// Adding items will cause them to be positioned adjacent to each other along the main axis.
99/// By varying this value throughout your tree, you can create complex axis-aligned layouts.
100///
101/// Items are always aligned relative to the cross axis, and justified relative to the main axis.
102///
103/// The default behavior is [`FlexDirection::Row`].
104///
105/// [Specification](https://www.w3.org/TR/css-flexbox-1/#flex-direction-property)
106#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
107#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
108pub enum FlexDirection {
109    /// Defines +x as the main axis
110    ///
111    /// Items will be added from left to right in a row.
112    #[default]
113    Row,
114    /// Defines +y as the main axis
115    ///
116    /// Items will be added from top to bottom in a column.
117    Column,
118    /// Defines -x as the main axis
119    ///
120    /// Items will be added from right to left in a row.
121    RowReverse,
122    /// Defines -y as the main axis
123    ///
124    /// Items will be added from bottom to top in a column.
125    ColumnReverse,
126}
127
128#[cfg(feature = "parse")]
129crate::util::parse::impl_parse_for_keyword_enum!(FlexDirection,
130    "row" => Row,
131    "column" => Column,
132    "row-reverse" => RowReverse,
133    "column-reverse" => ColumnReverse,
134);
135
136impl FlexDirection {
137    #[inline]
138    /// Is the direction [`FlexDirection::Row`] or [`FlexDirection::RowReverse`]?
139    pub(crate) const fn is_row(self) -> bool {
140        matches!(self, Self::Row | Self::RowReverse)
141    }
142
143    #[inline]
144    /// Is the direction [`FlexDirection::Column`] or [`FlexDirection::ColumnReverse`]?
145    pub(crate) const fn is_column(self) -> bool {
146        matches!(self, Self::Column | Self::ColumnReverse)
147    }
148
149    #[inline]
150    /// Is the direction [`FlexDirection::RowReverse`] or [`FlexDirection::ColumnReverse`]?
151    pub(crate) const fn is_reverse(self) -> bool {
152        matches!(self, Self::RowReverse | Self::ColumnReverse)
153    }
154
155    #[inline]
156    /// The `AbsoluteAxis` that corresponds to the main axis
157    pub(crate) const fn main_axis(self) -> AbsoluteAxis {
158        match self {
159            Self::Row | Self::RowReverse => AbsoluteAxis::Horizontal,
160            Self::Column | Self::ColumnReverse => AbsoluteAxis::Vertical,
161        }
162    }
163
164    #[inline]
165    /// The `AbsoluteAxis` that corresponds to the cross axis
166    pub(crate) const fn cross_axis(self) -> AbsoluteAxis {
167        match self {
168            Self::Row | Self::RowReverse => AbsoluteAxis::Vertical,
169            Self::Column | Self::ColumnReverse => AbsoluteAxis::Horizontal,
170        }
171    }
172}
173
174#[cfg(test)]
175mod tests {
176    mod test_flex_direction {
177        use crate::style::*;
178
179        #[test]
180        fn flex_direction_is_row() {
181            assert!(FlexDirection::Row.is_row());
182            assert!(FlexDirection::RowReverse.is_row());
183            assert!(!FlexDirection::Column.is_row());
184            assert!(!FlexDirection::ColumnReverse.is_row());
185        }
186
187        #[test]
188        fn flex_direction_is_column() {
189            assert!(!FlexDirection::Row.is_column());
190            assert!(!FlexDirection::RowReverse.is_column());
191            assert!(FlexDirection::Column.is_column());
192            assert!(FlexDirection::ColumnReverse.is_column());
193        }
194
195        #[test]
196        fn flex_direction_is_reverse() {
197            assert!(!FlexDirection::Row.is_reverse());
198            assert!(FlexDirection::RowReverse.is_reverse());
199            assert!(!FlexDirection::Column.is_reverse());
200            assert!(FlexDirection::ColumnReverse.is_reverse());
201        }
202    }
203}