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}