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;
#[cfg(feature = "grid")]
pub fn repeat<Input>(repetition_kind: Input, track_list: Vec<NonRepeatedTrackSizingFunction>) -> TrackSizingFunction
where
Input: TryInto<GridTrackRepetition>,
<Input as TryInto<GridTrackRepetition>>::Error: Debug,
{
TrackSizingFunction::Repeat(repetition_kind.try_into().unwrap(), track_list)
}
#[cfg(feature = "grid")]
pub fn evenly_sized_tracks(count: u16) -> Vec<TrackSizingFunction> {
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
}
pub fn line<T: TaffyGridLine>(index: i16) -> T {
T::from_line_index(index)
}
pub trait TaffyGridLine {
fn from_line_index(index: i16) -> Self;
}
pub fn span<T: TaffyGridSpan>(span: u16) -> T {
T::from_span(span)
}
pub trait TaffyGridSpan {
fn from_span(span: u16) -> Self;
}
#[cfg(feature = "grid")]
pub fn minmax<Output>(min: MinTrackSizingFunction, max: MaxTrackSizingFunction) -> Output
where
Output: From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>>,
{
MinMax { min, max }.into()
}
#[cfg(feature = "grid")]
pub fn flex<Input, Output>(flex_fraction: Input) -> Output
where
Input: Into<f32> + Copy,
Output: From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>>,
{
MinMax { min: zero(), max: fr(flex_fraction.into()) }.into()
}
pub const fn zero<T: TaffyZero>() -> T {
T::ZERO
}
pub trait TaffyZero {
const ZERO: Self;
}
impl TaffyZero for f32 {
const ZERO: f32 = 0.0;
}
impl<T: TaffyZero> TaffyZero for Option<T> {
const ZERO: Option<T> = Some(T::ZERO);
}
impl<T: TaffyZero> TaffyZero for Point<T> {
const ZERO: Point<T> = Point { x: T::ZERO, y: T::ZERO };
}
impl<T: TaffyZero> Point<T> {
pub const fn zero() -> Self {
zero::<Self>()
}
}
impl<T: TaffyZero> TaffyZero for Line<T> {
const ZERO: Line<T> = Line { start: T::ZERO, end: T::ZERO };
}
impl<T: TaffyZero> Line<T> {
pub const fn zero() -> Self {
zero::<Self>()
}
}
impl<T: TaffyZero> TaffyZero for Size<T> {
const ZERO: Size<T> = Size { width: T::ZERO, height: T::ZERO };
}
impl<T: TaffyZero> Size<T> {
pub const fn zero() -> Self {
zero::<Self>()
}
}
impl<T: TaffyZero> TaffyZero for Rect<T> {
const ZERO: Rect<T> = Rect { left: T::ZERO, right: T::ZERO, top: T::ZERO, bottom: T::ZERO };
}
impl<T: TaffyZero> Rect<T> {
pub const fn zero() -> Self {
zero::<Self>()
}
}
pub const fn auto<T: TaffyAuto>() -> T {
T::AUTO
}
pub trait TaffyAuto {
const AUTO: Self;
}
impl<T: TaffyAuto> TaffyAuto for Option<T> {
const AUTO: Option<T> = Some(T::AUTO);
}
impl<T: TaffyAuto> TaffyAuto for Point<T> {
const AUTO: Point<T> = Point { x: T::AUTO, y: T::AUTO };
}
impl<T: TaffyAuto> Point<T> {
pub const fn auto() -> Self {
auto::<Self>()
}
}
impl<T: TaffyAuto> TaffyAuto for Line<T> {
const AUTO: Line<T> = Line { start: T::AUTO, end: T::AUTO };
}
impl<T: TaffyAuto> Line<T> {
pub const fn auto() -> Self {
auto::<Self>()
}
}
impl<T: TaffyAuto> TaffyAuto for Size<T> {
const AUTO: Size<T> = Size { width: T::AUTO, height: T::AUTO };
}
impl<T: TaffyAuto> Size<T> {
pub const fn auto() -> Self {
auto::<Self>()
}
}
impl<T: TaffyAuto> TaffyAuto for Rect<T> {
const AUTO: Rect<T> = Rect { left: T::AUTO, right: T::AUTO, top: T::AUTO, bottom: T::AUTO };
}
impl<T: TaffyAuto> Rect<T> {
pub const fn auto() -> Self {
auto::<Self>()
}
}
pub const fn min_content<T: TaffyMinContent>() -> T {
T::MIN_CONTENT
}
pub trait TaffyMinContent {
const MIN_CONTENT: Self;
}
impl<T: TaffyMinContent> TaffyMinContent for Option<T> {
const MIN_CONTENT: Option<T> = Some(T::MIN_CONTENT);
}
impl<T: TaffyMinContent> TaffyMinContent for Point<T> {
const MIN_CONTENT: Point<T> = Point { x: T::MIN_CONTENT, y: T::MIN_CONTENT };
}
impl<T: TaffyMinContent> Point<T> {
pub const fn min_content() -> Self {
min_content::<Self>()
}
}
impl<T: TaffyMinContent> TaffyMinContent for Line<T> {
const MIN_CONTENT: Line<T> = Line { start: T::MIN_CONTENT, end: T::MIN_CONTENT };
}
impl<T: TaffyMinContent> Line<T> {
pub const fn min_content() -> Self {
min_content::<Self>()
}
}
impl<T: TaffyMinContent> TaffyMinContent for Size<T> {
const MIN_CONTENT: Size<T> = Size { width: T::MIN_CONTENT, height: T::MIN_CONTENT };
}
impl<T: TaffyMinContent> Size<T> {
pub const fn min_content() -> Self {
min_content::<Self>()
}
}
impl<T: TaffyMinContent> TaffyMinContent for Rect<T> {
const MIN_CONTENT: Rect<T> =
Rect { left: T::MIN_CONTENT, right: T::MIN_CONTENT, top: T::MIN_CONTENT, bottom: T::MIN_CONTENT };
}
impl<T: TaffyMinContent> Rect<T> {
pub const fn min_content() -> Self {
min_content::<Self>()
}
}
pub const fn max_content<T: TaffyMaxContent>() -> T {
T::MAX_CONTENT
}
pub trait TaffyMaxContent {
const MAX_CONTENT: Self;
}
impl<T: TaffyMaxContent> TaffyMaxContent for Option<T> {
const MAX_CONTENT: Option<T> = Some(T::MAX_CONTENT);
}
impl<T: TaffyMaxContent> TaffyMaxContent for Point<T> {
const MAX_CONTENT: Point<T> = Point { x: T::MAX_CONTENT, y: T::MAX_CONTENT };
}
impl<T: TaffyMaxContent> Point<T> {
pub const fn max_content() -> Self {
max_content::<Self>()
}
}
impl<T: TaffyMaxContent> TaffyMaxContent for Line<T> {
const MAX_CONTENT: Line<T> = Line { start: T::MAX_CONTENT, end: T::MAX_CONTENT };
}
impl<T: TaffyMaxContent> Line<T> {
pub const fn max_content() -> Self {
max_content::<Self>()
}
}
impl<T: TaffyMaxContent> TaffyMaxContent for Size<T> {
const MAX_CONTENT: Size<T> = Size { width: T::MAX_CONTENT, height: T::MAX_CONTENT };
}
impl<T: TaffyMaxContent> Size<T> {
pub const fn max_content() -> Self {
max_content::<Self>()
}
}
impl<T: TaffyMaxContent> TaffyMaxContent for Rect<T> {
const MAX_CONTENT: Rect<T> =
Rect { left: T::MAX_CONTENT, right: T::MAX_CONTENT, top: T::MAX_CONTENT, bottom: T::MAX_CONTENT };
}
impl<T: TaffyMaxContent> Rect<T> {
pub const fn max_content() -> Self {
max_content::<Self>()
}
}
pub fn fit_content<T: TaffyFitContent>(argument: LengthPercentage) -> T {
T::fit_content(argument)
}
pub trait TaffyFitContent {
fn fit_content(argument: LengthPercentage) -> Self;
}
impl<T: TaffyFitContent> TaffyFitContent for Point<T> {
fn fit_content(argument: LengthPercentage) -> Self {
Point { x: T::fit_content(argument), y: T::fit_content(argument) }
}
}
impl<T: TaffyFitContent> Point<T> {
pub fn fit_content(argument: LengthPercentage) -> Self {
fit_content(argument)
}
}
impl<T: TaffyFitContent> TaffyFitContent for Line<T> {
fn fit_content(argument: LengthPercentage) -> Self {
Line { start: T::fit_content(argument), end: T::fit_content(argument) }
}
}
impl<T: TaffyFitContent> Line<T> {
pub fn fit_content(argument: LengthPercentage) -> Self {
fit_content(argument)
}
}
impl<T: TaffyFitContent> TaffyFitContent for Size<T> {
fn fit_content(argument: LengthPercentage) -> Self {
Size { width: T::fit_content(argument), height: T::fit_content(argument) }
}
}
impl<T: TaffyFitContent> Size<T> {
pub fn fit_content(argument: LengthPercentage) -> Self {
fit_content(argument)
}
}
impl<T: TaffyFitContent> TaffyFitContent for Rect<T> {
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<T: TaffyFitContent> Rect<T> {
pub fn fit_content(argument: LengthPercentage) -> Self {
fit_content(argument)
}
}
pub fn length<Input: Into<f32> + Copy, T: FromLength>(value: Input) -> T {
T::from_length(value)
}
pub trait FromLength {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self;
}
impl FromLength for f32 {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
value.into()
}
}
impl FromLength for Option<f32> {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
Some(value.into())
}
}
impl<T: FromLength> FromLength for Point<T> {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
Point { x: T::from_length(value.into()), y: T::from_length(value.into()) }
}
}
impl<T: FromLength> Point<T> {
pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
length::<Input, Self>(value)
}
}
impl<T: FromLength> FromLength for Line<T> {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
Line { start: T::from_length(value.into()), end: T::from_length(value.into()) }
}
}
impl<T: FromLength> Line<T> {
pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
length::<Input, Self>(value)
}
}
impl<T: FromLength> FromLength for Size<T> {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
Size { width: T::from_length(value.into()), height: T::from_length(value.into()) }
}
}
impl<T: FromLength> Size<T> {
pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
length::<Input, Self>(value)
}
}
impl<T: FromLength> FromLength for Rect<T> {
fn from_length<Input: Into<f32> + 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<T: FromLength> Rect<T> {
pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
length::<Input, Self>(value)
}
}
pub fn percent<Input: Into<f32> + Copy, T: FromPercent>(percent: Input) -> T {
T::from_percent(percent)
}
pub trait FromPercent {
fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self;
}
impl FromPercent for f32 {
fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
percent.into()
}
}
impl FromPercent for Option<f32> {
fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
Some(percent.into())
}
}
impl<T: FromPercent> FromPercent for Point<T> {
fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
Point { x: T::from_percent(percent.into()), y: T::from_percent(percent.into()) }
}
}
impl<T: FromPercent> Point<T> {
pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
percent::<Input, Self>(percent_value)
}
}
impl<T: FromPercent> FromPercent for Line<T> {
fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
Line { start: T::from_percent(percent.into()), end: T::from_percent(percent.into()) }
}
}
impl<T: FromPercent> Line<T> {
pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
percent::<Input, Self>(percent_value)
}
}
impl<T: FromPercent> FromPercent for Size<T> {
fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
Size { width: T::from_percent(percent.into()), height: T::from_percent(percent.into()) }
}
}
impl<T: FromPercent> Size<T> {
pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
percent::<Input, Self>(percent_value)
}
}
impl<T: FromPercent> FromPercent for Rect<T> {
fn from_percent<Input: Into<f32> + 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<T: FromPercent> Rect<T> {
pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
percent::<Input, Self>(percent_value)
}
}
#[cfg(feature = "grid")]
pub fn fr<Input: Into<f32> + Copy, T: FromFlex>(flex: Input) -> T {
T::from_flex(flex)
}
pub trait FromFlex {
fn from_flex<Input: Into<f32> + 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<NonRepeatedTrackSizingFunction> = 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));
}
}