use indexmap::IndexSet;
use thunderdome::Index as TdIndex;
use crate::{Alignment, NodeCache, Rect, UiNode, UiTree};
pub struct Hider {
pub hidden: bool,
align: (Alignment, Alignment),
child: Option<TdIndex>,
}
impl Hider {
pub fn new() -> Self {
Self {
hidden: false,
align: (Alignment::Begin, Alignment::Begin),
child: None,
}
}
pub fn with_align(mut self, align: (Alignment, Alignment)) -> Self {
self.align = align;
self
}
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_hidden(mut self, hidden: bool) -> Self {
self.hidden = hidden;
self
}
}
impl Default for Hider {
fn default() -> Self {
Self::new()
}
}
impl UiNode for Hider {
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.hidden
&& let Some(child) = self.child
{
tree.get_cache(child).expect("Child not in cache").min_size
} else {
(0.0, 0.0)
}
}
fn calculate_rects(&self, cache: &NodeCache, tree: &UiTree) -> Vec<Rect> {
if !self.hidden
&& 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()
}
fn get_visible_children(&self) -> Vec<TdIndex> {
if !self.hidden
&& let Some(child) = self.child
{
vec![child]
} else {
vec![]
}
}
}
pub struct Selector {
selected: Option<TdIndex>,
align: (Alignment, Alignment),
children: IndexSet<TdIndex>,
}
impl Selector {
pub fn new() -> Self {
Self {
selected: None,
align: (Alignment::Begin, Alignment::Begin),
children: IndexSet::new(),
}
}
pub fn with_child(mut self, child: impl UiNode, tree: &mut UiTree) -> Self {
let index = tree.add_node(child);
if self.selected.is_none() {
self.selected = Some(index);
}
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, child: impl UiNode, tree: &mut UiTree) {
let index = tree.add_node(child);
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 let Some(selected) = self.selected
&& ti == selected
{
self.selected = None;
}
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<TdIndex> {
self.children.get_index(index).copied()
}
pub fn get_selected(&self) -> Option<TdIndex> {
self.selected
}
pub fn get_selected_index(&self) -> Option<usize> {
self.children.get_index_of(&self.selected?)
}
pub fn set_selected(&mut self, child: TdIndex) {
self.selected = Some(child)
}
pub fn set_selected_index(&mut self, index: usize) {
self.selected = self.children.get_index(index).copied()
}
pub fn unselect(&mut self) {
self.selected = None;
}
}
impl Default for Selector {
fn default() -> Self {
Self::new()
}
}
impl UiNode for Selector {
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(index) = self.selected {
tree.get_cache(index).expect("Child not in cache").min_size
} else {
(0.0, 0.0)
}
}
fn calculate_rects(&self, cache: &NodeCache, tree: &UiTree) -> Vec<Rect> {
if let Some(index) = self.selected {
let child_min = tree.get_cache(index).expect("Child not in cache").min_size;
let child = tree.get_node(index).expect("Child not in cache");
vec![cache.rect.align(child.get_align(), child_min)]
} else {
vec![]
}
}
fn get_children(&self) -> Vec<TdIndex> {
self.children.iter().copied().collect()
}
fn get_visible_children(&self) -> Vec<TdIndex> {
self.selected.iter().copied().collect()
}
}