use std::io;
use crate::backend::Backend;
use crate::buffer::TerminalBuffer;
pub struct Screen<B: Backend> {
backend: B,
current: TerminalBuffer,
next: TerminalBuffer,
last_size: (u16, u16),
force_full_redraw: bool,
}
impl<B: Backend> Screen<B> {
pub fn new(backend: B, width: u16, height: u16) -> Self {
Self {
backend,
current: TerminalBuffer::new(width, height),
next: TerminalBuffer::new(width, height),
last_size: (width, height),
force_full_redraw: false,
}
}
pub fn buffer_mut(&mut self) -> &mut TerminalBuffer {
&mut self.next
}
pub fn buffer(&self) -> &TerminalBuffer {
&self.next
}
pub fn backend(&self) -> &B {
&self.backend
}
pub fn backend_mut(&mut self) -> &mut B {
&mut self.backend
}
pub fn size(&self) -> (u16, u16) {
self.last_size
}
pub fn resize(&mut self, width: u16, height: u16) {
if (width, height) == self.last_size {
return;
}
self.current.resize(width, height);
self.next.resize(width, height);
self.last_size = (width, height);
self.force_full_redraw = true;
}
pub fn flush(&mut self) -> io::Result<()> {
if self.force_full_redraw {
self.force_full_redraw = false;
let cells = self.next.all_cells();
self.backend.begin_sync()?;
self.backend.clear()?;
self.backend.draw(cells.into_iter())?;
self.backend.flush()?;
self.backend.end_sync()?;
self.backend.flush()?;
} else {
let changes = self.next.diff(&self.current);
if !changes.is_empty() {
self.backend.begin_sync()?;
self.backend.draw(changes.into_iter())?;
self.backend.flush()?;
self.backend.end_sync()?;
self.backend.flush()?;
}
}
std::mem::swap(&mut self.current, &mut self.next);
self.current.clear_dirty();
self.next.clear_dirty();
Ok(())
}
}