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