From c4a5ee7b6e13edb878c20b4396f065bb594caf02 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Mon, 9 Sep 2024 14:57:14 +0300 Subject: [PATCH] wip: migrating to Widget trait --- crates/tek_core/src/engine/component.rs | 12 +- crates/tek_core/src/engine/layout.rs | 148 ++++++++++++------------ crates/tek_core/src/tui/tui_layout.rs | 111 +++++++----------- crates/tek_test/src/main.rs | 20 +--- 4 files changed, 130 insertions(+), 161 deletions(-) diff --git a/crates/tek_core/src/engine/component.rs b/crates/tek_core/src/engine/component.rs index f2e498b5..1c11f98d 100644 --- a/crates/tek_core/src/engine/component.rs +++ b/crates/tek_core/src/engine/component.rs @@ -96,16 +96,12 @@ pub trait Content { //() //} //} -impl Widget for W where W: Content { - type Engine = ::Engine; - fn layout (&self, to: <::Engine as Engine>::Area) - -> Perhaps<<::Engine as Engine>::Area> - { +impl Widget for W where W: Content { + type Engine = E; + fn layout (&self, to: E::Area) -> Perhaps { self.content().layout(to) } - fn render (&self, to: &mut ::Engine) - -> Perhaps<<::Engine as Engine>::Area> - { + fn render (&self, to: &mut E) -> Perhaps { self.content().render(to) } } diff --git a/crates/tek_core/src/engine/layout.rs b/crates/tek_core/src/engine/layout.rs index 5acf498a..e28bfe46 100644 --- a/crates/tek_core/src/engine/layout.rs +++ b/crates/tek_core/src/engine/layout.rs @@ -46,17 +46,34 @@ impl> Layout for Option { /// Override X and Y coordinates, aligning to corner, side, or center of area pub enum Align { Center(L), NW(L), N(L), NE(L), W(L), E(L), SW(L), S(L), SE(L) } /// Enforce minimum size of drawing area -pub enum Min { W(U, L), H(U, L), WH(U, U, L), } +pub enum Min { W(U, T), H(U, T), WH(U, U, T), } /// Enforce maximum size of drawing area -pub enum Max { W(U, L), H(U, L), WH(U, U, L), } +pub enum Max { W(U, T), H(U, T), WH(U, U, T), } /// Expand drawing area -pub enum Outset { W(U, L), H(U, L), WH(U, U, L), } +pub enum Outset { W(U, T), H(U, T), WH(U, U, T), } /// Shrink drawing area -pub enum Inset { W(U, L), H(U, L), WH(U, U, L), } +pub enum Inset { W(U, T), H(U, T), WH(U, U, T), } /// Move origin point of drawing area -pub enum Offset { X(U, L), Y(U, L), XY(U, U, L), } +pub enum Offset { X(U, T), Y(U, T), XY(U, U, T), } -impl> Layout for Min { +impl Align { + pub fn inner (&self) -> &T { + match self { + Self::Center(inner) => inner, + Self::NW(inner) => inner, + Self::N(inner) => inner, + Self::NE(inner) => inner, + Self::W(inner) => inner, + Self::E(inner) => inner, + Self::SW(inner) => inner, + Self::S(inner) => inner, + Self::SE(inner) => inner, + } + } +} + +impl> Widget for Min { + type Engine = E; fn layout (&self, area: E::Area) -> Perhaps { match self { Self::W(w, item) => if area.w() < *w { Ok(None) } else { @@ -72,9 +89,22 @@ impl> Layout for Min { } } } + fn render (&self, to: &mut E) -> Perhaps { + // 🡘 🡙 ←🡙→ + self.layout(to.area())? + .map(|area|to.with_area(area.x(), area.y(), area.w(), area.h())) + .map(|to|match self { + Self::W(_, inner) => inner, + Self::H(_, inner) => inner, + Self::WH(_, _, inner) => inner, + }.render(to)) + .transpose() + .map(|x|x.flatten()) + } } -impl> Layout for Max { +impl> Widget for Max { + type Engine = E; fn layout (&self, area: E::Area) -> Perhaps { match self { Self::W(w, item) => { @@ -90,9 +120,21 @@ impl> Layout for Max { } } } + fn render (&self, to: &mut E) -> Perhaps { + self.layout(to.area())? + .map(|area|to.with_area(area.x(), area.y(), area.w(), area.h())) + .map(|to|match self { + Self::W(_, inner) => inner, + Self::H(_, inner) => inner, + Self::WH(_, _, inner) => inner, + }.render(to)) + .transpose() + .map(|x|x.flatten()) + } } -impl> Layout for Outset { +impl> Widget for Outset { + type Engine = E; fn layout (&self, area: E::Area) -> Perhaps { match self { Self::W(w, item) => if area.x() < *w { Ok(None) } else { @@ -106,9 +148,21 @@ impl> Layout for Outset { } } } + fn render (&self, to: &mut E) -> Perhaps { + self.layout(to.area())? + .map(|area|to.with_area(area.x(), area.y(), area.w(), area.h())) + .map(|to|match self { + Self::W(_, inner) => inner, + Self::H(_, inner) => inner, + Self::WH(_, _, inner) => inner, + }.render(to)) + .transpose() + .map(|x|x.flatten()) + } } -impl> Layout for Inset { +impl> Widget for Inset { + type Engine = E; fn layout (&self, area: E::Area) -> Perhaps { match self { Self::W(w, item) => if area.w() < *w { Ok(None) } else { @@ -122,9 +176,21 @@ impl> Layout for Inset { } } } + fn render (&self, to: &mut E) -> Perhaps { + self.layout(to.area())? + .map(|area|to.with_area(area.x(), area.y(), area.w(), area.h())) + .map(|to|match self { + Self::W(_, inner) => inner, + Self::H(_, inner) => inner, + Self::WH(_, _, inner) => inner, + }.render(to)) + .transpose() + .map(|x|x.flatten()) + } } -impl> Layout for Offset { +impl> Widget for Offset { + type Engine = E; fn layout (&self, area: E::Area) -> Perhaps { match self { Self::X(x, item) => if area.w() < *x { Ok(None) } else { @@ -138,67 +204,7 @@ impl> Layout for Offset { } } } -} - -impl + Layout> Render for Min { - fn render (&self, to: &mut E) -> Perhaps { - // 🡘 🡙 ←🡙→ - self.layout(to.area())? - .map(|area|to.with_area(area.x(), area.y(), area.w(), area.h())) - .map(|to|match self { - Self::W(_, inner) => inner, - Self::H(_, inner) => inner, - Self::WH(_, _, inner) => inner, - }.render(to)) - .transpose() - .map(|x|x.flatten()) - } -} - -impl + Layout> Render for Max { - fn render (&self, to: &mut E) -> Perhaps { - self.layout(to.area())? - .map(|area|to.with_area(area.x(), area.y(), area.w(), area.h())) - .map(|to|match self { - Self::W(_, inner) => inner, - Self::H(_, inner) => inner, - Self::WH(_, _, inner) => inner, - }.render(to)) - .transpose() - .map(|x|x.flatten()) - } -} - -impl + Layout> Render for Inset { - fn render (&self, to: &mut E) -> Perhaps { - self.layout(to.area())? - .map(|area|to.with_area(area.x(), area.y(), area.w(), area.h())) - .map(|to|match self { - Self::W(_, inner) => inner, - Self::H(_, inner) => inner, - Self::WH(_, _, inner) => inner, - }.render(to)) - .transpose() - .map(|x|x.flatten()) - } -} - -impl + Layout> Render for Outset { - fn render (&self, to: &mut E) -> Perhaps { - self.layout(to.area())? - .map(|area|to.with_area(area.x(), area.y(), area.w(), area.h())) - .map(|to|match self { - Self::W(_, inner) => inner, - Self::H(_, inner) => inner, - Self::WH(_, _, inner) => inner, - }.render(to)) - .transpose() - .map(|x|x.flatten()) - } -} - -impl + Layout> Render for Offset { - fn render (&self, to: &mut E) -> Perhaps { + fn render (&self, to: &mut E) -> Perhaps { self.layout(to.area())? .map(|area|to.with_area(area.x(), area.y(), area.w(), area.h())) .map(|to|match self { diff --git a/crates/tek_core/src/tui/tui_layout.rs b/crates/tek_core/src/tui/tui_layout.rs index 34069775..05bb6faa 100644 --- a/crates/tek_core/src/tui/tui_layout.rs +++ b/crates/tek_core/src/tui/tui_layout.rs @@ -1,32 +1,5 @@ use crate::*; -impl<'a> Layout for Layers<'a, Tui> { - fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> { - let [x, y, ..] = area; - let mut w = 0; - let mut h = 0; - for layer in self.0.iter() { - if let Some(layer_area) = layer.layout(area)? { - w = w.max(layer_area.w()); - h = h.max(layer_area.h()); - } - } - Ok(Some([x, y, w, h])) - } -} -impl<'a> Render for Layers<'a, Tui> { - fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { - self.layout(to.area())? - .map(|area| { - for layer in self.0.iter() { - layer.render(to.with_rect(area))?; - } - Ok(area) - }) - .transpose() - } -} - impl<'a> Render for Layered<'a, Tui> { fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { let area = to.area(); @@ -88,54 +61,56 @@ impl<'a> Split<'a, Tui> { } } -impl + Layout> Layout for Align { - fn layout (&self, outer_area: [u16;4]) -> Perhaps<[u16;4]> { - Ok(match self { - Self::Center(inner) => inner, - Self::NW(inner) => inner, - Self::N(inner) => inner, - Self::NE(inner) => inner, - Self::W(inner) => inner, - Self::E(inner) => inner, - Self::SW(inner) => inner, - Self::S(inner) => inner, - Self::SE(inner) => inner, +impl<'a> Widget for Layers<'a, Tui> { + type Engine = Tui; + fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> { + let [x, y, ..] = area; + let mut w = 0; + let mut h = 0; + for layer in self.0.iter() { + if let Some(layer_area) = layer.layout(area)? { + w = w.max(layer_area.w()); + h = h.max(layer_area.h()); + } } - .layout(outer_area)? - .map(|inner_area|match self { - Self::Center(_) => { - let [_, _, w, h] = inner_area.xywh(); - let offset_x = (outer_area.w() - w) / 2; - let offset_y = (outer_area.h() - h) / 2; - [outer_area.x() + offset_x, outer_area.y() + offset_y, w, h] - }, - Self::NW(_) => { todo!() }, - Self::N(_) => { todo!() }, - Self::NE(_) => { todo!() }, - Self::W(_) => { todo!() }, - Self::E(_) => { todo!() }, - Self::SW(_) => { todo!() }, - Self::S(_) => { todo!() }, - Self::SE(_) => { todo!() }, - })) + Ok(Some([x, y, w, h])) + } + fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { + self.layout(to.area())? + .map(|area| { + for layer in self.0.iter() { + layer.render(to.with_rect(area))?; + } + Ok(area) + }) + .transpose() } } -impl + Layout> Render for Align { +impl> Widget for Align { + type Engine = Tui; + fn layout (&self, outer_area: [u16;4]) -> Perhaps<[u16;4]> { + Ok(self.inner().layout(outer_area)?.map(|inner_area|match self { + Self::Center(_) => { + let [_, _, w, h] = inner_area.xywh(); + let offset_x = (outer_area.w() - w) / 2; + let offset_y = (outer_area.h() - h) / 2; + [outer_area.x() + offset_x, outer_area.y() + offset_y, w, h] + }, + Self::NW(_) => { todo!() }, + Self::N(_) => { todo!() }, + Self::NE(_) => { todo!() }, + Self::W(_) => { todo!() }, + Self::E(_) => { todo!() }, + Self::SW(_) => { todo!() }, + Self::S(_) => { todo!() }, + Self::SE(_) => { todo!() }, + })) + } fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { self.layout(to.area())? .map(|area|to.with_area(area.x(), area.y(), area.w(), area.h())) - .map(|to|match self { - Self::Center(inner) => inner, - Self::NW(inner) => inner, - Self::N(inner) => inner, - Self::NE(inner) => inner, - Self::W(inner) => inner, - Self::E(inner) => inner, - Self::SW(inner) => inner, - Self::S(inner) => inner, - Self::SE(inner) => inner, - }.render(to)) + .map(|to|self.inner().render(to)) .transpose() .map(|x|x.flatten()) } diff --git a/crates/tek_test/src/main.rs b/crates/tek_test/src/main.rs index 67cdc6af..af5f21dc 100644 --- a/crates/tek_test/src/main.rs +++ b/crates/tek_test/src/main.rs @@ -24,7 +24,11 @@ impl Demo { })); Self { index: 0, items } } - fn content <'a> (&'a self) -> impl Layout + 'a { +} + +impl Content for Demo { + type Engine = E; + fn content (&self) -> impl Widget { Align::Center(Layers(&[ &Outset::WH(2, 1, FillBg(Color::Rgb(0,128,128))), &Layers(&[ @@ -35,18 +39,6 @@ impl Demo { } } -impl Layout for Demo { - fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> { - self.content().layout(area) - } -} - -impl Render for Demo { - fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { - self.content().render(to) - } -} - impl Handle for Demo { fn handle (&mut self, from: &Tui) -> Perhaps { match from.event() { @@ -62,7 +54,7 @@ impl Handle for Demo { }; Ok(Some(true)) }, - _ => Ok(None) + _ => Ok(None) } } }