// Height allocation follows tabled's height settings; see THIRD_PARTY_NOTICES.md.
///|
pub struct TableHeightIncrease[M, P] {
height : M
priority : P
} derive(Debug)
///|
pub fn[M] TableHeightIncrease::new(
height : M,
) -> TableHeightIncrease[M, PriorityRoundRobin] {
{ height, priority: PriorityRoundRobin::new(), }
}
///|
pub fn[M, P, Q] TableHeightIncrease::priority(
self : TableHeightIncrease[M, P],
priority : Q,
) -> TableHeightIncrease[M, Q] {
{ height: self.height, priority, }
}
///|
pub impl[M : Measurement, P : ResizeSelector] TableOption for TableHeightIncrease[
M,
P,
] with fn change(self, table) {
if table.is_empty() {
return
}
let target = Measurement::measure(self.height, table, Attribute::Height)
let (total, heights) = height_table_measure(table)
if total >= target {
return
}
let priority = ResizeSelector::fresh(self.priority)
// A legacy height limit can render zero lines. A lower bound below zero
// keeps those rows selectable for growth without changing their real sizes.
let minimums = Array::make(heights.length(), -1)
for _ in total.. TableHeightLimit[M, PriorityRoundRobin] {
{ height, priority: PriorityRoundRobin::new(), }
}
///|
pub fn[M, P, Q] TableHeightLimit::priority(
self : TableHeightLimit[M, P],
priority : Q,
) -> TableHeightLimit[M, Q] {
{ height: self.height, priority, }
}
///|
pub impl[M : Measurement, P : ResizeSelector] TableOption for TableHeightLimit[
M,
P,
] with fn change(self, table) {
if table.is_empty() {
return
}
let target = Measurement::measure(self.height, table, Attribute::Height)
let (total, heights) = height_table_measure(table)
if total <= target {
return
}
let priority = ResizeSelector::fresh(self.priority)
for _ in target.. height {
table.rows[row][col] = height_limit_lines(text, height)
}
}
}
table.dimension.set_heights(heights)
}
///|
pub impl[M : Measurement, P : ResizeSelector] TableOption for TableHeightLimit[
M,
P,
] with fn hint_change(_self) {
None
}
///|
// Measure records afresh, independently of cached dimensions. Include legacy
// render-time modes so height options use the same layout as the renderer.
fn height_table_measure(table : Table) -> (Int, Array[Int]) {
let heights = @papergrid.IterGridDimension::measure_heights(
@papergrid.IterRecords::new(table.rows),
table.config,
apply_modes=true,
)
let total = heights.fold(init=0, (sum, value) => sum + value) +
table.config.count_horizontal(table.count_rows()) +
table.config.margin_top +
table.config.margin_bottom
(total, heights)
}
///|
pub struct HeightList {
heights : Array[Int]
} derive(Debug)
///|
pub fn HeightList::new(heights : Array[Int]) -> HeightList {
{ heights: heights.copy(), }
}
///|
pub fn HeightList::from_array(heights : Array[Int]) -> HeightList {
HeightList::new(heights)
}
///|
pub fn HeightList::from_iter(heights : Iter[Int]) -> HeightList {
HeightList::new(heights.to_array())
}
///|
/// Fix row heights, including cell padding. A shorter list has no effect.
///
/// ```mbt check
/// test {
/// let table = @tabular.Table::from_rows([["one"], ["two"]]).with_(
/// @tabular.Height::list([0, 2]),
/// )
/// assert_eq(table.to_string(), "+-----+\n+-----+\n| two |\n| |\n+-----+")
/// }
/// ```
pub fn Height::list(heights : Array[Int]) -> HeightList {
HeightList::new(heights)
}
///|
pub impl TableOption for HeightList with fn change(self, table) {
if self.heights.length() >= table.count_rows() {
table.dimension.set_heights(self.heights)
}
}
///|
pub impl TableOption for HeightList with fn hint_change(_self) {
None
}
///|
pub extend TableHeightIncrease with @debug.Debug::{to_repr}
///|
pub extend TableHeightIncrease with TableOption::{change, hint_change}
///|
pub extend TableHeightLimit with @debug.Debug::{to_repr}
///|
pub extend TableHeightLimit with TableOption::{change, hint_change}
///|
pub extend HeightList with @debug.Debug::{to_repr}
///|
pub extend HeightList with TableOption::{change, hint_change}