move Layout trait to separate module
Some checks failed
/ build (push) Has been cancelled

- output: impl Layout for Measure, FieldH, FieldV
- tui: enable #[feature(trait_alias)]
- tui: define some trait aliases
This commit is contained in:
🪞👃🪞 2025-09-09 20:59:07 +03:00
parent 90fc869e14
commit 731f4a971e
13 changed files with 166 additions and 147 deletions

View file

@ -1,111 +1,32 @@
use crate::*; use crate::*;
pub trait HasContent<O: Out> { fn content (&self) -> impl Content<O>; }
pub trait Content<O: Out>: Draw<O> + Layout<O> {} pub trait Content<O: Out>: Draw<O> + Layout<O> {}
impl<O: Out, T: Draw<O> + Layout<O>> Content<O> for T {} impl<O: Out, T: Draw<O> + Layout<O>> Content<O> for T {}
impl<'a, O: Out> AsRef<dyn Draw<O> + 'a> for dyn Content<O> + 'a { fn as_ref (&self) -> &(dyn Draw<O> + 'a) { self } }
impl<'a, O: Out> AsRef<dyn Layout<O> + 'a> for dyn Content<O> + 'a { fn as_ref (&self) -> &(dyn Layout<O> + 'a) { self } } impl<'a, O: Out> AsRef<dyn Draw<O> + 'a> for dyn Content<O> + 'a {
/// Drawable with dynamic dispatch. fn as_ref (&self) -> &(dyn Draw<O> + 'a) { self }
pub trait Draw<O: Out> { fn draw (&self, to: &mut O); }
impl<O: Out> Draw<O> for () { fn draw (&self, to: &mut O) {} }
impl<O: Out> Draw<O> for fn(&mut O) { fn draw (&self, to: &mut O) { (*self)(to) } }
impl<O: Out> Draw<O> for Box<dyn Draw<O>> { fn draw (&self, to: &mut O) { (**self).draw(to) } }
impl<O: Out, D: Draw<O>> Draw<O> for &D { fn draw (&self, to: &mut O) { (*self).draw(to) } }
impl<O: Out, D: Draw<O>> Draw<O> for &mut D { fn draw (&self, to: &mut O) { (**self).draw(to) } }
impl<O: Out, D: Draw<O>> Draw<O> for Option<D> { fn draw (&self, to: &mut O) { if let Some(draw) = self { draw.draw(to) } } }
/// Drawable area of display.
pub trait Layout<O: Out> {
fn x (&self, to: O::Area) -> O::Unit { to.x() }
fn y (&self, to: O::Area) -> O::Unit { to.y() }
fn min_w (&self, to: O::Area) -> O::Unit { 0.into() }
fn max_w (&self, to: O::Area) -> O::Unit { to.w() }
fn w (&self, to: O::Area) -> O::Unit {
to.w().max(self.min_w(to)).min(self.max_w(to))
}
fn min_h (&self, to: O::Area) -> O::Unit { 0.into() }
fn max_h (&self, to: O::Area) -> O::Unit { to.h() }
fn h (&self, to: O::Area) -> O::Unit {
to.h().max(self.min_h(to)).min(self.max_h(to))
}
fn layout (&self, to: O::Area) -> O::Area {
[self.x(to), self.y(to), self.w(to), self.h(to)].into()
}
} }
impl<O: Out> Layout<O> for () { impl<'a, O: Out> AsRef<dyn Layout<O> + 'a> for dyn Content<O> + 'a {
fn x (&self, a: O::Area) -> O::Unit { a.x() } fn as_ref (&self) -> &(dyn Layout<O> + 'a) { self }
fn y (&self, a: O::Area) -> O::Unit { a.y() }
fn w (&self, _: O::Area) -> O::Unit { 0.into() }
fn min_w (&self, _: O::Area) -> O::Unit { 0.into() }
fn max_w (&self, _: O::Area) -> O::Unit { 0.into() }
fn h (&self, _: O::Area) -> O::Unit { 0.into() }
fn min_h (&self, _: O::Area) -> O::Unit { 0.into() }
fn max_h (&self, _: O::Area) -> O::Unit { 0.into() }
fn layout (&self, a: O::Area) -> O::Area { [a.x(), a.y(), 0.into(), 0.into()].into() }
} }
impl<O: Out, L: Layout<O>> Layout<O> for &L { pub trait HasContent<O: Out> {
fn x (&self, a: O::Area) -> O::Unit { (*self).x(a) } fn content (&self) -> impl Content<O>;
fn y (&self, a: O::Area) -> O::Unit { (*self).y(a) }
fn w (&self, a: O::Area) -> O::Unit { (*self).w(a) }
fn min_w (&self, a: O::Area) -> O::Unit { (*self).min_w(a) }
fn max_w (&self, a: O::Area) -> O::Unit { (*self).max_w(a) }
fn h (&self, a: O::Area) -> O::Unit { (*self).h(a) }
fn min_h (&self, a: O::Area) -> O::Unit { (*self).min_h(a) }
fn max_h (&self, a: O::Area) -> O::Unit { (*self).max_h(a) }
fn layout (&self, a: O::Area) -> O::Area { (*self).layout(a) }
} }
impl<O: Out, L: Layout<O>> Layout<O> for &mut L {
fn x (&self, a: O::Area) -> O::Unit { (**self).x(a) } pub struct Bounded<O: Out, D>(pub O::Area, pub D);
fn y (&self, a: O::Area) -> O::Unit { (**self).y(a) } impl<O: Out, D: Content<O>> HasContent<O> for Bounded<O, D> {
fn w (&self, a: O::Area) -> O::Unit { (**self).w(a) } fn content (&self) -> impl Content<O> { &self.1 }
fn min_w (&self, a: O::Area) -> O::Unit { (**self).min_w(a) }
fn max_w (&self, a: O::Area) -> O::Unit { (**self).max_w(a) }
fn h (&self, a: O::Area) -> O::Unit { (**self).h(a) }
fn min_h (&self, a: O::Area) -> O::Unit { (**self).min_h(a) }
fn max_h (&self, a: O::Area) -> O::Unit { (**self).max_h(a) }
fn layout (&self, a: O::Area) -> O::Area { (**self).layout(a) }
} }
impl<O: Out> Layout<O> for Box<dyn Layout<O>> { impl<O: Out, T: Draw<O>> Draw<O> for Bounded<O, T> {
fn x (&self, a: O::Area) -> O::Unit { (**self).x(a) } fn draw (&self, to: &mut O) {
fn y (&self, a: O::Area) -> O::Unit { (**self).y(a) } let area = to.area();
fn w (&self, a: O::Area) -> O::Unit { (**self).w(a) } *to.area_mut() = self.0;
fn min_w (&self, a: O::Area) -> O::Unit { (**self).min_w(a) } self.1.draw(to);
fn max_w (&self, a: O::Area) -> O::Unit { (**self).max_w(a) } *to.area_mut() = area;
fn h (&self, a: O::Area) -> O::Unit { (**self).h(a) }
fn min_h (&self, a: O::Area) -> O::Unit { (**self).min_h(a) }
fn max_h (&self, a: O::Area) -> O::Unit { (**self).max_h(a) }
fn layout (&self, a: O::Area) -> O::Area { (**self).layout(a) }
}
impl<O: Out, L: Layout<O>> Layout<O> for Option<L> {
fn x (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.x(to)).unwrap_or(to.x())
}
fn y (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.y(to)).unwrap_or(to.y())
}
fn min_w (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.min_w(to)).unwrap_or(0.into())
}
fn max_w (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.max_w(to)).unwrap_or(0.into())
}
fn w (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.w(to)).unwrap_or(0.into())
}
fn min_h (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.min_h(to)).unwrap_or(0.into())
}
fn max_h (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.max_h(to)).unwrap_or(0.into())
}
fn h (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.h(to)).unwrap_or(0.into())
}
fn layout (&self, to: O::Area) -> O::Area {
self.as_ref().map(|c|c.layout([self.x(to), self.y(to), self.w(to), self.h(to)].into()))
.unwrap_or([to.x(), to.y(), 0.into(), 0.into()].into())
} }
} }

