Add Terminal::{present_widget, present_async_widget}

This commit is contained in:
Joscha 2023-02-17 14:00:28 +01:00
parent ed14ea9023
commit ac2546ba97
2 changed files with 37 additions and 9 deletions

View file

@ -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<dyn Write>,
@ -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<E, W>(&mut self, widget: W) -> Result<bool, E>
where
E: From<io::Error>,
W: Widget<E>,
{
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<E, W>(&mut self, widget: W) -> Result<bool, E>
where
E: From<io::Error>,
W: AsyncWidget<E>,
{
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 {