use std::slice::{Iter, IterMut};
#[derive(Default)]
pub struct ColumnBuilder {
width: ColumnWidth,
min_width: f64,
max_width: f64,
}
impl ColumnBuilder {
pub fn new() -> Self {
ColumnBuilder::default()
}
pub fn width(mut self, width: ColumnWidth) -> Self {
self.width = width;
self
}
pub fn min_width(mut self, min_width: f64) -> Self {
self.min_width = min_width;
self
}
pub fn max_width(mut self, max_width: f64) -> Self {
self.max_width = max_width;
self
}
pub fn build(self) -> Column {
Column {
width: self.width,
min_width: self.min_width,
max_width: self.max_width,
current_width: 0.0,
}
}
}
#[derive(Copy, Clone, Debug, Default, PartialEq)]
pub struct Column {
pub width: ColumnWidth,
pub min_width: f64,
pub max_width: f64,
current_width: f64,
}
impl Column {
#[inline]
pub fn create() -> ColumnBuilder {
ColumnBuilder::new()
}
pub fn width(&self) -> ColumnWidth {
self.width
}
pub fn current_width(&self) -> f64 {
self.current_width
}
pub fn set_current_width(&mut self, width: f64) {
self.current_width = if self.min_width == 0.0 && self.max_width == 0.0 && width > 0.0 {
width
} else if width < self.min_width && self.min_width > 0.0 {
self.min_width
} else if width > self.max_width && self.max_width > 0.0 {
self.max_width
} else {
width
};
}
}
impl From<&str> for Column {
fn from(t: &str) -> Self {
match t {
"Auto" | "auto" => Column::create().width(ColumnWidth::Auto).build(),
_ => Column::create().width(ColumnWidth::Stretch).build(),
}
}
}
impl From<f64> for Column {
fn from(t: f64) -> Self {
Column::create().width(ColumnWidth::Width(t)).build()
}
}
impl From<i32> for Column {
fn from(t: i32) -> Self {
Column::create().width(ColumnWidth::Width(t.into())).build()
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ColumnWidth {
Auto,
Stretch,
Width(f64),
}
impl Default for ColumnWidth {
fn default() -> Self {
ColumnWidth::Stretch
}
}
#[derive(Default)]
pub struct ColumnsBuilder {
columns: Vec<Column>,
}
impl ColumnsBuilder {
pub fn new() -> Self {
ColumnsBuilder::default()
}
pub fn push<C: Into<Column>>(mut self, column: C) -> Self {
self.columns.push(column.into());
self
}
#[inline(always)]
#[deprecated = "Use push instead"]
pub fn column<C: Into<Column>>(self, column: C) -> Self {
self.push(column)
}
pub fn columns<R: Into<Column> + Clone>(mut self, columns: &[R]) -> Self {
for column in columns.to_vec() {
self.columns.push(column.into());
}
self
}
pub fn repeat<R: Into<Column> + Copy>(mut self, column: R, count: usize) -> Self {
for _ in 0..count {
self.columns.push(column.into())
}
self
}
pub fn build(self) -> Columns {
Columns(self.columns)
}
}
impl From<ColumnsBuilder> for Columns {
fn from(builder: ColumnsBuilder) -> Self {
builder.build()
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Columns(pub Vec<Column>);
impl Columns {
#[inline]
pub fn create() -> ColumnsBuilder {
ColumnsBuilder::new()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn get(&self, column: usize) -> Option<&Column> {
self.0.get(column)
}
pub fn get_mut(&mut self, column: usize) -> Option<&mut Column> {
self.0.get_mut(column)
}
pub fn iter(&self) -> Iter<Column> {
self.0.iter()
}
pub fn iter_mut(&mut self) -> IterMut<Column> {
self.0.iter_mut()
}
}
#[cfg(test)]
mod tests {
use super::*;
const ERROR: f64 = f64::EPSILON;
#[test]
fn test_width() {
let width = ColumnWidth::Width(64.0);
let builder = ColumnBuilder::new();
let column = builder.width(width).build();
assert_eq!(column.width, width);
}
#[test]
fn test_min_width() {
let min_width = 64.0;
let builder = ColumnBuilder::new();
let column = builder.min_width(min_width).build();
assert!((column.min_width - min_width).abs() < ERROR);
}
#[test]
fn test_max_width() {
let max_width = 64.0;
let builder = ColumnBuilder::new();
let column = builder.max_width(max_width).build();
assert!((column.max_width - max_width) < ERROR);
}
#[test]
fn test_set_current_width() {
let out_one_width = 10.0;
let out_two_width = 66.0;
let in_width = 33.0;
let min_width = 14.0;
let max_width = 64.0;
let builder = ColumnBuilder::new();
let mut column = builder.min_width(min_width).max_width(max_width).build();
column.set_current_width(out_one_width);
assert!((column.current_width() - min_width).abs() < ERROR);
column.set_current_width(out_two_width);
assert!((column.current_width() - max_width).abs() < ERROR);
column.set_current_width(in_width);
assert!((column.current_width() - min_width).abs() < ERROR);
}
#[test]
fn test_column() {
let builder = ColumnsBuilder::new();
let columns = builder.build();
assert_eq!(columns.len(), 0);
let builder = ColumnsBuilder::new();
let columns = builder
.push(Column::create().build())
.push(Column::create().build())
.build();
assert_eq!(columns.len(), 2);
}
#[test]
fn test_column_width_into() {
let column: Column = "Auto".into();
assert_eq!(column.width(), ColumnWidth::Auto);
let column: Column = "auto".into();
assert_eq!(column.width(), ColumnWidth::Auto);
let column: Column = "Stretch".into();
assert_eq!(column.width(), ColumnWidth::Stretch);
let column: Column = "stretch".into();
assert_eq!(column.width(), ColumnWidth::Stretch);
let column: Column = "*".into();
assert_eq!(column.width(), ColumnWidth::Stretch);
let column: Column = "other".into();
assert_eq!(column.width(), ColumnWidth::Stretch);
let column: Column = 64.0.into();
assert_eq!(column.width(), ColumnWidth::Width(64.0));
}
}