1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- use crate::app::{App, AppResult};
- use crate::event::EventHandler;
- use crate::ui;
- use crossterm::event::DisableMouseCapture;
- use crossterm::terminal::{self, EnterAlternateScreen, LeaveAlternateScreen};
- use std::io;
- use std::panic;
- use ratatui::backend::Backend;
- use ratatui::Terminal;
- /// Representation of a terminal user interface.
- ///
- /// It is responsible for setting up the terminal,
- /// initializing the interface and handling the draw events.
- #[derive(Debug)]
- pub struct Tui<B: Backend> {
- /// Interface to the Terminal.
- terminal: Terminal<B>,
- /// Terminal event handler.
- pub events: EventHandler,
- }
- impl<B: Backend> Tui<B> {
- /// Constructs a new instance of [`Tui`].
- pub fn new(terminal: Terminal<B>, events: EventHandler) -> Self {
- Self { terminal, events }
- }
- /// Initializes the terminal interface.
- ///
- /// It enables the raw mode and sets terminal properties.
- pub fn init(&mut self) -> AppResult<()> {
- terminal::enable_raw_mode()?;
- crossterm::execute!(io::stderr(), EnterAlternateScreen, DisableMouseCapture)?;
- // Define a custom panic hook to reset the terminal properties.
- // This way, you won't have your terminal messed up if an unexpected error happens.
- let panic_hook = panic::take_hook();
- panic::set_hook(Box::new(move |panic| {
- Self::reset().expect("failed to reset the terminal");
- panic_hook(panic);
- }));
- self.terminal.hide_cursor()?;
- self.terminal.clear()?;
- Ok(())
- }
- /// [`Draw`] the terminal interface by [`rendering`] the widgets.
- ///
- /// [`Draw`]: ratatui::Terminal::draw
- /// [`rendering`]: crate::ui:render
- pub fn draw(&mut self, app: &mut App) -> AppResult<()> {
- self.terminal.draw(|frame| ui::render(app, frame))?;
- Ok(())
- }
- /// Resets the terminal interface.
- ///
- /// This function is also used for the panic hook to revert
- /// the terminal properties if unexpected errors occur.
- fn reset() -> AppResult<()> {
- terminal::disable_raw_mode()?;
- crossterm::execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture)?;
- Ok(())
- }
- /// Exits the terminal interface.
- ///
- /// It disables the raw mode and reverts back the terminal properties.
- pub fn exit(&mut self) -> AppResult<()> {
- Self::reset()?;
- self.terminal.show_cursor()?;
- Ok(())
- }
- }
|