sim_restaurant/tui/
terminal.rs1use std::{io, panic};
4
5use crossterm::event::{DisableMouseCapture, EnableMouseCapture};
6use crossterm::terminal::{self, EnterAlternateScreen, LeaveAlternateScreen};
7use ratatui::Terminal;
8use ratatui::backend::Backend;
9
10use crate::tui::event::AppResult;
11
12#[derive(Debug)]
13pub struct Tui<B: Backend> {
14 terminal: Terminal<B>,
15}
16
17impl<B: Backend> Tui<B> {
18 pub fn new(terminal: Terminal<B>) -> Self {
19 Self { terminal }
20 }
21
22 pub fn init(&mut self) -> AppResult<()>
23 where
24 <B as Backend>::Error: 'static,
25 {
26 terminal::enable_raw_mode()?;
27 crossterm::execute!(io::stderr(), EnterAlternateScreen, EnableMouseCapture)?;
28
29 let panic_hook = panic::take_hook();
30 panic::set_hook(Box::new(move |panic| {
31 Self::reset().expect("failed to reset the terminal");
32 panic_hook(panic);
33 }));
34
35 self.terminal.hide_cursor()?;
36 self.terminal.clear()?;
37 Ok(())
38 }
39
40 pub fn draw(&mut self, app: &mut crate::tui::app::App) -> AppResult<()>
41 where
42 <B as Backend>::Error: 'static,
43 {
44 self.terminal
45 .draw(|frame| crate::tui::ui::render(app, frame))?;
46 Ok(())
47 }
48
49 fn reset() -> AppResult<()> {
50 terminal::disable_raw_mode()?;
51 crossterm::execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture)?;
52 Ok(())
53 }
54
55 pub fn exit(&mut self) -> AppResult<()>
56 where
57 <B as Backend>::Error: 'static,
58 {
59 Self::reset()?;
60 self.terminal.show_cursor()?;
61 Ok(())
62 }
63}