-
Notifications
You must be signed in to change notification settings - Fork 115
/
style.rs
745 lines (669 loc) · 27.7 KB
/
style.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
//! A representation of [CSS layout properties](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) in Rust, used for flexbox layout
use crate::geometry::{Rect, Size};
/// How [`Nodes`](crate::node::Node) are aligned relative to the cross axis
///
/// The default behavior is [`AlignItems::Stretch`].
///
/// [Specification](https://www.w3.org/TR/css-flexbox-1/#align-items-property)
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlignItems {
/// Items are packed toward the start of the cross axis
FlexStart,
/// Items are packed toward the end of the cross axis
FlexEnd,
/// Items are packed along the center of the cross axis
Center,
/// Items are aligned such as their baselines align
Baseline,
/// Stretch to fill the container
Stretch,
}
impl Default for AlignItems {
fn default() -> Self {
Self::Stretch
}
}
/// Overrides the inherited [`AlignItems`] behavior for this node.
///
/// The behavior of any child nodes will be controlled by this node's [`AlignItems`] value.
///
/// The default behavior is [`AlignSelf::Auto`].
///
/// [Specification](https://www.w3.org/TR/css-flexbox-1/#align-items-property)
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlignSelf {
/// Inherits the [`AlignItems`] behavior of the parent
Auto,
/// Items are packed toward the start of the cross axis
FlexStart,
/// Items are packed toward the end of the cross axis
FlexEnd,
/// Items are packed along the center of the cross axis
Center,
/// Items are aligned such as their baselines align
Baseline,
/// Distribute items evenly, but stretch them to fill the container
Stretch,
}
impl Default for AlignSelf {
fn default() -> Self {
Self::Auto
}
}
/// Sets the distribution of space between and around content items along the cross-axis
///
/// The default value is [`AlignContent::Stretch`].
///
/// [Specification](https://www.w3.org/TR/css-flexbox-1/#align-content-property)
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlignContent {
/// Items are packed toward the start of the axis
FlexStart,
/// Items are packed toward the end of the axis
FlexEnd,
/// Items are centered around the middle of the axis
Center,
/// Items are stretched to fill the container
Stretch,
/// The first and last items are aligned flush with the edges of the container (no gap)
/// The gap between items is distributed evenly.
SpaceBetween,
/// The gap between the first and last items is exactly THE SAME as the gap between items.
/// The gaps are distributed evenly
SpaceEvenly,
/// The gap between the first and last items is exactly HALF the gap between items.
/// The gaps are distributed evenly in proportion to these ratios.
SpaceAround,
}
impl Default for AlignContent {
fn default() -> Self {
Self::Stretch
}
}
/// Sets the layout used for the children of this node
///
/// [`Display::Flex`] is the default value.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Display {
/// The children will follow the flexbox layout algorithm
Flex,
/// The children will not be laid out, and will follow absolute positioning
None,
}
impl Default for Display {
fn default() -> Self {
Self::Flex
}
}
/// The direction of the flexbox layout main axis.
///
/// There are always two perpendicular layout axes: main (or primary) and cross (or secondary).
/// Adding items will cause them to be positioned adjacent to each other along the main axis.
/// By varying this value throughout your tree, you can create complex axis-aligned layouts.
///
/// Items are always aligned relative to the cross axis, and justified relative to the main axis.
///
/// The default behavior is [`FlexDirection::Row`].
///
/// [Specification](https://www.w3.org/TR/css-flexbox-1/#flex-direction-property)
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum FlexDirection {
/// Defines +x as the main axis
///
/// Items will be added from left to right in a row.
Row,
/// Defines +y as the main axis
///
/// Items will be added from top to bottom in a column.
Column,
/// Defines -x as the main axis
///
/// Items will be added from right to left in a row.
RowReverse,
/// Defines -y as the main axis
///
/// Items will be added from bottom to top in a column.
ColumnReverse,
}
impl Default for FlexDirection {
fn default() -> Self {
Self::Row
}
}
impl FlexDirection {
#[inline]
/// Is the direction [`FlexDirection::Row`] or [`FlexDirection::RowReverse`]?
pub(crate) fn is_row(self) -> bool {
matches!(self, Self::Row | Self::RowReverse)
}
#[inline]
/// Is the direction [`FlexDirection::Column`] or [`FlexDirection::ColumnReverse`]?
pub(crate) fn is_column(self) -> bool {
matches!(self, Self::Column | Self::ColumnReverse)
}
#[inline]
/// Is the direction [`FlexDirection::RowReverse`] or [`FlexDirection::ColumnReverse`]?
pub(crate) fn is_reverse(self) -> bool {
matches!(self, Self::RowReverse | Self::ColumnReverse)
}
}
/// Sets the distribution of space between and around content items along the main-axis
///
/// The default value is [`JustifyContent::FlexStart`].
///
/// [Specification](https://www.w3.org/TR/css-flexbox-1/#justify-content-property)
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum JustifyContent {
/// Items are packed toward the start of the main axis
FlexStart,
/// Items are packed toward the end of the main axis
FlexEnd,
/// Items are packed along the center of the main axis
Center,
/// The first and last items are aligned flush with the edges of the container (no gap)
/// The gaps between items are distributed evenly.
SpaceBetween,
/// The gap between the first and last items is exactly THE SAME as the gap between items.
/// The gaps are distributed evenly
SpaceEvenly,
/// The gap between the first and last items is exactly HALF the gap between items.
/// The gaps are distributed evenly in proportion to these ratios.
SpaceAround,
}
impl Default for JustifyContent {
fn default() -> Self {
Self::FlexStart
}
}
/// The positioning strategy for this item.
///
/// This controls both how the origin is determined for the [`Style::position`] field,
/// and whether or not the item will be controlled by flexbox's layout algorithm.
///
/// WARNING: this enum follows the behavior of [CSS's `position` property](https://developer.mozilla.org/en-US/docs/Web/CSS/position),
/// which can be unintuitive.
///
/// [`PositionType::Relative`] is the default value, in contrast to the default behavior in CSS.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum PositionType {
/// The offset is computed relative to the final position given by the layout algorithm.
/// Offsets do not affect the position of any other items; they are effectively a correction factor applied at the end.
Relative,
/// The offset is computed relative to this item's closest positioned ancestor, if any.
/// Otherwise, it is placed relative to the origin.
/// No space is created for the item in the page layout, and its size will not be altered.
///
/// WARNING: to opt-out of layouting entirely, you must use [`Display::None`] instead on your [`Style`] object.
Absolute,
}
impl Default for PositionType {
fn default() -> Self {
Self::Relative
}
}
/// Controls whether flex items are forced onto one line or can wrap onto multiple lines.
///
/// Defaults to [`FlexWrap::NoWrap`]
///
/// [Specification](https://www.w3.org/TR/css-flexbox-1/#flex-wrap-property)
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum FlexWrap {
/// Items will not wrap and stay on a single line
NoWrap,
/// Items will wrap according to this item's [`FlexDirection`]
Wrap,
/// Items will wrap in the opposite direction to this item's [`FlexDirection`]
WrapReverse,
}
impl Default for FlexWrap {
fn default() -> Self {
Self::NoWrap
}
}
/// A unit of linear measurement
///
/// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size<T>`].
/// The default value is [`Dimension::Undefined`].
#[derive(Copy, Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Dimension {
/// The dimension is not given
Undefined,
/// The dimension should be automatically computed
Auto,
/// The dimension is stored in [points](https://en.wikipedia.org/wiki/Point_(typography))
///
/// Each point is about 0.353 mm in size.
Points(f32),
/// The dimension is stored in percentage relative to the parent item.
Percent(f32),
}
impl Default for Dimension {
fn default() -> Self {
Self::Undefined
}
}
impl Dimension {
/// Is this value defined?
pub(crate) fn is_defined(self) -> bool {
matches!(self, Dimension::Points(_) | Dimension::Percent(_))
}
}
impl Default for Rect<Dimension> {
fn default() -> Self {
Self {
left: Default::default(),
right: Default::default(),
top: Default::default(),
bottom: Default::default(),
}
}
}
impl Rect<Dimension> {
/// Generates a [`Rect<Dimension>`] using [`Dimension::Points`] values for `start` and `top`
#[must_use]
pub const fn top_from_points(start: f32, top: f32) -> Rect<Dimension> {
Rect { left: Dimension::Points(start), top: Dimension::Points(top), ..Rect::AUTO }
}
/// Generates a [`Rect<Dimension>`] using [`Dimension::Points`] values for `end` and `bottom`
#[must_use]
pub const fn bot_from_points(end: f32, bottom: f32) -> Rect<Dimension> {
Rect { right: Dimension::Points(end), bottom: Dimension::Points(bottom), ..Rect::AUTO }
}
/// Generates a [`Rect<Dimension>`] using [`Dimension::Percent`] values for `start` and `top`
#[must_use]
pub const fn top_from_percent(start: f32, top: f32) -> Rect<Dimension> {
Rect { left: Dimension::Percent(start), top: Dimension::Percent(top), ..Rect::AUTO }
}
/// Generates a [`Rect<Dimension>`] using [`Dimension::Percent`] values for `end` and `bottom`
#[must_use]
pub const fn bot_from_percent(end: f32, bottom: f32) -> Rect<Dimension> {
Rect { right: Dimension::Percent(end), bottom: Dimension::Percent(bottom), ..Rect::AUTO }
}
/// Generates a [`Rect<Dimension>`] using [`Dimension::Undefined`] for all values
pub const UNDEFINED: Rect<Dimension> = Self {
left: Dimension::Undefined,
right: Dimension::Undefined,
top: Dimension::Undefined,
bottom: Dimension::Undefined,
};
/// Generates a [`Rect<Dimension>`] using [`Dimension::Auto`] for all values
pub const AUTO: Rect<Dimension> =
Self { left: Dimension::Auto, right: Dimension::Auto, top: Dimension::Auto, bottom: Dimension::Auto };
/// Create a new Rect with [`Dimension::Points`]
#[must_use]
pub const fn from_points(start: f32, end: f32, top: f32, bottom: f32) -> Self {
Rect {
left: Dimension::Points(start),
right: Dimension::Points(end),
top: Dimension::Points(top),
bottom: Dimension::Points(bottom),
}
}
/// Create a new Rect with [`Dimension::Percent`]
#[must_use]
pub const fn from_percent(start: f32, end: f32, top: f32, bottom: f32) -> Self {
Rect {
left: Dimension::Percent(start),
right: Dimension::Percent(end),
top: Dimension::Percent(top),
bottom: Dimension::Percent(bottom),
}
}
}
impl Default for Size<Dimension> {
fn default() -> Self {
Self { width: Dimension::Auto, height: Dimension::Auto }
}
}
/// The flexbox layout information for a single [`Node`](crate::node::Node).
///
/// The most important idea in flexbox is the notion of a "main" and "cross" axis, which are always perpendicular to each other.
/// The orientation of these axes are controlled via the [`FlexDirection`] field of this struct.
///
/// This struct follows the [CSS equivalent](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox) directly;
/// information about the behavior on the web should transfer directly.
///
/// Detailed information about the exact behavior of each of these fields
/// can be found on [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS) by searching for the field name.
/// The distinction between margin, padding and border is explained well in
/// this [introduction to the box model](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model).
///
/// If the behavior does not match the flexbox layout algorithm on the web, please file a bug!
#[derive(Copy, Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct Style {
/// What layout strategy should be used?
pub display: Display,
/// What should the `position` value of this struct use as a base offset?
pub position_type: PositionType,
/// Which direction does the main axis flow in?
pub flex_direction: FlexDirection,
/// Should elements wrap, or stay in a single line?
pub flex_wrap: FlexWrap,
/// How should items be aligned relative to the cross axis?
pub align_items: AlignItems,
/// Should this item violate the cross axis alignment specified by its parent's [`AlignItems`]?
pub align_self: AlignSelf,
/// How should content contained within this item be aligned relative to the cross axis?
pub align_content: AlignContent,
/// How should items be aligned relative to the main axis?
pub justify_content: JustifyContent,
/// How should the position of this element be tweaked relative to the layout defined?
pub position: Rect<Dimension>,
/// How large should the margin be on each side?
pub margin: Rect<Dimension>,
/// How large should the padding be on each side?
pub padding: Rect<Dimension>,
/// How large should the border be on each side?
pub border: Rect<Dimension>,
// Gap
/// How large should the gaps between items in a grid or flex container be?
pub gap: Size<Dimension>,
/// The relative rate at which this item grows when it is expanding to fill space
///
/// 0.0 is the default value, and this value must not be negative.
pub flex_grow: f32,
/// The relative rate at which this item shrinks when it is contracting to fit into space
///
/// 1.0 is the default value, and this value must not be negative.
pub flex_shrink: f32,
/// Sets the initial main axis size of the item
pub flex_basis: Dimension,
/// Sets the initial size of the item
// TODO: why does this exist as distinct from flex_basis? How do they interact?
pub size: Size<Dimension>,
/// Controls the minimum size of the item
pub min_size: Size<Dimension>,
/// Controls the maximum size of the item
pub max_size: Size<Dimension>,
/// Sets the preferred aspect ratio for the item
///
/// The ratio is calculated as width divided by height.
pub aspect_ratio: Option<f32>,
}
impl Style {
/// The [`Default`] layout, in a form that can be used in const functions
pub const DEFAULT: Style = Style {
display: Display::Flex,
position_type: PositionType::Relative,
flex_direction: FlexDirection::Row,
flex_wrap: FlexWrap::NoWrap,
align_items: AlignItems::Stretch,
align_self: AlignSelf::Auto,
align_content: AlignContent::Stretch,
justify_content: JustifyContent::FlexStart,
position: Rect::UNDEFINED,
margin: Rect::UNDEFINED,
padding: Rect::UNDEFINED,
border: Rect::UNDEFINED,
gap: Size::UNDEFINED,
flex_grow: 0.0,
flex_shrink: 1.0,
flex_basis: Dimension::Auto,
size: Size::AUTO,
min_size: Size::AUTO,
max_size: Size::AUTO,
aspect_ratio: None,
};
}
impl Default for Style {
fn default() -> Self {
Style::DEFAULT
}
}
impl Style {
/// If the `direction` is row-oriented, the min width. Otherwise the min height
pub(crate) fn min_main_size(&self, direction: FlexDirection) -> Dimension {
if direction.is_row() {
self.min_size.width
} else {
self.min_size.height
}
}
/// If the `direction` is row-oriented, the max width. Otherwise the max height
pub(crate) fn max_main_size(&self, direction: FlexDirection) -> Dimension {
if direction.is_row() {
self.max_size.width
} else {
self.max_size.height
}
}
/// If the `direction` is row-oriented, the margin start. Otherwise the margin top
pub(crate) fn main_margin_start(&self, direction: FlexDirection) -> Dimension {
if direction.is_row() {
self.margin.left
} else {
self.margin.top
}
}
/// If the `direction` is row-oriented, the margin end. Otherwise the margin bottom
pub(crate) fn main_margin_end(&self, direction: FlexDirection) -> Dimension {
if direction.is_row() {
self.margin.right
} else {
self.margin.bottom
}
}
/// If the `direction` is row-oriented, the height. Otherwise the width
pub(crate) fn cross_size(&self, direction: FlexDirection) -> Dimension {
if direction.is_row() {
self.size.height
} else {
self.size.width
}
}
/// If the `direction` is row-oriented, the min height. Otherwise the min width
pub(crate) fn min_cross_size(&self, direction: FlexDirection) -> Dimension {
if direction.is_row() {
self.min_size.height
} else {
self.min_size.width
}
}
/// If the `direction` is row-oriented, the max height. Otherwise the max width
pub(crate) fn max_cross_size(&self, direction: FlexDirection) -> Dimension {
if direction.is_row() {
self.max_size.height
} else {
self.max_size.width
}
}
/// If the `direction` is row-oriented, the margin top. Otherwise the margin start
pub(crate) fn cross_margin_start(&self, direction: FlexDirection) -> Dimension {
if direction.is_row() {
self.margin.top
} else {
self.margin.left
}
}
/// If the `direction` is row-oriented, the margin bottom. Otherwise the margin end
pub(crate) fn cross_margin_end(&self, direction: FlexDirection) -> Dimension {
if direction.is_row() {
self.margin.bottom
} else {
self.margin.right
}
}
/// Computes the final alignment of this item based on the parent's [`AlignItems`] and this item's [`AlignSelf`]
pub(crate) fn align_self(&self, parent: &Style) -> AlignSelf {
// FUTURE WARNING: This function should never return AlignSelf::Auto
// See #169 https://github.com/DioxusLabs/taffy/pull/169#issuecomment-1157698840
if self.align_self == AlignSelf::Auto {
match parent.align_items {
AlignItems::FlexStart => AlignSelf::FlexStart,
AlignItems::FlexEnd => AlignSelf::FlexEnd,
AlignItems::Center => AlignSelf::Center,
AlignItems::Baseline => AlignSelf::Baseline,
AlignItems::Stretch => AlignSelf::Stretch,
}
} else {
self.align_self
}
}
}
#[allow(clippy::bool_assert_comparison)]
#[cfg(test)]
mod tests {
use super::Style;
use crate::geometry::Size;
#[test]
fn defaults_match() {
let old_defaults = Style {
display: Default::default(),
position_type: Default::default(),
flex_direction: Default::default(),
flex_wrap: Default::default(),
align_items: Default::default(),
align_self: Default::default(),
align_content: Default::default(),
justify_content: Default::default(),
position: Default::default(),
margin: Default::default(),
padding: Default::default(),
border: Default::default(),
gap: Size::UNDEFINED,
flex_grow: 0.0,
flex_shrink: 1.0,
flex_basis: super::Dimension::Auto,
size: Default::default(),
min_size: Default::default(),
max_size: Default::default(),
aspect_ratio: Default::default(),
};
assert_eq!(Style::DEFAULT, Style::default());
assert_eq!(Style::DEFAULT, old_defaults);
}
mod test_flex_direction {
use crate::style::*;
#[test]
fn flex_direction_is_row() {
assert_eq!(FlexDirection::Row.is_row(), true);
assert_eq!(FlexDirection::RowReverse.is_row(), true);
assert_eq!(FlexDirection::Column.is_row(), false);
assert_eq!(FlexDirection::ColumnReverse.is_row(), false);
}
#[test]
fn flex_direction_is_column() {
assert_eq!(FlexDirection::Row.is_column(), false);
assert_eq!(FlexDirection::RowReverse.is_column(), false);
assert_eq!(FlexDirection::Column.is_column(), true);
assert_eq!(FlexDirection::ColumnReverse.is_column(), true);
}
#[test]
fn flex_direction_is_reverse() {
assert_eq!(FlexDirection::Row.is_reverse(), false);
assert_eq!(FlexDirection::RowReverse.is_reverse(), true);
assert_eq!(FlexDirection::Column.is_reverse(), false);
assert_eq!(FlexDirection::ColumnReverse.is_reverse(), true);
}
}
mod test_flexbox_layout {
use crate::style::*;
fn layout_from_align_items(align: AlignItems) -> Style {
Style { align_items: align, ..Default::default() }
}
fn layout_from_align_self(align: AlignSelf) -> Style {
Style { align_self: align, ..Default::default() }
}
#[test]
fn flexbox_layout_min_main_size() {
let layout = Style { min_size: Size::from_points(1.0, 2.0), ..Default::default() };
assert_eq!(layout.min_main_size(FlexDirection::Row), Dimension::Points(1.0));
assert_eq!(layout.min_main_size(FlexDirection::Column), Dimension::Points(2.0));
}
#[test]
fn flexbox_layout_max_main_size() {
let layout = Style { max_size: Size::from_points(1.0, 2.0), ..Default::default() };
assert_eq!(layout.max_main_size(FlexDirection::Row), Dimension::Points(1.0));
assert_eq!(layout.max_main_size(FlexDirection::Column), Dimension::Points(2.0));
}
#[test]
fn flexbox_layout_main_margin_start() {
let layout = Style { margin: Rect::top_from_points(2.0, 1.0), ..Default::default() };
assert_eq!(layout.main_margin_start(FlexDirection::Row), Dimension::Points(2.0));
assert_eq!(layout.main_margin_start(FlexDirection::Column), Dimension::Points(1.0));
}
#[test]
fn flexbox_layout_main_margin_end() {
let layout = Style { margin: Rect::bot_from_points(2.0, 1.0), ..Default::default() };
assert_eq!(layout.main_margin_end(FlexDirection::Row), Dimension::Points(2.0));
assert_eq!(layout.main_margin_end(FlexDirection::Column), Dimension::Points(1.0));
}
#[test]
fn flexbox_layout_cross_size() {
let layout = Style { size: Size::from_points(1.0, 2.0), ..Default::default() };
assert_eq!(layout.cross_size(FlexDirection::Row), Dimension::Points(2.0));
assert_eq!(layout.cross_size(FlexDirection::Column), Dimension::Points(1.0));
}
#[test]
fn flexbox_layout_min_cross_size() {
let layout = Style { min_size: Size::from_points(1.0, 2.0), ..Default::default() };
assert_eq!(layout.min_cross_size(FlexDirection::Row), Dimension::Points(2.0));
assert_eq!(layout.min_cross_size(FlexDirection::Column), Dimension::Points(1.0));
}
#[test]
fn flexbox_layout_max_cross_size() {
let layout = Style { max_size: Size::from_points(1.0, 2.0), ..Default::default() };
assert_eq!(layout.max_cross_size(FlexDirection::Row), Dimension::Points(2.0));
assert_eq!(layout.max_cross_size(FlexDirection::Column), Dimension::Points(1.0));
}
#[test]
fn flexbox_layout_cross_margin_start() {
let layout = Style { margin: Rect::top_from_points(2.0, 1.0), ..Default::default() };
assert_eq!(layout.cross_margin_start(FlexDirection::Row), Dimension::Points(1.0));
assert_eq!(layout.cross_margin_start(FlexDirection::Column), Dimension::Points(2.0));
}
#[test]
fn flexbox_layout_cross_margin_end() {
let layout = Style { margin: Rect::bot_from_points(2.0, 1.0), ..Default::default() };
assert_eq!(layout.cross_margin_end(FlexDirection::Row), Dimension::Points(1.0));
assert_eq!(layout.cross_margin_end(FlexDirection::Column), Dimension::Points(2.0));
}
#[test]
fn flexbox_layout_align_self_auto() {
let parent = layout_from_align_items(AlignItems::FlexStart);
let layout = layout_from_align_self(AlignSelf::Auto);
assert_eq!(layout.align_self(&parent), AlignSelf::FlexStart);
let parent = layout_from_align_items(AlignItems::FlexEnd);
let layout = layout_from_align_self(AlignSelf::Auto);
assert_eq!(layout.align_self(&parent), AlignSelf::FlexEnd);
let parent = layout_from_align_items(AlignItems::Center);
let layout = layout_from_align_self(AlignSelf::Auto);
assert_eq!(layout.align_self(&parent), AlignSelf::Center);
let parent = layout_from_align_items(AlignItems::Baseline);
let layout = layout_from_align_self(AlignSelf::Auto);
assert_eq!(layout.align_self(&parent), AlignSelf::Baseline);
let parent = layout_from_align_items(AlignItems::Stretch);
let layout = layout_from_align_self(AlignSelf::Auto);
assert_eq!(layout.align_self(&parent), AlignSelf::Stretch);
}
#[test]
fn align_self() {
let parent = layout_from_align_items(AlignItems::FlexEnd);
let layout = layout_from_align_self(AlignSelf::FlexStart);
assert_eq!(layout.align_self(&parent), AlignSelf::FlexStart);
let parent = layout_from_align_items(AlignItems::FlexStart);
let layout = layout_from_align_self(AlignSelf::FlexEnd);
assert_eq!(layout.align_self(&parent), AlignSelf::FlexEnd);
let parent = layout_from_align_items(AlignItems::FlexStart);
let layout = layout_from_align_self(AlignSelf::Center);
assert_eq!(layout.align_self(&parent), AlignSelf::Center);
let parent = layout_from_align_items(AlignItems::FlexStart);
let layout = layout_from_align_self(AlignSelf::Baseline);
assert_eq!(layout.align_self(&parent), AlignSelf::Baseline);
let parent = layout_from_align_items(AlignItems::FlexStart);
let layout = layout_from_align_self(AlignSelf::Stretch);
assert_eq!(layout.align_self(&parent), AlignSelf::Stretch);
}
}
}