mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-07-17 15:56:57 +02:00
fokken wip
This commit is contained in:
parent
be14173126
commit
2dc501c184
11 changed files with 129 additions and 136 deletions
2
dizzle
2
dizzle
|
|
@ -1 +1 @@
|
||||||
Subproject commit e984fbb9fe8e588399744d50841d006454c16657
|
Subproject commit 2dbf9d8797a3642f69813be4ef3613836e061b94
|
||||||
68
src/draw.rs
68
src/draw.rs
|
|
@ -1,5 +1,5 @@
|
||||||
mod draw;
|
use crate::*;
|
||||||
pub use self::draw::*;
|
pub use crate::space::*;
|
||||||
|
|
||||||
mod view;
|
mod view;
|
||||||
pub use self::view::*;
|
pub use self::view::*;
|
||||||
|
|
@ -10,29 +10,57 @@ pub use self::thunk::*;
|
||||||
mod screen;
|
mod screen;
|
||||||
pub use self::screen::*;
|
pub use self::screen::*;
|
||||||
|
|
||||||
use crate::*;
|
/// Implement the [Draw] trait for a particular drawable and [Screen].
|
||||||
pub use crate::space::*;
|
|
||||||
|
|
||||||
/// Only render when condition is true.
|
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use tengri::draw::*;
|
/// use tengri::{*, draw::*, term::*};
|
||||||
/// # fn test () -> impl tengri::draw::Draw<tengri::term::Tui> {
|
/// struct MyDrawable;
|
||||||
/// when(true, "Yes")
|
/// impl_draw!(|self: MyDrawable, to: Tui|{
|
||||||
/// # }
|
/// todo!("your draw logic")
|
||||||
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn when <T: Screen> (condition: bool, draw: impl Draw<T>) -> impl Draw<T> {
|
#[macro_export] macro_rules! impl_draw ((|
|
||||||
thunk(move|to: &mut T|if condition { draw.draw(to) } else { Ok(Default::default()) })
|
$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
|
||||||
|
} });
|
||||||
|
|
||||||
/// Render one thing if a condition is true and another false.
|
/// Drawable that supports dynamic dispatch.
|
||||||
|
///
|
||||||
|
/// Drawables are composable, e.g. the [when] and [either] conditionals
|
||||||
|
/// or the layout constraints.
|
||||||
|
///
|
||||||
|
/// Drawables are consumable, i.e. the [Draw::draw] method receives an
|
||||||
|
/// owned `self` and does not return it, consuming the drawable.
|
||||||
|
///
|
||||||
|
/// To draw a thing multiple times, instead of explicitly constructing it
|
||||||
|
/// every time, implement the [View] trait instead, which will construct
|
||||||
|
/// a [Draw]able.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use tengri::draw::*;
|
/// use tengri::{*, draw::*, term::*};
|
||||||
/// # fn test () -> impl tengri::draw::Draw<tengri::term::Tui> {
|
/// struct MyWidget(bool);
|
||||||
/// either(true, "Yes", "No")
|
/// impl Draw<Tui> for MyWidget {
|
||||||
/// # }
|
/// fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
||||||
|
/// todo!("your draw logic")
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn either <T: Screen> (condition: bool, a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
pub trait Draw<T: Screen> {
|
||||||
thunk(move|to: &mut T|if condition { a.draw(to) } else { b.draw(to) })
|
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>>;
|
||||||
}
|
}
|
||||||
|
impl<T: Screen, D: Draw<T>> Draw<T> for &D {
|
||||||
|
fn draw (self, __: &mut T) -> Usually<XYWH<T::Unit>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<T: Screen, D: Draw<T>> Draw<T> for Option<D> {
|
||||||
|
fn draw (self, __: &mut T) -> Usually<XYWH<T::Unit>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//impl<T: Screen, D: Draw<T>> Draw<T> for Arc<D> {
|
||||||
|
//fn draw (self, __: &mut T) -> Usually<XYWH<T::Unit>> {
|
||||||
|
//todo!()
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
use super::*;
|
|
||||||
|
|
||||||
/// Implement the [Draw] trait for a particular drawable and [Screen].
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use tengri::{*, draw::*, term::*};
|
|
||||||
/// struct MyDrawable;
|
|
||||||
/// impl_draw!(|self: MyDrawable, to: Tui|{
|
|
||||||
/// todo!()
|
|
||||||
/// });
|
|
||||||
/// ```
|
|
||||||
#[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
|
|
||||||
} });
|
|
||||||
|
|
||||||
/// Drawable that supports dynamic dispatch.
|
|
||||||
///
|
|
||||||
/// Drawables are composable, e.g. the [when] and [either] conditionals
|
|
||||||
/// or the layout constraints.
|
|
||||||
///
|
|
||||||
/// Drawables are consumable, i.e. the [Draw::draw] method receives an
|
|
||||||
/// owned `self` and does not return it, consuming the drawable.
|
|
||||||
///
|
|
||||||
/// To draw a thing multiple times, instead of explicitly constructing it
|
|
||||||
/// every time, implement the [View] trait instead, which will construct
|
|
||||||
/// a [Draw]able.
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use tengri::{*, draw::*};
|
|
||||||
/// struct MyScreen(bool);
|
|
||||||
/// impl Screen for MyScreen { type Unit = u16; }
|
|
||||||
/// impl X<u16> for MyScreen { fn x (&self) -> u16 { 0 } }
|
|
||||||
/// impl Y<u16> for MyScreen { fn y (&self) -> u16 { 0 } }
|
|
||||||
/// struct MyWidget(bool);
|
|
||||||
/// impl Draw<MyScreen> for MyWidget {
|
|
||||||
/// fn draw (self, screen: &mut MyScreen) -> Usually<XYWH<u16>> {
|
|
||||||
/// screen.0 |= self.0;
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// let mut screen = MyScreen(false);
|
|
||||||
/// MyWidget(false).draw(&mut screen);
|
|
||||||
/// MyWidget(true).draw(&mut screen);
|
|
||||||
/// MyWidget(false).draw(&mut screen);
|
|
||||||
/// ```
|
|
||||||
pub trait Draw<T: Screen> {
|
|
||||||
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>>;
|
|
||||||
}
|
|
||||||
impl<T: Screen, D: Draw<T>> Draw<T> for &D {
|
|
||||||
fn draw (self, __: &mut T) -> Usually<XYWH<T::Unit>> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T: Screen, D: Draw<T>> Draw<T> for Option<D> {
|
|
||||||
fn draw (self, __: &mut T) -> Usually<XYWH<T::Unit>> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -9,7 +9,7 @@ use super::*;
|
||||||
///
|
///
|
||||||
/// impl<T: Screen<Unit = u16>> Screen for TestOut {
|
/// impl<T: Screen<Unit = u16>> Screen for TestOut {
|
||||||
/// type Unit = u16;
|
/// type Unit = u16;
|
||||||
/// fn place_at <D: Draw<Self> + ?Sized> (&mut self, area: T, _: D) {
|
/// fn show <D: Draw<Self> + ?Sized> (&mut self, area: T, _: D) {
|
||||||
/// println!("placed: {area:?}");
|
/// println!("placed: {area:?}");
|
||||||
/// ()
|
/// ()
|
||||||
/// }
|
/// }
|
||||||
|
|
@ -21,14 +21,6 @@ use super::*;
|
||||||
/// ```
|
/// ```
|
||||||
pub trait Screen: Space<Self::Unit> + Send + Sync + Sized {
|
pub trait Screen: Space<Self::Unit> + Send + Sync + Sized {
|
||||||
type Unit: Coord;
|
type Unit: Coord;
|
||||||
/// Render drawable in area.
|
|
||||||
fn place <'t, T: Draw<Self> + ?Sized> (&mut self, content: &'t T) {
|
|
||||||
self.place_at(self.xywh(), content)
|
|
||||||
}
|
|
||||||
/// Render drawable in subarea specified by `area`
|
/// Render drawable in subarea specified by `area`
|
||||||
fn place_at <'t, T: Draw<Self> + ?Sized> (
|
fn show <'t, T: Draw<Self>> (&mut self, area: XYWH<Self::Unit>, content: T);
|
||||||
&mut self, _area: XYWH<Self::Unit>, _content: &'t T
|
|
||||||
) {
|
|
||||||
unimplemented!("place_at")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,51 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub const fn thunk <T: Screen, F: FnOnce(&mut T)->Usually<XYWH<T::Unit>>> (draw: F) -> Thunk<T, F> {
|
|
||||||
Thunk(draw, std::marker::PhantomData)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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)->Usually<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)->Usually<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) -> Usually<XYWH<T::Unit>> {
|
||||||
(self.0)(to)
|
(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) })
|
||||||
|
}
|
||||||
|
|
|
||||||
21
src/eval.rs
21
src/eval.rs
|
|
@ -59,23 +59,16 @@ macro_rules! eval_enum ((
|
||||||
/// Interpret layout operation.
|
/// Interpret layout operation.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use tengri::{lang::*, draw::*, eval::*};
|
/// # use tengri::{lang::*, draw::*, eval::*, term::*};
|
||||||
/// struct Target { xywh: XYWH<u16> /*platform-specific*/}
|
|
||||||
/// impl tengri::Out for Target {
|
|
||||||
/// type Unit = u16;
|
|
||||||
/// fn area (&self) -> XYWH<u16> { self.xywh }
|
|
||||||
/// fn area_mut (&mut self) -> &mut XYWH<u16> { &mut self.xywh }
|
|
||||||
/// fn show <'t, T: Draw<Self> + ?Sized> (&mut self, area: XYWH<u16>, content: &'t T) {}
|
|
||||||
/// }
|
|
||||||
///
|
///
|
||||||
/// struct State {/*app-specific*/}
|
/// struct State {/*app-specific*/}
|
||||||
/// impl<'b> Namespace<'b, bool> for State {}
|
/// impl<'b> Namespace<'b, bool> for State {}
|
||||||
/// impl<'b> Namespace<'b, u16> for State {}
|
/// impl<'b> Namespace<'b, u16> for State {}
|
||||||
/// impl Interpret<Target, ()> for State {}
|
/// impl Interpret<Tui, XYWH<u16>> for State {}
|
||||||
///
|
///
|
||||||
/// # fn main () -> tengri::Usually<()> {
|
/// # fn main () -> tengri::Usually<()> {
|
||||||
/// let state = State {};
|
/// let state = State {};
|
||||||
/// let mut target = Target { xywh: Default::default() };
|
/// let mut target = Tui::new(80, 25);
|
||||||
/// eval_view(&state, &mut target, &"")?;
|
/// eval_view(&state, &mut target, &"")?;
|
||||||
/// eval_view(&state, &mut target, &"(when true (text hello))")?;
|
/// eval_view(&state, &mut target, &"(when true (text hello))")?;
|
||||||
/// eval_view(&state, &mut target, &"(either true (text hello) (text world))")?;
|
/// eval_view(&state, &mut target, &"(either true (text hello) (text world))")?;
|
||||||
|
|
@ -197,13 +190,15 @@ pub fn eval_view_tui <'a, S> (
|
||||||
match frags.next() {
|
match frags.next() {
|
||||||
|
|
||||||
Some("text") => {
|
Some("text") => {
|
||||||
if let Some(src) = args?.src()? { output.place(&src) }
|
if let Some(src) = args?.src()? {
|
||||||
|
output.show(output.xywh(), &src)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Some("fg") => {
|
Some("fg") => {
|
||||||
let arg0 = arg0?.expect("fg: expected arg 0 (color)");
|
let arg0 = arg0?.expect("fg: expected arg 0 (color)");
|
||||||
let color = Namespace::namespace(state, arg0)?.unwrap_or_else(||panic!("fg: {arg0:?}: not a color"));
|
let color = Namespace::namespace(state, arg0)?.unwrap_or_else(||panic!("fg: {arg0:?}: not a color"));
|
||||||
output.place(&fg(color, thunk(move|output: &mut Tui|{
|
output.show(output.xywh(), &fg(color, thunk(move|output: &mut Tui|{
|
||||||
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())
|
||||||
|
|
@ -213,7 +208,7 @@ pub fn eval_view_tui <'a, S> (
|
||||||
Some("bg") => {
|
Some("bg") => {
|
||||||
let arg0 = arg0?.expect("bg: expected arg 0 (color)");
|
let arg0 = arg0?.expect("bg: expected arg 0 (color)");
|
||||||
let color = Namespace::namespace(state, arg0)?.unwrap_or_else(||panic!("bg: {arg0:?}: not a color"));
|
let color = Namespace::namespace(state, arg0)?.unwrap_or_else(||panic!("bg: {arg0:?}: not a color"));
|
||||||
output.place(&bg(color, thunk(move|output: &mut Tui|{
|
output.show(output.xywh(), &bg(color, thunk(move|output: &mut Tui|{
|
||||||
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())
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ pub use ::dizzle::{Usually, Perhaps, impl_default};
|
||||||
// FIXME: support attrs (docstrings)
|
// FIXME: support attrs (docstrings)
|
||||||
$($Variant $({ $($arg: $Arg),* })?),*
|
$($Variant $({ $($arg: $Arg),* })?),*
|
||||||
}
|
}
|
||||||
impl ::tengri::dizzle::Act<$State> for $Command {
|
impl ::tengri::lang::Act<$State> for $Command {
|
||||||
fn act (&self, $state: &mut $State) -> Perhaps<Self> {
|
fn act (&self, $state: &mut $State) -> Perhaps<Self> {
|
||||||
match self {
|
match self {
|
||||||
$(Self::$Variant $({ $($arg),* })? => $body,)*
|
$(Self::$Variant $({ $($arg),* })? => $body,)*
|
||||||
|
|
|
||||||
11
src/space.rs
11
src/space.rs
|
|
@ -125,13 +125,17 @@ pub trait Space<N: Coord>: X<N> + Y<N> {
|
||||||
// FIXME: factor origin
|
// FIXME: factor origin
|
||||||
fn lrtb (&self) -> [N;4] { [self.x(), self.y(), self.x()+self.w(), self.y()+self.h()] }
|
fn lrtb (&self) -> [N;4] { [self.x(), self.y(), self.x()+self.w(), self.y()+self.h()] }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Coord, T: X<N> + Y<N>> Space<N> for T {}
|
impl<N: Coord, T: X<N> + Y<N>> Space<N> for T {}
|
||||||
|
|
||||||
pub const fn xy_push <T: Screen> (x: T::Unit, y: T::Unit, a: impl Draw<T>) -> impl Draw<T> {
|
pub const fn xy_push <T: Screen> (x: T::Unit, y: T::Unit, a: impl Draw<T>) -> impl Draw<T> {
|
||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn xy_pull <T: Screen> (x: T::Unit, y: T::Unit, a: impl Draw<T>) -> impl Draw<T> {
|
pub const fn xy_pull <T: Screen> (x: T::Unit, y: T::Unit, a: impl Draw<T>) -> impl Draw<T> {
|
||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shrink drawing area symmetrically.
|
/// Shrink drawing area symmetrically.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
|
@ -142,6 +146,7 @@ pub const fn wh_pad <T: Screen> (w: T::Unit, h: T::Unit, draw: impl Draw<T>)
|
||||||
{
|
{
|
||||||
thunk(move|to: &mut T|draw.draw(todo!()))
|
thunk(move|to: &mut T|draw.draw(todo!()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Only draw content if area is above a certain size.
|
/// Only draw content if area is above a certain size.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
|
@ -161,7 +166,7 @@ pub const fn wh_min <T: Screen> (w: Option<T::Unit>, h: Option<T::Unit>, draw: i
|
||||||
pub const fn wh_max <T: Screen> (w: Option<T::Unit>, h: Option<T::Unit>, draw: impl Draw<T>)
|
pub const fn wh_max <T: Screen> (w: Option<T::Unit>, h: Option<T::Unit>, draw: impl Draw<T>)
|
||||||
-> impl Draw<T>
|
-> impl Draw<T>
|
||||||
{
|
{
|
||||||
thunk(move|to: &mut T|draw.draw(todo!()))
|
thunk(move|_to: &mut T|draw.draw(todo!()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the maximum width and/or height of the content.
|
/// Set the maximum width and/or height of the content.
|
||||||
|
|
@ -172,7 +177,7 @@ pub const fn wh_max <T: Screen> (w: Option<T::Unit>, h: Option<T::Unit>, draw: i
|
||||||
pub const fn wh_exact <T: Screen> (w: Option<T::Unit>, h: Option<T::Unit>, draw: impl Draw<T>)
|
pub const fn wh_exact <T: Screen> (w: Option<T::Unit>, h: Option<T::Unit>, draw: impl Draw<T>)
|
||||||
-> impl Draw<T>
|
-> impl Draw<T>
|
||||||
{
|
{
|
||||||
thunk(move|to: &mut T|draw.draw(todo!()))
|
thunk(move|_to: &mut T|draw.draw(todo!()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Limit size of drawing area
|
/// Limit size of drawing area
|
||||||
|
|
@ -182,7 +187,7 @@ pub const fn wh_exact <T: Screen> (w: Option<T::Unit>, h: Option<T::Unit>, draw:
|
||||||
pub const fn wh_clip <T: Screen> (
|
pub const fn wh_clip <T: Screen> (
|
||||||
w: Option<T::Unit>, h: Option<T::Unit>, draw: impl Draw<T>
|
w: Option<T::Unit>, h: Option<T::Unit>, draw: impl Draw<T>
|
||||||
) -> impl Draw<T> {
|
) -> impl Draw<T> {
|
||||||
thunk(move|to: &mut T|draw.draw(todo!()))
|
thunk(move|_to: &mut T|draw.draw(todo!()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn wh_full <T: Screen> (a: impl Draw<T>) -> impl Draw<T> { a }
|
pub const fn wh_full <T: Screen> (a: impl Draw<T>) -> impl Draw<T> { a }
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ pub fn iter_east <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_south <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
pub fn iter_south <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
||||||
_iter: impl Fn()->I, _draw: impl Fn(D)->U,
|
_iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
||||||
) -> impl Draw<S> {
|
) -> impl Draw<S> {
|
||||||
thunk(move|_to: &mut S|{ todo!() })
|
thunk(move|_to: &mut S|{ todo!() })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,12 +54,12 @@ impl Split {
|
||||||
let b = origin_b.align(b);
|
let b = origin_b.align(b);
|
||||||
match self {
|
match self {
|
||||||
Self::Below => {
|
Self::Below => {
|
||||||
to.place_at(area_b, &b);
|
to.show(area_b, &b);
|
||||||
to.place_at(area_b, &a);
|
to.show(area_b, &a);
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
to.place_at(area_a, &a);
|
to.show(area_a, &a);
|
||||||
to.place_at(area_a, &b);
|
to.show(area_a, &b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(to.xywh()) // FIXME: compute and return actually used area
|
Ok(to.xywh()) // FIXME: compute and return actually used area
|
||||||
|
|
|
||||||
32
src/term.rs
32
src/term.rs
|
|
@ -119,25 +119,12 @@ pub fn tui_output <
|
||||||
prev.resize(&mut backend, width, height);
|
prev.resize(&mut backend, width, height);
|
||||||
state.view().draw(&mut next).expect("draw failed"); // TODO draw error
|
state.view().draw(&mut next).expect("draw failed"); // TODO draw error
|
||||||
prev.redraw(&mut backend, &mut next);
|
prev.redraw(&mut backend, &mut next);
|
||||||
//tui_redraw(&mut backend, &mut prev, &mut next);
|
|
||||||
}
|
}
|
||||||
let timer = format!("{:>3.3}ms", perf.used.load(Relaxed));
|
let timer = format!("{:>3.3}ms", perf.used.load(Relaxed));
|
||||||
prev.set_string(0, 0, &timer, Style::default());
|
prev.set_string(0, 0, &timer, Style::default());
|
||||||
})?)
|
})?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tui_redraw <'b, W: Write> (
|
|
||||||
back: &mut CrosstermBackend<W>,
|
|
||||||
mut prev: &'b mut Buffer,
|
|
||||||
mut next: &'b mut Buffer
|
|
||||||
) {
|
|
||||||
let updates = prev.diff(&next);
|
|
||||||
back.draw(updates.into_iter()).expect("failed to render");
|
|
||||||
Backend::flush(back).expect("failed to flush output new");
|
|
||||||
std::mem::swap(&mut prev, &mut next);
|
|
||||||
next.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Terminal output.
|
/// Terminal output.
|
||||||
pub struct Tui(
|
pub struct Tui(
|
||||||
/// Ratatui buffer; area is screen size
|
/// Ratatui buffer; area is screen size
|
||||||
|
|
@ -147,10 +134,10 @@ pub struct Tui(
|
||||||
);
|
);
|
||||||
|
|
||||||
impl Tui {
|
impl Tui {
|
||||||
fn new (width: u16, height: u16) -> Self {
|
pub fn new (width: u16, height: u16) -> Self {
|
||||||
Self(Buffer::empty(Rect { x: 0, y: 0, width, height }), XYWH(0, 0, width, height))
|
Self(Buffer::empty(Rect { x: 0, y: 0, width, height }), XYWH(0, 0, width, height))
|
||||||
}
|
}
|
||||||
fn resize <W: Write> (&mut self, back: &mut CrosstermBackend<W>, width: u16, height: u16) {
|
pub fn resize <W: Write> (&mut self, back: &mut CrosstermBackend<W>, width: u16, height: u16) {
|
||||||
let size = Rect { x: 0, y: 0, width, height };
|
let size = Rect { x: 0, y: 0, width, height };
|
||||||
if self.0.area != size {
|
if self.0.area != size {
|
||||||
back.clear_region(ClearType::All).unwrap();
|
back.clear_region(ClearType::All).unwrap();
|
||||||
|
|
@ -158,7 +145,7 @@ impl Tui {
|
||||||
self.0.reset();
|
self.0.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn redraw <'b, W: Write> (&'b mut self, back: &mut CrosstermBackend<W>, mut next: &'b mut Self) {
|
pub fn redraw <'b, W: Write> (&'b mut self, back: &mut CrosstermBackend<W>, mut next: &'b mut Self) {
|
||||||
let updates = self.0.diff(&next.0);
|
let updates = self.0.diff(&next.0);
|
||||||
back.draw(updates.into_iter()).expect("failed to render");
|
back.draw(updates.into_iter()).expect("failed to render");
|
||||||
Backend::flush(back).expect("failed to flush output new");
|
Backend::flush(back).expect("failed to flush output new");
|
||||||
|
|
@ -167,7 +154,18 @@ impl Tui {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Screen for Tui { type Unit = u16; }
|
impl Screen for Tui {
|
||||||
|
type Unit = u16;
|
||||||
|
/// Render drawable in subarea specified by `area`
|
||||||
|
fn show <'t, T: Draw<Self>> (
|
||||||
|
&mut self, area: XYWH<u16>, content: T
|
||||||
|
) {
|
||||||
|
let previous_area = self.1;
|
||||||
|
self.1 = area;
|
||||||
|
let _result_area = content.draw(self);
|
||||||
|
self.1 = previous_area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Deref for Tui { type Target = Buffer; fn deref (&self) -> &Buffer { &self.0 } }
|
impl Deref for Tui { type Target = Buffer; fn deref (&self) -> &Buffer { &self.0 } }
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue