papergrid/dimension/
compact.rs1use core::cmp::max;
6
7use crate::{
8 config::compact::CompactConfig,
9 dimension::{Dimension, Estimate},
10 records::{IntoRecords, Records},
11 util::string::{count_lines, get_text_width},
12};
13
14#[derive(Debug, Default, Clone, PartialEq, Eq)]
18pub struct CompactGridDimension {
19 width: Vec<usize>,
20}
21
22impl CompactGridDimension {
23 pub fn height<R>(records: R, cfg: &CompactConfig) -> Vec<usize>
25 where
26 R: Records,
27 <R::Iter as IntoRecords>::Cell: AsRef<str>,
28 {
29 build_height(records, cfg)
30 }
31
32 pub fn width<R>(records: R, cfg: &CompactConfig) -> Vec<usize>
34 where
35 R: Records,
36 <R::Iter as IntoRecords>::Cell: AsRef<str>,
37 {
38 build_width(records, cfg)
39 }
40
41 pub fn dimension<R>(records: R, cfg: &CompactConfig) -> (Vec<usize>, Vec<usize>)
43 where
44 R: Records,
45 <R::Iter as IntoRecords>::Cell: AsRef<str>,
46 {
47 build_dimension(records, cfg)
48 }
49}
50
51impl Dimension for CompactGridDimension {
52 fn get_width(&self, column: usize) -> usize {
53 self.width[column]
54 }
55
56 fn get_height(&self, _: usize) -> usize {
57 1
58 }
59}
60
61impl<R> Estimate<R, CompactConfig> for CompactGridDimension
62where
63 R: Records,
64 <R::Iter as IntoRecords>::Cell: AsRef<str>,
65{
66 fn estimate(&mut self, records: R, cfg: &CompactConfig) {
67 self.width = build_width(records, cfg);
68 }
69}
70
71fn build_dimension<R>(records: R, cfg: &CompactConfig) -> (Vec<usize>, Vec<usize>)
72where
73 R: Records,
74 <R::Iter as IntoRecords>::Cell: AsRef<str>,
75{
76 let mut heights = vec![];
77 let mut widths = vec![0; records.count_columns()];
78
79 for columns in records.iter_rows() {
80 let mut row_height = 0;
81 for (col, cell) in columns.into_iter().enumerate() {
82 let height = get_cell_height(cell.as_ref(), cfg);
83 let width = get_cell_width(cell.as_ref(), cfg);
84 row_height = max(row_height, height);
85 widths[col] = max(widths[col], width)
86 }
87
88 heights.push(row_height);
89 }
90
91 (widths, heights)
92}
93
94fn build_height<R>(records: R, cfg: &CompactConfig) -> Vec<usize>
95where
96 R: Records,
97 <R::Iter as IntoRecords>::Cell: AsRef<str>,
98{
99 let mut heights = vec![];
100
101 for columns in records.iter_rows() {
102 let mut row_height = 0;
103 for cell in columns.into_iter() {
104 let height = get_cell_height(cell.as_ref(), cfg);
105 row_height = max(row_height, height);
106 }
107
108 heights.push(row_height);
109 }
110
111 heights
112}
113
114fn build_width<R>(records: R, cfg: &CompactConfig) -> Vec<usize>
115where
116 R: Records,
117 <R::Iter as IntoRecords>::Cell: AsRef<str>,
118{
119 let mut widths = vec![0; records.count_columns()];
120 for columns in records.iter_rows() {
121 for (col, cell) in columns.into_iter().enumerate() {
122 let width = get_cell_width(cell.as_ref(), cfg);
123 widths[col] = max(widths[col], width);
124 }
125 }
126
127 widths
128}
129
130fn get_cell_height(cell: &str, cfg: &CompactConfig) -> usize {
131 let count_lines = max(1, count_lines(cell));
132 let pad = cfg.get_padding();
133
134 count_lines + pad.top.size + pad.bottom.size
135}
136
137fn get_cell_width(text: &str, cfg: &CompactConfig) -> usize {
138 let width = get_text_width(text);
139 let pad = cfg.get_padding();
140
141 width + pad.left.size + pad.right.size
142}