use crate::*; use super::*; use Direction::*; impl Direction { pub fn is_north (&self) -> bool { matches!(self, Self::North) } pub fn is_south (&self) -> bool { matches!(self, Self::South) } pub fn is_east (&self) -> bool { matches!(self, Self::West) } pub fn is_west (&self) -> bool { matches!(self, Self::East) } /// Return next direction clockwise pub fn cw (&self) -> Self { match self { Self::North => Self::East, Self::South => Self::West, Self::West => Self::North, Self::East => Self::South, } } /// Return next direction counterclockwise pub fn ccw (&self) -> Self { match self { Self::North => Self::West, Self::South => Self::East, Self::West => Self::South, Self::East => Self::North, } } } 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) = to.area().split_fixed(self.1, 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, Y: Render> Default for Bsp { fn default () -> Self { Self::Null(Default::default()) } } impl, Y: Render> Render for Bsp { fn min_size (&self, to: E::Size) -> Perhaps { Ok(Some(match self { Self::Null(_) => [0.into(), 0.into()].into(), Self::S(a, b) => { let a = a.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); let b = b.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); [a.w().max(b.w()), a.h() + b.h()].into() }, Self::E(a, b) => { let a = a.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); let b = b.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); [a.w() + b.w(), a.h().max(b.h())].into() }, Self::W(a, b) => { let a = a.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); let b = b.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); [a.w() + b.w(), a.h().max(b.h())].into() }, Self::N(a, b) => { let a = a.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); let b = b.min_size(to)?.unwrap_or([0.into(), 0.into()].into()); [a.w().max(b.w()), a.h() + b.h()].into() }, _ => todo!() })) } fn render (&self, to: &mut E::Output) -> Usually<()> { let n = [0.into(), 0.into()].into(); let s = to.area().wh().into(); Ok(match self { Self::Null(_) => {}, Self::S(a, b) => { let s_a = a.min_size(s)?.unwrap_or(n); let _ = b.min_size(s)?.unwrap_or(n); let h = s_a.h().into(); to.render_in(to.area().clip_h(h).into(), a)?; to.render_in(to.area().shrink_y(h).push_y(h).into(), b)?; }, Self::E(a, b) => { let s_a = a.min_size(s)?.unwrap_or(n); let _ = b.min_size(s)?.unwrap_or(n); let w = s_a.w().into(); to.render_in(to.area().clip_w(w).into(), a)?; to.render_in(to.area().push_x(w).shrink_x(w).into(), b)?; }, Self::W(a, b) => { let s_a = a.min_size(s)?.unwrap_or(n); let _ = b.min_size(s)?.unwrap_or(n); let w = (to.area().w() - s_a.w()).into(); to.render_in(to.area().push_x(w).into(), a)?; to.render_in(to.area().shrink_x(w).into(), b)?; }, Self::N(a, b) => { let s_a = a.min_size(s)?.unwrap_or(n); let _ = b.min_size(s)?.unwrap_or(n); let h = to.area().h() - s_a.h(); to.render_in(to.area().push_y(h).into(), a)?; to.render_in(to.area().shrink_y(h).into(), b)?; }, _ => todo!() }) } } 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(()) } } #[cfg(test)] #[test] fn test_bsp () { // TODO }