tabled/features/
span.rs

1//! This module contains a [`Span`] settings, it helps to
2//! make a cell take more space then it generally takes.
3//!
4//! # Example
5//!
6//! ```
7//! use tabled::{object::Cell, Modify, TableIteratorExt, Span};
8//!
9//! let data = [[1, 2, 3], [4, 5, 6]];
10//!
11//! let table = data.table()
12//!     .with(Modify::new(Cell(2, 0)).with(Span::column(2)))
13//!     .with(Modify::new(Cell(0, 1)).with(Span::column(2)))
14//!     .to_string();
15//!
16//! assert_eq!(
17//!     table,
18//!     concat!(
19//!         "+---+---+---+\n",
20//!         "| 0 | 1     |\n",
21//!         "+---+---+---+\n",
22//!         "| 1 | 2 | 3 |\n",
23//!         "+---+---+---+\n",
24//!         "| 4     | 6 |\n",
25//!         "+---+---+---+",
26//!     )
27//! )
28//! ```
29
30use papergrid::{records::Records, Entity};
31
32use crate::{CellOption, Table};
33
34/// Span represent a horizontal/column span setting for any cell on a [`Table`].
35///
36/// It will be ignored if:
37///  - cell position is out of scope
38///  - size is bigger then the total number of columns.
39///  - size is bigger then the total number of rows.
40///
41/// ```rust,no_run
42/// # use tabled::{Style, Span, Modify, object::Columns, Table};
43/// # let data: Vec<&'static str> = Vec::new();
44/// let table = Table::new(&data)
45///     .with(Modify::new(Columns::single(0)).with(Span::column(2)));
46/// ```
47///
48/// [`Table`]: crate::Table
49#[derive(Debug)]
50pub struct Span(SpanType);
51
52#[derive(Debug)]
53enum SpanType {
54    Column(usize),
55    Row(usize),
56}
57
58impl Span {
59    /// New constructs a horizontal/column [`Span`].
60    ///
61    /// If size is bigger then the total number of columns it will be ignored.
62    pub fn column(size: usize) -> Self {
63        Self(SpanType::Column(size))
64    }
65
66    /// New constructs a vertical/row [`Span`].
67    ///
68    /// If size is bigger then the total number of rows it will be ignored.
69    pub fn row(size: usize) -> Self {
70        Self(SpanType::Row(size))
71    }
72}
73
74impl<R> CellOption<R> for Span
75where
76    R: Records,
77{
78    fn change_cell(&mut self, table: &mut Table<R>, entity: Entity) {
79        let (count_rows, count_cols) = table.shape();
80        for pos in entity.iter(count_rows, count_cols) {
81            match self.0 {
82                SpanType::Column(size) => {
83                    table.get_config_mut().set_column_span(pos, size);
84                }
85                SpanType::Row(size) => {
86                    table.get_config_mut().set_row_span(pos, size);
87                }
88            }
89        }
90
91        table.destroy_width_cache();
92        table.destroy_height_cache();
93    }
94}