1 //! Helper functions which it make it easier to create instances of types in the `style` and `geometry` modules.
2 use crate::{
3 geometry::{Line, Point, Rect, Size},
4 style::LengthPercentage,
5 };
6
7 #[cfg(feature = "grid")]
8 use crate::{
9 geometry::MinMax,
10 style::{
11 GridTrackRepetition, MaxTrackSizingFunction, MinTrackSizingFunction, NonRepeatedTrackSizingFunction,
12 TrackSizingFunction,
13 },
14 util::sys::Vec,
15 };
16 #[cfg(feature = "grid")]
17 use core::fmt::Debug;
18
19 /// Returns an auto-repeated track definition
20 #[cfg(feature = "grid")]
repeat<Input>(repetition_kind: Input, track_list: Vec<NonRepeatedTrackSizingFunction>) -> TrackSizingFunction where Input: TryInto<GridTrackRepetition>, <Input as TryInto<GridTrackRepetition>>::Error: Debug,21 pub fn repeat<Input>(repetition_kind: Input, track_list: Vec<NonRepeatedTrackSizingFunction>) -> TrackSizingFunction
22 where
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 /// Returns a grid template containing `count` evenly sized tracks
evenly_sized_tracks(count: u16) -> Vec<TrackSizingFunction>31 pub 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
40 /// Specifies a grid line to place a grid item between in CSS Grid Line coordinates:
41 /// - Positive indices count upwards from the start (top or left) of the explicit grid
42 /// - Negative indices count downwards from the end (bottom or right) of the explicit grid
43 /// - ZERO IS INVALID index, and will be treated as a GridPlacement::Auto.
line<T: TaffyGridLine>(index: i16) -> T44 pub fn line<T: TaffyGridLine>(index: i16) -> T {
45 T::from_line_index(index)
46 }
47 /// Trait to abstract over grid line values
48 pub trait TaffyGridLine {
49 /// Converts an i16 into Self
from_line_index(index: i16) -> Self50 fn from_line_index(index: i16) -> Self;
51 }
52
53 /// Returns a GridPlacement::Span
span<T: TaffyGridSpan>(span: u16) -> T54 pub fn span<T: TaffyGridSpan>(span: u16) -> T {
55 T::from_span(span)
56 }
57 /// Trait to abstract over grid span values
58 pub trait TaffyGridSpan {
59 /// Converts an iu6 into Self
from_span(span: u16) -> Self60 fn from_span(span: u16) -> Self;
61 }
62
63 /// Returns a MinMax with min value of min and max value of max
64 #[cfg(feature = "grid")]
minmax<Output>(min: MinTrackSizingFunction, max: MaxTrackSizingFunction) -> Output where Output: From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>>,65 pub fn minmax<Output>(min: MinTrackSizingFunction, max: MaxTrackSizingFunction) -> Output
66 where
67 Output: From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>>,
68 {
69 MinMax { min, max }.into()
70 }
71
72 /// Shorthand for minmax(0, Nfr). Probably what you want if you want exactly evenly sized tracks.
73 #[cfg(feature = "grid")]
flex<Input, Output>(flex_fraction: Input) -> Output where Input: Into<f32> + Copy, Output: From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>>,74 pub fn flex<Input, Output>(flex_fraction: Input) -> Output
75 where
76 Input: Into<f32> + Copy,
77 Output: From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>>,
78 {
79 MinMax { min: zero(), max: fr(flex_fraction.into()) }.into()
80 }
81
82 /// Returns the zero value for that type
zero<T: TaffyZero>() -> T83 pub const fn zero<T: TaffyZero>() -> T {
84 T::ZERO
85 }
86
87 /// Trait to abstract over zero values
88 pub trait TaffyZero {
89 /// The zero value for type implementing TaffyZero
90 const ZERO: Self;
91 }
92 impl TaffyZero for f32 {
93 const ZERO: f32 = 0.0;
94 }
95 impl<T: TaffyZero> TaffyZero for Option<T> {
96 const ZERO: Option<T> = Some(T::ZERO);
97 }
98 impl<T: TaffyZero> TaffyZero for Point<T> {
99 const ZERO: Point<T> = Point { x: T::ZERO, y: T::ZERO };
100 }
101 impl<T: TaffyZero> Point<T> {
102 /// Returns a Point where both the x and y values are the zero value of the contained type
103 /// (e.g. 0.0, Some(0.0), or Dimension::Length(0.0))
zero() -> Self104 pub const fn zero() -> Self {
105 zero::<Self>()
106 }
107 }
108 impl<T: TaffyZero> TaffyZero for Line<T> {
109 const ZERO: Line<T> = Line { start: T::ZERO, end: T::ZERO };
110 }
111 impl<T: TaffyZero> Line<T> {
112 /// Returns a Line where both the start and end values are the zero value of the contained type
113 /// (e.g. 0.0, Some(0.0), or Dimension::Length(0.0))
zero() -> Self114 pub const fn zero() -> Self {
115 zero::<Self>()
116 }
117 }
118 impl<T: TaffyZero> TaffyZero for Size<T> {
119 const ZERO: Size<T> = Size { width: T::ZERO, height: T::ZERO };
120 }
121 impl<T: TaffyZero> Size<T> {
122 /// Returns a Size where both the width and height values are the zero value of the contained type
123 /// (e.g. 0.0, Some(0.0), or Dimension::Length(0.0))
zero() -> Self124 pub const fn zero() -> Self {
125 zero::<Self>()
126 }
127 }
128 impl<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 }
131 impl<T: TaffyZero> Rect<T> {
132 /// Returns a Rect where the left, right, top, and bottom values are all the zero value of the contained type
133 /// (e.g. 0.0, Some(0.0), or Dimension::Length(0.0))
zero() -> Self134 pub const fn zero() -> Self {
135 zero::<Self>()
136 }
137 }
138
139 /// Returns the auto value for that type
auto<T: TaffyAuto>() -> T140 pub const fn auto<T: TaffyAuto>() -> T {
141 T::AUTO
142 }
143
144 /// Trait to abstract over auto values
145 pub trait TaffyAuto {
146 /// The auto value for type implementing TaffyAuto
147 const AUTO: Self;
148 }
149 impl<T: TaffyAuto> TaffyAuto for Option<T> {
150 const AUTO: Option<T> = Some(T::AUTO);
151 }
152 impl<T: TaffyAuto> TaffyAuto for Point<T> {
153 const AUTO: Point<T> = Point { x: T::AUTO, y: T::AUTO };
154 }
155 impl<T: TaffyAuto> Point<T> {
156 /// Returns a Point where both the x and y values are the auto value of the contained type
157 /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
auto() -> Self158 pub const fn auto() -> Self {
159 auto::<Self>()
160 }
161 }
162 impl<T: TaffyAuto> TaffyAuto for Line<T> {
163 const AUTO: Line<T> = Line { start: T::AUTO, end: T::AUTO };
164 }
165 impl<T: TaffyAuto> Line<T> {
166 /// Returns a Line where both the start and end values are the auto value of the contained type
167 /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
auto() -> Self168 pub const fn auto() -> Self {
169 auto::<Self>()
170 }
171 }
172 impl<T: TaffyAuto> TaffyAuto for Size<T> {
173 const AUTO: Size<T> = Size { width: T::AUTO, height: T::AUTO };
174 }
175 impl<T: TaffyAuto> Size<T> {
176 /// Returns a Size where both the width and height values are the auto value of the contained type
177 /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
auto() -> Self178 pub const fn auto() -> Self {
179 auto::<Self>()
180 }
181 }
182 impl<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 }
185 impl<T: TaffyAuto> Rect<T> {
186 /// Returns a Rect where the left, right, top, and bottom values are all the auto value of the contained type
187 /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
auto() -> Self188 pub const fn auto() -> Self {
189 auto::<Self>()
190 }
191 }
192
193 /// Returns the auto value for that type
min_content<T: TaffyMinContent>() -> T194 pub const fn min_content<T: TaffyMinContent>() -> T {
195 T::MIN_CONTENT
196 }
197
198 /// Trait to abstract over min_content values
199 pub trait TaffyMinContent {
200 /// The min_content value for type implementing TaffyZero
201 const MIN_CONTENT: Self;
202 }
203 impl<T: TaffyMinContent> TaffyMinContent for Option<T> {
204 const MIN_CONTENT: Option<T> = Some(T::MIN_CONTENT);
205 }
206 impl<T: TaffyMinContent> TaffyMinContent for Point<T> {
207 const MIN_CONTENT: Point<T> = Point { x: T::MIN_CONTENT, y: T::MIN_CONTENT };
208 }
209 impl<T: TaffyMinContent> Point<T> {
210 /// Returns a Point where both the x and y values are the min_content value of the contained type
211 /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
min_content() -> Self212 pub const fn min_content() -> Self {
213 min_content::<Self>()
214 }
215 }
216 impl<T: TaffyMinContent> TaffyMinContent for Line<T> {
217 const MIN_CONTENT: Line<T> = Line { start: T::MIN_CONTENT, end: T::MIN_CONTENT };
218 }
219 impl<T: TaffyMinContent> Line<T> {
220 /// Returns a Line where both the start and end values are the min_content value of the contained type
221 /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
min_content() -> Self222 pub const fn min_content() -> Self {
223 min_content::<Self>()
224 }
225 }
226 impl<T: TaffyMinContent> TaffyMinContent for Size<T> {
227 const MIN_CONTENT: Size<T> = Size { width: T::MIN_CONTENT, height: T::MIN_CONTENT };
228 }
229 impl<T: TaffyMinContent> Size<T> {
230 /// Returns a Size where both the width and height values are the min_content value of the contained type
231 /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
min_content() -> Self232 pub const fn min_content() -> Self {
233 min_content::<Self>()
234 }
235 }
236 impl<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 }
240 impl<T: TaffyMinContent> Rect<T> {
241 /// Returns a Rect where the left, right, top, and bottom values are all the min_content value of the contained type
242 /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
min_content() -> Self243 pub const fn min_content() -> Self {
244 min_content::<Self>()
245 }
246 }
247
248 /// Returns the auto value for that type
max_content<T: TaffyMaxContent>() -> T249 pub const fn max_content<T: TaffyMaxContent>() -> T {
250 T::MAX_CONTENT
251 }
252
253 /// Trait to abstract over max_content values
254 pub trait TaffyMaxContent {
255 /// The max_content value for type implementing TaffyZero
256 const MAX_CONTENT: Self;
257 }
258 impl<T: TaffyMaxContent> TaffyMaxContent for Option<T> {
259 const MAX_CONTENT: Option<T> = Some(T::MAX_CONTENT);
260 }
261 impl<T: TaffyMaxContent> TaffyMaxContent for Point<T> {
262 const MAX_CONTENT: Point<T> = Point { x: T::MAX_CONTENT, y: T::MAX_CONTENT };
263 }
264 impl<T: TaffyMaxContent> Point<T> {
265 /// Returns a Point where both the x and y values are the max_content value of the contained type
266 /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
max_content() -> Self267 pub const fn max_content() -> Self {
268 max_content::<Self>()
269 }
270 }
271 impl<T: TaffyMaxContent> TaffyMaxContent for Line<T> {
272 const MAX_CONTENT: Line<T> = Line { start: T::MAX_CONTENT, end: T::MAX_CONTENT };
273 }
274 impl<T: TaffyMaxContent> Line<T> {
275 /// Returns a Line where both the start and end values are the max_content value of the contained type
276 /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
max_content() -> Self277 pub const fn max_content() -> Self {
278 max_content::<Self>()
279 }
280 }
281 impl<T: TaffyMaxContent> TaffyMaxContent for Size<T> {
282 const MAX_CONTENT: Size<T> = Size { width: T::MAX_CONTENT, height: T::MAX_CONTENT };
283 }
284 impl<T: TaffyMaxContent> Size<T> {
285 /// Returns a Size where both the width and height values are the max_content value of the contained type
286 /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
max_content() -> Self287 pub const fn max_content() -> Self {
288 max_content::<Self>()
289 }
290 }
291 impl<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 }
295 impl<T: TaffyMaxContent> Rect<T> {
296 /// Returns a Rect where the left, right, top, and bottom values are all the max_content value of the contained type
297 /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
max_content() -> Self298 pub const fn max_content() -> Self {
299 max_content::<Self>()
300 }
301 }
302
303 /// Returns a value of the inferred type which represent a `fit-content(…)` value
304 /// with the given argument.
fit_content<T: TaffyFitContent>(argument: LengthPercentage) -> T305 pub fn fit_content<T: TaffyFitContent>(argument: LengthPercentage) -> T {
306 T::fit_content(argument)
307 }
308
309 /// Trait to create `fit-content(…)` values from plain numbers
310 pub trait TaffyFitContent {
311 /// Converts a LengthPercentage into Self
fit_content(argument: LengthPercentage) -> Self312 fn fit_content(argument: LengthPercentage) -> Self;
313 }
314 impl<T: TaffyFitContent> TaffyFitContent for Point<T> {
fit_content(argument: LengthPercentage) -> Self315 fn fit_content(argument: LengthPercentage) -> Self {
316 Point { x: T::fit_content(argument), y: T::fit_content(argument) }
317 }
318 }
319 impl<T: TaffyFitContent> Point<T> {
320 /// Returns a Point with x and y set to the same `fit-content(…)` value
321 /// with the given argument.
fit_content(argument: LengthPercentage) -> Self322 pub fn fit_content(argument: LengthPercentage) -> Self {
323 fit_content(argument)
324 }
325 }
326 impl<T: TaffyFitContent> TaffyFitContent for Line<T> {
fit_content(argument: LengthPercentage) -> Self327 fn fit_content(argument: LengthPercentage) -> Self {
328 Line { start: T::fit_content(argument), end: T::fit_content(argument) }
329 }
330 }
331 impl<T: TaffyFitContent> Line<T> {
332 /// Returns a Line with start and end set to the same `fit-content(…)` value
333 /// with the given argument.
fit_content(argument: LengthPercentage) -> Self334 pub fn fit_content(argument: LengthPercentage) -> Self {
335 fit_content(argument)
336 }
337 }
338 impl<T: TaffyFitContent> TaffyFitContent for Size<T> {
fit_content(argument: LengthPercentage) -> Self339 fn fit_content(argument: LengthPercentage) -> Self {
340 Size { width: T::fit_content(argument), height: T::fit_content(argument) }
341 }
342 }
343 impl<T: TaffyFitContent> Size<T> {
344 /// Returns a Size where with width and height set to the same `fit-content(…)` value
345 /// with the given argument.
fit_content(argument: LengthPercentage) -> Self346 pub fn fit_content(argument: LengthPercentage) -> Self {
347 fit_content(argument)
348 }
349 }
350 impl<T: TaffyFitContent> TaffyFitContent for Rect<T> {
fit_content(argument: LengthPercentage) -> Self351 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 }
360 impl<T: TaffyFitContent> Rect<T> {
361 /// Returns a Rect where the left, right, top and bottom values are all constant fit_content value of the contained type
362 /// (e.g. 2.1, Some(2.1), or Dimension::Length(2.1))
fit_content(argument: LengthPercentage) -> Self363 pub fn fit_content(argument: LengthPercentage) -> Self {
364 fit_content(argument)
365 }
366 }
367
368 /// Returns a value of the inferred type which represent an absolute length
length<Input: Into<f32> + Copy, T: FromLength>(value: Input) -> T369 pub fn length<Input: Into<f32> + Copy, T: FromLength>(value: Input) -> T {
370 T::from_length(value)
371 }
372
373 /// Trait to create absolute length values from plain numbers
374 pub trait FromLength {
375 /// Converts into an `Into<f32>` into Self
from_length<Input: Into<f32> + Copy>(value: Input) -> Self376 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self;
377 }
378 impl FromLength for f32 {
from_length<Input: Into<f32> + Copy>(value: Input) -> Self379 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
380 value.into()
381 }
382 }
383 impl FromLength for Option<f32> {
from_length<Input: Into<f32> + Copy>(value: Input) -> Self384 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
385 Some(value.into())
386 }
387 }
388 impl<T: FromLength> FromLength for Point<T> {
from_length<Input: Into<f32> + Copy>(value: Input) -> Self389 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 }
393 impl<T: FromLength> Point<T> {
394 /// Returns a Point where x and y values are the same given absolute length
length<Input: Into<f32> + Copy>(value: Input) -> Self395 pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
396 length::<Input, Self>(value)
397 }
398 }
399 impl<T: FromLength> FromLength for Line<T> {
from_length<Input: Into<f32> + Copy>(value: Input) -> Self400 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 }
404 impl<T: FromLength> Line<T> {
405 /// Returns a Line where both the start and end values are the same given absolute length
length<Input: Into<f32> + Copy>(value: Input) -> Self406 pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
407 length::<Input, Self>(value)
408 }
409 }
410 impl<T: FromLength> FromLength for Size<T> {
from_length<Input: Into<f32> + Copy>(value: Input) -> Self411 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 }
415 impl<T: FromLength> Size<T> {
416 /// Returns a Size where both the width and height values the same given absolute length
length<Input: Into<f32> + Copy>(value: Input) -> Self417 pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
418 length::<Input, Self>(value)
419 }
420 }
421 impl<T: FromLength> FromLength for Rect<T> {
from_length<Input: Into<f32> + Copy>(value: Input) -> Self422 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 }
431 impl<T: FromLength> Rect<T> {
432 /// Returns a Rect where the left, right, top and bottom values are all the same given absolute length
length<Input: Into<f32> + Copy>(value: Input) -> Self433 pub fn length<Input: Into<f32> + Copy>(value: Input) -> Self {
434 length::<Input, Self>(value)
435 }
436 }
437
438 /// Returns a value of the inferred type which represent a percentage
percent<Input: Into<f32> + Copy, T: FromPercent>(percent: Input) -> T439 pub fn percent<Input: Into<f32> + Copy, T: FromPercent>(percent: Input) -> T {
440 T::from_percent(percent)
441 }
442
443 /// Trait to create constant percent values from plain numbers
444 pub trait FromPercent {
445 /// Converts into an `Into<f32>` into Self
from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self446 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self;
447 }
448 impl FromPercent for f32 {
from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self449 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
450 percent.into()
451 }
452 }
453 impl FromPercent for Option<f32> {
from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self454 fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
455 Some(percent.into())
456 }
457 }
458 impl<T: FromPercent> FromPercent for Point<T> {
from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self459 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 }
463 impl<T: FromPercent> Point<T> {
464 /// Returns a Point where both the x and y values are the constant percent value of the contained type
465 /// (e.g. 2.1, Some(2.1), or Dimension::Length(2.1))
percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self466 pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
467 percent::<Input, Self>(percent_value)
468 }
469 }
470 impl<T: FromPercent> FromPercent for Line<T> {
from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self471 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 }
475 impl<T: FromPercent> Line<T> {
476 /// Returns a Line where both the start and end values are the constant percent value of the contained type
477 /// (e.g. 2.1, Some(2.1), or Dimension::Length(2.1))
percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self478 pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
479 percent::<Input, Self>(percent_value)
480 }
481 }
482 impl<T: FromPercent> FromPercent for Size<T> {
from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self483 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 }
487 impl<T: FromPercent> Size<T> {
488 /// Returns a Size where both the width and height values are the constant percent value of the contained type
489 /// (e.g. 2.1, Some(2.1), or Dimension::Length(2.1))
percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self490 pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
491 percent::<Input, Self>(percent_value)
492 }
493 }
494 impl<T: FromPercent> FromPercent for Rect<T> {
from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self495 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 }
504 impl<T: FromPercent> Rect<T> {
505 /// Returns a Rect where the left, right, top and bottom values are all constant percent value of the contained type
506 /// (e.g. 2.1, Some(2.1), or Dimension::Length(2.1))
percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self507 pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
508 percent::<Input, Self>(percent_value)
509 }
510 }
511
512 /// Create a `Fraction` track sizing function (`fr` in CSS)
513 #[cfg(feature = "grid")]
fr<Input: Into<f32> + Copy, T: FromFlex>(flex: Input) -> T514 pub fn fr<Input: Into<f32> + Copy, T: FromFlex>(flex: Input) -> T {
515 T::from_flex(flex)
516 }
517
518 /// Trait to create constant percent values from plain numbers
519 pub trait FromFlex {
520 /// Converts into an `Into<f32>` into Self
from_flex<Input: Into<f32> + Copy>(flex: Input) -> Self521 fn from_flex<Input: Into<f32> + Copy>(flex: Input) -> Self;
522 }
523
524 #[cfg(feature = "grid")]
525 #[cfg(test)]
526 mod 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]
test_repeat_u16()533 fn test_repeat_u16() {
534 assert_eq!(repeat(123, TEST_VEC), TrackSizingFunction::Repeat(GridTrackRepetition::Count(123), TEST_VEC));
535 }
536
537 #[test]
test_repeat_auto_fit_str()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]
test_repeat_auto_fill_str()543 fn test_repeat_auto_fill_str() {
544 assert_eq!(repeat("auto-fill", TEST_VEC), TrackSizingFunction::Repeat(GridTrackRepetition::AutoFill, TEST_VEC));
545 }
546 }
547