1use crate::{
4 grid::{
5 config::{Border as GridBorder, ColoredConfig, Entity},
6 records::{ExactRecords, Records},
7 },
8 settings::{CellOption, Color, TableOption},
9};
10
11#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
37pub struct BorderColor {
38 inner: GridBorder<Color>,
39}
40
41impl BorderColor {
42 pub(crate) const fn from_border(inner: GridBorder<Color>) -> Self {
43 BorderColor { inner }
44 }
45
46 pub const fn new() -> Self {
48 Self::from_border(GridBorder::empty())
49 }
50
51 #[allow(clippy::too_many_arguments)]
53 pub const fn full(
54 top: Color,
55 bottom: Color,
56 left: Color,
57 right: Color,
58 top_left: Color,
59 top_right: Color,
60 bottom_left: Color,
61 bottom_right: Color,
62 ) -> Self {
63 Self::from_border(GridBorder::full(
64 top,
65 bottom,
66 left,
67 right,
68 top_left,
69 top_right,
70 bottom_left,
71 bottom_right,
72 ))
73 }
74
75 pub fn filled(c: Color) -> Self {
78 Self::full(
79 c.clone(),
80 c.clone(),
81 c.clone(),
82 c.clone(),
83 c.clone(),
84 c.clone(),
85 c.clone(),
86 c,
87 )
88 }
89
90 pub fn top(mut self, c: Color) -> Self {
92 self.inner.top = Some(c);
93 BorderColor::from_border(self.inner)
94 }
95
96 pub fn bottom(mut self, c: Color) -> Self {
98 self.inner.bottom = Some(c);
99 BorderColor::from_border(self.inner)
100 }
101
102 pub fn left(mut self, c: Color) -> Self {
104 self.inner.left = Some(c);
105 BorderColor::from_border(self.inner)
106 }
107
108 pub fn right(mut self, c: Color) -> Self {
110 self.inner.right = Some(c);
111 BorderColor::from_border(self.inner)
112 }
113
114 pub fn into_inner(self) -> GridBorder<Color> {
116 self.inner
117 }
118
119 pub fn corner_top_left(mut self, c: Color) -> Self {
121 self.inner.left_top_corner = Some(c);
122 self
123 }
124
125 pub fn corner_top_right(mut self, c: Color) -> Self {
127 self.inner.right_top_corner = Some(c);
128 self
129 }
130
131 pub fn corner_bottom_left(mut self, c: Color) -> Self {
133 self.inner.left_bottom_corner = Some(c);
134 self
135 }
136
137 pub fn corner_bottom_right(mut self, c: Color) -> Self {
139 self.inner.right_bottom_corner = Some(c);
140 self
141 }
142}
143
144impl From<BorderColor> for GridBorder<Color> {
145 fn from(value: BorderColor) -> Self {
146 value.inner
147 }
148}
149
150impl<Data> CellOption<Data, ColoredConfig> for BorderColor
151where
152 Data: Records + ExactRecords,
153{
154 fn change(self, records: &mut Data, cfg: &mut ColoredConfig, entity: Entity) {
155 let border = self.inner.clone().convert();
156 if matches!(entity, Entity::Global) && border.is_same() && !border.is_empty() {
157 let color = border.top.expect("ok");
158 cfg.set_border_color_default(color);
159 return;
160 }
161
162 let count_rows = records.count_rows();
163 let count_columns = records.count_columns();
164
165 for pos in entity.iter(count_rows, count_columns) {
166 cfg.set_border_color(pos, border.clone());
167 }
168 }
169}
170
171impl<Data, D> TableOption<Data, ColoredConfig, D> for BorderColor
172where
173 Data: Records + ExactRecords,
174{
175 fn change(self, records: &mut Data, cfg: &mut ColoredConfig, _: &mut D) {
176 let count_rows = records.count_rows();
177 let count_columns = records.count_columns();
178 let shape = (count_rows, count_columns);
179
180 if count_rows == 0 || count_columns == 0 {
181 return;
182 }
183
184 let color = self.inner.clone().convert();
185
186 for col in 0..count_columns {
187 let pos = (0, col).into();
188 let mut b = GridBorder::cloned(&cfg.get_border_color(pos, shape));
189 b.top = color.top.clone();
190 b.right_top_corner = color.top.clone();
191 cfg.set_border_color(pos, b);
192
193 let pos = (count_rows - 1, col).into();
194 let mut b = GridBorder::cloned(&cfg.get_border_color(pos, shape));
195 b.bottom = color.bottom.clone();
196 b.right_bottom_corner = color.bottom.clone();
197 cfg.set_border_color(pos, b);
198 }
199
200 for row in 0..count_rows {
201 let pos = (row, 0).into();
202 let mut b = GridBorder::cloned(&cfg.get_border_color(pos, shape));
203 b.left = color.left.clone();
204 b.left_bottom_corner = color.left.clone();
205 cfg.set_border_color(pos, b);
206
207 let pos = (row, count_columns - 1).into();
208 let mut b = GridBorder::cloned(&cfg.get_border_color(pos, shape));
209 b.right = color.right.clone();
210 b.right_bottom_corner = color.right.clone();
211 cfg.set_border_color(pos, b);
212 }
213
214 let pos = (0, 0).into();
215 let mut b = GridBorder::cloned(&cfg.get_border_color(pos, shape));
216 b.left_top_corner = color.left_top_corner.clone();
217 cfg.remove_border_color(pos, shape);
218 cfg.set_border_color(pos, b);
219
220 let pos = (0, count_columns - 1).into();
221 let mut b = GridBorder::cloned(&cfg.get_border_color(pos, shape));
222 b.right_top_corner = color.right_top_corner.clone();
223 cfg.remove_border_color(pos, shape);
224 cfg.set_border_color(pos, b);
225
226 let pos = (count_rows - 1, 0).into();
227 let mut b = GridBorder::cloned(&cfg.get_border_color(pos, shape));
228 b.left_bottom_corner = color.left_bottom_corner.clone();
229 cfg.remove_border_color(pos, shape);
230 cfg.set_border_color(pos, b);
231
232 let pos = (count_rows - 1, count_columns - 1).into();
233 let mut b = GridBorder::cloned(&cfg.get_border_color(pos, shape));
234 b.right_bottom_corner = color.right_bottom_corner.clone();
235 cfg.remove_border_color(pos, shape);
236 cfg.set_border_color(pos, b);
237 }
238}