use crate::layout_struct::layout_states::{LayoutElement, LayoutElementInfo, element_info_states};
use cotis_defaults::element_configs::style::sizing::{AxisSizing, DoubleAxisSizing, Sizing};
use cotis_defaults::element_configs::style::types::LayoutDirection;
#[derive(Debug, Clone, PartialEq, Copy)]
pub(crate) enum Axis {
Width,
Height,
}
impl Axis {
pub fn get_direction(&self) -> LayoutDirection {
match self {
Axis::Width => LayoutDirection::LeftToRight,
Axis::Height => LayoutDirection::TopToBottom,
}
}
pub(crate) fn axis_sizing(self, sizing: &DoubleAxisSizing) -> AxisSizing {
match self {
Axis::Width => sizing.width,
Axis::Height => sizing.height,
}
}
}
impl LayoutElementInfo {
pub(crate) fn temp_axis(&self, axis: Axis) -> Option<f32> {
match axis {
Axis::Width => self.temp_width(),
Axis::Height => self.temp_height(),
}
}
pub(crate) fn min_axis(&self, axis: Axis) -> Option<f32> {
match axis {
Axis::Width => self.min_width(),
Axis::Height => self.min_height(),
}
}
pub(crate) fn get_final_axis(&self, axis: Axis) -> Option<f32> {
match axis {
Axis::Width => self.get_final_width(),
Axis::Height => self.get_final_height(),
}
}
}
impl LayoutElement {
pub(crate) fn internal_space_axis(&self, axis: Axis) -> f32 {
match axis {
Axis::Width => self.internal_space_width(),
Axis::Height => self.internal_space_height(),
}
}
pub(crate) fn wants_to_grow_axis(&self, axis: Axis) -> bool {
if self.config.floating.config.is_some() {
return false;
}
match self.config.layout.sizing {
Sizing::DoubleAxis(ref sizing) => match axis.axis_sizing(sizing) {
AxisSizing::Grow(_, max) => self.info.temp_axis(axis).unwrap_or(max) < max,
_ => false,
},
}
}
pub(crate) fn can_shrink_axis(&self, axis: Axis) -> bool {
if self.config.floating.config.is_some() {
return false;
}
match self.config.layout.sizing {
Sizing::DoubleAxis(ref sizing) => {
if matches!(axis.axis_sizing(sizing), AxisSizing::Percent(_)) {
return false;
}
}
}
match (self.info.temp_axis(axis), self.info.min_axis(axis)) {
(Some(temp), Some(min)) => temp > min,
_ => false,
}
}
fn is_percent_sizing_for_axis(&self, axis: Axis) -> Option<f32> {
match self.config.layout.sizing {
Sizing::DoubleAxis(ref axis_sizing) => match axis.axis_sizing(axis_sizing) {
AxisSizing::Percent(p) => Some(p),
_ => None,
},
}
}
fn resolve_floating_axis_size(&self, total_outer: f32, total_inner: f32, axis: Axis) -> f32 {
let ex = self.config.floating.config.unwrap().expand;
if ex.width != 0. && ex.height == 0. {
match axis {
Axis::Width => ex.width,
Axis::Height => ex.height,
}
} else {
let Sizing::DoubleAxis(ref sizing) = self.config.layout.sizing;
let temp = self.info.temp_axis(axis).unwrap_or(0.);
match axis.axis_sizing(sizing) {
AxisSizing::Fit(_, max) => temp.min(max),
AxisSizing::Grow(_, max) => temp.max(total_inner).min(max),
AxisSizing::Fixed(fix) => fix,
AxisSizing::Percent(per) => total_outer * per,
AxisSizing::InnerPercent(per) => total_inner * per,
}
}
}
pub(crate) fn set_floating_for_axis(&mut self, total_outer: f32, total_inner: f32, axis: Axis) {
if self.config.floating.config.is_none() {
return;
}
let dim = self.resolve_floating_axis_size(total_outer, total_inner, axis);
match axis {
Axis::Width => match &mut self.info {
LayoutElementInfo::SelfMinSize(old) => {
self.info = LayoutElementInfo::TotalSizeWidthMinHeight(
element_info_states::TotalSizeWidthMinHeight {
width: dim,
min_height: old.min_size_height,
preferred_size_height: old.preferred_size_height,
},
)
}
LayoutElementInfo::TotalMinSize(old) => {
self.info = LayoutElementInfo::TotalSizeWidthMinHeight(
element_info_states::TotalSizeWidthMinHeight {
width: dim,
min_height: old.min_size_height,
preferred_size_height: old.preferred_size_height,
},
)
}
_ => panic!("Tried to set percent width to final width"),
},
Axis::Height => match &mut self.info {
LayoutElementInfo::TotalSizeWidthMinHeight(old) => {
self.info = LayoutElementInfo::TotalSize(element_info_states::TotalSize {
width: old.width,
height: dim,
})
}
LayoutElementInfo::TextWrappedMinHeight(old) => {
self.info = LayoutElementInfo::TotalSize(element_info_states::TotalSize {
width: old.width,
height: dim,
})
}
_ => panic!("Tried to set percent width to final height or none final width"),
},
}
}
pub(crate) fn set_percent_sizing_for_axis(&mut self, total: f32, axis: Axis) {
let Some(percent) = self.is_percent_sizing_for_axis(axis) else {
return;
};
let dim = percent * total;
match axis {
Axis::Width => match &mut self.info {
LayoutElementInfo::SelfMinSize(old) => {
self.info = LayoutElementInfo::TotalSizeWidthMinHeight(
element_info_states::TotalSizeWidthMinHeight {
width: dim,
min_height: old.min_size_height,
preferred_size_height: old.preferred_size_height,
},
)
}
LayoutElementInfo::TotalMinSize(old) => {
self.info = LayoutElementInfo::TotalSizeWidthMinHeight(
element_info_states::TotalSizeWidthMinHeight {
width: dim,
min_height: old.min_size_height,
preferred_size_height: old.preferred_size_height,
},
)
}
_ => panic!("Tried to set percent width to final width"),
},
Axis::Height => match &mut self.info {
LayoutElementInfo::TotalSizeWidthMinHeight(old) => {
self.info = LayoutElementInfo::TotalSize(element_info_states::TotalSize {
width: old.width,
height: dim,
})
}
LayoutElementInfo::TextWrappedMinHeight(old) => {
self.info = LayoutElementInfo::TotalSize(element_info_states::TotalSize {
width: old.width,
height: dim,
})
}
_ => panic!("Tried to set percent width to final height or none final width"),
},
}
}
pub(crate) fn grow_axis_at_most(&mut self, size: f32, axis: Axis) {
let Sizing::DoubleAxis(ref sizing) = self.config.layout.sizing;
if let AxisSizing::Grow(_, max) = axis.axis_sizing(sizing) {
let cur = self.info.temp_axis(axis).unwrap_or(0.);
let next = (cur + size).min(max);
match axis {
Axis::Width => self.info.set_tmp_width(next),
Axis::Height => self.info.set_tmp_height(next),
}
}
}
pub(crate) fn grow_axis_to(&mut self, size: f32, axis: Axis) {
let Sizing::DoubleAxis(ref sizing) = self.config.layout.sizing;
if let AxisSizing::Grow(_, max) = axis.axis_sizing(sizing) {
let next = size.min(max);
match axis {
Axis::Width => self.info.set_tmp_width(next),
Axis::Height => self.info.set_tmp_height(next),
}
}
}
pub(crate) fn shrink_axis_at_most(&mut self, size: f32, axis: Axis) {
match axis {
Axis::Width => self
.info
.set_tmp_width(self.info.temp_width().unwrap_or(0.) - size),
Axis::Height => self
.info
.set_tmp_height(self.info.temp_height().unwrap_or(0.) - size),
}
}
pub(crate) fn shrink_axis_to(&mut self, size: f32, axis: Axis) {
let Sizing::DoubleAxis(ref sizing) = self.config.layout.sizing;
if let AxisSizing::Grow(min, max) = axis.axis_sizing(sizing) {
let next = size.max(min).min(max);
match axis {
Axis::Width => self.info.set_tmp_width(next),
Axis::Height => self.info.set_tmp_height(next),
}
}
if let AxisSizing::Fit(min, max) = axis.axis_sizing(sizing) {
let next = size.max(min).min(max);
match axis {
Axis::Width => self.info.set_tmp_width(next),
Axis::Height => self.info.set_tmp_height(next),
}
}
}
pub(crate) fn upgrade_axis(&mut self, axis: Axis) {
match axis {
Axis::Width => self.info.upgrade_width(),
Axis::Height => self.info.upgrade_height(),
}
}
}