use thunderdome::Index as TdIndex;
use crate::{Alignment, NodeCache, Rect, UiNode, UiTree};
pub struct Clip {
pub offset: (f32, f32),
align: (Alignment, Alignment),
child: Option<TdIndex>,
}
impl Clip {
pub fn new() -> Self {
Self {
offset: (0.0, 0.0),
align: (Alignment::Begin, Alignment::Begin),
child: None,
}
}
pub fn with_child(mut self, child: impl UiNode, tree: &mut UiTree) -> Self {
assert!(self.child.is_none());
self.child = Some(tree.add_node(child));
self
}
pub fn with_align(mut self, align: (Alignment, Alignment)) -> Self {
self.align = align;
self
}
pub fn with_offset(mut self, offset: (f32, f32)) -> Self {
assert!(offset.0 >= 0.0 && offset.1 >= 0.0);
self.offset = offset;
self
}
pub fn set_offset(&mut self, offset: (f32, f32)) {
assert!(offset.0 >= 0.0 && offset.1 >= 0.0);
self.offset = offset;
}
pub fn get_child(&self) -> Option<TdIndex> {
self.child
}
}
impl Default for Clip {
fn default() -> Self {
Self::new()
}
}
impl UiNode for Clip {
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) {
(0.0, 0.0)
}
fn calculate_rects(&self, cache: &NodeCache, tree: &UiTree) -> Vec<Rect> {
if let Some(child) = self.child {
let child_min = tree.get_cache(child).expect("Child not in cache").min_size;
let child = tree.get_node(child).expect("Child not in cache");
let (cax, cay) = child.get_align();
let (x, width) = match cax {
_ if child_min.0 > cache.rect.w => (cache.rect.x + self.offset.0, child_min.0),
Alignment::Begin => (cache.rect.x, child_min.0),
Alignment::Center => (
cache.rect.x + (cache.rect.w - child_min.0) * 0.5,
child_min.0,
),
Alignment::End => (cache.rect.x + cache.rect.w - child_min.0, child_min.0),
Alignment::Full => (cache.rect.x, cache.rect.w),
};
let (y, height) = match cay {
_ if child_min.1 > cache.rect.h => (cache.rect.y + self.offset.1, child_min.1),
Alignment::Begin => (cache.rect.y, child_min.1),
Alignment::Center => (
cache.rect.y + (cache.rect.h - child_min.1) * 0.5,
child_min.1,
),
Alignment::End => (cache.rect.y + cache.rect.h - child_min.1, child_min.1),
Alignment::Full => (cache.rect.y, cache.rect.h),
};
vec![Rect::new(x, y, width, height)]
} else {
vec![]
}
}
fn get_children(&self) -> Vec<TdIndex> {
self.child.into_iter().collect()
}
}