View file

@ -1,27 +1,10 @@
use crate::*; use crate::*;
pub struct Bound<O: Out, D>(pub O::Area, pub D); /// Drawable with dynamic dispatch.
pub trait Draw<O: Out> { fn draw (&self, to: &mut O); }
impl<O: Out, D: Content<O>> HasContent<O> for Bound<O, D> { impl<O: Out> Draw<O> for () { fn draw (&self, to: &mut O) {} }
fn content (&self) -> &impl Content<O> { &self.1 } impl<O: Out> Draw<O> for fn(&mut O) { fn draw (&self, to: &mut O) { (*self)(to) } }
} impl<O: Out> Draw<O> for Box<dyn Draw<O>> { fn draw (&self, to: &mut O) { (**self).draw(to) } }
impl<O: Out, D: Draw<O>> Draw<O> for &D { fn draw (&self, to: &mut O) { (*self).draw(to) } }
impl<O: Out, T> Layout<O> for Bound<O, T> { impl<O: Out, D: Draw<O>> Draw<O> for &mut D { fn draw (&self, to: &mut O) { (**self).draw(to) } }
fn x (&self, _: O::Area) -> O::Unit { self.0.x() } impl<O: Out, D: Draw<O>> Draw<O> for Option<D> { fn draw (&self, to: &mut O) { if let Some(draw) = self { draw.draw(to) } } }
fn y (&self, _: O::Area) -> O::Unit { self.0.y() }
fn w (&self, _: O::Area) -> O::Unit { self.0.w() }
fn min_w (&self, _: O::Area) -> O::Unit { self.0.w() }
fn max_w (&self, _: O::Area) -> O::Unit { self.0.w() }
fn h (&self, _: O::Area) -> O::Unit { self.0.h() }
fn min_h (&self, _: O::Area) -> O::Unit { self.0.w() }
fn max_h (&self, _: O::Area) -> O::Unit { self.0.w() }
}
impl<O: Out, T: Draw<O>> Draw<O> for Bound<O, T> {
fn draw (&self, to: &mut O) {
let area = to.area();
*to.area_mut() = self.0;
self.1.draw(to);
*to.area_mut() = area;
}
}

