use std::{mem::replace, str::FromStr};
#[cfg(feature = "reflect")]
use bevy::prelude::Reflect;
use crate::Oriented;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
#[cfg_attr(feature = "reflect", derive(Reflect))]
pub enum Alignment {
#[default]
Start,
Center,
End,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
#[cfg_attr(feature = "reflect", derive(Reflect))]
#[doc(alias = "justification")]
pub enum Distribution {
#[default]
Start,
FillMain,
End,
OverlapStart,
OverlapCenter,
OverlapEnd,
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub(crate) struct CrossAlign {
cross_parent_size: f32,
align: Alignment,
}
impl Alignment {
pub(crate) const fn compute(self, parent_size: Oriented<f32>) -> CrossAlign {
CrossAlign { cross_parent_size: parent_size.cross, align: self }
}
}
impl CrossAlign {
pub fn offset(self, cross_child_size: f32) -> f32 {
match self.align {
Alignment::Start => 0.0,
Alignment::Center => (self.cross_parent_size - cross_child_size) / 2.0,
Alignment::End => self.cross_parent_size - cross_child_size,
}
}
}
#[derive(Clone, PartialEq, Debug)]
pub(crate) struct MainAlign {
offset: f32,
gap: f32,
distrib: Distribution,
}
impl Distribution {
#[must_use]
pub const fn overlaps(self) -> bool {
use Distribution::{OverlapCenter, OverlapEnd, OverlapStart};
matches!(self, OverlapStart | OverlapCenter | OverlapEnd)
}
pub(crate) fn compute(
self,
main_size: f32,
child_main_size: f32,
single_child: bool,
count: f32,
) -> MainAlign {
let (offset, gap) = match self {
Self::FillMain if single_child => ((main_size - child_main_size) / 2., 0.),
Self::OverlapCenter => (0., main_size / 2.),
Self::FillMain => (0., (main_size - child_main_size) / count),
Self::Start | Self::OverlapStart => (0., 0.),
Self::End => (main_size - child_main_size, 0.),
Self::OverlapEnd => (0., main_size),
};
MainAlign { offset, gap, distrib: self }
}
}
impl MainAlign {
pub fn offset(&mut self, child_size: f32) -> f32 {
use Distribution::{End, FillMain, Start};
match self.distrib {
Start | FillMain | End => {
let new_offset = self.offset + child_size + self.gap;
replace(&mut self.offset, new_offset)
}
Distribution::OverlapStart => 0.,
Distribution::OverlapCenter => self.gap - child_size / 2.,
Distribution::OverlapEnd => self.gap - child_size,
}
}
}
impl FromStr for Distribution {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"dS" => Ok(Self::Start),
"dE" => Ok(Self::End),
"dC" => Ok(Self::FillMain),
"oS" => Ok(Self::OverlapStart),
"oE" => Ok(Self::OverlapEnd),
"oC" => Ok(Self::OverlapCenter),
_ => Err(()),
}
}
}
impl FromStr for Alignment {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"aS" => Ok(Self::Start),
"aE" => Ok(Self::End),
"aC" => Ok(Self::Center),
_ => Err(()),
}
}
}