generalize Split

This commit is contained in:
🪞👃🪞 2024-09-15 19:58:43 +03:00
parent f7b2134310
commit 73aed04c64
2 changed files with 90 additions and 79 deletions

View file

@ -46,6 +46,7 @@ pub trait Size<N: Number> {
fn y (&self) -> N;
#[inline] fn w (&self) -> N { self.x() }
#[inline] fn h (&self) -> N { self.y() }
#[inline] fn wh (&self) -> [N;2] { [self.x(), self.y()] }
#[inline] fn expect_min (&self, w: N, h: N) -> Usually<&Self> {
if self.w() < w || self.h() < h {
Err(format!("min {w}x{h}").into())
@ -574,3 +575,92 @@ impl<E: Engine, T: Widget<Engine = E>> Widget for Minus<E::Unit, T> {
}.into(), self.inner())).transpose()?.unwrap_or(()))
}
}
impl<E: Engine, F> Widget for Split<E, F>
where
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget<Engine = E>)->Usually<()>)->Usually<()>
{
type Engine = E;
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
let mut w = 0.into();
let mut h = 0.into();
match self.1 {
Direction::Down => {
(self.0)(&mut |component| {
if h >= to.h() {
return Ok(())
}
let size = Plus::Y(h, component as &dyn Widget<Engine = E>)
.layout(to)?;
if let Some([width, height]) = size.map(|size|size.wh()) {
h = h + height.into();
if width > w {
w = width;
}
}
Ok(())
})?;
},
Direction::Right => {
(self.0)(&mut |component| {
if w >= to.w() {
return Ok(())
}
let size = Plus::X(w, component as &dyn Widget<Engine = E>)
.layout(to)?;
if let Some([width, height]) = size.map(|size|size.wh()) {
w = w + width.into();
if height > h {
h = height
}
}
Ok(())
})?;
},
_ => todo!()
};
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 |component| {
if h >= area.h() {
return Ok(())
}
// FIXME -> ???
let size = Plus::Y(h, component as &dyn Widget<Engine = E>)
.layout(area.wh().into())?;
if let Some([width, height]) = size.map(|size|size.wh()) {
Plus::Y(h, component as &dyn Widget<Engine = E>).render(to)?;
h = h + height;
if width > w {
w = width
}
};
Ok(())
})?;
},
Direction::Right => {
(self.0)(&mut |component| {
if w >= area.w() {
return Ok(())
}
let size = Plus::X(w, component as &dyn Widget<Engine = E>)
.layout(area.wh().into())?;
if let Some([width, height]) = size.map(|size|size.wh()) {
Plus::X(w, component as &dyn Widget<Engine = E>).render(to)?;
w = width + w;
h = h.max(height)
};
Ok(())
})?;
},
_ => todo!()
};
Ok(())
}
}

View file

@ -337,85 +337,6 @@ impl<T: Widget<Engine = Tui>> Widget for Fixed<u16, T> {
}
}
impl<F> Widget for Split<Tui, F>
where
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget<Engine = Tui>)->Usually<()>)->Usually<()>
{
type Engine = Tui;
fn layout (&self, to: [u16;2]) -> Perhaps<[u16;2]> {
let mut w = 0;
let mut h = 0;
match self.1 {
Direction::Down => {
(self.0)(&mut |component| {
if h >= to.h() {
return Ok(())
}
let area = Plus::Y(h, component as &dyn Widget<Engine = Tui>).layout(to)?;
if let Some([width, height]) = area {
h += height;
w = w.max(width)
}
Ok(())
})?;
},
Direction::Right => {
(self.0)(&mut |component| {
if w >= to.w() {
return Ok(())
}
let area = Plus::X(w, component as &dyn Widget<Engine = Tui>).layout(to)?;
if let Some([width, height]) = area {
w += width;
h = h.max(height)
}
Ok(())
})?;
},
_ => todo!()
};
Ok(Some([w, h]))
}
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
let area = to.area();
let mut w = 0;
let mut h = 0;
match self.1 {
Direction::Down => {
(self.0)(&mut |component| {
if h >= area.h() {
return Ok(())
}
// FIXME
let area = Plus::Y(h, component as &dyn Widget<Engine = Tui>).layout(area.wh())?;
if let Some([width, height]) = area {
Plus::Y(h, component as &dyn Widget<Engine = Tui>).render(to)?;
h += height;
w = w.max(width)
};
Ok(())
})?;
},
Direction::Right => {
(self.0)(&mut |component| {
if w >= area.w() {
return Ok(())
}
let area = Plus::X(w, component as &dyn Widget<Engine = Tui>).layout(area.wh())?;
if let Some([width, height]) = area {
Plus::X(w, component as &dyn Widget<Engine = Tui>).render(to)?;
w += width;
h = h.max(height)
};
Ok(())
})?;
},
_ => todo!()
};
Ok(())
}
}
//impl<F> Widget for Layers<Tui, F>
//where
//F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget<Engine = Tui>)->Usually<()>)->Usually<()>