1pub mod error;
2
3use crate::error::RextTuiError;
4use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
5use ratatui::{
6 DefaultTerminal, Frame,
7 style::Stylize,
8 symbols::border,
9 text::{Line, Text},
10 widgets::{Block, Paragraph},
11};
12
13#[derive(Debug, Default)]
15pub struct App {
16 pub running: bool,
18 pub counter: u8,
19}
20
21impl App {
22 pub fn new() -> Self {
24 Self::default()
25 }
26
27 fn increment_counter(&mut self) {
28 self.counter += 1;
29 }
30
31 fn decrement_counter(&mut self) {
32 self.counter -= 1;
33 }
34
35 pub fn run(mut self, mut terminal: DefaultTerminal) -> Result<(), RextTuiError> {
37 self.running = true;
38 while self.running {
39 terminal.draw(|frame| self.render(frame))?;
40 self.handle_crossterm_events()?;
41 }
42 Ok(())
43 }
44
45 fn render(&mut self, frame: &mut Frame) {
52 let title = Line::from("Rext").bold().yellow().centered();
53 let instructions = Line::from(vec![
54 " Decrement ".into(),
55 "<Left>".bold().blue(),
56 " Increment ".into(),
57 "<Right>".bold().blue(),
58 " Quit ".into(),
59 "<Esc>".bold().blue(),
60 ]);
61
62 let block = Block::bordered()
63 .title(title.centered())
64 .title_bottom(instructions.centered())
65 .border_set(border::THICK);
66
67 let text = Text::from(vec![Line::from(vec![
68 "Value: ".into(),
69 self.counter.to_string().yellow(),
70 ])]);
71
72 frame.render_widget(Paragraph::new(text).block(block).centered(), frame.area());
73 }
74
75 fn handle_crossterm_events(&mut self) -> Result<(), RextTuiError> {
85 match event::read()? {
87 Event::Key(key) if key.kind == KeyEventKind::Press => self.on_key_event(key),
89 Event::Mouse(_) => {}
90 Event::Resize(_, _) => {}
91 _ => {}
92 }
93 Ok(())
94 }
95
96 pub fn on_key_event(&mut self, key: KeyEvent) {
98 match (key.modifiers, key.code) {
99 (_, KeyCode::Esc | KeyCode::Char('q'))
100 | (KeyModifiers::CONTROL, KeyCode::Char('c') | KeyCode::Char('C')) => self.quit(),
101 (_, KeyCode::Left) => self.decrement_counter(),
102 (_, KeyCode::Right) => self.increment_counter(),
103 _ => {}
104 }
105 }
106
107 fn quit(&mut self) {
109 self.running = false;
110 }
111}