mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-09-19 13:36:42 +02:00
This commit is contained in:
parent
20517f09b4
commit
a9f2fa2cdd
17 changed files with 655 additions and 491 deletions
|
|
@ -6,17 +6,19 @@ use crate::*;
|
|||
/// let _ = area(XYWH(1, 2, 3, 4), "southeast");
|
||||
/// let _ = area(Some(XYWH(1, 2, 3, 4)), "southeast");
|
||||
/// ```
|
||||
pub fn area <S: Screen, T: Draw<S>, U: Into<Option<XYWH<S::Unit>>>> (
|
||||
pub fn area <'a, S: Screen, T: Draw<'a, S>, U: Into<Option<XYWH<S::Unit>>>> (
|
||||
origin: U, it: T
|
||||
) -> Area<S, T> {
|
||||
Area(origin.into(), it)
|
||||
}
|
||||
|
||||
pub struct Area<S: Screen, T: Draw<S>>(
|
||||
pub struct Area<S: Screen, T>(
|
||||
pub Option<XYWH<S::Unit>>,
|
||||
pub T
|
||||
pub T,
|
||||
);
|
||||
|
||||
impl_draw!(<S: Screen, T: Draw<S>,>|self: Area<S, T>, to: S|{
|
||||
to.draw(self.0, &self.1)
|
||||
});
|
||||
impl<'a, S: Screen, T: Draw<'a, S>> Draw<'a, S> for Area<S, T> {
|
||||
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||
to.draw(self.0, &self.1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,296 @@
|
|||
use crate::*;
|
||||
|
||||
def_layout_modifier_flat!(
|
||||
LayoutFull (full_w full_h full_wh),
|
||||
Full { W H WH } kw_full "full" |self, to| {
|
||||
pub enum Full<'a, S: Screen, I: Draw<'a, S>> {
|
||||
__(PhantomData<&'a S>), W(I), H(I), WH(I),
|
||||
}
|
||||
|
||||
pub enum Exact<'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>>> {
|
||||
__(PhantomData<&'a S>), W(I, X), H(I, X), WH(I, X, X),
|
||||
}
|
||||
|
||||
pub enum Push<'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>>> {
|
||||
__(PhantomData<&'a S>), X(I, X), Y(I, X), XY(I, X, X),
|
||||
}
|
||||
|
||||
pub enum Pull<'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>>> {
|
||||
__(PhantomData<&'a S>), X(I, X), Y(I, X), XY(I, X, X),
|
||||
}
|
||||
|
||||
pub enum Min<'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>>> {
|
||||
__(PhantomData<&'a S>), W(I, X), H(I, X), WH(I, X, X),
|
||||
}
|
||||
|
||||
pub enum Max<'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>>> {
|
||||
__(PhantomData<&'a S>), W(I, X), H(I, X), WH(I, X, X),
|
||||
}
|
||||
|
||||
pub enum Pad<'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>>> {
|
||||
__(PhantomData<&'a S>), X(I, X), Y(I, X), XY(I, X, X),
|
||||
}
|
||||
|
||||
/// ```
|
||||
/// # fn test_layout_full () -> Usually<()> {
|
||||
/// assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
|
||||
/// assert_eq!(check_layout("1".full_w())?, Some(XYWH(1u16, 1, 80, 1)));
|
||||
/// assert_eq!(check_layout("1".full_h())?, Some(XYWH(1u16, 1, 1, 25)));
|
||||
/// assert_eq!(check_layout("1".full_wh())?, Some(XYWH(1u16, 1, 80, 25)));
|
||||
/// # Ok(()) }}
|
||||
/// ```
|
||||
pub trait LayoutFull<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||
fn full_w (self) -> Full<'a, S, Self> { Full::W(self) }
|
||||
fn full_h (self) -> Full<'a, S, Self> { Full::H(self) }
|
||||
fn full_wh (self) -> Full<'a, S, Self> { Full::WH(self) }
|
||||
}
|
||||
|
||||
/// ```
|
||||
/// # fn test_layout_exact () -> Usually<()> {
|
||||
/// assert_eq!(check_layout("FOOBAR\nKILROY")?, Some(XYWH(1, 1, 6, 2)));
|
||||
/// assert_eq!(check_layout("FOOBAR\nKILROY".exact_w(3))?, Some(XYWH(1, 1, 3, 2)));
|
||||
/// assert_eq!(check_layout("FOOBAR\nKILROY".exact_h(1))?, Some(XYWH(1, 1, 6, 1)));
|
||||
/// assert_eq!(check_layout("FOOBAR\nKILROY".exact_wh(2, 1))?, Some(XYWH(1, 1, 2, 1)));
|
||||
/// # Ok(()) }}
|
||||
/// ```
|
||||
pub trait LayoutExact<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||
fn exact_w <X: Into<Option<S::Unit>> + Copy> (self, w: X)
|
||||
-> Exact<'a, S, Self, X> { Exact::W(self, w) }
|
||||
fn exact_h <X: Into<Option<S::Unit>> + Copy> (self, h: X)
|
||||
-> Exact<'a, S, Self, X> { Exact::H(self, h) }
|
||||
fn exact_wh <X: Into<Option<S::Unit>> + Copy> (self, w: X, h: X)
|
||||
-> Exact<'a, S, Self, X> { Exact::WH(self, w, h) }
|
||||
}
|
||||
|
||||
/// ```
|
||||
/// # fn test_layout_min () -> Usually<()> {
|
||||
/// assert_eq!(check_layout("1".min_w(5))?, Some(XYWH(1u16, 1, 5, 1)));
|
||||
/// assert_eq!(check_layout("1".min_h(5))?, Some(XYWH(1u16, 1, 1, 5)));
|
||||
/// assert_eq!(check_layout("1".min_wh(5, 5))?, Some(XYWH(1u16, 1, 5, 5)));
|
||||
/// assert_eq!(check_layout("123456".min_w(5))?, Some(XYWH(1u16, 1, 6, 1)));
|
||||
/// # Ok(()) }}
|
||||
/// ```
|
||||
pub trait LayoutMin<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||
fn min_w <X: Into<Option<S::Unit>> + Copy> (self, w: X)
|
||||
-> Min<'a, S, Self, X> { Min::W(self, w) }
|
||||
fn min_h <X: Into<Option<S::Unit>> + Copy> (self, h: X)
|
||||
-> Min<'a, S, Self, X> { Min::H(self, h) }
|
||||
fn min_wh <X: Into<Option<S::Unit>> + Copy> (self, w: X, h: X)
|
||||
-> Min<'a, S, Self, X> { Min::WH(self, w, h) }
|
||||
}
|
||||
|
||||
pub trait LayoutMax<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||
fn max_w <X: Into<Option<S::Unit>> + Copy> (self, w: X)
|
||||
-> Max<'a, S, Self, X> { Max::W(self, w) }
|
||||
fn max_h <X: Into<Option<S::Unit>> + Copy> (self, h: X)
|
||||
-> Max<'a, S, Self, X> { Max::H(self, h) }
|
||||
fn max_wh <X: Into<Option<S::Unit>> + Copy> (self, w: X, h: X)
|
||||
-> Max<'a, S, Self, X> { Max::WH(self, w, h) }
|
||||
}
|
||||
|
||||
pub trait LayoutPad<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||
fn pad_w <X: Into<Option<S::Unit>> + Copy> (self, w: X)
|
||||
-> Pad<'a, S, Self, X> { Pad::X(self, w) }
|
||||
fn pad_h <X: Into<Option<S::Unit>> + Copy> (self, h: X)
|
||||
-> Pad<'a, S, Self, X> { Pad::Y(self, h) }
|
||||
fn pad_wh <X: Into<Option<S::Unit>> + Copy> (self, w: X, h: X)
|
||||
-> Pad<'a, S, Self, X> { Pad::XY(self, w, h) }
|
||||
}
|
||||
|
||||
/// ```
|
||||
/// # fn test_layout_pull () -> Usually<()> {
|
||||
/// assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
|
||||
/// assert_eq!(check_layout("1".push_x(1))?, Some(XYWH(2u16, 1, 1, 1)));
|
||||
/// assert_eq!(check_layout("1".push_y(1))?, Some(XYWH(1u16, 2, 1, 1)));
|
||||
/// assert_eq!(check_layout("1".push_xy(1, 1))?, Some(XYWH(2u16, 2, 1, 1)));
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub trait LayoutPush<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||
fn push_x <X: Into<Option<S::Unit>> + Copy> (self, w: X)
|
||||
-> Push<'a, S, Self, X> { Push::X(self, w) }
|
||||
fn push_y <X: Into<Option<S::Unit>> + Copy> (self, h: X)
|
||||
-> Push<'a, S, Self, X> { Push::Y(self, h) }
|
||||
fn push_xy <X: Into<Option<S::Unit>> + Copy> (self, w: X, h: X)
|
||||
-> Push<'a, S, Self, X> { Push::XY(self, w, h) }
|
||||
}
|
||||
|
||||
/// ```
|
||||
/// # fn test_layout_push () -> Usually<()> {
|
||||
/// assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
|
||||
/// assert_eq!(check_layout("1".pull_x(1))?, Some(XYWH(0u16, 1, 1, 1)));
|
||||
/// assert_eq!(check_layout("1".pull_y(1))?, Some(XYWH(1u16, 0, 1, 1)));
|
||||
/// assert_eq!(check_layout("1".pull_xy(1, 1))?, Some(XYWH(0u16, 0, 1, 1)));
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub trait LayoutPull<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||
fn pull_x <X: Into<Option<S::Unit>> + Copy> (self, w: X)
|
||||
-> Pull<'a, S, Self, X> { Pull::X(self, w) }
|
||||
fn pull_y <X: Into<Option<S::Unit>> + Copy> (self, h: X)
|
||||
-> Pull<'a, S, Self, X> { Pull::Y(self, h) }
|
||||
fn pull_xy <X: Into<Option<S::Unit>> + Copy> (self, w: X, h: X)
|
||||
-> Pull<'a, S, Self, X> { Pull::XY(self, w, h) }
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||
pub fn kw_full <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||
-> PerhapsRef<'a, XYWH<O::Unit>>
|
||||
where
|
||||
O: Screen + 'a,
|
||||
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||
+ Namespace<bool>
|
||||
+ Namespace<O::Unit>
|
||||
+ Namespace<Option<O::Unit>>
|
||||
{
|
||||
let thunk = draw(move|screen|ok_flat(expr.nth(1)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||
Ok(match expr.head()? {
|
||||
Some("full/x") | Some("full/w") => Full::W(thunk).draw(to)?,
|
||||
Some("full/y") | Some("full/h") => Full::H(thunk).draw(to)?,
|
||||
Some("full/xy") | Some("full/wh") => Full::WH(thunk).draw(to)?,
|
||||
frag => return Err(format!("invalid variant: {frag:?}").into())
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||
pub fn kw_exact <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||
-> PerhapsRef<'a, XYWH<O::Unit>>
|
||||
where
|
||||
O: Screen + 'a,
|
||||
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||
+ Namespace<bool>
|
||||
+ Namespace<O::Unit>
|
||||
+ Namespace<Option<O::Unit>>
|
||||
{
|
||||
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
|
||||
Ok(match expr.head()? {
|
||||
Some("exact/w") => thunk.exact_w(
|
||||
state.namespace(expr.nth(1)?)?
|
||||
).draw(to)?,
|
||||
Some("exact/h") => thunk.exact_h(
|
||||
state.namespace(expr.nth(1)?)?
|
||||
).draw(to)?,
|
||||
Some("exact/wh") => thunk.exact_wh(
|
||||
state.namespace(expr.nth(1)?)?,
|
||||
state.namespace(expr.nth(2)?)?,
|
||||
).draw(to)?,
|
||||
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||
pub fn kw_min <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||
-> PerhapsRef<'a, XYWH<O::Unit>>
|
||||
where
|
||||
O: Screen + 'a,
|
||||
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||
+ Namespace<bool>
|
||||
+ Namespace<O::Unit>
|
||||
+ Namespace<Option<O::Unit>>
|
||||
{
|
||||
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
|
||||
Ok(match expr.head()? {
|
||||
Some("min/w") => thunk.min_w(
|
||||
state.namespace(expr.nth(1)?)?
|
||||
).draw(to)?,
|
||||
Some("min/h") => thunk.min_h(
|
||||
state.namespace(expr.nth(1)?)?
|
||||
).draw(to)?,
|
||||
Some("min/wh") => thunk.min_wh(
|
||||
state.namespace(expr.nth(1)?)?,
|
||||
state.namespace(expr.nth(2)?)?,
|
||||
).draw(to)?,
|
||||
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||
pub fn kw_max <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||
-> PerhapsRef<'a, XYWH<O::Unit>>
|
||||
where
|
||||
O: Screen + 'a,
|
||||
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||
+ Namespace<bool>
|
||||
+ Namespace<O::Unit>
|
||||
+ Namespace<Option<O::Unit>>
|
||||
{
|
||||
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
|
||||
Ok(match expr.head()? {
|
||||
Some("max/w") => thunk.max_w(
|
||||
state.namespace(expr.nth(1)?)?
|
||||
).draw(to)?,
|
||||
Some("max/h") => thunk.max_h(
|
||||
state.namespace(expr.nth(1)?)?
|
||||
).draw(to)?,
|
||||
Some("max/wh") => thunk.max_wh(
|
||||
state.namespace(expr.nth(1)?)?,
|
||||
state.namespace(expr.nth(2)?)?,
|
||||
).draw(to)?,
|
||||
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||
pub fn kw_push <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||
-> PerhapsRef<'a, XYWH<O::Unit>>
|
||||
where
|
||||
O: Screen + 'a,
|
||||
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||
+ Namespace<bool>
|
||||
+ Namespace<O::Unit>
|
||||
+ Namespace<Option<O::Unit>>
|
||||
{
|
||||
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
|
||||
Ok(match expr.head()? {
|
||||
Some("push/w") => thunk.push_x(state.namespace(expr.nth(1)?)?).draw(to)?,
|
||||
Some("push/h") => thunk.push_y(state.namespace(expr.nth(1)?)?).draw(to)?,
|
||||
Some("push/wh") => thunk.push_xy(state.namespace(expr.nth(1)?)?, state.namespace(expr.nth(2)?)?,).draw(to)?,
|
||||
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||
pub fn kw_pull <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||
-> PerhapsRef<'a, XYWH<O::Unit>>
|
||||
where
|
||||
O: Screen + 'a,
|
||||
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||
+ Namespace<bool>
|
||||
+ Namespace<O::Unit>
|
||||
+ Namespace<Option<O::Unit>>
|
||||
{
|
||||
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
|
||||
Ok(match expr.head()? {
|
||||
Some("pull/w") => thunk.pull_x(state.namespace(expr.nth(1)?)?).draw(to)?,
|
||||
Some("pull/h") => thunk.pull_y(state.namespace(expr.nth(1)?)?).draw(to)?,
|
||||
Some("pull/wh") => thunk.pull_xy(state.namespace(expr.nth(1)?)?, state.namespace(expr.nth(2)?)?,).draw(to)?,
|
||||
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||
pub fn kw_pad <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||
-> PerhapsRef<'a, XYWH<O::Unit>>
|
||||
where
|
||||
O: Screen + 'a,
|
||||
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||
+ Namespace<bool>
|
||||
+ Namespace<O::Unit>
|
||||
+ Namespace<Option<O::Unit>>
|
||||
{
|
||||
let thunk = draw(move|screen|ok_flat(expr.last()?.map(|x: &'a str|state.interpret(screen, x))));
|
||||
Ok(match expr.head()? {
|
||||
Some("pad/w") => thunk.pad_w(
|
||||
state.namespace(expr.nth(1)?)?
|
||||
).draw(to)?,
|
||||
Some("pad/h") => thunk.pad_h(
|
||||
state.namespace(expr.nth(1)?)?
|
||||
).draw(to)?,
|
||||
Some("pad/wh") => thunk.pad_wh(
|
||||
state.namespace(expr.nth(1)?)?,
|
||||
state.namespace(expr.nth(2)?)?,
|
||||
).draw(to)?,
|
||||
_ => return Err(format!("invalid variant: {:?}", expr.head()?).into())
|
||||
})
|
||||
}
|
||||
|
||||
impl <'a, S: Screen, I: Draw<'a, S>> Draw<'a, S> for Full<'a, S, I> {
|
||||
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||
let XYWH(x0, y0, w0, h0) = to.area();
|
||||
let item = match self {
|
||||
Self::W(i) => i, Self::H(i) => i, Self::WH(i) => i, _ => unreachable!()
|
||||
|
|
@ -17,19 +305,10 @@ def_layout_modifier_flat!(
|
|||
x1.unwrap_or(x2), y1.unwrap_or(y2), w1.unwrap_or(w2), h1.unwrap_or(h2),
|
||||
)))
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(test)] #[test] fn test_layout_full () -> Usually<()> {
|
||||
assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
|
||||
assert_eq!(check_layout("1".full_w())?, Some(XYWH(1u16, 1, 80, 1)));
|
||||
assert_eq!(check_layout("1".full_h())?, Some(XYWH(1u16, 1, 1, 25)));
|
||||
assert_eq!(check_layout("1".full_wh())?, Some(XYWH(1u16, 1, 80, 25)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
def_layout_modifier!(
|
||||
LayoutExact (exact_w exact_h exact_wh),
|
||||
Exact { W H WH } kw_exact "exact" |self, to| {
|
||||
impl <'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>> + Copy> Draw<'a, S> for Exact<'a, S, I, X> {
|
||||
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||
let XYWH(x0, y0, w0, h0) = to.area();
|
||||
let (item, w1, h1) = match self {
|
||||
Self::W(item, w1) => (item, (*w1).into(), None),
|
||||
|
|
@ -48,19 +327,10 @@ def_layout_modifier!(
|
|||
_ => unreachable!()
|
||||
}))
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(test)] #[test] fn test_layout_exact () -> Usually<()> {
|
||||
assert_eq!(check_layout("FOOBAR\nKILROY")?, Some(XYWH(1, 1, 6, 2)));
|
||||
assert_eq!(check_layout("FOOBAR\nKILROY".exact_w(3))?, Some(XYWH(1, 1, 3, 2)));
|
||||
assert_eq!(check_layout("FOOBAR\nKILROY".exact_h(1))?, Some(XYWH(1, 1, 6, 1)));
|
||||
assert_eq!(check_layout("FOOBAR\nKILROY".exact_wh(2, 1))?, Some(XYWH(1, 1, 2, 1)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
def_layout_modifier!(
|
||||
LayoutMin (min_w min_h min_wh),
|
||||
Min { W H WH } kw_min "min" |self, to| {
|
||||
impl <'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>> + Copy> Draw<'a, S> for Min<'a, S, I, X> {
|
||||
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||
let XYWH(x0, y0, w0, h0) = to.area();
|
||||
let (item, w1, h1) = match self {
|
||||
Self::W(item, w1) => (item, (*w1).into(), None),
|
||||
|
|
@ -78,19 +348,10 @@ def_layout_modifier!(
|
|||
h1.map(|h1|h1.max(h2)).unwrap_or(h2)
|
||||
)))
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(test)] #[test] fn test_layout_min () -> Usually<()> {
|
||||
assert_eq!(check_layout("1".min_w(5))?, Some(XYWH(1u16, 1, 5, 1)));
|
||||
assert_eq!(check_layout("1".min_h(5))?, Some(XYWH(1u16, 1, 1, 5)));
|
||||
assert_eq!(check_layout("1".min_wh(5, 5))?, Some(XYWH(1u16, 1, 5, 5)));
|
||||
assert_eq!(check_layout("123456".min_w(5))?, Some(XYWH(1u16, 1, 6, 1)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
def_layout_modifier!(
|
||||
LayoutMax (max_w max_h max_wh),
|
||||
Max { W H WH } kw_max "max" |self, to| {
|
||||
impl <'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>> + Copy> Draw<'a, S> for Max<'a, S, I, X> {
|
||||
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||
let XYWH(x, y, w0, h0) = to.area();
|
||||
let (item, w, h) = match self {
|
||||
Self::W(item, w) => (item, (*w).into().unwrap_or(w0), h0),
|
||||
|
|
@ -100,31 +361,10 @@ def_layout_modifier!(
|
|||
};
|
||||
to.draw(XYWH(x, y, if w0 > w { w } else { w0 }, if h0 > h { h } else { h0 }), item)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
def_layout_modifier!(
|
||||
LayoutPad (pad_w pad_h pad_wh),
|
||||
Pad { X Y XY } kw_pad "pad" |self, to| {
|
||||
let XYWH(x, y, w0, h0) = to.area();
|
||||
let (item, w, h) = match self {
|
||||
Self::X(item, w) => (item, (*w).into().unwrap_or_default(), Default::default()),
|
||||
Self::Y(item, h) => (item, Default::default(), (*h).into().unwrap_or_default()),
|
||||
Self::XY(item, w, h) => (item, (*w).into().unwrap_or_default(),
|
||||
(*h).into().unwrap_or_default()),
|
||||
_ => return Ok(None)
|
||||
};
|
||||
to.draw(XYWH(
|
||||
x.plus(w),
|
||||
y.plus(h),
|
||||
w0.minus(w).minus(w),
|
||||
h0.minus(h).minus(h),
|
||||
), item)
|
||||
}
|
||||
);
|
||||
|
||||
def_layout_modifier!(
|
||||
LayoutPush (push_x push_y push_xy),
|
||||
Push { X Y XY } kw_push "push" |self, to| {
|
||||
impl <'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>> + Copy> Draw<'a, S> for Push<'a, S, I, X> {
|
||||
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||
match self {
|
||||
Self::__(_) => unreachable!(),
|
||||
Self::X(item, x1) if let Some(XYWH(x, y, w, h)) = to.size(None, item)? => {
|
||||
|
|
@ -139,19 +379,10 @@ def_layout_modifier!(
|
|||
_ => Ok(None)
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(test)] #[test] fn test_layout_push () -> Usually<()> {
|
||||
assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
|
||||
assert_eq!(check_layout("1".push_x(1))?, Some(XYWH(2u16, 1, 1, 1)));
|
||||
assert_eq!(check_layout("1".push_y(1))?, Some(XYWH(1u16, 2, 1, 1)));
|
||||
assert_eq!(check_layout("1".push_xy(1, 1))?, Some(XYWH(2u16, 2, 1, 1)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
def_layout_modifier!(
|
||||
LayoutPull (pull_x pull_y pull_xy),
|
||||
Pull { X Y XY } kw_pull "pull" |self, to| {
|
||||
impl <'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>> + Copy> Draw<'a, S> for Pull<'a, S, I, X> {
|
||||
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||
match self {
|
||||
Self::__(_) => unreachable!(),
|
||||
Self::X(item, x1) if let Some(XYWH(x, y, w, h)) = to.size(None, item)? => {
|
||||
|
|
@ -172,16 +403,41 @@ def_layout_modifier!(
|
|||
_ => Ok(None)
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
#[cfg(test)] #[test] fn test_layout_pull () -> Usually<()> {
|
||||
assert_eq!(check_layout("1")?, Some(XYWH(1u16, 1, 1, 1)));
|
||||
assert_eq!(check_layout("1".pull_x(1))?, Some(XYWH(0u16, 1, 1, 1)));
|
||||
assert_eq!(check_layout("1".pull_y(1))?, Some(XYWH(1u16, 0, 1, 1)));
|
||||
assert_eq!(check_layout("1".pull_xy(1, 1))?, Some(XYWH(0u16, 0, 1, 1)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)] fn check_layout (t: impl Draw<Tui>) -> Perhaps<XYWH<u16>> {
|
||||
impl <'a, S: Screen, I: Draw<'a, S>, X: Into<Option<S::Unit>> + Copy> Draw<'a, S> for Pad<'a, S, I, X> {
|
||||
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||
let XYWH(x, y, w0, h0) = to.area();
|
||||
let (item, w, h) = match self {
|
||||
Self::X(item, w) => (item, (*w).into().unwrap_or_default(), Default::default()),
|
||||
Self::Y(item, h) => (item, Default::default(), (*h).into().unwrap_or_default()),
|
||||
Self::XY(item, w, h) => (item, (*w).into().unwrap_or_default(),
|
||||
(*h).into().unwrap_or_default()),
|
||||
_ => return Ok(None)
|
||||
};
|
||||
to.draw(XYWH(
|
||||
x.plus(w),
|
||||
y.plus(h),
|
||||
w0.minus(w).minus(w),
|
||||
h0.minus(h).minus(h),
|
||||
), item)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: Screen, T: Draw<'a, S>> LayoutFull<'a, S> for T {}
|
||||
|
||||
impl<'a, S: Screen, T: Draw<'a, S>> LayoutExact<'a, S> for T {}
|
||||
|
||||
impl<'a, S: Screen, T: Draw<'a, S>> LayoutMin<'a, S> for T {}
|
||||
|
||||
impl<'a, S: Screen, T: Draw<'a, S>> LayoutMax<'a, S> for T {}
|
||||
|
||||
impl<'a, S: Screen, T: Draw<'a, S>> LayoutPush<'a, S> for T {}
|
||||
|
||||
impl<'a, S: Screen, T: Draw<'a, S>> LayoutPull<'a, S> for T {}
|
||||
|
||||
impl<'a, S: Screen, T: Draw<'a, S>> LayoutPad<'a, S> for T {}
|
||||
|
||||
#[cfg(test)] fn check_layout <'a> (t: impl Draw<'a, Tui>) -> Drawn<'a, u16> {
|
||||
Tui::Layout(XYWH(1u16, 1, 80, 25)).size(None, t)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,11 @@ pub struct Origin<T>(
|
|||
pub(crate) T
|
||||
);
|
||||
|
||||
impl_draw!(<S: Screen, T: Draw<S>,>|self: Origin<T>, _to: S|{
|
||||
todo!()
|
||||
});
|
||||
impl<'a, S: Screen, T: Draw<'a, S>> Draw<'a, S> for Origin<T> {
|
||||
fn draw (&self, _to: &mut S) -> Drawn<'a, S::Unit> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Something that has `[0, 0]` at a particular point.
|
||||
pub trait HasOrigin {
|
||||
|
|
@ -33,25 +35,47 @@ impl<T: AsRef<Azimuth>> HasOrigin for T {
|
|||
}
|
||||
}
|
||||
|
||||
fn_kw_layout!(kw_align |state, output, expr| {
|
||||
let head = expr.head();
|
||||
let mut frags = head.src()?.unwrap_or_default().split("/");
|
||||
Ok(matches!(frags.next(), Some("align")).then(||{
|
||||
draw(move|output: &mut O|{state.interpret(output, &expr.tail().head())}).align(
|
||||
eval_enum!("align", output, state,
|
||||
expr.head().src()?.unwrap_or_default().split("/").skip(1).next(),
|
||||
Azimuth {
|
||||
"c" => C, "x" => X, "y" => Y,
|
||||
"n" => N, "s" => S, "e" => E, "w" => W,
|
||||
"nw" => NW, "sw" => SW, "ne" => NE, "se" => SE,
|
||||
})
|
||||
).draw(output)
|
||||
}).transpose()?.flatten())
|
||||
});
|
||||
#[cfg(all(feature = "draw", feature = "eval"))]
|
||||
pub fn kw_align <'a, O, S> (state: &'a S, to: &mut O, expr: &'a str)
|
||||
-> Drawn<'a, O::Unit>
|
||||
where
|
||||
O: Screen,
|
||||
S: Interpret<'a, O, Option<XYWH<O::Unit>>>
|
||||
+ Namespace<bool>
|
||||
+ Namespace<O::Unit>
|
||||
+ Namespace<Option<O::Unit>>
|
||||
{
|
||||
let thunk = draw(move|screen|ok_flat(expr.nth(1)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||
Ok(match expr.head()? {
|
||||
Some("align/c") => Align(Some(Azimuth::C), thunk).draw(to)?,
|
||||
Some("align/x") => Align(Some(Azimuth::X), thunk).draw(to)?,
|
||||
Some("align/y") => Align(Some(Azimuth::Y), thunk).draw(to)?,
|
||||
Some("align/n") => Align(Some(Azimuth::N), thunk).draw(to)?,
|
||||
Some("align/s") => Align(Some(Azimuth::S), thunk).draw(to)?,
|
||||
Some("align/e") => Align(Some(Azimuth::E), thunk).draw(to)?,
|
||||
Some("align/w") => Align(Some(Azimuth::W), thunk).draw(to)?,
|
||||
Some("align/nw") => Align(Some(Azimuth::NW), thunk).draw(to)?,
|
||||
Some("align/sw") => Align(Some(Azimuth::SW), thunk).draw(to)?,
|
||||
Some("align/ne") => Align(Some(Azimuth::NE), thunk).draw(to)?,
|
||||
Some("align/se") => Align(Some(Azimuth::SE), thunk).draw(to)?,
|
||||
frag => return Err(format!("invalid variant: {frag:?}").into())
|
||||
})
|
||||
//Ok(matches!(expr.head().src()?.unwrap_or_default().split("/").next(), Some("align")).then(||{
|
||||
//draw(move|output: &mut O|{state.interpret(output, &expr.nth(1))}).align(
|
||||
//eval_enum!("align", output, state,
|
||||
//expr.head().src()?.unwrap_or_default().split("/").skip(1).next(),
|
||||
//Azimuth {
|
||||
//"c" => C, "x" => X, "y" => Y,
|
||||
//"n" => N, "s" => S, "e" => E, "w" => W,
|
||||
//"nw" => NW, "sw" => SW, "ne" => NE, "se" => SE,
|
||||
//})
|
||||
//).draw(output)
|
||||
//}).transpose()?.flatten())
|
||||
}
|
||||
|
||||
impl<S: Screen, T: Draw<S>> CanAlign<S> for T {}
|
||||
impl<'a, S: Screen, T: Draw<'a, S>> CanAlign<'a, S> for T {}
|
||||
|
||||
pub trait CanAlign<S: Screen>: Draw<S> + Sized {
|
||||
pub trait CanAlign<'a, S: Screen>: Draw<'a, S> + Sized {
|
||||
fn align (self, azimuth: impl Into<Option<Azimuth>>) -> Align<Self> {
|
||||
Align(azimuth.into(), self)
|
||||
}
|
||||
|
|
@ -95,8 +119,8 @@ pub struct Align<T>(
|
|||
pub(crate) T,
|
||||
);
|
||||
|
||||
impl<S: Screen, T: Draw<S>> Draw<S> for Align<T> {
|
||||
fn draw (&self, to: &mut S) -> Perhaps<XYWH<S::Unit>> {
|
||||
impl<'a, S: Screen, T: Draw<'a, S>> Draw<'a, S> for Align<T> {
|
||||
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||
let Self(azimuth, item) = self;
|
||||
let area0 = to.area();
|
||||
let size = to.size(area0, item)?;
|
||||
|
|
@ -133,25 +157,17 @@ fn align <S: Screen> (
|
|||
}
|
||||
|
||||
fn_kw_layout!(kw_split |state, output, expr| {
|
||||
let head = expr.head();
|
||||
let mut frags = head.src()?.unwrap_or_default().split("/");
|
||||
Ok(matches!(frags.next(), Some("bsp")).then(||{
|
||||
eval_enum!("bsp", output, state, frags.next(), Split {
|
||||
"n" => North,
|
||||
"s" => South,
|
||||
"e" => East,
|
||||
"w" => West,
|
||||
"a" => Above,
|
||||
"b" => Below
|
||||
}).stack(
|
||||
draw(move|output: &mut O|{
|
||||
state.interpret(output, &expr.tail().head()?)
|
||||
}),
|
||||
draw(move|output: &mut O|{
|
||||
state.interpret(output, &expr.tail().tail().head()?)
|
||||
}),
|
||||
).draw(output)
|
||||
}).transpose()?.flatten())
|
||||
let thunk_a = draw(move|screen|ok_flat(expr.nth(1)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||
let thunk_b = draw(move|screen|ok_flat(expr.nth(2)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||
Ok(match expr.head()? {
|
||||
Some("bsp/n") => Split::North.stack(thunk_a, thunk_b).draw(output)?,
|
||||
Some("bsp/s") => Split::South.stack(thunk_a, thunk_b).draw(output)?,
|
||||
Some("bsp/e") => Split::East.stack(thunk_a, thunk_b).draw(output)?,
|
||||
Some("bsp/w") => Split::West.stack(thunk_a, thunk_b).draw(output)?,
|
||||
Some("bsp/a") => Split::Above.stack(thunk_a, thunk_b).draw(output)?,
|
||||
Some("bsp/b") => Split::Below.stack(thunk_a, thunk_b).draw(output)?,
|
||||
frag => return Err(format!("invalid variant: {frag:?}").into())
|
||||
})
|
||||
});
|
||||
|
||||
/// Split along an axis. Direction determines order.
|
||||
|
|
@ -165,16 +181,28 @@ fn_kw_layout!(kw_split |state, output, expr| {
|
|||
#[default] Below
|
||||
}
|
||||
|
||||
pub struct Pair<S: Screen, A: Draw<S>, B: Draw<S>>(Split, A, B, PhantomData<S>);
|
||||
pub struct Pair<A, B>(Split, A, B);
|
||||
|
||||
pub fn split <S: Screen, A: Draw<S>, B: Draw<S>> (
|
||||
/// ```
|
||||
/// # fn test_split_stack () -> Usually<()> {
|
||||
/// use Split::*;
|
||||
/// fn size_of <A: Draw<Tui>, B: Draw<Tui>> (stack: &Pair<Tui, A, B>) -> Drawn<'a, S::Unit> {
|
||||
/// Tui::Layout(XYWH(0, 0, 80, 25)).size(None, stack)
|
||||
/// }
|
||||
/// assert_eq!(size_of(&split(East, "foo", "bar"))?, Some(XYWH(0, 0, 6, 1)));
|
||||
/// assert_eq!(size_of(&split(South, "foo", "bar"))?, Some(XYWH(0, 0, 3, 2)));
|
||||
/// assert_eq!(size_of(&split(South, split(East, "foo", "bar"), "baz"))?, Some(XYWH(0, 0, 6, 2)));
|
||||
/// assert_eq!(size_of(&split(East, split(South, "foo", "bar"), "baz"))?, Some(XYWH(0, 0, 6, 2)));
|
||||
/// # return Ok(()); }
|
||||
/// ```
|
||||
pub fn split <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (
|
||||
split: Split, a: A, b: B
|
||||
) -> Pair<S, A, B> {
|
||||
Pair(split, a, b, PhantomData)
|
||||
) -> Pair<A, B> {
|
||||
Pair(split, a, b)
|
||||
}
|
||||
|
||||
impl<S: Screen, A: Draw<S>, B: Draw<S>> Draw<S> for Pair<S, A, B> {
|
||||
fn draw (&self, to: &mut S) -> Drawn<S::Unit> {
|
||||
impl<'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> Draw<'a, S> for Pair<A, B> {
|
||||
fn draw (&self, to: &mut S) -> Drawn<'a, S::Unit> {
|
||||
let Self(split, a, b, ..) = self;
|
||||
let (area_a, area_b) = stack_areas(split, to, a, b)?;
|
||||
let (drawn_a, drawn_b) = draw_stacks(split, to, a, area_a, None, b, area_b, None)?;
|
||||
|
|
@ -182,16 +210,16 @@ impl<S: Screen, A: Draw<S>, B: Draw<S>> Draw<S> for Pair<S, A, B> {
|
|||
}
|
||||
}
|
||||
|
||||
fn draw_stacks <S: Screen> (
|
||||
fn draw_stacks <'a, S: Screen> (
|
||||
split: &Split,
|
||||
to: &mut S,
|
||||
a: impl Draw<S>,
|
||||
a: impl Draw<'a, S>,
|
||||
area_a: impl Into<Option<XYWH<S::Unit>>>,
|
||||
origin_a: impl Into<Option<Azimuth>>,
|
||||
b: impl Draw<S>,
|
||||
b: impl Draw<'a, S>,
|
||||
area_b: impl Into<Option<XYWH<S::Unit>>>,
|
||||
origin_b: impl Into<Option<Azimuth>>,
|
||||
) -> Usually<(Option<XYWH<S::Unit>>, Option<XYWH<S::Unit>>)> {
|
||||
) -> UsuallyRef<'a, (Option<XYWH<S::Unit>>, Option<XYWH<S::Unit>>)> {
|
||||
let draw_a = |to: &mut S|Ok::<_, Box<dyn Error>>(match origin_a.into() {
|
||||
Some(origin_a) => to.draw(area_a.into(), a.align(origin_a))?,
|
||||
None => to.draw(area_a.into(), a)?
|
||||
|
|
@ -209,12 +237,25 @@ fn draw_stacks <S: Screen> (
|
|||
})
|
||||
}
|
||||
|
||||
pub fn stack_areas <S: Screen> (
|
||||
/// ```
|
||||
/// # fn test_stack_areas () -> Usually<()> {
|
||||
/// let area = XYWH(0u16, 0, 80, 25);
|
||||
/// assert_eq!(stack_areas(&Split::East, &mut Tui::Layout(area), &"foo", &"bar")?, (
|
||||
/// Some(XYWH(0u16, 0, 3, 1)),
|
||||
/// Some(XYWH(3u16, 0, 3, 1)),
|
||||
/// ));
|
||||
/// assert_eq!(stack_areas(&Split::South, &mut Tui::Layout(area), &"foo", &"bar")?, (
|
||||
/// Some(XYWH(0u16, 0, 3, 1)),
|
||||
/// Some(XYWH(0u16, 1, 3, 1)),
|
||||
/// ));
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub fn stack_areas <'a, S: Screen> (
|
||||
split: &Split,
|
||||
to: &mut S,
|
||||
a: impl Draw<S>,
|
||||
b: impl Draw<S>,
|
||||
) -> Usually<(Option<XYWH<S::Unit>>, Option<XYWH<S::Unit>>)> {
|
||||
a: impl Draw<'a, S>,
|
||||
b: impl Draw<'a, S>,
|
||||
) -> UsuallyRef<'a, (Option<XYWH<S::Unit>>, Option<XYWH<S::Unit>>)> {
|
||||
let area_a = to.size(None, a)?;
|
||||
Ok(match split {
|
||||
Split::South => (
|
||||
|
|
@ -289,8 +330,10 @@ impl Split {
|
|||
/// let _ = Split::East.stack(&"", &"");
|
||||
/// let _ = Split::West.stack(&"", &"");
|
||||
/// ```
|
||||
pub const fn stack <S: Screen, A: Draw<S>, B: Draw<S>> (&self, a: A, b: B) -> impl Draw<S> {
|
||||
Pair(*self, a, b, PhantomData)
|
||||
pub const fn stack <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (&self, a: A, b: B)
|
||||
-> impl Draw<'a, S>
|
||||
{
|
||||
Pair(*self, a, b)
|
||||
}
|
||||
|
||||
/// ```
|
||||
|
|
@ -302,7 +345,9 @@ impl Split {
|
|||
/// let _ = Split::East.half(&"", &"");
|
||||
/// let _ = Split::West.half(&"", &"");
|
||||
/// ```
|
||||
pub const fn half <S: Screen, A: Draw<S>, B: Draw<S>> (&self, a: &A, b: &B) -> impl Draw<S> {
|
||||
pub const fn half <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (&self, a: &A, b: &B)
|
||||
-> impl Draw<'a, S>
|
||||
{
|
||||
draw(move|to: &mut S|{
|
||||
let (area_a, area_b) = to.xywh().split_half(self);
|
||||
let (origin_a, origin_b) = self.origins();
|
||||
|
|
@ -356,28 +401,28 @@ impl Split {
|
|||
|
||||
}
|
||||
|
||||
pub const fn east <S: Screen, A: Draw<S>, B: Draw<S>> (a: A, b: B) -> impl Draw<S> {
|
||||
Pair(Split::East, a, b, PhantomData)
|
||||
pub const fn east <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (a: A, b: B) -> impl Draw<'a, S> {
|
||||
Pair(Split::East, a, b)
|
||||
}
|
||||
|
||||
pub const fn north <S: Screen, A: Draw<S>, B: Draw<S>> (a: A, b: B) -> impl Draw<S> {
|
||||
Pair(Split::North, a, b, PhantomData)
|
||||
pub const fn north <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (a: A, b: B) -> impl Draw<'a, S> {
|
||||
Pair(Split::North, a, b)
|
||||
}
|
||||
|
||||
pub const fn west <S: Screen, A: Draw<S>, B: Draw<S>> (a: A, b: B) -> impl Draw<S> {
|
||||
Pair(Split::West, a, b, PhantomData)
|
||||
pub const fn west <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (a: A, b: B) -> impl Draw<'a, S> {
|
||||
Pair(Split::West, a, b)
|
||||
}
|
||||
|
||||
pub const fn south <S: Screen, A: Draw<S>, B: Draw<S>> (a: A, b: B) -> impl Draw<S> {
|
||||
Pair(Split::South, a, b, PhantomData)
|
||||
pub const fn south <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (a: A, b: B) -> impl Draw<'a, S> {
|
||||
Pair(Split::South, a, b)
|
||||
}
|
||||
|
||||
pub const fn above <S: Screen, A: Draw<S>, B: Draw<S>> (a: A, b: B) -> impl Draw<S> {
|
||||
Pair(Split::Above, a, b, PhantomData)
|
||||
pub const fn above <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (a: A, b: B) -> impl Draw<'a, S> {
|
||||
Pair(Split::Above, a, b)
|
||||
}
|
||||
|
||||
pub const fn below <S: Screen, A: Draw<S>, B: Draw<S>> (a: A, b: B) -> impl Draw<S> {
|
||||
Pair(Split::Below, a, b, PhantomData)
|
||||
pub const fn below <'a, S: Screen, A: Draw<'a, S>, B: Draw<'a, S>> (a: A, b: B) -> impl Draw<'a, S> {
|
||||
Pair(Split::Below, a, b)
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! north {
|
||||
|
|
@ -410,38 +455,6 @@ pub const fn below <S: Screen, A: Draw<S>, B: Draw<S>> (a: A, b: B) -> impl Draw
|
|||
($head:expr, $($tail:expr),* $(,)?) => { below($head, below!($($tail,)*)) };
|
||||
}
|
||||
|
||||
#[cfg(test)] #[test] fn test_stack_areas () -> Usually<()> {
|
||||
let area = XYWH(0u16, 0, 80, 25);
|
||||
|
||||
assert_eq!(stack_areas(&Split::East, &mut Tui::Layout(area), &"foo", &"bar")?, (
|
||||
Some(XYWH(0u16, 0, 3, 1)),
|
||||
Some(XYWH(3u16, 0, 3, 1)),
|
||||
));
|
||||
|
||||
assert_eq!(stack_areas(&Split::South, &mut Tui::Layout(area), &"foo", &"bar")?, (
|
||||
Some(XYWH(0u16, 0, 3, 1)),
|
||||
Some(XYWH(0u16, 1, 3, 1)),
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)] #[test] fn test_split_stack () -> Usually<()> {
|
||||
use Split::*;
|
||||
fn size_of <A: Draw<Tui>, B: Draw<Tui>> (stack: &Pair<Tui, A, B>) -> Perhaps<XYWH<u16>> {
|
||||
Tui::Layout(XYWH(0, 0, 80, 25)).size(None, stack)
|
||||
}
|
||||
assert_eq!(size_of(&split(East, "foo", "bar"))?,
|
||||
Some(XYWH(0, 0, 6, 1)));
|
||||
assert_eq!(size_of(&split(South, "foo", "bar"))?,
|
||||
Some(XYWH(0, 0, 3, 2)));
|
||||
assert_eq!(size_of(&split(South, split(East, "foo", "bar"), "baz"))?,
|
||||
Some(XYWH(0, 0, 6, 2)));
|
||||
assert_eq!(size_of(&split(East, split(South, "foo", "bar"), "baz"))?,
|
||||
Some(XYWH(0, 0, 6, 2)));
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[cfg(test)] #[test] fn test_align () -> Usually<()> {
|
||||
let mut screen = Tui::Layout(XYWH(0, 0, 80, 25));
|
||||
assert_eq!("FOOBAR\nKILROY".draw(&mut screen)?, Some(XYWH(0, 0, 6, 2)));
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
use crate::*;
|
||||
|
||||
fn_kw_layout!(kw_when |state, output, expr| {
|
||||
Ok(matches!(expr.head()?, Some("when")).then(||{
|
||||
when(state.namespace(expr.tail().head())?.unwrap(),
|
||||
draw(move|output: &mut O|{state.interpret(output, &expr.tail().tail().head())})
|
||||
).draw(output)
|
||||
}).transpose()?.flatten())
|
||||
let thunk = draw(move|screen|ok_flat(expr.nth(2)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||
ok_flat(matches!(expr.head()?, Some("when")).then(||{
|
||||
when(state.namespace(expr.nth(1)?)?.unwrap(), thunk) .draw(output)
|
||||
}))
|
||||
});
|
||||
|
||||
/// Only render when condition is true.
|
||||
|
|
@ -16,21 +15,16 @@ fn_kw_layout!(kw_when |state, output, expr| {
|
|||
/// when(true, "Yes")
|
||||
/// # }
|
||||
/// ```
|
||||
pub const fn when <T: Screen> (condition: bool, item: impl Draw<T>) -> impl Draw<T> {
|
||||
pub const fn when <'a, T: Screen> (condition: bool, item: impl Draw<'a, T>) -> impl Draw<'a, T> {
|
||||
draw(move|to: &mut T|if condition { item.draw(to) } else { Ok(Default::default()) })
|
||||
}
|
||||
|
||||
fn_kw_layout!(kw_either |state, output, expr| {
|
||||
Ok(matches!(expr.head()?, Some("either")).then(||{
|
||||
either(state.namespace(expr.tail().head()?)?.unwrap(),
|
||||
draw(move|output: &mut O|{
|
||||
state.interpret(output, &expr.tail().tail().head()?)
|
||||
}),
|
||||
draw(move|output: &mut O|{
|
||||
state.interpret(output, &expr.tail().tail().tail().head()?)
|
||||
}),
|
||||
).draw(output)
|
||||
}).transpose()?.flatten())
|
||||
let thunk_a = draw(move|screen|ok_flat(expr.nth(2)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||
let thunk_b = draw(move|screen|ok_flat(expr.nth(3)?.map(|x: &'a str|state.interpret(screen, x))));
|
||||
ok_flat(matches!(expr.head()?, Some("either")).then(||{
|
||||
either(state.namespace(expr.nth(1)?)?.unwrap(), thunk_a, thunk_b).draw(output)
|
||||
}))
|
||||
});
|
||||
|
||||
/// Render one thing if a condition is true and another false.
|
||||
|
|
@ -41,6 +35,8 @@ fn_kw_layout!(kw_either |state, output, expr| {
|
|||
/// either(true, "Yes", "No")
|
||||
/// # }
|
||||
/// ```
|
||||
pub const fn either <T: Screen> (condition: bool, a: impl Draw<T>, b: impl Draw<T>) -> impl Draw<T> {
|
||||
pub const fn either <'a, T: Screen> (
|
||||
condition: bool, a: impl Draw<'a, T>, b: impl Draw<'a, T>
|
||||
) -> impl Draw<'a, T> {
|
||||
draw(move|to: &mut T|if condition { a.draw(to) } else { b.draw(to) })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use super::*;
|
||||
|
||||
pub fn iter_south <'a, S: Screen, D: Draw<S>, I: Iterator<Item = D>> (
|
||||
pub fn iter_south <'a, S: Screen, D: Draw<'a, S>, I: Iterator<Item = D>> (
|
||||
iter: impl Fn()->I
|
||||
) -> impl Draw<S> {
|
||||
) -> impl Draw<'a, S> {
|
||||
draw(move|to: &mut S|{
|
||||
let XYWH(x, y, w, h) = to.area();
|
||||
let mut y_next = y;
|
||||
|
|
@ -22,9 +22,9 @@ pub fn iter_south <'a, S: Screen, D: Draw<S>, I: Iterator<Item = D>> (
|
|||
})
|
||||
}
|
||||
|
||||
pub fn iter_east <'a, S: Screen, D: Draw<S>, I: Iterator<Item = D>> (
|
||||
pub fn iter_east <'a, S: Screen, D: Draw<'a, S>, I: Iterator<Item = D>> (
|
||||
iter: impl Fn()->I
|
||||
) -> impl Draw<S> {
|
||||
) -> impl Draw<'a, S> {
|
||||
draw(move|to: &mut S|{
|
||||
let XYWH(x, y, w, h) = to.area();
|
||||
let mut x_next = x;
|
||||
|
|
@ -45,74 +45,75 @@ pub fn iter_east <'a, S: Screen, D: Draw<S>, I: Iterator<Item = D>> (
|
|||
}
|
||||
|
||||
/// Iterate over a collection of the same kind of [Draw]able:
|
||||
pub fn iter <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
||||
pub fn iter <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<'a, S>> (
|
||||
_iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
||||
) -> impl Draw<S> {
|
||||
) -> impl Draw<'a, S> {
|
||||
draw(move|_to: &mut S|{ todo!() })
|
||||
}
|
||||
|
||||
/// Iterate over a collection of the same kind of [Draw]able:
|
||||
pub fn iter_once <'a, S: Screen, D: 'a, U: Draw<S>> (
|
||||
pub fn iter_once <'a, S: Screen, D: 'a, U: Draw<'a, S>> (
|
||||
_iter: impl Iterator<Item = D>, _draw: impl Fn(D, usize)->U,
|
||||
) -> impl Draw<S> {
|
||||
) -> impl Draw<'a, S> {
|
||||
draw(move|_to: &mut S|{ todo!() })
|
||||
}
|
||||
|
||||
/// Iterate over a collection of various [Draw]ables:
|
||||
pub fn iter_dyn <
|
||||
'a,
|
||||
S: Screen, // Target screen
|
||||
D, // Input doesn't need to be [Draw]able, output does
|
||||
V: Fn()->I, // Function that returns the iterator
|
||||
I: Iterator<Item = D>, // Type of the iterator
|
||||
F: Fn(&D, usize)->dyn Draw<S>, // Function that returns [Draw]able from iterator item
|
||||
> (_items: V, _cb: F) -> impl Draw<S> {
|
||||
F: Fn(&D, usize)->dyn Draw<'a, S>, // Function that returns [Draw]able from iterator item
|
||||
> (_items: V, _cb: F) -> impl Draw<'a, S> {
|
||||
draw(move|_to: &mut S|{ todo!() })
|
||||
}
|
||||
|
||||
pub fn iter_north <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
||||
pub fn iter_north <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<'a, S>> (
|
||||
_iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
||||
) -> impl Draw<S> {
|
||||
) -> impl Draw<'a, S> {
|
||||
draw(move|_to: &mut S|{ todo!() })
|
||||
}
|
||||
|
||||
pub fn iter_east_fixed <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
||||
pub fn iter_east_fixed <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<'a, S>> (
|
||||
_height: S::Unit, _iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
||||
) -> impl Draw<S> {
|
||||
) -> impl Draw<'a, S> {
|
||||
draw(move|_to: &mut S|{ todo!() })
|
||||
}
|
||||
|
||||
pub fn iter_south_fixed <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
||||
pub fn iter_south_fixed <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<'a, S>> (
|
||||
_height: S::Unit, _iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
||||
) -> impl Draw<S> {
|
||||
) -> impl Draw<'a, S> {
|
||||
draw(move|_to: &mut S|{ todo!() })
|
||||
}
|
||||
|
||||
pub fn iter_west <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
||||
pub fn iter_west <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<'a, S>> (
|
||||
_iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
|
||||
) -> impl Draw<S> {
|
||||
) -> impl Draw<'a, S> {
|
||||
draw(move|_to: &mut S|{ todo!() })
|
||||
}
|
||||
|
||||
pub fn row_south <S: Screen> (south: S::Unit, height: S::Unit, content: impl Draw<S>)
|
||||
-> impl Draw<S>
|
||||
pub fn row_south <'a, S: Screen + 'a> (south: S::Unit, height: S::Unit, content: impl Draw<'a, S>)
|
||||
-> impl Draw<'a, S>
|
||||
{
|
||||
content.exact_h(height).push_y(south)
|
||||
}
|
||||
|
||||
pub fn row_north <S: Screen> (north: S::Unit, height: S::Unit, content: impl Draw<S>)
|
||||
-> impl Draw<S>
|
||||
pub fn row_north <'a, S: Screen + 'a> (north: S::Unit, height: S::Unit, content: impl Draw<'a, S>)
|
||||
-> impl Draw<'a, S>
|
||||
{
|
||||
content.exact_h(height).pull_y(north)
|
||||
}
|
||||
|
||||
pub fn col_east <S: Screen> (east: S::Unit, width: S::Unit, content: impl Draw<S>)
|
||||
-> impl Draw<S>
|
||||
pub fn col_east <'a, S: Screen + 'a> (east: S::Unit, width: S::Unit, content: impl Draw<'a, S>)
|
||||
-> impl Draw<'a, S>
|
||||
{
|
||||
content.exact_w(width).push_x(east)
|
||||
}
|
||||
|
||||
pub fn col_west <S: Screen> (west: S::Unit, width: S::Unit, content: impl Draw<S>)
|
||||
-> impl Draw<S>
|
||||
pub fn col_west <'a, S: Screen + 'a> (west: S::Unit, width: S::Unit, content: impl Draw<'a, S>)
|
||||
-> impl Draw<'a, S>
|
||||
{
|
||||
content.exact_w(width).pull_x(west)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue