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")]
22#[inline(always)]
23pub fn repeat<Input, S>(repetition_kind: Input, tracks: Vec<TrackSizingFunction>) -> GridTemplateComponent<S>
24where
25 Input: TryInto<RepetitionCount>,
26 <Input as TryInto<RepetitionCount>>::Error: Debug,
27 S: CheapCloneStr,
28{
29 GridTemplateComponent::Repeat(GridTemplateRepetition {
30 count: repetition_kind.try_into().unwrap(),
31 tracks,
32 line_names: Vec::new(),
33 })
34}
35
36#[cfg(feature = "grid")]
37pub fn evenly_sized_tracks<S: CheapCloneStr>(count: u16) -> Vec<GridTemplateComponent<S>> {
39 use crate::util::sys::new_vec_with_capacity;
40 let mut repeated_tracks = new_vec_with_capacity(1);
41 repeated_tracks.push(flex(1.0f32));
42 let mut tracks = new_vec_with_capacity(1);
43 tracks.push(repeat(count, repeated_tracks));
44 tracks
45}
46
47#[inline(always)]
52pub fn line<T: TaffyGridLine>(index: i16) -> T {
53 T::from_line_index(index)
54}
55pub trait TaffyGridLine {
57 fn from_line_index(index: i16) -> Self;
59}
60
61#[inline(always)]
63pub fn span<T: TaffyGridSpan>(span: u16) -> T {
64 T::from_span(span)
65}
66pub trait TaffyGridSpan {
68 fn from_span(span: u16) -> Self;
70}
71
72#[cfg(feature = "grid")]
74#[inline(always)]
75pub fn minmax<Output>(min: MinTrackSizingFunction, max: MaxTrackSizingFunction) -> Output
76where
77 Output: From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>>,
78{
79 MinMax { min, max }.into()
80}
81
82#[cfg(feature = "grid")]
84#[inline(always)]
85pub fn flex<Input, Output>(flex_fraction: Input) -> Output
86where
87 Input: Into<f64> + Copy,
88 Output: From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>>,
89{
90 MinMax { min: zero(), max: fr(flex_fraction) }.into()
91}
92
93#[inline(always)]
95pub const fn zero<T: TaffyZero>() -> T {
96 T::ZERO
97}
98
99pub trait TaffyZero {
101 const ZERO: Self;
103}
104impl TaffyZero for f32 {
105 const ZERO: f32 = 0.0;
106}
107impl<T: TaffyZero> TaffyZero for Option<T> {
108 const ZERO: Option<T> = Some(T::ZERO);
109}
110impl<T: TaffyZero> TaffyZero for Point<T> {
111 const ZERO: Point<T> = Point { x: T::ZERO, y: T::ZERO };
112}
113impl<T: TaffyZero> Point<T> {
114 #[inline(always)]
117 pub const fn zero() -> Self {
118 zero::<Self>()
119 }
120}
121impl<T: TaffyZero> TaffyZero for Line<T> {
122 const ZERO: Line<T> = Line { start: T::ZERO, end: T::ZERO };
123}
124impl<T: TaffyZero> Line<T> {
125 #[inline(always)]
128 pub const fn zero() -> Self {
129 zero::<Self>()
130 }
131}
132impl<T: TaffyZero> TaffyZero for Size<T> {
133 const ZERO: Size<T> = Size { width: T::ZERO, height: T::ZERO };
134}
135impl<T: TaffyZero> Size<T> {
136 #[inline(always)]
139 pub const fn zero() -> Self {
140 zero::<Self>()
141 }
142}
143impl<T: TaffyZero> TaffyZero for Rect<T> {
144 const ZERO: Rect<T> = Rect { left: T::ZERO, right: T::ZERO, top: T::ZERO, bottom: T::ZERO };
145}
146impl<T: TaffyZero> Rect<T> {
147 #[inline(always)]
150 pub const fn zero() -> Self {
151 zero::<Self>()
152 }
153}
154
155#[inline(always)]
157pub const fn auto<T: TaffyAuto>() -> T {
158 T::AUTO
159}
160
161pub trait TaffyAuto {
163 const AUTO: Self;
165}
166impl<T: TaffyAuto> TaffyAuto for Option<T> {
167 const AUTO: Option<T> = Some(T::AUTO);
168}
169impl<T: TaffyAuto> TaffyAuto for Point<T> {
170 const AUTO: Point<T> = Point { x: T::AUTO, y: T::AUTO };
171}
172impl<T: TaffyAuto> Point<T> {
173 #[inline(always)]
176 pub const fn auto() -> Self {
177 auto::<Self>()
178 }
179}
180impl<T: TaffyAuto> TaffyAuto for Line<T> {
181 const AUTO: Line<T> = Line { start: T::AUTO, end: T::AUTO };
182}
183impl<T: TaffyAuto> Line<T> {
184 #[inline(always)]
187 pub const fn auto() -> Self {
188 auto::<Self>()
189 }
190}
191impl<T: TaffyAuto> TaffyAuto for Size<T> {
192 const AUTO: Size<T> = Size { width: T::AUTO, height: T::AUTO };
193}
194impl<T: TaffyAuto> Size<T> {
195 #[inline(always)]
198 pub const fn auto() -> Self {
199 auto::<Self>()
200 }
201}
202impl<T: TaffyAuto> TaffyAuto for Rect<T> {
203 const AUTO: Rect<T> = Rect { left: T::AUTO, right: T::AUTO, top: T::AUTO, bottom: T::AUTO };
204}
205impl<T: TaffyAuto> Rect<T> {
206 #[inline(always)]
209 pub const fn auto() -> Self {
210 auto::<Self>()
211 }
212}
213
214#[inline(always)]
216pub const fn min_content<T: TaffyMinContent>() -> T {
217 T::MIN_CONTENT
218}
219
220pub trait TaffyMinContent {
222 const MIN_CONTENT: Self;
224}
225impl<T: TaffyMinContent> TaffyMinContent for Option<T> {
226 const MIN_CONTENT: Option<T> = Some(T::MIN_CONTENT);
227}
228impl<T: TaffyMinContent> TaffyMinContent for Point<T> {
229 const MIN_CONTENT: Point<T> = Point { x: T::MIN_CONTENT, y: T::MIN_CONTENT };
230}
231impl<T: TaffyMinContent> Point<T> {
232 #[inline(always)]
235 pub const fn min_content() -> Self {
236 min_content::<Self>()
237 }
238}
239impl<T: TaffyMinContent> TaffyMinContent for Line<T> {
240 const MIN_CONTENT: Line<T> = Line { start: T::MIN_CONTENT, end: T::MIN_CONTENT };
241}
242impl<T: TaffyMinContent> Line<T> {
243 #[inline(always)]
246 pub const fn min_content() -> Self {
247 min_content::<Self>()
248 }
249}
250impl<T: TaffyMinContent> TaffyMinContent for Size<T> {
251 const MIN_CONTENT: Size<T> = Size { width: T::MIN_CONTENT, height: T::MIN_CONTENT };
252}
253impl<T: TaffyMinContent> Size<T> {
254 #[inline(always)]
257 pub const fn min_content() -> Self {
258 min_content::<Self>()
259 }
260}
261impl<T: TaffyMinContent> TaffyMinContent for Rect<T> {
262 const MIN_CONTENT: Rect<T> =
263 Rect { left: T::MIN_CONTENT, right: T::MIN_CONTENT, top: T::MIN_CONTENT, bottom: T::MIN_CONTENT };
264}
265impl<T: TaffyMinContent> Rect<T> {
266 #[inline(always)]
269 pub const fn min_content() -> Self {
270 min_content::<Self>()
271 }
272}
273
274#[inline(always)]
276pub const fn max_content<T: TaffyMaxContent>() -> T {
277 T::MAX_CONTENT
278}
279
280pub trait TaffyMaxContent {
282 const MAX_CONTENT: Self;
284}
285impl<T: TaffyMaxContent> TaffyMaxContent for Option<T> {
286 const MAX_CONTENT: Option<T> = Some(T::MAX_CONTENT);
287}
288impl<T: TaffyMaxContent> TaffyMaxContent for Point<T> {
289 const MAX_CONTENT: Point<T> = Point { x: T::MAX_CONTENT, y: T::MAX_CONTENT };
290}
291impl<T: TaffyMaxContent> Point<T> {
292 #[inline(always)]
295 pub const fn max_content() -> Self {
296 max_content::<Self>()
297 }
298}
299impl<T: TaffyMaxContent> TaffyMaxContent for Line<T> {
300 const MAX_CONTENT: Line<T> = Line { start: T::MAX_CONTENT, end: T::MAX_CONTENT };
301}
302impl<T: TaffyMaxContent> Line<T> {
303 #[inline(always)]
306 pub const fn max_content() -> Self {
307 max_content::<Self>()
308 }
309}
310impl<T: TaffyMaxContent> TaffyMaxContent for Size<T> {
311 const MAX_CONTENT: Size<T> = Size { width: T::MAX_CONTENT, height: T::MAX_CONTENT };
312}
313impl<T: TaffyMaxContent> Size<T> {
314 #[inline(always)]
317 pub const fn max_content() -> Self {
318 max_content::<Self>()
319 }
320}
321impl<T: TaffyMaxContent> TaffyMaxContent for Rect<T> {
322 const MAX_CONTENT: Rect<T> =
323 Rect { left: T::MAX_CONTENT, right: T::MAX_CONTENT, top: T::MAX_CONTENT, bottom: T::MAX_CONTENT };
324}
325impl<T: TaffyMaxContent> Rect<T> {
326 #[inline(always)]
329 pub const fn max_content() -> Self {
330 max_content::<Self>()
331 }
332}
333
334#[inline(always)]
337pub fn fit_content<T: TaffyFitContent>(argument: LengthPercentage) -> T {
338 T::fit_content(argument)
339}
340
341pub trait TaffyFitContent {
343 fn fit_content(argument: LengthPercentage) -> Self;
345}
346impl<T: TaffyFitContent> TaffyFitContent for Point<T> {
347 #[inline(always)]
348 fn fit_content(argument: LengthPercentage) -> Self {
349 Point { x: T::fit_content(argument), y: T::fit_content(argument) }
350 }
351}
352impl<T: TaffyFitContent> Point<T> {
353 #[inline(always)]
356 pub fn fit_content(argument: LengthPercentage) -> Self {
357 fit_content(argument)
358 }
359}
360impl<T: TaffyFitContent> TaffyFitContent for Line<T> {
361 #[inline(always)]
362 fn fit_content(argument: LengthPercentage) -> Self {
363 Line { start: T::fit_content(argument), end: T::fit_content(argument) }
364 }
365}
366impl<T: TaffyFitContent> Line<T> {
367 #[inline(always)]
370 pub fn fit_content(argument: LengthPercentage) -> Self {
371 fit_content(argument)
372 }
373}
374impl<T: TaffyFitContent> TaffyFitContent for Size<T> {
375 #[inline(always)]
376 fn fit_content(argument: LengthPercentage) -> Self {
377 Size { width: T::fit_content(argument), height: T::fit_content(argument) }
378 }
379}
380impl<T: TaffyFitContent> Size<T> {
381 #[inline(always)]
384 pub fn fit_content(argument: LengthPercentage) -> Self {
385 fit_content(argument)
386 }
387}
388impl<T: TaffyFitContent> TaffyFitContent for Rect<T> {
389 #[inline(always)]
390 fn fit_content(argument: LengthPercentage) -> Self {
391 Rect {
392 left: T::fit_content(argument),
393 right: T::fit_content(argument),
394 top: T::fit_content(argument),
395 bottom: T::fit_content(argument),
396 }
397 }
398}
399impl<T: TaffyFitContent> Rect<T> {
400 #[inline(always)]
403 pub fn fit_content(argument: LengthPercentage) -> Self {
404 fit_content(argument)
405 }
406}
407
408#[inline(always)]
410pub fn length<Input: Into<f64> + Copy, T: FromLength>(value: Input) -> T {
411 T::from_length(value)
412}
413
414pub trait FromLength {
416 fn from_length<Input: Into<f64> + Copy>(value: Input) -> Self;
418}
419impl FromLength for f32 {
420 #[inline(always)]
421 fn from_length<Input: Into<f64> + Copy>(value: Input) -> Self {
422 value.into() as f32
423 }
424}
425impl FromLength for Option<f32> {
426 #[inline(always)]
427 fn from_length<Input: Into<f64> + Copy>(value: Input) -> Self {
428 Some(value.into() as f32)
429 }
430}
431impl<T: FromLength> FromLength for Point<T> {
432 #[inline(always)]
433 fn from_length<Input: Into<f64> + Copy>(value: Input) -> Self {
434 Point { x: T::from_length(value), y: T::from_length(value) }
435 }
436}
437impl<T: FromLength> Point<T> {
438 #[inline(always)]
440 pub fn length<Input: Into<f64> + Copy>(value: Input) -> Self {
441 length::<Input, Self>(value)
442 }
443}
444impl<T: FromLength> FromLength for Line<T> {
445 #[inline(always)]
446 fn from_length<Input: Into<f64> + Copy>(value: Input) -> Self {
447 Line { start: T::from_length(value), end: T::from_length(value) }
448 }
449}
450impl<T: FromLength> Line<T> {
451 #[inline(always)]
453 pub fn length<Input: Into<f64> + Copy>(value: Input) -> Self {
454 length::<Input, Self>(value)
455 }
456}
457impl<T: FromLength> FromLength for Size<T> {
458 #[inline(always)]
459 fn from_length<Input: Into<f64> + Copy>(value: Input) -> Self {
460 Size { width: T::from_length(value), height: T::from_length(value) }
461 }
462}
463impl<T: FromLength> Size<T> {
464 #[inline(always)]
466 pub fn length<Input: Into<f64> + Copy>(value: Input) -> Self {
467 length::<Input, Self>(value)
468 }
469}
470impl<T: FromLength> FromLength for Rect<T> {
471 #[inline(always)]
472 fn from_length<Input: Into<f64> + Copy>(value: Input) -> Self {
473 Rect {
474 left: T::from_length(value),
475 right: T::from_length(value),
476 top: T::from_length(value),
477 bottom: T::from_length(value),
478 }
479 }
480}
481impl<T: FromLength> Rect<T> {
482 #[inline(always)]
484 pub fn length<Input: Into<f64> + Copy>(value: Input) -> Self {
485 length::<Input, Self>(value)
486 }
487}
488
489#[inline(always)]
491pub fn percent<Input: Into<f64> + Copy, T: FromPercent>(percent: Input) -> T {
492 T::from_percent(percent)
493}
494
495pub trait FromPercent {
497 fn from_percent<Input: Into<f64> + Copy>(percent: Input) -> Self;
499}
500impl FromPercent for f32 {
501 #[inline(always)]
502 fn from_percent<Input: Into<f64> + Copy>(percent: Input) -> Self {
503 percent.into() as f32
504 }
505}
506impl FromPercent for Option<f32> {
507 #[inline(always)]
508 fn from_percent<Input: Into<f64> + Copy>(percent: Input) -> Self {
509 Some(percent.into() as f32)
510 }
511}
512impl<T: FromPercent> FromPercent for Point<T> {
513 #[inline(always)]
514 fn from_percent<Input: Into<f64> + Copy>(percent: Input) -> Self {
515 Point { x: T::from_percent(percent), y: T::from_percent(percent) }
516 }
517}
518impl<T: FromPercent> Point<T> {
519 #[inline(always)]
522 pub fn percent<Input: Into<f64> + Copy>(percent_value: Input) -> Self {
523 percent::<Input, Self>(percent_value)
524 }
525}
526impl<T: FromPercent> FromPercent for Line<T> {
527 #[inline(always)]
528 fn from_percent<Input: Into<f64> + Copy>(percent: Input) -> Self {
529 Line { start: T::from_percent(percent), end: T::from_percent(percent) }
530 }
531}
532impl<T: FromPercent> Line<T> {
533 #[inline(always)]
536 pub fn percent<Input: Into<f64> + Copy>(percent_value: Input) -> Self {
537 percent::<Input, Self>(percent_value)
538 }
539}
540impl<T: FromPercent> FromPercent for Size<T> {
541 #[inline(always)]
542 fn from_percent<Input: Into<f64> + Copy>(percent: Input) -> Self {
543 Size { width: T::from_percent(percent), height: T::from_percent(percent) }
544 }
545}
546impl<T: FromPercent> Size<T> {
547 #[inline(always)]
550 pub fn percent<Input: Into<f64> + Copy>(percent_value: Input) -> Self {
551 percent::<Input, Self>(percent_value)
552 }
553}
554impl<T: FromPercent> FromPercent for Rect<T> {
555 #[inline(always)]
556 fn from_percent<Input: Into<f64> + Copy>(percent: Input) -> Self {
557 Rect {
558 left: T::from_percent(percent),
559 right: T::from_percent(percent),
560 top: T::from_percent(percent),
561 bottom: T::from_percent(percent),
562 }
563 }
564}
565impl<T: FromPercent> Rect<T> {
566 #[inline(always)]
569 pub fn percent<Input: Into<f64> + Copy>(percent_value: Input) -> Self {
570 percent::<Input, Self>(percent_value)
571 }
572}
573
574#[cfg(feature = "grid")]
576#[inline(always)]
577pub fn fr<Input: Into<f64> + Copy, T: FromFr>(flex: Input) -> T {
578 T::from_fr(flex)
579}
580
581pub trait FromFr {
583 fn from_fr<Input: Into<f64> + Copy>(flex: Input) -> Self;
585}
586
587#[cfg(feature = "grid")]
588#[cfg(test)]
589mod repeat_fn_tests {
590 type S = crate::sys::DefaultCheapStr;
591 use super::repeat;
592 use crate::{
593 style::{GridTemplateComponent, RepetitionCount, TrackSizingFunction},
594 GridTemplateRepetition,
595 };
596
597 const TEST_VEC: Vec<TrackSizingFunction> = Vec::new();
598
599 #[test]
600 fn test_repeat_u16() {
601 assert_eq!(
602 repeat::<_, S>(123, TEST_VEC),
603 GridTemplateComponent::Repeat(GridTemplateRepetition {
604 count: RepetitionCount::Count(123),
605 tracks: TEST_VEC,
606 line_names: Vec::new(),
607 })
608 );
609 }
610
611 #[test]
612 fn test_repeat_auto_fit_str() {
613 assert_eq!(
614 repeat::<_, S>("auto-fit", TEST_VEC),
615 GridTemplateComponent::Repeat(GridTemplateRepetition {
616 count: RepetitionCount::AutoFit,
617 tracks: TEST_VEC,
618 line_names: Vec::new(),
619 })
620 );
621 }
622
623 #[test]
624 fn test_repeat_auto_fill_str() {
625 assert_eq!(
626 repeat::<_, S>("auto-fill", TEST_VEC),
627 GridTemplateComponent::Repeat(GridTemplateRepetition {
628 count: RepetitionCount::AutoFill,
629 tracks: TEST_VEC,
630 line_names: Vec::new(),
631 })
632 );
633 }
634}