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