1use crate::app::{App, AppResult};
2use crate::event::EventHandler;
3use crate::ui;
4use crate::utils::initialize_panic_handler;
5use color_eyre::eyre::Result;
6use crossterm::event::{DisableMouseCapture, EnableMouseCapture};
7use crossterm::terminal::{self, EnterAlternateScreen, LeaveAlternateScreen};
8use ratatui::backend::CrosstermBackend;
9use ratatui::Terminal;
10use std::io;
11
12pub type IO = std::io::Stdout;
13
14#[derive(Debug)]
19pub struct Tui {
20 terminal: Terminal<CrosstermBackend<IO>>,
22 pub events: EventHandler,
24}
25
26impl Tui {
27 pub fn new() -> Result<Self> {
29 let backend = CrosstermBackend::new(io::stdout());
31 let terminal = Terminal::new(backend)?;
32 let events = EventHandler::new(250);
33 Ok(Self { terminal, events })
34 }
35
36 pub fn init(&mut self) -> AppResult<()> {
40 terminal::enable_raw_mode()?;
41 crossterm::execute!(io::stderr(), EnterAlternateScreen, EnableMouseCapture)?;
42
43 initialize_panic_handler()?;
44
45 self.terminal.hide_cursor()?;
46 self.terminal.clear()?;
47 Ok(())
48 }
49
50 pub fn draw(&mut self, app: &mut App) -> AppResult<()> {
55 self.terminal.draw(|frame| ui::render(frame, app))?;
56 Ok(())
57 }
58
59 fn reset() -> AppResult<()> {
64 terminal::disable_raw_mode()?;
65 crossterm::execute!(io::stderr(), LeaveAlternateScreen, DisableMouseCapture)?;
66 Ok(())
67 }
68
69 pub fn exit(&mut self) -> AppResult<()> {
73 Self::reset()?;
74 self.terminal.show_cursor()?;
75 Ok(())
76 }
77}