use ratatui::backend::{Backend, ClearType, CrosstermBackend, WindowSize};
use ratatui::buffer::Cell;
use ratatui::layout::{Position, Size};
use std::io::{self, Stdout, Write};
use crate::scroll::Shift;
type Held = Vec<(u16, u16, Cell)>;
pub struct HeldBackend {
inner: CrosstermBackend<Stdout>,
held: Held,
}
impl HeldBackend {
pub fn new() -> Self {
Self {
inner: CrosstermBackend::new(io::stdout()),
held: Vec::new(),
}
}
pub fn release(&mut self) -> io::Result<()> {
let held = std::mem::take(&mut self.held);
self.paint(&held)
}
pub fn scroll_then_paint(
&mut self,
shift: Shift,
cells: &[(u16, u16, Cell)],
) -> io::Result<()> {
self.held.clear();
write!(
&mut self.inner,
"\x1b[0m\x1b[{};{}r\x1b[{}S\x1b[r",
shift.top + 1,
shift.top + shift.h,
shift.k
)?;
self.paint(cells)
}
fn paint(&mut self, cells: &[(u16, u16, Cell)]) -> io::Result<()> {
self.inner.draw(cells.iter().map(|(x, y, c)| (*x, *y, c)))?;
Backend::flush(&mut self.inner)
}
}
impl Backend for HeldBackend {
fn draw<'a, I>(&mut self, content: I) -> io::Result<()>
where
I: Iterator<Item = (u16, u16, &'a Cell)>,
{
self.held.extend(content.map(|(x, y, c)| (x, y, c.clone())));
Ok(())
}
fn append_lines(&mut self, n: u16) -> io::Result<()> {
self.inner.append_lines(n)
}
fn hide_cursor(&mut self) -> io::Result<()> {
self.inner.hide_cursor()
}
fn show_cursor(&mut self) -> io::Result<()> {
self.inner.show_cursor()
}
fn get_cursor_position(&mut self) -> io::Result<Position> {
self.inner.get_cursor_position()
}
fn set_cursor_position<P: Into<Position>>(&mut self, position: P) -> io::Result<()> {
self.inner.set_cursor_position(position)
}
fn clear(&mut self) -> io::Result<()> {
self.inner.clear()
}
fn clear_region(&mut self, clear_type: ClearType) -> io::Result<()> {
self.inner.clear_region(clear_type)
}
fn size(&self) -> io::Result<Size> {
self.inner.size()
}
fn window_size(&mut self) -> io::Result<WindowSize> {
self.inner.window_size()
}
fn flush(&mut self) -> io::Result<()> {
Backend::flush(&mut self.inner)
}
}