diff --git a/src/app.rs b/src/app.rs index aaad2f2..b894f1c 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,27 +1,77 @@ +use crossterm::event::Event; use eyre::Result; use ratatui::prelude::*; -use std::io::Stdout; use std::time::Duration; +use crate::app_event::AppEvent; +use crate::component::Component; +use crate::components; use crate::tui; pub struct App { - pub terminal: Terminal>, + pub tui: tui::Tui, pub tick_rate: Duration, + pub components: Vec>, } impl App { - pub fn start(tick_rate: Duration) -> Result { - let terminal = tui::init()?; + pub fn new(tick_rate: Duration) -> Result { + let tui = tui::init()?; + + let hello_world = components::hello_world::HelloWorld::default(); + let hello_world1 = components::hello_world::HelloWorld::default(); + let hello_world2 = components::hello_world::HelloWorld::default(); + let hello_world3 = components::hello_world::HelloWorld::default(); Ok(Self { - terminal, + tui, tick_rate, + components: vec![ + Box::new(hello_world), + Box::new(hello_world1), + Box::new(hello_world2), + Box::new(hello_world3), + ], }) } pub fn run(&mut self) -> Result<()> { - Ok(()) + loop { + let event: Option = match tui::get_event(self.tick_rate)? + { + Some(event) => match event { + Event::Key(key) => Some(AppEvent::Key(key)), + Event::Mouse(mouse) => Some(AppEvent::Mouse(mouse)), + Event::FocusGained => todo!(), + Event::FocusLost => todo!(), + Event::Paste(_) => todo!(), + Event::Resize(_, _) => todo!(), + }, + None => None, + }; + + if event.is_some() { + for component in self.components.iter_mut() { + let _ = component.handle_event(event.expect(""))?; + } + } + + self.tui.draw(|frame| { + let layout = Layout::default() + .direction(Direction::Vertical) + .constraints([ + Constraint::Percentage(25), + Constraint::Percentage(25), + Constraint::Percentage(25), + Constraint::Percentage(25), + ]) + .split(frame.size()); + + for (i, component) in self.components.iter_mut().enumerate() { + let _ = component.render(frame, layout[i]); + } + })?; + } } pub fn quit(&mut self) -> Result<()> { diff --git a/src/app_event.rs b/src/app_event.rs index 1cac719..ee9d037 100644 --- a/src/app_event.rs +++ b/src/app_event.rs @@ -1,5 +1,6 @@ use crossterm::event::{KeyEvent, MouseEvent}; +#[derive(Clone, Copy)] pub enum AppEvent { Key(KeyEvent), Mouse(MouseEvent), diff --git a/src/component.rs b/src/component.rs index 1896bc2..d8ca48f 100644 --- a/src/component.rs +++ b/src/component.rs @@ -39,5 +39,5 @@ pub trait Component { Ok(None) } - fn render(&mut self, frame: &mut Frame, rect: Rect); + fn render(&mut self, frame: &mut Frame, rect: Rect) -> Result<()>; } diff --git a/src/components/hello_world.rs b/src/components/hello_world.rs new file mode 100644 index 0000000..22c966c --- /dev/null +++ b/src/components/hello_world.rs @@ -0,0 +1,17 @@ +use ratatui::prelude::*; +use ratatui::widgets::Paragraph; + +use crate::component::Component; + +#[derive(Default, Clone)] +pub struct HelloWorld { + pub text: String, +} + +impl Component for HelloWorld { + fn render(&mut self, frame: &mut Frame, rect: Rect) -> eyre::Result<()> { + frame.render_widget(Paragraph::new(self.text.clone()), rect); + + Ok(()) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs new file mode 100644 index 0000000..c6dbc18 --- /dev/null +++ b/src/components/mod.rs @@ -0,0 +1 @@ +pub mod hello_world; diff --git a/src/main.rs b/src/main.rs index 32845d3..29c6439 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,12 +2,14 @@ mod action; mod app; mod app_event; mod component; +mod components; mod tui; use eyre::Result; fn main() -> Result<()> { - let mut app = app::App::start(std::time::Duration::from_millis(10))?; + let mut app = app::App::new(std::time::Duration::from_millis(10))?; + app.run()?; app.quit() } diff --git a/src/tui.rs b/src/tui.rs index 7f27ca3..d8ddb90 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -1,7 +1,7 @@ -use std::io::{self, stdout, Stdout}; - -use crossterm::{execute, terminal::*}; +use crossterm::{event, event::Event, execute, terminal::*}; use ratatui::prelude::*; +use std::io; +use std::io::{stdout, Stdout}; pub type Tui = Terminal>; @@ -18,3 +18,11 @@ pub fn restore() -> io::Result<()> { Ok(()) } + +pub fn get_event(tick: std::time::Duration) -> io::Result> { + if event::poll(tick)? { + return Ok(Some(event::read()?)); + } + + Ok(None) +}