fix table component field names

pull/31/head
Takayuki Maeda 3 years ago
parent 7e8291be22
commit 8ff6236f8d

@ -237,7 +237,7 @@ impl App {
return Ok(EventState::Consumed);
}
if let Some(index) = self.record_table.table.state.selected() {
if let Some(index) = self.record_table.table.selected_row.selected() {
if index.saturating_add(1)
% crate::utils::RECORDS_LIMIT_PER_PAGE as usize
== 0

@ -41,16 +41,16 @@ impl RecordTableComponent {
self.table.rows = rows;
self.table.headers = headers;
if !self.table.rows.is_empty() {
self.table.state.select(None);
self.table.state.select(Some(0));
self.table.selected_row.select(None);
self.table.selected_row.select(Some(0));
}
}
pub fn reset(&mut self) {
self.table = TableComponent::default();
if !self.table.rows.is_empty() {
self.table.state.select(None);
self.table.state.select(Some(0))
self.table.selected_row.select(None);
self.table.selected_row.select(Some(0))
}
self.filter = TableFilterComponent::default();
}

@ -15,30 +15,26 @@ use tui::{
use unicode_width::UnicodeWidthStr;
pub struct TableComponent {
pub state: TableState,
pub selected_row: TableState,
pub headers: Vec<String>,
pub rows: Vec<Vec<String>>,
pub eod: bool,
select_state: TableState,
selected_left_column_index: usize,
selected_right_cell: Option<(usize, usize)>,
selection_area_corner: Option<(usize, usize)>,
selected_column: usize,
column_page_start: std::cell::Cell<usize>,
scroll: VerticalScroll,
select_entire_row: bool,
}
impl Default for TableComponent {
fn default() -> Self {
Self {
state: TableState::default(),
select_state: TableState::default(),
selected_row: TableState::default(),
headers: vec![],
rows: vec![],
selected_left_column_index: 0,
selected_right_cell: None,
selected_column: 0,
selection_area_corner: None,
column_page_start: std::cell::Cell::new(0),
scroll: VerticalScroll::new(),
select_entire_row: false,
eod: false,
}
}
@ -46,31 +42,29 @@ impl Default for TableComponent {
impl TableComponent {
pub fn new(rows: Vec<Vec<String>>, headers: Vec<String>) -> Self {
let mut state = TableState::default();
let mut selected_row = TableState::default();
if !rows.is_empty() {
state.select(None);
state.select(Some(0))
selected_row.select(None);
selected_row.select(Some(0))
}
Self {
state,
selected_row,
headers,
rows,
..Self::default()
}
}
pub fn reset(&mut self) {
self.select_state.select(None);
self.selected_right_cell = None;
self.select_entire_row = false;
fn reset(&mut self) {
self.selection_area_corner = None;
}
pub fn end(&mut self) {
self.eod = true;
}
pub fn next(&mut self, lines: usize) {
let i = match self.state.selected() {
fn next_row(&mut self, lines: usize) {
let i = match self.selected_row.selected() {
Some(i) => {
if i + lines >= self.rows.len() {
Some(self.rows.len() - 1)
@ -81,25 +75,11 @@ impl TableComponent {
None => None,
};
self.reset();
self.state.select(i);
self.selected_row.select(i);
}
pub fn next_select(&mut self, lines: usize) {
let i = match self.select_state.selected() {
Some(i) => {
if i + lines >= self.rows.len() {
Some(self.rows.len() - 1)
} else {
Some(i + lines)
}
}
None => None,
};
self.select_state.select(i);
}
pub fn previous(&mut self, lines: usize) {
let i = match self.state.selected() {
fn previous_row(&mut self, lines: usize) {
let i = match self.selected_row.selected() {
Some(i) => {
if i <= lines {
Some(0)
@ -110,70 +90,56 @@ impl TableComponent {
None => None,
};
self.reset();
self.state.select(i);
self.selected_row.select(i);
}
pub fn previout_select(&mut self, lines: usize) {
let i = match self.select_state.selected() {
Some(i) => {
if i <= lines {
Some(0)
} else {
Some(i - lines)
}
}
None => None,
};
self.select_state.select(i);
}
pub fn scroll_top(&mut self) {
fn scroll_top(&mut self) {
if self.rows.is_empty() {
return;
}
self.reset();
self.state.select(Some(0));
self.selected_row.select(Some(0));
}
pub fn scroll_bottom(&mut self) {
fn scroll_bottom(&mut self) {
if self.rows.is_empty() {
return;
}
self.reset();
self.state.select(Some(self.rows.len() - 1));
self.selected_row.select(Some(self.rows.len() - 1));
}
pub fn next_column(&mut self) {
fn next_column(&mut self) {
if self.rows.is_empty() {
return;
}
if self.selected_left_column_index >= self.headers.len().saturating_sub(1) {
if self.selected_column >= self.headers.len().saturating_sub(1) {
return;
}
self.reset();
self.selected_left_column_index += 1;
self.selected_column += 1;
}
pub fn previous_column(&mut self) {
fn previous_column(&mut self) {
if self.rows.is_empty() {
return;
}
if self.selected_left_column_index == 0 {
if self.selected_column == 0 {
return;
}
self.reset();
self.selected_left_column_index -= 1;
self.selected_column -= 1;
}
pub fn expand_selected_area_x(&mut self, positive: bool) {
if self.selected_right_cell.is_none() {
self.selected_right_cell = Some((
self.selected_left_column_index,
self.state.selected().unwrap_or(0),
fn expand_selected_area_x(&mut self, positive: bool) {
if self.selection_area_corner.is_none() {
self.selection_area_corner = Some((
self.selected_column,
self.selected_row.selected().unwrap_or(0),
));
}
if let Some((x, y)) = self.selected_right_cell {
self.selected_right_cell = Some((
if let Some((x, y)) = self.selection_area_corner {
self.selection_area_corner = Some((
if positive {
(x + 1).min(self.headers.len().saturating_sub(1))
} else {
@ -184,25 +150,15 @@ impl TableComponent {
}
}
pub fn expand_selected_area_y(&mut self, positive: bool) {
if self.select_state.selected().is_none() {
self.select_state = self.state.clone();
}
if positive {
self.next_select(1);
} else {
self.previout_select(1);
}
if self.selected_right_cell.is_none() {
self.selected_right_cell = Some((
self.selected_left_column_index,
self.state.selected().unwrap_or(0),
fn expand_selected_area_y(&mut self, positive: bool) {
if self.selection_area_corner.is_none() {
self.selection_area_corner = Some((
self.selected_column,
self.selected_row.selected().unwrap_or(0),
));
}
if let Some((x, y)) = self.selected_right_cell {
self.selected_right_cell = Some((
if let Some((x, y)) = self.selection_area_corner {
self.selection_area_corner = Some((
x,
if positive {
(y + 1).min(self.rows.len().saturating_sub(1))
@ -213,50 +169,48 @@ impl TableComponent {
}
}
pub fn is_row_number_clumn(&self, row_index: usize, column_index: usize) -> bool {
matches!(self.state.selected(), Some(selected_row_index) if row_index == selected_row_index && 0 == column_index)
fn is_row_number_clumn(&self, row_index: usize, column_index: usize) -> bool {
matches!(self.selected_row.selected(), Some(selected_row_index) if row_index == selected_row_index && 0 == column_index)
}
pub fn selected_cells(&self) -> Option<String> {
if let Some((x, y)) = self.selected_right_cell {
let selected_row_index = self.state.selected()?;
if let Some((x, y)) = self.selection_area_corner {
let selected_row_index = self.selected_row.selected()?;
return Some(
self.rows[y.min(selected_row_index)..y.max(selected_row_index) + 1]
.iter()
.map(|row| {
row[x.min(self.selected_left_column_index)
..x.max(self.selected_left_column_index) + 1]
.join(",")
row[x.min(self.selected_column)..x.max(self.selected_column) + 1].join(",")
})
.collect::<Vec<String>>()
.join("\n"),
);
}
self.rows
.get(self.state.selected()?)?
.get(self.selected_left_column_index)
.get(self.selected_row.selected()?)?
.get(self.selected_column)
.map(|cell| cell.to_string())
}
pub fn selected_column_index(&self) -> usize {
if let Some((x, _)) = self.selected_right_cell {
fn selected_column_index(&self) -> usize {
if let Some((x, _)) = self.selection_area_corner {
return x;
}
self.selected_left_column_index
self.selected_column
}
pub fn is_selected_cell(
fn is_selected_cell(
&self,
row_index: usize,
column_index: usize,
selected_column_index: usize,
) -> bool {
if let Some((x, y)) = self.selected_right_cell {
if let Some((x, y)) = self.selection_area_corner {
let x_in_page = x
.saturating_add(1)
.saturating_sub(self.column_page_start.get());
return matches!(
self.state.selected(),
self.selected_row.selected(),
Some(selected_row_index)
if (x_in_page.min(selected_column_index).max(1)..x_in_page.max(selected_column_index) + 1)
.contains(&column_index)
@ -264,16 +218,16 @@ impl TableComponent {
.contains(&row_index)
);
}
matches!(self.state.selected(), Some(selected_row_index) if row_index == selected_row_index && column_index == selected_column_index)
matches!(self.selected_row.selected(), Some(selected_row_index) if row_index == selected_row_index && column_index == selected_column_index)
}
pub fn headers_with_number(&self, left: usize, right: usize) -> Vec<String> {
fn headers_with_number(&self, left: usize, right: usize) -> Vec<String> {
let mut headers = self.headers.clone()[left..right].to_vec();
headers.insert(0, "".to_string());
headers
}
pub fn rows_with_number(&self, left: usize, right: usize) -> Vec<Vec<String>> {
fn rows_with_number(&self, left: usize, right: usize) -> Vec<Vec<String>> {
let rows = self
.rows
.iter()
@ -287,7 +241,7 @@ impl TableComponent {
new_rows
}
pub fn calculate_widths(
fn calculate_widths(
&self,
area_width: u16,
) -> (usize, Vec<String>, Vec<Vec<String>>, Vec<Constraint>) {
@ -386,14 +340,14 @@ impl TableComponent {
constraints.insert(0, Constraint::Length(number_clomn_width));
self.column_page_start.set(left_column_index);
(
self.selected_right_cell
self.selection_area_corner
.map_or(selected_column_index + 1, |(x, _)| {
if x > self.selected_left_column_index {
if x > self.selected_column {
(selected_column_index + 1)
.saturating_sub(x.saturating_sub(self.selected_left_column_index))
.saturating_sub(x.saturating_sub(self.selected_column))
} else {
(selected_column_index + 1)
.saturating_add(self.selected_left_column_index.saturating_sub(x))
.saturating_add(self.selected_column.saturating_sub(x))
}
}),
self.headers_with_number(left_column_index, right_column_index),
@ -410,7 +364,7 @@ impl DrawableComponent for TableComponent {
.constraints(vec![Constraint::Length(3), Constraint::Length(5)])
.split(area);
self.state.selected().map_or_else(
self.selected_row.selected().map_or_else(
|| {
self.scroll.reset();
},
@ -461,24 +415,21 @@ impl DrawableComponent for TableComponent {
let table = Table::new(rows)
.header(header)
.block(block)
.highlight_style(if self.select_entire_row {
Style::default().bg(Color::Blue)
} else {
Style::default()
})
.style(if focused {
Style::default()
} else {
Style::default().fg(Color::DarkGray)
})
.widths(&constraints);
let mut state = self.selected_row.clone();
f.render_stateful_widget(
table,
layout[1],
if self.select_state.selected().is_some() {
&mut self.select_state
if let Some((_, y)) = self.selection_area_corner {
state.select(Some(y));
&mut state
} else {
&mut self.state
&mut self.selected_row
},
);
@ -495,29 +446,25 @@ impl Component for TableComponent {
return Ok(EventState::Consumed);
}
Key::Char('j') => {
self.next(1);
self.next_row(1);
return Ok(EventState::NotConsumed);
}
Key::Ctrl('d') => {
self.next(10);
self.next_row(10);
return Ok(EventState::NotConsumed);
}
Key::Char('k') => {
self.previous(1);
self.previous_row(1);
return Ok(EventState::Consumed);
}
Key::Ctrl('u') => {
self.previous(10);
self.previous_row(10);
return Ok(EventState::Consumed);
}
Key::Char('g') => {
self.scroll_top();
return Ok(EventState::Consumed);
}
Key::Char('r') => {
self.select_entire_row = true;
return Ok(EventState::Consumed);
}
Key::Char('G') => {
self.scroll_bottom();
return Ok(EventState::Consumed);
@ -591,10 +538,10 @@ mod test {
vec!["a", "b", "c"].iter().map(|h| h.to_string()).collect(),
vec!["d", "e", "f"].iter().map(|h| h.to_string()).collect(),
];
component.state.select(Some(1));
component.selected_left_column_index = 1;
component.selected_row.select(Some(1));
component.selected_column = 1;
component.expand_selected_area_x(false);
assert_eq!(component.selected_right_cell, Some((0, 1)));
assert_eq!(component.selection_area_corner, Some((0, 1)));
assert_eq!(component.selected_cells(), Some("d,e".to_string()));
}
@ -616,10 +563,10 @@ mod test {
vec!["a", "b", "c"].iter().map(|h| h.to_string()).collect(),
vec!["d", "e", "f"].iter().map(|h| h.to_string()).collect(),
];
component.state.select(Some(1));
component.selected_left_column_index = 1;
component.selected_row.select(Some(1));
component.selected_column = 1;
component.expand_selected_area_x(true);
assert_eq!(component.selected_right_cell, Some((2, 1)));
assert_eq!(component.selection_area_corner, Some((2, 1)));
assert_eq!(component.selected_cells(), Some("e,f".to_string()));
}
@ -640,10 +587,10 @@ mod test {
vec!["a", "b", "c"].iter().map(|h| h.to_string()).collect(),
vec!["d", "e", "f"].iter().map(|h| h.to_string()).collect(),
];
component.state.select(Some(1));
component.selected_left_column_index = 1;
component.selected_row.select(Some(1));
component.selected_column = 1;
component.expand_selected_area_y(false);
assert_eq!(component.selected_right_cell, Some((1, 0)));
assert_eq!(component.selection_area_corner, Some((1, 0)));
assert_eq!(component.selected_cells(), Some("b\ne".to_string()));
}
@ -664,10 +611,10 @@ mod test {
vec!["a", "b", "c"].iter().map(|h| h.to_string()).collect(),
vec!["d", "e", "f"].iter().map(|h| h.to_string()).collect(),
];
component.state.select(Some(0));
component.selected_left_column_index = 1;
component.selected_row.select(Some(0));
component.selected_column = 1;
component.expand_selected_area_y(true);
assert_eq!(component.selected_right_cell, Some((1, 1)));
assert_eq!(component.selection_area_corner, Some((1, 1)));
assert_eq!(component.selected_cells(), Some("b\ne".to_string()));
}
@ -683,7 +630,7 @@ mod test {
vec!["a", "b", "c"].iter().map(|h| h.to_string()).collect(),
vec!["d", "e", "f"].iter().map(|h| h.to_string()).collect(),
];
component.state.select(Some(0));
component.selected_row.select(Some(0));
assert_eq!(component.selected_cells(), Some("a".to_string()));
}
@ -699,8 +646,8 @@ mod test {
vec!["a", "b", "c"].iter().map(|h| h.to_string()).collect(),
vec!["d", "e", "f"].iter().map(|h| h.to_string()).collect(),
];
component.state.select(Some(0));
component.selected_right_cell = Some((1, 1));
component.selected_row.select(Some(0));
component.selection_area_corner = Some((1, 1));
assert_eq!(component.selected_cells(), Some("a,b\nd,e".to_string()));
}
@ -716,7 +663,7 @@ mod test {
vec!["a", "b", "c"].iter().map(|h| h.to_string()).collect(),
vec!["d", "e", "f"].iter().map(|h| h.to_string()).collect(),
];
component.state.select(Some(0));
component.selected_row.select(Some(0));
// a
assert!(component.is_selected_cell(0, 1, 1));
// d
@ -737,8 +684,8 @@ mod test {
vec!["a", "b", "c"].iter().map(|h| h.to_string()).collect(),
vec!["d", "e", "f"].iter().map(|h| h.to_string()).collect(),
];
component.state.select(Some(0));
component.selected_right_cell = Some((1, 1));
component.selected_row.select(Some(0));
component.selection_area_corner = Some((1, 1));
// a
assert!(component.is_selected_cell(0, 1, 1));
// b

Loading…
Cancel
Save