Repository: zhiburt/tabled (rust)

Issue:
Overlapping Panels throw uncaught errors
### Issue and Steps to Reproduce

When using the [Panel](https://github.com/zhiburt/tabled/blob/master/tabled/src/settings/panel/mod.rs) setting, if you insert horizontal and vertical panels that overlap each other it causes the application to crash.

You can easily test this scenario by visiting the Panel example, and changing either of the vertically injected panels to 1-4; conflicting with the previously applied table-length horizontal panels. 
https://github.com/zhiburt/tabled/blob/837bed213e824ced96cd7e9dc18a0c8c439fc314/tabled/examples/panel.rs#L43-L57

### Expected Behavior

It would be in keeping with other fault-tolerant table settings that if these functions cannot resolve, they simply return without making any modifications. Although perhaps, for Panel, it could be an option to have the most recently applied panel nest within those before it? Maybe look something like this (rather than crash):

<img width="549" alt="Screenshot 2023-03-31 at 12 42 04 PM" src="https://user-images.githubusercontent.com/46393653/229180332-38a943ac-fa83-426d-928d-76fb52b45262.png">

```rust
table
    .with(Panel::header("Tabled Releases"))
    .with(Panel::footer(format!("N - {}", DATA.len())))
    .with(Panel::vertical(0, "Some text goes here"))
    .with(Panel::vertical(4, "Some text goes here")) // <-- changed
```

### Additional Details
* I also tested this scenario with [Span](https://github.com/zhiburt/tabled/blob/master/tabled/src/settings/span/mod.rs) and it crashes as well. It would seem that conflicting spans are the real issue I'm documenting here 😆 

Pull request:
Fix cell object targeting
close #319

Patch:
diff --git a/json_to_table/examples/orientation.rs b/json_to_table/examples/orientation.rs
index 2a481fc..b47e356 100644
--- a/json_to_table/examples/orientation.rs
+++ b/json_to_table/examples/orientation.rs
@@ -25,15 +25,6 @@ fn main() {
         .set_object_mode(Orientation::Horizontal);
 
     let ctable = json_to_table(&json);
-    let mut is_root = true;
-    let ctable = ctable.set_mode_visitor(move |_| {
-        if is_root {
-            is_root = false;
-            return Orientation::Vertical;
-        }
-
-        Orientation::Horizontal
-    });
 
     println!("Vertical mode\n{vtable}");
     println!("Horizontal mode\n{htable}");
diff --git a/json_to_table/src/lib.rs b/json_to_table/src/lib.rs
index 11a1da8..e304fe7 100644
--- a/json_to_table/src/lib.rs
+++ b/json_to_table/src/lib.rs
@@ -98,6 +98,6 @@ mod table;
 /// See the example in a module documentation.
 ///
 /// [`Table`]: tabled::Table
-pub fn json_to_table(value: &Value) -> JsonTable<'_> {
+pub fn json_to_table(value: &Value) -> JsonTable<&Value> {
     JsonTable::new(value)
 }
diff --git a/json_to_table/src/table.rs b/json_to_table/src/table.rs
index d210cae..54d8924 100644
--- a/json_to_table/src/table.rs
+++ b/json_to_table/src/table.rs
@@ -1,4 +1,5 @@
 use core::fmt::{self, Display};
+use std::borrow::Borrow;
 
 use serde_json::Value;
 use tabled::{
@@ -9,16 +10,17 @@ use tabled::{
 
 /// Converter of [`Value`] to a table,
 /// with a set of configurations.
+
+// todo: rename to ValueTable.
 #[derive(Debug, Clone)]
-pub struct JsonTable<'val, ModeVisitor = fn(&Value) -> Orientation> {
-    value: &'val Value,
+pub struct JsonTable<T> {
+    value: T,
     cfg: Config,
-    mode_visitor: Option<ModeVisitor>,
 }
 
-impl JsonTable<'_> {
+impl<T> JsonTable<T> {
     /// Creates a new [`JsonTable`] object.
-    pub fn new(value: &Value) -> JsonTable<'_> {
+    pub fn new(value: T) -> Self {
         JsonTable {
             value,
             cfg: Config {
@@ -28,12 +30,9 @@ impl JsonTable<'_> {
                 array_orientation: Orientation::Vertical,
                 object_orientation: Orientation::Vertical,
             },
-            mode_visitor: None,
         }
     }
-}
 
-impl<'val, ModeVisitor> JsonTable<'val, ModeVisitor> {
     /// Set a style which will be used,
     /// default is [`Style::ascii`].
     pub fn set_style(&mut self, style: impl Into<RawStyle>) -> &mut Self {
@@ -48,35 +47,17 @@ impl<'val, ModeVisitor> JsonTable<'val, ModeVisitor> {
     }
 
     /// Set a table mode for a [`serde_json::Value::Object`].
-    ///
-    /// BE AWARE: The setting works only in not collapsed mode.
     pub fn set_object_mode(&mut self, mode: Orientation) -> &mut Self {
         self.cfg.object_orientation = mode;
         self
     }
 
     /// Set a table mode for a [`serde_json::Value::Array`].
-    ///
-    /// BE AWARE: The setting works only in not collapsed mode.
     pub fn set_array_mode(&mut self, mode: Orientation) -> &mut Self {
         self.cfg.array_orientation = mode;
         self
     }
 
-    /// Set a visitor which can configure table mode at processing time.
-    ///
-    /// BE AWARE: The setting works only in not collapsed mode.
-    pub fn set_mode_visitor<F>(self, visitor: F) -> JsonTable<'val, F>
-    where
-        F: FnMut(&Value) -> Orientation,
-    {
-        JsonTable {
-            cfg: self.cfg,
-            mode_visitor: Some(visitor),
-            value: self.value,
-        }
-    }
-
     /// Set a config which will be used.
     ///
     /// You can obtain a config from a [`Table`].
@@ -141,23 +122,22 @@ impl<'val, ModeVisitor> JsonTable<'val, ModeVisitor> {
     }
 }
 
-impl<ModeVisitor> Display for JsonTable<'_, ModeVisitor>
+impl<T> Display for JsonTable<T>
 where
-    ModeVisitor: FnMut(&Value) -> Orientation + Clone,
+    T: Borrow<Value>,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut mode_visitor = self.mode_visitor.clone();
-        let table = json_to_table::json_to_table(self.value, &self.cfg, mode_visitor.as_mut());
+        let table = json_to_table::json_to_table(self.value.borrow(), &self.cfg);
         table.fmt(f)
     }
 }
 
-impl<ModeVisitor> From<JsonTable<'_, ModeVisitor>> for Table
+impl<T> From<JsonTable<T>> for Table
 where
-    ModeVisitor: FnMut(&Value) -> Orientation,
+    T: Borrow<Value>,
 {
-    fn from(mut t: JsonTable<'_, ModeVisitor>) -> Self {
-        json_to_table::json_to_table(t.value, &t.cfg, t.mode_visitor.as_mut())
+    fn from(t: JsonTable<T>) -> Self {
+        json_to_table::json_to_table(t.value.borrow(), &t.cfg)
     }
 }
 
@@ -172,7 +152,7 @@ struct Config {
 
 /// The structure represents a table mode for a given entity,
 /// either it will be rendered vertically or horizontally.
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
 pub enum Orientation {
     /// Vertical mode (from top to bottom).
     Vertical,
@@ -199,52 +179,30 @@ mod json_to_table {
 
     use super::*;
 
-    pub(super) fn json_to_table<F>(
-        value: &Value,
-        cfg: &Config,
-        mut mode_visitor: Option<&mut F>,
-    ) -> Table
-    where
-        F: FnMut(&Value) -> Orientation,
-    {
+    pub(super) fn json_to_table(value: &Value, cfg: &Config) -> Table {
         if cfg.plain {
-            json_to_table_f(value, cfg, &mut mode_visitor, true)
+            json_to_table_f(value, cfg, true)
         } else {
             json_to_table_r(value, cfg, 0, 0, true, true, false, false, &[], None)
         }
     }
 
-    fn json_to_table_f<F>(
-        v: &Value,
-        config: &Config,
-        mode_visitor: &mut Option<&mut F>,
-        outer: bool,
-    ) -> Table
-    where
-        F: FnMut(&Value) -> Orientation,
-    {
+    fn json_to_table_f(v: &Value, config: &Config, outer: bool) -> Table {
         match v {
             Value::Array(arr) => {
                 let mut builder = Builder::new();
 
-                let orientation = mode_visitor
-                    .as_mut()
-                    .map(|f| (f)(v))
-                    .unwrap_or(config.array_orientation);
-
-                match orientation {
+                match config.array_orientation {
                     Orientation::Vertical => {
                         for value in arr {
-                            let val =
-                                json_to_table_f(value, config, mode_visitor, false).to_string();
+                            let val = json_to_table_f(value, config, false).to_string();
                             builder.push_record([val]);
                         }
                     }
                     Orientation::Horizontal => {
                         let mut row = Vec::with_capacity(arr.len());
                         for value in arr {
-                            let val =
-                                json_to_table_f(value, config, mode_visitor, false).to_string();
+                            let val = json_to_table_f(value, config, false).to_string();
                             row.push(val);
                         }
 
@@ -258,16 +216,10 @@ mod json_to_table {
             Value::Object(map) => {
                 let mut builder = Builder::new();
 
-                let orientation = mode_visitor
-                    .as_mut()
-                    .map(|f| (f)(v))
-                    .unwrap_or(config.object_orientation);
-
-                match orientation {
+                match config.object_orientation {
                     Orientation::Vertical => {
                         for (key, value) in map {
-                            let val =
-                                json_to_table_f(value, config, mode_visitor, false).to_string();
+                            let val = json_to_table_f(value, config, false).to_string();
                             builder.push_record([key.clone(), val]);
                         }
                     }
@@ -275,8 +227,7 @@ mod json_to_table {
                         let mut keys = Vec::with_capacity(map.len());
                         let mut vals = Vec::with_capacity(map.len());
                         for (key, value) in map {
-                            let val =
-                                json_to_table_f(value, config, mode_visitor, false).to_string();
+                            let val = json_to_table_f(value, config, false).to_string();
                             vals.push(val);
                             keys.push(key.clone());
                         }
@@ -896,4 +847,21 @@ mod json_to_table {
             self.0 = cfg.get_borders().top_intersection.unwrap_or(' ');
         }
     }
+
+    struct GetWidths(Vec<usize>);
+
+    impl<R, D> TableOption<R, D, ColoredConfig> for GetWidths
+    where
+        R: Records,
+        for<'a> &'a R: Records,
+        for<'a> D: Dimension + Estimate<&'a R, SpannedConfig>,
+    {
+        fn change(&mut self, records: &mut R, cfg: &mut ColoredConfig, dims: &mut D) {
+            dims.estimate(&*records, cfg);
+
+            self.0 = (0..records.count_columns())
+                .map(|col| dims.get_width(col))
+                .collect();
+        }
+    }
 }
diff --git a/papergrid/src/config/compact/mod.rs b/papergrid/src/config/compact/mod.rs
index 24b4539..7064321 100644
--- a/papergrid/src/config/compact/mod.rs
+++ b/papergrid/src/config/compact/mod.rs
@@ -37,7 +37,12 @@ impl CompactConfig {
             border_colors: Borders::empty(),
             margin: Sides::filled(Indent::zero()),
             margin_color: Sides::filled(StaticColor::new("", "")),
-            padding: Sides::filled(Indent::zero()),
+            padding: Sides::new(
+                Indent::spaced(1),
+                Indent::spaced(1),
+                Indent::zero(),
+                Indent::zero(),
+            ),
             padding_color: Sides::filled(StaticColor::new("", "")),
         }
     }
@@ -134,9 +139,3 @@ impl CompactConfig {
         self.padding_color
     }
 }
-
-impl From<&CompactConfig> for CompactConfig {
-    fn from(value: &CompactConfig) -> Self {
-        *value
-    }
-}
diff --git a/tabled/examples/panel.rs b/tabled/examples/panel.rs
index 8de8c9f..9d13976 100644
--- a/tabled/examples/panel.rs
+++ b/tabled/examples/panel.rs
@@ -3,7 +3,7 @@
 
 use tabled::{
     settings::{
-        object::{Cell, Segment},
+        object::Segment,
         style::{BorderSpanCorrection, Style},
         Alignment, Modify, Panel, Width,
     },
@@ -47,8 +47,8 @@ fn main() {
         .with(Panel::footer(format!("N - {}", DATA.len())))
         .with(Panel::vertical(0, "Some text goes here"))
         .with(Panel::vertical(5, "Some text goes here"))
-        .with(Modify::new(Cell::new(0, 0)).with(Width::wrap(1)))
-        .with(Modify::new(Cell::new(0, 5)).with(Width::wrap(1)))
+        .with(Modify::new((0, 0)).with(Width::wrap(1)))
+        .with(Modify::new((0, 5)).with(Width::wrap(1)))
         .with(Modify::new(Segment::all()).with(Alignment::center()))
         .with(Style::modern())
         .with(BorderSpanCorrection);
diff --git a/tabled/src/settings/format/format_positioned.rs b/tabled/src/settings/format/format_positioned.rs
index 00bd4a4..cca05ea 100644
--- a/tabled/src/settings/format/format_positioned.rs
+++ b/tabled/src/settings/format/format_positioned.rs
@@ -24,6 +24,11 @@ where
         let count_cols = records.count_columns();
 
         for pos in entity.iter(count_rows, count_cols) {
+            let is_valid_pos = pos.0 < count_rows && pos.1 < count_cols;
+            if !is_valid_pos {
+                continue;
+            }
+
             let content = records.get_text(pos);
             let content = (self.0)(content, pos);
             records.set(pos, content);
diff --git a/tabled/src/settings/height/cell_height_increase.rs b/tabled/src/settings/height/cell_height_increase.rs
index acacbcc..05c9e0f 100644
--- a/tabled/src/settings/height/cell_height_increase.rs
+++ b/tabled/src/settings/height/cell_height_increase.rs
@@ -53,6 +53,11 @@ where
         let count_columns = records.count_columns();
 
         for pos in entity.iter(count_rows, count_columns) {
+            let is_valid_pos = pos.0 < count_rows && pos.1 < count_columns;
+            if !is_valid_pos {
+                continue;
+            }
+
             let text = records.get_text(pos);
 
             let cell_height = count_lines(text);
diff --git a/tabled/src/settings/height/cell_height_limit.rs b/tabled/src/settings/height/cell_height_limit.rs
index c085a52..1c2f53c 100644
--- a/tabled/src/settings/height/cell_height_limit.rs
+++ b/tabled/src/settings/height/cell_height_limit.rs
@@ -53,6 +53,11 @@ where
         let count_columns = records.count_columns();
 
         for pos in entity.iter(count_rows, count_columns) {
+            let is_valid_pos = pos.0 < count_rows && pos.1 < count_columns;
+            if !is_valid_pos {
+                continue;
+            }
+
             let text = records.get_text(pos);
             let count_lines = count_lines(text);
 
diff --git a/tabled/src/settings/object/mod.rs b/tabled/src/settings/object/mod.rs
index f5b3151..46893c7 100644
--- a/tabled/src/settings/object/mod.rs
+++ b/tabled/src/settings/object/mod.rs
@@ -478,6 +478,15 @@ mod tests {
 
     use super::*;
 
+    #[test]
+    fn cell_test() {
+        assert_eq!(vec_cells((0, 0), 2, 3), [Entity::Cell(0, 0)]);
+        assert_eq!(vec_cells((1, 1), 2, 3), [Entity::Cell(1, 1)]);
+        assert_eq!(vec_cells((1, 1), 0, 0), [Entity::Cell(1, 1)]);
+        assert_eq!(vec_cells((1, 100), 2, 3), [Entity::Cell(1, 100)]);
+        assert_eq!(vec_cells((100, 1), 2, 3), [Entity::Cell(100, 1)]);
+    }
+
     #[test]
     fn columns_test() {
         assert_eq!(
diff --git a/tabled/src/settings/panel/horizontal_panel.rs b/tabled/src/settings/panel/horizontal_panel.rs
index 89bc741..987c2dc 100644
--- a/tabled/src/settings/panel/horizontal_panel.rs
+++ b/tabled/src/settings/panel/horizontal_panel.rs
@@ -31,6 +31,12 @@ where
             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);
 
diff --git a/tabled/src/settings/panel/vertical_panel.rs b/tabled/src/settings/panel/vertical_panel.rs
index cf30e2d..9eb7c8d 100644
--- a/tabled/src/settings/panel/vertical_panel.rs
+++ b/tabled/src/settings/panel/vertical_panel.rs
@@ -34,6 +34,14 @@ where
             return;
         }
 
+        let is_intersect_horizontal_span = (0..=records.count_rows())
+            .any(|row| cfg.is_cell_covered_by_column_span((row, self.col)));
+
+        println!("{is_intersect_horizontal_span} {}", self.col);
+        if is_intersect_horizontal_span {
+            return;
+        }
+
         move_columns_aside(records, self.col);
         move_column_spans(cfg, self.col);
 
diff --git a/tabled/src/settings/style/raw_style.rs b/tabled/src/settings/style/raw_style.rs
index d8d1b64..8c5cbe0 100644
--- a/tabled/src/settings/style/raw_style.rs
+++ b/tabled/src/settings/style/raw_style.rs
@@ -241,6 +241,11 @@ impl RawStyle {
         self
     }
 
+    /// Insert a horizontal line to a specific row location.
+    pub fn get_horizontal(&self, row: usize) -> Option<Line> {
+        self.horizontals.get(&row).cloned()
+    }
+
     /// Set vertical border lines.
     ///
     /// # Example
@@ -356,6 +361,11 @@ impl RawStyle {
             right_bottom_corner: self.borders.bottom_right,
         })
     }
+
+    /// Returns an general borders configuration of the style.
+    pub fn get_borders(&self) -> Borders<char> {
+        self.borders
+    }
 }
 
 impl From<Borders<char>> for RawStyle {
diff --git a/tabled/src/settings/width/min_width.rs b/tabled/src/settings/width/min_width.rs
index 87b6d0f..203e6ce 100644
--- a/tabled/src/settings/width/min_width.rs
+++ b/tabled/src/settings/width/min_width.rs
@@ -115,6 +115,11 @@ where
         let count_columns = records.count_columns();
 
         for pos in entity.iter(count_rows, count_columns) {
+            let is_valid_pos = pos.0 < count_rows && pos.1 < count_columns;
+            if !is_valid_pos {
+                continue;
+            }
+
             let cell = records.get_text(pos);
             let cell_width = string_width_multiline(cell);
             if cell_width >= width {
diff --git a/tabled/src/settings/width/truncate.rs b/tabled/src/settings/width/truncate.rs
index 23dd152..b7f1ac6 100644
--- a/tabled/src/settings/width/truncate.rs
+++ b/tabled/src/settings/width/truncate.rs
@@ -205,6 +205,11 @@ where
         let colorize = need_suffix_color_preservation(&self.suffix);
 
         for pos in entity.iter(count_rows, count_columns) {
+            let is_valid_pos = pos.0 < count_rows && pos.1 < count_columns;
+            if !is_valid_pos {
+                continue;
+            }
+
             let text = records.get_text(pos);
 
             let cell_width = string_width_multiline(text);
diff --git a/tabled/src/settings/width/wrap.rs b/tabled/src/settings/width/wrap.rs
index 005f7ac..def0089 100644
--- a/tabled/src/settings/width/wrap.rs
+++ b/tabled/src/settings/width/wrap.rs
@@ -134,6 +134,11 @@ where
         let count_columns = records.count_columns();
 
         for pos in entity.iter(count_rows, count_columns) {
+            let is_valid_pos = pos.0 < records.count_rows() && pos.1 < records.count_columns();
+            if !is_valid_pos {
+                continue;
+            }
+
             let text = records.get_text(pos);
             let cell_width = string_width_multiline(text);
             if cell_width <= width {
diff --git a/tabled/src/tables/compact.rs b/tabled/src/tables/compact.rs
index a9435ea..d41a17e 100644
--- a/tabled/src/tables/compact.rs
+++ b/tabled/src/tables/compact.rs
@@ -184,6 +184,10 @@ impl<I, D> CompactTable<I, D> {
         self
     }
 
+    /// Returns a table config.
+    pub fn get_config(&self) -> &CompactConfig {
+        &self.cfg
+    }
     /// Format table into [fmt::Write]er.
     pub fn fmt<W>(self, writer: W) -> fmt::Result
     where
@@ -232,13 +236,6 @@ impl<I, D> CompactTable<I, D> {
     }
 }
 
-impl CompactTable<(), ()> {
-    /// Return a default config.
-    pub fn config() -> CompactConfig {
-        create_config()
-    }
-}
-
 impl<T, const ROWS: usize, const COLS: usize> From<[[T; COLS]; ROWS]>
     for CompactTable<[[T; COLS]; ROWS], ConstDimension<COLS, ROWS>>
 where
@@ -298,3 +295,9 @@ const fn create_config() -> CompactConfig {
         .set_alignment_horizontal(AlignmentHorizontal::Left)
         .set_borders(*Style::ascii().get_borders())
 }
+
+impl<R, D> TableOption<R, D, CompactConfig> for CompactConfig {
+    fn change(&mut self, _: &mut R, cfg: &mut CompactConfig, _: &mut D) {
+        *cfg = *self;
+    }
+}
diff --git a/tabled/src/tables/table.rs b/tabled/src/tables/table.rs
index 158b90d..3b7fe93 100644
--- a/tabled/src/tables/table.rs
+++ b/tabled/src/tables/table.rs
@@ -1,12 +1,14 @@
 //! This module contains a main table representation [`Table`].
 
+use core::ops::DerefMut;
 use std::{borrow::Cow, collections::HashMap, fmt, iter::FromIterator};
 
 use crate::{
     builder::Builder,
     grid::{
         config::{
-            AlignmentHorizontal, ColoredConfig, Entity, Formatting, Indent, Sides, SpannedConfig,
+            AlignmentHorizontal, ColoredConfig, CompactConfig, Entity, Formatting, Indent, Sides,
+            SpannedConfig,
         },
         dimension::{CompleteDimension, PeekableDimension},
         dimension::{Dimension, Estimate},
@@ -290,6 +292,18 @@ impl From<Builder> for Table {
     }
 }
 
+impl<R, D> TableOption<R, D, ColoredConfig> for CompactConfig {
+    fn change(&mut self, _: &mut R, cfg: &mut ColoredConfig, _: &mut D) {
+        *cfg.deref_mut() = (*self).into();
+    }
+}
+
+impl<R, D> TableOption<R, D, ColoredConfig> for ColoredConfig {
+    fn change(&mut self, _: &mut R, cfg: &mut ColoredConfig, _: &mut D) {
+        *cfg = self.clone();
+    }
+}
+
 fn convert_fmt_alignment(alignment: fmt::Alignment) -> AlignmentHorizontal {
     match alignment {
         fmt::Alignment::Left => AlignmentHorizontal::Left,


Test patch:
diff --git a/json_to_table/tests/test_orientation_modes.rs b/json_to_table/tests/test_orientation_modes.rs
index 14ed9cc..d7600d8 100644
--- a/json_to_table/tests/test_orientation_modes.rs
+++ b/json_to_table/tests/test_orientation_modes.rs
@@ -1,6 +1,6 @@
 use json_to_table::{json_to_table, Orientation};
 use serde_json::json;
-use tabled::{settings::Style, Table};
+use tabled::settings::Style;
 
 #[test]
 fn orientation_test_1() {
@@ -157,146 +157,168 @@ fn orientation_visitor_test() {
         }}
     );
 
-    let mut i = false;
-    let table = Table::from({
-        let mut table = json_to_table(&value).set_mode_visitor(|_| {
-            if i {
-                i = false;
-                Orientation::Horizontal
-            } else {
-                i = true;
-                Orientation::Vertical
-            }
-        });
-
-        table.set_style(Style::modern());
-
-        table
-    })
-    .to_string();
+    let table = json_to_table(&value).set_style(Style::modern()).to_string();
 
     assert_eq!(
         table,
         concat!(
-            "┌──────┬────────────────────────────────────────────────────────────────┐\n",
-            "│ menu │ ┌──────────────┬─────────────────────────────────────────────┐ │\n",
-            "│      │ │ header       │ items                                       │ │\n",
-            "│      │ ├──────────────┼─────────────────────────────────────────────┤ │\n",
-            "│      │ │  SVG Viewer  │ ┌─────────────────────────────────────────┐ │ │\n",
-            "│      │ │              │ │ ┌────────┐                              │ │ │\n",
-            "│      │ │              │ │ │ id     │                              │ │ │\n",
-            "│      │ │              │ │ ├────────┤                              │ │ │\n",
-            "│      │ │              │ │ │  Open  │                              │ │ │\n",
-            "│      │ │              │ │ └────────┘                              │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌───────┬────────────┐                  │ │ │\n",
-            "│      │ │              │ │ │ id    │  OpenNew   │                  │ │ │\n",
-            "│      │ │              │ │ ├───────┼────────────┤                  │ │ │\n",
-            "│      │ │              │ │ │ label │  Open New  │                  │ │ │\n",
-            "│      │ │              │ │ └───────┴────────────┘                  │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │                                         │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌──────────┬───────────┐                │ │ │\n",
-            "│      │ │              │ │ │ id       │ label     │                │ │ │\n",
-            "│      │ │              │ │ ├──────────┼───────────┤                │ │ │\n",
-            "│      │ │              │ │ │  ZoomIn  │  Zoom In  │                │ │ │\n",
-            "│      │ │              │ │ └──────────┴───────────┘                │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌───────┬────────────┐                  │ │ │\n",
-            "│      │ │              │ │ │ id    │  ZoomOut   │                  │ │ │\n",
-            "│      │ │              │ │ ├───────┼────────────┤                  │ │ │\n",
-            "│      │ │              │ │ │ label │  Zoom Out  │                  │ │ │\n",
-            "│      │ │              │ │ └───────┴────────────┘                  │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌────────────────┬─────────────────┐    │ │ │\n",
-            "│      │ │              │ │ │ id             │ label           │    │ │ │\n",
-            "│      │ │              │ │ ├────────────────┼─────────────────┤    │ │ │\n",
-            "│      │ │              │ │ │  OriginalView  │  Original View  │    │ │ │\n",
-            "│      │ │              │ │ └────────────────┴─────────────────┘    │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │                                         │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌────┬───────────┐                      │ │ │\n",
-            "│      │ │              │ │ │ id │  Quality  │                      │ │ │\n",
-            "│      │ │              │ │ └────┴───────────┘                      │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌─────────┐                             │ │ │\n",
-            "│      │ │              │ │ │ id      │                             │ │ │\n",
-            "│      │ │              │ │ ├─────────┤                             │ │ │\n",
-            "│      │ │              │ │ │  Pause  │                             │ │ │\n",
-            "│      │ │              │ │ └─────────┘                             │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌────┬────────┐                         │ │ │\n",
-            "│      │ │              │ │ │ id │  Mute  │                         │ │ │\n",
-            "│      │ │              │ │ └────┴────────┘                         │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │                                         │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌────────┬───────────┐                  │ │ │\n",
-            "│      │ │              │ │ │ id     │ label     │                  │ │ │\n",
-            "│      │ │              │ │ ├────────┼───────────┤                  │ │ │\n",
-            "│      │ │              │ │ │  Find  │  Find...  │                  │ │ │\n",
-            "│      │ │              │ │ └────────┴───────────┘                  │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌───────┬──────────────┐                │ │ │\n",
-            "│      │ │              │ │ │ id    │  FindAgain   │                │ │ │\n",
-            "│      │ │              │ │ ├───────┼──────────────┤                │ │ │\n",
-            "│      │ │              │ │ │ label │  Find Again  │                │ │ │\n",
-            "│      │ │              │ │ └───────┴──────────────┘                │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌────────┐                              │ │ │\n",
-            "│      │ │              │ │ │ id     │                              │ │ │\n",
-            "│      │ │              │ │ ├────────┤                              │ │ │\n",
-            "│      │ │              │ │ │  Copy  │                              │ │ │\n",
-            "│      │ │              │ │ └────────┘                              │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌───────┬──────────────┐                │ │ │\n",
-            "│      │ │              │ │ │ id    │  CopyAgain   │                │ │ │\n",
-            "│      │ │              │ │ ├───────┼──────────────┤                │ │ │\n",
-            "│      │ │              │ │ │ label │  Copy Again  │                │ │ │\n",
-            "│      │ │              │ │ └───────┴──────────────┘                │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌───────────┬────────────┐              │ │ │\n",
-            "│      │ │              │ │ │ id        │ label      │              │ │ │\n",
-            "│      │ │              │ │ ├───────────┼────────────┤              │ │ │\n",
-            "│      │ │              │ │ │  CopySVG  │  Copy SVG  │              │ │ │\n",
-            "│      │ │              │ │ └───────────┴────────────┘              │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌───────┬────────────┐                  │ │ │\n",
-            "│      │ │              │ │ │ id    │  ViewSVG   │                  │ │ │\n",
-            "│      │ │              │ │ ├───────┼────────────┤                  │ │ │\n",
-            "│      │ │              │ │ │ label │  View SVG  │                  │ │ │\n",
-            "│      │ │              │ │ └───────┴────────────┘                  │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌──────────────┬───────────────┐        │ │ │\n",
-            "│      │ │              │ │ │ id           │ label         │        │ │ │\n",
-            "│      │ │              │ │ ├──────────────┼───────────────┤        │ │ │\n",
-            "│      │ │              │ │ │  ViewSource  │  View Source  │        │ │ │\n",
-            "│      │ │              │ │ └──────────────┴───────────────┘        │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌───────┬───────────┐                   │ │ │\n",
-            "│      │ │              │ │ │ id    │  SaveAs   │                   │ │ │\n",
-            "│      │ │              │ │ ├───────┼───────────┤                   │ │ │\n",
-            "│      │ │              │ │ │ label │  Save As  │                   │ │ │\n",
-            "│      │ │              │ │ └───────┴───────────┘                   │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │                                         │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌────────┐                              │ │ │\n",
-            "│      │ │              │ │ │ id     │                              │ │ │\n",
-            "│      │ │              │ │ ├────────┤                              │ │ │\n",
-            "│      │ │              │ │ │  Help  │                              │ │ │\n",
-            "│      │ │              │ │ └────────┘                              │ │ │\n",
-            "│      │ │              │ ├─────────────────────────────────────────┤ │ │\n",
-            "│      │ │              │ │ ┌───────┬─────────────────────────────┐ │ │ │\n",
-            "│      │ │              │ │ │ id    │  About                      │ │ │ │\n",
-            "│      │ │              │ │ ├───────┼─────────────────────────────┤ │ │ │\n",
-            "│      │ │              │ │ │ label │  About Adobe CVG Viewer...  │ │ │ │\n",
-            "│      │ │              │ │ └───────┴─────────────────────────────┘ │ │ │\n",
-            "│      │ │              │ └─────────────────────────────────────────┘ │ │\n",
-            "│      │ └──────────────┴─────────────────────────────────────────────┘ │\n",
-            "└──────┴────────────────────────────────────────────────────────────────┘",
+            "┌──────┬──────────────────────────────────────────────────────────┐\n",
+            "│ menu │ ┌────────┬─────────────────────────────────────────────┐ │\n",
+            "│      │ │ header │  SVG Viewer                                 │ │\n",
+            "│      │ ├────────┼─────────────────────────────────────────────┤ │\n",
+            "│      │ │ items  │ ┌─────────────────────────────────────────┐ │ │\n",
+            "│      │ │        │ │ ┌────┬────────┐                         │ │ │\n",
+            "│      │ │        │ │ │ id │  Open  │                         │ │ │\n",
+            "│      │ │        │ │ └────┴────────┘                         │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌───────┬────────────┐                  │ │ │\n",
+            "│      │ │        │ │ │ id    │  OpenNew   │                  │ │ │\n",
+            "│      │ │        │ │ ├───────┼────────────┤                  │ │ │\n",
+            "│      │ │        │ │ │ label │  Open New  │                  │ │ │\n",
+            "│      │ │        │ │ └───────┴────────────┘                  │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │                                         │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌───────┬───────────┐                   │ │ │\n",
+            "│      │ │        │ │ │ id    │  ZoomIn   │                   │ │ │\n",
+            "│      │ │        │ │ ├───────┼───────────┤                   │ │ │\n",
+            "│      │ │        │ │ │ label │  Zoom In  │                   │ │ │\n",
+            "│      │ │        │ │ └───────┴───────────┘                   │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌───────┬────────────┐                  │ │ │\n",
+            "│      │ │        │ │ │ id    │  ZoomOut   │                  │ │ │\n",
+            "│      │ │        │ │ ├───────┼────────────┤                  │ │ │\n",
+            "│      │ │        │ │ │ label │  Zoom Out  │                  │ │ │\n",
+            "│      │ │        │ │ └───────┴────────────┘                  │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌───────┬─────────────────┐             │ │ │\n",
+            "│      │ │        │ │ │ id    │  OriginalView   │             │ │ │\n",
+            "│      │ │        │ │ ├───────┼─────────────────┤             │ │ │\n",
+            "│      │ │        │ │ │ label │  Original View  │             │ │ │\n",
+            "│      │ │        │ │ └───────┴─────────────────┘             │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │                                         │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌────┬───────────┐                      │ │ │\n",
+            "│      │ │        │ │ │ id │  Quality  │                      │ │ │\n",
+            "│      │ │        │ │ └────┴───────────┘                      │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌────┬─────────┐                        │ │ │\n",
+            "│      │ │        │ │ │ id │  Pause  │                        │ │ │\n",
+            "│      │ │        │ │ └────┴─────────┘                        │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌────┬────────┐                         │ │ │\n",
+            "│      │ │        │ │ │ id │  Mute  │                         │ │ │\n",
+            "│      │ │        │ │ └────┴────────┘                         │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │                                         │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌───────┬───────────┐                   │ │ │\n",
+            "│      │ │        │ │ │ id    │  Find     │                   │ │ │\n",
+            "│      │ │        │ │ ├───────┼───────────┤                   │ │ │\n",
+            "│      │ │        │ │ │ label │  Find...  │                   │ │ │\n",
+            "│      │ │        │ │ └───────┴───────────┘                   │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌───────┬──────────────┐                │ │ │\n",
+            "│      │ │        │ │ │ id    │  FindAgain   │                │ │ │\n",
+            "│      │ │        │ │ ├───────┼──────────────┤                │ │ │\n",
+            "│      │ │        │ │ │ label │  Find Again  │                │ │ │\n",
+            "│      │ │        │ │ └───────┴──────────────┘                │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌────┬────────┐                         │ │ │\n",
+            "│      │ │        │ │ │ id │  Copy  │                         │ │ │\n",
+            "│      │ │        │ │ └────┴────────┘                         │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌───────┬──────────────┐                │ │ │\n",
+            "│      │ │        │ │ │ id    │  CopyAgain   │                │ │ │\n",
+            "│      │ │        │ │ ├───────┼──────────────┤                │ │ │\n",
+            "│      │ │        │ │ │ label │  Copy Again  │                │ │ │\n",
+            "│      │ │        │ │ └───────┴──────────────┘                │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌───────┬────────────┐                  │ │ │\n",
+            "│      │ │        │ │ │ id    │  CopySVG   │                  │ │ │\n",
+            "│      │ │        │ │ ├───────┼────────────┤                  │ │ │\n",
+            "│      │ │        │ │ │ label │  Copy SVG  │                  │ │ │\n",
+            "│      │ │        │ │ └───────┴────────────┘                  │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌───────┬────────────┐                  │ │ │\n",
+            "│      │ │        │ │ │ id    │  ViewSVG   │                  │ │ │\n",
+            "│      │ │        │ │ ├───────┼────────────┤                  │ │ │\n",
+            "│      │ │        │ │ │ label │  View SVG  │                  │ │ │\n",
+            "│      │ │        │ │ └───────┴────────────┘                  │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌───────┬───────────────┐               │ │ │\n",
+            "│      │ │        │ │ │ id    │  ViewSource   │               │ │ │\n",
+            "│      │ │        │ │ ├───────┼───────────────┤               │ │ │\n",
+            "│      │ │        │ │ │ label │  View Source  │               │ │ │\n",
+            "│      │ │        │ │ └───────┴───────────────┘               │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌───────┬───────────┐                   │ │ │\n",
+            "│      │ │        │ │ │ id    │  SaveAs   │                   │ │ │\n",
+            "│      │ │        │ │ ├───────┼───────────┤                   │ │ │\n",
+            "│      │ │        │ │ │ label │  Save As  │                   │ │ │\n",
+            "│      │ │        │ │ └───────┴───────────┘                   │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │                                         │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌────┬────────┐                         │ │ │\n",
+            "│      │ │        │ │ │ id │  Help  │                         │ │ │\n",
+            "│      │ │        │ │ └────┴────────┘                         │ │ │\n",
+            "│      │ │        │ ├─────────────────────────────────────────┤ │ │\n",
+            "│      │ │        │ │ ┌───────┬─────────────────────────────┐ │ │ │\n",
+            "│      │ │        │ │ │ id    │  About                      │ │ │ │\n",
+            "│      │ │        │ │ ├───────┼─────────────────────────────┤ │ │ │\n",
+            "│      │ │        │ │ │ label │  About Adobe CVG Viewer...  │ │ │ │\n",
+            "│      │ │        │ │ └───────┴─────────────────────────────┘ │ │ │\n",
+            "│      │ │        │ └─────────────────────────────────────────┘ │ │\n",
+            "│      │ └────────┴─────────────────────────────────────────────┘ │\n",
+            "└──────┴──────────────────────────────────────────────────────────┘",
         )
     );
 }
+
+// #[test]
+// fn orientation_collapse_test_1() {
+//     let value = json!(
+//         {"widget": {
+//             "debug": "on",
+//             "text": {
+//                 "data": ["Click Here", "asda", "123132"],
+//                 "size": 36,
+//                 "style": "bold",
+//                 "name": "text1",
+//                 "hOffset": 250,
+//                 "vOffset": 100,
+//                 "alignment": "center",
+//                 "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
+//             }
+//         }}
+//     );
+
+//     let table = json_to_table(&value)
+//         .set_style(Style::extended())
+//         .collapse()
+//         .set_object_mode(Orientation::Vertical)
+//         .to_string();
+
+//     println!("{table}");
+
+//     assert_eq!(
+//         table,
+//         concat!(
+//             "╔══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗\n",
+//             "║ widget                                                                                                                                                                                                                                                                   ║\n",
+//             "╠══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣\n",
+//             "║ ╔═══════╦═══════════════════════════════════════════════════════════════╦══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╦═══════════════════════════════════════════════════════════════════╗ ║\n",
+//             "║ ║ debug ║ image                                                         ║ text                                                                                                                     ║ window                                                            ║ ║\n",
+//             "║ ╠═══════╬═══════════════════════════════════════════════════════════════╬══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╬═══════════════════════════════════════════════════════════════════╣ ║\n",
+//             "║ ║  on   ║ ╔═══════════╦═════════╦════════╦══════════════════╦═════════╗ ║ ╔═══════════╦══════════════╦═════════╦═════════╦═════════════════════════════════════════════╦══════╦════════╦═════════╗ ║ ╔════════╦═══════════════╦══════════════════════════════╦═══════╗ ║ ║\n",
+//             "║ ║       ║ ║ alignment ║ hOffset ║ name   ║ src              ║ vOffset ║ ║ ║ alignment ║ data         ║ hOffset ║ name    ║ onMouseUp                                   ║ size ║ style  ║ vOffset ║ ║ ║ height ║ name          ║ title                        ║ width ║ ║ ║\n",
+//             "║ ║       ║ ╠═══════════╬═════════╬════════╬══════════════════╬═════════╣ ║ ╠═══════════╬══════════════╬═════════╬═════════╬═════════════════════════════════════════════╬══════╬════════╬═════════╣ ║ ╠════════╬═══════════════╬══════════════════════════════╬═══════╣ ║ ║\n",
+//             "║ ║       ║ ║  center   ║  250    ║  sun1  ║  Images/Sun.png  ║  250    ║ ║ ║  center   ║  Click Here  ║  250    ║  text1  ║  sun1.opacity = (sun1.opacity / 100) * 90;  ║  36  ║  bold  ║  100    ║ ║ ║  500   ║  main_window  ║  Sample Konfabulator Widget  ║  500  ║ ║ ║\n",
+//             "║ ║       ║ ╚═══════════╩═════════╩════════╩══════════════════╩═════════╝ ║ ╚═══════════╩══════════════╩═════════╩═════════╩═════════════════════════════════════════════╩══════╩════════╩═════════╝ ║ ╚════════╩═══════════════╩══════════════════════════════╩═══════╝ ║ ║\n",
+//             "║ ╚═══════╩═══════════════════════════════════════════════════════════════╩══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╩═══════════════════════════════════════════════════════════════════╝ ║\n",
+//             "╚══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝",
+//         )
+//     );
+// }
diff --git a/tabled/tests/compact_table.rs b/tabled/tests/compact_table.rs
index dc6f01b..ffc973f 100644
--- a/tabled/tests/compact_table.rs
+++ b/tabled/tests/compact_table.rs
@@ -3,7 +3,10 @@
 mod util;
 
 use tabled::{
-    grid::{dimension::CompactGridDimension, dimension::Estimate, records::IterRecords},
+    grid::{
+        config::CompactConfig, dimension::CompactGridDimension, dimension::Estimate,
+        records::IterRecords,
+    },
     tables::CompactTable,
 };
 use util::{create_matrix, test_table};
@@ -19,7 +22,7 @@ test_table!(
     {
         let data = create_matrix::<3, 3>();
         let mut dims = CompactGridDimension::default();
-        dims.estimate(IterRecords::new(&data, 3, None), &CompactTable::config());
+        dims.estimate(IterRecords::new(&data, 3, None), &CompactConfig::default());
         CompactTable::with_dimension(data, dims).columns(3).to_string()
     },
     "+-----+-----+-----+"