feat(table): Implement FromIterator for widgets::Row (#755)

The `Row::new` constructor accepts a single argument that implements
`IntoIterator`.  This commit adds an implementation of `FromIterator`,
as a thin wrapper around `Row::new`.  This allows `.collect::<Row>()`
to be used at the end of an iterator chain, rather than wrapping the
entire iterator chain in `Row::new`.
This commit is contained in:
Eric Lunderberg 2024-01-06 22:23:38 -06:00 committed by GitHub
parent bc274e2bd9
commit e64e194b6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 8 deletions

View File

@ -118,17 +118,17 @@ fn ui(f: &mut Frame, app: &mut App) {
let selected_style = Style::default().add_modifier(Modifier::REVERSED); let selected_style = Style::default().add_modifier(Modifier::REVERSED);
let normal_style = Style::default().bg(Color::Blue); let normal_style = Style::default().bg(Color::Blue);
let header_cells = ["Header1", "Header2", "Header3"] let header = ["Header1", "Header2", "Header3"]
.iter() .iter()
.map(|h| Cell::from(*h).style(Style::default().fg(Color::Red))); .map(|h| Cell::from(*h).style(Style::default().fg(Color::Red)))
let header = Row::new(header_cells) .collect::<Row>()
.style(normal_style) .style(normal_style)
.height(1) .height(1)
.bottom_margin(1); .bottom_margin(1);
let footer_cells = ["Footer1", "Footer2", "Footer3"] let footer = ["Footer1", "Footer2", "Footer3"]
.iter() .iter()
.map(|f| Cell::from(*f).style(Style::default().fg(Color::Yellow))); .map(|f| Cell::from(*f).style(Style::default().fg(Color::Yellow)))
let footer = Row::new(footer_cells) .collect::<Row>()
.style(normal_style) .style(normal_style)
.height(1) .height(1)
.top_margin(1); .top_margin(1);
@ -139,8 +139,11 @@ fn ui(f: &mut Frame, app: &mut App) {
.max() .max()
.unwrap_or(0) .unwrap_or(0)
+ 1; + 1;
let cells = item.iter().map(|c| Cell::from(*c)); item.iter()
Row::new(cells).height(height as u16).bottom_margin(1) .cloned()
.collect::<Row>()
.height(height as u16)
.bottom_margin(1)
}); });
let t = Table::new( let t = Table::new(
rows, rows,

View File

@ -45,6 +45,14 @@ use crate::prelude::*;
/// ]); /// ]);
/// ``` /// ```
/// ///
/// An iterator whose item type is convertible into [`Text`] can be collected into a row.
///
/// ```rust
/// use ratatui::widgets::Row;
///
/// (0..10).map(|i| format!("{i}")).collect::<Row>();
/// ```
///
/// `Row` implements [`Styled`] which means you can use style shorthands from the [`Stylize`] trait /// `Row` implements [`Styled`] which means you can use style shorthands from the [`Stylize`] trait
/// to set the style of the row concisely. /// to set the style of the row concisely.
/// ///
@ -235,6 +243,15 @@ impl<'a> Styled for Row<'a> {
} }
} }
impl<'a, Item> FromIterator<Item> for Row<'a>
where
Item: Into<Cell<'a>>,
{
fn from_iter<IterCells: IntoIterator<Item = Item>>(cells: IterCells) -> Self {
Row::new(cells)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::vec; use std::vec;
@ -249,6 +266,13 @@ mod tests {
assert_eq!(row.cells, cells); assert_eq!(row.cells, cells);
} }
#[test]
fn collect() {
let cells = vec![Cell::from("")];
let row: Row = cells.iter().cloned().collect();
assert_eq!(row.cells, cells);
}
#[test] #[test]
fn cells() { fn cells() {
let cells = vec![Cell::from("")]; let cells = vec![Cell::from("")];