wip: extract tek_layout

This commit is contained in:
🪞👃🪞 2024-12-09 12:19:55 +01:00
parent ddb3c28c01
commit 2265d951d1
36 changed files with 2010 additions and 1780 deletions

View file

@ -0,0 +1,179 @@
use crate::*;
#[macro_export] macro_rules! col {
($($expr:expr),* $(,)?) => { Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) };
($pat:pat in $collection:expr => $item:expr) => {
Stack::down(move |add|{
for $pat in $collection { add(&$item)?; }
Ok(())
})
}
}
#[macro_export] macro_rules! col_up {
($($expr:expr),* $(,)?) => { Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) };
($pat:pat in $collection:expr => $item:expr) => {
Stack::up(move |add|{
for $pat in $collection { add(&$item)?; }
Ok(())
})
}
}
#[macro_export] macro_rules! row {
($($expr:expr),* $(,)?) => { Stack::right(move|add|{ $(add(&$expr)?;)* Ok(()) }) };
($pat:pat in $collection:expr => $item:expr) => {
Stack::right(move |add|{
for $pat in $collection { add(&$item)?; }
Ok(())
})
}
}
pub struct Stack<
E: Engine,
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>
>(pub F, pub Direction, PhantomData<E>);
impl<
E: Engine,
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>
> Stack<E, F> {
#[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<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 {
Direction::Down => {
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 = 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<E>| {
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<E>| {
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<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 {
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(())
}
}