mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
169 lines
6.1 KiB
Rust
169 lines
6.1 KiB
Rust
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(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<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(())
|
|
}
|
|
}
|
|
|
|
|