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 pub(super) role: Option<String>,
98}
99
100impl TableCell {
101 #[must_use]
103 pub fn new(text: impl Into<String>) -> Self {
104 Self { text: text.into(), ..Self::default() }
105 }
106
107 #[must_use]
115 pub fn icon(mut self, glyph: impl Into<Glyph>, color: Option<&str>) -> Self {
116 self.icon = Some(glyph.into());
117 self.icon_color = color.map(str::to_owned);
118 self
119 }
120
121 #[must_use]
123 pub fn color(mut self, token: impl Into<String>) -> Self {
124 self.color = Some(token.into());
125 self
126 }
127
128 #[must_use]
133 pub fn role(mut self, role: impl Into<String>) -> Self {
134 self.role = Some(role.into());
135 self
136 }
137
138 pub(super) fn width(&self) -> u16 {
141 let glyph = match &self.icon {
142 None => 0,
143 Some(Glyph::Key(_)) => 2,
144 Some(Glyph::Literal(glyph)) => text::width(glyph).saturating_add(1),
145 };
146 text::width(&self.text).saturating_add(glyph)
147 }
148}
149
150impl From<&str> for TableCell {
151 fn from(text: &str) -> Self {
152 Self::new(text)
153 }
154}
155
156impl From<String> for TableCell {
157 fn from(text: String) -> Self {
158 Self::new(text)
159 }
160}
161
162#[derive(Debug, Clone, PartialEq, Eq, Default)]
164pub struct TableRow {
165 pub(super) cells: Vec<TableCell>,
166 pub(super) faint: bool,
167}
168
169impl TableRow {
170 #[must_use]
172 pub fn new(cells: impl IntoIterator<Item = impl Into<TableCell>>) -> Self {
173 Self { cells: cells.into_iter().map(Into::into).collect(), faint: false }
174 }
175
176 #[must_use]
178 pub fn faint(mut self, faint: bool) -> Self {
179 self.faint = faint;
180 self
181 }
182}