use crate::*; pub enum Collected<'a, E: Engine> { Box(Box + 'a>), Ref(&'a (dyn Widget + 'a)), } impl<'a, E: Engine> Widget for Collected<'a, E> { type Engine = E; fn layout (&self, area: E::Area) -> Perhaps { match self { Self::Box(inner) => (*inner).layout(area), Self::Ref(inner) => (*inner).layout(area), } } fn render (&self, to: &mut E) -> Perhaps { match self { Self::Box(inner) => (*inner).render(to), Self::Ref(inner) => (*inner).render(to), } } } pub struct Collection<'a, E: Engine>( pub Vec> ); impl<'a, E: Engine> Collection<'a, E> { pub fn new () -> Self { Self(vec![]) } } pub trait Collect<'a, E: Engine> { fn add_box (self, item: Box + 'a>) -> Self; fn add_ref (self, item: &'a dyn Widget) -> Self; fn add + Sized + 'a> (self, item: R) -> Self where Self: Sized { self.add_box(Box::new(item)) } } impl<'a, E: Engine> Collect<'a, E> for Collection<'a, E> { fn add_box (mut self, item: Box + 'a>) -> Self { self.0.push(Collected::Box(item)); self } fn add_ref (mut self, item: &'a dyn Widget) -> Self { self.0.push(Collected::Ref(item)); self } } pub struct Layers<'a, E: Engine>(pub &'a [&'a dyn Widget]); // this actually works, except for the type inference //pub struct Layers<'a, E: Engine + 'a, I: std::iter::IntoIterator>>( //pub &'a I //); pub struct Layered<'a, E: Engine>(pub Collection<'a, E>); impl<'a, E: Engine> Layered<'a, E> { pub fn new () -> Self { Self(Collection::new()) } } impl<'a, E: Engine> Collect<'a, E> for Layered<'a, E> { fn add_box (mut self, item: Box + 'a>) -> Self { self.0 = self.0.add_box(item); self } fn add_ref (mut self, item: &'a dyn Widget) -> Self { self.0 = self.0.add_ref(item); self } } #[derive(Copy, Clone)] pub enum Direction { Up, Down, Left, Right } impl Direction { pub fn is_down (&self) -> bool { match self { Self::Down => true, _ => false } } pub fn is_right (&self) -> bool { match self { Self::Right => true, _ => false } } } pub struct Split<'a, E: Engine> { pub items: Collection<'a, E>, pub direction: Direction, pub focus: Option } impl<'a, E: Engine> Split<'a, E> { pub fn new (direction: Direction) -> Self { Self { items: Collection::new(), direction, focus: None } } pub fn down () -> Self { Self::new(Direction::Down) } pub fn right () -> Self { Self::new(Direction::Right) } pub fn focus (mut self, focus: Option) -> Self { self.focus = focus; self } } impl<'a, E: Engine> Collect<'a, E> for Split<'a, E> { fn add_box (mut self, item: Box + 'a>) -> Self { self.items = self.items.add_box(item); self } fn add_ref (mut self, item: &'a dyn Widget) -> Self { self.items = self.items.add_ref(item); self } }