1use ansiq_core::{
2 BlockFrame, Constraint, Element, ElementKind, Flex, HighlightSpacing, Layout, Length, Row,
3 SelectHandler, Style, TableAlignment, TableProps, TableState, Text,
4};
5
6pub struct Table<Message = ()> {
7 block: Option<BlockFrame>,
8 header: Option<Row>,
9 footer: Option<Row>,
10 rows: Vec<Row>,
11 widths: Vec<Constraint>,
12 column_spacing: u16,
13 flex: Flex,
14 alignments: Vec<TableAlignment>,
15 state: TableState,
16 highlight_symbol: Option<Text>,
17 row_highlight_style: Style,
18 column_highlight_style: Style,
19 cell_highlight_style: Style,
20 highlight_spacing: HighlightSpacing,
21 on_select: Option<SelectHandler<Message>>,
22 layout: Layout,
23 style: Style,
24 focusable: bool,
25}
26
27impl<Message> Default for Table<Message> {
28 fn default() -> Self {
29 Self {
30 block: None,
31 header: None,
32 footer: None,
33 rows: Vec::new(),
34 widths: Vec::new(),
35 column_spacing: 1,
36 flex: Flex::Start,
37 alignments: Vec::new(),
38 state: TableState::default(),
39 highlight_symbol: None,
40 row_highlight_style: Style::default(),
41 column_highlight_style: Style::default(),
42 cell_highlight_style: Style::default(),
43 highlight_spacing: HighlightSpacing::WhenSelected,
44 on_select: None,
45 layout: Layout {
46 width: Length::Fill,
47 height: Length::Auto,
48 },
49 style: Style::default(),
50 focusable: false,
51 }
52 }
53}
54
55impl Table<()> {
56 pub fn new<R, T, C>(rows: R, widths: C) -> Self
57 where
58 R: IntoIterator<Item = T>,
59 T: Into<Row>,
60 C: IntoIterator,
61 C::Item: Into<Constraint>,
62 {
63 Self::default().rows(rows).widths(widths)
64 }
65}
66
67impl<Message> Table<Message> {
68 pub fn rows<I, T>(mut self, rows: I) -> Self
69 where
70 I: IntoIterator<Item = T>,
71 T: Into<Row>,
72 {
73 self.rows = rows.into_iter().map(Into::into).collect();
74 self
75 }
76
77 pub fn row<T>(mut self, row: T) -> Self
78 where
79 T: Into<Row>,
80 {
81 self.rows.push(row.into());
82 self
83 }
84
85 pub fn header<T>(mut self, row: T) -> Self
86 where
87 T: Into<Row>,
88 {
89 self.header = Some(row.into());
90 self
91 }
92
93 pub fn headers<T>(self, row: T) -> Self
94 where
95 T: Into<Row>,
96 {
97 self.header(row)
98 }
99
100 pub fn footer<T>(mut self, row: T) -> Self
101 where
102 T: Into<Row>,
103 {
104 self.footer = Some(row.into());
105 self
106 }
107
108 pub fn widths<I>(mut self, widths: I) -> Self
109 where
110 I: IntoIterator,
111 I::Item: Into<Constraint>,
112 {
113 self.widths = widths.into_iter().map(Into::into).collect();
114 self
115 }
116
117 pub fn column_spacing(mut self, spacing: u16) -> Self {
118 self.column_spacing = spacing;
119 self
120 }
121
122 pub fn flex(mut self, flex: Flex) -> Self {
123 self.flex = flex;
124 self
125 }
126
127 pub fn block(mut self, block: crate::Block<Message>) -> Self {
128 self.block = Some(block.into_frame());
129 self
130 }
131
132 pub fn selected(mut self, selected: Option<usize>) -> Self {
133 self.state.select(selected);
134 self
135 }
136
137 pub fn offset(mut self, offset: usize) -> Self {
138 *self.state.offset_mut() = offset;
139 self
140 }
141
142 pub fn state(mut self, state: TableState) -> Self {
143 self.state = state;
144 self
145 }
146
147 pub fn highlight_symbol<T>(mut self, symbol: T) -> Self
148 where
149 T: Into<Text>,
150 {
151 self.highlight_symbol = Some(symbol.into());
152 self
153 }
154
155 pub fn highlight_style<S: Into<Style>>(self, style: S) -> Self {
156 self.row_highlight_style(style)
157 }
158
159 pub fn row_highlight_style<S: Into<Style>>(mut self, style: S) -> Self {
160 self.row_highlight_style = style.into();
161 self
162 }
163
164 pub fn column_highlight_style<S: Into<Style>>(mut self, style: S) -> Self {
165 self.column_highlight_style = style.into();
166 self
167 }
168
169 pub fn cell_highlight_style<S: Into<Style>>(mut self, style: S) -> Self {
170 self.cell_highlight_style = style.into();
171 self
172 }
173
174 pub fn highlight_spacing(mut self, spacing: HighlightSpacing) -> Self {
175 self.highlight_spacing = spacing;
176 self
177 }
178
179 pub fn alignment(mut self, alignment: TableAlignment) -> Self {
180 self.alignments.push(alignment);
181 self
182 }
183
184 pub fn alignments<I>(mut self, alignments: I) -> Self
185 where
186 I: IntoIterator<Item = TableAlignment>,
187 {
188 self.alignments.extend(alignments);
189 self
190 }
191
192 pub fn on_select<NextMessage, F>(self, handler: F) -> Table<NextMessage>
193 where
194 F: FnMut(usize) -> Option<NextMessage> + 'static,
195 {
196 Table {
197 block: self.block,
198 header: self.header,
199 footer: self.footer,
200 rows: self.rows,
201 widths: self.widths,
202 column_spacing: self.column_spacing,
203 flex: self.flex,
204 alignments: self.alignments,
205 state: self.state,
206 highlight_symbol: self.highlight_symbol,
207 row_highlight_style: self.row_highlight_style,
208 column_highlight_style: self.column_highlight_style,
209 cell_highlight_style: self.cell_highlight_style,
210 highlight_spacing: self.highlight_spacing,
211 on_select: Some(std::boxed::Box::new(handler)),
212 layout: self.layout,
213 style: self.style,
214 focusable: true,
215 }
216 }
217
218 pub fn layout(mut self, layout: Layout) -> Self {
219 self.layout = layout;
220 self
221 }
222
223 pub fn style<S: Into<Style>>(mut self, style: S) -> Self {
224 self.style = style.into();
225 self
226 }
227
228 pub fn build(self) -> Element<Message> {
229 Element::new(ElementKind::Table(TableProps {
230 block: self.block,
231 header: self.header,
232 footer: self.footer,
233 rows: self.rows,
234 widths: self.widths,
235 column_spacing: self.column_spacing,
236 flex: self.flex,
237 alignments: self.alignments,
238 state: self.state,
239 highlight_symbol: self.highlight_symbol,
240 row_highlight_style: self.row_highlight_style,
241 column_highlight_style: self.column_highlight_style,
242 cell_highlight_style: self.cell_highlight_style,
243 highlight_spacing: self.highlight_spacing,
244 on_select: self.on_select,
245 }))
246 .with_layout(self.layout)
247 .with_style(self.style)
248 .with_focusable(self.focusable)
249 }
250}
251
252impl<Item> FromIterator<Item> for Table<()>
253where
254 Item: Into<Row>,
255{
256 fn from_iter<Iter: IntoIterator<Item = Item>>(iter: Iter) -> Self {
257 Self::default().rows(iter)
258 }
259}