basic/
basic.rs

1use std::{
2    fmt::Display,
3    io::{self, stdout, Stdout},
4    time::Duration,
5};
6
7use intui_tabs::{Tabs, TabsState};
8use ratatui::{
9    crossterm::{
10        event::{self, Event, KeyCode},
11        execute,
12        terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
13    },
14    prelude::CrosstermBackend,
15    widgets::Widget,
16    Terminal,
17};
18use ratatui::{prelude::*, style::Color};
19
20fn main() {
21    let mut terminal = init_terminal().unwrap();
22    App::new().run(&mut terminal).unwrap();
23    restore_terminal().unwrap();
24}
25
26fn init_terminal() -> io::Result<Terminal<CrosstermBackend<Stdout>>> {
27    enable_raw_mode()?;
28    execute!(stdout(), EnterAlternateScreen)?;
29    Terminal::new(CrosstermBackend::new(stdout()))
30}
31
32fn restore_terminal() -> io::Result<()> {
33    disable_raw_mode()?;
34    execute!(stdout(), LeaveAlternateScreen)
35}
36
37#[derive(Copy, Clone)]
38enum CurrentTab {
39    Main,
40    Settings,
41    About,
42}
43
44impl Display for CurrentTab {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        match self {
47            CurrentTab::Main => write!(f, "Main"),
48            CurrentTab::Settings => write!(f, "Settings"),
49            CurrentTab::About => write!(f, "About"),
50        }
51    }
52}
53
54impl Default for CurrentTab {
55    fn default() -> Self {
56        Self::Main
57    }
58}
59
60struct App {
61    tabs_state: TabsState<CurrentTab>,
62}
63
64impl App {
65    fn new() -> Self {
66        Self {
67            tabs_state: TabsState::new(vec![
68                CurrentTab::Main,
69                CurrentTab::Settings,
70                CurrentTab::About,
71            ]),
72        }
73    }
74
75    fn run(mut self, terminal: &mut Terminal<CrosstermBackend<Stdout>>) -> io::Result<()> {
76        loop {
77            terminal.draw(|frame| frame.render_widget(&mut self, frame.area()))?;
78
79            if event::poll(Duration::from_millis(10))? {
80                if let Event::Key(key) = event::read()? {
81                    match key.code {
82                        KeyCode::Char('q') => break,
83                        KeyCode::Char('h') => self.tabs_state.prev(),
84                        KeyCode::Char('l') => self.tabs_state.next(),
85                        KeyCode::Char('1') => self.tabs_state.set(1),
86                        KeyCode::Char('2') => self.tabs_state.set(2),
87                        KeyCode::Char('3') => self.tabs_state.set(3),
88                        _ => (),
89                    }
90                }
91            }
92        }
93
94        Ok(())
95    }
96}
97
98impl Widget for &mut App {
99    fn render(self, area: Rect, buf: &mut Buffer)
100    where
101        Self: Sized,
102    {
103        Tabs::new()
104            .color(Color::Red)
105            .beginner_mode(true)
106            .center(true)
107            .render(area, buf, &mut self.tabs_state);
108    }
109}