View file

@ -8,3 +8,101 @@ mod layout_pad; pub use self::layout_pad::*;
mod layout_move; pub use self::layout_move::*; mod layout_move; pub use self::layout_move::*;
mod layout_size; pub use self::layout_size::*; mod layout_size; pub use self::layout_size::*;
mod layout_stack; //pub use self::layout_stack::*; mod layout_stack; //pub use self::layout_stack::*;
/// Drawable area of display.
pub trait Layout<O: Out> {
fn x (&self, to: O::Area) -> O::Unit { to.x() }
fn y (&self, to: O::Area) -> O::Unit { to.y() }
fn min_w (&self, to: O::Area) -> O::Unit { 0.into() }
fn max_w (&self, to: O::Area) -> O::Unit { to.w() }
fn w (&self, to: O::Area) -> O::Unit {
to.w().max(self.min_w(to)).min(self.max_w(to))
}
fn min_h (&self, to: O::Area) -> O::Unit { 0.into() }
fn max_h (&self, to: O::Area) -> O::Unit { to.h() }
fn h (&self, to: O::Area) -> O::Unit {
to.h().max(self.min_h(to)).min(self.max_h(to))
}
fn layout (&self, to: O::Area) -> O::Area {
[self.x(to), self.y(to), self.w(to), self.h(to)].into()
}
}
impl<O: Out> Layout<O> for () {
fn x (&self, a: O::Area) -> O::Unit { a.x() }
fn y (&self, a: O::Area) -> O::Unit { a.y() }
fn w (&self, _: O::Area) -> O::Unit { 0.into() }
fn min_w (&self, _: O::Area) -> O::Unit { 0.into() }
fn max_w (&self, _: O::Area) -> O::Unit { 0.into() }
fn h (&self, _: O::Area) -> O::Unit { 0.into() }
fn min_h (&self, _: O::Area) -> O::Unit { 0.into() }
fn max_h (&self, _: O::Area) -> O::Unit { 0.into() }
fn layout (&self, a: O::Area) -> O::Area { [a.x(), a.y(), 0.into(), 0.into()].into() }
}
impl<O: Out, L: Layout<O>> Layout<O> for &L {
fn x (&self, a: O::Area) -> O::Unit { (*self).x(a) }
fn y (&self, a: O::Area) -> O::Unit { (*self).y(a) }
fn w (&self, a: O::Area) -> O::Unit { (*self).w(a) }
fn min_w (&self, a: O::Area) -> O::Unit { (*self).min_w(a) }
fn max_w (&self, a: O::Area) -> O::Unit { (*self).max_w(a) }
fn h (&self, a: O::Area) -> O::Unit { (*self).h(a) }
fn min_h (&self, a: O::Area) -> O::Unit { (*self).min_h(a) }
fn max_h (&self, a: O::Area) -> O::Unit { (*self).max_h(a) }
fn layout (&self, a: O::Area) -> O::Area { (*self).layout(a) }
}
impl<O: Out, L: Layout<O>> Layout<O> for &mut L {
fn x (&self, a: O::Area) -> O::Unit { (**self).x(a) }
fn y (&self, a: O::Area) -> O::Unit { (**self).y(a) }
fn w (&self, a: O::Area) -> O::Unit { (**self).w(a) }
fn min_w (&self, a: O::Area) -> O::Unit { (**self).min_w(a) }
fn max_w (&self, a: O::Area) -> O::Unit { (**self).max_w(a) }
fn h (&self, a: O::Area) -> O::Unit { (**self).h(a) }
fn min_h (&self, a: O::Area) -> O::Unit { (**self).min_h(a) }
fn max_h (&self, a: O::Area) -> O::Unit { (**self).max_h(a) }
fn layout (&self, a: O::Area) -> O::Area { (**self).layout(a) }
}
impl<O: Out> Layout<O> for Box<dyn Layout<O>> {
fn x (&self, a: O::Area) -> O::Unit { (**self).x(a) }
fn y (&self, a: O::Area) -> O::Unit { (**self).y(a) }
fn w (&self, a: O::Area) -> O::Unit { (**self).w(a) }
fn min_w (&self, a: O::Area) -> O::Unit { (**self).min_w(a) }
fn max_w (&self, a: O::Area) -> O::Unit { (**self).max_w(a) }
fn h (&self, a: O::Area) -> O::Unit { (**self).h(a) }
fn min_h (&self, a: O::Area) -> O::Unit { (**self).min_h(a) }
fn max_h (&self, a: O::Area) -> O::Unit { (**self).max_h(a) }
fn layout (&self, a: O::Area) -> O::Area { (**self).layout(a) }
}
impl<O: Out, L: Layout<O>> Layout<O> for Option<L> {
fn x (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.x(to)).unwrap_or(to.x())
}
fn y (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.y(to)).unwrap_or(to.y())
}
fn min_w (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.min_w(to)).unwrap_or(0.into())
}
fn max_w (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.max_w(to)).unwrap_or(0.into())
}
fn w (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.w(to)).unwrap_or(0.into())
}
fn min_h (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.min_h(to)).unwrap_or(0.into())
}
fn max_h (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.max_h(to)).unwrap_or(0.into())
}
fn h (&self, to: O::Area) -> O::Unit {
self.as_ref().map(|c|c.h(to)).unwrap_or(0.into())
}
fn layout (&self, to: O::Area) -> O::Area {
self.as_ref().map(|c|c.layout([self.x(to), self.y(to), self.w(to), self.h(to)].into()))
.unwrap_or([to.x(), to.y(), 0.into(), 0.into()].into())
}
}

