move table_status under table

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

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

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

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

@ -1,6 +1,6 @@
use super::{
utils::scroll_vertical::VerticalScroll, Component, DrawableComponent, EventState,
TableValueComponent,
TableStatusComponent, TableValueComponent,
};
use crate::components::command::{self, CommandInfo};
use crate::config::KeyConfig;
@ -40,7 +40,7 @@ impl TableComponent {
selected_column: 0,
selection_area_corner: None,
column_page_start: std::cell::Cell::new(0),
scroll: VerticalScroll::new(),
scroll: VerticalScroll::new(false, false),
eod: false,
key_config,
}
@ -68,7 +68,7 @@ impl TableComponent {
self.selected_column = 0;
self.selection_area_corner = None;
self.column_page_start = std::cell::Cell::new(0);
self.scroll = VerticalScroll::new();
self.scroll = VerticalScroll::new(false, false);
self.eod = false;
self.table = Some((database, table));
}
@ -80,7 +80,7 @@ impl TableComponent {
self.selected_column = 0;
self.selection_area_corner = None;
self.column_page_start = std::cell::Cell::new(0);
self.scroll = VerticalScroll::new();
self.scroll = VerticalScroll::new(false, false);
self.eod = false;
self.table = None;
}
@ -406,6 +406,25 @@ impl DrawableComponent for TableComponent {
.constraints(vec![Constraint::Length(3), Constraint::Length(5)])
.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.scroll.reset();
@ -422,9 +441,9 @@ impl DrawableComponent for TableComponent {
TableValueComponent::new(self.selected_cells().unwrap_or_default())
.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) =
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)| {
Cell::from(h.to_string()).style(if selected_column_index == column_index {
Style::default().add_modifier(Modifier::BOLD)
@ -466,7 +485,7 @@ impl DrawableComponent for TableComponent {
let mut state = self.selected_row.clone();
f.render_stateful_widget(
table,
layout[1],
chunks[0],
if let Some((_, y)) = self.selection_area_corner {
state.select(Some(y));
&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(())
}
}

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

@ -5,13 +5,17 @@ use tui::{backend::Backend, layout::Rect, Frame};
pub struct VerticalScroll {
top: Cell<usize>,
max_top: Cell<usize>,
inside: bool,
border: bool,
}
impl VerticalScroll {
pub const fn new() -> Self {
pub const fn new(border: bool, inside: bool) -> Self {
Self {
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) {
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,
style_bar: Style,
style_pos: Style,
inside: bool,
border: bool,
}
impl Scrollbar {
fn new(max: usize, pos: usize) -> Self {
fn new(max: usize, pos: usize, border: bool, inside: bool) -> Self {
Self {
max: u16::try_from(max).unwrap_or_default(),
pos: u16::try_from(pos).unwrap_or_default(),
style_pos: Style::default(),
style_bar: Style::default(),
inside,
border,
}
}
}
@ -38,7 +42,11 @@ impl Widget for Scrollbar {
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() {
return;
};
@ -46,7 +54,7 @@ impl Widget for Scrollbar {
let (bar_top, bar_height) = {
let scrollbar_area = area.inner(&Margin {
horizontal: 0,
vertical: 1,
vertical: if self.border { 1 } else { 0 },
});
(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) {
let mut widget = Scrollbar::new(max, pos);
pub fn draw_scrollbar<B: Backend>(
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);
f.render_widget(widget, r);
}

Loading…
Cancel
Save