use gpui_kit::{Pixels, px};
use crate::db::query::QueryResult;
const SAMPLE_ROWS: usize = 100;
const CHARACTER_WIDTH: f32 = 7.2;
const CELL_PADDING: f32 = 18.;
pub(super) const MIN_COLUMN_WIDTH: f32 = 56.;
const MAX_COLUMN_WIDTH: f32 = 420.;
const NULL_WIDTH: usize = 4;
pub(super) fn measure_columns(result: &QueryResult) -> Vec<Pixels> {
result
.columns
.iter()
.enumerate()
.map(|(index, name)| {
let mut characters = name.chars().count();
for row in result.rows.iter().take(SAMPLE_ROWS) {
let width = match row.get(index) {
Some(Some(value)) => value.chars().count(),
Some(None) => NULL_WIDTH,
None => 0,
};
characters = characters.max(width);
}
let width = characters as f32 * CHARACTER_WIDTH + CELL_PADDING;
px(width.clamp(MIN_COLUMN_WIDTH, MAX_COLUMN_WIDTH))
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
fn result(columns: &[&str], rows: Vec<Vec<Option<&str>>>) -> QueryResult {
QueryResult {
columns: columns.iter().map(|name| name.to_string()).collect(),
rows: rows
.into_iter()
.map(|row| {
row.into_iter()
.map(|cell| cell.map(|value| value.to_string()))
.collect()
})
.collect(),
..QueryResult::default()
}
}
#[test]
fn narrow_columns_get_the_minimum_width() {
let widths = measure_columns(&result(&["id"], vec![vec![Some("1")], vec![Some("2")]]));
assert_eq!(widths, [px(MIN_COLUMN_WIDTH)]);
}
#[test]
fn wide_values_are_capped() {
let long = "x".repeat(500);
let widths = measure_columns(&result(&["blob"], vec![vec![Some(long.as_str())]]));
assert_eq!(widths, [px(MAX_COLUMN_WIDTH)]);
}
#[test]
fn width_follows_the_longest_sampled_value() {
let widths = measure_columns(&result(
&["name"],
vec![
vec![Some("ada")],
vec![Some("a rather longer value")],
vec![None],
],
));
let expected = "a rather longer value".len() as f32 * CHARACTER_WIDTH + CELL_PADDING;
assert_eq!(widths, [px(expected)]);
}
#[test]
fn the_header_widens_a_column_of_short_values() {
let widths = measure_columns(&result(
&["a_column_with_a_long_name"],
vec![vec![Some("1")]],
));
let expected = "a_column_with_a_long_name".len() as f32 * CHARACTER_WIDTH + CELL_PADDING;
assert_eq!(widths, [px(expected)]);
}
#[test]
fn only_the_first_rows_are_sampled() {
let sampled = "a twenty char value.";
let long = "x".repeat(300);
let mut rows: Vec<Vec<Option<&str>>> = vec![vec![Some(sampled)]; SAMPLE_ROWS];
rows.push(vec![Some(long.as_str())]);
let widths = measure_columns(&result(&["value"], rows));
assert_eq!(
widths,
[px(sampled.len() as f32 * CHARACTER_WIDTH + CELL_PADDING)],
"a long value past the sample should not widen the column"
);
}
}