From 73aed04c64b01de6d2d0d041d51cb95d88253d4d Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sun, 15 Sep 2024 19:58:43 +0300 Subject: [PATCH] generalize Split --- crates/tek_core/src/space.rs | 90 ++++++++++++++++++++++++++++++++++++ crates/tek_core/src/tui.rs | 79 ------------------------------- 2 files changed, 90 insertions(+), 79 deletions(-) diff --git a/crates/tek_core/src/space.rs b/crates/tek_core/src/space.rs index 0f3b0308..4120fe18 100644 --- a/crates/tek_core/src/space.rs +++ b/crates/tek_core/src/space.rs @@ -46,6 +46,7 @@ pub trait Size { 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> Widget for Minus { }.into(), self.inner())).transpose()?.unwrap_or(())) } } + +impl Widget for Split +where + F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget)->Usually<()>)->Usually<()> +{ + type Engine = E; + fn layout (&self, to: E::Size) -> Perhaps { + 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) + .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) + .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) + .layout(area.wh().into())?; + if let Some([width, height]) = size.map(|size|size.wh()) { + Plus::Y(h, component as &dyn Widget).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) + .layout(area.wh().into())?; + if let Some([width, height]) = size.map(|size|size.wh()) { + Plus::X(w, component as &dyn Widget).render(to)?; + w = width + w; + h = h.max(height) + }; + Ok(()) + })?; + }, + _ => todo!() + }; + Ok(()) + } +} diff --git a/crates/tek_core/src/tui.rs b/crates/tek_core/src/tui.rs index ccb1716c..6538e804 100644 --- a/crates/tek_core/src/tui.rs +++ b/crates/tek_core/src/tui.rs @@ -337,85 +337,6 @@ impl> Widget for Fixed { } } -impl Widget for Split -where - F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget)->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).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).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).layout(area.wh())?; - if let Some([width, height]) = area { - Plus::Y(h, component as &dyn Widget).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).layout(area.wh())?; - if let Some([width, height]) = area { - Plus::X(w, component as &dyn Widget).render(to)?; - w += width; - h = h.max(height) - }; - Ok(()) - })?; - }, - _ => todo!() - }; - Ok(()) - } -} - //impl Widget for Layers //where //F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget)->Usually<()>)->Usually<()>