pub struct Table<'a, Selection> { /* private fields */ }
Expand description
Table widget.
Can be used as a drop-in replacement for the ratatui table. But that’s not the point of this widget.
This widget uses the TableData trait instead of rendering all the table-cells and putting them into a Vec. This way rendering time only depends on the screen-size not on the size of your data.
There is a second trait TableDataIter that works better if you only have an Iterator over your data.
See Table::data and Table::iter for an example.
Implementations§
Source§impl<'a, Selection> Table<'a, Selection>
impl<'a, Selection> Table<'a, Selection>
Sourcepub fn new_ratatui<R, C>(rows: R, widths: C) -> Selfwhere
R: IntoIterator,
R::Item: Into<Row<'a>>,
C: IntoIterator,
C::Item: Into<Constraint>,
Selection: Default,
pub fn new_ratatui<R, C>(rows: R, widths: C) -> Selfwhere
R: IntoIterator,
R::Item: Into<Row<'a>>,
C: IntoIterator,
C::Item: Into<Constraint>,
Selection: Default,
Create a new Table with preformatted data. For compatibility with ratatui.
Use of Table::data is preferred.
Sourcepub fn rows<T>(self, rows: T) -> Selfwhere
T: IntoIterator<Item = Row<'a>>,
pub fn rows<T>(self, rows: T) -> Selfwhere
T: IntoIterator<Item = Row<'a>>,
Set preformatted row-data. For compatibility with ratatui.
Use of Table::data is preferred.
Sourcepub fn data(self, data: impl TableData<'a> + 'a) -> Self
pub fn data(self, data: impl TableData<'a> + 'a) -> Self
Set a reference to the TableData facade to your data.
The way to go is to define a small struct that contains just a reference to your data. Then implement TableData for this struct.
use ratatui::buffer::Buffer;
use ratatui::layout::Rect;
use ratatui::style::Style;
use ratatui::text::Span;
use ratatui::widgets::{StatefulWidget, Widget};
use rat_ftable::{Table, TableContext, TableState, TableData}; ///
use rat_ftable::selection::RowSelection;
struct SampleRow;
struct Data1<'a>(&'a [SampleRow]);
impl<'a> TableData<'a> for Data1<'a> {
fn rows(&self) -> usize {
self.0.len()
}
fn row_height(&self, row: usize) -> u16 {
// to some calculations ...
1
}
fn row_style(&self, row: usize) -> Option<Style> {
// to some calculations ...
None
}
fn render_cell(&self, ctx: &TableContext, column: usize, row: usize, area: Rect, buf: &mut Buffer) {
if let Some(data) = self.0.get(row) {
let rend = match column {
0 => Span::from("column1"),
1 => Span::from("column2"),
2 => Span::from("column3"),
_ => return
};
rend.render(area, buf);
}
}
}
// When you are creating the table widget you hand over a reference
// to the facade struct.
let my_data_somewhere_else = vec![SampleRow;999999];
let mut table_state_somewhere_else = TableState::<RowSelection>::default();
// ...
let table1 = Table::default().data(Data1(&my_data_somewhere_else));
table1.render(area, buf, &mut table_state_somewhere_else);
Sourcepub fn iter(self, data: impl TableDataIter<'a> + 'a) -> Self
pub fn iter(self, data: impl TableDataIter<'a> + 'a) -> Self
Alternative representation for the data as a kind of Iterator. It uses interior iteration, which fits quite nice for this and avoids handing out lifetime bound results of the actual iterator. Which is a bit nightmarish to get right.
Caution: If you can’t give the number of rows, the table will iterate over all the data. See Table::no_row_count.
use std::iter::{Enumerate};
use std::slice::Iter;
use format_num_pattern::NumberFormat;
use ratatui::buffer::Buffer;
use ratatui::layout::{Constraint, Rect};
use ratatui::style::Color;
use ratatui::style::{Style, Stylize};
use ratatui::text::Span;
use ratatui::widgets::{Widget, StatefulWidget};
use rat_ftable::{Table, TableContext, TableState, TableDataIter};
use rat_ftable::selection::RowSelection;
struct Data {
struct RowIter1<'a> {
iter: Enumerate<Iter<'a, Sample>>,
item: Option<(usize, &'a Sample)>,
}
impl<'a> TableDataIter<'a> for RowIter1<'a> {
fn rows(&self) -> Option<usize> {
// If you can, give the length. Otherwise,
// the table will iterate all to find out a length.
None
// Some(100_000)
}
/// Select the nth element from the current position.
fn nth(&mut self, n: usize) -> bool {
self.item = self.iter.nth(n);
self.item.is_some()
}
/// Row height.
fn row_height(&self) -> u16 {
1
}
/// Row style.
fn row_style(&self) -> Option<Style> {
Some(Style::default())
}
/// Render one cell.
fn render_cell(&self,
ctx: &TableContext,
column: usize,
area: Rect,
buf: &mut Buffer)
{
let row = self.item.expect("data");
match column {
0 => {
let row_fmt = NumberFormat::new("000000").expect("fmt");
let span = Span::from(row_fmt.fmt_u(row.0));
buf.set_style(area, Style::new().black().bg(Color::from_u32(0xe7c787)));
span.render(area, buf);
}
1 => {
let span = Span::from(&row.1.text);
span.render(area, buf);
}
_ => {}
}
}
}
let mut rit = RowIter1 {
iter: data.table_data.iter().enumerate(),
item: None,
};
let table1 = Table::default()
.iter(rit)
.widths([
Constraint::Length(6),
Constraint::Length(20)
]);
let mut table_state_somewhere_else = TableState::<RowSelection>::default();
table1.render(area, buf, &mut table_state_somewhere_else);
Sourcepub fn no_row_count(self, no_row_count: bool) -> Self
pub fn no_row_count(self, no_row_count: bool) -> Self
If you work with an TableDataIter to fill the table, and if you don’t return a count with rows(), Table will run through all your iterator to find the actual number of rows.
This may take its time.
If you set no_row_count(true), this part will be skipped, and the row count will be set to an estimate of usize::MAX. This will destroy your ability to jump to the end of the data, but otherwise it’s fine. You can still page-down through the data, and if you ever reach the end, the correct row-count can be established.
Extra info: This might be only useful if you have a LOT of data. In my test it changed from 1.5ms to 150µs for about 100.000 rows. And 1.5ms is still not that much … so you probably want to test without this first and then decide.
Set the table-footer.
Sourcepub fn column_spacing(self, spacing: u16) -> Self
pub fn column_spacing(self, spacing: u16) -> Self
Spacing between columns.
Sourcepub fn layout_width(self, width: u16) -> Self
pub fn layout_width(self, width: u16) -> Self
Set the display width of the table. If this is not set, the width of the rendered area is used. The column layout uses this width.
See also auto_layout_width.
Sourcepub fn auto_layout_width(self) -> Self
pub fn auto_layout_width(self) -> Self
Calculates the width from the given column-constraints. If a fixed layout_width is set too, that one will win.
Panic: Rendering will panic, if any constraint other than Constraint::Length(), Constraint::Min() or Constraint::Max() is used.
Sourcepub fn styles(self, styles: TableStyle) -> Self
pub fn styles(self, styles: TableStyle) -> Self
Set all styles as a bundle.
Sourcepub fn header_style(self, style: Option<Style>) -> Self
pub fn header_style(self, style: Option<Style>) -> Self
Base style for the table.
Base style for the table.
Sourcepub fn auto_styles(self, auto_styles: bool) -> Self
pub fn auto_styles(self, auto_styles: bool) -> Self
Set the appropriate styles when rendering a cell. If this is set to false, no styles will be set at all. It’s up to the TableData/TableDataIter impl to set the correct styles.
Default is true.
Sourcepub fn select_row_style(self, select_style: Option<Style>) -> Self
pub fn select_row_style(self, select_style: Option<Style>) -> Self
Style for a selected row. The chosen selection must support row-selection for this to take effect.
Sourcepub fn show_row_focus(self, show: bool) -> Self
pub fn show_row_focus(self, show: bool) -> Self
Add the focus-style to the row-style if the table is focused.
Sourcepub fn select_column_style(self, select_style: Option<Style>) -> Self
pub fn select_column_style(self, select_style: Option<Style>) -> Self
Style for a selected column. The chosen selection must support column-selection for this to take effect.
Sourcepub fn show_column_focus(self, show: bool) -> Self
pub fn show_column_focus(self, show: bool) -> Self
Add the focus-style to the column-style if the table is focused.
Sourcepub fn select_cell_style(self, select_style: Option<Style>) -> Self
pub fn select_cell_style(self, select_style: Option<Style>) -> Self
Style for a selected cell. The chosen selection must support cell-selection for this to take effect.
Sourcepub fn show_cell_focus(self, show: bool) -> Self
pub fn show_cell_focus(self, show: bool) -> Self
Add the focus-style to the cell-style if the table is focused.
Sourcepub fn select_header_style(self, select_style: Option<Style>) -> Self
pub fn select_header_style(self, select_style: Option<Style>) -> Self
Style for a selected header cell. The chosen selection must support column-selection for this to take effect.
Sourcepub fn show_header_focus(self, show: bool) -> Self
pub fn show_header_focus(self, show: bool) -> Self
Add the focus-style to the header-style if the table is focused.
Style for a selected footer cell. The chosen selection must support column-selection for this to take effect.
Add the footer-style to the table-style if the table is focused.
Sourcepub fn focus_style(self, focus_style: Option<Style>) -> Self
pub fn focus_style(self, focus_style: Option<Style>) -> Self
This style will be patched onto the selection to indicate that the widget has the input focus.
The selection must support some kind of selection for this to be effective.
Trait Implementations§
Source§impl<'a, Selection> StatefulWidget for &Table<'a, Selection>where
Selection: TableSelection,
impl<'a, Selection> StatefulWidget for &Table<'a, Selection>where
Selection: TableSelection,
Source§type State = TableState<Selection>
type State = TableState<Selection>
Source§impl<Selection> StatefulWidget for Table<'_, Selection>where
Selection: TableSelection,
impl<Selection> StatefulWidget for Table<'_, Selection>where
Selection: TableSelection,
Source§type State = TableState<Selection>
type State = TableState<Selection>
Auto Trait Implementations§
impl<'a, Selection> Freeze for Table<'a, Selection>
impl<'a, Selection> !RefUnwindSafe for Table<'a, Selection>
impl<'a, Selection> !Send for Table<'a, Selection>
impl<'a, Selection> !Sync for Table<'a, Selection>
impl<'a, Selection> Unpin for Table<'a, Selection>where
Selection: Unpin,
impl<'a, Selection> !UnwindSafe for Table<'a, Selection>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more