move table_status under table

pull/54/head
Takayuki Maeda 3 years ago
parent 3a8529f9be
commit 6bc3afef12

@ -1,6 +1,12 @@
[[conn]] [[conn]]
type = "mysql" type = "mysql"
name = "sample" user = "root"
host = "localhost"
database = "world"
port = 3306
[[conn]]
type = "mysql"
user = "root" user = "root"
host = "localhost" host = "localhost"
port = 3306 port = 3306

@ -33,7 +33,6 @@ pub struct App {
help: HelpComponent, help: HelpComponent,
databases: DatabasesComponent, databases: DatabasesComponent,
connections: ConnectionsComponent, connections: ConnectionsComponent,
table_status: TableStatusComponent,
pool: Option<Box<dyn Pool>>, pool: Option<Box<dyn Pool>>,
pub config: Config, pub config: Config,
pub error: ErrorComponent, pub error: ErrorComponent,
@ -52,7 +51,6 @@ impl App {
tab: TabComponent::new(config.key_config.clone()), tab: TabComponent::new(config.key_config.clone()),
help: HelpComponent::new(config.key_config.clone()), help: HelpComponent::new(config.key_config.clone()),
databases: DatabasesComponent::new(config.key_config.clone()), databases: DatabasesComponent::new(config.key_config.clone()),
table_status: TableStatusComponent::default(),
error: ErrorComponent::new(config.key_config), error: ErrorComponent::new(config.key_config),
focus: Focus::ConnectionList, focus: Focus::ConnectionList,
pool: None, pool: None,
@ -77,15 +75,10 @@ impl App {
.direction(Direction::Horizontal) .direction(Direction::Horizontal)
.constraints([Constraint::Percentage(15), Constraint::Percentage(85)]) .constraints([Constraint::Percentage(15), Constraint::Percentage(85)])
.split(f.size()); .split(f.size());
let left_chunks = Layout::default()
.constraints([Constraint::Min(8), Constraint::Length(7)].as_ref())
.split(main_chunks[0]);
self.databases self.databases
.draw(f, left_chunks[0], matches!(self.focus, Focus::DabataseList)) .draw(f, main_chunks[0], matches!(self.focus, Focus::DabataseList))
.unwrap(); .unwrap();
self.table_status
.draw(f, left_chunks[1], matches!(self.focus, Focus::DabataseList))?;
let right_chunks = Layout::default() let right_chunks = Layout::default()
.direction(Direction::Vertical) .direction(Direction::Vertical)
@ -268,8 +261,6 @@ impl App {
table.clone(), table.clone(),
); );
} }
self.table_status
.update(self.record_table.len() as u64, table);
} }
Ok(()) Ok(())
} }

