wip: final simplify

This commit is contained in:
facile pop culture reference 2026-07-05 18:46:22 +03:00
parent 90ebae0f26
commit 0b9e9c0696
21 changed files with 607 additions and 544 deletions

View file

@ -1,14 +1,30 @@
use crate::*;
pub use crate::space::*;
mod view;
pub use self::view::*;
mod thunk;
pub use self::thunk::*;
mod screen;
pub use self::screen::*;
/// Output target.
///
/// ```
/// use tengri::{*, draw::*};
///
/// struct TestOut<T: Screen<Unit = u16>>(T);
///
/// impl<T: Screen<Unit = u16>> Screen for TestOut {
/// type Unit = u16;
/// fn show <D: Draw<Self> + ?Sized> (&mut self, _: D) {
/// println!("placed");
/// ()
/// }
/// }
///
/// impl_draw!(|self: String, to: TestOut<u16>|{
/// to.area_mut().set_w(self.len() as u16);
/// });
/// ```
pub trait Screen: Xy<Self::Unit> + Wh<Self::Unit> + Send + Sync + Sized {
type Unit: Coord;
/// Render drawable in subarea specified by `area`
fn show <'t, T: Draw<Self>> (&mut self, content: T) -> Perhaps<XYWH<Self::Unit>>;
}
/// Implement the [Draw] trait for a particular drawable and [Screen].
///
@ -22,7 +38,7 @@ pub use self::screen::*;
#[macro_export] macro_rules! impl_draw ((|
$self:ident:$Self:ty, $to:ident:$To:ty
|$draw:block)=>{ impl Draw<$To> for $Self {
fn draw ($self, $to: &mut $To) -> Usually<XYWH<u16>> $draw
fn draw ($self, $to: &mut $To) -> Usually<XYWH<<$To as Screen>::Unit>> $draw
} });
/// Drawable that supports dynamic dispatch.
@ -48,29 +64,94 @@ pub use self::screen::*;
/// ```
pub trait Draw<S: Screen> {
fn draw (self, to: &mut S) -> Usually<XYWH<S::Unit>>;
fn layout (&self, area: XYWH<S::Unit>) -> Perhaps<XYWH<S::Unit>> {
Ok(Some(area))
}
}
impl<S: Screen> Draw<S> for () {
fn draw (self, __: &mut S) -> Usually<XYWH<S::Unit>> {
Ok(Default::default())
}
}
impl<S: Screen, D: Draw<S>> Draw<S> for &D {
fn draw (self, __: &mut S) -> Usually<XYWH<S::Unit>> {
todo!()
}
}
impl<S: Screen, D: Draw<S>> Draw<S> for Option<D> {
fn draw (self, __: &mut S) -> Usually<XYWH<S::Unit>> {
todo!()
}
}
impl<S: Screen, D: Draw<S>> Draw<S> for RwLock<D> {
fn draw (self, __: &mut S) -> Usually<XYWH<S::Unit>> {
todo!()
fn draw (self, to: &mut S) -> Usually<XYWH<S::Unit>> {
self.map(|it|it.draw(to)).transpose().map(Option::unwrap_or_default)
}
}
//impl<S: Screen, D: Draw<S>> Draw<S> for RwLock<D> {
//fn draw (self, __: &mut S) -> Usually<XYWH<S::Unit>> {
//todo!()
//}
//}
//impl<T: Screen, D: Draw<T>> Draw<T> for Arc<D> {
//fn draw (self, __: &mut T) -> Usually<XYWH<T::Unit>> {
//todo!()
//}
//}
/// Emit a [Draw]able.
///
/// Speculative. How to avoid conflicts with [Draw] proper?
pub trait View<T: Screen> {
fn view (&self) -> impl Draw<T>;
}
impl<T: Screen, V: View<T>> Draw<T> for &V {
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>> {
self.view().draw(to)
}
}
/// Because we can't implement [Draw] for `F: FnOnce...` without conflicts.
pub struct Thunk<T: Screen, F: FnOnce(&mut T)->Usually<XYWH<T::Unit>>>(
pub F,
std::marker::PhantomData<T>
);
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)
}
}
/// Basic [Draw]able closure.
///
/// ```
/// # use tengri::{draw::*, term::*};
/// # fn test () -> impl tengri::draw::Draw<tengri::term::Tui> {
/// thunk(|to: &mut Tui|Ok(to.1))
/// # }
/// ```
pub const fn thunk <T: Screen, F: FnOnce(&mut T)->Usually<XYWH<T::Unit>>> (
draw: F
) -> Thunk<T, F> {
Thunk(draw, std::marker::PhantomData)
}
/// Only render when condition is true.
///
/// ```
/// # use tengri::{draw::*, term::*};
/// # fn test () -> impl tengri::draw::Draw<tengri::term::Tui> {
/// when(true, "Yes")
/// # }
/// ```
pub const fn when <T: Screen> (condition: bool, draw: impl Draw<T>) -> impl Draw<T> {
thunk(move|to: &mut T|if condition { draw.draw(to) } else { Ok(Default::default()) })
}
/// Render one thing if a condition is true and another false.
///
/// ```
/// # use tengri::{draw::*, term::*};
/// # fn test () -> impl tengri::draw::Draw<tengri::term::Tui> {
/// either(true, "Yes", "No")
/// # }
/// ```
pub const fn either <T: Screen> (condition: bool, a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
thunk(move|to: &mut T|if condition { a.draw(to) } else { b.draw(to) })
}