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}