
# Objective An easy way to create 2D grid layouts ## Solution Enable the `grid` feature in Taffy and add new style types for defining grids. ## Notes - ~I'm having a bit of trouble getting `#[derive(Reflect)]` to work properly. Help with that would be appreciated (EDIT: got it to compile by ignoring the problematic fields, but this presumably can't be merged).~ This is now fixed - ~The alignment types now have a `Normal` variant because I couldn't get reflect to work with `Option`.~ I've decided to stick with the flattened variant, as it saves a level of wrapping when authoring styles. But I've renamed the variants from `Normal` to `Default`. - ~This currently exposes a simplified API on top of grid. In particular the following is not currently supported:~ - ~Negative grid indices~ Now supported. - ~Custom `end` values for grid placement (you can only use `start` and `span`)~ Now supported - ~`minmax()` track sizing functions~ minmax is now support through a `GridTrack::minmax()` constructor - ~`repeat()`~ repeat is now implemented as `RepeatedGridTrack` - ~Documentation still needs to be improved.~ An initial pass over the documentation has been completed. ## Screenshot <img width="846" alt="Screenshot 2023-03-10 at 17 56 21" src="https://user-images.githubusercontent.com/1007307/224435332-69aa9eac-123d-4856-b75d-5449d3f1d426.png"> --- ## Changelog - Support for CSS Grid layout added to `bevy_ui` --------- Co-authored-by: Rob Parrett <robparrett@gmail.com> Co-authored-by: Andreas Weibye <13300393+Weibye@users.noreply.github.com>
667 lines
25 KiB
Rust
667 lines
25 KiB
Rust
use taffy::style_helpers;
|
|
|
|
use crate::{
|
|
AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, GridAutoFlow,
|
|
GridPlacement, GridTrack, GridTrackRepetition, JustifyContent, JustifyItems, JustifySelf,
|
|
MaxTrackSizingFunction, MinTrackSizingFunction, PositionType, RepeatedGridTrack, Size, Style,
|
|
UiRect, Val,
|
|
};
|
|
|
|
use super::LayoutContext;
|
|
|
|
impl Val {
|
|
fn into_length_percentage_auto(
|
|
self,
|
|
context: &LayoutContext,
|
|
) -> taffy::style::LengthPercentageAuto {
|
|
match self {
|
|
Val::Auto => taffy::style::LengthPercentageAuto::Auto,
|
|
Val::Percent(value) => taffy::style::LengthPercentageAuto::Percent(value / 100.),
|
|
Val::Px(value) => taffy::style::LengthPercentageAuto::Points(
|
|
(context.scale_factor * value as f64) as f32,
|
|
),
|
|
Val::VMin(value) => {
|
|
taffy::style::LengthPercentageAuto::Points(context.min_size * value / 100.)
|
|
}
|
|
Val::VMax(value) => {
|
|
taffy::style::LengthPercentageAuto::Points(context.max_size * value / 100.)
|
|
}
|
|
Val::Vw(value) => {
|
|
taffy::style::LengthPercentageAuto::Points(context.physical_size.x * value / 100.)
|
|
}
|
|
Val::Vh(value) => {
|
|
taffy::style::LengthPercentageAuto::Points(context.physical_size.y * value / 100.)
|
|
}
|
|
}
|
|
}
|
|
|
|
fn into_length_percentage(self, context: &LayoutContext) -> taffy::style::LengthPercentage {
|
|
match self.into_length_percentage_auto(context) {
|
|
taffy::style::LengthPercentageAuto::Auto => taffy::style::LengthPercentage::Points(0.0),
|
|
taffy::style::LengthPercentageAuto::Percent(value) => {
|
|
taffy::style::LengthPercentage::Percent(value)
|
|
}
|
|
taffy::style::LengthPercentageAuto::Points(value) => {
|
|
taffy::style::LengthPercentage::Points(value)
|
|
}
|
|
}
|
|
}
|
|
|
|
fn into_dimension(self, context: &LayoutContext) -> taffy::style::Dimension {
|
|
self.into_length_percentage_auto(context).into()
|
|
}
|
|
}
|
|
|
|
impl UiRect {
|
|
fn map_to_taffy_rect<T>(self, map_fn: impl Fn(Val) -> T) -> taffy::geometry::Rect<T> {
|
|
taffy::geometry::Rect {
|
|
left: map_fn(self.left),
|
|
right: map_fn(self.right),
|
|
top: map_fn(self.top),
|
|
bottom: map_fn(self.bottom),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Size {
|
|
fn map_to_taffy_size<T>(self, map_fn: impl Fn(Val) -> T) -> taffy::geometry::Size<T> {
|
|
taffy::geometry::Size {
|
|
width: map_fn(self.width),
|
|
height: map_fn(self.height),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn from_style(context: &LayoutContext, style: &Style) -> taffy::style::Style {
|
|
taffy::style::Style {
|
|
display: style.display.into(),
|
|
position: style.position_type.into(),
|
|
flex_direction: style.flex_direction.into(),
|
|
flex_wrap: style.flex_wrap.into(),
|
|
align_items: style.align_items.into(),
|
|
justify_items: style.justify_items.into(),
|
|
align_self: style.align_self.into(),
|
|
justify_self: style.justify_self.into(),
|
|
align_content: style.align_content.into(),
|
|
justify_content: style.justify_content.into(),
|
|
inset: taffy::prelude::Rect {
|
|
left: style.left.into_length_percentage_auto(context),
|
|
right: style.right.into_length_percentage_auto(context),
|
|
top: style.top.into_length_percentage_auto(context),
|
|
bottom: style.bottom.into_length_percentage_auto(context),
|
|
},
|
|
margin: style
|
|
.margin
|
|
.map_to_taffy_rect(|m| m.into_length_percentage_auto(context)),
|
|
padding: style
|
|
.padding
|
|
.map_to_taffy_rect(|m| m.into_length_percentage(context)),
|
|
border: style
|
|
.border
|
|
.map_to_taffy_rect(|m| m.into_length_percentage(context)),
|
|
flex_grow: style.flex_grow,
|
|
flex_shrink: style.flex_shrink,
|
|
flex_basis: style.flex_basis.into_dimension(context),
|
|
size: style.size.map_to_taffy_size(|s| s.into_dimension(context)),
|
|
min_size: style
|
|
.min_size
|
|
.map_to_taffy_size(|s| s.into_dimension(context)),
|
|
max_size: style
|
|
.max_size
|
|
.map_to_taffy_size(|s| s.into_dimension(context)),
|
|
aspect_ratio: style.aspect_ratio,
|
|
gap: style
|
|
.gap
|
|
.map_to_taffy_size(|s| s.into_length_percentage(context)),
|
|
grid_auto_flow: style.grid_auto_flow.into(),
|
|
grid_template_rows: style
|
|
.grid_template_rows
|
|
.iter()
|
|
.map(|track| track.clone_into_repeated_taffy_track(context))
|
|
.collect::<Vec<_>>(),
|
|
grid_template_columns: style
|
|
.grid_template_columns
|
|
.iter()
|
|
.map(|track| track.clone_into_repeated_taffy_track(context))
|
|
.collect::<Vec<_>>(),
|
|
grid_auto_rows: style
|
|
.grid_auto_rows
|
|
.iter()
|
|
.map(|track| track.into_taffy_track(context))
|
|
.collect::<Vec<_>>(),
|
|
grid_auto_columns: style
|
|
.grid_auto_columns
|
|
.iter()
|
|
.map(|track| track.into_taffy_track(context))
|
|
.collect::<Vec<_>>(),
|
|
grid_row: style.grid_row.into(),
|
|
grid_column: style.grid_column.into(),
|
|
}
|
|
}
|
|
|
|
impl From<AlignItems> for Option<taffy::style::AlignItems> {
|
|
fn from(value: AlignItems) -> Self {
|
|
match value {
|
|
AlignItems::Default => None,
|
|
AlignItems::Start => taffy::style::AlignItems::Start.into(),
|
|
AlignItems::End => taffy::style::AlignItems::End.into(),
|
|
AlignItems::FlexStart => taffy::style::AlignItems::FlexStart.into(),
|
|
AlignItems::FlexEnd => taffy::style::AlignItems::FlexEnd.into(),
|
|
AlignItems::Center => taffy::style::AlignItems::Center.into(),
|
|
AlignItems::Baseline => taffy::style::AlignItems::Baseline.into(),
|
|
AlignItems::Stretch => taffy::style::AlignItems::Stretch.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<JustifyItems> for Option<taffy::style::JustifyItems> {
|
|
fn from(value: JustifyItems) -> Self {
|
|
match value {
|
|
JustifyItems::Default => None,
|
|
JustifyItems::Start => taffy::style::JustifyItems::Start.into(),
|
|
JustifyItems::End => taffy::style::JustifyItems::End.into(),
|
|
JustifyItems::Center => taffy::style::JustifyItems::Center.into(),
|
|
JustifyItems::Baseline => taffy::style::JustifyItems::Baseline.into(),
|
|
JustifyItems::Stretch => taffy::style::JustifyItems::Stretch.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<AlignSelf> for Option<taffy::style::AlignSelf> {
|
|
fn from(value: AlignSelf) -> Self {
|
|
match value {
|
|
AlignSelf::Auto => None,
|
|
AlignSelf::Start => taffy::style::AlignSelf::Start.into(),
|
|
AlignSelf::End => taffy::style::AlignSelf::End.into(),
|
|
AlignSelf::FlexStart => taffy::style::AlignSelf::FlexStart.into(),
|
|
AlignSelf::FlexEnd => taffy::style::AlignSelf::FlexEnd.into(),
|
|
AlignSelf::Center => taffy::style::AlignSelf::Center.into(),
|
|
AlignSelf::Baseline => taffy::style::AlignSelf::Baseline.into(),
|
|
AlignSelf::Stretch => taffy::style::AlignSelf::Stretch.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<JustifySelf> for Option<taffy::style::JustifySelf> {
|
|
fn from(value: JustifySelf) -> Self {
|
|
match value {
|
|
JustifySelf::Auto => None,
|
|
JustifySelf::Start => taffy::style::JustifySelf::Start.into(),
|
|
JustifySelf::End => taffy::style::JustifySelf::End.into(),
|
|
JustifySelf::Center => taffy::style::JustifySelf::Center.into(),
|
|
JustifySelf::Baseline => taffy::style::JustifySelf::Baseline.into(),
|
|
JustifySelf::Stretch => taffy::style::JustifySelf::Stretch.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<AlignContent> for Option<taffy::style::AlignContent> {
|
|
fn from(value: AlignContent) -> Self {
|
|
match value {
|
|
AlignContent::Default => None,
|
|
AlignContent::Start => taffy::style::AlignContent::Start.into(),
|
|
AlignContent::End => taffy::style::AlignContent::End.into(),
|
|
AlignContent::FlexStart => taffy::style::AlignContent::FlexStart.into(),
|
|
AlignContent::FlexEnd => taffy::style::AlignContent::FlexEnd.into(),
|
|
AlignContent::Center => taffy::style::AlignContent::Center.into(),
|
|
AlignContent::Stretch => taffy::style::AlignContent::Stretch.into(),
|
|
AlignContent::SpaceBetween => taffy::style::AlignContent::SpaceBetween.into(),
|
|
AlignContent::SpaceAround => taffy::style::AlignContent::SpaceAround.into(),
|
|
AlignContent::SpaceEvenly => taffy::style::AlignContent::SpaceEvenly.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<JustifyContent> for Option<taffy::style::JustifyContent> {
|
|
fn from(value: JustifyContent) -> Self {
|
|
match value {
|
|
JustifyContent::Default => None,
|
|
JustifyContent::Start => taffy::style::JustifyContent::Start.into(),
|
|
JustifyContent::End => taffy::style::JustifyContent::End.into(),
|
|
JustifyContent::FlexStart => taffy::style::JustifyContent::FlexStart.into(),
|
|
JustifyContent::FlexEnd => taffy::style::JustifyContent::FlexEnd.into(),
|
|
JustifyContent::Center => taffy::style::JustifyContent::Center.into(),
|
|
JustifyContent::SpaceBetween => taffy::style::JustifyContent::SpaceBetween.into(),
|
|
JustifyContent::SpaceAround => taffy::style::JustifyContent::SpaceAround.into(),
|
|
JustifyContent::SpaceEvenly => taffy::style::JustifyContent::SpaceEvenly.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<Display> for taffy::style::Display {
|
|
fn from(value: Display) -> Self {
|
|
match value {
|
|
Display::Flex => taffy::style::Display::Flex,
|
|
Display::Grid => taffy::style::Display::Grid,
|
|
Display::None => taffy::style::Display::None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<FlexDirection> for taffy::style::FlexDirection {
|
|
fn from(value: FlexDirection) -> Self {
|
|
match value {
|
|
FlexDirection::Row => taffy::style::FlexDirection::Row,
|
|
FlexDirection::Column => taffy::style::FlexDirection::Column,
|
|
FlexDirection::RowReverse => taffy::style::FlexDirection::RowReverse,
|
|
FlexDirection::ColumnReverse => taffy::style::FlexDirection::ColumnReverse,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<PositionType> for taffy::style::Position {
|
|
fn from(value: PositionType) -> Self {
|
|
match value {
|
|
PositionType::Relative => taffy::style::Position::Relative,
|
|
PositionType::Absolute => taffy::style::Position::Absolute,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<FlexWrap> for taffy::style::FlexWrap {
|
|
fn from(value: FlexWrap) -> Self {
|
|
match value {
|
|
FlexWrap::NoWrap => taffy::style::FlexWrap::NoWrap,
|
|
FlexWrap::Wrap => taffy::style::FlexWrap::Wrap,
|
|
FlexWrap::WrapReverse => taffy::style::FlexWrap::WrapReverse,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<GridAutoFlow> for taffy::style::GridAutoFlow {
|
|
fn from(value: GridAutoFlow) -> Self {
|
|
match value {
|
|
GridAutoFlow::Row => taffy::style::GridAutoFlow::Row,
|
|
GridAutoFlow::RowDense => taffy::style::GridAutoFlow::RowDense,
|
|
GridAutoFlow::Column => taffy::style::GridAutoFlow::Column,
|
|
GridAutoFlow::ColumnDense => taffy::style::GridAutoFlow::ColumnDense,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<GridPlacement> for taffy::geometry::Line<taffy::style::GridPlacement> {
|
|
fn from(value: GridPlacement) -> Self {
|
|
let span = value.span.unwrap_or(1).max(1);
|
|
match (value.start, value.end) {
|
|
(Some(start), Some(end)) => taffy::geometry::Line {
|
|
start: style_helpers::line(start),
|
|
end: style_helpers::line(end),
|
|
},
|
|
(Some(start), None) => taffy::geometry::Line {
|
|
start: style_helpers::line(start),
|
|
end: style_helpers::span(span),
|
|
},
|
|
(None, Some(end)) => taffy::geometry::Line {
|
|
start: style_helpers::span(span),
|
|
end: style_helpers::line(end),
|
|
},
|
|
(None, None) => style_helpers::span(span),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MinTrackSizingFunction {
|
|
fn into_taffy(self, context: &LayoutContext) -> taffy::style::MinTrackSizingFunction {
|
|
match self {
|
|
MinTrackSizingFunction::Px(val) => taffy::style::MinTrackSizingFunction::Fixed(
|
|
Val::Px(val).into_length_percentage(context),
|
|
),
|
|
MinTrackSizingFunction::Percent(val) => taffy::style::MinTrackSizingFunction::Fixed(
|
|
Val::Percent(val).into_length_percentage(context),
|
|
),
|
|
MinTrackSizingFunction::Auto => taffy::style::MinTrackSizingFunction::Auto,
|
|
MinTrackSizingFunction::MinContent => taffy::style::MinTrackSizingFunction::MinContent,
|
|
MinTrackSizingFunction::MaxContent => taffy::style::MinTrackSizingFunction::MaxContent,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl MaxTrackSizingFunction {
|
|
fn into_taffy(self, context: &LayoutContext) -> taffy::style::MaxTrackSizingFunction {
|
|
match self {
|
|
MaxTrackSizingFunction::Px(val) => taffy::style::MaxTrackSizingFunction::Fixed(
|
|
Val::Px(val).into_length_percentage(context),
|
|
),
|
|
MaxTrackSizingFunction::Percent(val) => taffy::style::MaxTrackSizingFunction::Fixed(
|
|
Val::Percent(val).into_length_percentage(context),
|
|
),
|
|
MaxTrackSizingFunction::Auto => taffy::style::MaxTrackSizingFunction::Auto,
|
|
MaxTrackSizingFunction::MinContent => taffy::style::MaxTrackSizingFunction::MinContent,
|
|
MaxTrackSizingFunction::MaxContent => taffy::style::MaxTrackSizingFunction::MaxContent,
|
|
MaxTrackSizingFunction::FitContentPx(val) => {
|
|
taffy::style::MaxTrackSizingFunction::FitContent(
|
|
Val::Px(val).into_length_percentage(context),
|
|
)
|
|
}
|
|
MaxTrackSizingFunction::FitContentPercent(val) => {
|
|
taffy::style::MaxTrackSizingFunction::FitContent(
|
|
Val::Percent(val).into_length_percentage(context),
|
|
)
|
|
}
|
|
MaxTrackSizingFunction::Fraction(fraction) => {
|
|
taffy::style::MaxTrackSizingFunction::Fraction(fraction)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl GridTrack {
|
|
fn into_taffy_track(
|
|
self,
|
|
context: &LayoutContext,
|
|
) -> taffy::style::NonRepeatedTrackSizingFunction {
|
|
let min = self.min_sizing_function.into_taffy(context);
|
|
let max = self.max_sizing_function.into_taffy(context);
|
|
taffy::style_helpers::minmax(min, max)
|
|
}
|
|
}
|
|
|
|
impl RepeatedGridTrack {
|
|
fn clone_into_repeated_taffy_track(
|
|
&self,
|
|
context: &LayoutContext,
|
|
) -> taffy::style::TrackSizingFunction {
|
|
if self.tracks.len() == 1 && self.repetition == GridTrackRepetition::Count(1) {
|
|
let min = self.tracks[0].min_sizing_function.into_taffy(context);
|
|
let max = self.tracks[0].max_sizing_function.into_taffy(context);
|
|
let taffy_track = taffy::style_helpers::minmax(min, max);
|
|
taffy::style::TrackSizingFunction::Single(taffy_track)
|
|
} else {
|
|
let taffy_tracks: Vec<_> = self
|
|
.tracks
|
|
.iter()
|
|
.map(|track| {
|
|
let min = track.min_sizing_function.into_taffy(context);
|
|
let max = track.max_sizing_function.into_taffy(context);
|
|
taffy::style_helpers::minmax(min, max)
|
|
})
|
|
.collect();
|
|
|
|
match self.repetition {
|
|
GridTrackRepetition::Count(count) => {
|
|
taffy::style_helpers::repeat(count, taffy_tracks)
|
|
}
|
|
GridTrackRepetition::AutoFit => taffy::style_helpers::repeat(
|
|
taffy::style::GridTrackRepetition::AutoFit,
|
|
taffy_tracks,
|
|
),
|
|
GridTrackRepetition::AutoFill => taffy::style_helpers::repeat(
|
|
taffy::style::GridTrackRepetition::AutoFill,
|
|
taffy_tracks,
|
|
),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_convert_from() {
|
|
use taffy::style_helpers as sh;
|
|
|
|
let bevy_style = crate::Style {
|
|
display: Display::Flex,
|
|
position_type: PositionType::Absolute,
|
|
left: Val::Px(0.),
|
|
right: Val::Percent(0.),
|
|
top: Val::Auto,
|
|
bottom: Val::Auto,
|
|
direction: crate::Direction::Inherit,
|
|
flex_direction: FlexDirection::ColumnReverse,
|
|
flex_wrap: FlexWrap::WrapReverse,
|
|
align_items: AlignItems::Baseline,
|
|
align_self: AlignSelf::Start,
|
|
align_content: AlignContent::SpaceAround,
|
|
justify_items: JustifyItems::Default,
|
|
justify_self: JustifySelf::Center,
|
|
justify_content: JustifyContent::SpaceEvenly,
|
|
margin: UiRect {
|
|
left: Val::Percent(0.),
|
|
right: Val::Px(0.),
|
|
top: Val::Auto,
|
|
bottom: Val::Auto,
|
|
},
|
|
padding: UiRect {
|
|
left: Val::Percent(0.),
|
|
right: Val::Px(0.),
|
|
top: Val::Percent(0.),
|
|
bottom: Val::Percent(0.),
|
|
},
|
|
border: UiRect {
|
|
left: Val::Px(0.),
|
|
right: Val::Px(0.),
|
|
top: Val::Auto,
|
|
bottom: Val::Px(0.),
|
|
},
|
|
flex_grow: 1.,
|
|
flex_shrink: 0.,
|
|
flex_basis: Val::Px(0.),
|
|
size: Size {
|
|
width: Val::Px(0.),
|
|
height: Val::Auto,
|
|
},
|
|
min_size: Size {
|
|
width: Val::Px(0.),
|
|
height: Val::Percent(0.),
|
|
},
|
|
max_size: Size {
|
|
width: Val::Auto,
|
|
height: Val::Px(0.),
|
|
},
|
|
aspect_ratio: None,
|
|
overflow: crate::Overflow::Hidden,
|
|
gap: Size {
|
|
width: Val::Px(0.),
|
|
height: Val::Percent(0.),
|
|
},
|
|
grid_auto_flow: GridAutoFlow::ColumnDense,
|
|
grid_template_rows: vec![
|
|
GridTrack::px(10.0),
|
|
GridTrack::percent(50.0),
|
|
GridTrack::fr(1.0),
|
|
],
|
|
grid_template_columns: RepeatedGridTrack::px(5, 10.0),
|
|
grid_auto_rows: vec![
|
|
GridTrack::fit_content_px(10.0),
|
|
GridTrack::fit_content_percent(25.0),
|
|
GridTrack::flex(2.0),
|
|
],
|
|
grid_auto_columns: vec![
|
|
GridTrack::auto(),
|
|
GridTrack::min_content(),
|
|
GridTrack::max_content(),
|
|
],
|
|
grid_column: GridPlacement::start(4),
|
|
grid_row: GridPlacement::span(3),
|
|
};
|
|
let viewport_values = LayoutContext::new(1.0, bevy_math::Vec2::new(800., 600.));
|
|
let taffy_style = from_style(&viewport_values, &bevy_style);
|
|
assert_eq!(taffy_style.display, taffy::style::Display::Flex);
|
|
assert_eq!(taffy_style.position, taffy::style::Position::Absolute);
|
|
assert!(matches!(
|
|
taffy_style.inset.left,
|
|
taffy::style::LengthPercentageAuto::Points(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.inset.right,
|
|
taffy::style::LengthPercentageAuto::Percent(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.inset.top,
|
|
taffy::style::LengthPercentageAuto::Auto
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.inset.bottom,
|
|
taffy::style::LengthPercentageAuto::Auto
|
|
));
|
|
assert_eq!(
|
|
taffy_style.flex_direction,
|
|
taffy::style::FlexDirection::ColumnReverse
|
|
);
|
|
assert_eq!(taffy_style.flex_wrap, taffy::style::FlexWrap::WrapReverse);
|
|
assert_eq!(
|
|
taffy_style.align_items,
|
|
Some(taffy::style::AlignItems::Baseline)
|
|
);
|
|
assert_eq!(taffy_style.align_self, Some(taffy::style::AlignSelf::Start));
|
|
assert_eq!(
|
|
taffy_style.align_content,
|
|
Some(taffy::style::AlignContent::SpaceAround)
|
|
);
|
|
assert_eq!(
|
|
taffy_style.justify_content,
|
|
Some(taffy::style::JustifyContent::SpaceEvenly)
|
|
);
|
|
assert_eq!(taffy_style.justify_items, None);
|
|
assert_eq!(
|
|
taffy_style.justify_self,
|
|
Some(taffy::style::JustifySelf::Center)
|
|
);
|
|
assert!(matches!(
|
|
taffy_style.margin.left,
|
|
taffy::style::LengthPercentageAuto::Percent(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.margin.right,
|
|
taffy::style::LengthPercentageAuto::Points(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.margin.top,
|
|
taffy::style::LengthPercentageAuto::Auto
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.margin.bottom,
|
|
taffy::style::LengthPercentageAuto::Auto
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.padding.left,
|
|
taffy::style::LengthPercentage::Percent(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.padding.right,
|
|
taffy::style::LengthPercentage::Points(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.padding.top,
|
|
taffy::style::LengthPercentage::Percent(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.padding.bottom,
|
|
taffy::style::LengthPercentage::Percent(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.border.left,
|
|
taffy::style::LengthPercentage::Points(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.border.right,
|
|
taffy::style::LengthPercentage::Points(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.border.top,
|
|
taffy::style::LengthPercentage::Points(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.border.bottom,
|
|
taffy::style::LengthPercentage::Points(_)
|
|
));
|
|
assert_eq!(taffy_style.flex_grow, 1.);
|
|
assert_eq!(taffy_style.flex_shrink, 0.);
|
|
assert!(matches!(
|
|
taffy_style.flex_basis,
|
|
taffy::style::Dimension::Points(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.size.width,
|
|
taffy::style::Dimension::Points(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.size.height,
|
|
taffy::style::Dimension::Auto
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.min_size.width,
|
|
taffy::style::Dimension::Points(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.min_size.height,
|
|
taffy::style::Dimension::Percent(_)
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.max_size.width,
|
|
taffy::style::Dimension::Auto
|
|
));
|
|
assert!(matches!(
|
|
taffy_style.max_size.height,
|
|
taffy::style::Dimension::Points(_)
|
|
));
|
|
assert_eq!(taffy_style.aspect_ratio, None);
|
|
assert_eq!(
|
|
taffy_style.gap.width,
|
|
taffy::style::LengthPercentage::Points(0.)
|
|
);
|
|
assert_eq!(
|
|
taffy_style.gap.height,
|
|
taffy::style::LengthPercentage::Percent(0.)
|
|
);
|
|
assert_eq!(
|
|
taffy_style.grid_auto_flow,
|
|
taffy::style::GridAutoFlow::ColumnDense
|
|
);
|
|
assert_eq!(
|
|
taffy_style.grid_template_rows,
|
|
vec![sh::points(10.0), sh::percent(0.5), sh::fr(1.0)]
|
|
);
|
|
assert_eq!(
|
|
taffy_style.grid_template_columns,
|
|
vec![sh::repeat(5, vec![sh::points(10.0)])]
|
|
);
|
|
assert_eq!(
|
|
taffy_style.grid_auto_rows,
|
|
vec![
|
|
sh::fit_content(taffy::style::LengthPercentage::Points(10.0)),
|
|
sh::fit_content(taffy::style::LengthPercentage::Percent(0.25)),
|
|
sh::minmax(sh::points(0.0), sh::fr(2.0)),
|
|
]
|
|
);
|
|
assert_eq!(
|
|
taffy_style.grid_auto_columns,
|
|
vec![sh::auto(), sh::min_content(), sh::max_content()]
|
|
);
|
|
assert_eq!(
|
|
taffy_style.grid_column,
|
|
taffy::geometry::Line {
|
|
start: sh::line(4),
|
|
end: sh::span(1)
|
|
}
|
|
);
|
|
assert_eq!(taffy_style.grid_row, sh::span(3));
|
|
}
|
|
|
|
#[test]
|
|
fn test_into_length_percentage() {
|
|
use taffy::style::LengthPercentage;
|
|
let context = LayoutContext::new(2.0, bevy_math::Vec2::new(800., 600.));
|
|
let cases = [
|
|
(Val::Auto, LengthPercentage::Points(0.)),
|
|
(Val::Percent(1.), LengthPercentage::Percent(0.01)),
|
|
(Val::Px(1.), LengthPercentage::Points(2.)),
|
|
(Val::Vw(1.), LengthPercentage::Points(8.)),
|
|
(Val::Vh(1.), LengthPercentage::Points(6.)),
|
|
(Val::VMin(2.), LengthPercentage::Points(12.)),
|
|
(Val::VMax(2.), LengthPercentage::Points(16.)),
|
|
];
|
|
for (val, length) in cases {
|
|
assert!(match (val.into_length_percentage(&context), length) {
|
|
(LengthPercentage::Points(a), LengthPercentage::Points(b))
|
|
| (LengthPercentage::Percent(a), LengthPercentage::Percent(b)) =>
|
|
(a - b).abs() < 0.0001,
|
|
_ => false,
|
|
},);
|
|
}
|
|
}
|
|
}
|