use float_pigment_css::length_num::LengthNum;
use float_pigment_css::typing::{
AlignContent, AlignItems, AlignSelf, JustifyContent, JustifyItems, JustifySelf,
};
use crate::{LayoutStyle, LayoutTreeNode};
pub(crate) fn resolve_grid_align_self<T: LayoutTreeNode>(
child_style: &T::Style,
parent_style: &T::Style,
) -> AlignSelf {
let align_self = child_style.align_self();
if align_self == AlignSelf::Auto {
match parent_style.align_items() {
AlignItems::Stretch => AlignSelf::Stretch,
AlignItems::Center => AlignSelf::Center,
AlignItems::Start | AlignItems::FlexStart | AlignItems::SelfStart => AlignSelf::Start,
AlignItems::End | AlignItems::FlexEnd | AlignItems::SelfEnd => AlignSelf::End,
AlignItems::Baseline => AlignSelf::Baseline,
AlignItems::Normal => AlignSelf::Stretch,
}
} else {
align_self
}
}
pub(crate) fn resolve_grid_justify_self<T: LayoutTreeNode>(
child_style: &T::Style,
parent_style: &T::Style,
) -> JustifySelf {
let justify_self = child_style.justify_self();
if justify_self == JustifySelf::Auto {
match parent_style.justify_items() {
JustifyItems::Stretch => JustifySelf::Stretch,
JustifyItems::Center => JustifySelf::Center,
JustifyItems::Start | JustifyItems::FlexStart | JustifyItems::SelfStart => {
JustifySelf::Start
}
JustifyItems::End | JustifyItems::FlexEnd | JustifyItems::SelfEnd => JustifySelf::End,
JustifyItems::Left => JustifySelf::Left,
JustifyItems::Right => JustifySelf::Right,
JustifyItems::Normal => JustifySelf::Stretch,
}
} else {
justify_self
}
}
pub(crate) fn calculate_alignment_offset<L: LengthNum>(
align_self: AlignSelf,
item_size: L,
cell_size: L,
) -> L {
if cell_size <= item_size {
return L::zero();
}
let available_space = cell_size - item_size;
match align_self {
AlignSelf::Start | AlignSelf::FlexStart | AlignSelf::SelfStart => L::zero(),
AlignSelf::End | AlignSelf::FlexEnd | AlignSelf::SelfEnd => available_space,
AlignSelf::Center => available_space.div_f32(2.0),
AlignSelf::Stretch | AlignSelf::Auto | AlignSelf::Normal | AlignSelf::Baseline => L::zero(),
}
}
pub(crate) fn calculate_justify_offset<L: LengthNum>(
justify_self: JustifySelf,
item_size: L,
cell_size: L,
) -> L {
if cell_size <= item_size {
return L::zero();
}
let available_space = cell_size - item_size;
match justify_self {
JustifySelf::Start
| JustifySelf::FlexStart
| JustifySelf::SelfStart
| JustifySelf::Left => L::zero(),
JustifySelf::End | JustifySelf::FlexEnd | JustifySelf::SelfEnd | JustifySelf::Right => {
available_space
}
JustifySelf::Center => available_space.div_f32(2.0),
JustifySelf::Stretch | JustifySelf::Auto | JustifySelf::Normal => L::zero(),
}
}
pub(crate) fn calculate_justify_offset_rtl<L: LengthNum>(
justify_self: JustifySelf,
item_size: L,
cell_size: L,
) -> L {
if cell_size <= item_size {
return L::zero();
}
let available_space = cell_size - item_size;
match justify_self {
JustifySelf::Start | JustifySelf::FlexStart | JustifySelf::SelfStart => available_space,
JustifySelf::End | JustifySelf::FlexEnd | JustifySelf::SelfEnd => L::zero(),
JustifySelf::Left => L::zero(),
JustifySelf::Right => available_space,
JustifySelf::Center => available_space.div_f32(2.0),
JustifySelf::Stretch | JustifySelf::Auto | JustifySelf::Normal => L::zero(),
}
}
pub(crate) fn calculate_align_content_offset<L: LengthNum>(
align_content: AlignContent,
total_track_size: L,
container_size: L,
track_count: usize,
) -> (L, L) {
if container_size <= total_track_size || track_count == 0 {
return (L::zero(), L::zero());
}
let available_space = container_size - total_track_size;
match align_content {
AlignContent::Start | AlignContent::FlexStart => (L::zero(), L::zero()),
AlignContent::End | AlignContent::FlexEnd => (available_space, L::zero()),
AlignContent::Center => (available_space.div_f32(2.0), L::zero()),
AlignContent::SpaceBetween => {
if track_count <= 1 {
(L::zero(), L::zero())
} else {
let gap = available_space.div_f32((track_count - 1) as f32);
(L::zero(), gap)
}
}
AlignContent::SpaceAround => {
let gap = available_space.div_f32(track_count as f32);
(gap.div_f32(2.0), gap)
}
AlignContent::SpaceEvenly => {
let gap = available_space.div_f32((track_count + 1) as f32);
(gap, gap)
}
AlignContent::Stretch | AlignContent::Normal | AlignContent::Baseline => {
(L::zero(), L::zero())
}
}
}
pub(crate) fn calculate_justify_content_offset<L: LengthNum>(
justify_content: JustifyContent,
total_track_size: L,
container_size: L,
track_count: usize,
) -> (L, L) {
if container_size <= total_track_size || track_count == 0 {
return (L::zero(), L::zero());
}
let available_space = container_size - total_track_size;
match justify_content {
JustifyContent::Start | JustifyContent::FlexStart | JustifyContent::Left => {
(L::zero(), L::zero())
}
JustifyContent::End | JustifyContent::FlexEnd | JustifyContent::Right => {
(available_space, L::zero())
}
JustifyContent::Center => (available_space.div_f32(2.0), L::zero()),
JustifyContent::SpaceBetween => {
if track_count <= 1 {
(L::zero(), L::zero())
} else {
let gap = available_space.div_f32((track_count - 1) as f32);
(L::zero(), gap)
}
}
JustifyContent::SpaceAround => {
let gap = available_space.div_f32(track_count as f32);
(gap.div_f32(2.0), gap)
}
JustifyContent::SpaceEvenly => {
let gap = available_space.div_f32((track_count + 1) as f32);
(gap, gap)
}
JustifyContent::Stretch | JustifyContent::Baseline | JustifyContent::Normal => {
(L::zero(), L::zero())
}
}
}