diff --git a/src/draw/iter.rs b/src/draw/iter.rs index fa5d3de..1e5fa38 100644 --- a/src/draw/iter.rs +++ b/src/draw/iter.rs @@ -73,23 +73,23 @@ pub fn iter_west <'a, S: Screen, D: 'a, I: Iterator, U: Draw> ( pub fn row_south (south: S::Unit, height: S::Unit, content: impl Draw) -> impl Draw { - y_push(south, h_exact(height, content)) + content.exact_h(height).push_y(south) } pub fn row_north (north: S::Unit, height: S::Unit, content: impl Draw) -> impl Draw { - y_pull(north, h_exact(height, content)) + content.exact_h(height).pull_y(north) } pub fn col_east (east: S::Unit, width: S::Unit, content: impl Draw) -> impl Draw { - x_push(east, h_exact(width, content)) + content.exact_w(width).push_x(east) } pub fn col_west (west: S::Unit, width: S::Unit, content: impl Draw) -> impl Draw { - x_pull(west, h_exact(width, content)) + content.exact_w(width).pull_x(west) } diff --git a/src/draw/layout.rs b/src/draw/layout.rs index 5db0b5b..d1728bb 100644 --- a/src/draw/layout.rs +++ b/src/draw/layout.rs @@ -1,80 +1,189 @@ use crate::*; -pub enum Layout>, I: Draw> { - __(PhantomData), - MinW(X, I), - MinH(X, I), - MinWH(X, X, I), - MaxW(X, I), - MaxH(X, I), - MaxWH(X, X, I), - ExactW(X, I), - ExactH(X, I), - ExactWH(X, X, I), - ClipW(X, I), - ClipH(X, I), - ClipWH(X, X, I), +pub trait Layout: Draw + Sized { + fn full_w (self) -> impl Draw { + Full::W(self) + } + fn full_h (self) -> impl Draw { + Full::H(self) + } + fn full_wh (self) -> impl Draw { + Full::WH(self) + } + + fn exact_w >> (self, x: N) -> impl Draw { + Exact::W(self, x.into()) + } + fn exact_h >> (self, y: N) -> impl Draw { + Exact::H(self, y.into()) + } + fn exact_wh >> (self, x: N, y: N) -> impl Draw { + Exact::WH(self, x.into(), y.into()) + } + + fn min_w >> (self, x: N) -> impl Draw { + Min::W(self, x.into()) + } + fn min_h >> (self, y: N) -> impl Draw { + Min::H(self, y.into()) + } + fn min_wh >> (self, x: N, y: N) -> impl Draw { + Min::WH(self, x.into(), y.into()) + } + + fn max_w >> (self, x: N) -> impl Draw { + Max::W(self, x.into()) + } + fn max_h >> (self, y: N) -> impl Draw { + Max::H(self, y.into()) + } + fn max_wh >> (self, x: N, y: N) -> impl Draw { + Max::WH(self, x.into(), y.into()) + } + + fn pad_w >> (self, x: N) -> impl Draw { + Pad::W(self, x.into()) + } + fn pad_h >> (self, y: N) -> impl Draw { + Pad::H(self, y.into()) + } + fn pad_wh >> (self, x: N, y: N) -> impl Draw { + Pad::WH(self, x.into(), y.into()) + } + + fn pull_x >> (self, x: N) -> impl Draw { + Pull::X(self, x.into()) + } + fn pull_y >> (self, y: N) -> impl Draw { + Pull::X(self, y.into()) + } + fn pull_xy >> (self, x: N, y: N) -> impl Draw { + Pull::XY(self, x.into(), y.into()) + } + + fn push_x >> (self, x: N) -> impl Draw { + Push::X(self, x.into()) + } + fn push_y >> (self, y: N) -> impl Draw { + Push::X(self, y.into()) + } + fn push_xy >> (self, x: N, y: N) -> impl Draw { + Push::XY(self, x.into(), y.into()) + } } -impl_draw!(< - T: Screen, - X: Into>, - I: Draw, ->|self: Layout, to: T|{ - use Layout::*; - match self { - __(_) => unreachable!(), - MinW(x, it) => { - let x = x.into(); - it.draw(to) - }, - MinH(y, it) => { - let y = y.into(); - it.draw(to) - }, - MinWH(x, y, it) => { - let x = x.into(); - let y = y.into(); - it.draw(to) - }, - MaxW(x, it) => { - let x = x.into(); - it.draw(to) - }, - MaxH(y, it) => { - let y = y.into(); - it.draw(to) - }, - MaxWH(x, y, it) => { - let x = x.into(); - let y = y.into(); - it.draw(to) - }, - ExactW(x, it) => { - let x = x.into(); - it.draw(to) - }, - ExactH(y, it) => { - let y = y.into(); - it.draw(to) - }, - ExactWH(x, y, it) => { - let x = x.into(); - let y = y.into(); - it.draw(to) - }, - ClipW(x, it) => { - let x = x.into(); - it.draw(to) - }, - ClipH(y, it) => { - let y = y.into(); - it.draw(to) - }, - ClipWH(x, y, it) => { - let x = x.into(); - let y = y.into(); - it.draw(to) - }, - } +impl> Layout for T {} + +/// Use whole drawing area along one or both axes. +pub enum Full> { + __(PhantomData), + W(I), + H(I), + WH(I), +} + +impl_draw!(,>|self: Full, to: T|{ + todo!() +}); + +/// Only draw content if area is above a certain size. +/// +/// ``` +/// let min = tengri::wh_min(3, 5, "Hello"); // 5x5 +/// ``` +pub enum Push, X: Into>> { + __(PhantomData), + X(I, X), + Y(I, X), + XY(I, X, X), +} + +impl_draw!(, X: Into>,>|self: Push, to: T|{ + todo!() +}); + +/// Only draw content if area is above a certain size. +/// +/// ``` +/// let min = tengri::wh_min(3, 5, "Hello"); // 5x5 +/// ``` +pub enum Pull, X: Into>> { + __(PhantomData), + X(I, X), + Y(I, X), + XY(I, X, X), +} + +impl_draw!(, X: Into>,>|self: Pull, to: T|{ + todo!() +}); + +/// Only draw content if area is above a certain size. +/// +/// ``` +/// let min = tengri::wh_min(3, 5, "Hello"); // 5x5 +/// ``` +pub enum Min, X: Into>> { + __(PhantomData), + W(I, X), + H(I, X), + WH(I, X, X), +} + +impl_draw!(, X: Into>,>|self: Min, to: T|{ + todo!() +}); + +/// Set maximum size of of drawing area. +/// +/// ``` +/// let max = tengri::w_max(3, "Hello"); +/// let max = tengri::w_max(None, "Hello"); +/// let max = tengri::w_max(Some(3), "Hello"); +/// ``` +pub enum Max, X: Into>> { + __(PhantomData), + W(I, X), + H(I, X), + WH(I, X, X), +} + +impl_draw!(, X: Into>,>|self: Max, to: T|{ + todo!() +}); + +/// Set size of of drawing area. +/// +/// ``` +/// let max = tengri::w_max(3, "Hello"); +/// let max = tengri::w_max(None, "Hello"); +/// let max = tengri::w_max(Some(3), "Hello"); +/// ``` +pub enum Exact, X: Into>> { + __(PhantomData), + W(I, X), + H(I, X), + WH(I, X, X), +} + +impl_draw!(, X: Into>,>|self: Exact, to: T|{ + todo!() +}); + +/// Define inner drawing area. +/// +/// ``` +/// let max = tengri::w_max(3, "Hello"); +/// let max = tengri::w_max(None, "Hello"); +/// let max = tengri::w_max(Some(3), "Hello"); +/// ``` +pub enum Pad, X: Into>> { + __(PhantomData), + W(I, X), + H(I, X), + WH(I, X, X), +} + +impl_draw!(, X: Into>,>|self: Pad, to: T|{ + todo!() }); diff --git a/src/draw/xywh.rs b/src/draw/xywh.rs index c831d14..ebe866f 100644 --- a/src/draw/xywh.rs +++ b/src/draw/xywh.rs @@ -113,129 +113,3 @@ impl + Tall> Wh for T { } impl + Wh> Xywh for T {} - -/// Shrink drawing area symmetrically. -/// -/// ``` -/// let padded = tengri::wh_pad("Hello"); -/// ``` -pub const fn wh_pad (w: T::Unit, h: T::Unit, it: impl Draw) - -> impl Draw -{ - thunk(move|to: &mut T|it.draw(todo!())) -} - -/// Only draw content if area is above a certain size. -/// -/// ``` -/// let min = tengri::wh_min(3, 5, "Hello"); // 5x5 -/// ``` -pub const fn wh_min (w: Option, h: Option, it: impl Draw) - -> impl Draw -{ - thunk(move|to: &mut T|it.draw(todo!())) -} - -/// Set the maximum width and/or height of the content. -/// -/// ``` -/// let max = tengri::wh_max(Some(3), Some(5), "Hello"); -/// ``` -pub const fn wh_max (w: Option, h: Option, it: impl Draw) - -> impl Draw -{ - thunk(move|_to: &mut T|it.draw(todo!())) -} - -/// Set the maximum width and/or height of the content. -/// -/// ``` -/// let exact = tengri::wh_exact(Some(3), Some(5), "Hello"); -/// ``` -pub const fn wh_exact (w: Option, h: Option, it: impl Draw) - -> impl Draw -{ - thunk(move|_to: &mut T|it.draw(todo!())) -} - -/// Limit size of drawing area -/// ``` -/// let clipped = tengri::wh_clip(Some(3), Some(5), "Hello"); -/// ``` -pub const fn wh_clip ( - w: Option, h: Option, it: impl Draw -) -> impl Draw { - thunk(move|_to: &mut T|it.draw(todo!())) -} - -pub const fn wh_full (a: impl Draw) -> impl Draw { - todo!(); - a -} - -pub const fn w_full (a: impl Draw) -> impl Draw { - todo!(); - a -} - -pub const fn h_full (a: impl Draw) -> impl Draw { - todo!(); - a -} - -pub const fn h_max (h: Option, a: impl Draw) -> impl Draw { - wh_max(None, h, a) -} -pub const fn h_min (h: Option, a: impl Draw) -> impl Draw { - wh_min(None, h, a) -} -pub const fn h_exact (h: T::Unit, c: impl Draw) -> impl Draw { - wh_exact(None, Some(h), c) -} -pub const fn w_max (w: Option, a: impl Draw) -> impl Draw { - wh_max(w, None, a) -} -pub const fn w_min (w: Option, a: impl Draw) -> impl Draw { - wh_min(w, None, a) -} -pub const fn w_exact (w: T::Unit, c: impl Draw) -> impl Draw { - wh_exact(Some(w), None, c) -} -/// Shrink drawing area symmetrically. -/// -/// ``` -/// let padded = tengri::space::w_pad(3, "Hello"); -/// ``` -pub const fn w_pad (x: T::Unit, draw: impl Draw) -> impl Draw { - thunk(move|to: &mut T|draw.draw(todo!())) -} -/// Shrink drawing area symmetrically. -/// -/// ``` -/// let padded = tengri::space::w_pad(3, "Hello"); -/// ``` -pub const fn h_pad (x: T::Unit, draw: impl Draw) -> impl Draw { - thunk(move|to: &mut T|draw.draw(todo!())) -} - -pub const fn xy_push (x: T::Unit, y: T::Unit, a: impl Draw) -> impl Draw { - a -} - -pub const fn xy_pull (x: T::Unit, y: T::Unit, a: impl Draw) -> impl Draw { - a -} - -pub const fn x_push (x: T::Unit, a: impl Draw) -> impl Draw { - a -} -pub const fn x_pull (x: T::Unit, a: impl Draw) -> impl Draw { - a -} - -pub const fn y_push (x: T::Unit, a: impl Draw) -> impl Draw { - a -} -pub const fn y_pull (x: T::Unit, a: impl Draw) -> impl Draw { - a -} diff --git a/src/eval.rs b/src/eval.rs index b3d0a4f..6e6b8c4 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -14,23 +14,25 @@ macro_rules! eval_xy (( Some("xy") | None => $arg2, _ => panic!("{}: unsupported axis {variant:?}; try /x, /y, /xy", $name) })); + match variant { + // XY variant (can be omitted) - Some("xy") | None => xy_push( - $state.namespace($arg0?)?.unwrap(), - $state.namespace($arg1?)?.unwrap(), - cb + Some("xy") | None => cb.push_xy( + $state.namespace($arg0?)?, + $state.namespace($arg1?)?, ).draw($output), + // X variant - Some("x") => x_push( - $state.namespace($arg0?)?.unwrap(), - cb + Some("x") => cb.push_x( + $state.namespace($arg0?)?, ).draw($output), + // Y variant - Some("y") => y_push( - $state.namespace($arg0?)?.unwrap(), - cb + Some("y") => cb.push_y( + $state.namespace($arg0?)?, ).draw($output), + // Other namespace members are invalid frag => { let name = $name; @@ -41,6 +43,7 @@ macro_rules! eval_xy (( head.src()?.unwrap_or_default().split("/").next() ) } + } }}); diff --git a/src/term/border.rs b/src/term/border.rs index e8c984a..81aa69d 100644 --- a/src/term/border.rs +++ b/src/term/border.rs @@ -5,8 +5,8 @@ use super::*; /// ``` /// /// TODO /// ``` -pub const fn border (on: bool, style: impl BorderStyle, draw: impl Draw) -> impl Draw { - let content = wh_pad(1, 1, draw); +pub fn border (on: bool, style: impl BorderStyle, draw: impl Draw) -> impl Draw { + let content = draw.pad_wh(1, 1); let outline = when(on, thunk(move|to: &mut Tui|{ let XYWH(x, y, w, h) = to.1; if w > 0 && h > 0 { diff --git a/src/term/output.rs b/src/term/output.rs index eefb9e8..e0ff044 100644 --- a/src/term/output.rs +++ b/src/term/output.rs @@ -165,11 +165,11 @@ mod phat { pub const HI: &'static str = "▀"; /// A phat line pub fn lo (fg: Color, bg: Color) -> impl Draw { - h_exact(1, fg_bg(fg, bg, x_repeat(self::phat::LO))) + fg_bg(fg, bg, x_repeat(self::phat::LO)).exact_h(1) } /// A phat line pub fn hi (fg: Color, bg: Color) -> impl Draw { - h_exact(1, fg_bg(fg, bg, x_repeat(self::phat::HI))) + fg_bg(fg, bg, x_repeat(self::phat::HI)).exact_h(1) } } @@ -253,10 +253,10 @@ pub const fn button_3 <'a> ( /// /// TODO /// ``` pub fn phat (w: u16, h: u16, [fg, bg, hi, lo]: [Color;4], draw: impl Draw) -> impl Draw { - let top = w_exact(1, self::phat::lo(bg, hi)); - let low = w_exact(1, self::phat::hi(bg, lo)); + let top = self::phat::lo(bg, hi).exact_h(1); + let low = self::phat::hi(bg, lo).exact_h(1); let draw = fg_bg(fg, bg, draw); - wh_min(Some(w), Some(h), south(top, north(low, draw))) + south(top, north(low, draw)).min_wh(w, h) } fn x_scroll () -> impl Draw {