View file

@ -47,7 +47,7 @@ impl<T> Align<T> {
#[inline] pub const fn se (a: T) -> Self { Self(Alignment::SE, a) } #[inline] pub const fn se (a: T) -> Self { Self(Alignment::SE, a) }
} }
impl<O: Out, T: Content<O>> Draw<O> for Align<T> { impl<O: Out, T: Content<O>> Draw<O> for Align<T> {
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), &self.1).draw(to) } fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), &self.1).draw(to) }
} }
impl<O: Out, T: Layout<O>> Layout<O> for Align<T> { impl<O: Out, T: Layout<O>> Layout<O> for Align<T> {
fn x (&self, to: O::Area) -> O::Unit { fn x (&self, to: O::Area) -> O::Unit {

View file

@ -15,7 +15,7 @@ impl<O: Out, T: Layout<O>> Layout<O> for When<O, T> {
impl<O: Out, T: Content<O>> Draw<O> for When<O, T> { impl<O: Out, T: Content<O>> Draw<O> for When<O, T> {
fn draw (&self, to: &mut O) { fn draw (&self, to: &mut O) {
let Self(cond, item, ..) = self; let Self(cond, item, ..) = self;
if *cond { Bound(self.layout(to.area()), item).draw(to) } if *cond { Bounded(self.layout(to.area()), item).draw(to) }
} }
} }
@ -37,7 +37,7 @@ impl<E: Out, A: Content<E>, B: Content<E>> Draw<E> for Either<E, A, B> {
fn draw (&self, to: &mut E) { fn draw (&self, to: &mut E) {
let Self(cond, a, b, ..) = self; let Self(cond, a, b, ..) = self;
let area = self.layout(to.area()); let area = self.layout(to.area());
if *cond { Bound(area, a).draw(to) } else { Bound(area, b).draw(to) } if *cond { Bounded(area, a).draw(to) } else { Bounded(area, b).draw(to) }
} }
} }

View file

@ -9,7 +9,7 @@ impl<U: Coordinate, T> Push<U, T> {
#[inline] pub fn dy (&self) -> U { match self { Self::Y(y, ..) | Self::XY(_, y, _) => *y, Self::X(_, _) => 0.into() } } #[inline] pub fn dy (&self) -> U { match self { Self::Y(y, ..) | Self::XY(_, y, _) => *y, Self::X(_, _) => 0.into() } }
} }
impl<O: Out, T: Content<O>> Draw<O> for Push<O::Unit, T> { impl<O: Out, T: Content<O>> Draw<O> for Push<O::Unit, T> {
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) } fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
} }
impl<O: Out, T: Layout<O>> Layout<O> for Push<O::Unit, T> { impl<O: Out, T: Layout<O>> Layout<O> for Push<O::Unit, T> {
fn x (&self, area: O::Area) -> O::Unit { area.x().plus(self.dx()) } fn x (&self, area: O::Area) -> O::Unit { area.x().plus(self.dx()) }
@ -25,7 +25,7 @@ impl<U: Coordinate, T> Pull<U, T> {
#[inline] pub fn dy (&self) -> U { match self { Self::Y(y, ..) | Self::XY(_, y, _) => *y, Self::X(_, _) => 0.into() } } #[inline] pub fn dy (&self) -> U { match self { Self::Y(y, ..) | Self::XY(_, y, _) => *y, Self::X(_, _) => 0.into() } }
} }
impl<O: Out, T: Content<O>> Draw<O> for Pull<O::Unit, T> { impl<O: Out, T: Content<O>> Draw<O> for Pull<O::Unit, T> {
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) } fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
} }
impl<O: Out, T: Layout<O>> Layout<O> for Pull<O::Unit, T> { impl<O: Out, T: Layout<O>> Layout<O> for Pull<O::Unit, T> {
fn x (&self, area: O::Area) -> O::Unit { area.x().minus(self.dx()) } fn x (&self, area: O::Area) -> O::Unit { area.x().minus(self.dx()) }

View file

@ -9,7 +9,7 @@ impl<U: Coordinate, T> Pad<U, T> {
#[inline] pub fn dy (&self) -> U { match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, } } #[inline] pub fn dy (&self) -> U { match self { X(_, _) => 0.into(), Y(y, _) => *y, XY(_, y, _) => *y, } }
} }
impl<O: Out, T: Content<O>> Draw<O> for Pad<O::Unit, T> { impl<O: Out, T: Content<O>> Draw<O> for Pad<O::Unit, T> {
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) } fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
} }
impl<O: Out, T: Layout<O>> Layout<O> for Pad<O::Unit, T> { impl<O: Out, T: Layout<O>> Layout<O> for Pad<O::Unit, T> {
fn x (&self, area: O::Area) -> O::Unit { fn x (&self, area: O::Area) -> O::Unit {

View file

@ -7,7 +7,7 @@ impl<A> Fill<A> {
#[inline] pub const fn dy (&self) -> bool { match self { Self::Y(_) | Self::XY(_) => true, _ => false } } #[inline] pub const fn dy (&self) -> bool { match self { Self::Y(_) | Self::XY(_) => true, _ => false } }
} }
impl<O: Out, T: Content<O>> Draw<O> for Fill<T> { impl<O: Out, T: Content<O>> Draw<O> for Fill<T> {
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) } fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
} }
impl<O: Out, T: Layout<O>> Layout<O> for Fill<T> { impl<O: Out, T: Layout<O>> Layout<O> for Fill<T> {
fn x (&self, area: O::Area) -> O::Unit { if self.dx() { area.x() } else { self.inner().x(area) } } fn x (&self, area: O::Area) -> O::Unit { if self.dx() { area.x() } else { self.inner().x(area) } }
@ -29,7 +29,7 @@ impl<U: Copy, A> Fixed<U, A> {
#[inline] pub const fn dy (&self) -> Option<U> { match self { Self::Y(y, _) | Self::XY(y, ..) => Some(*y), _ => None } } #[inline] pub const fn dy (&self) -> Option<U> { match self { Self::Y(y, _) | Self::XY(y, ..) => Some(*y), _ => None } }
} }
impl<O: Out, T: Content<O>> Draw<O> for Fixed<O::Unit, T> { impl<O: Out, T: Content<O>> Draw<O> for Fixed<O::Unit, T> {
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) } fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
} }
impl<O: Out, T: Layout<O>> Layout<O> for Fixed<O::Unit, T> { impl<O: Out, T: Layout<O>> Layout<O> for Fixed<O::Unit, T> {
fn w (&self, area: O::Area) -> O::Unit { self.dx().unwrap_or(self.inner().w(area)) } fn w (&self, area: O::Area) -> O::Unit { self.dx().unwrap_or(self.inner().w(area)) }
@ -49,7 +49,7 @@ impl<U: Copy, A> Max<U, A> {
#[inline] pub const fn dy (&self) -> Option<U> { match self { Self::Y(y, _) | Self::XY(y, ..) => Some(*y), _ => None } } #[inline] pub const fn dy (&self) -> Option<U> { match self { Self::Y(y, _) | Self::XY(y, ..) => Some(*y), _ => None } }
} }
impl<O: Out, T: Content<O>> Draw<O> for Max<O::Unit, T> { impl<O: Out, T: Content<O>> Draw<O> for Max<O::Unit, T> {
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) } fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
} }
impl<E: Out, T: Layout<E>> Layout<E> for Max<E::Unit, T> { impl<E: Out, T: Layout<E>> Layout<E> for Max<E::Unit, T> {
fn layout (&self, area: E::Area) -> E::Area { fn layout (&self, area: E::Area) -> E::Area {
@ -71,7 +71,7 @@ impl<U: Copy, A> Min<U, A> {
#[inline] pub const fn dy (&self) -> Option<U> { match self { Self::Y(y, _) | Self::XY(y, ..) => Some(*y), _ => None } } #[inline] pub const fn dy (&self) -> Option<U> { match self { Self::Y(y, _) | Self::XY(y, ..) => Some(*y), _ => None } }
} }
impl<O: Out, T: Content<O>> Draw<O> for Min<O::Unit, T> { impl<O: Out, T: Content<O>> Draw<O> for Min<O::Unit, T> {
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) } fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
} }
impl<E: Out, T: Layout<E>> Layout<E> for Min<E::Unit, T> { impl<E: Out, T: Layout<E>> Layout<E> for Min<E::Unit, T> {
fn layout (&self, area: E::Area) -> E::Area { fn layout (&self, area: E::Area) -> E::Area {
@ -93,7 +93,7 @@ impl<U: Copy + Default, A> Expand<U, A> {
#[inline] pub const fn dy (&self) -> Option<U> { match self { Self::Y(y, _) | Self::XY(y, ..) => Some(*y), _ => None } } #[inline] pub const fn dy (&self) -> Option<U> { match self { Self::Y(y, _) | Self::XY(y, ..) => Some(*y), _ => None } }
} }
impl<O: Out, T: Content<O>> Draw<O> for Expand<O::Unit, T> { impl<O: Out, T: Content<O>> Draw<O> for Expand<O::Unit, T> {
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) } fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
} }
impl<O: Out, T: Layout<O>> Layout<O> for Expand<O::Unit, T> { impl<O: Out, T: Layout<O>> Layout<O> for Expand<O::Unit, T> {
fn w (&self, to: O::Area) -> O::Unit { self.inner().w(to).plus(self.dx().unwrap_or_default()) } fn w (&self, to: O::Area) -> O::Unit { self.inner().w(to).plus(self.dx().unwrap_or_default()) }
@ -109,7 +109,7 @@ impl<U: Copy, A> Shrink<U, A> {
#[inline] pub const fn dy (&self) -> Option<U> { match self { Self::Y(y, _) | Self::XY(y, ..) => Some(*y), _ => None } } #[inline] pub const fn dy (&self) -> Option<U> { match self { Self::Y(y, _) | Self::XY(y, ..) => Some(*y), _ => None } }
} }
impl<O: Out, T: Content<O>> Draw<O> for Shrink<O::Unit, T> { impl<O: Out, T: Content<O>> Draw<O> for Shrink<O::Unit, T> {
fn draw (&self, to: &mut O) { Bound(self.layout(to.area()), self.inner()).draw(to) } fn draw (&self, to: &mut O) { Bounded(self.layout(to.area()), self.inner()).draw(to) }
} }
impl<E: Out, T: Layout<E>> Layout<E> for Shrink<E::Unit, T> { impl<E: Out, T: Layout<E>> Layout<E> for Shrink<E::Unit, T> {
fn layout (&self, to: E::Area) -> E::Area { fn layout (&self, to: E::Area) -> E::Area {

View file

@ -7,6 +7,7 @@
#![feature(const_option_ops)] #![feature(const_option_ops)]
#![feature(const_trait_impl)] #![feature(const_trait_impl)]
#![feature(const_default)] #![feature(const_default)]
#![feature(trait_alias)]
//#![feature(non_lifetime_binders)] //#![feature(non_lifetime_binders)]
pub(crate) use self::Direction::*; pub(crate) use self::Direction::*;

View file

@ -2,28 +2,30 @@ use crate::*;
/// A widget that tracks its render width and height /// A widget that tracks its render width and height
#[derive(Default)] #[derive(Default)]
pub struct Measure<E: Out> { pub struct Measure<O: Out> {
_engine: PhantomData<E>, _engine: PhantomData<O>,
pub x: Arc<AtomicUsize>, pub x: Arc<AtomicUsize>,
pub y: Arc<AtomicUsize>, pub y: Arc<AtomicUsize>,
} }
impl<E: Out> PartialEq for Measure<E> { impl<O: Out> PartialEq for Measure<O> {
fn eq (&self, other: &Self) -> bool { fn eq (&self, other: &Self) -> bool {
self.x.load(Relaxed) == other.x.load(Relaxed) && self.x.load(Relaxed) == other.x.load(Relaxed) &&
self.y.load(Relaxed) == other.y.load(Relaxed) self.y.load(Relaxed) == other.y.load(Relaxed)
} }
} }
impl<O: Out> Layout<O> for Measure<O> {}
// TODO: 🡘 🡙 ←🡙→ indicator to expand window when too small // TODO: 🡘 🡙 ←🡙→ indicator to expand window when too small
impl<E: Out> Draw<E> for Measure<E> { impl<O: Out> Draw<O> for Measure<O> {
fn draw (&self, to: &mut E) { fn draw (&self, to: &mut O) {
self.x.store(to.area().w().into(), Relaxed); self.x.store(to.area().w().into(), Relaxed);
self.y.store(to.area().h().into(), Relaxed); self.y.store(to.area().h().into(), Relaxed);
} }
} }
impl<E: Out> Clone for Measure<E> { impl<O: Out> Clone for Measure<O> {
fn clone (&self) -> Self { fn clone (&self) -> Self {
Self { Self {
_engine: Default::default(), _engine: Default::default(),
@ -33,7 +35,7 @@ impl<E: Out> Clone for Measure<E> {
} }
} }
impl<E: Out> std::fmt::Debug for Measure<E> { impl<O: Out> std::fmt::Debug for Measure<O> {
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
f.debug_struct("Measure") f.debug_struct("Measure")
.field("width", &self.x) .field("width", &self.x)
@ -42,7 +44,7 @@ impl<E: Out> std::fmt::Debug for Measure<E> {
} }
} }
impl<E: Out> Measure<E> { impl<O: Out> Measure<O> {
pub fn new () -> Self { pub fn new () -> Self {
Self { Self {
_engine: PhantomData::default(), _engine: PhantomData::default(),
@ -75,7 +77,7 @@ impl<E: Out> Measure<E> {
pub fn format (&self) -> Arc<str> { pub fn format (&self) -> Arc<str> {
format!("{}x{}", self.w(), self.h()).into() format!("{}x{}", self.w(), self.h()).into()
} }
pub fn of <T: Draw<E>> (&self, item: T) -> Bsp<Fill<&Self>, T> { pub fn of <T: Draw<O>> (&self, item: T) -> Bsp<Fill<&Self>, T> {
Bsp::b(Fill::XY(self), item) Bsp::b(Fill::XY(self), item)
} }
} }

View file

@ -1,4 +1,5 @@
#![feature(type_changing_struct_update)] #![feature(type_changing_struct_update)]
#![feature(trait_alias)]
#[cfg(test)] mod tui_test; #[cfg(test)] mod tui_test;
mod tui_engine; pub use self::tui_engine::*; mod tui_engine; pub use self::tui_engine::*;
mod tui_content; pub use self::tui_content::*; mod tui_content; pub use self::tui_content::*;

View file

@ -1,5 +1,12 @@
use crate::*; use crate::*;
impl<T: TuiContent, U: TuiContent> Draw<TuiOut> for FieldH<ItemTheme, T, U> {
fn draw (&self, to: &mut TuiOut) { to.place(&self.content()) }
}
impl<T: TuiContent, U: TuiContent> Draw<TuiOut> for FieldV<ItemTheme, T, U> {
fn draw (&self, to: &mut TuiOut) { to.place(&self.content()) }
}
// TODO: // TODO:
pub struct Field<T, U> { pub struct Field<T, U> {
pub direction: Direction, pub direction: Direction,

View file

@ -73,12 +73,18 @@ impl Tui {
} }
} }
pub trait TuiRun<R: Draw<TuiOut> + Handle<TuiIn> + 'static> { pub trait TuiDraw = Draw<TuiOut>;
pub trait TuiLayout = Layout<TuiOut>;
pub trait TuiContent = Content<TuiOut>;
pub trait TuiHandle = Handle<TuiIn>;
pub trait TuiWidget = TuiDraw + TuiHandle;
pub trait TuiRun<T: TuiWidget + 'static> {
/// Run an app in the main loop. /// Run an app in the main loop.
fn run (&self, state: &Arc<RwLock<R>>) -> Usually<()>; fn run (&self, state: &Arc<RwLock<T>>) -> Usually<()>;
} }
impl<T: Draw<TuiOut> + Handle<TuiIn> + Send + Sync + 'static> TuiRun<T> for Arc<RwLock<Tui>> { impl<T: TuiWidget + Send + Sync + 'static> TuiRun<T> for Arc<RwLock<Tui>> {
fn run (&self, state: &Arc<RwLock<T>>) -> Usually<()> { fn run (&self, state: &Arc<RwLock<T>>) -> Usually<()> {
let _input_thread = TuiIn::run_input(self, state, Duration::from_millis(100)); let _input_thread = TuiIn::run_input(self, state, Duration::from_millis(100));
self.write().unwrap().setup()?; self.write().unwrap().setup()?;