summaryrefslogtreecommitdiffstats
path: root/vendor/tabled/src/settings/span/column.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/tabled/src/settings/span/column.rs')
-rw-r--r--vendor/tabled/src/settings/span/column.rs125
1 files changed, 125 insertions, 0 deletions
diff --git a/vendor/tabled/src/settings/span/column.rs b/vendor/tabled/src/settings/span/column.rs
new file mode 100644
index 000000000..50af64c23
--- /dev/null
+++ b/vendor/tabled/src/settings/span/column.rs
@@ -0,0 +1,125 @@
+use crate::{
+ grid::{
+ config::{ColoredConfig, Entity, Position, SpannedConfig},
+ records::{ExactRecords, Records},
+ },
+ settings::CellOption,
+};
+
+/// Columns (Vertical) span.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub struct ColumnSpan {
+ size: usize,
+}
+
+impl ColumnSpan {
+ /// Creates a new column (vertical) span.
+ pub fn new(size: usize) -> Self {
+ Self { size }
+ }
+
+ /// Creates a new column (vertical) span with a maximux value possible.
+ pub fn max() -> Self {
+ Self::new(usize::MAX)
+ }
+}
+
+impl<R> CellOption<R, ColoredConfig> for ColumnSpan
+where
+ R: Records + ExactRecords,
+{
+ fn change(self, records: &mut R, cfg: &mut ColoredConfig, entity: Entity) {
+ let count_rows = records.count_rows();
+ let count_cols = records.count_columns();
+
+ set_col_spans(cfg, self.size, entity, (count_rows, count_cols));
+ remove_false_spans(cfg);
+ }
+}
+
+fn set_col_spans(cfg: &mut SpannedConfig, span: usize, entity: Entity, shape: (usize, usize)) {
+ for pos in entity.iter(shape.0, shape.1) {
+ if !is_valid_pos(pos, shape) {
+ continue;
+ }
+
+ let mut span = span;
+ if !is_column_span_valid(pos.1, span, shape.1) {
+ span = shape.1 - pos.1;
+ }
+
+ if span_has_intersections(cfg, pos, span) {
+ continue;
+ }
+
+ set_span_column(cfg, pos, span);
+ }
+}
+
+fn set_span_column(cfg: &mut SpannedConfig, pos: (usize, usize), span: usize) {
+ if span == 0 {
+ let (row, col) = pos;
+ if col == 0 {
+ return;
+ }
+
+ if let Some(closecol) = closest_visible(cfg, (row, col - 1)) {
+ let span = col + 1 - closecol;
+ cfg.set_column_span((row, closecol), span);
+ }
+ }
+
+ cfg.set_column_span(pos, span);
+}
+
+fn closest_visible(cfg: &SpannedConfig, mut pos: Position) -> Option<usize> {
+ loop {
+ if cfg.is_cell_visible(pos) {
+ return Some(pos.1);
+ }
+
+ if pos.1 == 0 {
+ return None;
+ }
+
+ pos.1 -= 1;
+ }
+}
+
+fn is_column_span_valid(col: usize, span: usize, count_cols: usize) -> bool {
+ span + col <= count_cols
+}
+
+fn is_valid_pos((row, col): Position, (count_rows, count_cols): (usize, usize)) -> bool {
+ row < count_rows && col < count_cols
+}
+
+fn span_has_intersections(cfg: &SpannedConfig, (row, col): Position, span: usize) -> bool {
+ for col in col..col + span {
+ if !cfg.is_cell_visible((row, col)) {
+ return true;
+ }
+ }
+
+ false
+}
+
+fn remove_false_spans(cfg: &mut SpannedConfig) {
+ for (pos, _) in cfg.get_column_spans() {
+ if cfg.is_cell_visible(pos) {
+ continue;
+ }
+
+ cfg.set_row_span(pos, 1);
+ cfg.set_column_span(pos, 1);
+ }
+
+ for (pos, _) in cfg.get_row_spans() {
+ if cfg.is_cell_visible(pos) {
+ continue;
+ }
+
+ cfg.set_row_span(pos, 1);
+ cfg.set_column_span(pos, 1);
+ }
+}