qframe/widgets/table/
model.rs1use crate::icons::Glyph;
4use crate::text;
5use crate::widget::Align;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum ColumnWidth {
10 Fixed(u16),
12 Fit,
14 Fill(u16),
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum SortDirection {
21 Ascending,
23 Descending,
25}
26
27impl SortDirection {
28 #[must_use]
30 pub fn reversed(self) -> Self {
31 match self {
32 Self::Ascending => Self::Descending,
33 Self::Descending => Self::Ascending,
34 }
35 }
36}
37
38#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct Column {
41 pub(super) title: String,
42 pub(super) width: ColumnWidth,
43 pub(super) min: Option<u16>,
44 pub(super) align: Align,
45 pub(super) sortable: bool,
46}
47
48impl Column {
49 #[must_use]
51 pub fn new(title: impl Into<String>) -> Self {
52 Self { title: title.into(), width: ColumnWidth::Fill(1), min: None, align: Align::Start, sortable: false }
53 }
54
55 #[must_use]
57 pub fn width(mut self, width: ColumnWidth) -> Self {
58 self.width = width;
59 self
60 }
61
62 #[must_use]
66 pub fn min(mut self, cells: u16) -> Self {
67 self.min = Some(cells);
68 self
69 }
70
71 #[must_use]
73 pub fn align(mut self, align: Align) -> Self {
74 self.align = align;
75 self
76 }
77
78 #[must_use]
80 pub fn sortable(mut self, sortable: bool) -> Self {
81 self.sortable = sortable;
82 self
83 }
84
85 pub(super) fn title_width(&self) -> u16 {
86 text::width(&self.title).saturating_add(if self.sortable { 2 } else { 0 })
87 }
88}
89
90#[derive(Debug, Clone, PartialEq, Eq, Default)]
92pub struct TableCell {
93 pub(super) text: String,
94 pub(super) icon: Option<Glyph>,
95 pub(super) icon_color: Option<String>,
96 pub(super) color: Option<String>,
97}
98
99impl TableCell {
100 #[must_use]
102 pub fn new(text: impl Into<String>) -> Self {
103 Self { text: text.into(), ..Self::default() }
104 }
105
106 #[must_use]
114 pub fn icon(mut self, glyph: impl Into<Glyph>, color: Option<&str>) -> Self {
115 self.icon = Some(glyph.into());
116 self.icon_color = color.map(str::to_owned);
117 self
118 }
119
120 #[must_use]
122 pub fn color(mut self, token: impl Into<String>) -> Self {
123 self.color = Some(token.into());
124 self
125 }
126
127 pub(super) fn width(&self) -> u16 {
130 let glyph = match &self.icon {
131 None => 0,
132 Some(Glyph::Key(_)) => 2,
133 Some(Glyph::Literal(glyph)) => text::width(glyph).saturating_add(1),
134 };
135 text::width(&self.text).saturating_add(glyph)
136 }
137}
138
139impl From<&str> for TableCell {
140 fn from(text: &str) -> Self {
141 Self::new(text)
142 }
143}
144
145impl From<String> for TableCell {
146 fn from(text: String) -> Self {
147 Self::new(text)
148 }
149}
150
151#[derive(Debug, Clone, PartialEq, Eq, Default)]
153pub struct TableRow {
154 pub(super) cells: Vec<TableCell>,
155 pub(super) faint: bool,
156}
157
158impl TableRow {
159 #[must_use]
161 pub fn new(cells: impl IntoIterator<Item = impl Into<TableCell>>) -> Self {
162 Self { cells: cells.into_iter().map(Into::into).collect(), faint: false }
163 }
164
165 #[must_use]
167 pub fn faint(mut self, faint: bool) -> Self {
168 self.faint = faint;
169 self
170 }
171}