diff --git a/dizzle b/dizzle index b6c1bb5..3d04622 160000 --- a/dizzle +++ b/dizzle @@ -1 +1 @@ -Subproject commit b6c1bb5f9400c28de1709df78c18e0d4d5618a15 +Subproject commit 3d04622e4266eac65021da6cd3d378e84a843b87 diff --git a/src/layout/axis.rs b/src/layout/axis.rs index 1a02ab8..5d1767b 100644 --- a/src/layout/axis.rs +++ b/src/layout/axis.rs @@ -454,5 +454,5 @@ impl<'a, S: Screen, T: Draw> LayoutPull<'a, S> for T {} impl<'a, S: Screen, T: Draw> LayoutPad<'a, S> for T {} pub fn check_layout <'a> (t: impl Draw) -> Drawn { - Tui::Layout(XYWH(1u16, 1, 80, 25)).size(None, t) + Tui(XYWH(1u16, 1, 80, 25), None).size(None, t) } diff --git a/src/layout/azimuth.rs b/src/layout/azimuth.rs index c948a9a..8c6fc86 100644 --- a/src/layout/azimuth.rs +++ b/src/layout/azimuth.rs @@ -211,22 +211,25 @@ pub fn bar_areas <'a, S: Screen> ( let XYWH(x0, y0, w0, h0) = to.area(); Ok(match split { Split::South => ( - to.size(XYWH(x0, y0, w0, n), a)?, - to.size(XYWH(x0, y0 + n, w0, h0 - n), b)?, + Some(XYWH(x0, y0, w0, n)), + Some(XYWH(x0, y0 + n, w0, h0 - n)), ), Split::East => ( - to.size(XYWH(x0, y0, n, h0), a)?, - to.size(XYWH(x0 + n, y0, w0 - n, h0), b)?, + Some(XYWH(x0, y0, n, h0)), + Some(XYWH(x0 + n, y0, w0 - n, h0)), ), Split::North => ( - to.size(XYWH(x0, y0 + h0 - n, w0, n), a)?, - to.size(XYWH(x0, y0, w0, h0 - n), b)?, + Some(XYWH(x0, y0 + h0 - n, w0, n)), + Some(XYWH(x0, y0, w0, h0 - n)), ), Split::West => ( - to.size(XYWH(x0 + w0 - n, y0, n, h0), a)?, - to.size(XYWH(x0, y0, w0 - n, h0), b)?, + Some(XYWH(x0 + w0 - n, y0, n, h0)), + Some(XYWH(x0, y0, w0 - n, h0)), + ), + Split::Above | Split::Below => ( + Some(XYWH(x0, y0, w0, h0)), + Some(XYWH(x0, y0, w0, h0)), ), - _ => todo!() }) } @@ -238,7 +241,7 @@ pub struct Pair(Split, A, B); /// use ::tengri::*; /// use Split::*; /// fn size_of <'a, A: Draw, B: Draw> (stack: &Pair) -> Drawn { -/// Tui::Layout(XYWH(0, 0, 80, 25)).size(None, stack) +/// Tui(XYWH(0, 0, 80, 25), None).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))); @@ -293,11 +296,11 @@ fn draw_stacks <'a, S: Screen> ( /// ``` /// # use ::tengri::*; fn test_stack_areas () -> Usually<()> { /// let area = XYWH(0u16, 0, 80, 25); -/// assert_eq!(stack_areas(&Split::East, &mut Tui::Layout(area), &"foo", &"bar")?, ( +/// assert_eq!(stack_areas(&Split::East, &mut Tui(area, None), &"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")?, ( +/// assert_eq!(stack_areas(&Split::South, &mut Tui(area, None), &"foo", &"bar")?, ( /// Some(XYWH(0u16, 0, 3, 1)), /// Some(XYWH(0u16, 1, 3, 1)), /// )); @@ -522,7 +525,7 @@ pub const fn below <'a, S: Screen, A: Draw, B: Draw> (a: A, b: B) -> impl } #[cfg(test)] #[test] fn test_align () -> Usually<()> { - let mut screen = Tui::Layout(XYWH(0, 0, 80, 25)); + let mut screen = Tui(XYWH(0, 0, 80, 25), None); assert_eq!("FOOBAR\nKILROY".draw(&mut screen)?, Some(XYWH(0, 0, 6, 2))); assert_eq!("FOOBAR\nKILROY".align_nw().draw(&mut screen)?, Some(XYWH(0, 0, 6, 2))); assert_eq!("FOOBAR\nKILROY".align_n().draw(&mut screen)?, Some(XYWH(37, 0, 6, 2))); diff --git a/src/lib.rs b/src/lib.rs index 92d0b69..2d617e0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1792,67 +1792,7 @@ pub trait AsMutOpt { fn as_mut_opt (&mut self) -> Option<&mut T>; } } #[cfg(feature = "text")] pub use self::text::*; -#[cfg(feature = "text")] mod text { - #![allow(unused)] - - pub(crate) use ::unicode_width::*; - - /// Displays an owned [str]-like with fixed maximum width. - /// - /// Width is computed using [unicode_width]. - pub struct TrimString>(pub u16, pub T); - - impl> AsRef for TrimString { - fn as_ref (&self) -> &str { - self.1.as_ref() - } - } - - impl<'a, T: AsRef> TrimString { - fn to_ref (&self) -> TrimStr<'_, T> { - TrimStr(self.0, &self.1) - } - } - - /// Displays a borrowed [str]-like with fixed maximum width - /// - /// Width is computed using [unicode_width]. - pub struct TrimStr<'a, T: AsRef>(pub u16, pub &'a T); - - impl> AsRef for TrimStr<'_, T> { - fn as_ref (&self) -> &str { - self.1.as_ref() - } - } - - pub(crate) fn width_chars_max (max: u16, text: impl AsRef) -> u16 { - let mut width: u16 = 0; - let mut chars = text.as_ref().chars(); - while let Some(c) = chars.next() { - width += c.width().unwrap_or(0) as u16; - if width >= max { - break - } - } - return width - } - - /// Trim string with [unicode_width]. - pub fn trim_string (max_width: usize, input: impl AsRef) -> String { - let input = input.as_ref(); - let mut output = Vec::with_capacity(input.len()); - let mut width: usize = 1; - let mut chars = input.chars(); - while let Some(c) = chars.next() { - if width > max_width { - break - } - output.push(c); - width += c.width().unwrap_or(0); - } - return output.into_iter().collect() - } -} +#[cfg(feature = "text")] mod text; #[cfg(feature = "term")] pub use self::term::*; #[cfg(feature = "term")] mod term; diff --git a/src/term.rs b/src/term.rs index dffe505..a5ed594 100644 --- a/src/term.rs +++ b/src/term.rs @@ -29,6 +29,7 @@ mod modify; pub use self::modify::*; mod phat; pub use self::phat::*; mod repeat; pub use self::repeat::*; mod scroll; pub use self::scroll::*; +#[cfg(feature = "text")] mod text; #[macro_export] macro_rules! tui_app { ($Struct:ident { $($fields:tt)* }) => { @@ -75,30 +76,44 @@ mod scroll; pub use self::scroll::*; } /// Terminal output. -pub enum Tui { - /// Draw mode: updates contained [Buffer]. - Draw ( - /// Ratatui buffer; area is screen size - Buffer, - /// Current draw area - XYWH - ), - /// Discard mode: only computes sizes - Layout ( - /// Draw area; no buffer - XYWH - ) +pub struct Tui( + /// Current draw area + pub(crate) XYWH, + /// Ratatui buffer. + /// + /// - Area is screen size. + /// - If present, we're in draw mode. + /// - If absent, we're in layout mode. + pub(crate) Option +); + +impl AsRef> for Tui { + fn as_ref (&self) -> &XYWH { + &self.0 + } +} + +impl From<&Tui> for XYWH { + fn from (screen: &Tui) -> XYWH { + screen.0 + } +} + +impl<'a: 'b, 'b> From<&'a mut Tui> for &'b mut XYWH { + fn from (screen: &'a mut Tui) -> &'b mut XYWH { + &mut screen.0 + } } impl Screen for Tui { type Unit = u16; fn area (&self) -> XYWH { - self.into() + self.0 } fn size <'a> ( &mut self, area: impl Into>>, draw: impl Draw, ) -> Drawn { - Self::Layout(self.area()).clip(area, &|to|draw.draw(to)) + Self(self.area(), None).clip(area, &|to|draw.draw(to)) } fn draw <'a> ( &mut self, area: impl Into>>, draw: impl Draw @@ -111,10 +126,12 @@ impl Screen for Tui { let prev = self.area(); if let Some(area) = area.into() { *self.area_mut() = area.into(); + let result = draw(self); + *self.area_mut() = prev; + result + } else { + draw(self) } - let result = draw(self); - *self.area_mut() = prev; - result } } @@ -177,24 +194,28 @@ impl Tui { disable_raw_mode().map_err(Into::into) } pub fn new (width: u16, height: u16) -> Self { - Self::Draw(Buffer::empty(Rect { x: 0, y: 0, width, height }), XYWH(0, 0, width, height)) + Self( + XYWH(0, 0, width, height), + Some(Buffer::empty(Rect { x: 0, y: 0, width, height })) + ) } pub fn resize (&mut self, back: &mut CrosstermBackend, width: u16, height: u16) { let size = Rect { x: 0, y: 0, width, height }; - if let Self::Draw(buffer, ..) = self { + self.buffer().map(|buffer|{ if buffer.area != size { back.clear_region(ClearType::All).unwrap(); buffer.resize(size); buffer.reset(); } - } + }); } pub fn redraw <'b, W: Write> ( &'b mut self, back: &mut CrosstermBackend, next: &'b mut Self ) { - if let Self::Draw(prev, ..) = self && let Self::Draw(next, ..) = next { + if let Some(prev) = self.buffer() + && let Some(next) = next.buffer() { let updates = prev.diff(&next); back.draw(updates.into_iter()).expect("failed to render"); Backend::flush(back).expect("failed to flush output new"); @@ -204,7 +225,7 @@ impl Tui { } pub fn update (&mut self, callback: &impl Fn(&mut Cell, u16, u16)) -> XYWH { let XYWH(x0, y0, w, h) = self.area(); - if let Self::Draw(buffer, ..) = self { + if let Some(buffer) = self.buffer() { for row in 0..h { let y = y0 + row; for col in 0..w { @@ -220,7 +241,7 @@ impl Tui { self.xywh() } pub fn blit (&mut self, text: &impl AsRef, x: u16, y: u16, style: Option