1use std::{fmt, io};
2use std::cell::RefCell;
3use std::rc::Rc;
4
5use crate::column::{TPrintColumn, TPrintAlign};
6use crate::output::{TPrintOutput, TPrintOutputStdout};
7use crate::borders::{TPrintBorders, TPrintBordersASCII, TPrintBordersType};
8use crate::utils::get_string_width;
9
10type TPrintOutputRef = Rc<RefCell<dyn TPrintOutput>>;
11type TPrintBordersRef = Rc<RefCell<dyn TPrintBorders>>;
12
13pub struct TPrint {
15 output: TPrintOutputRef,
16 borders: TPrintBordersRef,
17 show_borders: bool,
18 show_headers: bool,
19 spaces_left: usize,
20 spaces_between: usize,
21 columns: Vec<TPrintColumn>,
22 current_column_id: usize,
23}
24
25impl TPrint {
26 pub fn new(show_borders: bool, show_headers: bool, spaces_left: usize, extra_spaces_between: usize) -> Self {
28 TPrint {
29 output: Rc::new(RefCell::new(TPrintOutputStdout {})),
30 borders: Rc::new(RefCell::new(TPrintBordersASCII {})),
31 show_borders,
32 show_headers,
33 spaces_left,
34 spaces_between: extra_spaces_between,
35 columns: Vec::new(),
36 current_column_id: 0,
37 }
38 }
39 pub fn new_with_output(output: TPrintOutputRef, show_borders: bool, show_headers: bool, spaces_left: usize, extra_spaces_between: usize) -> Self {
41 TPrint {
42 output,
43 borders: Rc::new(RefCell::new(TPrintBordersASCII {})),
44 show_borders,
45 show_headers,
46 spaces_left,
47 spaces_between: extra_spaces_between,
48 columns: Vec::new(),
49 current_column_id: 0,
50 }
51 }
52
53 pub fn new_with_borders(borders: TPrintBordersRef, show_borders: bool, show_headers: bool, spaces_left: usize, extra_spaces_between: usize) -> Self {
55 TPrint {
56 output: Rc::new(RefCell::new(TPrintOutputStdout {})),
57 borders,
58 show_borders,
59 show_headers,
60 spaces_left,
61 spaces_between: extra_spaces_between,
62 columns: Vec::new(),
63 current_column_id: 0,
64 }
65 }
66
67 pub fn new_with_borders_output(borders: TPrintBordersRef, output: TPrintOutputRef, show_borders: bool, show_headers: bool, spaces_left: usize, extra_spaces_between: usize) -> Self {
69 TPrint {
70 output,
71 borders,
72 show_borders,
73 show_headers,
74 spaces_left,
75 spaces_between: extra_spaces_between,
76 columns: Vec::new(),
77 current_column_id: 0,
78 }
79 }
80
81 pub fn column_add(&mut self, caption: &str, caption_align: TPrintAlign, cell_align: TPrintAlign) -> &mut Self {
84 self.columns.push(TPrintColumn::new(caption, caption_align, cell_align));
85 self
86 }
87
88 pub fn add_data<T: fmt::Display>(&mut self, value: T) -> &mut Self {
113 let column_id = self.current_column_id;
114 if let Some(column) = self.columns.get_mut(column_id) {
115 column.add_data(value);
116
117 if self.current_column_id + 1 >= self.columns.len() {
118 self.current_column_id = 0;
119 } else {
120 self.current_column_id += 1;
121 }
122 }
123 self
124 }
125
126 fn print_horizonal_border(&self, left: &TPrintBordersType, right: &TPrintBordersType, middle: &TPrintBordersType, line: &TPrintBordersType) -> io::Result<()> {
127 if !self.show_borders {
128 self.output.borrow_mut().print_str(self.borders.borrow().get_border(&TPrintBordersType::NewLine))?;
129 return Ok(());
130 }
131
132 if self.spaces_left > 0 {
133 self.output.borrow_mut().print_str(&self.borders.borrow().get_border(&TPrintBordersType::WhiteSpace).repeat(self.spaces_left))?;
134 }
135
136 self.output.borrow_mut().print_str(self.borders.borrow().get_border(left))?;
137
138 for i in 0..self.columns.len() {
139 let c = &self.columns[i];
140
141 self.output.borrow_mut().print_str(&self.borders.borrow().get_border(line).repeat(c.get_max_width() + 2 * self.spaces_between))?;
142
143 if i < self.columns.len() - 1 {
144 self.output.borrow_mut().print_str(self.borders.borrow().get_border(middle))?;
145 }
146 }
147
148 self.output.borrow_mut().print_str(self.borders.borrow().get_border(right))?;
149 self.output.borrow_mut().print_str(self.borders.borrow().get_border(&TPrintBordersType::NewLine))?;
150
151 Ok(())
152 }
153
154 fn print_left_border(&self, left_border: &TPrintBordersType) -> io::Result<()> {
155 if !self.show_borders {
156 return Ok(());
157 }
158 self.output.borrow_mut().print_str(self.borders.borrow().get_border(left_border))?;
159 Ok(())
160 }
161
162 fn print_right_border(&self, right_border: &TPrintBordersType) -> io::Result<()> {
163 if !self.show_borders {
164 return Ok(());
165 }
166 self.output.borrow_mut().print_str(self.borders.borrow().get_border(right_border))?;
167 self.output.borrow_mut().print_str(self.borders.borrow().get_border(&TPrintBordersType::NewLine))?;
168 Ok(())
169 }
170
171 fn print_internal_border(&self, v_border: &TPrintBordersType) -> io::Result<()> {
172 if !self.show_borders {
173 return Ok(());
174 }
175 self.output.borrow_mut().print_str(self.borders.borrow().get_border(v_border))?;
176 Ok(())
177 }
178
179 fn print_cell(&self, value: &str, max_width: usize, align: &TPrintAlign, whitespace: &str) -> io::Result<()> {
180 let left_spaces;
181 let right_spaces;
182
183 let value_len = get_string_width(value);
184
185 match align {
186 TPrintAlign::Left => {
187 left_spaces = self.spaces_between;
188 right_spaces = (self.spaces_between * 2 + max_width) - (left_spaces + value_len);
189 }
190 TPrintAlign::Center => {
191 left_spaces = self.spaces_between + (max_width - value_len) / 2;
192 right_spaces = (self.spaces_between * 2 + max_width) - (left_spaces + value_len);
193 }
194 TPrintAlign::Right => {
195 right_spaces = self.spaces_between;
196 left_spaces = (self.spaces_between * 2 + max_width) - (right_spaces + value_len);
197 }
198 }
199
200 self.output.borrow_mut().print_str(&whitespace.repeat(left_spaces))?;
201 self.output.borrow_mut().print_str(value)?;
202 self.output.borrow_mut().print_str(&whitespace.repeat(right_spaces))?;
203 Ok(())
204 }
205
206 pub fn print(&self) -> io::Result<()> {
208 let total_rows: usize = self.columns.iter().map(|c| c.get_rows_count()).max().unwrap_or(0);
209
210 let border = self.borders.borrow();
211 let whitespace = border.get_border(&TPrintBordersType::WhiteSpace);
212
213 self.output.borrow_mut().print_str(border.get_intro(self.show_borders, self.show_headers))?;
214
215 if self.show_headers {
216 self.print_horizonal_border(&TPrintBordersType::HeaderTopLeft, &TPrintBordersType::HeaderTopRight, &TPrintBordersType::HeaderTopMiddle, &TPrintBordersType::HeaderHLine)?;
217
218 if self.spaces_left > 0 {
219 self.output.borrow_mut().print_str(&whitespace.repeat(self.spaces_left))?;
220 }
221
222 self.print_left_border(&TPrintBordersType::HeaderLeftVLine)?;
223
224 for cid in 0..self.columns.len() {
225 let c = &self.columns[cid];
226
227 if cid > 0 {
228 self.print_internal_border(&TPrintBordersType::HeaderMiddleVLine)?;
229 }
230
231 self.print_cell(c.get_caption(), c.get_max_width(), c.get_caption_align(), whitespace)?;
232 }
233
234 self.print_right_border(&TPrintBordersType::HeaderRightVLine)?;
235
236 self.print_horizonal_border(&TPrintBordersType::HeaderBottomLeft, &TPrintBordersType::HeaderBottomRight, &TPrintBordersType::HeaderBottomMiddle, &TPrintBordersType::HeaderHLine)?;
237
238 } else {
239 self.print_horizonal_border(&TPrintBordersType::TopLeft, &TPrintBordersType::TopRight, &TPrintBordersType::TopMiddle, &TPrintBordersType::TopHLine)?;
240 }
241
242 for r in 0..total_rows {
243 if self.spaces_left > 0 {
244 self.output.borrow_mut().print_str(&whitespace.repeat(self.spaces_left))?;
245 }
246
247 self.print_left_border(&TPrintBordersType::MiddleLeftVLine)?;
248
249 for cid in 0..self.columns.len() {
250 let c = &self.columns[cid];
251 if cid > 0 {
252 self.print_internal_border(&TPrintBordersType::MiddleMiddleVLine)?;
253 }
254
255 self.print_cell(c.get_str(r), c.get_max_width(), c.get_cell_align(), whitespace)?;
256 }
257 self.print_right_border(&TPrintBordersType::MiddleRightVLine)?;
258
259 if r < total_rows - 1 {
260 self.print_horizonal_border(&TPrintBordersType::MiddleLeft, &TPrintBordersType::MiddleRight, &TPrintBordersType::MiddleMiddle, &TPrintBordersType::MiddleHLine)?;
261 }
262 }
263
264 self.print_horizonal_border(&TPrintBordersType::BottomLeft, &TPrintBordersType::BottomRight, &TPrintBordersType::BottomMiddle, &TPrintBordersType::BottomHLine)?;
265
266 self.output.borrow_mut().print_str(border.get_closing())
267 }
268}