xref: /DragonOS/tools/debugging/logmonitor/src/tui.rs (revision 7b32f5080f42bcbf7d2421013f3ea53c776a063c)
1*7b32f508SLoGin use crate::app::{App, AppResult};
2*7b32f508SLoGin use crate::event::EventHandler;
3*7b32f508SLoGin use crate::ui;
4*7b32f508SLoGin use crossterm::event::DisableMouseCapture;
5*7b32f508SLoGin use crossterm::terminal::{self, EnterAlternateScreen, LeaveAlternateScreen};
6*7b32f508SLoGin use std::io;
7*7b32f508SLoGin use std::panic;
8*7b32f508SLoGin 
9*7b32f508SLoGin use ratatui::backend::Backend;
10*7b32f508SLoGin use ratatui::Terminal;
11*7b32f508SLoGin 
12*7b32f508SLoGin /// Representation of a terminal user interface.
13*7b32f508SLoGin ///
14*7b32f508SLoGin /// It is responsible for setting up the terminal,
15*7b32f508SLoGin /// initializing the interface and handling the draw events.
16*7b32f508SLoGin #[derive(Debug)]
17*7b32f508SLoGin pub struct Tui<B: Backend> {
18*7b32f508SLoGin     /// Interface to the Terminal.
19*7b32f508SLoGin     terminal: Terminal<B>,
20*7b32f508SLoGin     /// Terminal event handler.
21*7b32f508SLoGin     pub events: EventHandler,
22*7b32f508SLoGin }
23*7b32f508SLoGin 
24*7b32f508SLoGin impl<B: Backend> Tui<B> {
25*7b32f508SLoGin     /// Constructs a new instance of [`Tui`].
new(terminal: Terminal<B>, events: EventHandler) -> Self26*7b32f508SLoGin     pub fn new(terminal: Terminal<B>, events: EventHandler) -> Self {
27*7b32f508SLoGin         Self { terminal, events }
28*7b32f508SLoGin     }
29*7b32f508SLoGin 
30*7b32f508SLoGin     /// Initializes the terminal interface.
31*7b32f508SLoGin     ///
32*7b32f508SLoGin     /// It enables the raw mode and sets terminal properties.
init(&mut self) -> AppResult<()>33*7b32f508SLoGin     pub fn init(&mut self) -> AppResult<()> {
34*7b32f508SLoGin         terminal::enable_raw_mode()?;
35*7b32f508SLoGin         crossterm::execute!(io::stderr(), EnterAlternateScreen, DisableMouseCapture)?;
36*7b32f508SLoGin 
37*7b32f508SLoGin         // Define a custom panic hook to reset the terminal properties.
38*7b32f508SLoGin         // This way, you won't have your terminal messed up if an unexpected error happens.
39*7b32f508SLoGin         let panic_hook = panic::take_hook();
40*7b32f508SLoGin         panic::set_hook(Box::new(move |panic| {
41*7b32f508SLoGin             Self::reset().expect("failed to reset the terminal");
42*7b32f508SLoGin             panic_hook(panic);
43*7b32f508SLoGin         }));
44*7b32f508SLoGin 
45*7b32f508SLoGin         self.terminal.hide_cursor()?;
46*7b32f508SLoGin         self.terminal.clear()?;
47*7b32f508SLoGin         Ok(())
48*7b32f508SLoGin     }
49*7b32f508SLoGin 
50*7b32f508SLoGin     /// [`Draw`] the terminal interface by [`rendering`] the widgets.
51*7b32f508SLoGin     ///
52*7b32f508SLoGin     /// [`Draw`]: ratatui::Terminal::draw
53*7b32f508SLoGin     /// [`rendering`]: crate::ui:render
draw(&mut self, app: &mut App) -> AppResult<()>54*7b32f508SLoGin     pub fn draw(&mut self, app: &mut App) -> AppResult<()> {
55*7b32f508SLoGin         self.terminal.draw(|frame| ui::render(app, frame))?;
56*7b32f508SLoGin         Ok(())
57*7b32f508SLoGin     }
58*7b32f508SLoGin 
59*7b32f508SLoGin     /// Resets the terminal interface.
60*7b32f508SLoGin     ///
61*7b32f508SLoGin     /// This function is also used for the panic hook to revert
62*7b32f508SLoGin     /// the terminal properties if unexpected errors occur.
reset() -> AppResult<()>63*7b32f508SLoGin     fn reset() -> AppResult<()> {
64*7b32f508SLoGin         terminal::disable_raw_mode()?;
65*7b32f508SLoGin         crossterm::execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture)?;
66*7b32f508SLoGin         Ok(())
67*7b32f508SLoGin     }
68*7b32f508SLoGin 
69*7b32f508SLoGin     /// Exits the terminal interface.
70*7b32f508SLoGin     ///
71*7b32f508SLoGin     /// It disables the raw mode and reverts back the terminal properties.
exit(&mut self) -> AppResult<()>72*7b32f508SLoGin     pub fn exit(&mut self) -> AppResult<()> {
73*7b32f508SLoGin         Self::reset()?;
74*7b32f508SLoGin         self.terminal.show_cursor()?;
75*7b32f508SLoGin         Ok(())
76*7b32f508SLoGin     }
77*7b32f508SLoGin }
78