tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 1077HTML 1008Markdown 12TOML 83209 Definitions

⎇ 52ae96646aca7b811a12109ca699fb14bf5b50b4 src/style_helpers.rs Rust · 538 lines · 19.6 KB History Who touched what raw

Fix deserialize partial values with serde (#366) 52ae96646 · Nico Burns ·

1//! Helper functions which it make it easier to create instances of types in the `style` and `geometry` modules.
2use crate::{
3    geometry::{Line, MinMax, Point, Rect, Size},
4    style::LengthPercentage,
5};
6use core::fmt::Debug;
7
8#[cfg(feature = "grid")]
9use crate::style::{
10    GridTrackRepetition, MaxTrackSizingFunction, MinTrackSizingFunction, NonRepeatedTrackSizingFunction,
11    TrackSizingFunction,
12};
13
14/// Returns an auto-repeated track definition
15#[cfg(feature = "grid")]
16pub fn repeat<Input>(repetition_kind: Input, track_list: Vec<NonRepeatedTrackSizingFunction>) -> TrackSizingFunction
17where
18    Input: TryInto<GridTrackRepetition>,
19    <Input as TryInto<GridTrackRepetition>>::Error: Debug,
20{
21    TrackSizingFunction::Repeat(repetition_kind.try_into().unwrap(), track_list)
22}
23
24#[cfg(feature = "grid")]
25#[cfg(test)]
26mod repeat_fn_tests {
27    use super::repeat;
28    use crate::style::{GridTrackRepetition, NonRepeatedTrackSizingFunction, TrackSizingFunction};
29
30    const TEST_VEC: Vec<NonRepeatedTrackSizingFunction> = Vec::new();
31
32    #[test]
33    fn test_repeat_u16() {
34        assert_eq!(repeat(123, TEST_VEC), TrackSizingFunction::Repeat(GridTrackRepetition::Count(123), TEST_VEC));
35    }
36
37    #[test]
38    fn test_repeat_auto_fit_str() {
39        assert_eq!(repeat("auto-fit", TEST_VEC), TrackSizingFunction::Repeat(GridTrackRepetition::AutoFit, TEST_VEC));
40    }
41
42    #[test]
43    fn test_repeat_auto_fill_str() {
44        assert_eq!(repeat("auto-fill", TEST_VEC), TrackSizingFunction::Repeat(GridTrackRepetition::AutoFill, TEST_VEC));
45    }
46}
47
48#[cfg(feature = "grid")]
49/// Returns a grid template containing `count` evenly sized tracks
50pub fn evenly_sized_tracks(count: u16) -> Vec<TrackSizingFunction> {
51    vec![repeat(count, vec![flex(1.0)])]
52}
53
54/// Specifies a grid line to place a grid item between in CSS Grid Line coordinates:
55///  - Positive indicies count upwards from the start (top or left) of the explicit grid
56///  - Negative indicies count downwards from the end (bottom or right) of the explicit grid
57///  - ZERO IS INVALID index, and will be treated as a GridPlacement::Auto.
58pub fn line<T: TaffyGridLine>(index: i16) -> T {
59    T::from_line_index(index)
60}
61/// Trait to abstract over grid line values
62pub trait TaffyGridLine {
63    /// Converts an i16 into Self
64    fn from_line_index(index: i16) -> Self;
65}
66
67/// Returns a GridPlacement::Span
68pub fn span<T: TaffyGridSpan>(span: u16) -> T {
69    T::from_span(span)
70}
71/// Trait to abstract over grid span values
72pub trait TaffyGridSpan {
73    /// Converts an iu6 into Self
74    fn from_span(span: u16) -> Self;
75}
76
77/// Returns a MinMax with min value of min and max value of max
78#[cfg(feature = "grid")]
79pub fn minmax<Output>(min: MinTrackSizingFunction, max: MaxTrackSizingFunction) -> Output
80where
81    Output: From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>>,
82{
83    MinMax { min, max }.into()
84}
85
86/// Shorthand for minmax(0, Nfr). Probably what you want if you want exactly evenly sized tracks.
87#[cfg(feature = "grid")]
88pub fn flex<Input, Output>(flex_fraction: Input) -> Output
89where
90    Input: Into<f32> + Copy,
91    Output: From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>>,
92{
93    MinMax { min: zero(), max: fr(flex_fraction.into()) }.into()
94}
95
96/// Returns the zero value for that type
97pub const fn zero<T: TaffyZero>() -> T {
98    T::ZERO
99}
100
101/// Trait to abstract over zero values
102pub trait TaffyZero {
103    /// The zero value for type implementing TaffyZero
104    const ZERO: Self;
105}
106impl TaffyZero for f32 {
107    const ZERO: f32 = 0.0;
108}
109impl<T: TaffyZero> TaffyZero for Option<T> {
110    const ZERO: Option<T> = Some(T::ZERO);
111}
112impl<T: TaffyZero> TaffyZero for Point<T> {
113    const ZERO: Point<T> = Point { x: T::ZERO, y: T::ZERO };
114}
115impl<T: TaffyZero> Point<T> {
116    /// Returns a Point where both the x and y values are the zero value of the contained type
117    /// (e.g. 0.0, Some(0.0), or Dimension::Points(0.0))
118    pub const fn zero() -> Self {
119        zero::<Self>()
120    }
121}
122impl<T: TaffyZero> TaffyZero for Line<T> {
123    const ZERO: Line<T> = Line { start: T::ZERO, end: T::ZERO };
124}
125impl<T: TaffyZero> Line<T> {
126    /// Returns a Line where both the start and end values are the zero value of the contained type
127    /// (e.g. 0.0, Some(0.0), or Dimension::Points(0.0))
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    /// Returns a Size where both the width and height values are the zero value of the contained type
137    /// (e.g. 0.0, Some(0.0), or Dimension::Points(0.0))
138    pub const fn zero() -> Self {
139        zero::<Self>()
140    }
141}
142impl<T: TaffyZero> TaffyZero for Rect<T> {
143    const ZERO: Rect<T> = Rect { left: T::ZERO, right: T::ZERO, top: T::ZERO, bottom: T::ZERO };
144}
145impl<T: TaffyZero> Rect<T> {
146    /// Returns a Size where the left, right, top, and bottom values are all the zero value of the contained type
147    /// (e.g. 0.0, Some(0.0), or Dimension::Points(0.0))
148    pub const fn zero() -> Self {
149        zero::<Self>()
150    }
151}
152
153/// Returns the auto value for that type
154pub const fn auto<T: TaffyAuto>() -> T {
155    T::AUTO
156}
157
158/// Trait to abstract over auto values
159pub trait TaffyAuto {
160    /// The auto value for type implementing TaffyZero
161    const AUTO: Self;
162}
163impl<T: TaffyAuto> TaffyAuto for Option<T> {
164    const AUTO: Option<T> = Some(T::AUTO);
165}
166impl<T: TaffyAuto> TaffyAuto for Point<T> {
167    const AUTO: Point<T> = Point { x: T::AUTO, y: T::AUTO };
168}
169impl<T: TaffyAuto> Point<T> {
170    /// Returns a Point where both the x and y values are the auto value of the contained type
171    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
172    pub const fn auto() -> Self {
173        auto::<Self>()
174    }
175}
176impl<T: TaffyAuto> TaffyAuto for Line<T> {
177    const AUTO: Line<T> = Line { start: T::AUTO, end: T::AUTO };
178}
179impl<T: TaffyAuto> Line<T> {
180    /// Returns a Line where both the start and end values are the auto value of the contained type
181    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
182    pub const fn auto() -> Self {
183        auto::<Self>()
184    }
185}
186impl<T: TaffyAuto> TaffyAuto for Size<T> {
187    const AUTO: Size<T> = Size { width: T::AUTO, height: T::AUTO };
188}
189impl<T: TaffyAuto> Size<T> {
190    /// Returns a Size where both the width and height values are the auto value of the contained type
191    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
192    pub const fn auto() -> Self {
193        auto::<Self>()
194    }
195}
196impl<T: TaffyAuto> TaffyAuto for Rect<T> {
197    const AUTO: Rect<T> = Rect { left: T::AUTO, right: T::AUTO, top: T::AUTO, bottom: T::AUTO };
198}
199impl<T: TaffyAuto> Rect<T> {
200    /// Returns a Size where the left, right, top, and bottom values are all the auto value of the contained type
201    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
202    pub const fn auto() -> Self {
203        auto::<Self>()
204    }
205}
206
207/// Returns the auto value for that type
208pub const fn min_content<T: TaffyMinContent>() -> T {
209    T::MIN_CONTENT
210}
211
212/// Trait to abstract over min_content values
213pub trait TaffyMinContent {
214    /// The min_content value for type implementing TaffyZero
215    const MIN_CONTENT: Self;
216}
217impl<T: TaffyMinContent> TaffyMinContent for Option<T> {
218    const MIN_CONTENT: Option<T> = Some(T::MIN_CONTENT);
219}
220impl<T: TaffyMinContent> TaffyMinContent for Point<T> {
221    const MIN_CONTENT: Point<T> = Point { x: T::MIN_CONTENT, y: T::MIN_CONTENT };
222}
223impl<T: TaffyMinContent> Point<T> {
224    /// Returns a Point where both the x and y values are the min_content value of the contained type
225    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
226    pub const fn min_content() -> Self {
227        min_content::<Self>()
228    }
229}
230impl<T: TaffyMinContent> TaffyMinContent for Line<T> {
231    const MIN_CONTENT: Line<T> = Line { start: T::MIN_CONTENT, end: T::MIN_CONTENT };
232}
233impl<T: TaffyMinContent> Line<T> {
234    /// Returns a Line where both the start and end values are the min_content value of the contained type
235    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
236    pub const fn min_content() -> Self {
237        min_content::<Self>()
238    }
239}
240impl<T: TaffyMinContent> TaffyMinContent for Size<T> {
241    const MIN_CONTENT: Size<T> = Size { width: T::MIN_CONTENT, height: T::MIN_CONTENT };
242}
243impl<T: TaffyMinContent> Size<T> {
244    /// Returns a Size where both the width and height values are the min_content value of the contained type
245    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
246    pub const fn min_content() -> Self {
247        min_content::<Self>()
248    }
249}
250impl<T: TaffyMinContent> TaffyMinContent for Rect<T> {
251    const MIN_CONTENT: Rect<T> =
252        Rect { left: T::MIN_CONTENT, right: T::MIN_CONTENT, top: T::MIN_CONTENT, bottom: T::MIN_CONTENT };
253}
254impl<T: TaffyMinContent> Rect<T> {
255    /// Returns a Size where the left, right, top, and bottom values are all the min_content value of the contained type
256    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
257    pub const fn min_content() -> Self {
258        min_content::<Self>()
259    }
260}
261
262/// Returns the auto value for that type
263pub const fn max_content<T: TaffyMaxContent>() -> T {
264    T::MAX_CONTENT
265}
266
267/// Trait to abstract over max_content values
268pub trait TaffyMaxContent {
269    /// The max_content value for type implementing TaffyZero
270    const MAX_CONTENT: Self;
271}
272impl<T: TaffyMaxContent> TaffyMaxContent for Option<T> {
273    const MAX_CONTENT: Option<T> = Some(T::MAX_CONTENT);
274}
275impl<T: TaffyMaxContent> TaffyMaxContent for Point<T> {
276    const MAX_CONTENT: Point<T> = Point { x: T::MAX_CONTENT, y: T::MAX_CONTENT };
277}
278impl<T: TaffyMaxContent> Point<T> {
279    /// Returns a Point where both the x and y values are the max_content value of the contained type
280    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
281    pub const fn max_content() -> Self {
282        max_content::<Self>()
283    }
284}
285impl<T: TaffyMaxContent> TaffyMaxContent for Line<T> {
286    const MAX_CONTENT: Line<T> = Line { start: T::MAX_CONTENT, end: T::MAX_CONTENT };
287}
288impl<T: TaffyMaxContent> Line<T> {
289    /// Returns a Line where both the start and end values are the max_content value of the contained type
290    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
291    pub const fn max_content() -> Self {
292        max_content::<Self>()
293    }
294}
295impl<T: TaffyMaxContent> TaffyMaxContent for Size<T> {
296    const MAX_CONTENT: Size<T> = Size { width: T::MAX_CONTENT, height: T::MAX_CONTENT };
297}
298impl<T: TaffyMaxContent> Size<T> {
299    /// Returns a Size where both the width and height values are the max_content value of the contained type
300    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
301    pub const fn max_content() -> Self {
302        max_content::<Self>()
303    }
304}
305impl<T: TaffyMaxContent> TaffyMaxContent for Rect<T> {
306    const MAX_CONTENT: Rect<T> =
307        Rect { left: T::MAX_CONTENT, right: T::MAX_CONTENT, top: T::MAX_CONTENT, bottom: T::MAX_CONTENT };
308}
309impl<T: TaffyMaxContent> Rect<T> {
310    /// Returns a Size where the left, right, top, and bottom values are all the max_content value of the contained type
311    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
312    pub const fn max_content() -> Self {
313        max_content::<Self>()
314    }
315}
316
317/// Returns a value of the inferred type which represent a constant of points
318pub fn fit_content<T: TaffyFitContent>(argument: LengthPercentage) -> T {
319    T::fit_content(argument)
320}
321
322/// Trait to create constant points values from plain numbers
323pub trait TaffyFitContent {
324    /// Converts into a LengthPercentage into Self
325    fn fit_content(argument: LengthPercentage) -> Self;
326}
327impl<T: TaffyFitContent> TaffyFitContent for Point<T> {
328    fn fit_content(argument: LengthPercentage) -> Self {
329        Point { x: T::fit_content(argument), y: T::fit_content(argument) }
330    }
331}
332impl<T: TaffyFitContent> Point<T> {
333    /// Returns a Point where both the x and y values are the constant points value of the contained type
334    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
335    pub fn fit_content(argument: LengthPercentage) -> Self {
336        fit_content(argument)
337    }
338}
339impl<T: TaffyFitContent> TaffyFitContent for Line<T> {
340    fn fit_content(argument: LengthPercentage) -> Self {
341        Line { start: T::fit_content(argument), end: T::fit_content(argument) }
342    }
343}
344impl<T: TaffyFitContent> Line<T> {
345    /// Returns a Line where both the start and end values are the constant points value of the contained type
346    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
347    pub fn fit_content(argument: LengthPercentage) -> Self {
348        fit_content(argument)
349    }
350}
351impl<T: TaffyFitContent> TaffyFitContent for Size<T> {
352    fn fit_content(argument: LengthPercentage) -> Self {
353        Size { width: T::fit_content(argument), height: T::fit_content(argument) }
354    }
355}
356impl<T: TaffyFitContent> Size<T> {
357    /// Returns a Size where both the width and height values are the constant fit_content value of the contained type
358    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
359    pub fn fit_content(argument: LengthPercentage) -> Self {
360        fit_content(argument)
361    }
362}
363impl<T: TaffyFitContent> TaffyFitContent for Rect<T> {
364    fn fit_content(argument: LengthPercentage) -> Self {
365        Rect {
366            left: T::fit_content(argument),
367            right: T::fit_content(argument),
368            top: T::fit_content(argument),
369            bottom: T::fit_content(argument),
370        }
371    }
372}
373impl<T: TaffyFitContent> Rect<T> {
374    /// Returns a Rect where the left, right, top and bottom values are all constant fit_content value of the contained type
375    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
376    pub fn fit_content(argument: LengthPercentage) -> Self {
377        fit_content(argument)
378    }
379}
380
381/// Returns a value of the inferred type which represent a constant of points
382pub fn points<Input: Into<f32> + Copy, T: FromPoints>(points: Input) -> T {
383    T::from_points(points)
384}
385
386/// Trait to create constant points values from plain numbers
387pub trait FromPoints {
388    /// Converts into an `Into<f32>` into Self
389    fn from_points<Input: Into<f32> + Copy>(points: Input) -> Self;
390}
391impl FromPoints for f32 {
392    fn from_points<Input: Into<f32> + Copy>(points: Input) -> Self {
393        points.into()
394    }
395}
396impl FromPoints for Option<f32> {
397    fn from_points<Input: Into<f32> + Copy>(points: Input) -> Self {
398        Some(points.into())
399    }
400}
401impl<T: FromPoints> FromPoints for Point<T> {
402    fn from_points<Input: Into<f32> + Copy>(points: Input) -> Self {
403        Point { x: T::from_points(points.into()), y: T::from_points(points.into()) }
404    }
405}
406impl<T: FromPoints> Point<T> {
407    /// Returns a Point where both the x and y values are the constant points value of the contained type
408    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
409    pub fn points<Input: Into<f32> + Copy>(points_value: Input) -> Self {
410        points::<Input, Self>(points_value)
411    }
412}
413impl<T: FromPoints> FromPoints for Line<T> {
414    fn from_points<Input: Into<f32> + Copy>(points: Input) -> Self {
415        Line { start: T::from_points(points.into()), end: T::from_points(points.into()) }
416    }
417}
418impl<T: FromPoints> Line<T> {
419    /// Returns a Line where both the start and end values are the constant points value of the contained type
420    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
421    pub fn points<Input: Into<f32> + Copy>(points_value: Input) -> Self {
422        points::<Input, Self>(points_value)
423    }
424}
425impl<T: FromPoints> FromPoints for Size<T> {
426    fn from_points<Input: Into<f32> + Copy>(points: Input) -> Self {
427        Size { width: T::from_points(points.into()), height: T::from_points(points.into()) }
428    }
429}
430impl<T: FromPoints> Size<T> {
431    /// Returns a Size where both the width and height values are the constant points value of the contained type
432    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
433    pub fn points<Input: Into<f32> + Copy>(points_value: Input) -> Self {
434        points::<Input, Self>(points_value)
435    }
436}
437impl<T: FromPoints> FromPoints for Rect<T> {
438    fn from_points<Input: Into<f32> + Copy>(points: Input) -> Self {
439        Rect {
440            left: T::from_points(points.into()),
441            right: T::from_points(points.into()),
442            top: T::from_points(points.into()),
443            bottom: T::from_points(points.into()),
444        }
445    }
446}
447impl<T: FromPoints> Rect<T> {
448    /// Returns a Rect where the left, right, top and bottom values are all constant points value of the contained type
449    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
450    pub fn points<Input: Into<f32> + Copy>(points_value: Input) -> Self {
451        points::<Input, Self>(points_value)
452    }
453}
454
455/// Returns a value of the inferred type which represent a constant of points
456pub fn percent<Input: Into<f32> + Copy, T: FromPercent>(percent: Input) -> T {
457    T::from_percent(percent)
458}
459
460/// Trait to create constant percent values from plain numbers
461pub trait FromPercent {
462    /// Converts into an `Into<f32>` into Self
463    fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self;
464}
465impl FromPercent for f32 {
466    fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
467        percent.into()
468    }
469}
470impl FromPercent for Option<f32> {
471    fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
472        Some(percent.into())
473    }
474}
475impl<T: FromPercent> FromPercent for Point<T> {
476    fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
477        Point { x: T::from_percent(percent.into()), y: T::from_percent(percent.into()) }
478    }
479}
480impl<T: FromPercent> Point<T> {
481    /// Returns a Point where both the x and y values are the constant percent value of the contained type
482    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
483    pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
484        percent::<Input, Self>(percent_value)
485    }
486}
487impl<T: FromPercent> FromPercent for Line<T> {
488    fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
489        Line { start: T::from_percent(percent.into()), end: T::from_percent(percent.into()) }
490    }
491}
492impl<T: FromPercent> Line<T> {
493    /// Returns a Line where both the start and end values are the constant percent value of the contained type
494    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
495    pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
496        percent::<Input, Self>(percent_value)
497    }
498}
499impl<T: FromPercent> FromPercent for Size<T> {
500    fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
501        Size { width: T::from_percent(percent.into()), height: T::from_percent(percent.into()) }
502    }
503}
504impl<T: FromPercent> Size<T> {
505    /// Returns a Size where both the width and height values are the constant percent value of the contained type
506    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
507    pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
508        percent::<Input, Self>(percent_value)
509    }
510}
511impl<T: FromPercent> FromPercent for Rect<T> {
512    fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
513        Rect {
514            left: T::from_percent(percent.into()),
515            right: T::from_percent(percent.into()),
516            top: T::from_percent(percent.into()),
517            bottom: T::from_percent(percent.into()),
518        }
519    }
520}
521impl<T: FromPercent> Rect<T> {
522    /// Returns a Rect where the left, right, top and bottom values are all constant percent value of the contained type
523    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
524    pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
525        percent::<Input, Self>(percent_value)
526    }
527}
528
529/// Create a `Fraction` track sizing function (`fr` in CSS)
530pub fn fr<Input: Into<f32> + Copy, T: FromFlex>(flex: Input) -> T {
531    T::from_flex(flex)
532}
533
534/// Trait to create constant percent values from plain numbers
535pub trait FromFlex {
536    /// Converts into an `Into<f32>` into Self
537    fn from_flex<Input: Into<f32> + Copy>(flex: Input) -> Self;
538}