summaryrefslogtreecommitdiffstats
path: root/vendor/papergrid/src/config/spanned/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/papergrid/src/config/spanned/mod.rs')
-rw-r--r--vendor/papergrid/src/config/spanned/mod.rs887
1 files changed, 887 insertions, 0 deletions
diff --git a/vendor/papergrid/src/config/spanned/mod.rs b/vendor/papergrid/src/config/spanned/mod.rs
new file mode 100644
index 000000000..a7f71e11c
--- /dev/null
+++ b/vendor/papergrid/src/config/spanned/mod.rs
@@ -0,0 +1,887 @@
+//! A module which contains configuration options for a [`Grid`].
+//!
+//! [`Grid`]: crate::grid::iterable::Grid
+
+mod borders_config;
+mod entity_map;
+mod formatting;
+mod offset;
+
+use std::collections::HashMap;
+
+use crate::color::{AnsiColor, StaticColor};
+use crate::config::compact::CompactConfig;
+use crate::config::{
+ AlignmentHorizontal, AlignmentVertical, Border, Borders, Entity, Indent, Position, Sides,
+};
+use borders_config::BordersConfig;
+
+pub use self::{entity_map::EntityMap, formatting::Formatting, offset::Offset};
+
+/// This structure represents a settings of a grid.
+///
+/// grid: crate::Grid.
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub struct SpannedConfig {
+ margin: Sides<ColoredMarginIndent>,
+ padding: EntityMap<Sides<ColoredIndent>>,
+ alignment_h: EntityMap<AlignmentHorizontal>,
+ alignment_v: EntityMap<AlignmentVertical>,
+ formatting: EntityMap<Formatting>,
+ span_columns: HashMap<Position, usize>,
+ span_rows: HashMap<Position, usize>,
+ borders: BordersConfig<char>,
+ borders_colors: BordersConfig<AnsiColor<'static>>,
+ borders_missing_char: char,
+ horizontal_chars: HashMap<Position, HashMap<Offset, char>>,
+ horizontal_colors: HashMap<Position, HashMap<Offset, AnsiColor<'static>>>,
+ vertical_chars: HashMap<Position, HashMap<Offset, char>>,
+ vertical_colors: HashMap<Position, HashMap<Offset, AnsiColor<'static>>>,
+ justification: EntityMap<char>,
+ justification_color: EntityMap<Option<AnsiColor<'static>>>,
+}
+
+impl Default for SpannedConfig {
+ fn default() -> Self {
+ Self {
+ margin: Sides::default(),
+ padding: EntityMap::default(),
+ formatting: EntityMap::default(),
+ alignment_h: EntityMap::new(AlignmentHorizontal::Left),
+ alignment_v: EntityMap::new(AlignmentVertical::Top),
+ span_columns: HashMap::default(),
+ span_rows: HashMap::default(),
+ borders: BordersConfig::default(),
+ borders_colors: BordersConfig::default(),
+ borders_missing_char: ' ',
+ horizontal_chars: HashMap::default(),
+ horizontal_colors: HashMap::default(),
+ vertical_chars: HashMap::default(),
+ vertical_colors: HashMap::default(),
+ justification: EntityMap::new(' '),
+ justification_color: EntityMap::default(),
+ }
+ }
+}
+
+impl SpannedConfig {
+ /// Set a margin of a grid.
+ pub fn set_margin(&mut self, margin: Sides<Indent>) {
+ self.margin.left.indent = margin.left;
+ self.margin.right.indent = margin.right;
+ self.margin.top.indent = margin.top;
+ self.margin.bottom.indent = margin.bottom;
+ }
+
+ /// Set a color of margin of a grid.
+ pub fn set_margin_color(&mut self, margin: Sides<Option<AnsiColor<'static>>>) {
+ self.margin.left.color = margin.left;
+ self.margin.right.color = margin.right;
+ self.margin.top.color = margin.top;
+ self.margin.bottom.color = margin.bottom;
+ }
+
+ /// Set an offset of margin of a grid.
+ pub fn set_margin_offset(&mut self, margin: Sides<Offset>) {
+ self.margin.left.offset = margin.left;
+ self.margin.right.offset = margin.right;
+ self.margin.top.offset = margin.top;
+ self.margin.bottom.offset = margin.bottom;
+ }
+
+ /// Returns a margin value currently set.
+ pub fn get_margin(&self) -> Sides<Indent> {
+ Sides::new(
+ self.margin.left.indent,
+ self.margin.right.indent,
+ self.margin.top.indent,
+ self.margin.bottom.indent,
+ )
+ }
+
+ /// Returns a margin color value currently set.
+ pub fn get_margin_color(&self) -> Sides<Option<AnsiColor<'static>>> {
+ Sides::new(
+ self.margin.left.color.clone(),
+ self.margin.right.color.clone(),
+ self.margin.top.color.clone(),
+ self.margin.bottom.color.clone(),
+ )
+ }
+
+ /// Returns a margin offset value currently set.
+ pub fn get_margin_offset(&self) -> Sides<Offset> {
+ Sides::new(
+ self.margin.left.offset,
+ self.margin.right.offset,
+ self.margin.top.offset,
+ self.margin.bottom.offset,
+ )
+ }
+
+ /// Clears all theme changes.
+ /// And sets it to default.
+ pub fn clear_theme(&mut self) {
+ self.borders = BordersConfig::default();
+ self.horizontal_chars.clear();
+ self.vertical_chars.clear();
+ self.horizontal_colors.clear();
+ self.vertical_colors.clear();
+ }
+
+ /// Set the [`Borders`] value as correct one.
+ pub fn set_borders(&mut self, borders: Borders<char>) {
+ self.borders.set_borders(borders);
+ }
+
+ /// Gets a global border value if set.
+ pub fn get_global_border(&self) -> Option<&char> {
+ self.borders.get_global()
+ }
+
+ /// Set the all [`Borders`] values to a char.
+ pub fn set_global_border(&mut self, c: char) {
+ self.borders.set_global(c);
+ }
+
+ /// Returns a current [`Borders`] structure.
+ pub fn get_borders(&self) -> &Borders<char> {
+ self.borders.get_borders()
+ }
+
+ /// Set the border line by row index.
+ ///
+ /// Row `0` means the top row.
+ /// Row `grid.count_rows()` means the bottom row.
+ pub fn insert_horizontal_line(&mut self, line: usize, val: HorizontalLine) {
+ self.borders.insert_horizontal_line(line, val);
+ }
+
+ /// Sets off the border line by row index if any were set
+ ///
+ /// Row `0` means the top row.
+ /// Row `grid.count_rows()` means the bottom row.
+ pub fn remove_horizontal_line(&mut self, line: usize, count_rows: usize) {
+ self.borders.remove_horizontal_line(line, count_rows);
+ }
+
+ /// Gets a overridden vertical line.
+ ///
+ /// Row `0` means the left row.
+ /// Row `grid.count_columns()` means the right most row.
+ pub fn get_vertical_line(&self, line: usize) -> Option<&VerticalLine> {
+ self.borders.get_vertical_line(line)
+ }
+
+ /// Set the border line by column index.
+ ///
+ /// Row `0` means the left row.
+ /// Row `grid.count_columns()` means the right most row.
+ pub fn insert_vertical_line(&mut self, line: usize, val: VerticalLine) {
+ self.borders.insert_vertical_line(line, val);
+ }
+
+ /// Sets off the border line by column index if any were set
+ ///
+ /// Row `0` means the left row.
+ /// Row `grid.count_columns()` means the right most row.
+ pub fn remove_vertical_line(&mut self, line: usize, count_columns: usize) {
+ self.borders.remove_vertical_line(line, count_columns);
+ }
+
+ /// Gets a overridden line.
+ ///
+ /// Row `0` means the top row.
+ /// Row `grid.count_rows()` means the bottom row.
+ pub fn get_horizontal_line(&self, line: usize) -> Option<&HorizontalLine> {
+ self.borders.get_horizontal_line(line)
+ }
+
+ /// Override a character on a horizontal line.
+ ///
+ /// If borders are not set the char won't be used.
+ ///
+ /// It takes not cell position but line as row and column of a cell;
+ /// So its range is line <= count_rows && col < count_columns.
+ pub fn set_horizontal_char(&mut self, pos: Position, c: char, offset: Offset) {
+ let chars = self
+ .horizontal_chars
+ .entry(pos)
+ .or_insert_with(|| HashMap::with_capacity(1));
+
+ chars.insert(offset, c);
+ }
+
+ /// Get a list of overridden chars in a horizontal border.
+ ///
+ /// It takes not cell position but line as row and column of a cell;
+ /// So its range is line <= count_rows && col < count_columns.
+ pub fn lookup_horizontal_char(&self, pos: Position, offset: usize, end: usize) -> Option<char> {
+ self.horizontal_chars
+ .get(&pos)
+ .and_then(|chars| {
+ chars.get(&Offset::Begin(offset)).or_else(|| {
+ if end > offset {
+ if end == 0 {
+ chars.get(&Offset::End(0))
+ } else {
+ chars.get(&Offset::End(end - offset - 1))
+ }
+ } else {
+ None
+ }
+ })
+ })
+ .copied()
+ }
+
+ /// Checks if there any char in a horizontal border being overridden.
+ ///
+ /// It takes not cell position but line as row and column of a cell;
+ /// So its range is line <= count_rows && col < count_columns.
+ pub fn is_overridden_horizontal(&self, pos: Position) -> bool {
+ self.horizontal_chars.get(&pos).is_some()
+ }
+
+ /// Removes a list of overridden chars in a horizontal border.
+ ///
+ /// It takes not cell position but line as row and column of a cell;
+ /// So its range is line <= count_rows && col < count_columns.
+ pub fn remove_overridden_horizontal(&mut self, pos: Position) {
+ self.horizontal_chars.remove(&pos);
+ }
+
+ /// Override a vertical split line.
+ ///
+ /// If borders are not set the char won't be used.
+ ///
+ /// It takes not cell position but cell row and column of a line;
+ /// So its range is row < count_rows && col <= count_columns.
+ pub fn set_vertical_char(&mut self, pos: Position, c: char, offset: Offset) {
+ let chars = self
+ .vertical_chars
+ .entry(pos)
+ .or_insert_with(|| HashMap::with_capacity(1));
+
+ chars.insert(offset, c);
+ }
+
+ /// Get a list of overridden chars in a horizontal border.
+ ///
+ /// It takes not cell position but cell row and column of a line;
+ /// So its range is row < count_rows && col <= count_columns.
+ pub fn lookup_vertical_char(&self, pos: Position, offset: usize, end: usize) -> Option<char> {
+ self.vertical_chars
+ .get(&pos)
+ .and_then(|chars| {
+ chars.get(&Offset::Begin(offset)).or_else(|| {
+ if end > offset {
+ if end == 0 {
+ chars.get(&Offset::End(0))
+ } else {
+ chars.get(&Offset::End(end - offset - 1))
+ }
+ } else {
+ None
+ }
+ })
+ })
+ .copied()
+ }
+
+ /// Checks if there any char in a horizontal border being overridden.
+ ///
+ /// It takes not cell position but cell row and column of a line;
+ /// So its range is row < count_rows && col <= count_columns.
+ pub fn is_overridden_vertical(&self, pos: Position) -> bool {
+ self.vertical_chars.get(&pos).is_some()
+ }
+
+ /// Removes a list of overridden chars in a horizontal border.
+ ///
+ /// It takes not cell position but cell row and column of a line;
+ /// So its range is row < count_rows && col <= count_columns.
+ pub fn remove_overridden_vertical(&mut self, pos: Position) {
+ self.vertical_chars.remove(&pos);
+ }
+
+ /// Override a character color on a horizontal line.
+ pub fn set_horizontal_color(&mut self, pos: Position, c: AnsiColor<'static>, offset: Offset) {
+ let chars = self
+ .horizontal_colors
+ .entry(pos)
+ .or_insert_with(|| HashMap::with_capacity(1));
+
+ chars.insert(offset, c);
+ }
+
+ /// Get a overridden color in a horizontal border.
+ pub fn lookup_horizontal_color(
+ &self,
+ pos: Position,
+ offset: usize,
+ end: usize,
+ ) -> Option<&AnsiColor<'static>> {
+ self.horizontal_colors.get(&pos).and_then(|chars| {
+ chars.get(&Offset::Begin(offset)).or_else(|| {
+ if end > offset {
+ if end == 0 {
+ chars.get(&Offset::End(0))
+ } else {
+ chars.get(&Offset::End(end - offset - 1))
+ }
+ } else {
+ None
+ }
+ })
+ })
+ }
+
+ /// Override a character color on a vertical line.
+ pub fn set_vertical_color(&mut self, pos: Position, c: AnsiColor<'static>, offset: Offset) {
+ let chars = self
+ .vertical_colors
+ .entry(pos)
+ .or_insert_with(|| HashMap::with_capacity(1));
+
+ chars.insert(offset, c);
+ }
+
+ /// Get a overridden color in a vertical border.
+ pub fn lookup_vertical_color(
+ &self,
+ pos: Position,
+ offset: usize,
+ end: usize,
+ ) -> Option<&AnsiColor<'static>> {
+ self.vertical_colors.get(&pos).and_then(|chars| {
+ chars.get(&Offset::Begin(offset)).or_else(|| {
+ if end > offset {
+ if end == 0 {
+ chars.get(&Offset::End(0))
+ } else {
+ chars.get(&Offset::End(end - offset - 1))
+ }
+ } else {
+ None
+ }
+ })
+ })
+ }
+
+ /// Set a padding to a given cells.
+ pub fn set_padding(&mut self, entity: Entity, padding: Sides<Indent>) {
+ let mut pad = self.padding.get(entity).clone();
+ pad.left.indent = padding.left;
+ pad.right.indent = padding.right;
+ pad.top.indent = padding.top;
+ pad.bottom.indent = padding.bottom;
+
+ self.padding.insert(entity, pad);
+ }
+
+ /// Set a padding to a given cells.
+ pub fn set_padding_color(
+ &mut self,
+ entity: Entity,
+ padding: Sides<Option<AnsiColor<'static>>>,
+ ) {
+ let mut pad = self.padding.get(entity).clone();
+ pad.left.color = padding.left;
+ pad.right.color = padding.right;
+ pad.top.color = padding.top;
+ pad.bottom.color = padding.bottom;
+
+ self.padding.insert(entity, pad);
+ }
+
+ /// Get a padding for a given [Entity].
+ pub fn get_padding(&self, entity: Entity) -> Sides<Indent> {
+ let pad = self.padding.get(entity);
+ Sides::new(
+ pad.left.indent,
+ pad.right.indent,
+ pad.top.indent,
+ pad.bottom.indent,
+ )
+ }
+
+ /// Get a padding color for a given [Entity].
+ pub fn get_padding_color(&self, entity: Entity) -> Sides<Option<AnsiColor<'static>>> {
+ let pad = self.padding.get(entity);
+ Sides::new(
+ pad.left.color.clone(),
+ pad.right.color.clone(),
+ pad.top.color.clone(),
+ pad.bottom.color.clone(),
+ )
+ }
+
+ /// Set a formatting to a given cells.
+ pub fn set_formatting(&mut self, entity: Entity, formatting: Formatting) {
+ self.formatting.insert(entity, formatting);
+ }
+
+ /// Get a formatting settings for a given [Entity].
+ pub fn get_formatting(&self, entity: Entity) -> &Formatting {
+ self.formatting.get(entity)
+ }
+
+ /// Set a vertical alignment to a given cells.
+ pub fn set_alignment_vertical(&mut self, entity: Entity, alignment: AlignmentVertical) {
+ self.alignment_v.insert(entity, alignment);
+ }
+
+ /// Get a vertical alignment for a given [Entity].
+ pub fn get_alignment_vertical(&self, entity: Entity) -> &AlignmentVertical {
+ self.alignment_v.get(entity)
+ }
+
+ /// Set a horizontal alignment to a given cells.
+ pub fn set_alignment_horizontal(&mut self, entity: Entity, alignment: AlignmentHorizontal) {
+ self.alignment_h.insert(entity, alignment);
+ }
+
+ /// Get a horizontal alignment for a given [Entity].
+ pub fn get_alignment_horizontal(&self, entity: Entity) -> &AlignmentHorizontal {
+ self.alignment_h.get(entity)
+ }
+
+ /// Set border set a border value to all cells in [`Entity`].
+ pub fn set_border(&mut self, pos: Position, border: Border<char>) {
+ self.borders.insert_border(pos, border);
+ }
+
+ /// Returns a border of a cell.
+ pub fn get_border(&self, pos: Position, shape: (usize, usize)) -> Border<char> {
+ self.borders.get_border(pos, shape).copied()
+ }
+
+ /// Returns a border color of a cell.
+ pub fn get_border_color(
+ &self,
+ pos: Position,
+ shape: (usize, usize),
+ ) -> Border<&AnsiColor<'static>> {
+ self.borders_colors.get_border(pos, shape)
+ }
+
+ /// Set a character which will be used in case any misconfiguration of borders.
+ ///
+ /// It will be usde for example when you set a left char for border frame and top but didn't set a top left corner.
+ pub fn set_borders_missing(&mut self, c: char) {
+ self.borders_missing_char = c;
+ }
+
+ /// Get a character which will be used in case any misconfiguration of borders.
+ pub fn get_borders_missing(&self) -> char {
+ self.borders_missing_char
+ }
+
+ /// Gets a color of all borders on the grid.
+ pub fn get_border_color_global(&self) -> Option<&AnsiColor<'static>> {
+ self.borders_colors.get_global()
+ }
+
+ /// Sets a color of all borders on the grid.
+ pub fn set_border_color_global(&mut self, clr: AnsiColor<'static>) {
+ self.borders_colors = BordersConfig::default();
+ self.borders_colors.set_global(clr);
+ }
+
+ /// Gets colors of a borders carcass on the grid.
+ pub fn get_color_borders(&self) -> &Borders<AnsiColor<'static>> {
+ self.borders_colors.get_borders()
+ }
+
+ /// Sets colors of border carcass on the grid.
+ pub fn set_borders_color(&mut self, clrs: Borders<AnsiColor<'static>>) {
+ self.borders_colors.set_borders(clrs);
+ }
+
+ /// Sets a color of border of a cell on the grid.
+ pub fn set_border_color(&mut self, pos: Position, border: Border<AnsiColor<'static>>) {
+ self.borders_colors.insert_border(pos, border)
+ }
+
+ /// Sets off all borders possible on the [`Entity`].
+ ///
+ /// It doesn't changes globally set borders through [`SpannedConfig::set_borders`].
+ //
+ // todo: would be great to remove a shape
+ pub fn remove_border(&mut self, pos: Position, shape: (usize, usize)) {
+ self.borders.remove_border(pos, shape);
+ }
+
+ /// Gets a color of border of a cell on the grid.
+ //
+ // todo: would be great to remove a shape
+ pub fn remove_border_color(&mut self, pos: Position, shape: (usize, usize)) {
+ self.borders_colors.remove_border(pos, shape);
+ }
+
+ /// Get a justification which will be used while expanding cells width/height.
+ pub fn get_justification(&self, entity: Entity) -> char {
+ *self.justification.get(entity)
+ }
+
+ /// Get a justification color which will be used while expanding cells width/height.
+ ///
+ /// `None` means no color.
+ pub fn get_justification_color(&self, entity: Entity) -> Option<&AnsiColor<'static>> {
+ self.justification_color.get(entity).as_ref()
+ }
+
+ /// Set a justification which will be used while expanding cells width/height.
+ pub fn set_justification(&mut self, entity: Entity, c: char) {
+ self.justification.insert(entity, c);
+ }
+
+ /// Set a justification color which will be used while expanding cells width/height.
+ ///
+ /// `None` removes it.
+ pub fn set_justification_color(&mut self, entity: Entity, color: Option<AnsiColor<'static>>) {
+ self.justification_color.insert(entity, color);
+ }
+
+ /// Get a span value of the cell, if any is set.
+ pub fn get_column_spans(&self) -> HashMap<Position, usize> {
+ self.span_columns.clone()
+ }
+
+ /// Get a span value of the cell, if any is set.
+ pub fn get_row_spans(&self) -> HashMap<Position, usize> {
+ self.span_rows.clone()
+ }
+
+ /// Get a span value of the cell, if any is set.
+ pub fn get_column_span(&self, pos: Position) -> Option<usize> {
+ self.span_columns.get(&pos).copied()
+ }
+
+ /// Get a span value of the cell, if any is set.
+ pub fn get_row_span(&self, pos: Position) -> Option<usize> {
+ self.span_rows.get(&pos).copied()
+ }
+
+ /// Removes column spans.
+ pub fn remove_column_spans(&mut self) {
+ self.span_columns.clear()
+ }
+
+ /// Removes row spans.
+ pub fn remove_row_spans(&mut self) {
+ self.span_rows.clear()
+ }
+
+ /// Set a column span to a given cells.
+ ///
+ /// BEWARE
+ ///
+ /// IT'S CALLER RESPONSIBILITY TO MAKE SURE
+ /// THAT THERE NO INTERSECTIONS IN PLACE AND THE SPAN VALUE IS CORRECT
+ pub fn set_column_span(&mut self, pos: Position, span: usize) {
+ set_cell_column_span(self, pos, span);
+ }
+
+ /// Verifies if there's any spans set.
+ pub fn has_column_spans(&self) -> bool {
+ !self.span_columns.is_empty()
+ }
+
+ /// Set a column span to a given cells.
+ ///
+ /// BEWARE
+ ///
+ /// IT'S CALLER RESPONSIBILITY TO MAKE SURE
+ /// THAT THERE NO INTERSECTIONS IN PLACE AND THE SPAN VALUE IS CORRECT
+ pub fn set_row_span(&mut self, pos: Position, span: usize) {
+ set_cell_row_span(self, pos, span);
+ }
+
+ /// Verifies if there's any spans set.
+ pub fn has_row_spans(&self) -> bool {
+ !self.span_rows.is_empty()
+ }
+
+ /// Gets an intersection character which would be rendered on the grid.
+ ///
+ /// grid: crate::Grid
+ pub fn get_intersection(&self, pos: Position, shape: (usize, usize)) -> Option<char> {
+ let c = self.borders.get_intersection(pos, shape);
+ if let Some(c) = c {
+ return Some(*c);
+ }
+
+ if self.has_horizontal(pos.0, shape.0) && self.has_vertical(pos.1, shape.1) {
+ return Some(self.get_borders_missing());
+ }
+
+ None
+ }
+
+ /// Gets a horizontal character which would be rendered on the grid.
+ ///
+ /// grid: crate::Grid
+ pub fn get_horizontal(&self, pos: Position, count_rows: usize) -> Option<char> {
+ let c = self.borders.get_horizontal(pos, count_rows);
+ if let Some(c) = c {
+ return Some(*c);
+ }
+
+ if self.has_horizontal(pos.0, count_rows) {
+ return Some(self.get_borders_missing());
+ }
+
+ None
+ }
+
+ /// Gets a vertical character which would be rendered on the grid.
+ ///
+ /// grid: crate::Grid
+ pub fn get_vertical(&self, pos: Position, count_columns: usize) -> Option<char> {
+ if let Some(c) = self.borders.get_vertical(pos, count_columns) {
+ return Some(*c);
+ }
+
+ if self.has_vertical(pos.1, count_columns) {
+ return Some(self.get_borders_missing());
+ }
+
+ None
+ }
+
+ /// Gets a color of a cell horizontal.
+ pub fn get_horizontal_color(
+ &self,
+ pos: Position,
+ count_rows: usize,
+ ) -> Option<&AnsiColor<'static>> {
+ self.borders_colors.get_horizontal(pos, count_rows)
+ }
+
+ /// Gets a color of a cell vertical.
+ pub fn get_vertical_color(
+ &self,
+ pos: Position,
+ count_columns: usize,
+ ) -> Option<&AnsiColor<'static>> {
+ self.borders_colors.get_vertical(pos, count_columns)
+ }
+
+ /// Gets a color of a cell vertical.
+ pub fn get_intersection_color(
+ &self,
+ pos: Position,
+ shape: (usize, usize),
+ ) -> Option<&AnsiColor<'static>> {
+ self.borders_colors.get_intersection(pos, shape)
+ }
+
+ /// Checks if grid would have a horizontal border with the current configuration.
+ ///
+ /// grid: crate::Grid
+ pub fn has_horizontal(&self, row: usize, count_rows: usize) -> bool {
+ self.borders.has_horizontal(row, count_rows)
+ }
+
+ /// Checks if grid would have a vertical border with the current configuration.
+ ///
+ /// grid: crate::Grid
+ pub fn has_vertical(&self, col: usize, count_columns: usize) -> bool {
+ self.borders.has_vertical(col, count_columns)
+ }
+
+ /// Calculates an amount of horizontal lines would present on the grid.
+ ///
+ /// grid: crate::Grid
+ pub fn count_horizontal(&self, count_rows: usize) -> usize {
+ (0..=count_rows)
+ .filter(|&row| self.has_horizontal(row, count_rows))
+ .count()
+ }
+
+ /// Calculates an amount of vertical lines would present on the grid.
+ ///
+ /// grid: crate::Grid
+ pub fn count_vertical(&self, count_columns: usize) -> usize {
+ (0..=count_columns)
+ .filter(|&col| self.has_vertical(col, count_columns))
+ .count()
+ }
+
+ /// The function returns whether the cells will be rendered or it will be hidden because of a span.
+ pub fn is_cell_visible(&self, pos: Position) -> bool {
+ !(self.is_cell_covered_by_column_span(pos)
+ || self.is_cell_covered_by_row_span(pos)
+ || self.is_cell_covered_by_both_spans(pos))
+ }
+
+ /// The function checks if a cell is hidden because of a row span.
+ pub fn is_cell_covered_by_row_span(&self, pos: Position) -> bool {
+ is_cell_covered_by_row_span(self, pos)
+ }
+
+ /// The function checks if a cell is hidden because of a column span.
+ pub fn is_cell_covered_by_column_span(&self, pos: Position) -> bool {
+ is_cell_covered_by_column_span(self, pos)
+ }
+
+ /// The function checks if a cell is hidden indirectly because of a row and column span combination.
+ pub fn is_cell_covered_by_both_spans(&self, pos: Position) -> bool {
+ is_cell_covered_by_both_spans(self, pos)
+ }
+}
+
+impl From<CompactConfig> for SpannedConfig {
+ fn from(compact: CompactConfig) -> Self {
+ use Entity::Global;
+
+ let mut cfg = Self::default();
+
+ cfg.set_padding(Global, *compact.get_padding());
+ cfg.set_padding_color(Global, to_ansi_color(compact.get_padding_color()));
+ cfg.set_margin(*compact.get_margin());
+ cfg.set_margin_color(to_ansi_color(compact.get_margin_color()));
+ cfg.set_alignment_horizontal(Global, compact.get_alignment_horizontal());
+ cfg.set_borders(*compact.get_borders());
+ cfg.set_borders_color(borders_static_color_to_ansi_color(
+ *compact.get_borders_color(),
+ ));
+
+ if let Some(line) = compact.get_first_horizontal_line() {
+ cfg.insert_horizontal_line(
+ 1,
+ HorizontalLine {
+ intersection: line.intersection,
+ left: line.connect1,
+ right: line.connect2,
+ main: Some(line.main),
+ },
+ );
+ }
+
+ cfg
+ }
+}
+
+fn to_ansi_color(b: Sides<StaticColor>) -> Sides<Option<AnsiColor<'static>>> {
+ Sides::new(
+ Some(b.left.into()),
+ Some(b.right.into()),
+ Some(b.top.into()),
+ Some(b.bottom.into()),
+ )
+}
+
+fn borders_static_color_to_ansi_color(b: Borders<StaticColor>) -> Borders<AnsiColor<'static>> {
+ Borders {
+ left: b.left.map(|c| c.into()),
+ right: b.right.map(|c| c.into()),
+ top: b.top.map(|c| c.into()),
+ bottom: b.bottom.map(|c| c.into()),
+ bottom_intersection: b.bottom_intersection.map(|c| c.into()),
+ bottom_left: b.bottom_left.map(|c| c.into()),
+ bottom_right: b.bottom_right.map(|c| c.into()),
+ horizontal: b.horizontal.map(|c| c.into()),
+ intersection: b.intersection.map(|c| c.into()),
+ left_intersection: b.left_intersection.map(|c| c.into()),
+ right_intersection: b.right_intersection.map(|c| c.into()),
+ top_intersection: b.top_intersection.map(|c| c.into()),
+ top_left: b.top_left.map(|c| c.into()),
+ top_right: b.top_right.map(|c| c.into()),
+ vertical: b.vertical.map(|c| c.into()),
+ }
+}
+
+fn set_cell_row_span(cfg: &mut SpannedConfig, pos: Position, span: usize) {
+ // such spans aren't supported
+ if span == 0 {
+ return;
+ }
+
+ // It's a default span so we can do nothing.
+ // but we check if it's an override of a span.
+ if span == 1 {
+ cfg.span_rows.remove(&pos);
+ return;
+ }
+
+ cfg.span_rows.insert(pos, span);
+}
+
+fn set_cell_column_span(cfg: &mut SpannedConfig, pos: Position, span: usize) {
+ // such spans aren't supported
+ if span == 0 {
+ return;
+ }
+
+ // It's a default span so we can do nothing.
+ // but we check if it's an override of a span.
+ if span == 1 {
+ cfg.span_columns.remove(&pos);
+ return;
+ }
+
+ cfg.span_columns.insert(pos, span);
+}
+
+fn is_cell_covered_by_column_span(cfg: &SpannedConfig, pos: Position) -> bool {
+ cfg.span_columns
+ .iter()
+ .any(|(&(row, col), span)| pos.1 > col && pos.1 < col + span && row == pos.0)
+}
+
+fn is_cell_covered_by_row_span(cfg: &SpannedConfig, pos: Position) -> bool {
+ cfg.span_rows
+ .iter()
+ .any(|(&(row, col), span)| pos.0 > row && pos.0 < row + span && col == pos.1)
+}
+
+fn is_cell_covered_by_both_spans(cfg: &SpannedConfig, pos: Position) -> bool {
+ if !cfg.has_column_spans() || !cfg.has_row_spans() {
+ return false;
+ }
+
+ cfg.span_rows.iter().any(|(p1, row_span)| {
+ cfg.span_columns
+ .iter()
+ .filter(|(p2, _)| &p1 == p2)
+ .any(|(_, col_span)| {
+ pos.0 > p1.0 && pos.0 < p1.0 + row_span && pos.1 > p1.1 && pos.1 < p1.1 + col_span
+ })
+ })
+}
+
+#[derive(Default, Debug, Clone, PartialEq, Eq)]
+struct ColoredIndent {
+ indent: Indent,
+ color: Option<AnsiColor<'static>>,
+}
+
+/// A colorefull margin indent.
+#[derive(Debug, Clone, PartialEq, Eq)]
+struct ColoredMarginIndent {
+ /// An indent value.
+ indent: Indent,
+ /// An offset value.
+ offset: Offset,
+ /// An color value.
+ color: Option<AnsiColor<'static>>,
+}
+
+impl Default for ColoredMarginIndent {
+ fn default() -> Self {
+ Self {
+ indent: Indent::default(),
+ offset: Offset::Begin(0),
+ color: None,
+ }
+ }
+}
+
+/// HorizontalLine represents a horizontal border line.
+pub type HorizontalLine = borders_config::HorizontalLine<char>;
+
+/// HorizontalLine represents a vertical border line.
+pub type VerticalLine = borders_config::VerticalLine<char>;