use crate::{ControlObject, ObservableCollection, ObservableComposite, Subscription, VecDiff};
use std::rc::Rc;
pub enum Children {
None,
SingleStatic(Rc<dyn ControlObject>),
MultipleStatic(Vec<Rc<dyn ControlObject>>),
SingleDynamic(Box<dyn ObservableCollection<Rc<dyn ControlObject>>>),
}
impl Children {
pub fn empty() -> Self {
Children::None
}
pub fn from(children_vec: Vec<Children>) -> Self {
let mut sources_to_compose: Vec<
Box<dyn ObservableCollection<Rc<dyn ControlObject>>>,
> = Vec::new();
let mut static_children: Vec<Rc<dyn ControlObject>> = Vec::new();
for next in children_vec {
match next {
Children::None => (),
Children::SingleStatic(item) => {
static_children.push(item);
}
Children::MultipleStatic(mut items) => {
static_children.append(&mut items);
}
Children::SingleDynamic(items) => {
if static_children.len() > 0 {
sources_to_compose.push(Box::new(static_children));
static_children = Vec::new();
}
sources_to_compose.push(items);
}
}
}
if sources_to_compose.len() > 0 && static_children.len() > 0 {
sources_to_compose.push(Box::new(static_children));
static_children = Vec::new();
}
if static_children.len() == 1 {
Children::SingleStatic(static_children.into_iter().next().unwrap())
} else if static_children.len() > 1 {
Children::MultipleStatic(static_children)
} else if sources_to_compose.len() == 1 {
Children::SingleDynamic(sources_to_compose.into_iter().next().unwrap())
} else if sources_to_compose.len() > 1 {
Children::SingleDynamic(Box::new(ObservableComposite::from(sources_to_compose)))
} else {
Children::None
}
}
pub fn len(&self) -> usize {
match self {
Children::None => 0,
Children::SingleStatic(_) => 1,
Children::MultipleStatic(x) => x.len(),
Children::SingleDynamic(x) => x.len(),
}
}
pub fn get(&self, index: usize) -> Option<Rc<dyn ControlObject>> {
match self {
Children::None => None,
Children::SingleStatic(x) => {
if index == 0 {
Some(x.clone())
} else {
None
}
}
Children::MultipleStatic(x) => x.get(index),
Children::SingleDynamic(x) => x.get(index),
}
}
}
impl From<Rc<dyn ControlObject>> for Children {
fn from(item: Rc<dyn ControlObject>) -> Children {
Children::SingleStatic(item)
}
}
impl<T: ControlObject + 'static> From<Rc<T>> for Children {
fn from(item: Rc<T>) -> Children {
Children::SingleStatic(item as Rc<dyn ControlObject>)
}
}
impl From<Vec<Rc<dyn ControlObject>>> for Children {
fn from(items: Vec<Rc<dyn ControlObject>>) -> Children {
Children::MultipleStatic(items)
}
}
impl<T: 'static + ControlObject> From<Vec<Rc<T>>> for Children {
fn from(items: Vec<Rc<T>>) -> Children {
Children::MultipleStatic(
items
.into_iter()
.map(|item| item as Rc<dyn ControlObject>)
.collect(),
)
}
}
impl<T: Into<Box<dyn ObservableCollection<Rc<dyn ControlObject>>>>> From<T> for Children {
fn from(items: T) -> Children {
Children::SingleDynamic(items.into())
}
}
impl ObservableCollection<Rc<dyn ControlObject>> for Children {
fn len(&self) -> usize {
Children::len(self)
}
fn get(&self, index: usize) -> Option<Rc<dyn ControlObject>> {
Children::get(self, index)
}
fn on_changed(
&self,
f: Box<dyn FnMut(VecDiff<Rc<dyn ControlObject>>)>,
) -> Option<Subscription> {
match self {
Children::None | Children::SingleStatic(_) | Children::MultipleStatic(_) => None,
Children::SingleDynamic(x) => x.on_changed(f),
}
}
}