mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-07-17 15:56:57 +02:00
13e woo
This commit is contained in:
parent
5d627f7669
commit
eb899906f9
8 changed files with 627 additions and 728 deletions
501
src/draw.rs
501
src/draw.rs
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{*, lang::*, color::*};
|
||||
use crate::{*, lang::*, color::*, space::*};
|
||||
|
||||
/// Drawable that supports dynamic dispatch.
|
||||
///
|
||||
|
|
@ -8,7 +8,7 @@ use crate::{*, lang::*, color::*};
|
|||
/// impl Screen for TestScreen { type Unit = u16; }
|
||||
/// struct TestWidget(bool);
|
||||
/// impl Draw<TestScreen> for TestWidget {
|
||||
/// fn draw (&self, screen: &mut T) -> Usually<WH<u16>> {
|
||||
/// fn draw (&self, screen: &mut T) -> Usually<XYWH<u16>> {
|
||||
/// screen.0 |= self.0;
|
||||
/// }
|
||||
/// }
|
||||
|
|
@ -18,45 +18,45 @@ use crate::{*, lang::*, color::*};
|
|||
/// TestWidget(false).draw(&mut screen);
|
||||
/// ```
|
||||
pub trait Draw<T: Screen> {
|
||||
fn draw (&self, to: &mut T) -> Usually<WH<T::Unit>>;
|
||||
fn draw (&self, to: &mut T) -> Usually<XYWH<T::Unit>>;
|
||||
}
|
||||
impl<T: Screen> Draw<T> for () {
|
||||
fn draw (&self, __: &mut T) -> Usually<WH<T::Unit>> {
|
||||
fn draw (&self, __: &mut T) -> Usually<XYWH<T::Unit>> {
|
||||
Ok(Default::default())
|
||||
}
|
||||
}
|
||||
impl<T: Screen, D: Draw<T>> Draw<T> for &D {
|
||||
fn draw (&self, to: &mut T) -> Usually<WH<T::Unit>> {
|
||||
fn draw (&self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
||||
(*self).draw(to)
|
||||
}
|
||||
}
|
||||
impl<T: Screen, D: Draw<T>> Draw<T> for Arc<D> {
|
||||
fn draw (&self, to: &mut T) -> Usually<WH<T::Unit>> {
|
||||
fn draw (&self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
||||
(**self).draw(to)
|
||||
}
|
||||
}
|
||||
impl<T: Screen, D: Draw<T>> Draw<T> for RwLock<D> {
|
||||
fn draw (&self, to: &mut T) -> Usually<WH<T::Unit>> {
|
||||
fn draw (&self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
||||
self.read().unwrap().draw(to)
|
||||
}
|
||||
}
|
||||
impl<T: Screen, D: Draw<T>> Draw<T> for Option<D> {
|
||||
fn draw (&self, to: &mut T) -> Usually<WH<T::Unit>> {
|
||||
self.map(|draw|draw.draw(to)).transpose()?.flatten()
|
||||
fn draw (&self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
||||
Ok(self.as_ref().map(|draw|draw.draw(to)).transpose()?.unwrap_or_default())
|
||||
}
|
||||
}
|
||||
|
||||
/// Because we can't implement [Draw] for `F: FnOnce...` without conflicts.
|
||||
pub struct Thunk<T: Screen, F: FnOnce(&mut T)->Usually<WH<T::Unit>>>(
|
||||
pub struct Thunk<T: Screen, F: FnOnce(&mut T)->Usually<XYWH<T::Unit>>>(
|
||||
pub F,
|
||||
std::marker::PhantomData<T>
|
||||
);
|
||||
pub const fn thunk <T: Screen, F: FnOnce(&mut T)->Usually<WH<T::Unit>>> (draw: F) -> Thunk<T, F> {
|
||||
pub const fn thunk <T: Screen, F: FnOnce(&mut T)->Usually<XYWH<T::Unit>>> (draw: F) -> Thunk<T, F> {
|
||||
Thunk(draw, std::marker::PhantomData)
|
||||
}
|
||||
impl<T: Screen, F: FnOnce(&mut T)->Usually<WH<T::Unit>>> Draw<T> for Thunk<T, F> {
|
||||
fn draw (&self, to: &mut T) -> Usually<WH<T::Unit>> {
|
||||
(self.0)(to)
|
||||
impl<T: Screen, F: FnOnce(&mut T)->Usually<XYWH<T::Unit>>> Draw<T> for Thunk<T, F> {
|
||||
fn draw (&self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
||||
(&self.0)(to)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -82,447 +82,6 @@ pub const fn either <T: Screen> (condition: bool, a: impl Draw<T>, b: impl Draw<
|
|||
thunk(move|to: &mut T|if condition { a.draw(to) } else { b.draw(to) })
|
||||
}
|
||||
|
||||
/// Something that has `[0, 0]` at a particular point.
|
||||
pub trait HasOrigin {
|
||||
fn origin (&self) -> Origin;
|
||||
}
|
||||
impl<T: AsRef<Origin>> HasOrigin for T {
|
||||
fn origin (&self) -> Origin { self.as_ref() }
|
||||
}
|
||||
|
||||
/// Where is [0, 0] located?
|
||||
///
|
||||
/// ```
|
||||
/// use tengri::draw::Origin;
|
||||
/// let _ = Origin::NW.align(())
|
||||
/// ```
|
||||
#[cfg_attr(test, derive(Arbitrary))]
|
||||
#[derive(Debug, Copy, Clone, Default)] pub enum Origin {
|
||||
#[default] C, X, Y, NW, N, NE, E, SE, S, SW, W
|
||||
}
|
||||
impl Origin {
|
||||
pub fn align <T: Screen> (&self, a: impl Draw<T>) -> impl Draw<T> {
|
||||
align(*self, a)
|
||||
}
|
||||
}
|
||||
|
||||
/// ```
|
||||
/// use tengri::draw::{align, Origin::*};
|
||||
/// let _ = align(NW, "test");
|
||||
/// let _ = align(SE, "test");
|
||||
/// ```
|
||||
pub fn align <T: Screen> (origin: Origin, a: impl Draw<T>) -> impl Draw<T> {
|
||||
thunk(move|to: &mut T| { todo!() })
|
||||
}
|
||||
|
||||
/// A numeric type that can be used as coordinate.
|
||||
///
|
||||
/// FIXME: Replace with `num` crate?
|
||||
/// FIXME: Use AsRef/AsMut?
|
||||
///
|
||||
/// ```
|
||||
/// use tengri::draw::Coord;
|
||||
/// let a: u16 = Coord::zero();
|
||||
/// let b: u16 = a.plus(1);
|
||||
/// let c: u16 = a.minus(2);
|
||||
/// let d = a.atomic();
|
||||
/// ```
|
||||
pub trait Coord: Send + Sync + Copy
|
||||
+ Add<Self, Output=Self>
|
||||
+ Sub<Self, Output=Self>
|
||||
+ Mul<Self, Output=Self>
|
||||
+ Div<Self, Output=Self>
|
||||
+ Ord + PartialEq + Eq
|
||||
+ Debug + Display + Default
|
||||
+ From<u16> + Into<u16>
|
||||
+ Into<usize>
|
||||
+ Into<f64>
|
||||
+ std::iter::Step
|
||||
{
|
||||
/// Zero in own type.
|
||||
fn zero () -> Self { 0.into() }
|
||||
/// Addition.
|
||||
fn plus (self, other: Self) -> Self;
|
||||
/// Saturating subtraction.
|
||||
fn minus (self, other: Self) -> Self { if self >= other { self - other } else { 0.into() } }
|
||||
/// Convert to [AtomicUsize].
|
||||
fn atomic (self) -> AtomicUsize { AtomicUsize::new(self.into()) }
|
||||
}
|
||||
|
||||
/// A cardinal direction.
|
||||
#[cfg_attr(test, derive(Arbitrary))]
|
||||
#[derive(Copy, Clone, PartialEq, Debug, Default)] pub enum Split {
|
||||
North, South, East, West, Above, #[default] Below
|
||||
}
|
||||
|
||||
pub const fn east <T: Screen> (a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
Split::East.half(a, b)
|
||||
}
|
||||
pub const fn north <T: Screen> (a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
Split::North.half(a, b)
|
||||
}
|
||||
pub const fn west <T: Screen> (a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
Split::West.half(a, b)
|
||||
}
|
||||
pub const fn south <T: Screen> (a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
Split::South.half(a, b)
|
||||
}
|
||||
pub const fn above <T: Screen> (a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
Split::Above.half(a, b)
|
||||
}
|
||||
pub const fn below <T: Screen> (a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
Split::Below.half(a, b)
|
||||
}
|
||||
impl Split {
|
||||
/// ```
|
||||
/// use tengri::draw::Split::*;
|
||||
/// let _ = Above.bsp((), ());
|
||||
/// let _ = Below.bsp((), ());
|
||||
/// let _ = North.bsp((), ());
|
||||
/// let _ = South.bsp((), ());
|
||||
/// let _ = East.bsp((), ());
|
||||
/// let _ = West.bsp((), ());
|
||||
/// ```
|
||||
pub const fn half <T: Screen> (&self, a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
thunk(move|to: &mut T|{
|
||||
let (area_a, area_b) = to.xywh().split_half(self);
|
||||
let (origin_a, origin_b) = self.origins();
|
||||
match self {
|
||||
Self::Below => {
|
||||
to.place(area_b, &origin_b.align(b));
|
||||
to.place(area_a, &origin_a.align(a));
|
||||
},
|
||||
_ => {
|
||||
to.place(area_a, &origin_a.align(a));
|
||||
to.place(area_b, &origin_b.align(b));
|
||||
}
|
||||
}
|
||||
Ok(to.wh()) // FIXME: compute and return actually used area
|
||||
})
|
||||
}
|
||||
/// Newly split areas begin at the center of the split
|
||||
/// to maintain centeredness in the user's field of view.
|
||||
///
|
||||
/// Use [align] to override that and always start
|
||||
/// at the top, bottom, etc.
|
||||
///
|
||||
/// ```
|
||||
/// /*
|
||||
///
|
||||
/// Split east: Split south:
|
||||
/// | | | | A |
|
||||
/// | <-A|B-> | |---------|
|
||||
/// | | | | B |
|
||||
///
|
||||
/// */
|
||||
/// ```
|
||||
const fn origins (&self) -> (Origin, Origin) {
|
||||
use Origin::*;
|
||||
match self {
|
||||
Self::South => (S, N),
|
||||
Self::East => (E, W),
|
||||
Self::North => (N, S),
|
||||
Self::West => (W, E),
|
||||
Self::Above => (C, C),
|
||||
Self::Below => (C, C),
|
||||
}
|
||||
}
|
||||
/// Iterate over a collection of renderables:
|
||||
///
|
||||
/// ```
|
||||
/// use tengri::draw::{Origin::*, Split::*};
|
||||
/// let _ = Below.iter([
|
||||
/// NW.align(W(15).max(W(10).min("Leftbar"))),
|
||||
/// NE.align(W(12).max(W(10).min("Rightbar"))),
|
||||
/// Center.align(W(40).max(H(20.max("Center"))))
|
||||
/// ].iter(), |x|x);
|
||||
/// ```
|
||||
pub fn iter <T: Screen, U: Draw<T>, F: Fn(U)->dyn Draw<T>> (
|
||||
_items: impl Iterator<Item = U>, _cb: F
|
||||
) -> impl Draw<T> {
|
||||
thunk(move|_to: &mut T|{ todo!() })
|
||||
}
|
||||
}
|
||||
|
||||
/// Coordinate along horizontal axis.
|
||||
#[derive(Copy, Clone, Debug, Default)] pub struct X<N: Coord>(pub N);
|
||||
impl<N: Coord> X<N> {
|
||||
pub const fn push <T: Screen<Unit = N>> (x: N, a: impl Draw<T>) -> impl Draw<T> {
|
||||
a
|
||||
}
|
||||
pub const fn pull <T: Screen<Unit = N>> (x: N, a: impl Draw<T>) -> impl Draw<T> {
|
||||
a
|
||||
}
|
||||
}
|
||||
#[derive(Copy, Clone, Debug, Default)] pub struct W<N: Coord>(pub N);
|
||||
impl<N: Coord> W<N> {
|
||||
pub const fn max <T: Screen<Unit = N>> (w: Option<N>, a: impl Draw<T>) -> impl Draw<T> {
|
||||
WH::max(w, None, a)
|
||||
}
|
||||
pub const fn min <T: Screen<Unit = N>> (w: Option<N>, a: impl Draw<T>) -> impl Draw<T> {
|
||||
WH::min(w, None, a)
|
||||
}
|
||||
pub const fn exact <T: Screen<Unit = N>> (w: T::Unit, c: impl Draw<T>) -> impl Draw<T> {
|
||||
WH::exact(Some(w), None, c)
|
||||
}
|
||||
/// Shrink drawing area symmetrically.
|
||||
///
|
||||
/// ```
|
||||
/// let padded = tengri::W(3).pad("Hello");
|
||||
/// ```
|
||||
pub const fn pad <T: Screen<Unit = N>> (x: N, draw: impl Draw<T>)
|
||||
-> impl Draw<T>
|
||||
{
|
||||
thunk(move|to: &mut T|draw.draw(todo!()))
|
||||
}
|
||||
}
|
||||
#[derive(Copy, Clone, Debug, Default)] pub struct Y<N: Coord>(pub N);
|
||||
impl<N: Coord> Y<N> {
|
||||
pub const fn push <T: Screen<Unit = N>> (x: N, a: impl Draw<T>) -> impl Draw<T> {
|
||||
a
|
||||
}
|
||||
pub const fn pull <T: Screen<Unit = N>> (x: N, a: impl Draw<T>) -> impl Draw<T> {
|
||||
a
|
||||
}
|
||||
}
|
||||
#[derive(Copy, Clone, Debug, Default)] pub struct H<N: Coord>(pub N);
|
||||
impl<N: Coord> H<N> {
|
||||
pub const fn max <T: Screen<Unit = N>> (h: Option<N>, a: impl Draw<T>) -> impl Draw<T> {
|
||||
WH::max(None, h, a)
|
||||
}
|
||||
pub const fn min <T: Screen<Unit = N>> (h: Option<N>, a: impl Draw<T>) -> impl Draw<T> {
|
||||
WH::min(None, h, a)
|
||||
}
|
||||
pub const fn exact <T: Screen<Unit = N>> (h: T::Unit, c: impl Draw<T>) -> impl Draw<T> {
|
||||
WH::exact(None, Some(h), c)
|
||||
}
|
||||
/// Shrink drawing area symmetrically.
|
||||
///
|
||||
/// ```
|
||||
/// let padded = tengri::W::pad(3, "Hello");
|
||||
/// ```
|
||||
pub const fn pad <T: Screen<Unit = N>> (x: N, draw: impl Draw<T>) -> impl Draw<T> {
|
||||
thunk(move|to: &mut T|draw.draw(todo!()))
|
||||
}
|
||||
}
|
||||
/// An origin point (X, Y).
|
||||
///
|
||||
/// ```
|
||||
/// let xy = tengri::XY(0u16, 0);
|
||||
/// ```
|
||||
#[cfg_attr(test, derive(Arbitrary))] #[derive(Copy, Clone, Debug, Default, PartialEq)]
|
||||
pub struct XY<C: Coord>(pub C, pub C);
|
||||
impl<N: Coord> HasX<N> for XY<N> { fn x (&self) -> X<N> { X(self.0) } }
|
||||
impl<N: Coord> HasY<N> for XY<N> { fn y (&self) -> Y<N> { Y(self.1) } }
|
||||
impl<N: Coord> XY<N> {
|
||||
pub const fn push <T: Screen<Unit = N>> (&self, a: impl Draw<T>) -> impl Draw<T> {
|
||||
a
|
||||
}
|
||||
pub const fn pull <T: Screen<Unit = N>> (&self, a: impl Draw<T>) -> impl Draw<T> {
|
||||
a
|
||||
}
|
||||
}
|
||||
/// A size (Width, Height).
|
||||
///
|
||||
/// ```
|
||||
/// let wh = tengri::WH(0u16, 0);
|
||||
/// ```
|
||||
#[cfg_attr(test, derive(Arbitrary))] #[derive(Copy, Clone, Debug, Default, PartialEq)]
|
||||
pub struct WH<C: Coord>(pub C, pub C);
|
||||
impl<N: Coord> HasW<N> for WH<N> { fn w (&self) -> W<N> { W(self.0) } }
|
||||
impl<N: Coord> HasH<N> for WH<N> { fn h (&self) -> H<N> { H(self.1) } }
|
||||
impl<N: Coord> WH<N> {
|
||||
/// Shrink drawing area symmetrically.
|
||||
///
|
||||
/// ```
|
||||
/// let padded = tengri::WH(3, 5).pad("Hello");
|
||||
/// ```
|
||||
pub const fn pad <T: Screen<Unit = N>> (&self, draw: impl Draw<T>)
|
||||
-> impl Draw<T>
|
||||
{
|
||||
thunk(move|to: &mut T|draw.draw(todo!()))
|
||||
}
|
||||
|
||||
/// Only draw content if area is above a certain size.
|
||||
///
|
||||
/// ```
|
||||
/// let min = tengri::WH::min(3, 5, "Hello"); // 5x5
|
||||
/// ```
|
||||
pub const fn min <T: Screen<Unit = N>> (w: Option<N>, h: Option<N>, draw: impl Draw<T>)
|
||||
-> impl Draw<T>
|
||||
{
|
||||
thunk(move|to: &mut T|draw.draw(todo!()))
|
||||
}
|
||||
|
||||
/// Set the maximum width and/or height of the content.
|
||||
///
|
||||
/// ```
|
||||
/// let max = tengri::WH::max(Some(3), Some(5), "Hello");
|
||||
/// ```
|
||||
pub const fn max <T: Screen<Unit = N>> (w: Option<N>, h: Option<N>, draw: impl Draw<T>)
|
||||
-> impl Draw<T>
|
||||
{
|
||||
thunk(move|to: &mut T|draw.draw(todo!()))
|
||||
}
|
||||
|
||||
/// Set the maximum width and/or height of the content.
|
||||
///
|
||||
/// ```
|
||||
/// let exact = tengri::WH::exact(Some(3), Some(5), "Hello");
|
||||
/// ```
|
||||
pub const fn exact <T: Screen<Unit = N>> (w: Option<N>, h: Option<N>, draw: impl Draw<T>)
|
||||
-> impl Draw<T>
|
||||
{
|
||||
thunk(move|to: &mut T|draw.draw(todo!()))
|
||||
}
|
||||
|
||||
/// Limit size of drawing area
|
||||
/// ```
|
||||
/// let clipped = tengri::WH::clip(Some(3), Some(5), "Hello");
|
||||
/// ```
|
||||
pub const fn clip <T: Screen<Unit = N>> (w: Option<N>, h: Option<N>, draw: impl Draw<T>) -> impl Draw<T> {
|
||||
thunk(move|to: &mut T|draw.draw(todo!()))
|
||||
}
|
||||
}
|
||||
/// Point with size.
|
||||
///
|
||||
/// ```
|
||||
/// let xywh = tengri::XYWH(0u16, 0, 0, 0);
|
||||
/// assert_eq!(tengri::XYWH(10u16, 10, 20, 20).center(), tengri::XY(20, 20));
|
||||
/// ```
|
||||
///
|
||||
/// * [ ] TODO: origin field (determines at which corner/side is X0 Y0)
|
||||
///
|
||||
#[cfg_attr(test, derive(Arbitrary))] #[derive(Copy, Clone, Debug, Default, PartialEq)]
|
||||
pub struct XYWH<C: Coord>(pub C, pub C, pub C, pub C);
|
||||
impl<N: Coord> HasX<N> for XYWH<N> { fn x (&self) -> X<N> { X(self.0) } }
|
||||
impl<N: Coord> HasY<N> for XYWH<N> { fn y (&self) -> Y<N> { Y(self.1) } }
|
||||
impl<N: Coord> HasW<N> for XYWH<N> { fn w (&self) -> W<N> { W(self.2) } }
|
||||
impl<N: Coord> HasH<N> for XYWH<N> { fn h (&self) -> H<N> { H(self.3) } }
|
||||
impl<N: Coord> XYWH<N> {
|
||||
pub fn zero () -> Self {
|
||||
Self(0.into(), 0.into(), 0.into(), 0.into())
|
||||
}
|
||||
pub fn center (&self) -> XY<N> {
|
||||
let Self(x, y, w, h) = *self;
|
||||
XY(x.plus(w/2.into()), y.plus(h/2.into()))
|
||||
}
|
||||
pub fn centered (&self) -> XY<N> {
|
||||
let Self(x, y, w, h) = *self;
|
||||
XY(x.minus(w/2.into()), y.minus(h/2.into()))
|
||||
}
|
||||
pub fn centered_x (&self, n: N) -> Self {
|
||||
let Self(x, y, w, h) = *self;
|
||||
let x_center = (x.plus(w / 2.into())).minus(n / 2.into());
|
||||
let y_center = y.plus(h / 2.into());
|
||||
XYWH(x_center, y_center, n, 1.into())
|
||||
}
|
||||
pub fn centered_y (&self, n: N) -> Self {
|
||||
let Self(x, y, w, h) = *self;
|
||||
let x_center = x.plus(w / 2.into());
|
||||
let y_corner = (y.plus(h / 2.into())).minus(n / 2.into());
|
||||
XYWH(x_center, y_corner, 1.into(), n)
|
||||
}
|
||||
pub fn centered_xy (&self, [n, m]: [N;2]) -> Self {
|
||||
let Self(x, y, w, h) = *self;
|
||||
let x_center = (x.plus(w / 2.into())).minus(n / 2.into());
|
||||
let y_corner = (y.plus(h / 2.into())).minus(m / 2.into());
|
||||
XYWH(x_center, y_corner, n, m)
|
||||
}
|
||||
pub fn split_half (&self, direction: &Split) -> (Self, Self) {
|
||||
use Split::*;
|
||||
let XYWH(x, y, w, h) = self.xywh();
|
||||
match self {
|
||||
South => (XYWH(x, y, w, h - h / 2), XYWH(x, y + h / 2, w, h / 2)),
|
||||
East => (XYWH(x, y, w - w / 2, h), XYWH(x + w / 2, y, w / 2, h)),
|
||||
North => (XYWH(x, y + h / 2, w, h - h / 2), XYWH(x, y, w, h / 2)),
|
||||
West => (XYWH(x + w / 2, y, w - w / 2, h), XYWH(x, y, w / 2, h)),
|
||||
Above | Below => (XYWH(x, y, w, h), XYWH(x, y, w, h))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HasXYWH<N: Coord>: HasXY<N> + HasWH<N> {
|
||||
fn xywh (&self) -> XYWH<N>;
|
||||
}
|
||||
pub trait HasXY<N: Coord>: HasX<N> + HasY<N> {
|
||||
fn xy (&self) -> XY<N>;
|
||||
}
|
||||
pub trait HasWH<N: Coord>: HasX<N> + HasY<N> {
|
||||
fn wh (&self) -> WH<N>;
|
||||
}
|
||||
pub trait HasX<N: Coord> {
|
||||
fn x (&self) -> X<N>;
|
||||
fn iter_x (&self) -> impl Iterator<Item = N> where Self: HasW<N> + HasOrigin {
|
||||
self.x_west()..self.x_east()
|
||||
}
|
||||
fn x_west (&self) -> N where Self: HasW<N> + HasOrigin {
|
||||
use Origin::*;
|
||||
let w = self.w();
|
||||
let a = self.origin();
|
||||
let d = match a { NW|W|SW => 0.into(), N|X|C|Y|S => w/2.into(), NE|E|SE => w };
|
||||
self.x().minus(d)
|
||||
}
|
||||
fn x_east (&self) -> N where Self: HasW<N> + HasOrigin {
|
||||
use Origin::*;
|
||||
let w = self.w();
|
||||
let a = self.origin();
|
||||
let d = match a { NW|W|SW => w, N|X|C|Y|S => w/2.into(), NE|E|SE => 0.into() };
|
||||
self.x().plus(d)
|
||||
}
|
||||
fn x_center (&self) -> N where Self: HasW<N> + HasOrigin {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
pub trait HasY<N: Coord> {
|
||||
fn y (&self) -> Y<N>;
|
||||
fn iter_y (&self) -> impl Iterator<Item = N> where Self: HasH<N> + HasOrigin {
|
||||
self.y_north()..self.y_south()
|
||||
}
|
||||
fn y_north (&self) -> N where Self: HasH<N> + HasOrigin {
|
||||
let a = self.origin();
|
||||
let h = self.h();
|
||||
use Origin::*;
|
||||
let d = match a { NW|N|NE => 0.into(), W|X|C|Y|E => h/2.into(), SW|S|SE => h };
|
||||
self.y().minus(d)
|
||||
}
|
||||
fn y_south (&self) -> N where Self: HasH<N> + HasOrigin {
|
||||
let a = self.origin();
|
||||
let h = self.h();
|
||||
use Origin::*;
|
||||
let d = match a { NW|N|NE => h, W|X|C|Y|E => h/2.into(), SW|S|SE => 0.into() };
|
||||
self.y().plus(d)
|
||||
}
|
||||
fn y_center (&self) -> N where Self: HasH<N> + HasOrigin {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
pub trait HasW<N: Coord> {
|
||||
fn w (&self) -> W<N>;
|
||||
fn w_min (&self) -> W<N> { self.w() }
|
||||
fn w_max (&self) -> W<N> { self.w() }
|
||||
}
|
||||
pub trait HasH<N: Coord> {
|
||||
fn h (&self) -> H<N>;
|
||||
fn h_min (&self) -> H<N> { self.h() }
|
||||
fn h_max (&self) -> H<N> { self.h() }
|
||||
}
|
||||
impl<N: Coord, T: AsRef<X<N>>> HasX<N> for T {
|
||||
fn x (&self) -> X<N> { *self.as_ref() }
|
||||
}
|
||||
impl<N: Coord, T: AsRef<X<N>>> HasY<N> for T {
|
||||
fn y (&self) -> Y<N> { *self.as_ref() }
|
||||
}
|
||||
impl<N: Coord, T: HasX<N> + HasY<N>> HasXY<N> for T {
|
||||
fn xy (&self) -> XY<N> { XY(self.x(), self.y()) }
|
||||
}
|
||||
impl<N: Coord, T: HasX<N> + HasY<N>> HasWH<N> for T {
|
||||
fn wh (&self) -> WH<N> { WH(self.x(), self.h()) }
|
||||
}
|
||||
impl<N: Coord, T: HasXY<N> + HasWH<N>> HasXYWH<N> for T {
|
||||
fn xywh (&self) -> XYWH<N> { XYWH(self.x(), self.y(), self.w(), self.h()) }
|
||||
}
|
||||
|
||||
/// Output target.
|
||||
///
|
||||
/// ```
|
||||
|
|
@ -539,38 +98,18 @@ impl<N: Coord, T: HasXY<N> + HasWH<N>> HasXYWH<N> for T {
|
|||
/// }
|
||||
///
|
||||
/// impl Draw<Screen> for String {
|
||||
/// fn draw (&self, to: &mut TestOut) -> Usually<WH<u16>> {
|
||||
/// fn draw (&self, to: &mut TestOut) -> Usually<XYWH<u16>> {
|
||||
/// to.area_mut().set_w(self.len() as u16);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub trait Screen: HasXYWH<Self::Unit> + HasOrigin + Send + Sync + Sized {
|
||||
pub trait Screen: Space<Self::Unit> + Send + Sync + Sized {
|
||||
type Unit: Coord;
|
||||
/// Render drawable in area specified by `area`
|
||||
fn place <'t, T: Draw<Self> + ?Sized> (&mut self, area: impl HasWH<Self::Unit>, content: &'t T) {
|
||||
fn place <'t, T: Draw<Self> + ?Sized> (
|
||||
&mut self, content: &'t T, area: Option<XYWH<Self::Unit>>
|
||||
) {
|
||||
let area = area.unwrap_or_else(||self.xywh());
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Something that has a [Measure] of its rendered size.
|
||||
pub trait Measured <N: Coord> {}
|
||||
|
||||
/// Something that has a bounding box
|
||||
///
|
||||
/// ```
|
||||
/// use tengri::{Bounded, XYWH};
|
||||
/// let bounded: Bounded<tengri::Tui, _> = Bounded(0, 0 ,0 ,0 ,"");
|
||||
/// ```
|
||||
pub trait Bounding <N: Coord>: HasXY<N> + HasWH<N> + HasOrigin {
|
||||
}
|
||||
|
||||
//impl<O: Screen, T: Draw<O>> Draw<O> for Bounded<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;
|
||||
//}
|
||||
//}
|
||||
|
||||
// pub fn displace ...
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue