Move CompactLength into it's own module (#787)
1//! A typed representation of [CSS style properties](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) in Rust. Used as input to layout computation.
2mod alignment;
3mod available_space;
4mod compact_length;
5mod dimension;
6
7#[cfg(feature = "block_layout")]
8mod block;
9#[cfg(feature = "flexbox")]
10mod flex;
11#[cfg(feature = "grid")]
12mod grid;
13
14pub use self::alignment::{AlignContent, AlignItems, AlignSelf, JustifyContent, JustifyItems, JustifySelf};
15pub use self::available_space::AvailableSpace;
16pub use self::compact_length::CompactLength;
17pub use self::dimension::{Dimension, LengthPercentage, LengthPercentageAuto};
18
19#[cfg(feature = "block_layout")]
20pub use self::block::{BlockContainerStyle, BlockItemStyle, TextAlign};
21#[cfg(feature = "flexbox")]
22pub use self::flex::{FlexDirection, FlexWrap, FlexboxContainerStyle, FlexboxItemStyle};
23#[cfg(feature = "grid")]
24pub(crate) use self::grid::{GenericGridPlacement, OriginZeroGridPlacement};
25#[cfg(feature = "grid")]
26pub use self::grid::{
27 GridAutoFlow, GridContainerStyle, GridItemStyle, GridPlacement, GridTrackRepetition, MaxTrackSizingFunction,
28 MinTrackSizingFunction, NonRepeatedTrackSizingFunction, TrackSizingFunction,
29};
30
31use crate::geometry::{Point, Rect, Size};
32use crate::style_helpers::TaffyAuto as _;
33
34#[cfg(feature = "grid")]
35use crate::geometry::Line;
36#[cfg(feature = "serde")]
37use crate::style_helpers;
38#[cfg(feature = "grid")]
39use crate::util::sys::GridTrackVec;
40
41/// The core set of styles that are shared between all CSS layout nodes
42///
43/// Note that all methods come with a default implementation which simply returns the default value for that style property
44/// but this is a just a convenience to save on boilerplate for styles that your implementation doesn't support. You will need
45/// to override the default implementation for each style property that your style type actually supports.
46pub trait CoreStyle {
47 /// Which box generation mode should be used
48 #[inline(always)]
49 fn box_generation_mode(&self) -> BoxGenerationMode {
50 BoxGenerationMode::DEFAULT
51 }
52 /// Is block layout?
53 #[inline(always)]
54 fn is_block(&self) -> bool {
55 false
56 }
57 /// Which box do size styles apply to
58 #[inline(always)]
59 fn box_sizing(&self) -> BoxSizing {
60 BoxSizing::BorderBox
61 }
62
63 // Overflow properties
64 /// How children overflowing their container should affect layout
65 #[inline(always)]
66 fn overflow(&self) -> Point<Overflow> {
67 Style::DEFAULT.overflow
68 }
69 /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
70 #[inline(always)]
71 fn scrollbar_width(&self) -> f32 {
72 0.0
73 }
74
75 // Position properties
76 /// What should the `position` value of this struct use as a base offset?
77 #[inline(always)]
78 fn position(&self) -> Position {
79 Style::DEFAULT.position
80 }
81 /// How should the position of this element be tweaked relative to the layout defined?
82 #[inline(always)]
83 fn inset(&self) -> Rect<LengthPercentageAuto> {
84 Style::DEFAULT.inset
85 }
86
87 // Size properies
88 /// Sets the initial size of the item
89 #[inline(always)]
90 fn size(&self) -> Size<Dimension> {
91 Style::DEFAULT.size
92 }
93 /// Controls the minimum size of the item
94 #[inline(always)]
95 fn min_size(&self) -> Size<Dimension> {
96 Style::DEFAULT.min_size
97 }
98 /// Controls the maximum size of the item
99 #[inline(always)]
100 fn max_size(&self) -> Size<Dimension> {
101 Style::DEFAULT.max_size
102 }
103 /// Sets the preferred aspect ratio for the item
104 /// The ratio is calculated as width divided by height.
105 #[inline(always)]
106 fn aspect_ratio(&self) -> Option<f32> {
107 Style::DEFAULT.aspect_ratio
108 }
109
110 // Spacing Properties
111 /// How large should the margin be on each side?
112 #[inline(always)]
113 fn margin(&self) -> Rect<LengthPercentageAuto> {
114 Style::DEFAULT.margin
115 }
116 /// How large should the padding be on each side?
117 #[inline(always)]
118 fn padding(&self) -> Rect<LengthPercentage> {
119 Style::DEFAULT.padding
120 }
121 /// How large should the border be on each side?
122 #[inline(always)]
123 fn border(&self) -> Rect<LengthPercentage> {
124 Style::DEFAULT.border
125 }
126}
127
128/// Sets the layout used for the children of this node
129///
130/// The default values depends on on which feature flags are enabled. The order of precedence is: Flex, Grid, Block, None.
131#[derive(Copy, Clone, PartialEq, Eq, Debug)]
132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
133pub enum Display {
134 /// The children will follow the block layout algorithm
135 #[cfg(feature = "block_layout")]
136 Block,
137 /// The children will follow the flexbox layout algorithm
138 #[cfg(feature = "flexbox")]
139 Flex,
140 /// The children will follow the CSS Grid layout algorithm
141 #[cfg(feature = "grid")]
142 Grid,
143 /// The node is hidden, and it's children will also be hidden
144 None,
145}
146
147impl Display {
148 /// The default Display mode
149 #[cfg(feature = "flexbox")]
150 pub const DEFAULT: Display = Display::Flex;
151
152 /// The default Display mode
153 #[cfg(all(feature = "grid", not(feature = "flexbox")))]
154 pub const DEFAULT: Display = Display::Grid;
155
156 /// The default Display mode
157 #[cfg(all(feature = "block_layout", not(feature = "flexbox"), not(feature = "grid")))]
158 pub const DEFAULT: Display = Display::Block;
159
160 /// The default Display mode
161 #[cfg(all(not(feature = "flexbox"), not(feature = "grid"), not(feature = "block_layout")))]
162 pub const DEFAULT: Display = Display::None;
163}
164
165impl Default for Display {
166 fn default() -> Self {
167 Self::DEFAULT
168 }
169}
170
171impl core::fmt::Display for Display {
172 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
173 match self {
174 Display::None => write!(f, "NONE"),
175 #[cfg(feature = "block_layout")]
176 Display::Block => write!(f, "BLOCK"),
177 #[cfg(feature = "flexbox")]
178 Display::Flex => write!(f, "FLEX"),
179 #[cfg(feature = "grid")]
180 Display::Grid => write!(f, "GRID"),
181 }
182 }
183}
184
185/// An abstracted version of the CSS `display` property where any value other than "none" is represented by "normal"
186/// See: <https://www.w3.org/TR/css-display-3/#box-generation>
187#[derive(Copy, Clone, PartialEq, Eq, Debug)]
188#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
189pub enum BoxGenerationMode {
190 /// The node generates a box in the regular way
191 Normal,
192 /// The node and it's descendants generate no boxes (they are hidden)
193 None,
194}
195
196impl BoxGenerationMode {
197 /// The default of BoxGenerationMode
198 pub const DEFAULT: BoxGenerationMode = BoxGenerationMode::Normal;
199}
200
201impl Default for BoxGenerationMode {
202 fn default() -> Self {
203 Self::DEFAULT
204 }
205}
206
207/// The positioning strategy for this item.
208///
209/// This controls both how the origin is determined for the [`Style::position`] field,
210/// and whether or not the item will be controlled by flexbox's layout algorithm.
211///
212/// WARNING: this enum follows the behavior of [CSS's `position` property](https://developer.mozilla.org/en-US/docs/Web/CSS/position),
213/// which can be unintuitive.
214///
215/// [`Position::Relative`] is the default value, in contrast to the default behavior in CSS.
216#[derive(Copy, Clone, PartialEq, Eq, Debug)]
217#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
218pub enum Position {
219 /// The offset is computed relative to the final position given by the layout algorithm.
220 /// Offsets do not affect the position of any other items; they are effectively a correction factor applied at the end.
221 Relative,
222 /// The offset is computed relative to this item's closest positioned ancestor, if any.
223 /// Otherwise, it is placed relative to the origin.
224 /// No space is created for the item in the page layout, and its size will not be altered.
225 ///
226 /// WARNING: to opt-out of layouting entirely, you must use [`Display::None`] instead on your [`Style`] object.
227 Absolute,
228}
229
230impl Default for Position {
231 fn default() -> Self {
232 Self::Relative
233 }
234}
235
236/// Specifies whether size styles for this node are assigned to the node's "content box" or "border box"
237///
238/// - The "content box" is the node's inner size excluding padding, border and margin
239/// - The "border box" is the node's outer size including padding and border (but still excluding margin)
240///
241/// This property modifies the application of the following styles:
242///
243/// - `size`
244/// - `min_size`
245/// - `max_size`
246/// - `flex_basis`
247///
248/// See h<ttps://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing>
249#[derive(Copy, Clone, PartialEq, Eq, Debug)]
250#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
251pub enum BoxSizing {
252 /// Size styles such size, min_size, max_size specify the box's "content box" (the size excluding padding/border/margin)
253 BorderBox,
254 /// Size styles such size, min_size, max_size specify the box's "border box" (the size excluding margin but including padding/border)
255 ContentBox,
256}
257
258impl Default for BoxSizing {
259 fn default() -> Self {
260 Self::BorderBox
261 }
262}
263
264/// How children overflowing their container should affect layout
265///
266/// In CSS the primary effect of this property is to control whether contents of a parent container that overflow that container should
267/// be displayed anyway, be clipped, or trigger the container to become a scroll container. However it also has secondary effects on layout,
268/// the main ones being:
269///
270/// - The automatic minimum size Flexbox/CSS Grid items with non-`Visible` overflow is `0` rather than being content based
271/// - `Overflow::Scroll` nodes have space in the layout reserved for a scrollbar (width controlled by the `scrollbar_width` property)
272///
273/// In Taffy, we only implement the layout related secondary effects as we are not concerned with drawing/painting. The amount of space reserved for
274/// a scrollbar is controlled by the `scrollbar_width` property. If this is `0` then `Scroll` behaves identically to `Hidden`.
275///
276/// <https://developer.mozilla.org/en-US/docs/Web/CSS/overflow>
277#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
278#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
279pub enum Overflow {
280 /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content.
281 /// Content that overflows this node *should* contribute to the scroll region of its parent.
282 #[default]
283 Visible,
284 /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content.
285 /// Content that overflows this node should *not* contribute to the scroll region of its parent.
286 Clip,
287 /// The automatic minimum size of this node as a flexbox/grid item should be `0`.
288 /// Content that overflows this node should *not* contribute to the scroll region of its parent.
289 Hidden,
290 /// The automatic minimum size of this node as a flexbox/grid item should be `0`. Additionally, space should be reserved
291 /// for a scrollbar. The amount of space reserved is controlled by the `scrollbar_width` property.
292 /// Content that overflows this node should *not* contribute to the scroll region of its parent.
293 Scroll,
294}
295
296impl Overflow {
297 /// Returns true for overflow modes that contain their contents (`Overflow::Hidden`, `Overflow::Scroll`, `Overflow::Auto`)
298 /// or else false for overflow modes that allow their contains to spill (`Overflow::Visible`).
299 #[inline(always)]
300 pub(crate) fn is_scroll_container(self) -> bool {
301 match self {
302 Self::Visible | Self::Clip => false,
303 Self::Hidden | Self::Scroll => true,
304 }
305 }
306
307 /// Returns `Some(0.0)` if the overflow mode would cause the automatic minimum size of a Flexbox or CSS Grid item
308 /// to be `0`. Else returns None.
309 #[inline(always)]
310 pub(crate) fn maybe_into_automatic_min_size(self) -> Option<f32> {
311 match self.is_scroll_container() {
312 true => Some(0.0),
313 false => None,
314 }
315 }
316}
317
318/// A typed representation of the CSS style information for a single node.
319///
320/// The most important idea in flexbox is the notion of a "main" and "cross" axis, which are always perpendicular to each other.
321/// The orientation of these axes are controlled via the [`FlexDirection`] field of this struct.
322///
323/// This struct follows the [CSS equivalent](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox) directly;
324/// information about the behavior on the web should transfer directly.
325///
326/// Detailed information about the exact behavior of each of these fields
327/// can be found on [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS) by searching for the field name.
328/// The distinction between margin, padding and border is explained well in
329/// this [introduction to the box model](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model).
330///
331/// If the behavior does not match the flexbox layout algorithm on the web, please file a bug!
332#[derive(Clone, PartialEq, Debug)]
333#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
334#[cfg_attr(feature = "serde", serde(default))]
335pub struct Style {
336 /// What layout strategy should be used?
337 pub display: Display,
338 /// Whether a child is display:table or not. This affects children of block layouts.
339 /// This should really be part of `Display`, but it is currently seperate because table layout isn't implemented
340 pub item_is_table: bool,
341 /// Should size styles apply to the content box or the border box of the node
342 pub box_sizing: BoxSizing,
343
344 // Overflow properties
345 /// How children overflowing their container should affect layout
346 pub overflow: Point<Overflow>,
347 /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
348 pub scrollbar_width: f32,
349
350 // Position properties
351 /// What should the `position` value of this struct use as a base offset?
352 pub position: Position,
353 /// How should the position of this element be tweaked relative to the layout defined?
354 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
355 pub inset: Rect<LengthPercentageAuto>,
356
357 // Size properties
358 /// Sets the initial size of the item
359 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
360 pub size: Size<Dimension>,
361 /// Controls the minimum size of the item
362 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
363 pub min_size: Size<Dimension>,
364 /// Controls the maximum size of the item
365 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
366 pub max_size: Size<Dimension>,
367 /// Sets the preferred aspect ratio for the item
368 ///
369 /// The ratio is calculated as width divided by height.
370 pub aspect_ratio: Option<f32>,
371
372 // Spacing Properties
373 /// How large should the margin be on each side?
374 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
375 pub margin: Rect<LengthPercentageAuto>,
376 /// How large should the padding be on each side?
377 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
378 pub padding: Rect<LengthPercentage>,
379 /// How large should the border be on each side?
380 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
381 pub border: Rect<LengthPercentage>,
382
383 // Alignment properties
384 /// How this node's children aligned in the cross/block axis?
385 #[cfg(any(feature = "flexbox", feature = "grid"))]
386 pub align_items: Option<AlignItems>,
387 /// How this node should be aligned in the cross/block axis
388 /// Falls back to the parents [`AlignItems`] if not set
389 #[cfg(any(feature = "flexbox", feature = "grid"))]
390 pub align_self: Option<AlignSelf>,
391 /// How this node's children should be aligned in the inline axis
392 #[cfg(feature = "grid")]
393 pub justify_items: Option<AlignItems>,
394 /// How this node should be aligned in the inline axis
395 /// Falls back to the parents [`JustifyItems`] if not set
396 #[cfg(feature = "grid")]
397 pub justify_self: Option<AlignSelf>,
398 /// How should content contained within this item be aligned in the cross/block axis
399 #[cfg(any(feature = "flexbox", feature = "grid"))]
400 pub align_content: Option<AlignContent>,
401 /// How should content contained within this item be aligned in the main/inline axis
402 #[cfg(any(feature = "flexbox", feature = "grid"))]
403 pub justify_content: Option<JustifyContent>,
404 /// How large should the gaps between items in a grid or flex container be?
405 #[cfg(any(feature = "flexbox", feature = "grid"))]
406 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
407 pub gap: Size<LengthPercentage>,
408
409 // Block container properties
410 /// How items elements should aligned in the inline axis
411 #[cfg(feature = "block_layout")]
412 pub text_align: TextAlign,
413
414 // Flexbox container properties
415 /// Which direction does the main axis flow in?
416 #[cfg(feature = "flexbox")]
417 pub flex_direction: FlexDirection,
418 /// Should elements wrap, or stay in a single line?
419 #[cfg(feature = "flexbox")]
420 pub flex_wrap: FlexWrap,
421
422 // Flexbox item properties
423 /// Sets the initial main axis size of the item
424 #[cfg(feature = "flexbox")]
425 pub flex_basis: Dimension,
426 /// The relative rate at which this item grows when it is expanding to fill space
427 ///
428 /// 0.0 is the default value, and this value must be positive.
429 #[cfg(feature = "flexbox")]
430 pub flex_grow: f32,
431 /// The relative rate at which this item shrinks when it is contracting to fit into space
432 ///
433 /// 1.0 is the default value, and this value must be positive.
434 #[cfg(feature = "flexbox")]
435 pub flex_shrink: f32,
436
437 // Grid container properies
438 /// Defines the track sizing functions (heights) of the grid rows
439 #[cfg(feature = "grid")]
440 pub grid_template_rows: GridTrackVec<TrackSizingFunction>,
441 /// Defines the track sizing functions (widths) of the grid columns
442 #[cfg(feature = "grid")]
443 pub grid_template_columns: GridTrackVec<TrackSizingFunction>,
444 /// Defines the size of implicitly created rows
445 #[cfg(feature = "grid")]
446 pub grid_auto_rows: GridTrackVec<NonRepeatedTrackSizingFunction>,
447 /// Defined the size of implicitly created columns
448 #[cfg(feature = "grid")]
449 pub grid_auto_columns: GridTrackVec<NonRepeatedTrackSizingFunction>,
450 /// Controls how items get placed into the grid for auto-placed items
451 #[cfg(feature = "grid")]
452 pub grid_auto_flow: GridAutoFlow,
453
454 // Grid child properties
455 /// Defines which row in the grid the item should start and end at
456 #[cfg(feature = "grid")]
457 pub grid_row: Line<GridPlacement>,
458 /// Defines which column in the grid the item should start and end at
459 #[cfg(feature = "grid")]
460 pub grid_column: Line<GridPlacement>,
461}
462
463impl Style {
464 /// The [`Default`] layout, in a form that can be used in const functions
465 pub const DEFAULT: Style = Style {
466 display: Display::DEFAULT,
467 item_is_table: false,
468 box_sizing: BoxSizing::BorderBox,
469 overflow: Point { x: Overflow::Visible, y: Overflow::Visible },
470 scrollbar_width: 0.0,
471 position: Position::Relative,
472 inset: Rect::auto(),
473 margin: Rect::zero(),
474 padding: Rect::zero(),
475 border: Rect::zero(),
476 size: Size::auto(),
477 min_size: Size::auto(),
478 max_size: Size::auto(),
479 aspect_ratio: None,
480 #[cfg(any(feature = "flexbox", feature = "grid"))]
481 gap: Size::zero(),
482 // Alignment
483 #[cfg(any(feature = "flexbox", feature = "grid"))]
484 align_items: None,
485 #[cfg(any(feature = "flexbox", feature = "grid"))]
486 align_self: None,
487 #[cfg(feature = "grid")]
488 justify_items: None,
489 #[cfg(feature = "grid")]
490 justify_self: None,
491 #[cfg(any(feature = "flexbox", feature = "grid"))]
492 align_content: None,
493 #[cfg(any(feature = "flexbox", feature = "grid"))]
494 justify_content: None,
495 // Block
496 #[cfg(feature = "block_layout")]
497 text_align: TextAlign::Auto,
498 // Flexbox
499 #[cfg(feature = "flexbox")]
500 flex_direction: FlexDirection::Row,
501 #[cfg(feature = "flexbox")]
502 flex_wrap: FlexWrap::NoWrap,
503 #[cfg(feature = "flexbox")]
504 flex_grow: 0.0,
505 #[cfg(feature = "flexbox")]
506 flex_shrink: 1.0,
507 #[cfg(feature = "flexbox")]
508 flex_basis: Dimension::AUTO,
509 // Grid
510 #[cfg(feature = "grid")]
511 grid_template_rows: GridTrackVec::new(),
512 #[cfg(feature = "grid")]
513 grid_template_columns: GridTrackVec::new(),
514 #[cfg(feature = "grid")]
515 grid_auto_rows: GridTrackVec::new(),
516 #[cfg(feature = "grid")]
517 grid_auto_columns: GridTrackVec::new(),
518 #[cfg(feature = "grid")]
519 grid_auto_flow: GridAutoFlow::Row,
520 #[cfg(feature = "grid")]
521 grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
522 #[cfg(feature = "grid")]
523 grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
524 };
525}
526
527impl Default for Style {
528 fn default() -> Self {
529 Style::DEFAULT
530 }
531}
532
533impl CoreStyle for Style {
534 #[inline(always)]
535 fn box_generation_mode(&self) -> BoxGenerationMode {
536 match self.display {
537 Display::None => BoxGenerationMode::None,
538 _ => BoxGenerationMode::Normal,
539 }
540 }
541 #[inline(always)]
542 #[cfg(feature = "block_layout")]
543 fn is_block(&self) -> bool {
544 matches!(self.display, Display::Block)
545 }
546 #[inline(always)]
547 fn box_sizing(&self) -> BoxSizing {
548 self.box_sizing
549 }
550 #[inline(always)]
551 fn overflow(&self) -> Point<Overflow> {
552 self.overflow
553 }
554 #[inline(always)]
555 fn scrollbar_width(&self) -> f32 {
556 self.scrollbar_width
557 }
558 #[inline(always)]
559 fn position(&self) -> Position {
560 self.position
561 }
562 #[inline(always)]
563 fn inset(&self) -> Rect<LengthPercentageAuto> {
564 self.inset
565 }
566 #[inline(always)]
567 fn size(&self) -> Size<Dimension> {
568 self.size
569 }
570 #[inline(always)]
571 fn min_size(&self) -> Size<Dimension> {
572 self.min_size
573 }
574 #[inline(always)]
575 fn max_size(&self) -> Size<Dimension> {
576 self.max_size
577 }
578 #[inline(always)]
579 fn aspect_ratio(&self) -> Option<f32> {
580 self.aspect_ratio
581 }
582 #[inline(always)]
583 fn margin(&self) -> Rect<LengthPercentageAuto> {
584 self.margin
585 }
586 #[inline(always)]
587 fn padding(&self) -> Rect<LengthPercentage> {
588 self.padding
589 }
590 #[inline(always)]
591 fn border(&self) -> Rect<LengthPercentage> {
592 self.border
593 }
594}
595
596impl<T: CoreStyle> CoreStyle for &'_ T {
597 #[inline(always)]
598 fn box_generation_mode(&self) -> BoxGenerationMode {
599 (*self).box_generation_mode()
600 }
601 #[inline(always)]
602 fn is_block(&self) -> bool {
603 (*self).is_block()
604 }
605 #[inline(always)]
606 fn box_sizing(&self) -> BoxSizing {
607 (*self).box_sizing()
608 }
609 #[inline(always)]
610 fn overflow(&self) -> Point<Overflow> {
611 (*self).overflow()
612 }
613 #[inline(always)]
614 fn scrollbar_width(&self) -> f32 {
615 (*self).scrollbar_width()
616 }
617 #[inline(always)]
618 fn position(&self) -> Position {
619 (*self).position()
620 }
621 #[inline(always)]
622 fn inset(&self) -> Rect<LengthPercentageAuto> {
623 (*self).inset()
624 }
625 #[inline(always)]
626 fn size(&self) -> Size<Dimension> {
627 (*self).size()
628 }
629 #[inline(always)]
630 fn min_size(&self) -> Size<Dimension> {
631 (*self).min_size()
632 }
633 #[inline(always)]
634 fn max_size(&self) -> Size<Dimension> {
635 (*self).max_size()
636 }
637 #[inline(always)]
638 fn aspect_ratio(&self) -> Option<f32> {
639 (*self).aspect_ratio()
640 }
641 #[inline(always)]
642 fn margin(&self) -> Rect<LengthPercentageAuto> {
643 (*self).margin()
644 }
645 #[inline(always)]
646 fn padding(&self) -> Rect<LengthPercentage> {
647 (*self).padding()
648 }
649 #[inline(always)]
650 fn border(&self) -> Rect<LengthPercentage> {
651 (*self).border()
652 }
653}
654
655#[cfg(feature = "block_layout")]
656impl BlockContainerStyle for &Style {
657 #[inline(always)]
658 fn text_align(&self) -> TextAlign {
659 self.text_align
660 }
661}
662
663#[cfg(feature = "block_layout")]
664impl<T: BlockContainerStyle> BlockContainerStyle for &'_ T {
665 #[inline(always)]
666 fn text_align(&self) -> TextAlign {
667 (*self).text_align()
668 }
669}
670
671#[cfg(feature = "block_layout")]
672impl BlockItemStyle for Style {
673 #[inline(always)]
674 fn is_table(&self) -> bool {
675 self.item_is_table
676 }
677}
678
679#[cfg(feature = "block_layout")]
680impl<T: BlockItemStyle> BlockItemStyle for &'_ T {
681 #[inline(always)]
682 fn is_table(&self) -> bool {
683 (*self).is_table()
684 }
685}
686
687#[cfg(feature = "flexbox")]
688impl FlexboxContainerStyle for Style {
689 #[inline(always)]
690 fn flex_direction(&self) -> FlexDirection {
691 self.flex_direction
692 }
693 #[inline(always)]
694 fn flex_wrap(&self) -> FlexWrap {
695 self.flex_wrap
696 }
697 #[inline(always)]
698 fn gap(&self) -> Size<LengthPercentage> {
699 self.gap
700 }
701 #[inline(always)]
702 fn align_content(&self) -> Option<AlignContent> {
703 self.align_content
704 }
705 #[inline(always)]
706 fn align_items(&self) -> Option<AlignItems> {
707 self.align_items
708 }
709 #[inline(always)]
710 fn justify_content(&self) -> Option<JustifyContent> {
711 self.justify_content
712 }
713}
714
715#[cfg(feature = "flexbox")]
716impl<T: FlexboxContainerStyle> FlexboxContainerStyle for &'_ T {
717 #[inline(always)]
718 fn flex_direction(&self) -> FlexDirection {
719 (*self).flex_direction()
720 }
721 #[inline(always)]
722 fn flex_wrap(&self) -> FlexWrap {
723 (*self).flex_wrap()
724 }
725 #[inline(always)]
726 fn gap(&self) -> Size<LengthPercentage> {
727 (*self).gap()
728 }
729 #[inline(always)]
730 fn align_content(&self) -> Option<AlignContent> {
731 (*self).align_content()
732 }
733 #[inline(always)]
734 fn align_items(&self) -> Option<AlignItems> {
735 (*self).align_items()
736 }
737 #[inline(always)]
738 fn justify_content(&self) -> Option<JustifyContent> {
739 (*self).justify_content()
740 }
741}
742
743#[cfg(feature = "flexbox")]
744impl FlexboxItemStyle for Style {
745 #[inline(always)]
746 fn flex_basis(&self) -> Dimension {
747 self.flex_basis
748 }
749 #[inline(always)]
750 fn flex_grow(&self) -> f32 {
751 self.flex_grow
752 }
753 #[inline(always)]
754 fn flex_shrink(&self) -> f32 {
755 self.flex_shrink
756 }
757 #[inline(always)]
758 fn align_self(&self) -> Option<AlignSelf> {
759 self.align_self
760 }
761}
762
763#[cfg(feature = "flexbox")]
764impl<T: FlexboxItemStyle> FlexboxItemStyle for &'_ T {
765 #[inline(always)]
766 fn flex_basis(&self) -> Dimension {
767 (*self).flex_basis()
768 }
769 #[inline(always)]
770 fn flex_grow(&self) -> f32 {
771 (*self).flex_grow()
772 }
773 #[inline(always)]
774 fn flex_shrink(&self) -> f32 {
775 (*self).flex_shrink()
776 }
777 #[inline(always)]
778 fn align_self(&self) -> Option<AlignSelf> {
779 (*self).align_self()
780 }
781}
782
783#[cfg(feature = "grid")]
784impl GridContainerStyle for Style {
785 type TemplateTrackList<'a>
786 = &'a [TrackSizingFunction]
787 where
788 Self: 'a;
789 type AutoTrackList<'a>
790 = &'a [NonRepeatedTrackSizingFunction]
791 where
792 Self: 'a;
793
794 #[inline(always)]
795 fn grid_template_rows(&self) -> &[TrackSizingFunction] {
796 &self.grid_template_rows
797 }
798 #[inline(always)]
799 fn grid_template_columns(&self) -> &[TrackSizingFunction] {
800 &self.grid_template_columns
801 }
802 #[inline(always)]
803 fn grid_auto_rows(&self) -> &[NonRepeatedTrackSizingFunction] {
804 &self.grid_auto_rows
805 }
806 #[inline(always)]
807 fn grid_auto_columns(&self) -> &[NonRepeatedTrackSizingFunction] {
808 &self.grid_auto_columns
809 }
810 #[inline(always)]
811 fn grid_auto_flow(&self) -> GridAutoFlow {
812 self.grid_auto_flow
813 }
814 #[inline(always)]
815 fn gap(&self) -> Size<LengthPercentage> {
816 self.gap
817 }
818 #[inline(always)]
819 fn align_content(&self) -> Option<AlignContent> {
820 self.align_content
821 }
822 #[inline(always)]
823 fn justify_content(&self) -> Option<JustifyContent> {
824 self.justify_content
825 }
826 #[inline(always)]
827 fn align_items(&self) -> Option<AlignItems> {
828 self.align_items
829 }
830 #[inline(always)]
831 fn justify_items(&self) -> Option<AlignItems> {
832 self.justify_items
833 }
834}
835
836#[cfg(feature = "grid")]
837impl<T: GridContainerStyle> GridContainerStyle for &'_ T {
838 type TemplateTrackList<'a>
839 = T::TemplateTrackList<'a>
840 where
841 Self: 'a;
842 type AutoTrackList<'a>
843 = T::AutoTrackList<'a>
844 where
845 Self: 'a;
846
847 #[inline(always)]
848 fn grid_template_rows(&self) -> Self::TemplateTrackList<'_> {
849 (*self).grid_template_rows()
850 }
851 #[inline(always)]
852 fn grid_template_columns(&self) -> Self::TemplateTrackList<'_> {
853 (*self).grid_template_columns()
854 }
855 #[inline(always)]
856 fn grid_auto_rows(&self) -> Self::AutoTrackList<'_> {
857 (*self).grid_auto_rows()
858 }
859 #[inline(always)]
860 fn grid_auto_columns(&self) -> Self::AutoTrackList<'_> {
861 (*self).grid_auto_columns()
862 }
863 #[inline(always)]
864 fn grid_auto_flow(&self) -> GridAutoFlow {
865 (*self).grid_auto_flow()
866 }
867 #[inline(always)]
868 fn gap(&self) -> Size<LengthPercentage> {
869 (*self).gap()
870 }
871 #[inline(always)]
872 fn align_content(&self) -> Option<AlignContent> {
873 (*self).align_content()
874 }
875 #[inline(always)]
876 fn justify_content(&self) -> Option<JustifyContent> {
877 (*self).justify_content()
878 }
879 #[inline(always)]
880 fn align_items(&self) -> Option<AlignItems> {
881 (*self).align_items()
882 }
883 #[inline(always)]
884 fn justify_items(&self) -> Option<AlignItems> {
885 (*self).justify_items()
886 }
887}
888
889#[cfg(feature = "grid")]
890impl GridItemStyle for &'_ Style {
891 #[inline(always)]
892 fn grid_row(&self) -> Line<GridPlacement> {
893 self.grid_row
894 }
895 #[inline(always)]
896 fn grid_column(&self) -> Line<GridPlacement> {
897 self.grid_column
898 }
899 #[inline(always)]
900 fn align_self(&self) -> Option<AlignSelf> {
901 self.align_self
902 }
903 #[inline(always)]
904 fn justify_self(&self) -> Option<AlignSelf> {
905 self.justify_self
906 }
907}
908
909#[cfg(feature = "grid")]
910impl<T: GridItemStyle> GridItemStyle for &'_ T {
911 #[inline(always)]
912 fn grid_row(&self) -> Line<GridPlacement> {
913 (*self).grid_row()
914 }
915 #[inline(always)]
916 fn grid_column(&self) -> Line<GridPlacement> {
917 (*self).grid_column()
918 }
919 #[inline(always)]
920 fn align_self(&self) -> Option<AlignSelf> {
921 (*self).align_self()
922 }
923 #[inline(always)]
924 fn justify_self(&self) -> Option<AlignSelf> {
925 (*self).justify_self()
926 }
927}
928
929#[cfg(test)]
930mod tests {
931 use super::Style;
932 use crate::{geometry::*, style_helpers::TaffyAuto as _};
933
934 #[test]
935 fn defaults_match() {
936 #[cfg(feature = "grid")]
937 use super::GridPlacement;
938
939 let old_defaults = Style {
940 display: Default::default(),
941 item_is_table: false,
942 box_sizing: Default::default(),
943 overflow: Default::default(),
944 scrollbar_width: 0.0,
945 position: Default::default(),
946 #[cfg(feature = "flexbox")]
947 flex_direction: Default::default(),
948 #[cfg(feature = "flexbox")]
949 flex_wrap: Default::default(),
950 #[cfg(any(feature = "flexbox", feature = "grid"))]
951 align_items: Default::default(),
952 #[cfg(any(feature = "flexbox", feature = "grid"))]
953 align_self: Default::default(),
954 #[cfg(feature = "grid")]
955 justify_items: Default::default(),
956 #[cfg(feature = "grid")]
957 justify_self: Default::default(),
958 #[cfg(any(feature = "flexbox", feature = "grid"))]
959 align_content: Default::default(),
960 #[cfg(any(feature = "flexbox", feature = "grid"))]
961 justify_content: Default::default(),
962 inset: Rect::auto(),
963 margin: Rect::zero(),
964 padding: Rect::zero(),
965 border: Rect::zero(),
966 gap: Size::zero(),
967 #[cfg(feature = "block_layout")]
968 text_align: Default::default(),
969 #[cfg(feature = "flexbox")]
970 flex_grow: 0.0,
971 #[cfg(feature = "flexbox")]
972 flex_shrink: 1.0,
973 #[cfg(feature = "flexbox")]
974 flex_basis: super::Dimension::AUTO,
975 size: Size::auto(),
976 min_size: Size::auto(),
977 max_size: Size::auto(),
978 aspect_ratio: Default::default(),
979 #[cfg(feature = "grid")]
980 grid_template_rows: Default::default(),
981 #[cfg(feature = "grid")]
982 grid_template_columns: Default::default(),
983 #[cfg(feature = "grid")]
984 grid_auto_rows: Default::default(),
985 #[cfg(feature = "grid")]
986 grid_auto_columns: Default::default(),
987 #[cfg(feature = "grid")]
988 grid_auto_flow: Default::default(),
989 #[cfg(feature = "grid")]
990 grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
991 #[cfg(feature = "grid")]
992 grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
993 };
994
995 assert_eq!(Style::DEFAULT, Style::default());
996 assert_eq!(Style::DEFAULT, old_defaults);
997 }
998
999 // NOTE: Please feel free the update the sizes in this test as required. This test is here to prevent unintentional size changes
1000 // and to serve as accurate up-to-date documentation on the sizes.
1001 #[test]
1002 fn style_sizes() {
1003 use super::*;
1004
1005 fn assert_type_size<T>(expected_size: usize) {
1006 let name = ::core::any::type_name::<T>();
1007 let name = name.replace("taffy::geometry::", "");
1008 let name = name.replace("taffy::style::dimension::", "");
1009 let name = name.replace("taffy::style::alignment::", "");
1010 let name = name.replace("taffy::style::flex::", "");
1011 let name = name.replace("taffy::style::grid::", "");
1012
1013 assert_eq!(
1014 ::core::mem::size_of::<T>(),
1015 expected_size,
1016 "Expected {} for be {} byte(s) but it was {} byte(s)",
1017 name,
1018 expected_size,
1019 ::core::mem::size_of::<T>(),
1020 );
1021 }
1022
1023 // Display and Position
1024 assert_type_size::<Display>(1);
1025 assert_type_size::<BoxSizing>(1);
1026 assert_type_size::<Position>(1);
1027 assert_type_size::<Overflow>(1);
1028
1029 // Dimensions and aggregations of Dimensions
1030 assert_type_size::<f32>(4);
1031 assert_type_size::<LengthPercentage>(8);
1032 assert_type_size::<LengthPercentageAuto>(8);
1033 assert_type_size::<Dimension>(8);
1034 assert_type_size::<Size<LengthPercentage>>(16);
1035 assert_type_size::<Size<LengthPercentageAuto>>(16);
1036 assert_type_size::<Size<Dimension>>(16);
1037 assert_type_size::<Rect<LengthPercentage>>(32);
1038 assert_type_size::<Rect<LengthPercentageAuto>>(32);
1039 assert_type_size::<Rect<Dimension>>(32);
1040
1041 // Alignment
1042 assert_type_size::<AlignContent>(1);
1043 assert_type_size::<AlignItems>(1);
1044 assert_type_size::<Option<AlignItems>>(1);
1045
1046 // Flexbox Container
1047 assert_type_size::<FlexDirection>(1);
1048 assert_type_size::<FlexWrap>(1);
1049
1050 // CSS Grid Container
1051 assert_type_size::<GridAutoFlow>(1);
1052 assert_type_size::<MinTrackSizingFunction>(8);
1053 assert_type_size::<MaxTrackSizingFunction>(8);
1054 assert_type_size::<NonRepeatedTrackSizingFunction>(16);
1055 assert_type_size::<TrackSizingFunction>(32);
1056 assert_type_size::<Vec<NonRepeatedTrackSizingFunction>>(24);
1057 assert_type_size::<Vec<TrackSizingFunction>>(24);
1058
1059 // CSS Grid Item
1060 assert_type_size::<GridPlacement>(4);
1061 assert_type_size::<Line<GridPlacement>>(8);
1062
1063 // Overall
1064 assert_type_size::<Style>(352);
1065 }
1066}