tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 497HTML 254C 19JavaScript 81329 Definiciones

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

Units trait WIP 7c123d3d5 · Nico Burns ·

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