mod alignment;
mod dimension;
mod flex;
pub use self::alignment::{AlignContent, AlignItems, AlignSelf, JustifyContent, JustifyItems, JustifySelf};
pub use self::dimension::{AvailableSpace, Dimension, LengthPercentage, LengthPercentageAuto};
pub use self::flex::{FlexDirection, FlexWrap};
#[cfg(feature = "experimental_grid")]
mod grid;
#[cfg(feature = "experimental_grid")]
pub use self::grid::{
GridAutoFlow, GridPlacement, GridTrackRepetition, MaxTrackSizingFunction, MinTrackSizingFunction,
NonRepeatedTrackSizingFunction, TrackSizingFunction,
};
use crate::geometry::{Rect, Size};
#[cfg(feature = "experimental_grid")]
use crate::geometry::Line;
#[cfg(feature = "experimental_grid")]
use crate::sys::GridTrackVec;
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Display {
Flex,
#[cfg(feature = "experimental_grid")]
Grid,
None,
}
impl Default for Display {
fn default() -> Self {
Self::Flex
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum PositionType {
Relative,
Absolute,
}
impl Default for PositionType {
fn default() -> Self {
Self::Relative
}
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Style {
pub display: Display,
pub position_type: PositionType,
pub position: Rect<LengthPercentageAuto>,
pub size: Size<Dimension>,
pub min_size: Size<Dimension>,
pub max_size: Size<Dimension>,
pub aspect_ratio: Option<f32>,
pub margin: Rect<LengthPercentageAuto>,
pub padding: Rect<LengthPercentage>,
pub border: Rect<LengthPercentage>,
pub align_items: Option<AlignItems>,
pub align_self: Option<AlignSelf>,
#[cfg(feature = "experimental_grid")]
pub justify_items: Option<AlignItems>,
pub justify_self: Option<AlignSelf>,
pub align_content: Option<AlignContent>,
pub justify_content: Option<JustifyContent>,
pub gap: Size<LengthPercentage>,
pub flex_direction: FlexDirection,
pub flex_wrap: FlexWrap,
pub flex_basis: Dimension,
pub flex_grow: f32,
pub flex_shrink: f32,
#[cfg(feature = "experimental_grid")]
pub grid_template_rows: GridTrackVec<TrackSizingFunction>,
#[cfg(feature = "experimental_grid")]
pub grid_template_columns: GridTrackVec<TrackSizingFunction>,
#[cfg(feature = "experimental_grid")]
pub grid_auto_rows: GridTrackVec<NonRepeatedTrackSizingFunction>,
#[cfg(feature = "experimental_grid")]
pub grid_auto_columns: GridTrackVec<NonRepeatedTrackSizingFunction>,
#[cfg(feature = "experimental_grid")]
pub grid_auto_flow: GridAutoFlow,
#[cfg(feature = "experimental_grid")]
pub grid_row: Line<GridPlacement>,
#[cfg(feature = "experimental_grid")]
pub grid_column: Line<GridPlacement>,
}
impl Style {
pub const DEFAULT: Style = Style {
display: Display::Flex,
position_type: PositionType::Relative,
flex_direction: FlexDirection::Row,
flex_wrap: FlexWrap::NoWrap,
align_items: None,
align_self: None,
#[cfg(feature = "experimental_grid")]
justify_items: None,
justify_self: None,
align_content: None,
justify_content: None,
position: Rect::auto(),
margin: Rect::zero(),
padding: Rect::zero(),
border: Rect::zero(),
gap: Size::zero(),
flex_grow: 0.0,
flex_shrink: 1.0,
flex_basis: Dimension::Auto,
size: Size::auto(),
min_size: Size::auto(),
max_size: Size::auto(),
aspect_ratio: None,
#[cfg(feature = "experimental_grid")]
grid_template_rows: GridTrackVec::new(),
#[cfg(feature = "experimental_grid")]
grid_template_columns: GridTrackVec::new(),
#[cfg(feature = "experimental_grid")]
grid_auto_rows: GridTrackVec::new(),
#[cfg(feature = "experimental_grid")]
grid_auto_columns: GridTrackVec::new(),
#[cfg(feature = "experimental_grid")]
grid_auto_flow: GridAutoFlow::Row,
#[cfg(feature = "experimental_grid")]
grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
#[cfg(feature = "experimental_grid")]
grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
};
}
impl Default for Style {
fn default() -> Self {
Style::DEFAULT
}
}
impl Style {
pub(crate) fn min_main_size(&self, direction: FlexDirection) -> Dimension {
if direction.is_row() {
self.min_size.width
} else {
self.min_size.height
}
}
pub(crate) fn max_main_size(&self, direction: FlexDirection) -> Dimension {
if direction.is_row() {
self.max_size.width
} else {
self.max_size.height
}
}
pub(crate) fn main_margin_start(&self, direction: FlexDirection) -> LengthPercentageAuto {
if direction.is_row() {
self.margin.left
} else {
self.margin.top
}
}
pub(crate) fn main_margin_end(&self, direction: FlexDirection) -> LengthPercentageAuto {
if direction.is_row() {
self.margin.right
} else {
self.margin.bottom
}
}
pub(crate) fn cross_size(&self, direction: FlexDirection) -> Dimension {
if direction.is_row() {
self.size.height
} else {
self.size.width
}
}
pub(crate) fn min_cross_size(&self, direction: FlexDirection) -> Dimension {
if direction.is_row() {
self.min_size.height
} else {
self.min_size.width
}
}
pub(crate) fn max_cross_size(&self, direction: FlexDirection) -> Dimension {
if direction.is_row() {
self.max_size.height
} else {
self.max_size.width
}
}
pub(crate) fn cross_margin_start(&self, direction: FlexDirection) -> LengthPercentageAuto {
if direction.is_row() {
self.margin.top
} else {
self.margin.left
}
}
pub(crate) fn cross_margin_end(&self, direction: FlexDirection) -> LengthPercentageAuto {
if direction.is_row() {
self.margin.bottom
} else {
self.margin.right
}
}
}
#[allow(clippy::bool_assert_comparison)]
#[cfg(test)]
mod tests {
use super::Style;
use crate::geometry::*;
#[test]
fn defaults_match() {
#[cfg(feature = "experimental_grid")]
use super::GridPlacement;
let old_defaults = Style {
display: Default::default(),
position_type: Default::default(),
flex_direction: Default::default(),
flex_wrap: Default::default(),
align_items: Default::default(),
align_self: Default::default(),
#[cfg(feature = "experimental_grid")]
justify_items: Default::default(),
justify_self: Default::default(),
align_content: Default::default(),
justify_content: Default::default(),
position: Rect::auto(),
margin: Rect::zero(),
padding: Rect::zero(),
border: Rect::zero(),
gap: Size::zero(),
flex_grow: 0.0,
flex_shrink: 1.0,
flex_basis: super::Dimension::Auto,
size: Size::auto(),
min_size: Size::auto(),
max_size: Size::auto(),
aspect_ratio: Default::default(),
#[cfg(feature = "experimental_grid")]
grid_template_rows: Default::default(),
#[cfg(feature = "experimental_grid")]
grid_template_columns: Default::default(),
#[cfg(feature = "experimental_grid")]
grid_auto_rows: Default::default(),
#[cfg(feature = "experimental_grid")]
grid_auto_columns: Default::default(),
#[cfg(feature = "experimental_grid")]
grid_auto_flow: Default::default(),
#[cfg(feature = "experimental_grid")]
grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
#[cfg(feature = "experimental_grid")]
grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
};
assert_eq!(Style::DEFAULT, Style::default());
assert_eq!(Style::DEFAULT, old_defaults);
}
mod test_flex_direction {
use crate::style::*;
#[test]
fn flex_direction_is_row() {
assert_eq!(FlexDirection::Row.is_row(), true);
assert_eq!(FlexDirection::RowReverse.is_row(), true);
assert_eq!(FlexDirection::Column.is_row(), false);
assert_eq!(FlexDirection::ColumnReverse.is_row(), false);
}
#[test]
fn flex_direction_is_column() {
assert_eq!(FlexDirection::Row.is_column(), false);
assert_eq!(FlexDirection::RowReverse.is_column(), false);
assert_eq!(FlexDirection::Column.is_column(), true);
assert_eq!(FlexDirection::ColumnReverse.is_column(), true);
}
#[test]
fn flex_direction_is_reverse() {
assert_eq!(FlexDirection::Row.is_reverse(), false);
assert_eq!(FlexDirection::RowReverse.is_reverse(), true);
assert_eq!(FlexDirection::Column.is_reverse(), false);
assert_eq!(FlexDirection::ColumnReverse.is_reverse(), true);
}
}
mod test_flexbox_layout {
use crate::style::*;
use crate::style_helpers::*;
#[test]
fn flexbox_layout_min_main_size() {
let layout = Style { min_size: Size::from_points(1.0, 2.0), ..Default::default() };
assert_eq!(layout.min_main_size(FlexDirection::Row), Dimension::Points(1.0));
assert_eq!(layout.min_main_size(FlexDirection::Column), Dimension::Points(2.0));
}
#[test]
fn flexbox_layout_max_main_size() {
let layout = Style { max_size: Size::from_points(1.0, 2.0), ..Default::default() };
assert_eq!(layout.max_main_size(FlexDirection::Row), Dimension::Points(1.0));
assert_eq!(layout.max_main_size(FlexDirection::Column), Dimension::Points(2.0));
}
#[test]
fn flexbox_layout_main_margin_start() {
let layout = Style {
margin: Rect { top: points(1.0), bottom: auto(), left: points(2.0), right: auto() },
..Default::default()
};
assert_eq!(layout.main_margin_start(FlexDirection::Row), points(2.0));
assert_eq!(layout.main_margin_start(FlexDirection::Column), points(1.0));
}
#[test]
fn flexbox_layout_main_margin_end() {
let layout = Style {
margin: Rect { top: auto(), bottom: points(1.0), left: auto(), right: points(2.0) },
..Default::default()
};
assert_eq!(layout.main_margin_end(FlexDirection::Row), points(2.0));
assert_eq!(layout.main_margin_end(FlexDirection::Column), points(1.0));
}
#[test]
fn flexbox_layout_cross_size() {
let layout = Style { size: Size::from_points(1.0, 2.0), ..Default::default() };
assert_eq!(layout.cross_size(FlexDirection::Row), Dimension::Points(2.0));
assert_eq!(layout.cross_size(FlexDirection::Column), Dimension::Points(1.0));
}
#[test]
fn flexbox_layout_min_cross_size() {
let layout = Style { min_size: Size::from_points(1.0, 2.0), ..Default::default() };
assert_eq!(layout.min_cross_size(FlexDirection::Row), Dimension::Points(2.0));
assert_eq!(layout.min_cross_size(FlexDirection::Column), Dimension::Points(1.0));
}
#[test]
fn flexbox_layout_max_cross_size() {
let layout = Style { max_size: Size::from_points(1.0, 2.0), ..Default::default() };
assert_eq!(layout.max_cross_size(FlexDirection::Row), Dimension::Points(2.0));
assert_eq!(layout.max_cross_size(FlexDirection::Column), Dimension::Points(1.0));
}
#[test]
fn flexbox_layout_cross_margin_start() {
let layout = Style {
margin: Rect { top: points(1.0), bottom: auto(), left: points(2.0), right: auto() },
..Default::default()
};
assert_eq!(layout.cross_margin_start(FlexDirection::Row), points(1.0));
assert_eq!(layout.cross_margin_start(FlexDirection::Column), points(2.0));
}
#[test]
fn flexbox_layout_cross_margin_end() {
let layout = Style {
margin: Rect { top: auto(), bottom: points(1.0), left: auto(), right: points(2.0) },
..Default::default()
};
assert_eq!(layout.cross_margin_end(FlexDirection::Row), points(1.0));
assert_eq!(layout.cross_margin_end(FlexDirection::Column), points(2.0));
}
}
}