diff options
Diffstat (limited to 'vendor/tabled/src/settings/panel')
-rw-r--r-- | vendor/tabled/src/settings/panel/footer.rs | 32 | ||||
-rw-r--r-- | vendor/tabled/src/settings/panel/header.rs | 32 | ||||
-rw-r--r-- | vendor/tabled/src/settings/panel/horizontal_panel.rs | 80 | ||||
-rw-r--r-- | vendor/tabled/src/settings/panel/mod.rs | 127 | ||||
-rw-r--r-- | vendor/tabled/src/settings/panel/vertical_panel.rs | 83 |
5 files changed, 354 insertions, 0 deletions
diff --git a/vendor/tabled/src/settings/panel/footer.rs b/vendor/tabled/src/settings/panel/footer.rs new file mode 100644 index 000000000..8d16481cf --- /dev/null +++ b/vendor/tabled/src/settings/panel/footer.rs @@ -0,0 +1,32 @@ +use crate::{ + grid::config::ColoredConfig, + grid::records::{ExactRecords, Records, RecordsMut, Resizable}, + settings::TableOption, +}; + +use super::Panel; + +/// Footer renders a [`Panel`] at the bottom. +/// See [`Panel`]. +#[derive(Debug)] +pub struct Footer<S>(S); + +impl<S> Footer<S> { + /// Creates a new object. + pub fn new(text: S) -> Self + where + S: AsRef<str>, + { + Self(text) + } +} + +impl<S, R, D> TableOption<R, D, ColoredConfig> for Footer<S> +where + S: AsRef<str>, + R: Records + ExactRecords + Resizable + RecordsMut<String>, +{ + fn change(self, records: &mut R, cfg: &mut ColoredConfig, dimension: &mut D) { + Panel::horizontal(records.count_rows(), self.0.as_ref()).change(records, cfg, dimension); + } +} diff --git a/vendor/tabled/src/settings/panel/header.rs b/vendor/tabled/src/settings/panel/header.rs new file mode 100644 index 000000000..e9d398cb5 --- /dev/null +++ b/vendor/tabled/src/settings/panel/header.rs @@ -0,0 +1,32 @@ +use crate::{ + grid::config::ColoredConfig, + grid::records::{ExactRecords, Records, RecordsMut, Resizable}, + settings::TableOption, +}; + +use super::Panel; + +/// Header inserts a [`Panel`] at the top. +/// See [`Panel`]. +#[derive(Debug)] +pub struct Header<S>(S); + +impl<S> Header<S> { + /// Creates a new object. + pub fn new(text: S) -> Self + where + S: AsRef<str>, + { + Self(text) + } +} + +impl<S, R, D> TableOption<R, D, ColoredConfig> for Header<S> +where + S: AsRef<str>, + R: Records + ExactRecords + Resizable + RecordsMut<String>, +{ + fn change(self, records: &mut R, cfg: &mut ColoredConfig, dimension: &mut D) { + Panel::horizontal(0, self.0.as_ref()).change(records, cfg, dimension); + } +} diff --git a/vendor/tabled/src/settings/panel/horizontal_panel.rs b/vendor/tabled/src/settings/panel/horizontal_panel.rs new file mode 100644 index 000000000..d5871d720 --- /dev/null +++ b/vendor/tabled/src/settings/panel/horizontal_panel.rs @@ -0,0 +1,80 @@ +use crate::{ + grid::config::{ColoredConfig, SpannedConfig}, + grid::records::{ExactRecords, Records, RecordsMut, Resizable}, + settings::TableOption, +}; + +/// A horizontal/column span from 0 to a count rows. +#[derive(Debug)] +pub struct HorizontalPanel<S> { + text: S, + row: usize, +} + +impl<S> HorizontalPanel<S> { + /// Creates a new horizontal panel. + pub fn new(row: usize, text: S) -> Self { + Self { row, text } + } +} + +impl<S, R, D> TableOption<R, D, ColoredConfig> for HorizontalPanel<S> +where + S: AsRef<str>, + R: Records + ExactRecords + Resizable + RecordsMut<String>, +{ + fn change(self, records: &mut R, cfg: &mut ColoredConfig, _: &mut D) { + let count_rows = records.count_rows(); + let count_cols = records.count_columns(); + + if self.row > count_rows { + return; + } + + let is_intersect_vertical_span = (0..records.count_columns()) + .any(|col| cfg.is_cell_covered_by_row_span((self.row, col))); + if is_intersect_vertical_span { + return; + } + + move_rows_aside(records, self.row); + move_row_spans(cfg, self.row); + + let text = self.text.as_ref().to_owned(); + records.set((self.row, 0), text); + + cfg.set_column_span((self.row, 0), count_cols); + } +} + +fn move_rows_aside<R: ExactRecords + Resizable>(records: &mut R, row: usize) { + records.push_row(); + + let count_rows = records.count_rows(); + + let shift_count = count_rows - row; + for i in 1..shift_count { + let row = count_rows - i; + records.swap_row(row, row - 1); + } +} + +fn move_row_spans(cfg: &mut SpannedConfig, target_row: usize) { + for ((row, col), span) in cfg.get_column_spans() { + if row < target_row { + continue; + } + + cfg.set_column_span((row, col), 1); + cfg.set_column_span((row + 1, col), span); + } + + for ((row, col), span) in cfg.get_row_spans() { + if row < target_row { + continue; + } + + cfg.set_row_span((row, col), 1); + cfg.set_row_span((row + 1, col), span); + } +} diff --git a/vendor/tabled/src/settings/panel/mod.rs b/vendor/tabled/src/settings/panel/mod.rs new file mode 100644 index 000000000..e4e819b6c --- /dev/null +++ b/vendor/tabled/src/settings/panel/mod.rs @@ -0,0 +1,127 @@ +//! This module contains primitives to create a spread row. +//! Ultimately it is a cell with a span set to a number of columns on the [`Table`]. +//! +//! You can use a [`Span`] to set a custom span. +//! +//! # Example +//! +//! ``` +//! use tabled::{Table, settings::Panel}; +//! +//! let data = [[1, 2, 3], [4, 5, 6]]; +//! +//! let table = Table::new(data) +//! .with(Panel::vertical(1, "S\np\nl\ni\nt")) +//! .with(Panel::header("Numbers")) +//! .to_string(); +//! +//! println!("{}", table); +//! +//! assert_eq!( +//! table, +//! concat!( +//! "+---+---+---+---+\n", +//! "| Numbers |\n", +//! "+---+---+---+---+\n", +//! "| 0 | S | 1 | 2 |\n", +//! "+---+ p +---+---+\n", +//! "| 1 | l | 2 | 3 |\n", +//! "+---+ i +---+---+\n", +//! "| 4 | t | 5 | 6 |\n", +//! "+---+---+---+---+", +//! ) +//! ) +//! ``` +//! +//! [`Table`]: crate::Table +//! [`Span`]: crate::settings::span::Span + +mod footer; +mod header; +mod horizontal_panel; +mod vertical_panel; + +pub use footer::Footer; +pub use header::Header; +pub use horizontal_panel::HorizontalPanel; +pub use vertical_panel::VerticalPanel; + +/// Panel allows to add a Row which has 1 continues Cell to a [`Table`]. +/// +/// See `examples/panel.rs`. +/// +/// [`Table`]: crate::Table +#[derive(Debug)] +pub struct Panel; + +impl Panel { + /// Creates an empty vertical row at given index. + /// + /// ``` + /// use tabled::{settings::Panel, Table}; + /// + /// let data = [[1, 2, 3], [4, 5, 6]]; + /// + /// let table = Table::new(data) + /// .with(Panel::vertical(1, "Tabled Releases")) + /// .to_string(); + /// + /// println!("{}", table); + /// + /// assert_eq!( + /// table, + /// concat!( + /// "+---+-----------------+---+---+\n", + /// "| 0 | Tabled Releases | 1 | 2 |\n", + /// "+---+ +---+---+\n", + /// "| 1 | | 2 | 3 |\n", + /// "+---+ +---+---+\n", + /// "| 4 | | 5 | 6 |\n", + /// "+---+-----------------+---+---+", + /// ) + /// ) + /// ``` + pub fn vertical<S: AsRef<str>>(column: usize, text: S) -> VerticalPanel<S> { + VerticalPanel::new(column, text) + } + + /// Creates an empty horizontal row at given index. + /// + /// ``` + /// use tabled::{Table, settings::Panel}; + /// + /// let data = [[1, 2, 3], [4, 5, 6]]; + /// + /// let table = Table::new(data) + /// .with(Panel::vertical(1, "")) + /// .to_string(); + /// + /// println!("{}", table); + /// + /// assert_eq!( + /// table, + /// concat!( + /// "+---+--+---+---+\n", + /// "| 0 | | 1 | 2 |\n", + /// "+---+ +---+---+\n", + /// "| 1 | | 2 | 3 |\n", + /// "+---+ +---+---+\n", + /// "| 4 | | 5 | 6 |\n", + /// "+---+--+---+---+", + /// ) + /// ) + /// ``` + pub fn horizontal<S: AsRef<str>>(row: usize, text: S) -> HorizontalPanel<S> { + HorizontalPanel::new(row, text) + } + + /// Creates an horizontal row at first row. + pub fn header<S: AsRef<str>>(text: S) -> Header<S> { + Header::new(text) + } + + /// Creates an horizontal row at last row. + pub fn footer<S: AsRef<str>>(text: S) -> Footer<S> { + Footer::new(text) + } +} diff --git a/vendor/tabled/src/settings/panel/vertical_panel.rs b/vendor/tabled/src/settings/panel/vertical_panel.rs new file mode 100644 index 000000000..ddc0a562b --- /dev/null +++ b/vendor/tabled/src/settings/panel/vertical_panel.rs @@ -0,0 +1,83 @@ +use crate::{ + grid::config::{ColoredConfig, SpannedConfig}, + grid::records::{ExactRecords, Records, RecordsMut, Resizable}, + settings::TableOption, +}; + +/// A vertical/row span from 0 to a count columns. +#[derive(Debug)] +pub struct VerticalPanel<S> { + text: S, + col: usize, +} + +impl<S> VerticalPanel<S> { + /// Creates a new vertical panel. + pub fn new(col: usize, text: S) -> Self + where + S: AsRef<str>, + { + Self { text, col } + } +} + +impl<S, R, D> TableOption<R, D, ColoredConfig> for VerticalPanel<S> +where + S: AsRef<str>, + R: Records + ExactRecords + Resizable + RecordsMut<String>, +{ + fn change(self, records: &mut R, cfg: &mut ColoredConfig, _: &mut D) { + let count_rows = records.count_rows(); + let count_cols = records.count_columns(); + + if self.col > count_cols { + return; + } + + let is_intersect_horizontal_span = (0..=records.count_rows()) + .any(|row| cfg.is_cell_covered_by_column_span((row, self.col))); + + if is_intersect_horizontal_span { + return; + } + + move_columns_aside(records, self.col); + move_column_spans(cfg, self.col); + + let text = self.text.as_ref().to_owned(); + records.set((0, self.col), text); + + cfg.set_row_span((0, self.col), count_rows); + } +} + +fn move_columns_aside<R: Records + Resizable>(records: &mut R, column: usize) { + records.push_column(); + + let count_columns = records.count_columns(); + let shift_count = count_columns - column; + for i in 1..shift_count { + let col = count_columns - i; + records.swap_column(col, col - 1); + } +} + +fn move_column_spans(cfg: &mut SpannedConfig, target_column: usize) { + for ((row, col), span) in cfg.get_column_spans() { + if col < target_column { + continue; + } + + cfg.set_column_span((row, col), 1); + cfg.set_column_span((row, col + 1), span); + } + + for ((row, col), span) in cfg.get_row_spans() { + if col < target_column { + continue; + } + + cfg.set_row_span((row, col), 1); + cfg.set_row_span((row, col + 1), span); + } +} |