use crate::*; /// A binary split with fixed proportion pub struct Split(pub bool, pub Direction, pub E::Unit, A, B, PhantomData) where E: Engine, A: Render, B: Render; impl, B: Render> Split { #[inline] pub fn new (flip: bool, direction: Direction, proportion: E::Unit, a: A, b: B) -> Self { Self(flip, direction, proportion, a, b, Default::default()) } #[inline] pub fn n (flip: bool, proportion: E::Unit, a: A, b: B) -> Self { Self::new(flip, North, proportion, a, b) } #[inline] pub fn s (flip: bool, proportion: E::Unit, a: A, b: B) -> Self { Self::new(flip, South, proportion, a, b) } #[inline] pub fn e (flip: bool, proportion: E::Unit, a: A, b: B) -> Self { Self::new(flip, West, proportion, a, b) } #[inline] pub fn w (flip: bool, proportion: E::Unit, a: A, b: B) -> Self { Self::new(flip, East, proportion, a, b) } } impl, B: Render> Render for Split { fn min_size (&self, to: E::Size) -> Perhaps { Ok(Some(to)) } fn render (&self, to: &mut E::Output) -> Usually<()> { let (a, b) = self.1.split_fixed(to.area(), self.2); Ok(if self.0 { to.render_in(a.into(), &self.4)?; to.render_in(b.into(), &self.3)?; } else { to.render_in(a.into(), &self.3)?; to.render_in(b.into(), &self.4)?; }) } } 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 { South => { 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 = Max::y(max, Push::y(h, component)); 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())) }, East => { 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 = Max::x(max, Push::x(h, component)); 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())) }, North => { 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 = Max::y(to.h() - h, component); 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())) }, West => { let w: E::Unit = 0.into(); let 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 { South => { (self.0)(&mut |item| { if h < area.h() { let item = Max::y(area.h() - h, Push::y(h, item)); 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(()) })?; }, East => { (self.0)(&mut |item| { if w < area.w() { let item = Max::x(area.w() - w, Push::x(w, item)); 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(()) })?; }, North => { (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 { Shrink::y(height, Push::y(area.h() - height, item)) .render(to)?; h = h + height; if width > w { w = width } }; } Ok(()) })?; }, _ => todo!() }; Ok(()) } }