use crate::layout_algorithm::axis_utils::Axis;
use crate::layout_struct::layout_states::LayoutElement;
use crate::layout_struct::layout_tree::{LayoutTreeCursor, LayoutTreeNodeLocalMut};
pub(crate) fn child_axis_size_for_aggregate(child: &LayoutElement, axis: Axis) -> f32 {
if let Some(v) = child.info.temp_axis(axis) {
return v;
}
if let Some(v) = child.info.get_final_axis(axis) {
return v;
}
panic!("tried to get_child_axis_total but child was not initialized");
}
pub(crate) fn get_children_axis_total<'a>(
children: impl Iterator<Item = &'a LayoutElement>,
axis: Axis,
child_gap: f32,
) -> f32 {
let mut res = 0.0;
let mut in_flow_count = 0usize;
for child in children {
if child.config.floating.config.is_some() {
continue;
}
in_flow_count += 1;
res += child_axis_size_for_aggregate(child, axis);
}
if in_flow_count > 1 {
res += child_gap * (in_flow_count - 1) as f32;
}
res
}
pub(crate) fn get_child_axis_max<'a>(
children: impl Iterator<Item = &'a LayoutElement>,
axis: Axis,
) -> f32 {
let mut res: f32 = 0.0;
for child in children {
if child.config.floating.config.is_some() {
continue;
}
res = res.max(child_axis_size_for_aggregate(child, axis));
}
res
}
impl LayoutTreeNodeLocalMut<'_> {
pub(crate) fn free_space_axis(&self, axis: Axis) -> f32 {
let element: &LayoutElement = self.self_element;
let children = self.children_elements.iter().map(|c| &**c);
let axis_size = element
.info
.get_final_axis(axis)
.expect("Expected element to have finalized axis for free space calculation");
let mut res = axis_size;
res -= element.internal_space_axis(axis);
if element.config.layout.layout_direction == axis.get_direction() {
res -= get_children_axis_total(children, axis, element.config.layout.child_gap);
} else if element.config.clip.horizontal {
res = res.max(get_child_axis_max(children, axis))
}
if element.config.clip.horizontal {
res = res.max(0.0);
}
res
}
fn grow_children_axis(&mut self, axis: Axis) {
if self.self_element.config.layout.layout_direction == axis.get_direction() {
loop {
let free_space = self.free_space_axis(axis);
let mut growing_children: Vec<_> = Vec::new();
for child in self.children_elements.iter_mut() {
if child.wants_to_grow_axis(axis) {
growing_children.push(child);
}
}
if free_space <= 0.0 || growing_children.is_empty() {
break;
}
let grow_size_per_child = free_space / growing_children.len() as f32;
for child in growing_children.iter_mut() {
child.grow_axis_at_most(grow_size_per_child, axis);
}
}
} else {
let free_space = self.free_space_axis(axis);
for child in self.children_elements.iter_mut() {
if child.wants_to_grow_axis(axis) {
child.grow_axis_to(free_space, axis);
}
}
}
}
fn shrink_children_axis(&mut self, axis: Axis) {
if self.self_element.config.layout.layout_direction == axis.get_direction() {
loop {
let free_space = self.free_space_axis(axis);
let mut shrinking_children: Vec<_> = Vec::new();
for child in self.children_elements.iter_mut() {
if child.can_shrink_axis(axis) {
shrinking_children.push(child);
}
}
if free_space >= 0.0 || shrinking_children.is_empty() {
break;
}
let shrink_size_per_child = -free_space / shrinking_children.len() as f32;
for child in shrinking_children.iter_mut() {
child.shrink_axis_at_most(shrink_size_per_child, axis);
}
}
} else {
let free_space = self.free_space_axis(axis);
for child in self.children_elements.iter_mut() {
if child.can_shrink_axis(axis) {
child.shrink_axis_to(free_space, axis);
}
}
}
}
}
pub(crate) fn fit_grow_shrink_children_axis(local: &mut LayoutTreeCursor, axis: Axis) {
{
let mut local = local.get_local_mut();
if local.self_element.config.layout.layout_direction == axis.get_direction() {
let axis_size = local
.self_element
.info
.get_final_axis(axis)
.expect("tried to fit_grow_shrink_children_axis before finalized parent axis");
for child in local.children_elements.iter_mut() {
child.set_percent_sizing_for_axis(axis_size, axis);
child.set_floating_for_axis(axis_size, axis_size, axis);
}
let free = local.free_space_axis(axis);
if free > 0.0 {
local.grow_children_axis(axis);
} else if free < 0.0 && !local.self_element.config.clip.horizontal {
local.shrink_children_axis(axis);
}
for child in local.children_elements.iter_mut() {
child.upgrade_axis(axis);
}
} else {
let axis_size = local
.self_element
.info
.get_final_axis(axis)
.expect("tried to fit_grow_shrink_children_axis before finalized parent axis");
for child in local.children_elements.iter_mut() {
child.set_percent_sizing_for_axis(axis_size, axis);
child.set_floating_for_axis(axis_size, axis_size, axis);
}
local.grow_children_axis(axis);
local.shrink_children_axis(axis);
for child in local.children_elements.iter_mut() {
child.upgrade_axis(axis);
}
}
}
for child in local.get_all_child_ids() {
fit_grow_shrink_children_axis(&mut local.get_child_cursor(child).unwrap(), axis)
}
}