1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
use super::helper::*;
use super::{ColumnDisplayInfo, DisplayInfos};
use crate::style::{ColumnConstraint, ColumnConstraint::*, Width};
use crate::{Column, Table};
/// Look at given constraints of a column and check if some of them can be resolved at the very
/// beginning.
///
/// For example:
/// - We get an absolute width.
/// - MinWidth constraints on columns, whose content is garantueed to be smaller than the specified
/// minimal width.
/// - The Column is supposed to be hidden.
pub fn evaluate(
table: &Table,
visible_columns: usize,
infos: &mut DisplayInfos,
column: &Column,
max_content_width: u16,
) {
match &column.constraint {
Some(ContentWidth) => {
let info = ColumnDisplayInfo::new(column, max_content_width);
infos.insert(column.index, info);
}
Some(Absolute(width)) => {
if let Some(width) = absolute_value_from_width(table, width, visible_columns) {
// The column should get always get a fixed width.
let width = absolute_width_with_padding(column, width);
let info = ColumnDisplayInfo::new(column, width);
infos.insert(column.index, info);
}
}
Some(Hidden) => {
let mut info = ColumnDisplayInfo::new(column, max_content_width);
info.is_hidden = true;
infos.insert(column.index, info);
}
_ => {}
}
if let Some(min_width) = min(table, &column.constraint, visible_columns) {
// In case a min_width is specified, we may already fix the size of the column.
// We do this, if we know that the content is smaller than the min size.
let max_width = max_content_width + column.padding_width();
if max_width <= min_width {
let width = absolute_width_with_padding(column, min_width);
let info = ColumnDisplayInfo::new(column, width);
infos.insert(column.index, info);
}
}
}
/// A little wrapper, which resolves possible lower boundary constraints to their actual value for
/// the current table and terminal width.
///
/// This returns the value of absolute characters that are allowed to be in this column. \
/// Lower boundaries with [Width::Fixed] just return their internal value. \
/// Lower boundaries with [Width::Percentage] return the percental amount of the current table
/// width.
pub fn min(
table: &Table,
constraint: &Option<ColumnConstraint>,
visible_columns: usize,
) -> Option<u16> {
let constraint = if let Some(constraint) = constraint {
constraint
} else {
return None;
};
match constraint {
LowerBoundary(width) | Boundaries { lower: width, .. } => {
absolute_value_from_width(table, width, visible_columns)
}
_ => None,
}
}
/// A little wrapper, which resolves possible upper boundary constraints to their actual value for
/// the current table and terminal width.
///
/// This returns the value of absolute characters that are allowed to be in this column. \
/// Upper boundaries with [Width::Fixed] just return their internal value. \
/// Upper boundaries with [Width::Percentage] return the percental amount of the current table
/// width.
pub fn max(
table: &Table,
constraint: &Option<ColumnConstraint>,
visible_columns: usize,
) -> Option<u16> {
let constraint = if let Some(constraint) = constraint {
constraint
} else {
return None;
};
match constraint {
UpperBoundary(width) | Boundaries { upper: width, .. } => {
absolute_value_from_width(table, width, visible_columns)
}
_ => None,
}
}
/// Resolve an absolute value from a given boundary
pub fn absolute_value_from_width(
table: &Table,
width: &Width,
visible_columns: usize,
) -> Option<u16> {
match width {
Width::Fixed(width) => Some(*width),
Width::Percentage(percent) => {
// Don't return a value, if we cannot determine the current table width.
let table_width = table.width().map(usize::from)?;
// Enforce at most 100%
let percent = std::cmp::min(*percent, 100u16);
// Subtract the borders from the table width.
let width = table_width.saturating_sub(count_border_columns(table, visible_columns));
// Calculate the absolute value in actual columns.
let width = (width * usize::from(percent) / 100)
.try_into()
.unwrap_or(u16::MAX);
Some(width)
}
}
}