From 8ba68fc98c72fb4c2f7d7cf4dbd2e84def96cd3e Mon Sep 17 00:00:00 2001 From: Daniel Heras Quesada Date: Sat, 1 Aug 2026 18:36:36 +0200 Subject: [PATCH] feat: main layout implemented with 0 logic --- src/modules/ui/app.rs | 85 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 10 deletions(-) diff --git a/src/modules/ui/app.rs b/src/modules/ui/app.rs index e6534fb..0a5ff82 100644 --- a/src/modules/ui/app.rs +++ b/src/modules/ui/app.rs @@ -1,10 +1,16 @@ use crate::modules::source::FileDatabase; +use crossterm::event::{ + self, + Event::{self, Key}, +}; use ratatui::{ DefaultTerminal, Frame, - layout::{Constraint, Direction, Layout}, - widgets::Paragraph, + layout::{Constraint, Direction, Flex, Layout}, + style::{Color, Style}, + text::Text, + widgets::{Block, Borders, Padding, Paragraph}, }; -use std::io::{self}; +use std::io; pub enum UiState { LIST, @@ -39,22 +45,81 @@ impl App { pub fn run(&mut self, terminal: &mut DefaultTerminal) -> io::Result<()> { while !self.exit { terminal.draw(|frame| self.draw(frame))?; - // self.handle_events()?; + let event_result = self.handle_events(); + if let Err(_) = event_result { + break; + } } Ok(()) } fn draw(&self, frame: &mut Frame) { let main_layout = Layout::default() - .direction(Direction::Horizontal) + .direction(Direction::Vertical) + .spacing(0) .margin(1) - .constraints(vec![Constraint::Max(10)]) + .constraints(vec![ + Constraint::Length(3), + Constraint::Fill(1), + Constraint::Length(3), + ]) .split(frame.area()); - frame.render_widget(Paragraph::new("Word filter"), main_layout[0]); + let filters_layout = Layout::default() + .direction(Direction::Horizontal) + .spacing(1) + .constraints(vec![Constraint::Fill(1), Constraint::Length(8)]) + .split(main_layout[0]); + + let words_layout = + Layout::horizontal(vec![Constraint::Percentage(30), Constraint::Percentage(70)]) + .split(main_layout[1]); + + let help_layout = Layout::horizontal(vec![Constraint::Fill(1)]) + .flex(Flex::Center) + .split(main_layout[2]); + + frame.render_widget( + Paragraph::new("test word").block(Block::new().title("Word").borders(Borders::ALL)), + filters_layout[0], + ); + + frame.render_widget( + Paragraph::new("en").block(Block::new().title("Lang").borders(Borders::ALL)), + filters_layout[1], + ); + + frame.render_widget( + Paragraph::new("Word list").block(Block::new().borders(Borders::ALL).title("Entries")), + words_layout[0], + ); + + frame.render_widget( + Paragraph::new("Selected word description").block(Block::new().borders(Borders::ALL)), + words_layout[1], + ); + + let help_text = Text::raw("(m)ove | (f)ilter | (d)elete | (e)dit | (a)dd | (q)uit ") + .style(Style::new().fg(Color::DarkGray)); + let help_area = help_layout[0].centered( + Constraint::Length(help_text.width() as u16), + Constraint::Length(1), + ); + + frame.render_widget(help_text, help_area); } - // fn handle_events(&mut self) -> io::Result<()> { - // todo!() - // } + fn handle_events(&mut self) -> io::Result<()> { + if let Event::Key(key) = event::read()? { + match key.code { + event::KeyCode::Char(c) => { + if c == 'q' { + return Err(io::Error::last_os_error()); // FIXME: this is not right + } + } + _ => return Ok(()), + } + } + Ok(()) + } }