diff --git a/examples/hello_world.rs b/examples/hello_world.rs index e2c6e94..391075e 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -12,19 +12,13 @@ fn draw(f: &mut Frame) { } fn render_frame(term: &mut Terminal) { - loop { - // Must be called before rendering, otherwise the terminal has out-of-date - // size information and will present garbage. + // Must be called before rendering, otherwise the terminal has out-of-date + // size information and will present garbage. + term.autoresize().unwrap(); + draw(term.frame()); + while term.present().unwrap() { term.autoresize().unwrap(); - draw(term.frame()); - term.present().unwrap(); - - if term.measuring_required() { - term.measure_widths().unwrap(); - } else { - break; - } } } diff --git a/examples/hello_world_widgets.rs b/examples/hello_world_widgets.rs index a0dc4d1..23dc43b 100644 --- a/examples/hello_world_widgets.rs +++ b/examples/hello_world_widgets.rs @@ -1,11 +1,11 @@ -use std::convert::Infallible; +use std::io; use crossterm::event::Event; use crossterm::style::Stylize; use toss::widgets::{BorderLook, Text}; use toss::{Style, Styled, Terminal, Widget, WidgetExt}; -fn widget() -> impl Widget { +fn widget() -> impl Widget { let styled = Styled::new("Hello world!", Style::new().dark_green()) .then_plain("\n") .then("Press any key to exit", Style::new().on_dark_blue()); @@ -22,19 +22,13 @@ fn widget() -> impl Widget { } fn render_frame(term: &mut Terminal) { - loop { - // Must be called before rendering, otherwise the terminal has out-of-date - // size information and will present garbage. + // Must be called before rendering, otherwise the terminal has out-of-date + // size information and will present garbage. + term.autoresize().unwrap(); + widget().draw(term.frame()).unwrap(); + while term.present().unwrap() { term.autoresize().unwrap(); - widget().draw(term.frame()).unwrap(); - term.present().unwrap(); - - if term.measuring_required() { - term.measure_widths().unwrap(); - } else { - break; - } } } diff --git a/examples/overlapping_graphemes.rs b/examples/overlapping_graphemes.rs index 562553f..0a8f90b 100644 --- a/examples/overlapping_graphemes.rs +++ b/examples/overlapping_graphemes.rs @@ -49,19 +49,13 @@ fn draw(f: &mut Frame) { } fn render_frame(term: &mut Terminal) { - loop { - // Must be called before rendering, otherwise the terminal has out-of-date - // size information and will present garbage. + // Must be called before rendering, otherwise the terminal has out-of-date + // size information and will present garbage. + term.autoresize().unwrap(); + draw(term.frame()); + while term.present().unwrap() { term.autoresize().unwrap(); - draw(term.frame()); - term.present().unwrap(); - - if term.measuring_required() { - term.measure_widths().unwrap(); - } else { - break; - } } } diff --git a/examples/text_wrapping.rs b/examples/text_wrapping.rs index 1943fae..21f0ffe 100644 --- a/examples/text_wrapping.rs +++ b/examples/text_wrapping.rs @@ -38,19 +38,13 @@ fn draw(f: &mut Frame) { } fn render_frame(term: &mut Terminal) { - loop { - // Must be called before rendering, otherwise the terminal has out-of-date - // size information and will present garbage. + // Must be called before rendering, otherwise the terminal has out-of-date + // size information and will present garbage. + term.autoresize().unwrap(); + draw(term.frame()); + while term.present().unwrap() { term.autoresize().unwrap(); - draw(term.frame()); - term.present().unwrap(); - - if term.measuring_required() { - term.measure_widths().unwrap(); - } else { - break; - } } } diff --git a/src/terminal.rs b/src/terminal.rs index 2f1bf5b..2828600 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -91,16 +91,6 @@ impl Terminal { self.frame.widthdb.active } - pub fn measuring_required(&self) -> bool { - self.frame.widthdb.measuring_required() - } - - pub fn measure_widths(&mut self) -> io::Result<()> { - self.frame.widthdb.measure_widths(&mut self.out)?; - self.full_redraw = true; - Ok(()) - } - /// Resize the frame and other internal buffers if the terminal size has /// changed. pub fn autoresize(&mut self) -> io::Result<()> { @@ -124,11 +114,27 @@ impl Terminal { } /// Display the current frame on the screen and prepare the next frame. - /// Returns `true` if an immediate redraw is required. + /// + /// Before drawing and presenting a frame, [`Self::autoresize`] should be + /// called. [`Self::present`] does **not** call it automatically. + /// + /// If width measurements are turned on, any new graphemes encountered since + /// the last [`Self::present`] call will be measured. This can lead to the + /// screen flickering or being mostly blank until measurements complete. + /// + /// Returns `true` if any new graphemes were measured. Since their widths + /// may have changed because of the measurements, the application using this + /// [`Terminal`] should re-draw and re-present the current frame. /// /// After calling this function, the frame returned by [`Self::frame`] will /// be empty again and have no cursor position. - pub fn present(&mut self) -> io::Result<()> { + pub fn present(&mut self) -> io::Result { + let measure = self.frame.widthdb.measuring_required(); + if measure { + self.frame.widthdb.measure_widths(&mut self.out)?; + self.full_redraw = true; + } + if self.full_redraw { io::stdout().queue(Clear(ClearType::All))?; self.prev_frame_buffer.reset(); // Because the screen is now empty @@ -142,7 +148,7 @@ impl Terminal { mem::swap(&mut self.prev_frame_buffer, &mut self.frame.buffer); self.frame.reset(); - Ok(()) + Ok(measure) } fn draw_differences(&mut self) -> io::Result<()> {