super_table/
row.rs

1use std::slice::Iter;
2
3use crate::{
4    cell::{Cell, Cells},
5    utils::formatting::content_split::measure_text_width,
6};
7
8/// Each row contains [Cells](crate::Cell) and can be added to a [Table](crate::Table).
9#[derive(Clone, Debug, Default)]
10pub struct Row {
11    /// Index of the row.
12    /// This will be set as soon as the row is added to the table.
13    pub(crate) index: Option<usize>,
14    pub(crate) cells: Vec<Cell>,
15    pub(crate) max_height: Option<usize>,
16}
17
18impl Row {
19    pub fn new() -> Self {
20        Self::default()
21    }
22
23    /// Add a cell to the row.
24    ///
25    /// **Attention:**
26    /// If a row has already been added to a table and you add more cells to it
27    /// than there're columns currently know to the [Table](crate::Table) struct,
28    /// these columns won't be known to the table unless you call
29    /// [crate::Table::discover_columns].
30    ///
31    /// ```rust
32    /// use super_table::{Row, Cell};
33    ///
34    /// let mut row = Row::new();
35    /// row.add_cell(Cell::new("One"));
36    /// ```
37    pub fn add_cell(&mut self, cell: Cell) -> &mut Self {
38        self.cells.push(cell);
39
40        self
41    }
42
43    /// Truncate content of cells which occupies more than X lines of space.
44    ///
45    /// ```
46    /// use super_table::{Row, Cell};
47    ///
48    /// let mut row = Row::new();
49    /// row.max_height(5);
50    /// ```
51    pub fn max_height(&mut self, lines: usize) -> &mut Self {
52        self.max_height = Some(lines);
53
54        self
55    }
56
57    /// Get the longest content width for all cells of this row
58    pub(crate) fn max_content_widths(&self) -> Vec<usize> {
59        // Iterate over all cells
60        self.cells
61            .iter()
62            .map(|cell| {
63                // Iterate over all content strings and return a vector of string widths.
64                // Each entry represents the longest string width for a cell.
65                cell.content
66                    .iter()
67                    .map(|string| measure_text_width(string))
68                    .max()
69                    .unwrap_or(0)
70            })
71            .collect()
72    }
73
74    /// Get the amount of cells on this row.
75    pub fn cell_count(&self) -> usize {
76        self.cells.len()
77    }
78
79    /// Get the effective column count for this row, accounting for colspan.
80    ///
81    /// This sums up the colspan of all cells in the row to determine
82    /// how many column positions the row actually occupies.
83    pub(crate) fn effective_column_count(&self) -> usize {
84        self.cells.iter().map(|cell| cell.colspan() as usize).sum()
85    }
86
87    /// Returns an iterator over all cells of this row
88    pub fn cell_iter(&self) -> Iter<'_, Cell> {
89        self.cells.iter()
90    }
91}
92
93/// Create a Row from any `Into<Cells>`. \
94/// [Cells] is a simple wrapper around a `Vec<Cell>`.
95///
96/// Check the [From] implementations on [Cell] for more information.
97///
98/// ```rust
99/// use super_table::{Row, Cell};
100///
101/// let row = Row::from(vec!["One", "Two", "Three",]);
102/// let row = Row::from(vec![
103///    Cell::new("One"),
104///    Cell::new("Two"),
105///    Cell::new("Three"),
106/// ]);
107/// let row = Row::from(vec![1, 2, 3, 4]);
108/// ```
109impl<T: Into<Cells>> From<T> for Row {
110    fn from(cells: T) -> Self {
111        Self {
112            index: None,
113            cells: cells.into().0,
114            max_height: None,
115        }
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122
123    #[test]
124    fn test_correct_max_content_width() {
125        let row = Row::from(vec![
126            "",
127            "four",
128            "fivef",
129            "sixsix",
130            "11 but with\na newline",
131        ]);
132
133        let max_content_widths = row.max_content_widths();
134
135        assert_eq!(max_content_widths, vec![0, 4, 5, 6, 11]);
136    }
137
138    #[test]
139    fn test_some_functions() {
140        let cells = ["one", "two", "three"];
141        let mut row = Row::new();
142        for cell in cells.iter() {
143            row.add_cell(Cell::new(cell));
144        }
145        assert_eq!(row.cell_count(), cells.len());
146
147        let mut cell_content_iter = cells.iter();
148        for cell in row.cell_iter() {
149            assert_eq!(
150                cell.content(),
151                cell_content_iter.next().unwrap().to_string()
152            );
153        }
154    }
155}