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