From a9f918b53d4facf8f674ba2855acc012e44f0ab6 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda <41065217+TaKO8Ki@users.noreply.github.com> Date: Fri, 9 Jul 2021 19:32:55 +0900 Subject: [PATCH] add error component (#19) --- src/app.rs | 50 ++++++------------------------------- src/components/error.rs | 55 +++++++++++++++++++++++++++++++++++++++++ src/components/mod.rs | 2 ++ src/handlers/mod.rs | 24 ++++++++++-------- src/handlers/query.rs | 2 +- src/main.rs | 2 +- 6 files changed, 80 insertions(+), 55 deletions(-) create mode 100644 src/components/error.rs diff --git a/src/app.rs b/src/app.rs index b4d4baa..8a54a83 100644 --- a/src/app.rs +++ b/src/app.rs @@ -3,17 +3,16 @@ use crate::components::DrawableComponent as _; use crate::{ components::tab::Tab, components::{ - ConnectionsComponent, DatabasesComponent, QueryComponent, TabComponent, TableComponent, - TableStatusComponent, + ConnectionsComponent, DatabasesComponent, ErrorComponent, QueryComponent, TabComponent, + TableComponent, TableStatusComponent, }, user_config::UserConfig, }; use sqlx::MySqlPool; use tui::{ backend::Backend, - layout::{Constraint, Direction, Layout}, - style::{Color, Style}, - widgets::{Block, Borders, Clear, ListState, Paragraph}, + layout::{Constraint, Direction, Layout, Rect}, + widgets::ListState, Frame, }; @@ -36,7 +35,7 @@ pub struct App { pub table_status: TableStatusComponent, pub clipboard: Clipboard, pub pool: Option, - pub error: Option, + pub error: ErrorComponent, } impl Default for App { @@ -54,7 +53,7 @@ impl Default for App { table_status: TableStatusComponent::default(), clipboard: Clipboard::new(), pool: None, - error: None, + error: ErrorComponent::default(), } } } @@ -133,42 +132,7 @@ impl App { matches!(self.focus_block, FocusBlock::Table), )?, } - self.draw_error_popup(f); + self.error.draw(f, Rect::default(), false)?; Ok(()) } - - fn draw_error_popup(&self, f: &mut Frame<'_, B>) { - if let Some(error) = self.error.as_ref() { - let percent_x = 60; - let percent_y = 20; - let error = Paragraph::new(error.to_string()) - .block(Block::default().title("Error").borders(Borders::ALL)) - .style(Style::default().fg(Color::Red)); - let popup_layout = Layout::default() - .direction(Direction::Vertical) - .constraints( - [ - Constraint::Percentage((100 - percent_y) / 2), - Constraint::Percentage(percent_y), - Constraint::Percentage((100 - percent_y) / 2), - ] - .as_ref(), - ) - .split(f.size()); - - let area = Layout::default() - .direction(Direction::Horizontal) - .constraints( - [ - Constraint::Percentage((100 - percent_x) / 2), - Constraint::Percentage(percent_x), - Constraint::Percentage((100 - percent_x) / 2), - ] - .as_ref(), - ) - .split(popup_layout[1])[1]; - f.render_widget(Clear, area); - f.render_widget(error, area); - } - } } diff --git a/src/components/error.rs b/src/components/error.rs new file mode 100644 index 0000000..d83af84 --- /dev/null +++ b/src/components/error.rs @@ -0,0 +1,55 @@ +use super::{Component, DrawableComponent}; +use crate::event::Key; +use anyhow::Result; +use tui::{ + backend::Backend, + layout::{Alignment, Rect}, + style::{Color, Style}, + widgets::{Block, Borders, Clear, Paragraph, Wrap}, + Frame, +}; + +pub struct ErrorComponent { + pub error: Option, +} + +impl Default for ErrorComponent { + fn default() -> Self { + Self { error: None } + } +} + +impl ErrorComponent { + pub fn set(&mut self, error: String) { + self.error = Some(error); + } +} + +impl DrawableComponent for ErrorComponent { + fn draw(&mut self, f: &mut Frame, _area: Rect, _focused: bool) -> Result<()> { + if let Some(error) = self.error.as_ref() { + let width = 65; + let height = 10; + let error = Paragraph::new(error.to_string()) + .block(Block::default().title("Error").borders(Borders::ALL)) + .style(Style::default().fg(Color::Red)) + .alignment(Alignment::Left) + .wrap(Wrap { trim: true }); + let area = Rect::new( + (f.size().width.saturating_sub(width)) / 2, + (f.size().height.saturating_sub(height)) / 2, + width.min(f.size().width), + height.min(f.size().height), + ); + f.render_widget(Clear, area); + f.render_widget(error, area); + } + Ok(()) + } +} + +impl Component for ErrorComponent { + fn event(&mut self, key: Key) -> Result<()> { + Ok(()) + } +} diff --git a/src/components/mod.rs b/src/components/mod.rs index 8a5b7b9..3d67b41 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,6 +1,7 @@ pub mod command; pub mod connections; pub mod databases; +pub mod error; pub mod query; pub mod tab; pub mod table; @@ -11,6 +12,7 @@ pub mod utils; pub use command::{CommandInfo, CommandText}; pub use connections::ConnectionsComponent; pub use databases::DatabasesComponent; +pub use error::ErrorComponent; pub use query::QueryComponent; pub use tab::TabComponent; pub use table::TableComponent; diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 3bf09a6..c2fb900 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -10,15 +10,6 @@ use crate::components::Component as _; use crate::event::Key; pub async fn handle_app(key: Key, app: &mut App) -> anyhow::Result<()> { - match app.focus_block { - FocusBlock::ConnectionList => connection_list::handler(key, app).await?, - FocusBlock::DabataseList => database_list::handler(key, app).await?, - FocusBlock::Table => match app.tab.selected_tab { - Tab::Records => record_table::handler(key, app).await?, - Tab::Structure => structure_table::handler(key, app).await?, - }, - FocusBlock::Query => query::handler(key, app).await?, - } match key { Key::Char('d') => match app.focus_block { FocusBlock::Query => (), @@ -29,8 +20,21 @@ pub async fn handle_app(key: Key, app: &mut App) -> anyhow::Result<()> { _ => app.focus_block = FocusBlock::Table, }, Key::Char('e') => app.focus_block = FocusBlock::Query, - Key::Esc => app.error = None, + Key::Esc if app.error.error.is_some() => { + app.error.error = None; + return Ok(()); + } key => app.tab.event(key)?, } + + match app.focus_block { + FocusBlock::ConnectionList => connection_list::handler(key, app).await?, + FocusBlock::DabataseList => database_list::handler(key, app).await?, + FocusBlock::Table => match app.tab.selected_tab { + Tab::Records => record_table::handler(key, app).await?, + Tab::Structure => structure_table::handler(key, app).await?, + }, + FocusBlock::Query => query::handler(key, app).await?, + } Ok(()) } diff --git a/src/handlers/query.rs b/src/handlers/query.rs index 22f65f4..a1ce829 100644 --- a/src/handlers/query.rs +++ b/src/handlers/query.rs @@ -39,7 +39,7 @@ pub async fn handler(key: Key, app: &mut App) -> anyhow::Result<()> { } } } - Key::Esc => app.focus_block = FocusBlock::DabataseList, + Key::Esc => app.focus_block = FocusBlock::Table, key => app.query.event(key)?, } Ok(()) diff --git a/src/main.rs b/src/main.rs index 4b408ac..bd8d88b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,7 +51,7 @@ async fn main() -> anyhow::Result<()> { }; match handle_app(key, &mut app).await { Ok(_) => (), - Err(err) => app.error = Some(err.to_string()), + Err(err) => app.error.set(err.to_string()), } } Event::Tick => (),