use thunderdome::Index as TdIndex;
use crate::{Alignment, NodeCache, Rect, UiNode, UiTree};
pub struct Margin {
pub left: f32,
pub right: f32,
pub top: f32,
pub bottom: f32,
align: (Alignment, Alignment),
child: Option<TdIndex>,
}
impl Margin {
pub fn new() -> Self {
Self {
left: 0.0,
right: 0.0,
top: 0.0,
bottom: 0.0,
align: (Alignment::Begin, Alignment::Begin),
child: None,
}
}
pub fn with_child(mut self, child: impl UiNode, tree: &mut UiTree) -> Self {
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_margins(mut self, left: f32, right: f32, top: f32, bottom: f32) -> Self {
self.left = left;
self.right = right;
self.top = top;
self.bottom = bottom;
self
}
pub fn with_left(mut self, left: f32) -> Self {
self.left = left;
self
}
pub fn with_right(mut self, right: f32) -> Self {
self.right = right;
self
}
pub fn with_top(mut self, top: f32) -> Self {
self.top = top;
self
}
pub fn with_bottom(mut self, bottom: f32) -> Self {
self.bottom = bottom;
self
}
}
impl Default for Margin {
fn default() -> Self {
Self::new()
}
}
impl UiNode for Margin {
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 let Some(child) = self.child {
let child = tree.get_cache(child).expect("Child not in cache");
let (w, h) = child.min_size;
(w + self.left + self.right, h + self.top + self.bottom)
} else {
(self.left + self.right, self.top + self.bottom)
}
}
fn calculate_rects(&self, cache: &NodeCache, tree: &UiTree) -> Vec<Rect> {
let Some(child_idx) = self.child else { return vec![]; };
let child_min = tree.get_cache(child_idx).expect("Child not in cache").min_size;
let child = tree.get_node(child_idx).expect("Child not in cache");
let space = Rect::new(
cache.rect.x + self.left,
cache.rect.y + self.top,
cache.rect.width - self.left - self.right,
cache.rect.height - self.top - self.bottom,
)
.align(child.get_align(), child_min);
vec![space]
}
fn get_children(&self) -> Vec<TdIndex> {
self.child.into_iter().collect()
}
}
pub struct Minimum {
pub min_override: (f32, f32),
child: Option<TdIndex>,
align: (Alignment, Alignment),
}
impl Minimum {
pub fn new() -> Self {
Self {
min_override: (0.0, 0.0),
child: None,
align: (Alignment::Begin, Alignment::Begin),
}
}
pub fn with_child(mut self, child: impl UiNode, tree: &mut UiTree) -> Self {
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_min(mut self, min: (f32, f32)) -> Self {
self.min_override = min;
self
}
}
impl Default for Minimum {
fn default() -> Self {
Self::new()
}
}
impl UiNode for Minimum {
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 let Some(child) = self.child {
let child = tree.get_cache(child).expect("Child not in cache");
let (w, h) = child.min_size;
(w.max(self.min_override.0), h.max(self.min_override.1))
} else {
self.min_override
}
}
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 space = cache.rect.align(child.get_align(), child_min);
vec![space]
} else {
vec![]
}
}
fn get_children(&self) -> Vec<TdIndex> {
self.child.into_iter().collect()
}
}