1 | use 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)] |
9 | pub struct HorizontalPanel<S> { |
10 | text: S, |
11 | row: usize, |
12 | } |
13 | |
14 | impl<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 | |
21 | impl<S, R, D> TableOption<R, D, ColoredConfig> for HorizontalPanel<S> |
22 | where |
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: usize = records.count_rows(); |
28 | let count_cols: usize = records.count_columns(); |
29 | |
30 | if self.row > count_rows { |
31 | return; |
32 | } |
33 | |
34 | let is_intersect_vertical_span: bool = (0..records.count_columns()) |
35 | .any(|col: usize| cfg.is_cell_covered_by_row_span((self.row, col))); |
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: String = self.text.as_ref().to_owned(); |
44 | records.set((self.row, 0), text); |
45 | |
46 | cfg.set_column_span((self.row, 0), span:count_cols); |
47 | } |
48 | } |
49 | |
50 | fn move_rows_aside<R: ExactRecords + Resizable>(records: &mut R, row: usize) { |
51 | records.push_row(); |
52 | |
53 | let count_rows: usize = records.count_rows(); |
54 | |
55 | let shift_count: usize = count_rows - row; |
56 | for i: usize in 1..shift_count { |
57 | let row: usize = count_rows - i; |
58 | records.swap_row(lhs:row, rhs:row - 1); |
59 | } |
60 | } |
61 | |
62 | fn move_row_spans(cfg: &mut SpannedConfig, target_row: usize) { |
63 | for ((row: usize, col: usize), span: usize) in cfg.get_column_spans() { |
64 | if row < target_row { |
65 | continue; |
66 | } |
67 | |
68 | cfg.set_column_span((row, col), span:1); |
69 | cfg.set_column_span((row + 1, col), span); |
70 | } |
71 | |
72 | for ((row: usize, col: usize), span: usize) in cfg.get_row_spans() { |
73 | if row < target_row { |
74 | continue; |
75 | } |
76 | |
77 | cfg.set_row_span((row, col), span:1); |
78 | cfg.set_row_span((row + 1, col), span); |
79 | } |
80 | } |
81 | |