diff --git a/src/style/flex.rs b/src/style/flex.rs index 8cce6d051..2dfc3e9a6 100644 --- a/src/style/flex.rs +++ b/src/style/flex.rs @@ -1,4 +1,76 @@ //! Style types for Flexbox layout +use super::{AlignContent, AlignItems, AlignSelf, CoreStyle, Dimension, LengthPercentage, Style}; +use crate::geometry::Size; + +/// The set of styles required for a Flexbox container +pub trait FlexboxContainerStyle: CoreStyle { + /// Which direction does the main axis flow in? + #[inline(always)] + fn flex_direction(&self) -> FlexDirection { + Style::DEFAULT.flex_direction + } + /// Should elements wrap, or stay in a single line? + #[inline(always)] + fn flex_wrap(&self) -> FlexWrap { + Style::DEFAULT.flex_wrap + } + + /// How large should the gaps between items in a grid or flex container be? + #[inline(always)] + fn gap(&self) -> Size { + Style::DEFAULT.gap + } + + // Alignment properties + + /// How should content contained within this item be aligned in the cross/block axis + #[inline(always)] + fn align_content(&self) -> Option { + Style::DEFAULT.align_content + } + /// How this node's children aligned in the cross/block axis? + #[inline(always)] + fn align_items(&self) -> Option { + Style::DEFAULT.align_items + } + /// How this node's children should be aligned in the inline axis + #[inline(always)] + fn justify_items(&self) -> Option { + Style::DEFAULT.justify_items + } +} + +/// The set of styles required for a Flexbox item (child of a Flexbox container) +pub trait FlexboxItemStyle: CoreStyle { + /// Sets the initial main axis size of the item + #[inline(always)] + fn flex_basis(&self) -> Dimension { + Style::DEFAULT.flex_basis + } + /// The relative rate at which this item grows when it is expanding to fill space + #[inline(always)] + fn flex_grow(&self) -> f32 { + Style::DEFAULT.flex_grow + } + /// The relative rate at which this item shrinks when it is contracting to fit into space + #[inline(always)] + fn flex_shrink(&self) -> f32 { + Style::DEFAULT.flex_shrink + } + + /// How this node should be aligned in the cross/block axis + /// Falls back to the parents [`AlignItems`] if not set + #[inline(always)] + fn align_self(&self) -> Option { + Style::DEFAULT.align_self + } + /// How this node should be aligned in the inline axis + /// Falls back to the parents [`super::JustifyItems`] if not set + #[inline(always)] + fn justify_self(&self) -> Option { + Style::DEFAULT.justify_self + } +} /// Controls whether flex items are forced onto one line or can wrap onto multiple lines. /// diff --git a/src/style/grid.rs b/src/style/grid.rs index 63a76a0e3..510fc038c 100644 --- a/src/style/grid.rs +++ b/src/style/grid.rs @@ -1,13 +1,97 @@ //! Style types for CSS Grid layout -use super::{AlignContent, LengthPercentage, Style}; +use super::{AlignContent, AlignItems, AlignSelf, CoreStyle, JustifyContent, LengthPercentage, Style}; use crate::compute::grid::{GridCoordinate, GridLine, OriginZeroLine}; -use crate::geometry::{AbsoluteAxis, AbstractAxis}; -use crate::geometry::{Line, MinMax}; +use crate::geometry::{AbsoluteAxis, AbstractAxis, Line, MinMax, Size}; use crate::style_helpers::*; use crate::util::sys::GridTrackVec; use core::cmp::{max, min}; use core::convert::Infallible; +/// The set of styles required for a CSS Grid container +pub trait GridContainerStyle: CoreStyle { + /// Defines the track sizing functions (heights) of the grid rows + #[inline(always)] + fn grid_template_rows(&self) -> &[TrackSizingFunction] { + &[] + } + /// Defines the track sizing functions (widths) of the grid columns + #[inline(always)] + fn grid_template_columns(&self) -> &[TrackSizingFunction] { + &[] + } + /// Defines the size of implicitly created rows + #[inline(always)] + fn grid_auto_rows(&self) -> &[NonRepeatedTrackSizingFunction] { + &[] + } + /// Defined the size of implicitly created columns + #[inline(always)] + fn grid_auto_columns(&self) -> &[NonRepeatedTrackSizingFunction] { + &[] + } + /// Controls how items get placed into the grid for auto-placed items + #[inline(always)] + fn grid_auto_flow(&self) -> GridAutoFlow { + Style::DEFAULT.grid_auto_flow + } + + /// How large should the gaps between items in a grid or flex container be? + #[inline(always)] + fn gap(&self) -> Size { + Style::DEFAULT.gap + } + + // Alignment properties + + /// How should content contained within this item be aligned in the cross/block axis + #[inline(always)] + fn align_content(&self) -> Option { + Style::DEFAULT.align_content + } + /// How should contained within this item be aligned in the main/inline axis + #[inline(always)] + fn justify_content(&self) -> Option { + Style::DEFAULT.justify_content + } + /// How this node's children aligned in the cross/block axis? + #[inline(always)] + fn align_items(&self) -> Option { + Style::DEFAULT.align_items + } + /// How this node's children should be aligned in the inline axis + #[inline(always)] + fn justify_items(&self) -> Option { + Style::DEFAULT.justify_items + } +} + +/// The set of styles required for a CSS Grid item (child of a CSS Grid container) +pub trait GridItemStyle: CoreStyle { + /// Defines which row in the grid the item should start and end at + #[inline(always)] + fn grid_row(&self) -> Line { + Style::DEFAULT.grid_row + } + /// Defines which column in the grid the item should start and end at + #[inline(always)] + fn grid_column(&self) -> Line { + Style::DEFAULT.grid_column + } + + /// How this node should be aligned in the cross/block axis + /// Falls back to the parents [`AlignItems`] if not set + #[inline(always)] + fn align_self(&self) -> Option { + Style::DEFAULT.align_self + } + /// How this node should be aligned in the inline axis + /// Falls back to the parents [`super::JustifyItems`] if not set + #[inline(always)] + fn justify_self(&self) -> Option { + Style::DEFAULT.justify_self + } +} + /// Controls whether grid items are placed row-wise or column-wise. And whether the sparse or dense packing algorithm is used. /// /// The "dense" packing algorithm attempts to fill in holes earlier in the grid, if smaller items come up later. This may cause items to appear out-of-order, when doing so would fill in holes left by larger items. diff --git a/src/style/mod.rs b/src/style/mod.rs index 80acfd506..d08e00db7 100644 --- a/src/style/mod.rs +++ b/src/style/mod.rs @@ -9,7 +9,7 @@ pub use self::alignment::{AlignContent, AlignItems, AlignSelf, JustifyContent, J pub use self::dimension::{AvailableSpace, Dimension, LengthPercentage, LengthPercentageAuto}; #[cfg(feature = "flexbox")] -pub use self::flex::{FlexDirection, FlexWrap}; +pub use self::flex::{FlexDirection, FlexWrap, FlexboxContainerStyle, FlexboxItemStyle}; #[cfg(feature = "grid")] mod grid; @@ -17,8 +17,8 @@ mod grid; pub(crate) use self::grid::{GenericGridPlacement, OriginZeroGridPlacement}; #[cfg(feature = "grid")] pub use self::grid::{ - GridAutoFlow, GridPlacement, GridTrackRepetition, MaxTrackSizingFunction, MinTrackSizingFunction, - NonRepeatedTrackSizingFunction, TrackSizingFunction, + GridAutoFlow, GridContainerStyle, GridItemStyle, GridPlacement, GridTrackRepetition, MaxTrackSizingFunction, + MinTrackSizingFunction, NonRepeatedTrackSizingFunction, TrackSizingFunction, }; use crate::geometry::{Point, Rect, Size}; @@ -29,6 +29,80 @@ use crate::style_helpers; #[cfg(feature = "grid")] use crate::util::sys::GridTrackVec; +/// The core set of styles that are shared between all CSS layout nodes +/// +/// Note that all methods come with a default implementation which simply returns the default value for that style property +/// but this is a just a convenience to save on boilerplate for styles that your implementation doesn't support. You will need +/// to override the default implementation for each style property that your style type actually supports. +pub trait CoreStyle { + /// What layout strategy should be used? + // fn display(&self); + + // Overflow properties + /// How children overflowing their container should affect layout + #[inline(always)] + fn overflow(&self) -> Point { + Style::DEFAULT.overflow + } + /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes. + #[inline(always)] + fn scrollbar_width(&self) -> f32 { + 0.0 + } + + // Position properties + /// What should the `position` value of this struct use as a base offset? + #[inline(always)] + fn position(&self) -> Position { + Style::DEFAULT.position + } + /// How should the position of this element be tweaked relative to the layout defined? + #[inline(always)] + fn inset(&self) -> Rect { + Style::DEFAULT.inset + } + + // Size properies + /// Sets the initial size of the item + #[inline(always)] + fn size(&self) -> Size { + Style::DEFAULT.size + } + /// Controls the minimum size of the item + #[inline(always)] + fn min_size(&self) -> Size { + Style::DEFAULT.min_size + } + /// Controls the maximum size of the item + #[inline(always)] + fn max_size(&self) -> Size { + Style::DEFAULT.max_size + } + /// Sets the preferred aspect ratio for the item + /// The ratio is calculated as width divided by height. + #[inline(always)] + fn aspect_ratio(&self) -> Option { + Style::DEFAULT.aspect_ratio + } + + // Spacing Properties + /// How large should the margin be on each side? + #[inline(always)] + fn margin(&self) -> Rect { + Style::DEFAULT.margin + } + /// How large should the padding be on each side? + #[inline(always)] + fn padding(&self) -> Rect { + Style::DEFAULT.padding + } + /// How large should the border be on each side? + #[inline(always)] + fn border(&self) -> Rect { + Style::DEFAULT.border + } +} + /// Sets the layout used for the children of this node /// /// The default values depends on on which feature flags are enabled. The order of precedence is: Flex, Grid, Block, None. @@ -268,10 +342,10 @@ pub struct Style { pub flex_shrink: f32, // Grid container properies - /// Defines the track sizing functions (widths) of the grid rows + /// Defines the track sizing functions (heights) of the grid rows #[cfg(feature = "grid")] pub grid_template_rows: GridTrackVec, - /// Defines the track sizing functions (heights) of the grid columns + /// Defines the track sizing functions (widths) of the grid columns #[cfg(feature = "grid")] pub grid_template_columns: GridTrackVec, /// Defines the size of implicitly created rows @@ -358,6 +432,167 @@ impl Default for Style { } } +impl CoreStyle for Style { + #[inline(always)] + fn overflow(&self) -> Point { + self.overflow + } + #[inline(always)] + fn scrollbar_width(&self) -> f32 { + self.scrollbar_width + } + #[inline(always)] + fn position(&self) -> Position { + self.position + } + #[inline(always)] + fn inset(&self) -> Rect { + self.inset + } + #[inline(always)] + fn size(&self) -> Size { + self.size + } + #[inline(always)] + fn min_size(&self) -> Size { + self.min_size + } + #[inline(always)] + fn max_size(&self) -> Size { + self.max_size + } + #[inline(always)] + fn aspect_ratio(&self) -> Option { + self.aspect_ratio + } + #[inline(always)] + fn margin(&self) -> Rect { + self.margin + } + #[inline(always)] + fn padding(&self) -> Rect { + self.padding + } + #[inline(always)] + fn border(&self) -> Rect { + self.border + } +} + +#[cfg(feature = "flexbox")] +impl FlexboxContainerStyle for Style { + #[inline(always)] + fn flex_direction(&self) -> FlexDirection { + self.flex_direction + } + #[inline(always)] + fn flex_wrap(&self) -> FlexWrap { + self.flex_wrap + } + #[inline(always)] + fn gap(&self) -> Size { + self.gap + } + #[inline(always)] + fn align_content(&self) -> Option { + self.align_content + } + #[inline(always)] + fn align_items(&self) -> Option { + self.align_items + } + #[inline(always)] + fn justify_items(&self) -> Option { + self.justify_items + } +} +#[cfg(feature = "flexbox")] +impl FlexboxItemStyle for Style { + #[inline(always)] + fn flex_basis(&self) -> Dimension { + self.flex_basis + } + #[inline(always)] + fn flex_grow(&self) -> f32 { + self.flex_grow + } + #[inline(always)] + fn flex_shrink(&self) -> f32 { + self.flex_shrink + } + #[inline(always)] + fn align_self(&self) -> Option { + self.align_self + } + #[inline(always)] + fn justify_self(&self) -> Option { + self.justify_self + } +} + +#[cfg(feature = "grid")] +impl GridContainerStyle for Style { + #[inline(always)] + fn grid_template_rows(&self) -> &[TrackSizingFunction] { + &self.grid_template_rows + } + #[inline(always)] + fn grid_template_columns(&self) -> &[TrackSizingFunction] { + &self.grid_template_columns + } + #[inline(always)] + fn grid_auto_rows(&self) -> &[NonRepeatedTrackSizingFunction] { + &self.grid_auto_rows + } + #[inline(always)] + fn grid_auto_columns(&self) -> &[NonRepeatedTrackSizingFunction] { + &self.grid_auto_columns + } + #[inline(always)] + fn grid_auto_flow(&self) -> GridAutoFlow { + self.grid_auto_flow + } + #[inline(always)] + fn gap(&self) -> Size { + self.gap + } + #[inline(always)] + fn align_content(&self) -> Option { + self.align_content + } + #[inline(always)] + fn justify_content(&self) -> Option { + self.justify_content + } + #[inline(always)] + fn align_items(&self) -> Option { + self.align_items + } + #[inline(always)] + fn justify_items(&self) -> Option { + self.justify_items + } +} +#[cfg(feature = "grid")] +impl GridItemStyle for Style { + #[inline(always)] + fn grid_row(&self) -> Line { + self.grid_row + } + #[inline(always)] + fn grid_column(&self) -> Line { + self.grid_column + } + #[inline(always)] + fn align_self(&self) -> Option { + self.align_self + } + #[inline(always)] + fn justify_self(&self) -> Option { + self.justify_self + } +} + #[cfg(test)] mod tests { use super::Style;