@ -49,7 +49,7 @@ impl DatabasesComponent {
Self { Self {
tree: DatabaseTree::default(), tree: DatabaseTree::default(),
filterd_tree: None, filterd_tree: None,
scroll: VerticalScroll::new(), scroll: VerticalScroll::new(true, true),
input: Vec::new(), input: Vec::new(),
input_idx: 0, input_idx: 0,
input_cursor_position: 0, input_cursor_position: 0,

@ -1,6 +1,6 @@
use super::{ use super::{
utils::scroll_vertical::VerticalScroll, Component, DrawableComponent, EventState, utils::scroll_vertical::VerticalScroll, Component, DrawableComponent, EventState,
TableValueComponent, TableStatusComponent, TableValueComponent,
}; };
use crate::components::command::{self, CommandInfo}; use crate::components::command::{self, CommandInfo};
use crate::config::KeyConfig; use crate::config::KeyConfig;
@ -40,7 +40,7 @@ impl TableComponent {
selected_column: 0, selected_column: 0,
selection_area_corner: None, selection_area_corner: None,
column_page_start: std::cell::Cell::new(0), column_page_start: std::cell::Cell::new(0),
scroll: VerticalScroll::new(), scroll: VerticalScroll::new(false, false),
eod: false, eod: false,
key_config, key_config,
} }
@ -68,7 +68,7 @@ impl TableComponent {
self.selected_column = 0; self.selected_column = 0;
self.selection_area_corner = None; self.selection_area_corner = None;
self.column_page_start = std::cell::Cell::new(0); self.column_page_start = std::cell::Cell::new(0);
self.scroll = VerticalScroll::new(); self.scroll = VerticalScroll::new(false, false);
self.eod = false; self.eod = false;
self.table = Some((database, table)); self.table = Some((database, table));
} }
@ -80,7 +80,7 @@ impl TableComponent {
self.selected_column = 0; self.selected_column = 0;
self.selection_area_corner = None; self.selection_area_corner = None;
self.column_page_start = std::cell::Cell::new(0); self.column_page_start = std::cell::Cell::new(0);
self.scroll = VerticalScroll::new(); self.scroll = VerticalScroll::new(false, false);
self.eod = false; self.eod = false;
self.table = None; self.table = None;
} }
@ -406,6 +406,25 @@ impl DrawableComponent for TableComponent {
.constraints(vec![Constraint::Length(3), Constraint::Length(5)]) .constraints(vec![Constraint::Length(3), Constraint::Length(5)])
.split(area); .split(area);
f.render_widget(
Block::default()
.title(self.title())
.borders(Borders::ALL)
.style(if focused {
Style::default()
} else {
Style::default().fg(Color::DarkGray)
}),
layout[1],
);
let chunks = Layout::default()
.vertical_margin(1)
.horizontal_margin(1)
.direction(Direction::Vertical)
.constraints([Constraint::Min(1), Constraint::Length(2)].as_ref())
.split(layout[1]);
self.selected_row.selected().map_or_else( self.selected_row.selected().map_or_else(
|| { || {
self.scroll.reset(); self.scroll.reset();
@ -422,9 +441,9 @@ impl DrawableComponent for TableComponent {
TableValueComponent::new(self.selected_cells().unwrap_or_default()) TableValueComponent::new(self.selected_cells().unwrap_or_default())
.draw(f, layout[0], focused)?; .draw(f, layout[0], focused)?;
let block = Block::default().borders(Borders::ALL).title(self.title()); let block = Block::default().borders(Borders::NONE);
let (selected_column_index, headers, rows, constraints) = let (selected_column_index, headers, rows, constraints) =
self.calculate_cell_widths(block.inner(layout[1]).width); self.calculate_cell_widths(block.inner(chunks[0]).width);
let header_cells = headers.iter().enumerate().map(|(column_index, h)| { let header_cells = headers.iter().enumerate().map(|(column_index, h)| {
Cell::from(h.to_string()).style(if selected_column_index == column_index { Cell::from(h.to_string()).style(if selected_column_index == column_index {
Style::default().add_modifier(Modifier::BOLD) Style::default().add_modifier(Modifier::BOLD)
@ -466,7 +485,7 @@ impl DrawableComponent for TableComponent {
let mut state = self.selected_row.clone(); let mut state = self.selected_row.clone();
f.render_stateful_widget( f.render_stateful_widget(
table, table,
layout[1], chunks[0],
if let Some((_, y)) = self.selection_area_corner { if let Some((_, y)) = self.selection_area_corner {
state.select(Some(y)); state.select(Some(y));
&mut state &mut state
@ -475,7 +494,22 @@ impl DrawableComponent for TableComponent {
}, },
); );
self.scroll.draw(f, layout[1]); TableStatusComponent::new(
if self.rows.is_empty() {
None
} else {
Some(self.rows.len())
},
if self.headers.is_empty() {
None
} else {
Some(self.headers.len())
},
self.table.as_ref().map_or(None, |t| Some(t.1.clone())),
)
.draw(f, chunks[1], focused)?;
self.scroll.draw(f, chunks[0]);
Ok(()) Ok(())
} }
} }

@ -8,79 +8,65 @@ use tui::{
layout::Rect, layout::Rect,
style::{Color, Style}, style::{Color, Style},
text::{Span, Spans}, text::{Span, Spans},
widgets::{Block, Borders, List, ListItem}, widgets::{Block, Borders, Paragraph, Wrap},
Frame, Frame,
}; };
pub struct TableStatusComponent { pub struct TableStatusComponent {
rows_count: u64, column_count: Option<usize>,
row_count: Option<usize>,
table: Option<Table>, table: Option<Table>,
} }
impl Default for TableStatusComponent { impl Default for TableStatusComponent {
fn default() -> Self { fn default() -> Self {
Self { Self {
rows_count: 0, row_count: None,
column_count: None,
table: None, table: None,
} }
} }
} }
impl TableStatusComponent { impl TableStatusComponent {
pub fn update(&mut self, count: u64, table: Table) { pub fn new(
self.rows_count = count; row_count: Option<usize>,
self.table = Some(table); column_count: Option<usize>,
} table: Option<Table>,
) -> Self {
fn status_str(&self) -> Vec<String> { Self {
if let Some(table) = self.table.as_ref() { row_count,
return vec![ column_count,
format!( table,
"created: {}",
table
.create_time
.map(|time| time.to_string())
.unwrap_or_default()
),
format!(
"updated: {}",
table
.update_time
.map(|time| time.to_string())
.unwrap_or_default()
),
format!(
"engine: {}",
table
.engine
.as_ref()
.map(|engine| engine.to_string())
.unwrap_or_default()
),
format!("rows: {}", self.rows_count),
];
} }
Vec::new()
} }
} }
impl DrawableComponent for TableStatusComponent { impl DrawableComponent for TableStatusComponent {
fn draw<B: Backend>(&mut self, f: &mut Frame<B>, area: Rect, focused: bool) -> Result<()> { fn draw<B: Backend>(&mut self, f: &mut Frame<B>, area: Rect, focused: bool) -> Result<()> {
let table_status: Vec<ListItem> = self let status = Paragraph::new(Spans::from(vec![
.status_str() Span::from("rows: "),
.iter() Span::from(format!(
.map(|i| { "{}, ",
ListItem::new(vec![Spans::from(Span::raw(i.to_string()))]).style(Style::default()) self.row_count.map_or("-".to_string(), |c| c.to_string())
}) )),
.collect(); Span::from("columns: "),
let tasks = List::new(table_status).block(Block::default().borders(Borders::ALL).style( Span::from(format!(
if focused { "{}, ",
Style::default() self.column_count.map_or("-".to_string(), |c| c.to_string())
} else { )),
Style::default().fg(Color::DarkGray) Span::from("engine: "),
}, Span::from(self.table.as_ref().map_or("-".to_string(), |c| {
)); c.engine.as_ref().map_or("-".to_string(), |e| e.to_string())
f.render_widget(tasks, area); })),
]))
.block(Block::default().borders(Borders::TOP).style(if focused {
Style::default()
} else {
Style::default().fg(Color::DarkGray)
}))
.wrap(Wrap { trim: true });
f.render_widget(status, area);
Ok(()) Ok(())
} }
} }

@ -5,13 +5,17 @@ use tui::{backend::Backend, layout::Rect, Frame};
pub struct VerticalScroll { pub struct VerticalScroll {
top: Cell<usize>, top: Cell<usize>,
max_top: Cell<usize>, max_top: Cell<usize>,
inside: bool,
border: bool,
} }
impl VerticalScroll { impl VerticalScroll {
pub const fn new() -> Self { pub const fn new(border: bool, inside: bool) -> Self {
Self { Self {
top: Cell::new(0), top: Cell::new(0),
max_top: Cell::new(0), max_top: Cell::new(0),
border,
inside,
} }
} }
@ -38,7 +42,14 @@ impl VerticalScroll {
} }
pub fn draw<B: Backend>(&self, f: &mut Frame<B>, r: Rect) { pub fn draw<B: Backend>(&self, f: &mut Frame<B>, r: Rect) {
draw_scrollbar(f, r, self.max_top.get(), self.top.get()); draw_scrollbar(
f,
r,
self.max_top.get(),
self.top.get(),
self.border,
self.inside,
);
} }
} }

@ -15,15 +15,19 @@ struct Scrollbar {
pos: u16, pos: u16,
style_bar: Style, style_bar: Style,
style_pos: Style, style_pos: Style,
inside: bool,
border: bool,
} }
impl Scrollbar { impl Scrollbar {
fn new(max: usize, pos: usize) -> Self { fn new(max: usize, pos: usize, border: bool, inside: bool) -> Self {
Self { Self {
max: u16::try_from(max).unwrap_or_default(), max: u16::try_from(max).unwrap_or_default(),
pos: u16::try_from(pos).unwrap_or_default(), pos: u16::try_from(pos).unwrap_or_default(),
style_pos: Style::default(), style_pos: Style::default(),
style_bar: Style::default(), style_bar: Style::default(),
inside,
border,
} }
} }
} }
@ -38,7 +42,11 @@ impl Widget for Scrollbar {
return; return;
} }
let right = area.right().saturating_sub(1); let right = if self.inside {
area.right().saturating_sub(1)
} else {
area.right()
};
if right <= area.left() { if right <= area.left() {
return; return;
}; };
@ -46,7 +54,7 @@ impl Widget for Scrollbar {
let (bar_top, bar_height) = { let (bar_top, bar_height) = {
let scrollbar_area = area.inner(&Margin { let scrollbar_area = area.inner(&Margin {
horizontal: 0, horizontal: 0,
vertical: 1, vertical: if self.border { 1 } else { 0 },
}); });
(scrollbar_area.top(), scrollbar_area.height) (scrollbar_area.top(), scrollbar_area.height)
@ -67,8 +75,15 @@ impl Widget for Scrollbar {
} }
} }
pub fn draw_scrollbar<B: Backend>(f: &mut Frame<B>, r: Rect, max: usize, pos: usize) { pub fn draw_scrollbar<B: Backend>(
let mut widget = Scrollbar::new(max, pos); f: &mut Frame<B>,
r: Rect,
max: usize,
pos: usize,
border: bool,
inside: bool,
) {
let mut widget = Scrollbar::new(max, pos, border, inside);
widget.style_pos = Style::default().fg(Color::Blue); widget.style_pos = Style::default().fg(Color::Blue);
f.render_widget(widget, r); f.render_widget(widget, r);
} }

Loading…
Cancel
Save