tabled/settings/panel/
horizontal_panel.rs

1use crate::{
2    grid::config::{ColoredConfig, SpannedConfig},
3    grid::records::{ExactRecords, Records, RecordsMut, Resizable},
4    settings::TableOption,
5};
6
7/// A horizontal/column span from 0 to a count rows.
8#[derive(Debug)]
9pub struct HorizontalPanel<S> {
10    text: S,
11    row: usize,
12}
13
14impl<S> HorizontalPanel<S> {
15    /// Creates a new horizontal panel.
16    pub fn new(row: usize, text: S) -> Self {
17        Self { row, text }
18    }
19}
20
21impl<S, R, D> TableOption<R, ColoredConfig, D> for HorizontalPanel<S>
22where
23    S: AsRef<str>,
24    R: Records + ExactRecords + Resizable + RecordsMut<String>,
25{
26    fn change(self, records: &mut R, cfg: &mut ColoredConfig, _: &mut D) {
27        let count_rows = records.count_rows();
28        let count_cols = records.count_columns();
29
30        if self.row > count_rows {
31            return;
32        }
33
34        let is_intersect_vertical_span = (0..records.count_columns())
35            .any(|col| cfg.is_cell_covered_by_row_span((self.row, col).into()));
36        if is_intersect_vertical_span {
37            return;
38        }
39
40        move_rows_aside(records, self.row);
41        move_row_spans(cfg, self.row);
42
43        let text = self.text.as_ref().to_owned();
44        records.set((self.row, 0).into(), text);
45
46        cfg.set_column_span((self.row, 0).into(), count_cols);
47    }
48}
49
50fn move_rows_aside<R: ExactRecords + Resizable>(records: &mut R, row: usize) {
51    records.push_row();
52
53    let count_rows = records.count_rows();
54
55    let shift_count = count_rows - row;
56    for i in 1..shift_count {
57        let row = count_rows - i;
58        records.swap_row(row, row - 1);
59    }
60}
61
62fn move_row_spans(cfg: &mut SpannedConfig, target_row: usize) {
63    for (p, span) in cfg.get_column_spans() {
64        if p.row < target_row {
65            continue;
66        }
67
68        cfg.set_column_span(p, 1);
69        cfg.set_column_span(p + (1, 0), span);
70    }
71
72    for (p, span) in cfg.get_row_spans() {
73        if p.row < target_row {
74            continue;
75        }
76
77        cfg.set_row_span(p, 1);
78        cfg.set_row_span(p + (1, 0), span);
79    }
80}