mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-01-31 10:56:41 +01:00
Compare commits
5 commits
277f96d5cc
...
a4dbf88220
| Author | SHA1 | Date | |
|---|---|---|---|
| a4dbf88220 | |||
| 18b6803912 | |||
| d6dcf137a8 | |||
| baa582b9dd | |||
| 5e6338fad8 |
25 changed files with 411 additions and 273 deletions
28
Justfile
28
Justfile
|
|
@ -1,17 +1,29 @@
|
|||
covfig := "CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' RUSTDOCFLAGS='-Cinstrument-coverage' LLVM_PROFILE_FILE='cov/cargo-test-%p-%m.profraw'"
|
||||
export LLVM_PROFILE_FILE := "cov/cargo-test-%p-%m.profraw"
|
||||
grcov-binary := "--binary-path ./target/coverage/deps/"
|
||||
grcov-ignore := "--ignore-not-existing --ignore '../*' --ignore \"/*\" --ignore 'target/*'"
|
||||
|
||||
bacon:
|
||||
{{covfig}} bacon -s
|
||||
bacon -s
|
||||
|
||||
cov:
|
||||
{{covfig}} time cargo test -j4 --workspace --profile coverage
|
||||
CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' \
|
||||
time cargo test -j4 --workspace --profile coverage
|
||||
rm -rf target/coverage/html || true
|
||||
{{covfig}} time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t html -o target/coverage/html
|
||||
time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t html -o target/coverage/html
|
||||
|
||||
cov-md:
|
||||
{{covfig}} time cargo test -j4 --workspace --profile coverage
|
||||
{{covfig}} time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t markdown | sort
|
||||
CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' \
|
||||
time cargo test -j4 --workspace --profile coverage
|
||||
time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t markdown | sort
|
||||
|
||||
cov-md-ci:
|
||||
{{covfig}} time cargo test -j4 --workspace --profile coverage -- --skip test_tui_engine
|
||||
{{covfig}} time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t markdown | sort
|
||||
CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' \
|
||||
time cargo test -j4 --workspace --profile coverage -- --skip test_tui_engine
|
||||
time grcov . -s . {{grcov-binary}} {{grcov-ignore}} -t markdown | sort
|
||||
|
||||
doc:
|
||||
CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' RUSTDOCFLAGS='-Cinstrument-coverage' \
|
||||
cargo doc
|
||||
|
||||
example-tui:
|
||||
cargo run -p tengri_tui --example tui
|
||||
|
|
|
|||
|
|
@ -1,13 +1,18 @@
|
|||
mod core_macros;
|
||||
pub(crate) use std::error::Error;
|
||||
|
||||
/// Standard result type.
|
||||
pub type Usually<T> = Result<T, Box<dyn Error>>;
|
||||
|
||||
/// Standard optional result type.
|
||||
pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
|
||||
|
||||
/// Type-dispatched `get` and `get_mut`.
|
||||
pub trait Has<T>: Send + Sync { fn get (&self) -> &T; fn get_mut (&mut self) -> &mut T; }
|
||||
|
||||
/// Type-dispatched `get` and `get_mut` that return an [Option]-wrapped result.
|
||||
pub trait MaybeHas<T>: Send + Sync { fn get (&self) -> Option<&T>; fn get_mut (&mut self) -> Option<&mut T>; }
|
||||
|
||||
/// May compute a `RetVal` from `Args`.
|
||||
pub trait Eval<Args, RetVal> {
|
||||
/// A custom operation on [Args] that may return [Result::Err] or [Option::None].
|
||||
|
|
@ -22,3 +27,11 @@ pub trait Eval<Args, RetVal> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! as_ref {
|
||||
($T:ty: |$self:ident : $S:ty| $x:expr) => {
|
||||
impl AsRef<$T> for $S {
|
||||
fn as_ref (&$self) -> &$T { &$x }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ dsl_type!(DslExpr {
|
|||
).into())
|
||||
};
|
||||
)*
|
||||
Ok(Some($body as $Type))
|
||||
Ok(Some($body/* as $Type*/))
|
||||
};
|
||||
($name, get)
|
||||
}),* )? ];
|
||||
|
|
@ -74,12 +74,14 @@ pub trait DslNsExprs<'a, T: 'a>: 'a {
|
|||
const EXPRS: DslExprs<'a, Self, T> = &[];
|
||||
/// Resolve an expression if known.
|
||||
fn from_expr (&'a self, dsl: impl DslExpr + 'a) -> Perhaps<T> {
|
||||
if let Some(dsl) = dsl.expr()? {
|
||||
let head = dsl.head()?;
|
||||
for (key, get) in Self::EXPRS.iter() {
|
||||
if Some(*key) == head {
|
||||
return get(self, dsl.tail()?.unwrap_or(""))
|
||||
}
|
||||
}
|
||||
return Ok(None)
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,3 +16,31 @@ pub trait DslNs<'a, T: 'a>: DslNsWords<'a, T> + DslNsExprs<'a, T> {
|
|||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! dsl_ns {
|
||||
($State:ty: $Type:ty {
|
||||
$(literal = |$dsl:ident| $literal:expr;)?
|
||||
$(word = |$state_w:ident| {
|
||||
$($word:literal => $body_w:expr),* $(,)?
|
||||
};)?
|
||||
$(expr = |$state_e:ident| {
|
||||
$($head:literal $args:tt => $body_e:expr),* $(,)?
|
||||
};)?
|
||||
}) => {
|
||||
impl<'a> DslNs<'a, $Type> for $State {
|
||||
$(fn from_literal (&self, $dsl: impl Dsl) -> Perhaps<$Type> {
|
||||
$literal
|
||||
})?
|
||||
}
|
||||
impl<'a> DslNsWords<'a, $Type> for $State {
|
||||
$(dsl_words! { 'a |$state_w| -> $Type {
|
||||
$($word => $body_w),*
|
||||
} })?
|
||||
}
|
||||
impl<'a> DslNsExprs<'a, $Type> for $State {
|
||||
$(dsl_exprs! { 'a |$state_e| -> $Type {
|
||||
$($head $args => $body_e),*
|
||||
} })?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,37 +4,6 @@ use crate::*;
|
|||
pub trait Draw<O: Out> {
|
||||
/// Write data to display.
|
||||
fn draw (&self, to: &mut O);
|
||||
|
||||
fn boxed <'a> (self) -> Box<dyn Draw<O> + 'a> where Self: Sized + 'a {
|
||||
Box::new(self) as Box<dyn Draw<O> + 'a>
|
||||
}
|
||||
fn rc <'a> (self) -> Rc<dyn Draw<O> + 'a> where Self: Sized + 'a {
|
||||
Rc::new(self) as Rc<dyn Draw<O> + 'a>
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out> Draw<O> for () {
|
||||
fn draw (&self, _: &mut O) {}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for &T {
|
||||
fn draw (&self, to: &mut O) {
|
||||
(*self).draw(to)
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for &mut T {
|
||||
fn draw (&self, to: &mut O) {
|
||||
(**self).draw(to)
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for [T] {
|
||||
fn draw (&self, to: &mut O) {
|
||||
for draw in self.iter() {
|
||||
draw.draw(to)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out> Draw<O> for fn(&mut O) {
|
||||
|
|
@ -43,6 +12,12 @@ impl<O: Out> Draw<O> for fn(&mut O) {
|
|||
}
|
||||
}
|
||||
|
||||
impl<O: Out> Draw<O> for () { fn draw (&self, _: &mut O) {} }
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for &T {
|
||||
fn draw (&self, to: &mut O) { (*self).draw(to) }
|
||||
}
|
||||
|
||||
impl<'x, O: Out> Draw<O> for &(dyn Draw<O> + 'x) {
|
||||
fn draw (&self, to: &mut O) {
|
||||
(*self).draw(to)
|
||||
|
|
@ -55,6 +30,32 @@ impl<'x, O: Out> Draw<O> for &mut (dyn Draw<O> + 'x) {
|
|||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for RwLock<T> {
|
||||
fn draw (&self, to: &mut O) { self.read().unwrap().draw(to) }
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for [T] {
|
||||
fn draw (&self, to: &mut O) {
|
||||
for draw in self.iter() {
|
||||
draw.draw(to)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//impl<O: Out, T: Draw<O>> Draw<O> for &mut T {
|
||||
//fn draw (&self, to: &mut O) {
|
||||
//(**self).draw(to)
|
||||
//}
|
||||
//}
|
||||
|
||||
//impl<O: Out, T: Iterator<Item = U>, U: Draw<O>> Draw<O> for &mut T {
|
||||
//fn draw (&self, to: &mut O) {
|
||||
//for draw in *self {
|
||||
//draw.draw(to)
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
|
||||
/// Implement custom drawing for a struct.
|
||||
#[macro_export] macro_rules! draw {
|
||||
|
||||
|
|
@ -82,4 +83,12 @@ impl<'x, O: Out> Draw<O> for &mut (dyn Draw<O> + 'x) {
|
|||
|
||||
draw!(|self: Arc<T: Draw<O>>, to|(**self).draw(to));
|
||||
draw!(|self: Box<T: Draw<O>>, to|(**self).draw(to));
|
||||
draw!(|self: Option<T: Draw<O>>, to|if let Some(draw) = self { draw.draw(to) });
|
||||
//draw!(|self: Option<T: Draw<O>>, to|if let Some(draw) = self { draw.draw(to) });
|
||||
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for Option<T> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
if let Some(draw) = self {
|
||||
draw.draw(to)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
12
output/src/group.rs
Normal file
12
output/src/group.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#[allow(unused)] use crate::*;
|
||||
|
||||
pub struct Group<T>(T);
|
||||
|
||||
impl<T> Group<T> {
|
||||
pub const fn new () -> Group<()> {
|
||||
Group(())
|
||||
}
|
||||
pub const fn add <U> (self, value: U) -> Group<(T, U)> {
|
||||
Group((self.0, value))
|
||||
}
|
||||
}
|
||||
|
|
@ -32,7 +32,7 @@ pub trait Layout<O: Out> {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! layout {
|
||||
#[macro_export] macro_rules! layout {
|
||||
// Implement for all [Out] backends.
|
||||
(|$self:ident:$Struct:ident $(<
|
||||
$($L:lifetime),* $($T:ident $(:$Trait:path)?),*
|
||||
|
|
@ -63,12 +63,24 @@ impl<O: Out> Layout<O> for () {}
|
|||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for &L { /*FIXME*/ }
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for RwLock<L> { /*FIXME*/ }
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for Option<L> { /*FIXME*/ }
|
||||
|
||||
//impl<O: Out> Layout<O> for fn(&mut O) {}
|
||||
|
||||
impl<O: Out, L: Layout<O>> Layout<O> for Arc<L> {
|
||||
fn layout (&self, to: O::Area) -> O::Area {
|
||||
(**self).layout(to)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'x, O: Out> Layout<O> for &(dyn Draw<O> + 'x) {
|
||||
fn layout (&self, to: O::Area) -> O::Area {
|
||||
Fill::xy(self).layout(to)
|
||||
}
|
||||
}
|
||||
|
||||
mod layout_align; pub use self::layout_align::*;
|
||||
mod layout_bsp; pub use self::layout_bsp::*;
|
||||
mod layout_cond; pub use self::layout_cond::*;
|
||||
|
|
@ -83,4 +95,4 @@ mod layout_padding; pub use self::layout_padding::*;
|
|||
mod layout_pull; pub use self::layout_pull::*;
|
||||
mod layout_push; pub use self::layout_push::*;
|
||||
mod layout_shrink; pub use self::layout_shrink::*;
|
||||
mod layout_stack; pub use self::layout_stack::*;
|
||||
mod layout_stack; //pub use self::layout_stack::*;
|
||||
|
|
|
|||
|
|
@ -32,32 +32,32 @@ use crate::*;
|
|||
#[derive(Debug, Copy, Clone, Default)]
|
||||
pub enum Alignment { #[default] Center, X, Y, NW, N, NE, E, SE, S, SW, W }
|
||||
|
||||
pub struct Align<A>(Alignment, A);
|
||||
pub struct Align<T>(Alignment, T);
|
||||
|
||||
impl<A> Align<A> {
|
||||
#[inline] pub const fn c (a: A) -> Self { Self(Alignment::Center, a) }
|
||||
#[inline] pub const fn x (a: A) -> Self { Self(Alignment::X, a) }
|
||||
#[inline] pub const fn y (a: A) -> Self { Self(Alignment::Y, a) }
|
||||
#[inline] pub const fn n (a: A) -> Self { Self(Alignment::N, a) }
|
||||
#[inline] pub const fn s (a: A) -> Self { Self(Alignment::S, a) }
|
||||
#[inline] pub const fn e (a: A) -> Self { Self(Alignment::E, a) }
|
||||
#[inline] pub const fn w (a: A) -> Self { Self(Alignment::W, a) }
|
||||
#[inline] pub const fn nw (a: A) -> Self { Self(Alignment::NW, a) }
|
||||
#[inline] pub const fn sw (a: A) -> Self { Self(Alignment::SW, a) }
|
||||
#[inline] pub const fn ne (a: A) -> Self { Self(Alignment::NE, a) }
|
||||
#[inline] pub const fn se (a: A) -> Self { Self(Alignment::SE, a) }
|
||||
impl<T> Align<T> {
|
||||
#[inline] pub const fn c (a: T) -> Self { Self(Alignment::Center, a) }
|
||||
#[inline] pub const fn x (a: T) -> Self { Self(Alignment::X, a) }
|
||||
#[inline] pub const fn y (a: T) -> Self { Self(Alignment::Y, a) }
|
||||
#[inline] pub const fn n (a: T) -> Self { Self(Alignment::N, a) }
|
||||
#[inline] pub const fn s (a: T) -> Self { Self(Alignment::S, a) }
|
||||
#[inline] pub const fn e (a: T) -> Self { Self(Alignment::E, a) }
|
||||
#[inline] pub const fn w (a: T) -> Self { Self(Alignment::W, a) }
|
||||
#[inline] pub const fn nw (a: T) -> Self { Self(Alignment::NW, a) }
|
||||
#[inline] pub const fn sw (a: T) -> Self { Self(Alignment::SW, a) }
|
||||
#[inline] pub const fn ne (a: T) -> Self { Self(Alignment::NE, a) }
|
||||
#[inline] pub const fn se (a: T) -> Self { Self(Alignment::SE, a) }
|
||||
}
|
||||
|
||||
impl<E: Out, A: Draw<E>> Draw<E> for Align<A> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
self.1.draw(to)
|
||||
}
|
||||
}
|
||||
impl<E: Out, A: Layout<E>> Layout<E> for Align<A> {
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Align<T> {
|
||||
fn layout (&self, on: E::Area) -> E::Area {
|
||||
self.0.align(on, &self.1)
|
||||
}
|
||||
}
|
||||
impl<E: Out, T: Draw<E> + Layout<E>> Draw<E> for Align<T> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
to.place_at(self.layout(to.area()), &self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Alignment {
|
||||
fn align <E: Out> (&self, on: E::Area, content: &impl Layout<E>) -> E::Area {
|
||||
|
|
|
|||
|
|
@ -2,26 +2,29 @@ use crate::*;
|
|||
use Direction::*;
|
||||
|
||||
/// A split or layer.
|
||||
pub struct Bsp<A, B>(
|
||||
pub struct Bsp<Head, Tail>(
|
||||
pub(crate) Direction,
|
||||
pub(crate) A,
|
||||
pub(crate) B,
|
||||
/// First element.
|
||||
pub(crate) Head,
|
||||
/// Second element.
|
||||
pub(crate) Tail,
|
||||
);
|
||||
impl<A, B> Bsp<A, B> {
|
||||
#[inline] pub const fn n (a: A, b: B) -> Self { Self(North, a, b) }
|
||||
#[inline] pub const fn s (a: A, b: B) -> Self { Self(South, a, b) }
|
||||
#[inline] pub const fn e (a: A, b: B) -> Self { Self(East, a, b) }
|
||||
#[inline] pub const fn w (a: A, b: B) -> Self { Self(West, a, b) }
|
||||
#[inline] pub const fn a (a: A, b: B) -> Self { Self(Above, a, b) }
|
||||
#[inline] pub const fn b (a: A, b: B) -> Self { Self(Below, a, b) }
|
||||
|
||||
impl<Head, Tail> Bsp<Head, Tail> {
|
||||
#[inline] pub const fn n (a: Head, b: Tail) -> Self { Self(North, a, b) }
|
||||
#[inline] pub const fn s (a: Head, b: Tail) -> Self { Self(South, a, b) }
|
||||
#[inline] pub const fn e (a: Head, b: Tail) -> Self { Self(East, a, b) }
|
||||
#[inline] pub const fn w (a: Head, b: Tail) -> Self { Self(West, a, b) }
|
||||
#[inline] pub const fn a (a: Head, b: Tail) -> Self { Self(Above, a, b) }
|
||||
#[inline] pub const fn b (a: Head, b: Tail) -> Self { Self(Below, a, b) }
|
||||
}
|
||||
impl<E: Out, A: Layout<E>, B: Layout<E>> Layout<E> for Bsp<A, B> {
|
||||
fn layout (&self, area: E::Area) -> E::Area {
|
||||
bsp_areas(area, self.0, &self.1, &self.2)[2]
|
||||
}
|
||||
}
|
||||
impl<E: Out, A: Draw<E> + Layout<E>, B: Draw<E> + Layout<E>> Draw<E> for Bsp<A, B> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
|
||||
impl<
|
||||
O: Out,
|
||||
Head: Draw<O> + Layout<O>,
|
||||
Tail: Draw<O> + Layout<O>
|
||||
> Draw<O> for Bsp<Head, Tail> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
let [a, b, _] = bsp_areas(to.area(), self.0, &self.1, &self.2);
|
||||
if self.0 == Below {
|
||||
to.place_at(a, &self.1);
|
||||
|
|
@ -32,9 +35,16 @@ impl<E: Out, A: Draw<E> + Layout<E>, B: Draw<E> + Layout<E>> Draw<E> for Bsp<A,
|
|||
}
|
||||
}
|
||||
}
|
||||
fn bsp_areas <E: Out> (
|
||||
area: E::Area, direction: Direction, a: &impl Layout<E>, b: &impl Layout<E>,
|
||||
) -> [E::Area;3] {
|
||||
|
||||
impl<O: Out, Head: Layout<O>, Tail: Layout<O>> Layout<O> for Bsp<Head, Tail> {
|
||||
fn layout (&self, area: O::Area) -> O::Area {
|
||||
bsp_areas(area, self.0, &self.1, &self.2)[2]
|
||||
}
|
||||
}
|
||||
|
||||
fn bsp_areas <O: Out> (
|
||||
area: O::Area, direction: Direction, a: &impl Layout<O>, b: &impl Layout<O>,
|
||||
) -> [O::Area;3] {
|
||||
let [x, y, w, h] = area.xywh();
|
||||
let [aw, ah] = a.layout(area).wh();
|
||||
let [bw, bh] = b.layout(match direction {
|
||||
|
|
|
|||
|
|
@ -28,20 +28,22 @@ impl<E: Out, A: Draw<E>> Draw<E> for When<A> {
|
|||
}
|
||||
|
||||
/// Show one item if a condition is true and another if the condition is false
|
||||
pub struct Either<A, B>(pub bool, pub A, pub B);
|
||||
impl<A, B> Either<A, B> {
|
||||
pub struct Either<E: Out, A: Draw<E> + Layout<E>, B: Draw<E> + Layout<E>>(pub bool, pub A, pub B, pub PhantomData<E>);
|
||||
impl<E: Out, A: Draw<E> + Layout<E>, B: Draw<E> + Layout<E>> Either<E, A, B> {
|
||||
/// Create a ternary view condition.
|
||||
pub const fn new (c: bool, a: A, b: B) -> Self { Self(c, a, b) }
|
||||
pub const fn new (c: bool, a: A, b: B) -> Self {
|
||||
Self(c, a, b, PhantomData)
|
||||
}
|
||||
impl<E: Out, A: Layout<E>, B: Layout<E>> Layout<E> for Either<A, B> {
|
||||
}
|
||||
impl<E: Out, A: Draw<E> + Layout<E>, B: Draw<E> + Layout<E>> Layout<E> for Either<E, A, B> {
|
||||
fn layout (&self, to: E::Area) -> E::Area {
|
||||
let Self(cond, a, b) = self;
|
||||
let Self(cond, a, b, ..) = self;
|
||||
if *cond { a.layout(to) } else { b.layout(to) }
|
||||
}
|
||||
}
|
||||
impl<E: Out, A: Draw<E>, B: Draw<E>> Draw<E> for Either<A, B> {
|
||||
impl<E: Out, A: Draw<E> + Layout<E>, B: Draw<E> + Layout<E>> Draw<E> for Either<E, A, B> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
let Self(cond, a, b) = self;
|
||||
let Self(cond, a, b, ..) = self;
|
||||
if *cond { a.draw(to) } else { b.draw(to) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
use crate::*;
|
||||
|
||||
pub enum Fill<A> {
|
||||
/// Use maximum width of area.
|
||||
X(A),
|
||||
/// Use maximum height of area.
|
||||
Y(A),
|
||||
/// Use maximum width and height of area.
|
||||
XY(A)
|
||||
}
|
||||
|
||||
|
|
@ -28,25 +31,25 @@ impl<T> Fill<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Draw<E> + Layout<E>> Layout<E> for Fill<T> {
|
||||
fn min_w (&self, area: E::Area) -> E::Unit {
|
||||
if self.has_x() {
|
||||
area.w()
|
||||
} else {
|
||||
self.content().min_w(area)
|
||||
}
|
||||
}
|
||||
fn min_h (&self, area: E::Area) -> E::Unit {
|
||||
if self.has_y() {
|
||||
area.h()
|
||||
} else {
|
||||
self.content().min_h(area)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Draw<E> + Layout<E>> Draw<E> for Fill<T> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for Fill<T> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
to.place_at(self.layout(to.area()), &self.content())
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: Out, T: Draw<O>> Layout<O> for Fill<T> {
|
||||
fn min_w (&self, area: O::Area) -> O::Unit {
|
||||
if self.has_x() {
|
||||
area.w()
|
||||
} else {
|
||||
0.into()
|
||||
}
|
||||
}
|
||||
fn min_h (&self, area: O::Area) -> O::Unit {
|
||||
if self.has_y() {
|
||||
area.h()
|
||||
} else {
|
||||
0.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,25 +29,19 @@ impl<U: Coordinate, T> Fixed<U, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Draw<E> + Layout<E>> Draw<E> for Fixed<E::Unit, T> {
|
||||
fn draw (&self, to: &mut E) {
|
||||
to.place_at(self.layout(to.area()), &self.content())
|
||||
impl<O: Out, T: Draw<O>> Draw<O> for Fixed<O::Unit, T> {
|
||||
fn draw (&self, to: &mut O) {
|
||||
let area = Layout::<O>::layout(&self, to.area());
|
||||
to.place_at(area, &self.content())
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Out, T: Layout<E>> Layout<E> for Fixed<E::Unit, T> {
|
||||
fn layout (&self, area: E::Area) -> E::Area {
|
||||
let [x, y, w, h] = area.xywh();
|
||||
let [x, y, w, h] = self.content().layout(match self {
|
||||
Self::X(fw, _) => [x, y, *fw, h],
|
||||
Self::Y(fh, _) => [x, y, w, *fh],
|
||||
Self::XY(fw, fh, _) => [x, y, *fw, *fh],
|
||||
}.into()).xywh();
|
||||
let fixed_area = match self {
|
||||
Self::X(fw, _) => [x, y, *fw, h],
|
||||
Self::Y(fh, _) => [x, y, w, *fh],
|
||||
Self::XY(fw, fh, _) => [x, y, *fw, *fh],
|
||||
};
|
||||
fixed_area.into()
|
||||
impl<O: Out, T> Layout<O> for Fixed<O::Unit, T> {
|
||||
fn layout (&self, area: O::Area) -> O::Area {
|
||||
[area.x(), area.y(), match self {
|
||||
Fixed::X(w, _) | Fixed::XY(w, _, _) => *w, _ => area.w()
|
||||
}, match self {
|
||||
Fixed::Y(h, _) | Fixed::XY(_, h, _) => *h, _ => area.h()
|
||||
}].into()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
use crate::*;
|
||||
|
||||
/// Draws items from an iterator.
|
||||
pub struct Map<E, A, B, I, F, G>
|
||||
pub struct Map<O, A, B, I, F, G>
|
||||
where
|
||||
I: Iterator<Item = A> + Send + Sync,
|
||||
F: Fn() -> I + Send + Sync,
|
||||
{
|
||||
__: PhantomData<(E, B)>,
|
||||
__: PhantomData<(O, B)>,
|
||||
/// Function that returns iterator over stacked components
|
||||
get_iter: F,
|
||||
/// Function that returns each stacked component
|
||||
get_item: G,
|
||||
}
|
||||
|
||||
impl<'a, E, A, B, I, F, G> Map<E, A, B, I, F, G> where
|
||||
impl<'a, O, A, B, I, F, G> Map<O, A, B, I, F, G> where
|
||||
I: Iterator<Item = A> + Send + Sync + 'a,
|
||||
F: Fn() -> I + Send + Sync + 'a,
|
||||
{
|
||||
|
|
@ -27,30 +27,30 @@ impl<'a, E, A, B, I, F, G> Map<E, A, B, I, F, G> where
|
|||
}
|
||||
|
||||
macro_rules! impl_map_direction (($name:ident, $axis:ident, $align:ident)=>{
|
||||
impl<'a, E, A, B, I, F> Map<
|
||||
E, A, Push<E::Unit, Align<Fixed<E::Unit, Fill<B>>>>, I, F, fn(A, usize)->B
|
||||
impl<'a, O, A, B, I, F> Map<
|
||||
O, A, Push<O::Unit, Align<Fixed<O::Unit, Fill<B>>>>, I, F, fn(A, usize)->B
|
||||
> where
|
||||
E: Out,
|
||||
B: Draw<E>,
|
||||
O: Out,
|
||||
B: Draw<O> + Layout<O>,
|
||||
I: Iterator<Item = A> + Send + Sync + 'a,
|
||||
F: Fn() -> I + Send + Sync + 'a
|
||||
{
|
||||
pub const fn $name (
|
||||
size: E::Unit,
|
||||
size: O::Unit,
|
||||
get_iter: F,
|
||||
get_item: impl Fn(A, usize)->B + Send + Sync
|
||||
) -> Map<
|
||||
E, A,
|
||||
Push<E::Unit, Align<Fixed<E::Unit, B>>>,
|
||||
O, A,
|
||||
Push<O::Unit, Align<Fixed<O::Unit, B>>>,
|
||||
I, F,
|
||||
impl Fn(A, usize)->Push<E::Unit, Align<Fixed<E::Unit, B>>> + Send + Sync
|
||||
impl Fn(A, usize)->Push<O::Unit, Align<Fixed<O::Unit, B>>> + Send + Sync
|
||||
> {
|
||||
Map {
|
||||
__: PhantomData,
|
||||
get_iter,
|
||||
get_item: move |item: A, index: usize|{
|
||||
// FIXME: multiply
|
||||
let mut push: E::Unit = E::Unit::from(0u16);
|
||||
let mut push: O::Unit = O::Unit::from(0u16);
|
||||
for _ in 0..index {
|
||||
push = push + size;
|
||||
}
|
||||
|
|
@ -66,14 +66,14 @@ impl_map_direction!(south, y, n);
|
|||
impl_map_direction!(west, x, e);
|
||||
impl_map_direction!(north, y, s);
|
||||
|
||||
impl<'a, E, A, B, I, F, G> Layout<E> for Map<E, A, B, I, F, G> where
|
||||
E: Out,
|
||||
B: Draw<E> + Layout<E>,
|
||||
impl<'a, O, A, B, I, F, G> Layout<O> for Map<O, A, B, I, F, G> where
|
||||
O: Out,
|
||||
B: Draw<O> + Layout<O>,
|
||||
I: Iterator<Item = A> + Send + Sync + 'a,
|
||||
F: Fn() -> I + Send + Sync + 'a,
|
||||
G: Fn(A, usize)->B + Send + Sync
|
||||
{
|
||||
fn layout (&self, area: E::Area) -> E::Area {
|
||||
fn layout (&self, area: O::Area) -> O::Area {
|
||||
let Self { get_iter, get_item, .. } = self;
|
||||
let mut index = 0;
|
||||
let [mut min_x, mut min_y] = area.center();
|
||||
|
|
@ -92,14 +92,14 @@ impl<'a, E, A, B, I, F, G> Layout<E> for Map<E, A, B, I, F, G> where
|
|||
area.center_xy([w.into(), h.into()].into()).into()
|
||||
}
|
||||
}
|
||||
impl<'a, E, A, B, I, F, G> Draw<E> for Map<E, A, B, I, F, G> where
|
||||
E: Out,
|
||||
B: Draw<E> + Layout<E>,
|
||||
impl<'a, O, A, B, I, F, G> Draw<O> for Map<O, A, B, I, F, G> where
|
||||
O: Out,
|
||||
B: Draw<O> + Layout<O>,
|
||||
I: Iterator<Item = A> + Send + Sync + 'a,
|
||||
F: Fn() -> I + Send + Sync + 'a,
|
||||
G: Fn(A, usize)->B + Send + Sync
|
||||
{
|
||||
fn draw (&self, to: &mut E) {
|
||||
fn draw (&self, to: &mut O) {
|
||||
let Self { get_iter, get_item, .. } = self;
|
||||
let mut index = 0;
|
||||
let area = self.layout(to.area());
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
mod content; pub use self::content::*;
|
||||
mod draw; pub use self::draw::*;
|
||||
mod group; pub use self::group::*;
|
||||
mod layout; pub use self::layout::*;
|
||||
mod space; pub use self::space::*;
|
||||
mod thunk; pub use self::thunk::*;
|
||||
|
|
@ -14,11 +15,9 @@ mod widget; pub use self::widget::*;
|
|||
pub(crate) use self::Direction::*;
|
||||
pub(crate) use std::fmt::{Debug, Display};
|
||||
pub(crate) use std::marker::PhantomData;
|
||||
pub(crate) use std::ops::{Add, Sub, Mul, Div, Deref};
|
||||
pub(crate) use std::rc::Rc;
|
||||
pub(crate) use std::ops::{Add, Sub, Mul, Div};
|
||||
pub(crate) use std::sync::{Arc, RwLock, atomic::{AtomicUsize, Ordering::Relaxed}};
|
||||
pub(crate) use tengri_core::*;
|
||||
#[cfg(feature = "dsl")] pub(crate) use ::tengri_dsl::*;
|
||||
|
||||
/// Draw target.
|
||||
pub trait Out: Send + Sync + Sized {
|
||||
|
|
|
|||
|
|
@ -1,39 +1,28 @@
|
|||
use crate::*;
|
||||
|
||||
pub struct Group<T>(T);
|
||||
|
||||
impl<T> Group<T> {
|
||||
pub const fn new () -> Group<()> {
|
||||
Group(())
|
||||
}
|
||||
pub const fn add <U> (self, value: U) -> Group<(T, U)> {
|
||||
Group((self.0, value))
|
||||
}
|
||||
}
|
||||
|
||||
/// Lazily-evaluated [Draw]able.
|
||||
pub struct Thunk<E: Out, T: Draw<E>, F: Fn()->T>(
|
||||
PhantomData<E>,
|
||||
F
|
||||
);
|
||||
impl<E: Out, T: Draw<E>, F: Fn()->T> Thunk<E, T, F> {
|
||||
pub struct Lazy<E, T, F>(PhantomData<(E, T)>, F);
|
||||
impl<E: Out, T: Draw<E> + Layout<E>, F: Fn()->T> Lazy<E, T, F> {
|
||||
pub const fn new (thunk: F) -> Self {
|
||||
Self(PhantomData, thunk)
|
||||
}
|
||||
}
|
||||
impl<E: Out, T: Draw<E> + Layout<E>, F: Fn()->T> Content<E> for Thunk<E, T, F> {
|
||||
impl<E: Out, T: Draw<E> + Layout<E>, F: Fn()->T> Content<E> for Lazy<E, T, F> {
|
||||
fn content (&self) -> impl Draw<E> + Layout<E> + '_ {
|
||||
(self.1)()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ThunkDraw<E: Out, F: Fn(&mut E)>(PhantomData<E>, F);
|
||||
impl<E: Out, F: Fn(&mut E)> ThunkDraw<E, F> {
|
||||
pub fn new (render: F) -> Self { Self(PhantomData, render) }
|
||||
pub struct Thunk<E: Out, F: Fn(&mut E)>(PhantomData<E>, F);
|
||||
impl<E: Out, F: Fn(&mut E)> Thunk<E, F> {
|
||||
pub const fn new (draw: F) -> Self { Self(PhantomData, draw) }
|
||||
}
|
||||
impl<E: Out, F: Fn(&mut E)> Draw<E> for ThunkDraw<E, F> {
|
||||
impl<E: Out, F: Fn(&mut E)> Draw<E> for Thunk<E, F> {
|
||||
fn draw (&self, to: &mut E) { (self.1)(to) }
|
||||
}
|
||||
impl<E: Out, F: Fn(&mut E)> Layout<E> for Thunk<E, F> {
|
||||
fn layout (&self, to: E::Area) -> E::Area { to }
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)] pub struct Memo<T, U> {
|
||||
pub value: T,
|
||||
|
|
@ -47,10 +36,10 @@ impl<T: PartialEq, U> Memo<T, U> {
|
|||
pub fn update <R> (
|
||||
&mut self,
|
||||
newval: T,
|
||||
render: impl Fn(&mut U, &T, &T)->R
|
||||
draw: impl Fn(&mut U, &T, &T)->R
|
||||
) -> Option<R> {
|
||||
if newval != self.value {
|
||||
let result = render(&mut*self.view.write().unwrap(), &newval, &self.value);
|
||||
let result = draw(&mut*self.view.write().unwrap(), &newval, &self.value);
|
||||
self.value = newval;
|
||||
return Some(result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,3 +13,6 @@ syn = { workspace = true }
|
|||
quote = { workspace = true }
|
||||
proc-macro2 = { workspace = true }
|
||||
heck = { workspace = true }
|
||||
|
||||
[target.'cfg(target_os = "linux")']
|
||||
rustflags = ["-C", "link-arg=-fuse-ld=mold"]
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ pub(crate) struct ExposeMeta;
|
|||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct ExposeImpl(ItemImpl, BTreeMap<ExposeType, BTreeMap<String, Ident>>);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct ExposeSym(LitStr);
|
||||
//#[derive(Debug, Clone)]
|
||||
//struct ExposeSym(LitStr);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct ExposeType(Box<Type>);
|
||||
|
|
@ -169,33 +169,33 @@ impl ExposeImpl {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<LitStr> for ExposeSym { fn from (this: LitStr) -> Self { Self(this) } }
|
||||
//impl From<LitStr> for ExposeSym { fn from (this: LitStr) -> Self { Self(this) } }
|
||||
|
||||
impl PartialOrd for ExposeSym {
|
||||
fn partial_cmp (&self, other: &Self) -> Option<Ordering> {
|
||||
let this = &self.0;
|
||||
let that = &other.0;
|
||||
Some(format!("{}", quote! { #this }).cmp(&format!("{}", quote! { #that })))
|
||||
}
|
||||
}
|
||||
//impl PartialOrd for ExposeSym {
|
||||
//fn partial_cmp (&self, other: &Self) -> Option<Ordering> {
|
||||
//let this = &self.0;
|
||||
//let that = &other.0;
|
||||
//Some(format!("{}", quote! { #this }).cmp(&format!("{}", quote! { #that })))
|
||||
//}
|
||||
//}
|
||||
|
||||
impl Ord for ExposeSym {
|
||||
fn cmp (&self, other: &Self) -> Ordering {
|
||||
let this = &self.0;
|
||||
let that = &other.0;
|
||||
format!("{}", quote! { #this }).cmp(&format!("{}", quote! { #that }))
|
||||
}
|
||||
}
|
||||
//impl Ord for ExposeSym {
|
||||
//fn cmp (&self, other: &Self) -> Ordering {
|
||||
//let this = &self.0;
|
||||
//let that = &other.0;
|
||||
//format!("{}", quote! { #this }).cmp(&format!("{}", quote! { #that }))
|
||||
//}
|
||||
//}
|
||||
|
||||
impl PartialEq for ExposeSym {
|
||||
fn eq (&self, other: &Self) -> bool {
|
||||
let this = &self.0;
|
||||
let that = &other.0;
|
||||
format!("{}", quote! { #this }) == format!("{}", quote! { #that })
|
||||
}
|
||||
}
|
||||
//impl PartialEq for ExposeSym {
|
||||
//fn eq (&self, other: &Self) -> bool {
|
||||
//let this = &self.0;
|
||||
//let that = &other.0;
|
||||
//format!("{}", quote! { #this }) == format!("{}", quote! { #that })
|
||||
//}
|
||||
//}
|
||||
|
||||
impl Eq for ExposeSym {}
|
||||
//impl Eq for ExposeSym {}
|
||||
|
||||
impl From<Type> for ExposeType { fn from (this: Type) -> Self { Self(Box::new(this)) } }
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
{pkgs?import<nixpkgs>{}}:let
|
||||
stdenv = pkgs.clang19Stdenv;
|
||||
name = "tengri";
|
||||
nativeBuildInputs = with pkgs; [ pkg-config libclang ];
|
||||
buildInputs = with pkgs; [ libclang ];
|
||||
nativeBuildInputs = [ pkgs.pkg-config pkgs.libclang pkgs.mold ];
|
||||
buildInputs = [ pkgs.libclang ];
|
||||
LIBCLANG_PATH = "${pkgs.libclang.lib.outPath}/lib";
|
||||
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath (with pkgs; []);
|
||||
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [];
|
||||
in pkgs.mkShell.override {
|
||||
inherit stdenv;
|
||||
} {
|
||||
|
|
|
|||
|
|
@ -22,3 +22,6 @@ tengri_tui = { optional = true, path = "../tui" }
|
|||
tengri_proc = { path = "../proc" }
|
||||
tengri = { path = ".", features = [ "dsl" ] }
|
||||
crossterm = { workspace = true }
|
||||
|
||||
[target.'cfg(target_os = "linux")']
|
||||
rustflags = ["-C", "link-arg=-fuse-ld=mold"]
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ impl ExampleCommand {
|
|||
}
|
||||
}
|
||||
|
||||
tui_draw!(|self: Example, to|to.place(&self.content()));
|
||||
content!(TuiOut: |self: Example|{
|
||||
let index = self.0 + 1;
|
||||
let wh = self.1.wh();
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ impl Tui {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! tui_layout ((|$self:ident:$Self:ty, $to:ident|$expr:expr)=>{
|
||||
#[macro_export] macro_rules! tui_layout ((|$self:ident:$Self:ty, $to:ident|$expr:expr)=>{
|
||||
impl Layout<TuiOut> for $Self {
|
||||
fn layout (&$self, $to: [u16;4]) -> [u16;4] {
|
||||
$expr
|
||||
|
|
@ -29,7 +29,7 @@ macro_rules! tui_layout ((|$self:ident:$Self:ty, $to:ident|$expr:expr)=>{
|
|||
}
|
||||
});
|
||||
|
||||
macro_rules! tui_draw ((|$self:ident:$Self:ty, $to:ident|$expr:expr)=>{
|
||||
#[macro_export] macro_rules! tui_draw ((|$self:ident:$Self:ty, $to:ident|$expr:expr)=>{
|
||||
impl Draw<TuiOut> for $Self {
|
||||
fn draw (&$self, $to: &mut TuiOut) {
|
||||
$expr
|
||||
|
|
@ -38,18 +38,73 @@ macro_rules! tui_draw ((|$self:ident:$Self:ty, $to:ident|$expr:expr)=>{
|
|||
});
|
||||
|
||||
mod tui_border; pub use self::tui_border::*;
|
||||
mod tui_button; //pub use self::tui_button::*;
|
||||
mod tui_button; pub use self::tui_button::*;
|
||||
mod tui_color; pub use self::tui_color::*;
|
||||
mod tui_error; pub use self::tui_error::*;
|
||||
mod tui_field; pub use self::tui_field::*;
|
||||
mod tui_number; //pub use self::tui_number::*;
|
||||
mod tui_phat; pub use self::tui_phat::*;
|
||||
mod tui_repeat; pub use self::tui_repeat::*;
|
||||
mod tui_scroll; pub use self::tui_scroll::*;
|
||||
mod tui_string; pub use self::tui_string::*;
|
||||
mod tui_style; pub use self::tui_style::*;
|
||||
|
||||
mod tui_number; //pub use self::tui_number::*;
|
||||
mod tui_tryptich; //pub use self::tui_tryptich::*;
|
||||
|
||||
pub struct TuiForeground<T>(pub(crate) Foreground<Color, T>);
|
||||
pub struct TuiBackground<T>(pub(crate) Background<Color, T>);
|
||||
pub struct Modify<T>(pub bool, pub Modifier, pub T);
|
||||
pub struct Styled<T>(pub Option<Style>, pub T);
|
||||
|
||||
impl<T: Layout<TuiOut>> Layout<TuiOut> for TuiForeground<T> {
|
||||
fn layout (&self, to: [u16;4]) -> [u16;4] {
|
||||
self.0.layout(to)
|
||||
}
|
||||
}
|
||||
impl<T: Layout<TuiOut> + Draw<TuiOut>> Draw<TuiOut> for TuiForeground<T> {
|
||||
fn draw (&self, to: &mut TuiOut) {
|
||||
let area = self.layout(to.area());
|
||||
to.fill_bg(area, self.0.0);
|
||||
to.place_at(area, &self.0.1);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Layout<TuiOut>> Layout<TuiOut> for TuiBackground<T> {
|
||||
fn layout (&self, to: [u16;4]) -> [u16;4] {
|
||||
self.0.layout(to)
|
||||
}
|
||||
}
|
||||
impl<T: Layout<TuiOut> + Draw<TuiOut>> Draw<TuiOut> for TuiBackground<T> {
|
||||
fn draw (&self, to: &mut TuiOut) {
|
||||
let area = self.layout(to.area());
|
||||
to.fill_bg(area, self.0.0);
|
||||
to.place_at(area, &self.0.1);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Layout<TuiOut>> Layout<TuiOut> for Modify<T> {
|
||||
fn layout (&self, to: [u16;4]) -> [u16;4] {
|
||||
self.2.layout(to)
|
||||
}
|
||||
}
|
||||
impl<T: Draw<TuiOut>> Draw<TuiOut> for Modify<T> {
|
||||
fn draw (&self, to: &mut TuiOut) {
|
||||
to.fill_mod(to.area(), self.0, self.1);
|
||||
self.2.draw(to)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Layout<TuiOut>> Layout<TuiOut> for Styled<T> {
|
||||
fn layout (&self, to: [u16;4]) -> [u16;4] {
|
||||
self.1.layout(to)
|
||||
}
|
||||
}
|
||||
impl<T: Layout<TuiOut> + Draw<TuiOut>> Draw<TuiOut> for Styled<T> {
|
||||
fn draw (&self, to: &mut TuiOut) {
|
||||
to.place(&self.1);
|
||||
// TODO write style over area
|
||||
}
|
||||
}
|
||||
|
||||
//impl<T: Draw<TuiOut> + Layout<TuiOut>> Content<TuiOut> for Result<T, Box<dyn std::error::Error>> {
|
||||
//fn content (&self) -> impl Draw<TuiOut> + Layout<TuiOut> + '_ {
|
||||
//Bsp::a(self.as_ref().ok(), self.as_ref().err().map(
|
||||
|
|
|
|||
|
|
@ -1 +1,38 @@
|
|||
//use crate::{*, Color::*};
|
||||
use crate::{*, Color::*};
|
||||
|
||||
pub fn button_2 <'a> (
|
||||
key: impl Draw<TuiOut> + Layout<TuiOut> + 'a,
|
||||
label: impl Draw<TuiOut> + Layout<TuiOut> + 'a,
|
||||
editing: bool,
|
||||
) -> impl Draw<TuiOut> + Layout<TuiOut> + 'a {
|
||||
let key = Tui::fg_bg(Tui::orange(), Tui::g(0), Bsp::e(
|
||||
Tui::fg(Tui::g(0), "▐"),
|
||||
Bsp::e(key, Tui::fg(Tui::g(96), "▐"))
|
||||
));
|
||||
let label = When::new(!editing, Tui::fg_bg(Tui::g(255), Tui::g(96), label));
|
||||
Tui::bold(true, Bsp::e(key, label))
|
||||
}
|
||||
|
||||
pub fn button_3 <'a> (
|
||||
key: impl Draw<TuiOut> + Layout<TuiOut> + 'a,
|
||||
label: impl Draw<TuiOut> + Layout<TuiOut> + 'a,
|
||||
value: impl Draw<TuiOut> + Layout<TuiOut> + 'a,
|
||||
editing: bool,
|
||||
) -> impl Draw<TuiOut> + Layout<TuiOut> + 'a {
|
||||
let key = Tui::fg_bg(Tui::orange(), Tui::g(0),
|
||||
Bsp::e(Tui::fg(Tui::g(0), "▐"), Bsp::e(key, Tui::fg(if editing {
|
||||
Tui::g(128)
|
||||
} else {
|
||||
Tui::g(96)
|
||||
}, "▐"))));
|
||||
let label = Bsp::e(
|
||||
When::new(!editing, Bsp::e(
|
||||
Tui::fg_bg(Tui::g(255), Tui::g(96), label),
|
||||
Tui::fg_bg(Tui::g(128), Tui::g(96), "▐"),
|
||||
)),
|
||||
Bsp::e(
|
||||
Tui::fg_bg(Tui::g(224), Tui::g(128), value),
|
||||
Tui::fg_bg(Tui::g(128), Reset, "▌"),
|
||||
));
|
||||
Tui::bold(true, Bsp::e(key, label))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ tui_draw!(|self: &str, to|{
|
|||
to.text(&self, x, y, w)
|
||||
});
|
||||
|
||||
tui_layout!(|self: Arc<str>, to|self.as_ref().layout(to));
|
||||
tui_draw!(|self: Arc<str>, to|self.as_ref().draw(to));
|
||||
|
||||
tui_layout!(|self: String, to|self.as_str().layout(to));
|
||||
tui_draw!(|self: String, to|self.as_str().draw(to));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,56 +1 @@
|
|||
use crate::*;
|
||||
|
||||
pub struct TuiForeground<T>(pub(crate) Foreground<Color, T>);
|
||||
pub struct TuiBackground<T>(pub(crate) Background<Color, T>);
|
||||
pub struct Modify<T>(pub bool, pub Modifier, pub T);
|
||||
pub struct Styled<T>(pub Option<Style>, pub T);
|
||||
|
||||
impl<T: Layout<TuiOut>> Layout<TuiOut> for TuiForeground<T> {
|
||||
fn layout (&self, to: [u16;4]) -> [u16;4] {
|
||||
self.0.layout(to)
|
||||
}
|
||||
}
|
||||
impl<T: Layout<TuiOut> + Draw<TuiOut>> Draw<TuiOut> for TuiForeground<T> {
|
||||
fn draw (&self, to: &mut TuiOut) {
|
||||
let area = self.layout(to.area());
|
||||
to.fill_bg(area, self.0.0);
|
||||
to.place_at(area, &self.0.1);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Layout<TuiOut>> Layout<TuiOut> for TuiBackground<T> {
|
||||
fn layout (&self, to: [u16;4]) -> [u16;4] {
|
||||
self.0.layout(to)
|
||||
}
|
||||
}
|
||||
impl<T: Layout<TuiOut> + Draw<TuiOut>> Draw<TuiOut> for TuiBackground<T> {
|
||||
fn draw (&self, to: &mut TuiOut) {
|
||||
let area = self.layout(to.area());
|
||||
to.fill_bg(area, self.0.0);
|
||||
to.place_at(area, &self.0.1);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Layout<TuiOut>> Layout<TuiOut> for Modify<T> {
|
||||
fn layout (&self, to: [u16;4]) -> [u16;4] {
|
||||
self.2.layout(to)
|
||||
}
|
||||
}
|
||||
impl<T: Draw<TuiOut>> Draw<TuiOut> for Modify<T> {
|
||||
fn draw (&self, to: &mut TuiOut) {
|
||||
to.fill_mod(to.area(), self.0, self.1);
|
||||
self.2.draw(to)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Layout<TuiOut>> Layout<TuiOut> for Styled<T> {
|
||||
fn layout (&self, to: [u16;4]) -> [u16;4] {
|
||||
self.1.layout(to)
|
||||
}
|
||||
}
|
||||
impl<T: Layout<TuiOut> + Draw<TuiOut>> Draw<TuiOut> for Styled<T> {
|
||||
fn draw (&self, to: &mut TuiOut) {
|
||||
to.place(&self.1);
|
||||
// TODO write style over area
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@ use crate::*;
|
|||
use std::time::Duration;
|
||||
use std::thread::{spawn, JoinHandle};
|
||||
use unicode_width::*;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct TuiOut {
|
||||
pub buffer: Buffer,
|
||||
pub area: [u16;4]
|
||||
}
|
||||
|
||||
impl Out for TuiOut {
|
||||
type Unit = u16;
|
||||
type Size = [Self::Unit;2];
|
||||
|
|
@ -24,6 +26,10 @@ impl Out for TuiOut {
|
|||
*self.area_mut() = last;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Layout<TuiOut> for fn(&mut TuiOut) {}
|
||||
|
||||
impl TuiOut {
|
||||
/// Spawn the output thread.
|
||||
pub fn run_output <T: Draw<TuiOut> + Send + Sync + 'static> (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue