1use crate::{
3 geometry::{Line, Point, Rect, Size},
4 style::LengthPercentage,
5};
6
7#[cfg(feature = "grid")]
8use crate::{
9 geometry::MinMax,
10 style::{
11 GridTrackRepetition, MaxTrackSizingFunction, MinTrackSizingFunction, NonRepeatedTrackSizingFunction,
12 TrackSizingFunction,
13 },
14 util::sys::Vec,
15};
16#[cfg(feature = "grid")]
17use core::fmt::Debug;
18
19#[cfg(feature = "grid")]
21pub fn repeat<Input>(repetition_kind: Input, track_list: Vec<NonRepeatedTrackSizingFunction>) -> TrackSizingFunction
22where
23 Input: TryInto<GridTrackRepetition>,
24 <Input as TryInto<GridTrackRepetition>>::Error: Debug,
25{
26 TrackSizingFunction::Repeat(repetition_kind.try_into().unwrap(), track_list)
27}
28
29#[cfg(feature = "grid")]
30pub fn evenly_sized_tracks(count: u16) -> Vec<TrackSizingFunction> {
32 use crate::util::sys::new_vec_with_capacity;
33 let mut repeated_tracks = new_vec_with_capacity(1);
34 repeated_tracks.push(flex(1.0f32));
35 let mut tracks = new_vec_with_capacity(1);
36 tracks.push(repeat(count, repeated_tracks));
37 tracks
38}
39
40pub fn line<T: TaffyGridLine>(index: i16) -> T {
45 T::from_line_index(index)
46}
47pub trait TaffyGridLine {
49 fn from_line_index(index: i16) -> Self;
51}
52
53pub fn span<T: TaffyGridSpan>(span: u16) -> T {
55 T::from_span(span)
56}
57pub trait TaffyGridSpan {
59 fn from_span(span: u16) -> Self;
61}
62
63#[cfg(feature = "grid")]
65pub fn minmax<Output>(min: MinTrackSizingFunction, max: MaxTrackSizingFunction) -> Output
66where
67 Output: From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>>,
68{
69 MinMax { min, max }.into()
70}
71
72#[cfg(feature = "grid")]
74pub fn flex<Input, Output>(flex_fraction: Input) -> Output
75where
76 Input: Into<f32> + Copy,
77 Output: From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>>,
78{
79 MinMax { min: zero(), max: fr(flex_fraction.into()) }.into()
80}
81
82pub const fn zero<T: TaffyZero>() -> T {
84 T::ZERO
85}
86
87pub trait TaffyZero {
89 const ZERO: Self;
91}
92impl TaffyZero for f32 {
93 const ZERO: f32 = 0.0;
94}
95impl<T: TaffyZero> TaffyZero for Option<T> {
96 const ZERO: Option<T> = Some(T::ZERO);
97}
98impl<T: TaffyZero> TaffyZero for Point<T> {
99 const ZERO: Point<T> = Point { x: T::ZERO, y: T::ZERO };
100}
101impl<T: TaffyZero> Point<T> {
102 pub const fn zero() -> Self {
105 zero::<Self>()
106 }
107}
108impl<T: TaffyZero> TaffyZero for Line<T> {
109 const ZERO: Line<T> = Line { start: T::ZERO, end: T::ZERO };
110}
111impl<T: TaffyZero> Line<T> {
112 pub const fn zero() -> Self {
115 zero::<Self>()
116 }
117}
118impl<T: TaffyZero> TaffyZero for Size<T> {
119 const ZERO: Size<T> = Size { width: T::ZERO, height: T::ZERO };
120}
121impl<T: TaffyZero> Size<T> {
122 pub const fn zero() -> Self {
125 zero::<Self>()
126 }
127}
128impl<T: TaffyZero> TaffyZero for Rect<T> {
129 const ZERO: Rect<T> = Rect { left: T::ZERO, right: T::ZERO, top: T::ZERO, bottom: T::ZERO };
130}
131impl<T: TaffyZero> Rect<T> {
132 pub const fn zero() -> Self {
135 zero::<Self>()
136 }
137}
138
139pub const fn auto<T: TaffyAuto>() -> T {
141 T::AUTO
142}
143
144pub trait TaffyAuto {
146 const AUTO: Self;
148}
149impl<T: TaffyAuto> TaffyAuto for Option<T> {
150 const AUTO: Option<T> = Some(T::AUTO);
151}
152impl<T: TaffyAuto> TaffyAuto for Point<T> {
153 const AUTO: Point<T> = Point { x: T::AUTO, y: T::AUTO };
154}
155impl<T: TaffyAuto> Point<T> {
156 pub const fn auto() -> Self {
159 auto::<Self>()
160 }
161}
162impl<T: TaffyAuto> TaffyAuto for Line<T> {
163 const AUTO: Line<T> = Line { start: T::AUTO, end: T::AUTO };
164}
165impl<T: TaffyAuto> Line<T> {
166 pub const fn auto() -> Self {
169 auto::<Self>()
170 }
171}
172impl<T: TaffyAuto> TaffyAuto for Size<T> {
173 const AUTO: Size<T> = Size { width: T::AUTO, height: T::AUTO };
174}
175impl<T: TaffyAuto> Size<T> {
176 pub const fn auto() -> Self {
179 auto::<Self>()
180 }
181}
182impl<T: TaffyAuto> TaffyAuto for Rect<T> {
183 const AUTO: Rect<T> = Rect { left: T::AUTO, right: T::AUTO, top: T::AUTO, bottom: T::AUTO };
184}
185impl<T: TaffyAuto> Rect<T> {
186 pub const fn auto() -> Self {
189 auto::<Self>()
190 }
191}
192
193pub const fn min_content<T: TaffyMinContent>() -> T {
195 T::MIN_CONTENT
196}
197
198pub trait TaffyMinContent {
200 const MIN_CONTENT: Self;
202}
203impl<T: TaffyMinContent> TaffyMinContent for Option<T> {
204 const MIN_CONTENT: Option<T> = Some(T::MIN_CONTENT);
205}
206impl<T: TaffyMinContent> TaffyMinContent for Point<T> {
207 const MIN_CONTENT: Point<T> = Point { x: T::MIN_CONTENT, y: T::MIN_CONTENT };
208}
209impl<T: TaffyMinContent> Point<T> {
210 pub const fn min_content() -> Self {
213 min_content::<Self>()
214 }
215}
216impl<T: TaffyMinContent> TaffyMinContent for Line<T> {
217 const MIN_CONTENT: Line<T> = Line { start: T::MIN_CONTENT, end: T::MIN_CONTENT };
218}
219impl<T: TaffyMinContent> Line<T> {
220 pub const fn min_content() -> Self {
223 min_content::<Self>()
224 }
225}
226impl<T: TaffyMinContent> TaffyMinContent for Size<T> {
227 const MIN_CONTENT: Size<T> = Size { width: T::MIN_CONTENT, height: T::MIN_CONTENT };
228}
229impl<T: TaffyMinContent> Size<T> {
230 pub const fn min_content() -> Self {
233 min_content::<Self>()
234 }
235}
236impl<T: TaffyMinContent> TaffyMinContent for Rect<T> {
237 const MIN_CONTENT: Rect<T> =
238 Rect { left: T::MIN_CONTENT, right: T::MIN_CONTENT, top: T::MIN_CONTENT, bottom: T::MIN_CONTENT };
239}
240impl<T: TaffyMinContent> Rect<T> {
241 pub const fn min_content() -> Self {
244 min_content::<Self>()
245 }
246}
247
248pub const fn max_content<T: TaffyMaxContent>() -> T {
250 T::MAX_CONTENT
251}
252
253pub trait TaffyMaxContent {
255 const MAX_CONTENT: Self;
257}
258impl<T: TaffyMaxContent> TaffyMaxContent for Option<T> {
259 const MAX_CONTENT: Option<T> = Some(T::MAX_CONTENT);
260}
261impl<T: TaffyMaxContent> TaffyMaxContent for Point<T> {
262 const MAX_CONTENT: Point<T> = Point { x: T::MAX_CONTENT, y: T::MAX_CONTENT };
263}
264impl<T: TaffyMaxContent> Point<T> {
265 pub const fn max_content() -> Self {
268 max_content::<Self>()
269 }
270}
271impl<T: TaffyMaxContent> TaffyMaxContent for Line<T> {
272 const MAX_CONTENT: Line<T> = Line { start: T::MAX_CONTENT, end: T::MAX_CONTENT };
273}
274impl<T: TaffyMaxContent> Line<T> {
275 pub const fn max_content() -> Self {
278 max_content::<Self>()
279 }
280}
281impl<T: TaffyMaxContent> TaffyMaxContent for Size<T> {
282 const MAX_CONTENT: Size<T> = Size { width: T::MAX_CONTENT, height: T::MAX_CONTENT };
283}
284impl<T: TaffyMaxContent> Size<T> {
285 pub const fn max_content() -> Self {
288 max_content::<Self>()
289 }
290}
291impl<T: TaffyMaxContent> TaffyMaxContent for Rect<T> {
292 const MAX_CONTENT: Rect<T> =
293 Rect { left: T::MAX_CONTENT, right: T::MAX_CONTENT, top: T::MAX_CONTENT, bottom: T::MAX_CONTENT };
294}
295impl<T: TaffyMaxContent> Rect<T> {
296 pub const fn max_content() -> Self {
299 max_content::<Self>()
300 }
301}
302
303pub fn fit_content<T: TaffyFitContent>(argument: LengthPercentage) -> T {
306 T::fit_content(argument)
307}
308
309pub trait TaffyFitContent {
311 fn fit_content(argument: LengthPercentage) -> Self;
313}
314impl<T: TaffyFitContent> TaffyFitContent for Point<T> {
315 fn fit_content(argument: LengthPercentage) -> Self {
316 Point { x: T::fit_content(argument), y: T::fit_content(argument) }
317 }
318}
319impl<T: TaffyFitContent> Point<T> {
320 pub fn fit_content(argument: LengthPercentage) -> Self {
323 fit_content(argument)
324 }
325}
326impl<T: TaffyFitContent> TaffyFitContent for Line<T> {
327 fn fit_content(argument: LengthPercentage) -> Self {
328 Line { start: T::fit_content(argument), end: T::fit_content(argument) }
329 }
330}
331impl<T: TaffyFitContent> Line<T> {
332 pub fn fit_content(argument: LengthPercentage) -> Self {
335 fit_content(argument)
336 }
337}
338impl<T: TaffyFitContent> TaffyFitContent for Size<T> {
339 fn fit_content(argument: LengthPercentage) -> Self {
340 Size { width: T::fit_content(argument), height: T::fit_content(argument) }
341 }
342}
343impl<T: TaffyFitContent> Size<T> {
344 pub fn fit_content(argument: LengthPercentage) -> Self {
347 fit_content(argument)
348 }
349}
350impl<T: TaffyFitContent> TaffyFitContent for Rect<T> {
351 fn fit_content(argument: LengthPercentage) -> Self {
352 Rect {
353 left: T::fit_content(argument),
354 right: T::fit_content(argument),
355 top: T::fit_content(argument),
356 bottom: T::fit_content(argument),
357 }
358 }
359}
360impl<T: TaffyFitContent> Rect<T> {
361 pub fn fit_content(argument: LengthPercentage) -> Self {
364 fit_content(argument)
365 }
366}
367
368pub fn length<Input: Into<f32> + Copy, T: FromLength>(value: Input) -> T {
370 T::from_length(value)
371}
372
373pub trait FromLength {
375 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self;
377}
378impl FromLength for f32 {
379 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
380 value.into()
381 }
382}
383impl FromLength for Option<f32> {
384 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
385 Some(value.into())
386 }
387}
388impl<T: FromLength> FromLength for Point<T> {
389 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
390 Point { x: T::from_length(value.into()), y: T::from_length(value.into()) }
391 }
392}
393impl<T: FromLength> Point<T> {
394 pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
396 length::<Input, Self>(value)
397 }
398}
399impl<T: FromLength> FromLength for Line<T> {
400 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
401 Line { start: T::from_length(value.into()), end: T::from_length(value.into()) }
402 }
403}
404impl<T: FromLength> Line<T> {
405 pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
407 length::<Input, Self>(value)
408 }
409}
410impl<T: FromLength> FromLength for Size<T> {
411 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
412 Size { width: T::from_length(value.into()), height: T::from_length(value.into()) }
413 }
414}
415impl<T: FromLength> Size<T> {
416 pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
418 length::<Input, Self>(value)
419 }
420}
421impl<T: FromLength> FromLength for Rect<T> {
422 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
423 Rect {
424 left: T::from_length(value.into()),
425 right: T::from_length(value.into()),
426 top: T::from_length(value.into()),
427 bottom: T::from_length(value.into()),
428 }
429 }
430}
431impl<T: FromLength> Rect<T> {
432 pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
434 length::<Input, Self>(value)
435 }
436}
437
438pub fn percent<Input: Into<f32> + Copy, T: FromPercent>(percent: Input) -> T {
440 T::from_percent(percent)
441}
442
443pub trait FromPercent {
445 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self;
447}
448impl FromPercent for f32 {
449 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
450 percent.into()
451 }
452}
453impl FromPercent for Option<f32> {
454 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
455 Some(percent.into())
456 }
457}
458impl<T: FromPercent> FromPercent for Point<T> {
459 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
460 Point { x: T::from_percent(percent.into()), y: T::from_percent(percent.into()) }
461 }
462}
463impl<T: FromPercent> Point<T> {
464 pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
467 percent::<Input, Self>(percent_value)
468 }
469}
470impl<T: FromPercent> FromPercent for Line<T> {
471 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
472 Line { start: T::from_percent(percent.into()), end: T::from_percent(percent.into()) }
473 }
474}
475impl<T: FromPercent> Line<T> {
476 pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
479 percent::<Input, Self>(percent_value)
480 }
481}
482impl<T: FromPercent> FromPercent for Size<T> {
483 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
484 Size { width: T::from_percent(percent.into()), height: T::from_percent(percent.into()) }
485 }
486}
487impl<T: FromPercent> Size<T> {
488 pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
491 percent::<Input, Self>(percent_value)
492 }
493}
494impl<T: FromPercent> FromPercent for Rect<T> {
495 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
496 Rect {
497 left: T::from_percent(percent.into()),
498 right: T::from_percent(percent.into()),
499 top: T::from_percent(percent.into()),
500 bottom: T::from_percent(percent.into()),
501 }
502 }
503}
504impl<T: FromPercent> Rect<T> {
505 pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
508 percent::<Input, Self>(percent_value)
509 }
510}
511
512#[cfg(feature = "grid")]
514pub fn fr<Input: Into<f32> + Copy, T: FromFlex>(flex: Input) -> T {
515 T::from_flex(flex)
516}
517
518pub trait FromFlex {
520 fn from_flex<Input: Into<f32> + Copy>(flex: Input) -> Self;
522}
523
524#[cfg(feature = "grid")]
525#[cfg(test)]
526mod repeat_fn_tests {
527 use super::repeat;
528 use crate::style::{GridTrackRepetition, NonRepeatedTrackSizingFunction, TrackSizingFunction};
529
530 const TEST_VEC: Vec<NonRepeatedTrackSizingFunction> = Vec::new();
531
532 #[test]
533 fn test_repeat_u16() {
534 assert_eq!(repeat(123, TEST_VEC), TrackSizingFunction::Repeat(GridTrackRepetition::Count(123), TEST_VEC));
535 }
536
537 #[test]
538 fn test_repeat_auto_fit_str() {
539 assert_eq!(repeat("auto-fit", TEST_VEC), TrackSizingFunction::Repeat(GridTrackRepetition::AutoFit, TEST_VEC));
540 }
541
542 #[test]
543 fn test_repeat_auto_fill_str() {
544 assert_eq!(repeat("auto-fill", TEST_VEC), TrackSizingFunction::Repeat(GridTrackRepetition::AutoFill, TEST_VEC));
545 }
546}