1use crate::app::{App, AppResult};
2use crate::event::EventHandler;
3use crate::ui;
4use crossterm::event::{DisableMouseCapture, EnableMouseCapture};
5use crossterm::terminal::{self, EnterAlternateScreen, LeaveAlternateScreen};
6use std::io;
7use tui::backend::Backend;
8use tui::Terminal;
9
10#[derive(Debug)]
15pub struct Tui<B: Backend> {
16 terminal: Terminal<B>,
18 pub events: EventHandler,
20}
21
22impl<B: Backend> Tui<B> {
23 pub fn new(terminal: Terminal<B>, events: EventHandler) -> Self {
25 Self { terminal, events }
26 }
27
28 pub fn init(&mut self) -> AppResult<()> {
32 terminal::enable_raw_mode()?;
33 crossterm::execute!(io::stderr(), EnterAlternateScreen, EnableMouseCapture)?;
34 self.terminal.hide_cursor()?;
35 self.terminal.clear()?;
36
37 let original_hook = std::panic::take_hook();
38 std::panic::set_hook(Box::new(move |panic| {
39 terminal::disable_raw_mode().unwrap();
40 crossterm::execute!(io::stderr(), LeaveAlternateScreen, DisableMouseCapture).unwrap();
41 original_hook(panic)
42 }));
43
44 Ok(())
45 }
46
47 pub fn draw(&mut self, app: &mut App) -> AppResult<()> {
52 self.terminal.draw(|frame| ui::render(app, frame))?;
53 Ok(())
54 }
55
56 pub fn exit(&mut self) -> AppResult<()> {
60 terminal::disable_raw_mode()?;
61 crossterm::execute!(io::stderr(), LeaveAlternateScreen, DisableMouseCapture)?;
62 self.terminal.show_cursor()?;
63 Ok(())
64 }
65}