wip: big flat pt.4: extract layout crate

This commit is contained in:
🪞👃🪞 2024-12-30 19:07:43 +01:00
parent cb680ab096
commit 34e731f111
21 changed files with 2125 additions and 83 deletions

View file

@ -0,0 +1,169 @@
use crate::*;
/// A binary split with fixed proportion
pub struct Split<E, A, B>(pub bool, pub Direction, pub E::Unit, A, B, PhantomData<E>)
where E: Engine, A: Render<E>, B: Render<E>;
impl<E: Engine, A: Render<E>, B: Render<E>> Split<E, A, B> {
#[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<E: Engine, A: Render<E>, B: Render<E>> Render<E> for Split<E, A, B> {
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
Ok(Some(to))
}
fn render (&self, to: &mut E::Output) -> Usually<()> {
let (a, b) = self.1.split_fixed(self.2, self.3);
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<E: Engine, F> Render<E> for Stack<E, F>
where
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>
{
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
match self.1 {
South => {
let mut w: E::Unit = 0.into();
let mut h: E::Unit = 0.into();
(self.0)(&mut |component: &dyn Render<E>| {
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<E>| {
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<E>| {
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<E>| {
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(())
}
}