diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index 94b600e7..c6c29af1 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -11,7 +11,8 @@ github with a [breaking change] label. This is a quick summary of the sections below: - Unreleased (0.24.1) - - `Table::widths()` now accepts `AsRef<[Constraint]>` + - `Table::new()` now requires specifying the widths + -`Table::widths()` now accepts `IntoIterator>` - Layout::new() now accepts direction and constraint parameters - The default `Tabs::highlight_style` is now `Style::new().reversed()` @@ -46,9 +47,39 @@ widget in the default configuration would not show any indication of the selecte [#635]: https://github.com/ratatui-org/ratatui/pull/635 -### `Table::widths()` now accepts `AsRef<[Constraint]>` ([#628]) +### The default `Tabs::highlight_style` is now `Style::new().reversed()` ([#635]) -[#628]: https://github.com/ratatui-org/ratatui/pull/628 +Previously the default highlight style for tabs was `Style::default()`, which meant that a `Tabs` +widget in the default configuration would not show any indication of the selected tab. + + +### `Table::new()` now requires specifying the widths of the columrs (#664) + +Previously `Table`s could be constructed without widths. In almost all cases this is an error. +A new widths parameter is now manadatory on `Table::new()`. Existing code of the form: + +```rust +Table::new(rows).widths(widths) +``` + +Should be updated to: + +```rust +Table::new(rows, widths) +``` + +For ease of automated replacement in cases where the amount of code broken by this change is large +or complex, it may be convenient to replace `Table::new` with `Table::default().rows`. + +```rust +Table::new(rows).block(block).widths(widths); +// becomes +Table::default().rows(rows).widths(widths) +``` + +### `Table::widths()` now accepts `IntoIterator>` ([#663]) + +[#663]: https://github.com/ratatui-org/ratatui/pull/663 Previously `Table::widths()` took a slice (`&'a [Constraint]`). This change will introduce clippy `needless_borrow` warnings for places where slices are passed to this method. To fix these, remove diff --git a/examples/demo/ui.rs b/examples/demo/ui.rs index f40f712d..10c73ef8 100644 --- a/examples/demo/ui.rs +++ b/examples/demo/ui.rs @@ -289,18 +289,20 @@ fn draw_second_tab(f: &mut Frame, app: &mut App, area: Rect) { }; Row::new(vec![s.name, s.location, s.status]).style(style) }); - let table = Table::new(rows) - .header( - Row::new(vec!["Server", "Location", "Status"]) - .style(Style::default().fg(Color::Yellow)) - .bottom_margin(1), - ) - .block(Block::default().title("Servers").borders(Borders::ALL)) - .widths([ + let table = Table::new( + rows, + [ Constraint::Length(15), Constraint::Length(15), Constraint::Length(10), - ]); + ], + ) + .header( + Row::new(vec!["Server", "Location", "Status"]) + .style(Style::default().fg(Color::Yellow)) + .bottom_margin(1), + ) + .block(Block::default().title("Servers").borders(Borders::ALL)); f.render_widget(table, chunks[0]); let map = Canvas::default() @@ -393,12 +395,14 @@ fn draw_third_tab(f: &mut Frame, _app: &mut App, area: Rect) { Row::new(cells) }) .collect(); - let table = Table::new(items) - .block(Block::default().title("Colors").borders(Borders::ALL)) - .widths([ + let table = Table::new( + items, + [ Constraint::Ratio(1, 3), Constraint::Ratio(1, 3), Constraint::Ratio(1, 3), - ]); + ], + ) + .block(Block::default().title("Colors").borders(Borders::ALL)); f.render_widget(table, chunks[0]); } diff --git a/examples/demo2/tabs/recipe.rs b/examples/demo2/tabs/recipe.rs index 67aaef54..15c59f4e 100644 --- a/examples/demo2/tabs/recipe.rs +++ b/examples/demo2/tabs/recipe.rs @@ -146,10 +146,9 @@ fn render_ingredients(selected_row: usize, area: Rect, buf: &mut Buffer) { let rows = INGREDIENTS.iter().map(|&i| i.into()).collect_vec(); let theme = THEME.recipe; StatefulWidget::render( - Table::new(rows) + Table::new(rows, [Constraint::Length(7), Constraint::Length(30)]) .block(Block::new().style(theme.ingredients)) .header(Row::new(vec!["Qty", "Ingredient"]).style(theme.ingredients_header)) - .widths([Constraint::Length(7), Constraint::Length(30)]) .highlight_style(Style::new().light_yellow()), area, buf, diff --git a/examples/demo2/tabs/traceroute.rs b/examples/demo2/tabs/traceroute.rs index 40a79eb7..c4800710 100644 --- a/examples/demo2/tabs/traceroute.rs +++ b/examples/demo2/tabs/traceroute.rs @@ -50,9 +50,8 @@ fn render_hops(selected_row: usize, area: Rect, buf: &mut Buffer) { .title_alignment(Alignment::Center) .padding(Padding::new(1, 1, 1, 1)); StatefulWidget::render( - Table::new(rows) + Table::new(rows, [Constraint::Max(100), Constraint::Length(15)]) .header(Row::new(vec!["Host", "Address"]).set_style(THEME.traceroute.header)) - .widths([Constraint::Max(100), Constraint::Length(15)]) .highlight_style(THEME.traceroute.selected) .block(block), area, diff --git a/examples/table.rs b/examples/table.rs index 000086eb..b639a8f6 100644 --- a/examples/table.rs +++ b/examples/table.rs @@ -137,15 +137,17 @@ fn ui(f: &mut Frame, app: &mut App) { let cells = item.iter().map(|c| Cell::from(*c)); Row::new(cells).height(height as u16).bottom_margin(1) }); - let t = Table::new(rows) - .header(header) - .block(Block::default().borders(Borders::ALL).title("Table")) - .highlight_style(selected_style) - .highlight_symbol(">> ") - .widths([ + let t = Table::new( + rows, + [ Constraint::Percentage(50), Constraint::Max(30), Constraint::Min(10), - ]); + ], + ) + .header(header) + .block(Block::default().borders(Borders::ALL).title("Table")) + .highlight_style(selected_style) + .highlight_symbol(">> "); f.render_stateful_widget(t, rects[0], &mut app.state); } diff --git a/src/widgets/table.rs b/src/widgets/table.rs index 95ae4ca8..9441e940 100644 --- a/src/widgets/table.rs +++ b/src/widgets/table.rs @@ -204,28 +204,33 @@ impl HighlightSpacing { /// ```rust /// use ratatui::{prelude::*, widgets::*}; /// -/// Table::new(vec![ -/// // Row can be created from simple strings. -/// Row::new(vec!["Row11", "Row12", "Row13"]), -/// // You can style the entire row. -/// Row::new(vec!["Row21", "Row22", "Row23"]).style(Style::default().fg(Color::Blue)), -/// // If you need more control over the styling you may need to create Cells directly -/// Row::new(vec![ -/// Cell::from("Row31"), -/// Cell::from("Row32").style(Style::default().fg(Color::Yellow)), -/// Cell::from(Line::from(vec![ -/// Span::raw("Row"), -/// Span::styled("33", Style::default().fg(Color::Green)) -/// ])), -/// ]), -/// // If a Row need to display some content over multiple lines, you just have to change -/// // its height. -/// Row::new(vec![ -/// Cell::from("Row\n41"), -/// Cell::from("Row\n42"), -/// Cell::from("Row\n43"), -/// ]).height(2), -/// ]) +/// Table::new( +/// vec![ +/// // Row can be created from simple strings. +/// Row::new(vec!["Row11", "Row12", "Row13"]), +/// // You can style the entire row. +/// Row::new(vec!["Row21", "Row22", "Row23"]).style(Style::default().fg(Color::Blue)), +/// // If you need more control over the styling you may need to create Cells directly +/// Row::new(vec![ +/// Cell::from("Row31"), +/// Cell::from("Row32").style(Style::default().fg(Color::Yellow)), +/// Cell::from(Line::from(vec![ +/// Span::raw("Row"), +/// Span::styled("33", Style::default().fg(Color::Green)) +/// ])), +/// ]), +/// // If a Row need to display some content over multiple lines, you just have to change +/// // its height. +/// Row::new(vec![ +/// Cell::from("Row\n41"), +/// Cell::from("Row\n42"), +/// Cell::from("Row\n43"), +/// ]).height(2), +/// ], +/// // Columns widths are constrained in the same way as Layout... +/// [Constraint::Length(5), Constraint::Length(5), Constraint::Length(10)]) +/// // ...and they can be separated by a fixed spacing. +/// .column_spacing(1) /// // You can set the style of the entire Table. /// .style(Style::default().fg(Color::White)) /// // It has an optional header, which is simply a Row always visible at the top. @@ -238,10 +243,6 @@ impl HighlightSpacing { /// ) /// // As any other widget, a Table can be wrapped in a Block. /// .block(Block::default().title("Table")) -/// // Columns widths are constrained in the same way as Layout... -/// .widths(&[Constraint::Length(5), Constraint::Length(5), Constraint::Length(10)]) -/// // ...and they can be separated by a fixed spacing. -/// .column_spacing(1) /// // If you wish to highlight a row in any specific way when it is selected... /// .highlight_style(Style::default().add_modifier(Modifier::BOLD)) /// // ...and potentially show a symbol in front of the selection. @@ -275,31 +276,41 @@ impl<'a> Table<'a> { /// Creates a new [`Table`] widget with the given rows. /// /// The `rows` parameter is a Vector of [`Row`], this holds the data to be displayed by the - /// table + /// table. + /// + /// The `widths` parameter is an array (or any other type that implements IntoIterator) of + /// [`Constraint`]s, this holds the widths of each column. This parameter was added in 0.25.0. /// /// # Examples /// /// ```rust /// # use ratatui::{prelude::*, widgets::*}; - /// let table = Table::new(vec![ - /// Row::new(vec![ - /// Cell::from("Cell1"), - /// Cell::from("Cell2") - /// ]), - /// Row::new(vec![ - /// Cell::from("Cell3"), - /// Cell::from("Cell4") - /// ]), - /// ]); + /// let table = Table::new( + /// vec![ + /// Row::new(vec![ + /// Cell::from("Cell1"), + /// Cell::from("Cell2") + /// ]), + /// Row::new(vec![ + /// Cell::from("Cell3"), + /// Cell::from("Cell4") + /// ]), + /// ], + /// [Constraint::Length(5), Constraint::Length(5)] + /// ); /// ``` - pub fn new(rows: T) -> Self + pub fn new(rows: R, widths: C) -> Self where - T: IntoIterator>, + R: IntoIterator>, + C: IntoIterator, + C::Item: AsRef, { + let widths = widths.into_iter().map(|c| *c.as_ref()).collect_vec(); + ensure_percentages_less_than_100(&widths); Self { block: None, style: Style::default(), - widths: vec![], + widths, column_spacing: 1, highlight_style: Style::default(), highlight_symbol: None, @@ -319,16 +330,20 @@ impl<'a> Table<'a> { /// /// ```rust /// # use ratatui::{prelude::*, widgets::*}; - /// let table = Table::new(vec![ - /// Row::new(vec![ - /// Cell::from("Cell1"), - /// Cell::from("Cell2") - /// ]), - /// Row::new(vec![ - /// Cell::from("Cell3"), - /// Cell::from("Cell4") - /// ]), - /// ]).block(Block::default().title("Table")); + /// let table = Table::new( + /// vec![ + /// Row::new(vec![ + /// Cell::from("Cell1"), + /// Cell::from("Cell2") + /// ]), + /// Row::new(vec![ + /// Cell::from("Cell3"), + /// Cell::from("Cell4") + /// ]), + /// ], + /// [Constraint::Length(5), Constraint::Length(5)] + /// ) + /// .block(Block::default().title("Table")); /// ``` pub fn block(mut self, block: Block<'a>) -> Self { self.block = Some(block); @@ -344,12 +359,13 @@ impl<'a> Table<'a> { /// /// ```rust /// # use ratatui::{prelude::*, widgets::*}; - /// let table = Table::new(vec![ - /// Row::new(vec![ - /// Cell::from("Cell1"), - /// Cell::from("Cell2") - /// ]) - /// ]).header( + /// let table = Table::new( + /// vec![ + /// Row::new(vec![Cell::from("Cell1"), Cell::from("Cell2")]) + /// ], + /// [Constraint::Length(20), Constraint::Length(20)] + /// ) + /// .header( /// Row::new(vec![ /// Cell::from("Header Cell 1"), /// Cell::from("Header Cell 2") @@ -370,13 +386,13 @@ impl<'a> Table<'a> { /// /// ```rust /// # use ratatui::{prelude::*, widgets::*}; - /// let table = Table::new(vec![]).widths([Constraint::Length(5), Constraint::Length(5)]); - /// let table = Table::new(vec![]).widths(&[Constraint::Length(5), Constraint::Length(5)]); + /// let table = Table::default().widths([Constraint::Length(5), Constraint::Length(5)]); + /// let table = Table::default().widths(&[Constraint::Length(5), Constraint::Length(5)]); /// /// // widths could also be computed at runtime /// let widths = vec![Constraint::Length(5), Constraint::Length(5)]; - /// let table = Table::new(vec![]).widths(widths.clone()); - /// let table = Table::new(vec![]).widths(&widths); + /// let table = Table::default().widths(widths.clone()); + /// let table = Table::default().widths(&widths); /// ``` pub fn widths(mut self, widths: I) -> Self where @@ -384,14 +400,7 @@ impl<'a> Table<'a> { C: AsRef, { let widths = widths.into_iter().map(|c| *c.as_ref()).collect_vec(); - let between_0_and_100 = |&w| match w { - Constraint::Percentage(p) => p <= 100, - _ => true, - }; - assert!( - widths.iter().all(between_0_and_100), - "Percentages should be between 0 and 100 inclusively." - ); + ensure_percentages_less_than_100(&widths); self.widths = widths; self } @@ -491,6 +500,7 @@ impl<'a> Table<'a> { /// space to the last column or to distribute it equally. /// /// # Examples + /// /// Create a table that needs at least 30 columns to display. Any extra space will be assigned /// to the last column. #[cfg_attr(feature = "unstable", doc = " ```")] @@ -499,8 +509,7 @@ impl<'a> Table<'a> { /// # use ratatui::layout::SegmentSize; /// # use ratatui::widgets::Table; /// let widths = [Constraint::Min(10), Constraint::Min(10), Constraint::Min(10)]; - /// let table = Table::new([]) - /// .widths(widths) + /// let table = Table::new([], widths) /// .segment_size(SegmentSize::LastTakesRemainder); /// ``` #[stability::unstable( @@ -514,6 +523,17 @@ impl<'a> Table<'a> { } } +fn ensure_percentages_less_than_100(widths: &[Constraint]) { + let between_0_and_100 = |&w| match w { + Constraint::Percentage(p) => p <= 100, + _ => true, + }; + assert!( + widths.iter().all(between_0_and_100), + "Percentages should be between 0 and 100 inclusively." + ); +} + impl<'a> Styled for Table<'a> { type Item = Table<'a>; @@ -710,30 +730,30 @@ mod tests { #[test] #[should_panic] fn table_invalid_percentages() { - Table::new(vec![]).widths([Constraint::Percentage(110)]); + Table::new(vec![], [Constraint::Percentage(110)]); } #[test] fn widths_conversions() { let array = [Constraint::Percentage(100)]; - let table = Table::new(vec![]).widths(array); + let table = Table::new(vec![], array); assert_eq!(table.widths, vec![Constraint::Percentage(100)], "array"); let array_ref = &[Constraint::Percentage(100)]; - let table = Table::new(vec![]).widths(array_ref); + let table = Table::new(vec![], array_ref); assert_eq!(table.widths, vec![Constraint::Percentage(100)], "array ref"); let vec = vec![Constraint::Percentage(100)]; let slice = vec.as_slice(); - let table = Table::new(vec![]).widths(slice); + let table = Table::new(vec![], slice); assert_eq!(table.widths, vec![Constraint::Percentage(100)], "slice"); let vec = vec![Constraint::Percentage(100)]; - let table = Table::new(vec![]).widths(vec); + let table = Table::new(vec![], vec); assert_eq!(table.widths, vec![Constraint::Percentage(100)], "vec"); let vec_ref = &vec![Constraint::Percentage(100)]; - let table = Table::new(vec![]).widths(vec_ref); + let table = Table::new(vec![], vec_ref); assert_eq!(table.widths, vec![Constraint::Percentage(100)], "vec ref"); } @@ -751,9 +771,7 @@ mod tests { selection_width: u16, expected: &[(u16, u16)], ) { - let table = Table::new(vec![]) - .segment_size(segment_size) - .widths(constraints); + let table = Table::new(vec![], constraints).segment_size(segment_size); let widths = table.get_columns_widths(available_width, selection_width); assert_eq!(widths, expected); @@ -997,12 +1015,14 @@ mod tests { #[test] fn test_render_table_with_alignment() { let mut buf = Buffer::empty(Rect::new(0, 0, 20, 3)); - let table = Table::new(vec![ - Row::new(vec![Line::from("Left").alignment(Alignment::Left)]), - Row::new(vec![Line::from("Center").alignment(Alignment::Center)]), - Row::new(vec![Line::from("Right").alignment(Alignment::Right)]), - ]) - .widths([Percentage(100)]); + let table = Table::new( + vec![ + Row::new(vec![Line::from("Left").alignment(Alignment::Left)]), + Row::new(vec![Line::from("Center").alignment(Alignment::Center)]), + Row::new(vec![Line::from("Right").alignment(Alignment::Right)]), + ], + [Percentage(100)], + ); Widget::render(table, Rect::new(0, 0, 20, 3), &mut buf); @@ -1047,7 +1067,7 @@ mod tests { #[test] fn table_can_be_stylized() { assert_eq!( - Table::new(vec![Row::new(vec![Cell::from("")])]) + Table::new(vec![Row::new(vec![Cell::from("")])], [Percentage(100)]) .black() .on_white() .bold() diff --git a/tests/widgets_table.rs b/tests/widgets_table.rs index 15ef24ca..cbe97fa8 100644 --- a/tests/widgets_table.rs +++ b/tests/widgets_table.rs @@ -19,19 +19,21 @@ fn widgets_table_column_spacing_can_be_changed() { terminal .draw(|f| { let size = f.size(); - let table = Table::new(vec![ - Row::new(vec!["Row11", "Row12", "Row13"]), - Row::new(vec!["Row21", "Row22", "Row23"]), - Row::new(vec!["Row31", "Row32", "Row33"]), - Row::new(vec!["Row41", "Row42", "Row43"]), - ]) + let table = Table::new( + vec![ + Row::new(vec!["Row11", "Row12", "Row13"]), + Row::new(vec!["Row21", "Row22", "Row23"]), + Row::new(vec!["Row31", "Row32", "Row33"]), + Row::new(vec!["Row41", "Row42", "Row43"]), + ], + [ + Constraint::Length(5), + Constraint::Length(5), + Constraint::Length(5), + ], + ) .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) .block(Block::default().borders(Borders::ALL)) - .widths([ - Constraint::Length(5), - Constraint::Length(5), - Constraint::Length(5), - ]) .column_spacing(column_spacing); f.render_widget(table, size); }) @@ -117,15 +119,17 @@ fn widgets_table_columns_widths_can_use_fixed_length_constraints() { terminal .draw(|f| { let size = f.size(); - let table = Table::new(vec![ - Row::new(vec!["Row11", "Row12", "Row13"]), - Row::new(vec!["Row21", "Row22", "Row23"]), - Row::new(vec!["Row31", "Row32", "Row33"]), - Row::new(vec!["Row41", "Row42", "Row43"]), - ]) + let table = Table::new( + vec![ + Row::new(vec!["Row11", "Row12", "Row13"]), + Row::new(vec!["Row21", "Row22", "Row23"]), + Row::new(vec!["Row31", "Row32", "Row33"]), + Row::new(vec!["Row41", "Row42", "Row43"]), + ], + widths, + ) .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) - .block(Block::default().borders(Borders::ALL)) - .widths(widths); + .block(Block::default().borders(Borders::ALL)); f.render_widget(table, size); }) .unwrap(); @@ -206,15 +210,17 @@ fn widgets_table_columns_widths_can_use_percentage_constraints() { terminal .draw(|f| { let size = f.size(); - let table = Table::new(vec![ - Row::new(vec!["Row11", "Row12", "Row13"]), - Row::new(vec!["Row21", "Row22", "Row23"]), - Row::new(vec!["Row31", "Row32", "Row33"]), - Row::new(vec!["Row41", "Row42", "Row43"]), - ]) + let table = Table::new( + vec![ + Row::new(vec!["Row11", "Row12", "Row13"]), + Row::new(vec!["Row21", "Row22", "Row23"]), + Row::new(vec!["Row31", "Row32", "Row33"]), + Row::new(vec!["Row41", "Row42", "Row43"]), + ], + widths, + ) .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) .block(Block::default().borders(Borders::ALL)) - .widths(widths) .column_spacing(0); f.render_widget(table, size); }) @@ -313,15 +319,17 @@ fn widgets_table_columns_widths_can_use_mixed_constraints() { terminal .draw(|f| { let size = f.size(); - let table = Table::new(vec![ - Row::new(vec!["Row11", "Row12", "Row13"]), - Row::new(vec!["Row21", "Row22", "Row23"]), - Row::new(vec!["Row31", "Row32", "Row33"]), - Row::new(vec!["Row41", "Row42", "Row43"]), - ]) + let table = Table::new( + vec![ + Row::new(vec!["Row11", "Row12", "Row13"]), + Row::new(vec!["Row21", "Row22", "Row23"]), + Row::new(vec!["Row31", "Row32", "Row33"]), + Row::new(vec!["Row41", "Row42", "Row43"]), + ], + widths, + ) .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) - .block(Block::default().borders(Borders::ALL)) - .widths(widths); + .block(Block::default().borders(Borders::ALL)); f.render_widget(table, size); }) .unwrap(); @@ -423,15 +431,17 @@ fn widgets_table_columns_widths_can_use_ratio_constraints() { terminal .draw(|f| { let size = f.size(); - let table = Table::new(vec![ - Row::new(vec!["Row11", "Row12", "Row13"]), - Row::new(vec!["Row21", "Row22", "Row23"]), - Row::new(vec!["Row31", "Row32", "Row33"]), - Row::new(vec!["Row41", "Row42", "Row43"]), - ]) + let table = Table::new( + vec![ + Row::new(vec!["Row11", "Row12", "Row13"]), + Row::new(vec!["Row21", "Row22", "Row23"]), + Row::new(vec!["Row31", "Row32", "Row33"]), + Row::new(vec!["Row41", "Row42", "Row43"]), + ], + widths, + ) .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) .block(Block::default().borders(Borders::ALL)) - .widths(widths) .column_spacing(0); f.render_widget(table, size); }) @@ -528,20 +538,22 @@ fn widgets_table_can_have_rows_with_multi_lines() { terminal .draw(|f| { let size = f.size(); - let table = Table::new(vec![ - Row::new(vec!["Row11", "Row12", "Row13"]), - Row::new(vec!["Row21", "Row22", "Row23"]).height(2), - Row::new(vec!["Row31", "Row32", "Row33"]), - Row::new(vec!["Row41", "Row42", "Row43"]).height(2), - ]) + let table = Table::new( + vec![ + Row::new(vec!["Row11", "Row12", "Row13"]), + Row::new(vec!["Row21", "Row22", "Row23"]).height(2), + Row::new(vec!["Row31", "Row32", "Row33"]), + Row::new(vec!["Row41", "Row42", "Row43"]).height(2), + ], + [ + Constraint::Length(5), + Constraint::Length(5), + Constraint::Length(5), + ], + ) .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) .block(Block::default().borders(Borders::ALL)) .highlight_symbol(">> ") - .widths([ - Constraint::Length(5), - Constraint::Length(5), - Constraint::Length(5), - ]) .column_spacing(1); f.render_stateful_widget(table, size, state); }) @@ -622,21 +634,23 @@ fn widgets_table_enable_always_highlight_spacing() { terminal .draw(|f| { let size = f.size(); - let table = Table::new(vec![ - Row::new(vec!["Row11", "Row12", "Row13"]), - Row::new(vec!["Row21", "Row22", "Row23"]).height(2), - Row::new(vec!["Row31", "Row32", "Row33"]), - Row::new(vec!["Row41", "Row42", "Row43"]).height(2), - ]) + let table = Table::new( + vec![ + Row::new(vec!["Row11", "Row12", "Row13"]), + Row::new(vec!["Row21", "Row22", "Row23"]).height(2), + Row::new(vec!["Row31", "Row32", "Row33"]), + Row::new(vec!["Row41", "Row42", "Row43"]).height(2), + ], + [ + Constraint::Length(5), + Constraint::Length(5), + Constraint::Length(5), + ], + ) .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) .block(Block::default().borders(Borders::ALL)) .highlight_symbol(">> ") .highlight_spacing(space) - .widths([ - Constraint::Length(5), - Constraint::Length(5), - Constraint::Length(5), - ]) .column_spacing(1); f.render_stateful_widget(table, size, state); }) @@ -756,28 +770,31 @@ fn widgets_table_can_have_elements_styled_individually() { terminal .draw(|f| { let size = f.size(); - let table = Table::new(vec![ - Row::new(vec!["Row11", "Row12", "Row13"]).style(Style::default().fg(Color::Green)), - Row::new(vec![ - Cell::from("Row21"), - Cell::from("Row22").style(Style::default().fg(Color::Yellow)), - Cell::from(Line::from(vec![ - Span::raw("Row"), - Span::styled("23", Style::default().fg(Color::Blue)), - ])) - .style(Style::default().fg(Color::Red)), - ]) - .style(Style::default().fg(Color::LightGreen)), - ]) + let table = Table::new( + vec![ + Row::new(vec!["Row11", "Row12", "Row13"]) + .style(Style::default().fg(Color::Green)), + Row::new(vec![ + Cell::from("Row21"), + Cell::from("Row22").style(Style::default().fg(Color::Yellow)), + Cell::from(Line::from(vec![ + Span::raw("Row"), + Span::styled("23", Style::default().fg(Color::Blue)), + ])) + .style(Style::default().fg(Color::Red)), + ]) + .style(Style::default().fg(Color::LightGreen)), + ], + [ + Constraint::Length(6), + Constraint::Length(6), + Constraint::Length(6), + ], + ) .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) .block(Block::default().borders(Borders::LEFT | Borders::RIGHT)) .highlight_symbol(">> ") .highlight_style(Style::default().add_modifier(Modifier::BOLD)) - .widths([ - Constraint::Length(6), - Constraint::Length(6), - Constraint::Length(6), - ]) .column_spacing(1); f.render_stateful_widget(table, size, &mut state); }) @@ -831,15 +848,17 @@ fn widgets_table_should_render_even_if_empty() { terminal .draw(|f| { let size = f.size(); - let table = Table::new(vec![]) - .header(Row::new(vec!["Head1", "Head2", "Head3"])) - .block(Block::default().borders(Borders::LEFT | Borders::RIGHT)) - .widths([ + let table = Table::new( + vec![], + [ Constraint::Length(6), Constraint::Length(6), Constraint::Length(6), - ]) - .column_spacing(1); + ], + ) + .header(Row::new(vec!["Head1", "Head2", "Head3"])) + .block(Block::default().borders(Borders::LEFT | Borders::RIGHT)) + .column_spacing(1); f.render_widget(table, size); }) .unwrap(); @@ -869,17 +888,19 @@ fn widgets_table_columns_dont_panic() { // based on https://github.com/fdehau/tui-rs/issues/470#issuecomment-852562848 let table1_width = 98; - let table1 = Table::new(vec![Row::new(vec!["r1", "r2", "r3", "r4"])]) - .header(Row::new(vec!["h1", "h2", "h3", "h4"])) - .block(Block::default().borders(Borders::ALL)) - .highlight_symbol(">> ") - .column_spacing(1) - .widths([ + let table1 = Table::new( + vec![Row::new(vec!["r1", "r2", "r3", "r4"])], + [ Constraint::Percentage(15), Constraint::Percentage(15), Constraint::Percentage(25), Constraint::Percentage(45), - ]); + ], + ) + .header(Row::new(vec!["h1", "h2", "h3", "h4"])) + .block(Block::default().borders(Borders::ALL)) + .highlight_symbol(">> ") + .column_spacing(1); let mut state = TableState::default(); @@ -899,21 +920,23 @@ fn widgets_table_should_clamp_offset_if_rows_are_removed() { terminal .draw(|f| { let size = f.size(); - let table = Table::new(vec![ - Row::new(vec!["Row01", "Row02", "Row03"]), - Row::new(vec!["Row11", "Row12", "Row13"]), - Row::new(vec!["Row21", "Row22", "Row23"]), - Row::new(vec!["Row31", "Row32", "Row33"]), - Row::new(vec!["Row41", "Row42", "Row43"]), - Row::new(vec!["Row51", "Row52", "Row53"]), - ]) + let table = Table::new( + vec![ + Row::new(vec!["Row01", "Row02", "Row03"]), + Row::new(vec!["Row11", "Row12", "Row13"]), + Row::new(vec!["Row21", "Row22", "Row23"]), + Row::new(vec!["Row31", "Row32", "Row33"]), + Row::new(vec!["Row41", "Row42", "Row43"]), + Row::new(vec!["Row51", "Row52", "Row53"]), + ], + [ + Constraint::Length(5), + Constraint::Length(5), + Constraint::Length(5), + ], + ) .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) .block(Block::default().borders(Borders::ALL)) - .widths([ - Constraint::Length(5), - Constraint::Length(5), - Constraint::Length(5), - ]) .column_spacing(1); f.render_stateful_widget(table, size, &mut state); }) @@ -935,15 +958,17 @@ fn widgets_table_should_clamp_offset_if_rows_are_removed() { terminal .draw(|f| { let size = f.size(); - let table = Table::new(vec![Row::new(vec!["Row31", "Row32", "Row33"])]) - .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) - .block(Block::default().borders(Borders::ALL)) - .widths([ + let table = Table::new( + vec![Row::new(vec!["Row31", "Row32", "Row33"])], + [ Constraint::Length(5), Constraint::Length(5), Constraint::Length(5), - ]) - .column_spacing(1); + ], + ) + .header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1)) + .block(Block::default().borders(Borders::ALL)) + .column_spacing(1); f.render_stateful_widget(table, size, &mut state); }) .unwrap();