#[allow(unused_imports)]
use crate::{Field, FieldKind, Fill, Region, RowPart};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Width {
Content,
Fixed,
Fill,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub enum Priority {
Optional,
Secondary,
Essential,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Fallback {
Wrap,
Stack,
Shed,
Menu,
}
pub const MIN_CEILING: u16 = 64;
const FILL_FLOOR: u16 = 16;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Column<'a> {
pub name: &'a str,
pub width: Width,
pub priority: Priority,
pub kind: ColumnKind,
pub min: Option<u16>,
pub sortable: bool,
pub sorted: Option<Sort>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[non_exhaustive]
pub enum ColumnKind {
#[default]
Text,
Identifier,
Date,
Number,
Code,
Status,
Actions,
}
impl ColumnKind {
#[must_use]
pub const fn floor(self) -> u16 {
match self {
Self::Text | Self::Code | Self::Status | Self::Actions => 8,
Self::Identifier => 12,
Self::Date => 10,
Self::Number => 6,
}
}
#[must_use]
#[deprecated(
since = "0.50.1",
note = "a floor binds for every kind; priority decides whether a column gives up room"
)]
pub const fn holds_minimum(self) -> bool {
matches!(
self,
Self::Date | Self::Number | Self::Status | Self::Actions
)
}
#[must_use]
pub const fn aligns_end(self) -> bool {
matches!(self, Self::Number | Self::Actions)
}
#[must_use]
pub const fn wraps(self) -> bool {
matches!(self, Self::Text | Self::Identifier)
}
#[must_use]
pub const fn monospace(self) -> bool {
matches!(self, Self::Identifier | Self::Code)
}
#[must_use]
pub const fn tabular(self) -> bool {
matches!(self, Self::Date | Self::Number)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Sort {
Ascending,
Descending,
}
impl Sort {
#[must_use]
pub const fn reversed(self) -> Self {
match self {
Self::Ascending => Self::Descending,
Self::Descending => Self::Ascending,
}
}
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::Ascending => "ascending",
Self::Descending => "descending",
}
}
#[must_use]
pub const fn glyph(self) -> &'static str {
match self {
Self::Ascending => "\u{25B2}",
Self::Descending => "\u{25BC}",
}
}
}
impl<'a> Column<'a> {
#[must_use]
pub const fn new(name: &'a str) -> Self {
Self {
name,
width: Width::Fill,
priority: Priority::Essential,
kind: ColumnKind::Text,
min: None,
sortable: false,
sorted: None,
}
}
#[must_use]
pub const fn min(mut self, ch: u16) -> Self {
self.min = Some(ch);
self
}
#[must_use]
pub const fn floor(&self) -> u16 {
let raw = match self.min {
Some(ch) => ch,
None => {
let caret = if self.sortable || self.sorted.is_some() {
2
} else {
0
};
let heading = if self.name.len() > MIN_CEILING as usize {
MIN_CEILING
} else {
self.name.len() as u16 + 2 + caret
};
let kind = self.kind.floor();
let fill = if matches!(self.width, Width::Fill) {
FILL_FLOOR
} else {
0
};
let wider = if heading > kind { heading } else { kind };
if fill > wider { fill } else { wider }
}
};
let raw = if raw > MIN_CEILING { MIN_CEILING } else { raw };
let even = raw + raw % 2;
if even < 2 {
2
} else if even > MIN_CEILING {
MIN_CEILING
} else {
even
}
}
#[must_use]
pub const fn kept_at(&self, cutoff: Priority) -> bool {
(self.priority as u8) >= (cutoff as u8)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum CellPart {
Value,
Tokens,
Actions,
Link,
}
impl CellPart {
#[must_use]
pub const fn intent(self) -> &'static str {
match self {
Self::Value => "content",
Self::Tokens => "content",
Self::Actions => "content",
Self::Link => "content",
}
}
}