mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 12:46:42 +01:00
151 lines
5.4 KiB
Rust
151 lines
5.4 KiB
Rust
use crate::*;
|
|
|
|
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(())
|
|
}
|
|
}
|