You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gobang/src/app.rs

172 lines
5.4 KiB
Rust

use crate::components::DrawableComponent as _;
use crate::{
components::tab::Tab,
components::{
ConnectionsComponent, DatabasesComponent, 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},
Frame,
};
pub enum FocusBlock {
DabataseList,
Table,
ConnectionList,
Query,
}
pub struct App {
pub query: QueryComponent,
pub record_table: TableComponent,
pub structure_table: TableComponent,
pub focus_block: FocusBlock,
pub tab: TabComponent,
pub user_config: Option<UserConfig>,
pub selected_connection: ListState,
pub databases: DatabasesComponent,
pub connections: ConnectionsComponent,
pub table_status: TableStatusComponent,
pub pool: Option<MySqlPool>,
pub error: Option<String>,
}
impl Default for App {
fn default() -> App {
App {
query: QueryComponent::default(),
record_table: TableComponent::default(),
structure_table: TableComponent::default(),
focus_block: FocusBlock::DabataseList,
tab: TabComponent::default(),
user_config: None,
selected_connection: ListState::default(),
databases: DatabasesComponent::new(),
connections: ConnectionsComponent::default(),
table_status: TableStatusComponent::default(),
pool: None,
error: None,
}
}
}
impl App {
pub fn new(user_config: UserConfig) -> App {
App {
user_config: Some(user_config.clone()),
connections: ConnectionsComponent::new(user_config.conn),
focus_block: FocusBlock::ConnectionList,
..App::default()
}
}
pub fn draw<B: Backend>(&mut self, f: &mut Frame<'_, B>) -> anyhow::Result<()> {
if let FocusBlock::ConnectionList = self.focus_block {
self.connections.draw(
f,
Layout::default()
.constraints([Constraint::Percentage(100)])
.split(f.size())[0],
false,
)?;
return Ok(());
}
let main_chunks = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(15), Constraint::Percentage(85)])
.split(f.size());
let left_chunks = Layout::default()
.constraints([Constraint::Min(8), Constraint::Length(7)].as_ref())
.split(main_chunks[0]);
self.databases
.draw(
f,
left_chunks[0],
matches!(self.focus_block, FocusBlock::DabataseList),
)
.unwrap();
self.table_status.draw(
f,
left_chunks[1],
matches!(self.focus_block, FocusBlock::DabataseList),
)?;
let right_chunks = Layout::default()
.direction(Direction::Vertical)
.constraints(
[
Constraint::Length(3),
Constraint::Length(3),
Constraint::Length(5),
]
.as_ref(),
)
.split(main_chunks[1]);
self.tab.draw(f, right_chunks[0], false)?;
self.query.draw(
f,
right_chunks[1],
matches!(self.focus_block, FocusBlock::Query),
)?;
match self.tab.selected_tab {
Tab::Records => self.record_table.draw(
f,
right_chunks[2],
matches!(self.focus_block, FocusBlock::Table),
)?,
Tab::Structure => self.structure_table.draw(
f,
right_chunks[2],
matches!(self.focus_block, FocusBlock::Table),
)?,
}
self.draw_error_popup(f);
Ok(())
}
fn draw_error_popup<B: Backend>(&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);
}
}
}