diff --git a/examples/hello_world_widgets.rs b/examples/hello_world_widgets.rs index 23dc43b..27c81c1 100644 --- a/examples/hello_world_widgets.rs +++ b/examples/hello_world_widgets.rs @@ -22,14 +22,7 @@ fn widget() -> impl Widget { } fn render_frame(term: &mut Terminal) { - // 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(); - } + while term.present_widget(widget()).unwrap() {} } fn main() { diff --git a/src/terminal.rs b/src/terminal.rs index 2828600..1d9175f 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -13,8 +13,13 @@ use crossterm::terminal::{Clear, ClearType, EnterAlternateScreen, LeaveAlternate use crossterm::{ExecutableCommand, QueueableCommand}; use crate::buffer::Buffer; -use crate::{Frame, Size, WidthDb}; +use crate::{AsyncWidget, Frame, Size, Widget, WidthDb}; +/// Wrapper that manages terminal output. +/// +/// This struct wraps around stdout (usually) and handles showing things on the +/// terminal. It cleans up after itself when droppped, so it shouldn't leave the +/// terminal in a weird state even if your program crashes. pub struct Terminal { /// Render target. out: Box, @@ -151,6 +156,36 @@ impl Terminal { Ok(measure) } + /// Display a [`Widget`] on the screen. + /// + /// Internally calls [`Self::autoresize`] and [`Self::present`], and passes + /// on the value returned by [`Self::present`]. + pub fn present_widget(&mut self, widget: W) -> Result + where + E: From, + W: Widget, + { + self.autoresize()?; + widget.draw(self.frame())?; + let dirty = self.present()?; + Ok(dirty) + } + + /// Display an [`AsyncWidget`] on the screen. + /// + /// Internally calls [`Self::autoresize`] and [`Self::present`], and passes + /// on the value returned by [`Self::present`]. + pub async fn present_async_widget(&mut self, widget: W) -> Result + where + E: From, + W: AsyncWidget, + { + self.autoresize()?; + widget.draw(self.frame()).await?; + let dirty = self.present()?; + Ok(dirty) + } + fn draw_differences(&mut self) -> io::Result<()> { for (x, y, cell) in self.frame.buffer.cells() { if self.prev_frame_buffer.at(x, y) == cell {