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 GridTemplateComponent, GridTemplateRepetition, MaxTrackSizingFunction, MinTrackSizingFunction, RepetitionCount,
12 TrackSizingFunction,
13 },
14 util::sys::Vec,
15 CheapCloneStr,
16};
17#[cfg(feature = "grid")]
18use core::fmt::Debug;
19
20#[cfg(feature = "grid")]
22pub fn repeat<Input, S>(repetition_kind: Input, tracks: Vec<TrackSizingFunction>) -> GridTemplateComponent<S>
23where
24 Input: TryInto<RepetitionCount>,
25 <Input as TryInto<RepetitionCount>>::Error: Debug,
26 S: CheapCloneStr,
27{
28 GridTemplateComponent::Repeat(GridTemplateRepetition {
29 count: repetition_kind.try_into().unwrap(),
30 tracks,
31 line_names: Vec::new(),
32 })
33}
34
35#[cfg(feature = "grid")]
36pub fn evenly_sized_tracks<S: CheapCloneStr>(count: u16) -> Vec<GridTemplateComponent<S>> {
38 use crate::util::sys::new_vec_with_capacity;
39 let mut repeated_tracks = new_vec_with_capacity(1);
40 repeated_tracks.push(flex(1.0f32));
41 let mut tracks = new_vec_with_capacity(1);
42 tracks.push(repeat(count, repeated_tracks));
43 tracks
44}
45
46pub fn line<T: TaffyGridLine>(index: i16) -> T {
51 T::from_line_index(index)
52}
53pub trait TaffyGridLine {
55 fn from_line_index(index: i16) -> Self;
57}
58
59pub fn span<T: TaffyGridSpan>(span: u16) -> T {
61 T::from_span(span)
62}
63pub trait TaffyGridSpan {
65 fn from_span(span: u16) -> Self;
67}
68
69#[cfg(feature = "grid")]
71pub fn minmax<Output>(min: MinTrackSizingFunction, max: MaxTrackSizingFunction) -> Output
72where
73 Output: From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>>,
74{
75 MinMax { min, max }.into()
76}
77
78#[cfg(feature = "grid")]
80pub fn flex<Input, Output>(flex_fraction: Input) -> Output
81where
82 Input: Into<f32> + Copy,
83 Output: From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>>,
84{
85 MinMax { min: zero(), max: fr(flex_fraction.into()) }.into()
86}
87
88pub const fn zero<T: TaffyZero>() -> T {
90 T::ZERO
91}
92
93pub trait TaffyZero {
95 const ZERO: Self;
97}
98impl TaffyZero for f32 {
99 const ZERO: f32 = 0.0;
100}
101impl<T: TaffyZero> TaffyZero for Option<T> {
102 const ZERO: Option<T> = Some(T::ZERO);
103}
104impl<T: TaffyZero> TaffyZero for Point<T> {
105 const ZERO: Point<T> = Point { x: T::ZERO, y: T::ZERO };
106}
107impl<T: TaffyZero> Point<T> {
108 pub const fn zero() -> Self {
111 zero::<Self>()
112 }
113}
114impl<T: TaffyZero> TaffyZero for Line<T> {
115 const ZERO: Line<T> = Line { start: T::ZERO, end: T::ZERO };
116}
117impl<T: TaffyZero> Line<T> {
118 pub const fn zero() -> Self {
121 zero::<Self>()
122 }
123}
124impl<T: TaffyZero> TaffyZero for Size<T> {
125 const ZERO: Size<T> = Size { width: T::ZERO, height: T::ZERO };
126}
127impl<T: TaffyZero> Size<T> {
128 pub const fn zero() -> Self {
131 zero::<Self>()
132 }
133}
134impl<T: TaffyZero> TaffyZero for Rect<T> {
135 const ZERO: Rect<T> = Rect { left: T::ZERO, right: T::ZERO, top: T::ZERO, bottom: T::ZERO };
136}
137impl<T: TaffyZero> Rect<T> {
138 pub const fn zero() -> Self {
141 zero::<Self>()
142 }
143}
144
145pub const fn auto<T: TaffyAuto>() -> T {
147 T::AUTO
148}
149
150pub trait TaffyAuto {
152 const AUTO: Self;
154}
155impl<T: TaffyAuto> TaffyAuto for Option<T> {
156 const AUTO: Option<T> = Some(T::AUTO);
157}
158impl<T: TaffyAuto> TaffyAuto for Point<T> {
159 const AUTO: Point<T> = Point { x: T::AUTO, y: T::AUTO };
160}
161impl<T: TaffyAuto> Point<T> {
162 pub const fn auto() -> Self {
165 auto::<Self>()
166 }
167}
168impl<T: TaffyAuto> TaffyAuto for Line<T> {
169 const AUTO: Line<T> = Line { start: T::AUTO, end: T::AUTO };
170}
171impl<T: TaffyAuto> Line<T> {
172 pub const fn auto() -> Self {
175 auto::<Self>()
176 }
177}
178impl<T: TaffyAuto> TaffyAuto for Size<T> {
179 const AUTO: Size<T> = Size { width: T::AUTO, height: T::AUTO };
180}
181impl<T: TaffyAuto> Size<T> {
182 pub const fn auto() -> Self {
185 auto::<Self>()
186 }
187}
188impl<T: TaffyAuto> TaffyAuto for Rect<T> {
189 const AUTO: Rect<T> = Rect { left: T::AUTO, right: T::AUTO, top: T::AUTO, bottom: T::AUTO };
190}
191impl<T: TaffyAuto> Rect<T> {
192 pub const fn auto() -> Self {
195 auto::<Self>()
196 }
197}
198
199pub const fn min_content<T: TaffyMinContent>() -> T {
201 T::MIN_CONTENT
202}
203
204pub trait TaffyMinContent {
206 const MIN_CONTENT: Self;
208}
209impl<T: TaffyMinContent> TaffyMinContent for Option<T> {
210 const MIN_CONTENT: Option<T> = Some(T::MIN_CONTENT);
211}
212impl<T: TaffyMinContent> TaffyMinContent for Point<T> {
213 const MIN_CONTENT: Point<T> = Point { x: T::MIN_CONTENT, y: T::MIN_CONTENT };
214}
215impl<T: TaffyMinContent> Point<T> {
216 pub const fn min_content() -> Self {
219 min_content::<Self>()
220 }
221}
222impl<T: TaffyMinContent> TaffyMinContent for Line<T> {
223 const MIN_CONTENT: Line<T> = Line { start: T::MIN_CONTENT, end: T::MIN_CONTENT };
224}
225impl<T: TaffyMinContent> Line<T> {
226 pub const fn min_content() -> Self {
229 min_content::<Self>()
230 }
231}
232impl<T: TaffyMinContent> TaffyMinContent for Size<T> {
233 const MIN_CONTENT: Size<T> = Size { width: T::MIN_CONTENT, height: T::MIN_CONTENT };
234}
235impl<T: TaffyMinContent> Size<T> {
236 pub const fn min_content() -> Self {
239 min_content::<Self>()
240 }
241}
242impl<T: TaffyMinContent> TaffyMinContent for Rect<T> {
243 const MIN_CONTENT: Rect<T> =
244 Rect { left: T::MIN_CONTENT, right: T::MIN_CONTENT, top: T::MIN_CONTENT, bottom: T::MIN_CONTENT };
245}
246impl<T: TaffyMinContent> Rect<T> {
247 pub const fn min_content() -> Self {
250 min_content::<Self>()
251 }
252}
253
254pub const fn max_content<T: TaffyMaxContent>() -> T {
256 T::MAX_CONTENT
257}
258
259pub trait TaffyMaxContent {
261 const MAX_CONTENT: Self;
263}
264impl<T: TaffyMaxContent> TaffyMaxContent for Option<T> {
265 const MAX_CONTENT: Option<T> = Some(T::MAX_CONTENT);
266}
267impl<T: TaffyMaxContent> TaffyMaxContent for Point<T> {
268 const MAX_CONTENT: Point<T> = Point { x: T::MAX_CONTENT, y: T::MAX_CONTENT };
269}
270impl<T: TaffyMaxContent> Point<T> {
271 pub const fn max_content() -> Self {
274 max_content::<Self>()
275 }
276}
277impl<T: TaffyMaxContent> TaffyMaxContent for Line<T> {
278 const MAX_CONTENT: Line<T> = Line { start: T::MAX_CONTENT, end: T::MAX_CONTENT };
279}
280impl<T: TaffyMaxContent> Line<T> {
281 pub const fn max_content() -> Self {
284 max_content::<Self>()
285 }
286}
287impl<T: TaffyMaxContent> TaffyMaxContent for Size<T> {
288 const MAX_CONTENT: Size<T> = Size { width: T::MAX_CONTENT, height: T::MAX_CONTENT };
289}
290impl<T: TaffyMaxContent> Size<T> {
291 pub const fn max_content() -> Self {
294 max_content::<Self>()
295 }
296}
297impl<T: TaffyMaxContent> TaffyMaxContent for Rect<T> {
298 const MAX_CONTENT: Rect<T> =
299 Rect { left: T::MAX_CONTENT, right: T::MAX_CONTENT, top: T::MAX_CONTENT, bottom: T::MAX_CONTENT };
300}
301impl<T: TaffyMaxContent> Rect<T> {
302 pub const fn max_content() -> Self {
305 max_content::<Self>()
306 }
307}
308
309pub fn fit_content<T: TaffyFitContent>(argument: LengthPercentage) -> T {
312 T::fit_content(argument)
313}
314
315pub trait TaffyFitContent {
317 fn fit_content(argument: LengthPercentage) -> Self;
319}
320impl<T: TaffyFitContent> TaffyFitContent for Point<T> {
321 fn fit_content(argument: LengthPercentage) -> Self {
322 Point { x: T::fit_content(argument), y: T::fit_content(argument) }
323 }
324}
325impl<T: TaffyFitContent> Point<T> {
326 pub fn fit_content(argument: LengthPercentage) -> Self {
329 fit_content(argument)
330 }
331}
332impl<T: TaffyFitContent> TaffyFitContent for Line<T> {
333 fn fit_content(argument: LengthPercentage) -> Self {
334 Line { start: T::fit_content(argument), end: T::fit_content(argument) }
335 }
336}
337impl<T: TaffyFitContent> Line<T> {
338 pub fn fit_content(argument: LengthPercentage) -> Self {
341 fit_content(argument)
342 }
343}
344impl<T: TaffyFitContent> TaffyFitContent for Size<T> {
345 fn fit_content(argument: LengthPercentage) -> Self {
346 Size { width: T::fit_content(argument), height: T::fit_content(argument) }
347 }
348}
349impl<T: TaffyFitContent> Size<T> {
350 pub fn fit_content(argument: LengthPercentage) -> Self {
353 fit_content(argument)
354 }
355}
356impl<T: TaffyFitContent> TaffyFitContent for Rect<T> {
357 fn fit_content(argument: LengthPercentage) -> Self {
358 Rect {
359 left: T::fit_content(argument),
360 right: T::fit_content(argument),
361 top: T::fit_content(argument),
362 bottom: T::fit_content(argument),
363 }
364 }
365}
366impl<T: TaffyFitContent> Rect<T> {
367 pub fn fit_content(argument: LengthPercentage) -> Self {
370 fit_content(argument)
371 }
372}
373
374pub fn length<Input: Into<f32> + Copy, T: FromLength>(value: Input) -> T {
376 T::from_length(value)
377}
378
379pub trait FromLength {
381 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self;
383}
384impl FromLength for f32 {
385 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
386 value.into()
387 }
388}
389impl FromLength for Option<f32> {
390 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
391 Some(value.into())
392 }
393}
394impl<T: FromLength> FromLength for Point<T> {
395 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
396 Point { x: T::from_length(value.into()), y: T::from_length(value.into()) }
397 }
398}
399impl<T: FromLength> Point<T> {
400 pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
402 length::<Input, Self>(value)
403 }
404}
405impl<T: FromLength> FromLength for Line<T> {
406 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
407 Line { start: T::from_length(value.into()), end: T::from_length(value.into()) }
408 }
409}
410impl<T: FromLength> Line<T> {
411 pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
413 length::<Input, Self>(value)
414 }
415}
416impl<T: FromLength> FromLength for Size<T> {
417 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
418 Size { width: T::from_length(value.into()), height: T::from_length(value.into()) }
419 }
420}
421impl<T: FromLength> Size<T> {
422 pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
424 length::<Input, Self>(value)
425 }
426}
427impl<T: FromLength> FromLength for Rect<T> {
428 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
429 Rect {
430 left: T::from_length(value.into()),
431 right: T::from_length(value.into()),
432 top: T::from_length(value.into()),
433 bottom: T::from_length(value.into()),
434 }
435 }
436}
437impl<T: FromLength> Rect<T> {
438 pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
440 length::<Input, Self>(value)
441 }
442}
443
444pub fn percent<Input: Into<f32> + Copy, T: FromPercent>(percent: Input) -> T {
446 T::from_percent(percent)
447}
448
449pub trait FromPercent {
451 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self;
453}
454impl FromPercent for f32 {
455 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
456 percent.into()
457 }
458}
459impl FromPercent for Option<f32> {
460 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
461 Some(percent.into())
462 }
463}
464impl<T: FromPercent> FromPercent for Point<T> {
465 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
466 Point { x: T::from_percent(percent.into()), y: T::from_percent(percent.into()) }
467 }
468}
469impl<T: FromPercent> Point<T> {
470 pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
473 percent::<Input, Self>(percent_value)
474 }
475}
476impl<T: FromPercent> FromPercent for Line<T> {
477 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
478 Line { start: T::from_percent(percent.into()), end: T::from_percent(percent.into()) }
479 }
480}
481impl<T: FromPercent> Line<T> {
482 pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
485 percent::<Input, Self>(percent_value)
486 }
487}
488impl<T: FromPercent> FromPercent for Size<T> {
489 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
490 Size { width: T::from_percent(percent.into()), height: T::from_percent(percent.into()) }
491 }
492}
493impl<T: FromPercent> Size<T> {
494 pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
497 percent::<Input, Self>(percent_value)
498 }
499}
500impl<T: FromPercent> FromPercent for Rect<T> {
501 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
502 Rect {
503 left: T::from_percent(percent.into()),
504 right: T::from_percent(percent.into()),
505 top: T::from_percent(percent.into()),
506 bottom: T::from_percent(percent.into()),
507 }
508 }
509}
510impl<T: FromPercent> Rect<T> {
511 pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
514 percent::<Input, Self>(percent_value)
515 }
516}
517
518#[cfg(feature = "grid")]
520pub fn fr<Input: Into<f32> + Copy, T: FromFr>(flex: Input) -> T {
521 T::from_fr(flex)
522}
523
524pub trait FromFr {
526 fn from_fr<Input: Into<f32> + Copy>(flex: Input) -> Self;
528}
529
530#[cfg(feature = "grid")]
531#[cfg(test)]
532mod repeat_fn_tests {
533 type S = crate::sys::DefaultCheapStr;
534 use super::repeat;
535 use crate::{
536 style::{GridTemplateComponent, RepetitionCount, TrackSizingFunction},
537 GridTemplateRepetition,
538 };
539
540 const TEST_VEC: Vec<TrackSizingFunction> = Vec::new();
541
542 #[test]
543 fn test_repeat_u16() {
544 assert_eq!(
545 repeat::<_, S>(123, TEST_VEC),
546 GridTemplateComponent::Repeat(GridTemplateRepetition {
547 count: RepetitionCount::Count(123),
548 tracks: TEST_VEC,
549 line_names: Vec::new(),
550 })
551 );
552 }
553
554 #[test]
555 fn test_repeat_auto_fit_str() {
556 assert_eq!(
557 repeat::<_, S>("auto-fit", TEST_VEC),
558 GridTemplateComponent::Repeat(GridTemplateRepetition {
559 count: RepetitionCount::AutoFit,
560 tracks: TEST_VEC,
561 line_names: Vec::new(),
562 })
563 );
564 }
565
566 #[test]
567 fn test_repeat_auto_fill_str() {
568 assert_eq!(
569 repeat::<_, S>("auto-fill", TEST_VEC),
570 GridTemplateComponent::Repeat(GridTemplateRepetition {
571 count: RepetitionCount::AutoFill,
572 tracks: TEST_VEC,
573 line_names: Vec::new(),
574 })
575 );
576 }
577}