use indexmap::IndexSet;
use thunderdome::Index as NodeIndex;
use crate::{Alignment, NodeCache, Rect, UiNode, UiTree};
pub struct Overlap {
align: (Alignment, Alignment),
children: IndexSet<NodeIndex>,
}
impl Overlap {
pub fn new() -> Self {
Self {
align: (Alignment::Begin, Alignment::Begin),
children: IndexSet::new(),
}
}
pub fn with_child(mut self, index: NodeIndex) -> Self {
self.children.insert(index);
self
}
pub fn with_align(mut self, align: (Alignment, Alignment)) -> Self {
self.align = align;
self
}
pub fn add_child(&mut self, index: NodeIndex) {
self.children.insert(index);
}
pub fn len(&self) -> usize {
self.children.len()
}
pub fn is_empty(&self) -> bool {
self.children.is_empty()
}
pub fn remove_child(&mut self, index: usize, tree: &mut UiTree) -> bool {
let Some(ti) = self.children.shift_remove_index(index) else {
return false;
};
if tree.get_node(ti).is_none() {
return false;
}
tree.remove_node(ti);
true
}
pub fn set_child_position(&mut self, index: usize, position: usize) -> bool {
self.children.move_index(index, position);
true
}
pub fn get_child_index(&self, index: usize) -> Option<NodeIndex> {
self.children.get_index(index).copied()
}
}
impl Default for Overlap {
fn default() -> Self {
Self::new()
}
}
impl UiNode for Overlap {
fn get_align(&self) -> (Alignment, Alignment) {
self.align
}
fn get_align_mut(&mut self) -> (&mut Alignment, &mut Alignment) {
(&mut self.align.0, &mut self.align.1)
}
fn calculate_min_size(&self, tree: &UiTree) -> (f32, f32) {
if self.children.is_empty() {
return (0.0, 0.0);
}
let mut w = 0.0f32;
let mut h = 0.0f32;
for child in &self.children {
let child = tree.get_cache(*child).expect("Child not in cache");
let (cw, ch) = child.min_size;
w = w.max(cw);
h = h.max(ch);
}
(w, h)
}
fn calculate_rects(&self, cache: &NodeCache, tree: &UiTree) -> Vec<Rect> {
let mut child_rects = Vec::with_capacity(self.children.len());
for child in &self.children {
let child_min = tree.get_cache(*child).expect("Child not in cache").min_size;
let child = tree.get_node(*child).expect("Child not in arena");
let space = cache.rect.align(child.get_align(), child_min);
child_rects.push(space);
}
child_rects
}
}