#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum Display {
Flex {
flex_direction: FlexDirection,
},
#[default]
Block,
Inline,
None,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum FlexDirection {
Row,
#[default]
Column,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Length {
Px(f32),
Percent(f32),
Vw(f32),
Vh(f32),
Auto,
Add(Box<Length>, Box<Length>),
Sub(Box<Length>, Box<Length>),
Mul(Box<Length>, f32),
Div(Box<Length>, f32),
Min(Box<Length>, Box<Length>),
Max(Box<Length>, Box<Length>),
Clamp {
min: Box<Length>,
val: Box<Length>,
max: Box<Length>,
},
}
impl Default for Length {
fn default() -> Self {
Length::Px(0.0)
}
}
impl Length {
pub fn resolve_with(
&self,
containing_block: Option<f32>,
viewport_width: f32,
viewport_height: f32,
) -> Option<f32> {
match self {
Length::Auto => None,
Length::Px(v) => Some(*v),
Length::Percent(p) => containing_block.map(|cb| cb * *p / 100.0),
Length::Vw(v) => Some(viewport_width * *v / 100.0),
Length::Vh(v) => Some(viewport_height * *v / 100.0),
Length::Add(a, b) => Some(
a.resolve_with(containing_block, viewport_width, viewport_height)?
+ b.resolve_with(containing_block, viewport_width, viewport_height)?,
),
Length::Sub(a, b) => Some(
a.resolve_with(containing_block, viewport_width, viewport_height)?
- b.resolve_with(containing_block, viewport_width, viewport_height)?,
),
Length::Mul(a, n) => {
Some(a.resolve_with(containing_block, viewport_width, viewport_height)? * n)
}
Length::Div(a, n) => {
if *n == 0.0 {
None
} else {
Some(a.resolve_with(containing_block, viewport_width, viewport_height)? / n)
}
}
Length::Min(a, b) => Some(
a.resolve_with(containing_block, viewport_width, viewport_height)?
.min(b.resolve_with(containing_block, viewport_width, viewport_height)?),
),
Length::Max(a, b) => Some(
a.resolve_with(containing_block, viewport_width, viewport_height)?
.max(b.resolve_with(containing_block, viewport_width, viewport_height)?),
),
Length::Clamp { min, val, max } => {
let v = val.resolve_with(containing_block, viewport_width, viewport_height)?;
let min_v = min.resolve_with(containing_block, viewport_width, viewport_height)?;
let max_v = max.resolve_with(containing_block, viewport_width, viewport_height)?;
Some(v.clamp(min_v, max_v))
}
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct ItemStyle {
pub flex_grow: f32,
pub flex_shrink: f32,
pub flex_basis: Length,
pub align_self: Option<AlignItems>,
}
impl Default for ItemStyle {
fn default() -> Self {
ItemStyle {
flex_grow: 0.0,
flex_shrink: 1.0,
flex_basis: Length::Auto,
align_self: None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SizeStyle {
pub width: Length,
pub height: Length,
pub min_width: Length,
pub max_width: Length,
pub min_height: Length,
pub max_height: Length,
}
impl Default for SizeStyle {
fn default() -> Self {
SizeStyle {
width: Length::Auto,
height: Length::Auto,
min_width: Length::Auto,
max_width: Length::Auto,
min_height: Length::Auto,
max_height: Length::Auto,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum BoxSizing {
#[default]
ContentBox,
BorderBox,
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Spacing {
pub margin_top: Length,
pub margin_bottom: Length,
pub margin_left: Length,
pub margin_right: Length,
pub border_top: Length,
pub border_bottom: Length,
pub border_left: Length,
pub border_right: Length,
pub padding_top: Length,
pub padding_bottom: Length,
pub padding_left: Length,
pub padding_right: Length,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum JustifyContent {
#[default]
Start,
Center,
End,
SpaceBetween,
SpaceAround,
SpaceEvenly,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum AlignItems {
Start,
Center,
End,
#[default]
Stretch,
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Style {
pub display: Display,
pub item_style: ItemStyle,
pub size: SizeStyle,
pub box_sizing: BoxSizing,
pub spacing: Spacing,
pub justify_content: JustifyContent,
pub align_items: AlignItems,
pub column_gap: Length,
pub row_gap: Length,
}
use std::ops::{Add, Sub};
impl Add for Length {
type Output = Length;
fn add(self, rhs: Length) -> Length {
Length::Add(Box::new(self), Box::new(rhs))
}
}
impl Sub for Length {
type Output = Length;
fn sub(self, rhs: Length) -> Length {
Length::Sub(Box::new(self), Box::new(rhs))
}
}