mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-07-17 15:56:57 +02:00
wip: impl_draw, optional drawing
This commit is contained in:
parent
0b9e9c0696
commit
bf16288884
12 changed files with 213 additions and 229 deletions
43
src/draw.rs
43
src/draw.rs
|
|
@ -35,11 +35,18 @@ pub trait Screen: Xy<Self::Unit> + Wh<Self::Unit> + Send + Sync + Sized {
|
||||||
/// todo!("your draw logic")
|
/// todo!("your draw logic")
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export] macro_rules! impl_draw ((|
|
#[macro_export] macro_rules! impl_draw (
|
||||||
|
($(<$($T:ident: $Trait:path,)+>)?|
|
||||||
|
$self:ident:$Self:path, $to:ident:$To:ty
|
||||||
|
|$draw:block)=>{ impl$(<$($T:$Trait),+>)? Draw<$To> for $Self {
|
||||||
|
fn draw ($self, $to: &mut $To) -> Perhaps<XYWH<<$To as Screen>::Unit>> $draw
|
||||||
|
} };
|
||||||
|
($(<$($T:ident: $Trait:path,)+>)?|
|
||||||
$self:ident:$Self:ty, $to:ident:$To:ty
|
$self:ident:$Self:ty, $to:ident:$To:ty
|
||||||
|$draw:block)=>{ impl Draw<$To> for $Self {
|
|$draw:block)=>{ impl$(<$($T:$Trait),+>)? Draw<$To> for $Self {
|
||||||
fn draw ($self, $to: &mut $To) -> Usually<XYWH<<$To as Screen>::Unit>> $draw
|
fn draw ($self, $to: &mut $To) -> Perhaps<XYWH<<$To as Screen>::Unit>> $draw
|
||||||
} });
|
} }
|
||||||
|
);
|
||||||
|
|
||||||
/// Drawable that supports dynamic dispatch.
|
/// Drawable that supports dynamic dispatch.
|
||||||
///
|
///
|
||||||
|
|
@ -57,38 +64,36 @@ pub trait Screen: Xy<Self::Unit> + Wh<Self::Unit> + Send + Sync + Sized {
|
||||||
/// use tengri::{*, draw::*, term::*};
|
/// use tengri::{*, draw::*, term::*};
|
||||||
/// struct MyWidget(bool);
|
/// struct MyWidget(bool);
|
||||||
/// impl Draw<Tui> for MyWidget {
|
/// impl Draw<Tui> for MyWidget {
|
||||||
/// fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
/// fn draw (self, to: &mut Tui) -> Perhaps<XYWH<u16>> {
|
||||||
/// todo!("your draw logic")
|
/// todo!("your draw logic")
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub trait Draw<S: Screen> {
|
pub trait Draw<S: Screen> {
|
||||||
fn draw (self, to: &mut S) -> Usually<XYWH<S::Unit>>;
|
fn draw (self, to: &mut S) -> Perhaps<XYWH<S::Unit>>;
|
||||||
fn layout (&self, area: XYWH<S::Unit>) -> Perhaps<XYWH<S::Unit>> {
|
fn layout (&self, area: XYWH<S::Unit>) -> Perhaps<XYWH<S::Unit>> {
|
||||||
Ok(Some(area))
|
Ok(Some(area))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Screen> Draw<S> for () {
|
impl<S: Screen> Draw<S> for () {
|
||||||
fn draw (self, __: &mut S) -> Usually<XYWH<S::Unit>> {
|
fn draw (self, _: &mut S) -> Perhaps<XYWH<S::Unit>> {
|
||||||
Ok(Default::default())
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Screen, D: Draw<S>> Draw<S> for Option<D> {
|
impl_draw!(<S: Screen, D: Draw<S>,>|self: Option<D>, to: S|{
|
||||||
fn draw (self, to: &mut S) -> Usually<XYWH<S::Unit>> {
|
|
||||||
self.map(|it|it.draw(to)).transpose().map(Option::unwrap_or_default)
|
self.map(|it|it.draw(to)).transpose().map(Option::unwrap_or_default)
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
|
||||||
//impl<S: Screen, D: Draw<S>> Draw<S> for RwLock<D> {
|
//impl<S: Screen, D: Draw<S>> Draw<S> for RwLock<D> {
|
||||||
//fn draw (self, __: &mut S) -> Usually<XYWH<S::Unit>> {
|
//fn draw (self, __: &mut S) -> Perhaps<XYWH<S::Unit>> {
|
||||||
//todo!()
|
//todo!()
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//impl<T: Screen, D: Draw<T>> Draw<T> for Arc<D> {
|
//impl<T: Screen, D: Draw<T>> Draw<T> for Arc<D> {
|
||||||
//fn draw (self, __: &mut T) -> Usually<XYWH<T::Unit>> {
|
//fn draw (self, __: &mut T) -> Perhaps<XYWH<T::Unit>> {
|
||||||
//todo!()
|
//todo!()
|
||||||
//}
|
//}
|
||||||
//}
|
//}
|
||||||
|
|
@ -101,19 +106,19 @@ pub trait View<T: Screen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Screen, V: View<T>> Draw<T> for &V {
|
impl<T: Screen, V: View<T>> Draw<T> for &V {
|
||||||
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
fn draw (self, to: &mut T) -> Perhaps<XYWH<T::Unit>> {
|
||||||
self.view().draw(to)
|
self.view().draw(to)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Because we can't implement [Draw] for `F: FnOnce...` without conflicts.
|
/// 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 struct Thunk<T: Screen, F: FnOnce(&mut T)->Perhaps<XYWH<T::Unit>>>(
|
||||||
pub F,
|
pub F,
|
||||||
std::marker::PhantomData<T>
|
std::marker::PhantomData<T>
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<T: Screen, F: FnOnce(&mut T)->Usually<XYWH<T::Unit>>> Draw<T> for Thunk<T, F> {
|
impl<T: Screen, F: FnOnce(&mut T)->Perhaps<XYWH<T::Unit>>> Draw<T> for Thunk<T, F> {
|
||||||
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
fn draw (self, to: &mut T) -> Perhaps<XYWH<T::Unit>> {
|
||||||
(self.0)(to)
|
(self.0)(to)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -126,7 +131,7 @@ impl<T: Screen, F: FnOnce(&mut T)->Usually<XYWH<T::Unit>>> Draw<T> for Thunk<T,
|
||||||
/// thunk(|to: &mut Tui|Ok(to.1))
|
/// thunk(|to: &mut Tui|Ok(to.1))
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn thunk <T: Screen, F: FnOnce(&mut T)->Usually<XYWH<T::Unit>>> (
|
pub const fn thunk <T: Screen, F: FnOnce(&mut T)->Perhaps<XYWH<T::Unit>>> (
|
||||||
draw: F
|
draw: F
|
||||||
) -> Thunk<T, F> {
|
) -> Thunk<T, F> {
|
||||||
Thunk(draw, std::marker::PhantomData)
|
Thunk(draw, std::marker::PhantomData)
|
||||||
|
|
|
||||||
33
src/eval.rs
33
src/eval.rs
|
|
@ -114,22 +114,23 @@ pub fn eval_view <'a, O: Screen + 'a, S> (
|
||||||
).draw(output),
|
).draw(output),
|
||||||
|
|
||||||
// Second `frags.next()` calls returns the namespace member.
|
// Second `frags.next()` calls returns the namespace member.
|
||||||
Some("bsp") => eval_enum!(
|
Some("bsp") => {
|
||||||
"bsp", output, state, frags.next(), arg0, Split {
|
let direction = eval_enum!("bsp", output, state, frags.next(), arg0, Split {
|
||||||
"n" => North, "s" => South, "e" => East, "w" => West, "a" => Above, "b" => Below
|
"n" => North, "s" => South, "e" => East, "w" => West, "a" => Above, "b" => Below
|
||||||
}
|
});
|
||||||
).half(
|
direction.half(
|
||||||
thunk(move|output: &mut O|state.interpret(output, &arg0)),
|
thunk(move|output: &mut O|state.interpret(output, &arg0)),
|
||||||
thunk(move|output: &mut O|state.interpret(output, &arg1)),
|
thunk(move|output: &mut O|state.interpret(output, &arg1)),
|
||||||
).draw(output),
|
).draw(output)
|
||||||
|
},
|
||||||
|
|
||||||
Some("align") => eval_enum!(
|
Some("align") => {
|
||||||
"align", output, state, frags.next(), arg0, Origin {
|
let alignment = eval_enum!("align", output, state, frags.next(), arg0, Origin {
|
||||||
"c" => C, "n" => N, "s" => S, "e" => E, "w" => W, "x" => X, "y" => Y
|
"c" => C, "n" => N, "s" => S, "e" => E, "w" => W, "x" => X, "y" => Y
|
||||||
}
|
});
|
||||||
).align(
|
let content = thunk(move|output: &mut O|state.interpret(output, &arg0));
|
||||||
thunk(move|output: &mut O|state.interpret(output, &arg0))
|
align(alignment, content).draw(output)
|
||||||
).draw(output),
|
},
|
||||||
|
|
||||||
Some("exact") => eval_xy!(
|
Some("exact") => eval_xy!(
|
||||||
"exact", expr, head, output, state, frags.next(),
|
"exact", expr, head, output, state, frags.next(),
|
||||||
|
|
@ -191,11 +192,11 @@ pub fn eval_view_tui <'a, S> (
|
||||||
let arg0 = args.head();
|
let arg0 = args.head();
|
||||||
let tail0 = args.tail();
|
let tail0 = args.tail();
|
||||||
let arg1 = tail0.head();
|
let arg1 = tail0.head();
|
||||||
Ok(Some(match frags.next() {
|
match frags.next() {
|
||||||
|
|
||||||
Some("text") => {
|
Some("text") => {
|
||||||
if let Some(src) = args?.src()? {
|
if let Some(src) = args?.src()? {
|
||||||
output.show(src)?
|
output.show(src)
|
||||||
} else {
|
} else {
|
||||||
return Ok(None)
|
return Ok(None)
|
||||||
}
|
}
|
||||||
|
|
@ -208,7 +209,7 @@ pub fn eval_view_tui <'a, S> (
|
||||||
state.interpret(output, &arg1)?;
|
state.interpret(output, &arg1)?;
|
||||||
// FIXME?: don't max out the used area?
|
// FIXME?: don't max out the used area?
|
||||||
Ok(output.area().into())
|
Ok(output.area().into())
|
||||||
})))?
|
})))
|
||||||
},
|
},
|
||||||
|
|
||||||
Some("bg") => {
|
Some("bg") => {
|
||||||
|
|
@ -218,10 +219,10 @@ pub fn eval_view_tui <'a, S> (
|
||||||
state.interpret(output, &arg1)?;
|
state.interpret(output, &arg1)?;
|
||||||
// FIXME?: don't max out the used area?
|
// FIXME?: don't max out the used area?
|
||||||
Ok(output.area().into())
|
Ok(output.area().into())
|
||||||
})))?
|
})))
|
||||||
},
|
},
|
||||||
|
|
||||||
_ => return Ok(None)
|
_ => return Ok(None)
|
||||||
|
|
||||||
}))
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ use crate::*;
|
||||||
|
|
||||||
mod align; pub use self::align::*;
|
mod align; pub use self::align::*;
|
||||||
mod area; pub use self::area::*;
|
mod area; pub use self::area::*;
|
||||||
mod origin; pub use self::origin::*;
|
|
||||||
mod split; pub use self::split::*;
|
mod split; pub use self::split::*;
|
||||||
|
|
||||||
pub enum Layout<T: Screen, X: Into<Option<T::Unit>>, I: Draw<T>> {
|
pub enum Layout<T: Screen, X: Into<Option<T::Unit>>, I: Draw<T>> {
|
||||||
|
|
@ -21,12 +20,11 @@ pub enum Layout<T: Screen, X: Into<Option<T::Unit>>, I: Draw<T>> {
|
||||||
ClipWH(X, X, I),
|
ClipWH(X, X, I),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl_draw!(<
|
||||||
T: Screen,
|
T: Screen,
|
||||||
X: Into<Option<T::Unit>>,
|
X: Into<Option<T::Unit>>,
|
||||||
I: Draw<T>
|
I: Draw<T>,
|
||||||
> Draw<T> for Layout<T, X, I> {
|
>|self: Layout<T, X, I>, to: T|{
|
||||||
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
|
||||||
use Layout::*;
|
use Layout::*;
|
||||||
match self {
|
match self {
|
||||||
__(_) => unreachable!(),
|
__(_) => unreachable!(),
|
||||||
|
|
@ -83,5 +81,4 @@ impl<
|
||||||
it.draw(to)
|
it.draw(to)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
pub struct Align<T>(Option<Origin>, T);
|
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use tengri::*;
|
/// use tengri::*;
|
||||||
/// let _ = align(None, "unaligned");
|
/// let _ = align(None, "unaligned");
|
||||||
|
|
@ -11,3 +9,7 @@ pub struct Align<T>(Option<Origin>, T);
|
||||||
pub fn align <S: Screen, T: Draw<S>, U: Into<Option<Origin>>> (origin: U, it: T) -> Align<T> {
|
pub fn align <S: Screen, T: Draw<S>, U: Into<Option<Origin>>> (origin: U, it: T) -> Align<T> {
|
||||||
Align(origin.into(), it)
|
Align(origin.into(), it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Align<T>(Option<Origin>, T);
|
||||||
|
|
||||||
|
impl_draw!(<S: Screen, T: Draw<S>,>|self: Align<T>, to: S|{ todo!() });
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
pub struct Area<S: Screen, T: Draw<S>>(Option<XYWH<S::Unit>>, T);
|
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use tengri::*;
|
/// use tengri::*;
|
||||||
/// let _ = area(None, "unareaed");
|
/// let _ = area(None, "unareaed");
|
||||||
|
|
@ -13,3 +11,7 @@ pub fn area <S: Screen, T: Draw<S>, U: Into<Option<XYWH<S::Unit>>>> (
|
||||||
) -> Area<S, T> {
|
) -> Area<S, T> {
|
||||||
Area(origin.into(), it)
|
Area(origin.into(), it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Area<S: Screen, T: Draw<S>>(Option<XYWH<S::Unit>>, T);
|
||||||
|
|
||||||
|
impl_draw!(<S: Screen, T: Draw<S>,>|self: Area<S, T>, to: S|{ todo!() });
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
use super::*;
|
|
||||||
|
|
||||||
/// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,3 +5,4 @@ mod coord; pub use self::coord::*;
|
||||||
mod iter; pub use self::iter::*;
|
mod iter; pub use self::iter::*;
|
||||||
mod sizer; pub use self::sizer::*;
|
mod sizer; pub use self::sizer::*;
|
||||||
mod xywh; pub use self::xywh::*;
|
mod xywh; pub use self::xywh::*;
|
||||||
|
mod lrtb; pub use self::lrtb::*;
|
||||||
|
|
|
||||||
47
src/space/lrtb.rs
Normal file
47
src/space/lrtb.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
use crate::*;
|
||||||
|
use Origin::*;
|
||||||
|
|
||||||
|
impl<N: Coord, T: Xywh<N>> Lrtb<N> for T {}
|
||||||
|
|
||||||
|
pub trait Lrtb<N: Coord>: Xywh<N> {
|
||||||
|
fn lrtb (&self) -> [N;4] {
|
||||||
|
// FIXME: factor origin
|
||||||
|
[self.x(), self.y(), self.x()+self.w(), self.y()+self.h()]
|
||||||
|
}
|
||||||
|
fn iter_x (&self) -> impl Iterator<Item = N> where Self: HasOrigin {
|
||||||
|
self.x_west()..self.x_east()
|
||||||
|
}
|
||||||
|
fn x_west (&self) -> N where Self: HasOrigin {
|
||||||
|
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: HasOrigin {
|
||||||
|
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: HasOrigin {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn iter_y (&self) -> impl Iterator<Item = N> where Self: HasOrigin {
|
||||||
|
self.y_north()..self.y_south()
|
||||||
|
}
|
||||||
|
fn y_north (&self) -> N where Self: HasOrigin {
|
||||||
|
let a = self.origin();
|
||||||
|
let h = self.h();
|
||||||
|
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: HasOrigin {
|
||||||
|
let a = self.origin();
|
||||||
|
let h = self.h();
|
||||||
|
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: HasOrigin {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,28 @@ use super::*;
|
||||||
use Origin::*;
|
use Origin::*;
|
||||||
use Split::*;
|
use Split::*;
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Xy<N: Coord> {
|
pub trait Xy<N: Coord> {
|
||||||
fn x (&self) -> N;
|
fn x (&self) -> N;
|
||||||
fn y (&self) -> N;
|
fn y (&self) -> N;
|
||||||
|
|
@ -17,59 +39,16 @@ pub trait Xywh<N: Coord>: Xy<N> + Wh<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Lrtb<N: Coord> {
|
pub trait Wide<N: Coord>: Xy<N> {
|
||||||
// FIXME: factor origin
|
|
||||||
fn lrtb (&self) -> [N;4] {
|
|
||||||
[self.x(), self.y(), self.x()+self.w(), self.y()+self.h()]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Wide<N: Coord> {
|
|
||||||
fn w (&self) -> N { N::zero() }
|
fn w (&self) -> N { N::zero() }
|
||||||
fn w_min (&self) -> N { self.w() }
|
fn w_min (&self) -> N { self.w() }
|
||||||
fn w_max (&self) -> N { self.w() }
|
fn w_max (&self) -> N { self.w() }
|
||||||
fn iter_x (&self) -> impl Iterator<Item = N> where Self: HasOrigin {
|
|
||||||
self.x_west()..self.x_east()
|
|
||||||
}
|
|
||||||
fn x_west (&self) -> N where Self: HasOrigin {
|
|
||||||
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: HasOrigin {
|
|
||||||
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: HasOrigin {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Tall<N: Coord> {
|
pub trait Tall<N: Coord> {
|
||||||
fn h (&self) -> N { N::zero() }
|
fn h (&self) -> N { N::zero() }
|
||||||
fn h_min (&self) -> N { self.h() }
|
fn h_min (&self) -> N { self.h() }
|
||||||
fn h_max (&self) -> N { self.h() }
|
fn h_max (&self) -> N { self.h() }
|
||||||
fn iter_y (&self) -> impl Iterator<Item = N> where Self: HasOrigin {
|
|
||||||
self.y_north()..self.y_south()
|
|
||||||
}
|
|
||||||
fn y_north (&self) -> N where Self: HasOrigin {
|
|
||||||
let a = self.origin();
|
|
||||||
let h = self.h();
|
|
||||||
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: HasOrigin {
|
|
||||||
let a = self.origin();
|
|
||||||
let h = self.h();
|
|
||||||
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: HasOrigin {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Point with size.
|
/// Point with size.
|
||||||
|
|
|
||||||
|
|
@ -325,13 +325,8 @@ impl Coord for u16 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Draw<Tui> for u64 {
|
impl_draw!(|self: u64, _to: Tui|{ todo!() });
|
||||||
fn draw (self, _to: &mut Tui) -> Usually<XYWH<u16>> { todo!() }
|
impl_draw!(|self: f64, _to: Tui|{ todo!() });
|
||||||
}
|
|
||||||
|
|
||||||
impl Draw<Tui> for f64 {
|
|
||||||
fn draw (self, _to: &mut Tui) -> Usually<XYWH<u16>> { todo!() }
|
|
||||||
}
|
|
||||||
|
|
||||||
mod phat {
|
mod phat {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ pub const fn border (on: bool, style: impl BorderStyle, draw: impl Draw<Tui>) ->
|
||||||
to.blit(&style.border_e(), x + w - 1, y, style.style());
|
to.blit(&style.border_e(), x + w - 1, y, style.style());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(XYWH(x, y, w, h))
|
Ok(Some(XYWH(x, y, w, h)))
|
||||||
}));
|
}));
|
||||||
above(outline, content)
|
above(outline, content)
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +48,7 @@ macro_rules! border {
|
||||||
#[derive(Copy, Clone)] pub struct $T(pub bool, pub Style);
|
#[derive(Copy, Clone)] pub struct $T(pub bool, pub Style);
|
||||||
//impl Layout<Tui> for $T {}
|
//impl Layout<Tui> for $T {}
|
||||||
impl Draw<Tui> for $T {
|
impl Draw<Tui> for $T {
|
||||||
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
fn draw (self, to: &mut Tui) -> Perhaps<XYWH<u16>> {
|
||||||
when(self.enabled(), thunk(|to: &mut Tui|BorderStyle::draw(self, to))).draw(to)
|
when(self.enabled(), thunk(|to: &mut Tui|BorderStyle::draw(self, to))).draw(to)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
44
src/text.rs
44
src/text.rs
|
|
@ -3,40 +3,19 @@ pub(crate) use ::unicode_width::*;
|
||||||
|
|
||||||
#[cfg(feature = "term")] mod impl_term {
|
#[cfg(feature = "term")] mod impl_term {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::term::Tui;
|
use crate::*;
|
||||||
use ratatui::prelude::Position;
|
use ratatui::prelude::Position;
|
||||||
|
|
||||||
impl Draw<Tui> for &str {
|
impl_draw!(|self: String, to: Tui|{self.as_str().draw(to)});
|
||||||
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
impl_draw!(|self: std::sync::Arc<str>, to: Tui|{self.as_ref().draw(to)});
|
||||||
|
impl_draw!(|self: &std::sync::Arc<str>, to: Tui|{self.as_ref().draw(to)});
|
||||||
|
impl_draw!(|self: &str, to: Tui|{
|
||||||
let XYWH(x, y, w, ..) = to.1.centered_xy([width_chars_max(to.w(), self), 1]);
|
let XYWH(x, y, w, ..) = to.1.centered_xy([width_chars_max(to.w(), self), 1]);
|
||||||
to.text(&self, x, y, w)
|
to.text(&self, x, y, w)
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
|
||||||
impl Draw<Tui> for String {
|
impl_draw!(<T: AsRef<str>,>|self: TrimString<T>, to: Tui|{self.as_ref().draw(to)});
|
||||||
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
impl_draw!(<T: AsRef<str>,>|self: TrimStringRef<'_, T>, to: Tui|{
|
||||||
self.as_str().draw(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Draw<Tui> for std::sync::Arc<str> {
|
|
||||||
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
|
||||||
self.as_ref().draw(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Draw<Tui> for &std::sync::Arc<str> {
|
|
||||||
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
|
||||||
self.as_ref().draw(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: AsRef<str>> Draw<Tui> for TrimString<T> {
|
|
||||||
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> { self.as_ref().draw(to) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: AsRef<str>> Draw<Tui> for TrimStringRef<'_, T> {
|
|
||||||
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
|
||||||
let XYWH(x, y, w, ..) = to.1;
|
let XYWH(x, y, w, ..) = to.1;
|
||||||
let mut width: u16 = 1;
|
let mut width: u16 = 1;
|
||||||
let mut chars = self.1.as_ref().chars();
|
let mut chars = self.1.as_ref().chars();
|
||||||
|
|
@ -52,14 +31,13 @@ pub(crate) use ::unicode_width::*;
|
||||||
}
|
}
|
||||||
let XYWH(x, y, w, ..) = XYWH(to.x(), to.y(), to.w().min(self.0).min(self.1.as_ref().width() as u16), to.h());
|
let XYWH(x, y, w, ..) = XYWH(to.x(), to.y(), to.w().min(self.0).min(self.1.as_ref().width() as u16), to.h());
|
||||||
to.text(&self.as_ref(), x, y, w)
|
to.text(&self.as_ref(), x, y, w)
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
|
||||||
impl Tui {
|
impl Tui {
|
||||||
/// Write a line of text
|
/// Write a line of text
|
||||||
///
|
///
|
||||||
/// TODO: do a paragraph (handle newlines)
|
/// TODO: do a paragraph (handle newlines)
|
||||||
pub fn text (&mut self, text: &impl AsRef<str>, x0: u16, y: u16, max_width: u16) -> Usually<XYWH<u16>> {
|
pub fn text (&mut self, text: &impl AsRef<str>, x0: u16, y: u16, max_width: u16) -> Perhaps<XYWH<u16>> {
|
||||||
let text = text.as_ref();
|
let text = text.as_ref();
|
||||||
let mut string_width: u16 = 0;
|
let mut string_width: u16 = 0;
|
||||||
for character in text.chars() {
|
for character in text.chars() {
|
||||||
|
|
@ -75,7 +53,7 @@ pub(crate) use ::unicode_width::*;
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(XYWH(x0, y, string_width, 1))
|
Ok(Some(XYWH(x0, y, string_width, 1)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue