mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
wip: migrating to Widget trait
This commit is contained in:
parent
b944dd5f9e
commit
c4a5ee7b6e
4 changed files with 130 additions and 161 deletions
|
|
@ -96,16 +96,12 @@ pub trait Content {
|
||||||
//()
|
//()
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
impl<W> Widget for W where W: Content {
|
impl<E: Engine, W> Widget for W where W: Content<Engine = E> {
|
||||||
type Engine = <Self as Content>::Engine;
|
type Engine = E;
|
||||||
fn layout (&self, to: <<Self as Content>::Engine as Engine>::Area)
|
fn layout (&self, to: E::Area) -> Perhaps<E::Area> {
|
||||||
-> Perhaps<<<Self as Content>::Engine as Engine>::Area>
|
|
||||||
{
|
|
||||||
self.content().layout(to)
|
self.content().layout(to)
|
||||||
}
|
}
|
||||||
fn render (&self, to: &mut <Self as Content>::Engine)
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
-> Perhaps<<<Self as Content>::Engine as Engine>::Area>
|
|
||||||
{
|
|
||||||
self.content().render(to)
|
self.content().render(to)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,17 +46,34 @@ impl<E: Engine, T: Layout<E>> Layout<E> for Option<T> {
|
||||||
/// Override X and Y coordinates, aligning to corner, side, or center of area
|
/// Override X and Y coordinates, aligning to corner, side, or center of area
|
||||||
pub enum Align<L> { Center(L), NW(L), N(L), NE(L), W(L), E(L), SW(L), S(L), SE(L) }
|
pub enum Align<L> { Center(L), NW(L), N(L), NE(L), W(L), E(L), SW(L), S(L), SE(L) }
|
||||||
/// Enforce minimum size of drawing area
|
/// Enforce minimum size of drawing area
|
||||||
pub enum Min<U: Number, L> { W(U, L), H(U, L), WH(U, U, L), }
|
pub enum Min<U: Number, T> { W(U, T), H(U, T), WH(U, U, T), }
|
||||||
/// Enforce maximum size of drawing area
|
/// Enforce maximum size of drawing area
|
||||||
pub enum Max<U: Number, L> { W(U, L), H(U, L), WH(U, U, L), }
|
pub enum Max<U: Number, T> { W(U, T), H(U, T), WH(U, U, T), }
|
||||||
/// Expand drawing area
|
/// Expand drawing area
|
||||||
pub enum Outset<U: Number, L> { W(U, L), H(U, L), WH(U, U, L), }
|
pub enum Outset<U: Number, T> { W(U, T), H(U, T), WH(U, U, T), }
|
||||||
/// Shrink drawing area
|
/// Shrink drawing area
|
||||||
pub enum Inset<U: Number, L> { W(U, L), H(U, L), WH(U, U, L), }
|
pub enum Inset<U: Number, T> { W(U, T), H(U, T), WH(U, U, T), }
|
||||||
/// Move origin point of drawing area
|
/// Move origin point of drawing area
|
||||||
pub enum Offset<U: Number, L> { X(U, L), Y(U, L), XY(U, U, L), }
|
pub enum Offset<U: Number, T> { X(U, T), Y(U, T), XY(U, U, T), }
|
||||||
|
|
||||||
impl<E: Engine, L: Layout<E>> Layout<E> for Min<E:: Unit, L> {
|
impl<T> Align<T> {
|
||||||
|
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<E: Engine, T: Widget<Engine = E>> Widget for Min<E::Unit, T> {
|
||||||
|
type Engine = E;
|
||||||
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
|
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
|
||||||
match self {
|
match self {
|
||||||
Self::W(w, item) => if area.w() < *w { Ok(None) } else {
|
Self::W(w, item) => if area.w() < *w { Ok(None) } else {
|
||||||
|
|
@ -72,9 +89,22 @@ impl<E: Engine, L: Layout<E>> Layout<E> for Min<E:: Unit, L> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
|
// 🡘 🡙 ←🡙→
|
||||||
|
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<E: Engine, L: Layout<E>> Layout<E> for Max<E:: Unit, L> {
|
impl<E: Engine, T: Widget<Engine = E>> Widget for Max<E:: Unit, T> {
|
||||||
|
type Engine = E;
|
||||||
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
|
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
|
||||||
match self {
|
match self {
|
||||||
Self::W(w, item) => {
|
Self::W(w, item) => {
|
||||||
|
|
@ -90,9 +120,21 @@ impl<E: Engine, L: Layout<E>> Layout<E> for Max<E:: Unit, L> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
|
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<E: Engine, L: Layout<E>> Layout<E> for Outset<E::Unit, L> {
|
impl<E: Engine, T: Widget<Engine = E>> Widget for Outset<E::Unit, T> {
|
||||||
|
type Engine = E;
|
||||||
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
|
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
|
||||||
match self {
|
match self {
|
||||||
Self::W(w, item) => if area.x() < *w { Ok(None) } else {
|
Self::W(w, item) => if area.x() < *w { Ok(None) } else {
|
||||||
|
|
@ -106,9 +148,21 @@ impl<E: Engine, L: Layout<E>> Layout<E> for Outset<E::Unit, L> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
|
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<E: Engine, L: Layout<E>> Layout<E> for Inset<E::Unit, L> {
|
impl<E: Engine, T: Widget<Engine = E>> Widget for Inset<E::Unit, T> {
|
||||||
|
type Engine = E;
|
||||||
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
|
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
|
||||||
match self {
|
match self {
|
||||||
Self::W(w, item) => if area.w() < *w { Ok(None) } else {
|
Self::W(w, item) => if area.w() < *w { Ok(None) } else {
|
||||||
|
|
@ -122,9 +176,21 @@ impl<E: Engine, L: Layout<E>> Layout<E> for Inset<E::Unit, L> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
|
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<E: Engine, L: Layout<E>> Layout<E> for Offset<E::Unit, L> {
|
impl<E: Engine, T: Widget<Engine = E>> Widget for Offset<E::Unit, T> {
|
||||||
|
type Engine = E;
|
||||||
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
|
fn layout (&self, area: E::Area) -> Perhaps<E::Area> {
|
||||||
match self {
|
match self {
|
||||||
Self::X(x, item) => if area.w() < *x { Ok(None) } else {
|
Self::X(x, item) => if area.w() < *x { Ok(None) } else {
|
||||||
|
|
@ -138,67 +204,7 @@ impl<E: Engine, L: Layout<E>> Layout<E> for Offset<E::Unit, L> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
fn render (&self, to: &mut E) -> Perhaps<E::Area> {
|
||||||
|
|
||||||
impl<E: Engine, R: Render<E> + Layout<E>> Render<E> for Min<E::Unit, R> {
|
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
// 🡘 🡙 ←🡙→
|
|
||||||
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<E: Engine, R: Render<E> + Layout<E>> Render<E> for Max<E::Unit, R> {
|
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
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<E: Engine, R: Render<E> + Layout<E>> Render<E> for Inset<E::Unit, R> {
|
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
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<E: Engine, R: Render<E> + Layout<E>> Render<E> for Outset<E::Unit, R> {
|
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
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<E: Engine, R: Render<E> + Layout<E>> Render<E> for Offset<E::Unit, R> {
|
|
||||||
fn render (&self, to: &mut E) -> Perhaps<E::Rendered> {
|
|
||||||
self.layout(to.area())?
|
self.layout(to.area())?
|
||||||
.map(|area|to.with_area(area.x(), area.y(), area.w(), area.h()))
|
.map(|area|to.with_area(area.x(), area.y(), area.w(), area.h()))
|
||||||
.map(|to|match self {
|
.map(|to|match self {
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,5 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
impl<'a> Layout<Tui> 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<Tui> 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<Tui> for Layered<'a, Tui> {
|
impl<'a> Render<Tui> for Layered<'a, Tui> {
|
||||||
fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> {
|
fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> {
|
||||||
let area = to.area();
|
let area = to.area();
|
||||||
|
|
@ -88,54 +61,56 @@ impl<'a> Split<'a, Tui> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Render<Tui> + Layout<Tui>> Layout<Tui> for Align<T> {
|
impl<'a> Widget for Layers<'a, Tui> {
|
||||||
fn layout (&self, outer_area: [u16;4]) -> Perhaps<[u16;4]> {
|
type Engine = Tui;
|
||||||
Ok(match self {
|
fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> {
|
||||||
Self::Center(inner) => inner,
|
let [x, y, ..] = area;
|
||||||
Self::NW(inner) => inner,
|
let mut w = 0;
|
||||||
Self::N(inner) => inner,
|
let mut h = 0;
|
||||||
Self::NE(inner) => inner,
|
for layer in self.0.iter() {
|
||||||
Self::W(inner) => inner,
|
if let Some(layer_area) = layer.layout(area)? {
|
||||||
Self::E(inner) => inner,
|
w = w.max(layer_area.w());
|
||||||
Self::SW(inner) => inner,
|
h = h.max(layer_area.h());
|
||||||
Self::S(inner) => inner,
|
}
|
||||||
Self::SE(inner) => inner,
|
|
||||||
}
|
}
|
||||||
.layout(outer_area)?
|
Ok(Some([x, y, w, h]))
|
||||||
.map(|inner_area|match self {
|
}
|
||||||
Self::Center(_) => {
|
fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> {
|
||||||
let [_, _, w, h] = inner_area.xywh();
|
self.layout(to.area())?
|
||||||
let offset_x = (outer_area.w() - w) / 2;
|
.map(|area| {
|
||||||
let offset_y = (outer_area.h() - h) / 2;
|
for layer in self.0.iter() {
|
||||||
[outer_area.x() + offset_x, outer_area.y() + offset_y, w, h]
|
layer.render(to.with_rect(area))?;
|
||||||
},
|
}
|
||||||
Self::NW(_) => { todo!() },
|
Ok(area)
|
||||||
Self::N(_) => { todo!() },
|
})
|
||||||
Self::NE(_) => { todo!() },
|
.transpose()
|
||||||
Self::W(_) => { todo!() },
|
|
||||||
Self::E(_) => { todo!() },
|
|
||||||
Self::SW(_) => { todo!() },
|
|
||||||
Self::S(_) => { todo!() },
|
|
||||||
Self::SE(_) => { todo!() },
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Render<Tui> + Layout<Tui>> Render<Tui> for Align<T> {
|
impl<T: Widget<Engine = Tui>> Widget for Align<T> {
|
||||||
|
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]> {
|
fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> {
|
||||||
self.layout(to.area())?
|
self.layout(to.area())?
|
||||||
.map(|area|to.with_area(area.x(), area.y(), area.w(), area.h()))
|
.map(|area|to.with_area(area.x(), area.y(), area.w(), area.h()))
|
||||||
.map(|to|match self {
|
.map(|to|self.inner().render(to))
|
||||||
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))
|
|
||||||
.transpose()
|
.transpose()
|
||||||
.map(|x|x.flatten())
|
.map(|x|x.flatten())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,11 @@ impl Demo<Tui> {
|
||||||
}));
|
}));
|
||||||
Self { index: 0, items }
|
Self { index: 0, items }
|
||||||
}
|
}
|
||||||
fn content <'a> (&'a self) -> impl Layout<Tui> + 'a {
|
}
|
||||||
|
|
||||||
|
impl<E: Engine> Content for Demo<E> {
|
||||||
|
type Engine = E;
|
||||||
|
fn content (&self) -> impl Widget<Engine = E> {
|
||||||
Align::Center(Layers(&[
|
Align::Center(Layers(&[
|
||||||
&Outset::WH(2, 1, FillBg(Color::Rgb(0,128,128))),
|
&Outset::WH(2, 1, FillBg(Color::Rgb(0,128,128))),
|
||||||
&Layers(&[
|
&Layers(&[
|
||||||
|
|
@ -35,18 +39,6 @@ impl Demo<Tui> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Layout<Tui> for Demo<Tui> {
|
|
||||||
fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> {
|
|
||||||
self.content().layout(area)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Render<Tui> for Demo<Tui> {
|
|
||||||
fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> {
|
|
||||||
self.content().render(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Handle<Tui> for Demo<Tui> {
|
impl Handle<Tui> for Demo<Tui> {
|
||||||
fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
|
fn handle (&mut self, from: &Tui) -> Perhaps<bool> {
|
||||||
match from.event() {
|
match from.event() {
|
||||||
|
|
@ -62,7 +54,7 @@ impl Handle<Tui> for Demo<Tui> {
|
||||||
};
|
};
|
||||||
Ok(Some(true))
|
Ok(Some(true))
|
||||||
},
|
},
|
||||||
_ => Ok(None)
|
_ => Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue