tabled/features/style/
border.rs

1use papergrid::{records::Records, Entity};
2
3use crate::{CellOption, Table};
4
5/// Border represents a border of a Cell.
6///
7/// ```rust,no_run
8/// # use tabled::{Style, Border, object::Rows, Table, Modify};
9/// # let data: Vec<&'static str> = Vec::new();
10/// let table = Table::new(&data)
11///     .with(Style::ascii())
12///     .with(Modify::new(Rows::single(0)).with(Border::default().top('x')));
13/// ```
14#[derive(Debug, Clone, Default, Eq, PartialEq)]
15pub struct Border {
16    border: Option<papergrid::Border<char>>,
17}
18
19impl Border {
20    pub(crate) const fn new_raw(border: Option<papergrid::Border<char>>) -> Self {
21        Self { border }
22    }
23}
24
25impl Border {
26    /// This function constructs a cell borders with all sides set.
27    #[allow(clippy::too_many_arguments)]
28    pub fn full(
29        top: char,
30        bottom: char,
31        left: char,
32        right: char,
33        top_left: char,
34        top_right: char,
35        bottom_left: char,
36        bottom_right: char,
37    ) -> Self {
38        Self::from(papergrid::Border::full(
39            top,
40            bottom,
41            left,
42            right,
43            top_left,
44            top_right,
45            bottom_left,
46            bottom_right,
47        ))
48    }
49
50    /// Using this function you deconstruct the existing borders.
51    pub fn empty() -> Self {
52        Self { border: None }
53    }
54
55    /// This function constructs a cell borders with all sides's char set to a given character.
56    /// It behaives like [`Border::full`] with the same character set to each side.
57    pub fn filled(c: char) -> Self {
58        Self::full(c, c, c, c, c, c, c, c)
59    }
60
61    /// Set a top border character.
62    pub fn top(self, c: char) -> Self {
63        let mut b = self.border.unwrap_or_default();
64        b.top = Some(c);
65        Self::from(b)
66    }
67
68    /// Set a bottom border character.
69    pub fn bottom(self, c: char) -> Self {
70        let mut b = self.border.unwrap_or_default();
71        b.bottom = Some(c);
72        Self::from(b)
73    }
74
75    /// Set a left border character.
76    pub fn left(self, c: char) -> Self {
77        let mut b = self.border.unwrap_or_default();
78        b.left = Some(c);
79        Self::from(b)
80    }
81
82    /// Set a right border character.
83    pub fn right(self, c: char) -> Self {
84        let mut b = self.border.unwrap_or_default();
85        b.right = Some(c);
86        Self::from(b)
87    }
88
89    /// Set a top left intersection character.
90    pub fn top_left_corner(self, c: char) -> Self {
91        let mut b = self.border.unwrap_or_default();
92        b.left_top_corner = Some(c);
93        Self::from(b)
94    }
95
96    /// Set a top right intersection character.
97    pub fn top_right_corner(self, c: char) -> Self {
98        let mut b = self.border.unwrap_or_default();
99        b.right_top_corner = Some(c);
100        Self::from(b)
101    }
102
103    /// Set a bottom left intersection character.
104    pub fn bottom_left_corner(self, c: char) -> Self {
105        let mut b = self.border.unwrap_or_default();
106        b.left_bottom_corner = Some(c);
107        Self::from(b)
108    }
109
110    /// Set a bottom right intersection character.
111    pub fn bottom_right_corner(self, c: char) -> Self {
112        let mut b = self.border.unwrap_or_default();
113        b.right_bottom_corner = Some(c);
114        Self::from(b)
115    }
116}
117
118impl<R> CellOption<R> for Border
119where
120    R: Records,
121{
122    fn change_cell(&mut self, table: &mut Table<R>, entity: Entity) {
123        let (count_rows, count_cols) = table.shape();
124        let cfg = table.get_config_mut();
125        for pos in entity.iter(count_rows, count_cols) {
126            match &self.border {
127                Some(border) => cfg.set_border(pos, border.clone()),
128                None => cfg.remove_border(pos, (count_rows, count_cols)),
129            }
130        }
131
132        table.destroy_width_cache();
133        table.destroy_height_cache();
134    }
135}
136
137impl From<papergrid::Border> for Border {
138    fn from(b: papergrid::Border) -> Border {
139        Border { border: Some(b) }
140    }
141}
142
143impl From<Border> for Option<papergrid::Border> {
144    fn from(val: Border) -> Self {
145        val.border
146    }
147}