//! Helper functions which it make it easier to create instances of types in the `style` and `geometry` modules. use crate::{ geometry::{Line, Point, Rect, Size}, style::LengthPercentage, }; #[cfg(feature = "grid")] use crate::{ geometry::MinMax, style::{ GridTrackRepetition, MaxTrackSizingFunction, MinTrackSizingFunction, NonRepeatedTrackSizingFunction, TrackSizingFunction, }, util::sys::Vec, }; #[cfg(feature = "grid")] use core::fmt::Debug; /// Returns an auto-repeated track definition #[cfg(feature = "grid")] pub fn repeat(repetition_kind: Input, track_list: Vec) -> TrackSizingFunction where Input: TryInto, >::Error: Debug, { TrackSizingFunction::Repeat(repetition_kind.try_into().unwrap(), track_list) } #[cfg(feature = "grid")] /// Returns a grid template containing `count` evenly sized tracks pub fn evenly_sized_tracks(count: u16) -> Vec { use crate::util::sys::new_vec_with_capacity; let mut repeated_tracks = new_vec_with_capacity(1); repeated_tracks.push(flex(1.0f32)); let mut tracks = new_vec_with_capacity(1); tracks.push(repeat(count, repeated_tracks)); tracks } /// Specifies a grid line to place a grid item between in CSS Grid Line coordinates: /// - Positive indices count upwards from the start (top or left) of the explicit grid /// - Negative indices count downwards from the end (bottom or right) of the explicit grid /// - ZERO IS INVALID index, and will be treated as a GridPlacement::Auto. pub fn line(index: i16) -> T { T::from_line_index(index) } /// Trait to abstract over grid line values pub trait TaffyGridLine { /// Converts an i16 into Self fn from_line_index(index: i16) -> Self; } /// Returns a GridPlacement::Span pub fn span(span: u16) -> T { T::from_span(span) } /// Trait to abstract over grid span values pub trait TaffyGridSpan { /// Converts an iu6 into Self fn from_span(span: u16) -> Self; } /// Returns a MinMax with min value of min and max value of max #[cfg(feature = "grid")] pub fn minmax(min: MinTrackSizingFunction, max: MaxTrackSizingFunction) -> Output where Output: From>, { MinMax { min, max }.into() } /// Shorthand for minmax(0, Nfr). Probably what you want if you want exactly evenly sized tracks. #[cfg(feature = "grid")] pub fn flex(flex_fraction: Input) -> Output where Input: Into + Copy, Output: From>, { MinMax { min: zero(), max: fr(flex_fraction.into()) }.into() } /// Returns the zero value for that type pub const fn zero() -> T { T::ZERO } /// Trait to abstract over zero values pub trait TaffyZero { /// The zero value for type implementing TaffyZero const ZERO: Self; } impl TaffyZero for f32 { const ZERO: f32 = 0.0; } impl TaffyZero for Option { const ZERO: Option = Some(T::ZERO); } impl TaffyZero for Point { const ZERO: Point = Point { x: T::ZERO, y: T::ZERO }; } impl Point { /// Returns a Point where both the x and y values are the zero value of the contained type /// (e.g. 0.0, Some(0.0), or Dimension::Length(0.0)) pub const fn zero() -> Self { zero::() } } impl TaffyZero for Line { const ZERO: Line = Line { start: T::ZERO, end: T::ZERO }; } impl Line { /// Returns a Line where both the start and end values are the zero value of the contained type /// (e.g. 0.0, Some(0.0), or Dimension::Length(0.0)) pub const fn zero() -> Self { zero::() } } impl TaffyZero for Size { const ZERO: Size = Size { width: T::ZERO, height: T::ZERO }; } impl Size { /// Returns a Size where both the width and height values are the zero value of the contained type /// (e.g. 0.0, Some(0.0), or Dimension::Length(0.0)) pub const fn zero() -> Self { zero::() } } impl TaffyZero for Rect { const ZERO: Rect = Rect { left: T::ZERO, right: T::ZERO, top: T::ZERO, bottom: T::ZERO }; } impl Rect { /// Returns a Rect where the left, right, top, and bottom values are all the zero value of the contained type /// (e.g. 0.0, Some(0.0), or Dimension::Length(0.0)) pub const fn zero() -> Self { zero::() } } /// Returns the auto value for that type pub const fn auto() -> T { T::AUTO } /// Trait to abstract over auto values pub trait TaffyAuto { /// The auto value for type implementing TaffyAuto const AUTO: Self; } impl TaffyAuto for Option { const AUTO: Option = Some(T::AUTO); } impl TaffyAuto for Point { const AUTO: Point = Point { x: T::AUTO, y: T::AUTO }; } impl Point { /// Returns a Point where both the x and y values are the auto value of the contained type /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto) pub const fn auto() -> Self { auto::() } } impl TaffyAuto for Line { const AUTO: Line = Line { start: T::AUTO, end: T::AUTO }; } impl Line { /// Returns a Line where both the start and end values are the auto value of the contained type /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto) pub const fn auto() -> Self { auto::() } } impl TaffyAuto for Size { const AUTO: Size = Size { width: T::AUTO, height: T::AUTO }; } impl Size { /// Returns a Size where both the width and height values are the auto value of the contained type /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto) pub const fn auto() -> Self { auto::() } } impl TaffyAuto for Rect { const AUTO: Rect = Rect { left: T::AUTO, right: T::AUTO, top: T::AUTO, bottom: T::AUTO }; } impl Rect { /// Returns a Rect where the left, right, top, and bottom values are all the auto value of the contained type /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto) pub const fn auto() -> Self { auto::() } } /// Returns the auto value for that type pub const fn min_content() -> T { T::MIN_CONTENT } /// Trait to abstract over min_content values pub trait TaffyMinContent { /// The min_content value for type implementing TaffyZero const MIN_CONTENT: Self; } impl TaffyMinContent for Option { const MIN_CONTENT: Option = Some(T::MIN_CONTENT); } impl TaffyMinContent for Point { const MIN_CONTENT: Point = Point { x: T::MIN_CONTENT, y: T::MIN_CONTENT }; } impl Point { /// Returns a Point where both the x and y values are the min_content value of the contained type /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto) pub const fn min_content() -> Self { min_content::() } } impl TaffyMinContent for Line { const MIN_CONTENT: Line = Line { start: T::MIN_CONTENT, end: T::MIN_CONTENT }; } impl Line { /// Returns a Line where both the start and end values are the min_content value of the contained type /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto) pub const fn min_content() -> Self { min_content::() } } impl TaffyMinContent for Size { const MIN_CONTENT: Size = Size { width: T::MIN_CONTENT, height: T::MIN_CONTENT }; } impl Size { /// Returns a Size where both the width and height values are the min_content value of the contained type /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto) pub const fn min_content() -> Self { min_content::() } } impl TaffyMinContent for Rect { const MIN_CONTENT: Rect = Rect { left: T::MIN_CONTENT, right: T::MIN_CONTENT, top: T::MIN_CONTENT, bottom: T::MIN_CONTENT }; } impl Rect { /// Returns a Rect where the left, right, top, and bottom values are all the min_content value of the contained type /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto) pub const fn min_content() -> Self { min_content::() } } /// Returns the auto value for that type pub const fn max_content() -> T { T::MAX_CONTENT } /// Trait to abstract over max_content values pub trait TaffyMaxContent { /// The max_content value for type implementing TaffyZero const MAX_CONTENT: Self; } impl TaffyMaxContent for Option { const MAX_CONTENT: Option = Some(T::MAX_CONTENT); } impl TaffyMaxContent for Point { const MAX_CONTENT: Point = Point { x: T::MAX_CONTENT, y: T::MAX_CONTENT }; } impl Point { /// Returns a Point where both the x and y values are the max_content value of the contained type /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto) pub const fn max_content() -> Self { max_content::() } } impl TaffyMaxContent for Line { const MAX_CONTENT: Line = Line { start: T::MAX_CONTENT, end: T::MAX_CONTENT }; } impl Line { /// Returns a Line where both the start and end values are the max_content value of the contained type /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto) pub const fn max_content() -> Self { max_content::() } } impl TaffyMaxContent for Size { const MAX_CONTENT: Size = Size { width: T::MAX_CONTENT, height: T::MAX_CONTENT }; } impl Size { /// Returns a Size where both the width and height values are the max_content value of the contained type /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto) pub const fn max_content() -> Self { max_content::() } } impl TaffyMaxContent for Rect { const MAX_CONTENT: Rect = Rect { left: T::MAX_CONTENT, right: T::MAX_CONTENT, top: T::MAX_CONTENT, bottom: T::MAX_CONTENT }; } impl Rect { /// Returns a Rect where the left, right, top, and bottom values are all the max_content value of the contained type /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto) pub const fn max_content() -> Self { max_content::() } } /// Returns a value of the inferred type which represent a `fit-content(…)` value /// with the given argument. pub fn fit_content(argument: LengthPercentage) -> T { T::fit_content(argument) } /// Trait to create `fit-content(…)` values from plain numbers pub trait TaffyFitContent { /// Converts a LengthPercentage into Self fn fit_content(argument: LengthPercentage) -> Self; } impl TaffyFitContent for Point { fn fit_content(argument: LengthPercentage) -> Self { Point { x: T::fit_content(argument), y: T::fit_content(argument) } } } impl Point { /// Returns a Point with x and y set to the same `fit-content(…)` value /// with the given argument. pub fn fit_content(argument: LengthPercentage) -> Self { fit_content(argument) } } impl TaffyFitContent for Line { fn fit_content(argument: LengthPercentage) -> Self { Line { start: T::fit_content(argument), end: T::fit_content(argument) } } } impl Line { /// Returns a Line with start and end set to the same `fit-content(…)` value /// with the given argument. pub fn fit_content(argument: LengthPercentage) -> Self { fit_content(argument) } } impl TaffyFitContent for Size { fn fit_content(argument: LengthPercentage) -> Self { Size { width: T::fit_content(argument), height: T::fit_content(argument) } } } impl Size { /// Returns a Size where with width and height set to the same `fit-content(…)` value /// with the given argument. pub fn fit_content(argument: LengthPercentage) -> Self { fit_content(argument) } } impl TaffyFitContent for Rect { fn fit_content(argument: LengthPercentage) -> Self { Rect { left: T::fit_content(argument), right: T::fit_content(argument), top: T::fit_content(argument), bottom: T::fit_content(argument), } } } impl Rect { /// Returns a Rect where the left, right, top and bottom values are all constant fit_content value of the contained type /// (e.g. 2.1, Some(2.1), or Dimension::Length(2.1)) pub fn fit_content(argument: LengthPercentage) -> Self { fit_content(argument) } } /// Returns a value of the inferred type which represent an absolute length pub fn length + Copy, T: FromLength>(value: Input) -> T { T::from_length(value) } /// Trait to create absolute length values from plain numbers pub trait FromLength { /// Converts into an `Into` into Self fn from_length + Copy>(value: Input) -> Self; } impl FromLength for f32 { fn from_length + Copy>(value: Input) -> Self { value.into() } } impl FromLength for Option { fn from_length + Copy>(value: Input) -> Self { Some(value.into()) } } impl FromLength for Point { fn from_length + Copy>(value: Input) -> Self { Point { x: T::from_length(value.into()), y: T::from_length(value.into()) } } } impl Point { /// Returns a Point where x and y values are the same given absolute length pub fn length + Copy>(value: Input) -> Self { length::(value) } } impl FromLength for Line { fn from_length + Copy>(value: Input) -> Self { Line { start: T::from_length(value.into()), end: T::from_length(value.into()) } } } impl Line { /// Returns a Line where both the start and end values are the same given absolute length pub fn length + Copy>(value: Input) -> Self { length::(value) } } impl FromLength for Size { fn from_length + Copy>(value: Input) -> Self { Size { width: T::from_length(value.into()), height: T::from_length(value.into()) } } } impl Size { /// Returns a Size where both the width and height values the same given absolute length pub fn length + Copy>(value: Input) -> Self { length::(value) } } impl FromLength for Rect { fn from_length + Copy>(value: Input) -> Self { Rect { left: T::from_length(value.into()), right: T::from_length(value.into()), top: T::from_length(value.into()), bottom: T::from_length(value.into()), } } } impl Rect { /// Returns a Rect where the left, right, top and bottom values are all the same given absolute length pub fn length + Copy>(value: Input) -> Self { length::(value) } } /// Returns a value of the inferred type which represent a percentage pub fn percent + Copy, T: FromPercent>(percent: Input) -> T { T::from_percent(percent) } /// Trait to create constant percent values from plain numbers pub trait FromPercent { /// Converts into an `Into` into Self fn from_percent + Copy>(percent: Input) -> Self; } impl FromPercent for f32 { fn from_percent + Copy>(percent: Input) -> Self { percent.into() } } impl FromPercent for Option { fn from_percent + Copy>(percent: Input) -> Self { Some(percent.into()) } } impl FromPercent for Point { fn from_percent + Copy>(percent: Input) -> Self { Point { x: T::from_percent(percent.into()), y: T::from_percent(percent.into()) } } } impl Point { /// Returns a Point where both the x and y values are the constant percent value of the contained type /// (e.g. 2.1, Some(2.1), or Dimension::Length(2.1)) pub fn percent + Copy>(percent_value: Input) -> Self { percent::(percent_value) } } impl FromPercent for Line { fn from_percent + Copy>(percent: Input) -> Self { Line { start: T::from_percent(percent.into()), end: T::from_percent(percent.into()) } } } impl Line { /// Returns a Line where both the start and end values are the constant percent value of the contained type /// (e.g. 2.1, Some(2.1), or Dimension::Length(2.1)) pub fn percent + Copy>(percent_value: Input) -> Self { percent::(percent_value) } } impl FromPercent for Size { fn from_percent + Copy>(percent: Input) -> Self { Size { width: T::from_percent(percent.into()), height: T::from_percent(percent.into()) } } } impl Size { /// Returns a Size where both the width and height values are the constant percent value of the contained type /// (e.g. 2.1, Some(2.1), or Dimension::Length(2.1)) pub fn percent + Copy>(percent_value: Input) -> Self { percent::(percent_value) } } impl FromPercent for Rect { fn from_percent + Copy>(percent: Input) -> Self { Rect { left: T::from_percent(percent.into()), right: T::from_percent(percent.into()), top: T::from_percent(percent.into()), bottom: T::from_percent(percent.into()), } } } impl Rect { /// Returns a Rect where the left, right, top and bottom values are all constant percent value of the contained type /// (e.g. 2.1, Some(2.1), or Dimension::Length(2.1)) pub fn percent + Copy>(percent_value: Input) -> Self { percent::(percent_value) } } /// Create a `Fraction` track sizing function (`fr` in CSS) #[cfg(feature = "grid")] pub fn fr + Copy, T: FromFlex>(flex: Input) -> T { T::from_flex(flex) } /// Trait to create constant percent values from plain numbers pub trait FromFlex { /// Converts into an `Into` into Self fn from_flex + Copy>(flex: Input) -> Self; } #[cfg(feature = "grid")] #[cfg(test)] mod repeat_fn_tests { use super::repeat; use crate::style::{GridTrackRepetition, NonRepeatedTrackSizingFunction, TrackSizingFunction}; const TEST_VEC: Vec = Vec::new(); #[test] fn test_repeat_u16() { assert_eq!(repeat(123, TEST_VEC), TrackSizingFunction::Repeat(GridTrackRepetition::Count(123), TEST_VEC)); } #[test] fn test_repeat_auto_fit_str() { assert_eq!(repeat("auto-fit", TEST_VEC), TrackSizingFunction::Repeat(GridTrackRepetition::AutoFit, TEST_VEC)); } #[test] fn test_repeat_auto_fill_str() { assert_eq!(repeat("auto-fill", TEST_VEC), TrackSizingFunction::Repeat(GridTrackRepetition::AutoFill, TEST_VEC)); } }