use std::{
error::Error,
io::{self, stdout, Stdout},
};
use crossterm::{
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use ratatui::{
buffer::Buffer,
layout::Rect,
prelude::CrosstermBackend,
widgets::{StatefulWidget, Widget},
};
pub type WidgetBackend = CrosstermBackend<Stdout>;
pub type WidgetTerminal = ratatui::Terminal<WidgetBackend>;
#[derive(Debug, Hash)]
pub struct WidgetFrame {
pub(crate) cursor_position: Option<(u16, u16)>,
pub(crate) viewport_area: Rect,
pub(crate) buffer: Buffer,
pub(crate) count: usize,
}
impl WidgetFrame {
pub const fn size(&self) -> Rect {
self.viewport_area
}
pub fn render_widget<W: Widget>(&mut self, widget: W, area: Rect) {
widget.render(area, &mut self.buffer);
}
pub fn set_cursor(&mut self, x: u16, y: u16) {
self.cursor_position = Some((x, y));
}
pub fn buffer_mut(&mut self) -> &mut Buffer {
&mut self.buffer
}
pub const fn count(&self) -> usize {
self.count
}
}
pub fn setup_terminal() -> Result<WidgetTerminal, io::Error> {
enable_raw_mode()?;
let mut stdout = stdout();
execute!(stdout, EnterAlternateScreen)?;
let backend = CrosstermBackend::new(stdout);
let terminal = WidgetTerminal::new(backend)?;
Ok(terminal)
}
pub fn restore_terminal(mut terminal: WidgetTerminal) -> Result<(), io::Error> {
disable_raw_mode()?;
execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
Ok(())
}
pub fn reset_terminal() -> Result<(), io::Error> {
disable_raw_mode()?;
execute!(stdout(), LeaveAlternateScreen)?;
Ok(())
}