pub use self::logical::*; mod logical { use crate::*; /// Thunks can be natural error boundaries! /// /// ``` /// let _ = tengri::ErrorBoundary::::new(Ok(Some("hello"))); /// let _ = tengri::ErrorBoundary::::new(Ok(None)); /// let _ = tengri::ErrorBoundary::::new(Err("draw fail".into())); /// ``` pub struct ErrorBoundary>( pub Perhaps, pub PhantomData, ); /// Late-evaluate a rendering. /// /// ``` /// let _ = tengri::Thunk::::new(|out|{}); /// ``` pub struct Thunk( pub F, pub PhantomData, ); /// Memoize a rendering. /// /// ``` /// let _ = tengri::Memo::new((), ()); /// ``` #[derive(Debug, Default)] pub struct Memo { pub value: T, pub view: Arc> } } pub use self::spatial::*; mod spatial { use crate::*; /// A binary split or layer. /// /// ``` /// let _ = tengri::Bsp::n((), ()); /// let _ = tengri::Bsp::s((), ()); /// let _ = tengri::Bsp::e((), ()); /// let _ = tengri::Bsp::w((), ()); /// let _ = tengri::Bsp::a((), ()); /// let _ = tengri::Bsp::b((), ()); /// ``` pub struct Bsp( /// Direction of split pub(crate) Direction, /// First element. pub(crate) Head, /// Second element. pub(crate) Tail, ); /// A point (X, Y). /// /// ``` /// let xy = tengri::XY(0u16, 0); /// ``` #[cfg_attr(test, derive(Arbitrary))] #[derive(Copy, Clone, Debug, Default, PartialEq)] pub struct XY( pub C, pub C ); /// A size (Width, Height). /// /// ``` /// let wh = tengri::WH(0u16, 0); /// ``` #[cfg_attr(test, derive(Arbitrary))] #[derive(Copy, Clone, Debug, Default, PartialEq)] pub struct WH( pub C, pub C ); /// Point with size. /// /// ``` /// let xywh = tengri::XYWH(0u16, 0, 0, 0); /// assert_eq!(tengri::XYWH(10u16, 10, 20, 20).center(), tengri::XY(20, 20)); /// ``` /// /// * [ ] TODO: anchor field (determines at which corner/side is X0 Y0) /// #[cfg_attr(test, derive(Arbitrary))] #[derive(Copy, Clone, Debug, Default, PartialEq)] pub struct XYWH( pub C, pub C, pub C, pub C ); /// A cardinal direction. /// /// ``` /// let direction = tengri::Direction::Above; /// ``` #[cfg_attr(test, derive(Arbitrary))] #[derive(Copy, Clone, PartialEq, Debug)] pub enum Direction { North, South, East, West, Above, Below } /// 9th of area to place. /// /// ``` /// let alignment = tengri::Alignment::Center; /// ``` #[cfg_attr(test, derive(Arbitrary))] #[derive(Debug, Copy, Clone, Default)] pub enum Alignment { #[default] Center, X, Y, NW, N, NE, E, SE, S, SW, W } /// A widget that tracks its rendered width and height. /// /// ``` /// let measure = tengri::Measure::::default(); /// ``` #[derive(Default)] pub struct Measure { pub __: PhantomData, pub x: Arc, pub y: Arc, } /// Show an item only when a condition is true. /// /// ``` /// fn test () -> impl tengri::Draw { /// tengri::when(true, "Yes") /// } /// ``` pub struct When(pub bool, pub T, pub PhantomData); pub const fn when(condition: bool, content: T) -> When { When(condition, content, PhantomData) } /// Show one item if a condition is true and another if the condition is false. /// /// ``` /// fn test () -> impl tengri::Draw { /// tengri::either(true, "Yes", "No") /// } /// ``` pub struct Either(pub bool, pub A, pub B, pub PhantomData); pub const fn either(condition: bool, content_a: A, content_b: B) -> Either { Either(condition, content_a, content_b, PhantomData) } /// Increment X and/or Y coordinate. /// /// ``` /// let pushed = tengri::Push::XY(2, 2, "Hello"); /// ``` pub enum Push { X(U, A), Y(U, A), XY(U, U, A), } /// Decrement X and/or Y coordinate. /// /// ``` /// let pulled = tengri::Pull::XY(2, 2, "Hello"); /// ``` pub enum Pull { X(U, A), Y(U, A), XY(U, U, A), } /// Set the content to fill the container. /// /// ``` /// let filled = tengri::Fill::XY("Hello"); /// ``` pub enum Fill { X(A), Y(A), XY(A) } /// Set fixed size for content. /// /// ``` /// let fixed = tengri::Fixed::XY(3, 5, "Hello"); // 3x5 /// ``` pub enum Fixed { X(U, A), Y(U, A), XY(U, U, A), } /// Set the maximum width and/or height of the content. /// /// ``` /// let maximum = tengri::Max::XY(3, 5, "Hello"); // 3x1 /// ``` pub enum Max { X(U, A), Y(U, A), XY(U, U, A), } /// Set the minimum width and/or height of the content. /// /// ``` /// let minimum = tengri::Min::XY(3, 5, "Hello"); // 5x5 /// ``` pub enum Min { X(U, A), Y(U, A), XY(U, U, A), } /// Decrease the width and/or height of the content. /// /// ``` /// let shrunk = tengri::Shrink::XY(2, 0, "Hello"); // 1x1 /// ``` pub enum Shrink { X(U, A), Y(U, A), XY(U, U, A), } /// Increaase the width and/or height of the content. /// /// ``` /// let expanded = tengri::Expand::XY(5, 3, "HELLO"); // 15x3 /// ``` pub enum Expand { X(U, A), Y(U, A), XY(U, U, A), } /// Align position of inner area to middle, side, or corner of outer area. /// /// /// ``` /// use ::tengri::*; /// let area = XYWH(10u16, 10, 20, 20); /// fn test (area: XYWH, item: &impl Draw, expected: [u16;4]) { /// //assert_eq!(Lay::layout(item, area), expected); /// //assert_eq!(Draw::layout(item, area), expected); /// }; /// /// let four = ||Fixed::XY(4, 4, ""); /// test(area, &Align::nw(four()), [10, 10, 4, 4]); /// test(area, &Align::n(four()), [18, 10, 4, 4]); /// test(area, &Align::ne(four()), [26, 10, 4, 4]); /// test(area, &Align::e(four()), [26, 18, 4, 4]); /// test(area, &Align::se(four()), [26, 26, 4, 4]); /// test(area, &Align::s(four()), [18, 26, 4, 4]); /// test(area, &Align::sw(four()), [10, 26, 4, 4]); /// test(area, &Align::w(four()), [10, 18, 4, 4]); /// /// let two_by_four = ||Fixed::XY(4, 2, ""); /// test(area, &Align::nw(two_by_four()), [10, 10, 4, 2]); /// test(area, &Align::n(two_by_four()), [18, 10, 4, 2]); /// test(area, &Align::ne(two_by_four()), [26, 10, 4, 2]); /// test(area, &Align::e(two_by_four()), [26, 19, 4, 2]); /// test(area, &Align::se(two_by_four()), [26, 28, 4, 2]); /// test(area, &Align::s(two_by_four()), [18, 28, 4, 2]); /// test(area, &Align::sw(two_by_four()), [10, 28, 4, 2]); /// test(area, &Align::w(two_by_four()), [10, 19, 4, 2]); /// ``` pub struct Align(pub Alignment, pub T); // TODO DOCUMENTME pub enum Pad { X(U, A), Y(U, A), XY(U, U, A), } // TODO DOCUMENTME pub struct Bordered(pub bool, pub S, pub W); // TODO DOCUMENTME pub struct Border(pub bool, pub S); /// TODO DOCUMENTME /// /// ``` /// use tengri::{Bounded, XYWH}; /// let area = XYWH(0, 0, 0, 0); /// let content = ""; /// let bounded: Bounded = Bounded(area, content); /// ``` pub struct Bounded(pub XYWH, pub D); /// Draws items from an iterator. /// /// ``` /// // FIXME let map = tengri::Map(||[].iter(), |_|{}); /// ``` pub struct Map where I: Iterator + Send + Sync, F: Fn() -> I + Send + Sync, { /// Function that returns iterator over stacked components pub get_iter: F, /// Function that returns each stacked component pub get_item: G, pub __: PhantomData<(O, B)>, } /// A color in OKHSL and RGB representations. #[derive(Debug, Default, Copy, Clone, PartialEq)] pub struct ItemColor { pub okhsl: Okhsl, #[cfg(feature = "tui")] pub rgb: Color, } /// A color in OKHSL and RGB with lighter and darker variants. #[derive(Debug, Default, Copy, Clone, PartialEq)] pub struct ItemTheme { pub base: ItemColor, pub light: ItemColor, pub lighter: ItemColor, pub lightest: ItemColor, pub dark: ItemColor, pub darker: ItemColor, pub darkest: ItemColor, } // TODO DOCUMENTME pub struct FieldH(pub Theme, pub Label, pub Value); // TODO DOCUMENTME pub struct FieldV(pub Theme, pub Label, pub Value); // TODO: pub struct Field { pub direction: Direction, pub label: Option, pub label_fg: Option, pub label_bg: Option, pub label_align: Option, pub value: Option, pub value_fg: Option, pub value_bg: Option, pub value_align: Option, } } #[cfg(feature = "tui")] pub use self::terminal::*; #[cfg(feature = "tui")] mod terminal { use crate::*; /// The TUI engine. /// /// ``` /// # fn main () -> tengri::Usually<()> { /// let tui = tengri::Tui::new(Box::new(vec![0u8;0]))?; /// # Ok(()) } /// ``` pub struct Tui { /// Exit flag pub exited: Arc, /// Error message pub error: Option>, /// Performance counter pub perf: PerfModel, /// Ratatui backend pub backend: RwLock>>, /// Current tnput event pub event: Option, /// Current output buffer pub buffer: RwLock, /// FIXME unused? pub area: XYWH, } #[derive(Debug)] pub struct TuiThread { pub exit: Arc, pub perf: Arc, pub join: JoinHandle<()>, } #[derive(Debug, Clone, Eq, PartialEq, PartialOrd)] pub struct TuiEvent( pub Event ); #[derive(Debug, Clone, Eq, PartialEq, PartialOrd)] pub struct TuiKey( pub Option, pub KeyModifiers ); /// TUI buffer sized by `usize` instead of `u16`. #[derive(Default)] pub struct BigBuffer { pub width: usize, pub height: usize, pub content: Vec } // TODO DOCUMENTME pub struct Foreground(pub Color, pub Item); // TODO DOCUMENTME pub struct Background(pub Color, pub Item); pub struct Modify(pub bool, pub Modifier, pub T); pub struct Styled(pub Option