use crate::*; pub struct Stack< E: Engine, F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render)->Usually<()>)->Usually<()> >(pub F, pub Direction, PhantomData); impl< E: Engine, F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render)->Usually<()>)->Usually<()> > Stack { #[inline] pub fn new (direction: Direction, build: F) -> Self { Self(build, direction, Default::default()) } #[inline] pub fn right (build: F) -> Self { Self::new(Direction::Right, build) } #[inline] pub fn down (build: F) -> Self { Self::new(Direction::Down, build) } #[inline] pub fn up (build: F) -> Self { Self::new(Direction::Up, build) } } impl Render for Stack where F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render)->Usually<()>)->Usually<()> { fn min_size (&self, to: E::Size) -> Perhaps { match self.1 { Direction::Down => { let mut w: E::Unit = 0.into(); let mut h: E::Unit = 0.into(); (self.0)(&mut |component: &dyn Render| { let max = to.h().minus(h); if max > E::Unit::ZERO() { let item = component.push_y(h).max_y(max); let size = item.min_size(to)?.map(|size|size.wh()); if let Some([width, height]) = size { h = h + height.into(); w = w.max(width); } } Ok(()) })?; Ok(Some([w, h].into())) }, Direction::Right => { let mut w: E::Unit = 0.into(); let mut h: E::Unit = 0.into(); (self.0)(&mut |component: &dyn Render| { let max = to.w().minus(w); if max > E::Unit::ZERO() { let item = component.push_x(w).max_x(max); let size = item.min_size(to)?.map(|size|size.wh()); if let Some([width, height]) = size { w = w + width.into(); h = h.max(height); } } Ok(()) })?; Ok(Some([w, h].into())) }, Direction::Up => { let mut w: E::Unit = 0.into(); let mut h: E::Unit = 0.into(); (self.0)(&mut |component: &dyn Render| { let max = to.h().minus(h); if max > E::Unit::ZERO() { let item = component.max_y(to.h() - h); let size = item.min_size(to)?.map(|size|size.wh()); if let Some([width, height]) = size { h = h + height.into(); w = w.max(width); } } Ok(()) })?; Ok(Some([w, h].into())) }, Direction::Left => { let mut w: E::Unit = 0.into(); let mut h: E::Unit = 0.into(); (self.0)(&mut |component: &dyn Render| { if w < to.w() { todo!(); } Ok(()) })?; Ok(Some([w, h].into())) }, } } fn render (&self, to: &mut E::Output) -> Usually<()> { let area = to.area(); let mut w = 0.into(); let mut h = 0.into(); match self.1 { Direction::Down => { (self.0)(&mut |item| { if h < area.h() { let item = item.push_y(h).max_y(area.h() - h); let show = item.min_size(area.wh().into())?.map(|s|s.wh()); if let Some([width, height]) = show { item.render(to)?; h = h + height; if width > w { w = width } }; } Ok(()) })?; }, Direction::Right => { (self.0)(&mut |item| { if w < area.w() { let item = item.push_x(w).max_x(area.w() - w); let show = item.min_size(area.wh().into())?.map(|s|s.wh()); if let Some([width, height]) = show { item.render(to)?; w = width + w; if height > h { h = height } }; } Ok(()) })?; }, Direction::Up => { (self.0)(&mut |item| { if h < area.h() { let show = item.min_size([area.w(), area.h().minus(h)].into())?.map(|s|s.wh()); if let Some([width, height]) = show { item.push_y(area.h() - height).shrink_y(height).render(to)?; h = h + height; if width > w { w = width } }; } Ok(()) })?; }, _ => todo!() }; Ok(()) } }