tabled/settings/padding_expand/
mod.rs1use papergrid::{
4 config::{AlignmentHorizontal, AlignmentVertical},
5 dimension::iterable::IterGridDimension,
6 records::{ExactRecords, IntoRecords, PeekableRecords, Records},
7};
8
9#[cfg(feature = "std")]
10use crate::{
11 grid::{config::ColoredConfig, config::Entity},
12 settings::CellOption,
13};
14
15use super::TableOption;
16
17#[cfg_attr(feature = "ansi", doc = "```")]
23#[cfg_attr(not(feature = "ansi"), doc = "```ignore")]
24#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
69pub enum PaddingExpand {
70 Horizontal,
72 Vertical,
74}
75
76impl<R, D> TableOption<R, ColoredConfig, D> for PaddingExpand
77where
78 R: Records + ExactRecords + PeekableRecords,
79 for<'a> &'a R: Records,
80 for<'a> <<&'a R as Records>::Iter as IntoRecords>::Cell: AsRef<str>,
81{
82 fn change(self, records: &mut R, cfg: &mut ColoredConfig, _: &mut D) {
83 <Self as CellOption<R, ColoredConfig>>::change(self, records, cfg, Entity::Global)
84 }
85}
86
87impl<R> CellOption<R, ColoredConfig> for PaddingExpand
88where
89 R: Records + ExactRecords + PeekableRecords,
90 for<'a> &'a R: Records,
91 for<'a> <<&'a R as Records>::Iter as IntoRecords>::Cell: AsRef<str>,
92{
93 fn change(self, records: &mut R, cfg: &mut ColoredConfig, entity: Entity) {
94 match self {
95 PaddingExpand::Vertical => expand_vertical(records, cfg, entity),
96 PaddingExpand::Horizontal => expand_horizontal(records, cfg, entity),
97 }
98 }
99}
100
101fn expand_horizontal<R>(records: &mut R, cfg: &mut ColoredConfig, entity: Entity)
102where
103 R: Records + ExactRecords + PeekableRecords,
104 for<'a> &'a R: Records,
105 for<'a> <<&'a R as Records>::Iter as IntoRecords>::Cell: AsRef<str>,
106{
107 let widths = IterGridDimension::width(&*records, cfg);
108
109 let count_rows = records.count_rows();
110 let count_cols = records.count_columns();
111
112 for pos in entity.iter(count_rows, count_cols) {
113 let col = pos.col;
114 let column_width = widths[col];
115 let width = records.get_width(pos);
116
117 if width < column_width {
118 let alignment = *cfg.get_alignment_horizontal(pos);
119
120 let available_width = column_width - width;
121 let (left, right) = split_horizontal_space(alignment, available_width);
122
123 let mut pad = *cfg.get_padding(pos);
124 pad.left.size = left;
125 pad.right.size = right;
126
127 cfg.set_padding(Entity::from(pos), pad);
128 }
129 }
130}
131
132fn expand_vertical<R>(records: &mut R, cfg: &mut ColoredConfig, entity: Entity)
133where
134 R: Records + ExactRecords + PeekableRecords,
135 for<'a> &'a R: Records,
136 for<'a> <<&'a R as Records>::Iter as IntoRecords>::Cell: AsRef<str>,
137{
138 let heights = IterGridDimension::height(&*records, cfg);
139
140 let count_rows = records.count_rows();
141 let count_cols = records.count_columns();
142
143 for pos in entity.iter(count_rows, count_cols) {
144 let row = pos.row;
145 let row_height = heights[row];
146 let cell_height = records.count_lines(pos);
147
148 if cell_height < row_height {
149 let alignment = *cfg.get_alignment_vertical(pos);
150
151 let available_width = row_height - cell_height;
152 let (top, bottom) = split_vertical_space(alignment, available_width);
153
154 let mut pad = *cfg.get_padding(pos);
155 pad.top.size = top;
156 pad.bottom.size = bottom;
157
158 cfg.set_padding(Entity::from(pos), pad);
159 }
160 }
161}
162
163fn split_horizontal_space(al: AlignmentHorizontal, space: usize) -> (usize, usize) {
164 match al {
165 AlignmentHorizontal::Center => {
166 let left = space / 2;
167 let right = space - left;
168 (left, right)
169 }
170 AlignmentHorizontal::Left => (0, space),
171 AlignmentHorizontal::Right => (space, 0),
172 }
173}
174
175fn split_vertical_space(al: AlignmentVertical, space: usize) -> (usize, usize) {
176 match al {
177 AlignmentVertical::Center => {
178 let left = space / 2;
179 let right = space - left;
180 (left, right)
181 }
182 AlignmentVertical::Top => (0, space),
183 AlignmentVertical::Bottom => (space, 0),
184 }
185}