freya_components/
table.rs1use freya_core::prelude::*;
2use torin::{
3 gaps::Gaps,
4 prelude::Alignment,
5 size::Size,
6};
7
8use crate::{
9 get_theme,
10 icons::arrow::ArrowIcon,
11 theming::component_themes::{
12 TableTheme,
13 TableThemePartial,
14 },
15};
16
17#[derive(Clone, Copy, PartialEq, Default)]
18pub enum OrderDirection {
19 Up,
20 #[default]
21 Down,
22}
23
24#[derive(PartialEq)]
25pub struct TableArrow {
26 pub order_direction: OrderDirection,
27 key: DiffKey,
28}
29
30impl TableArrow {
31 pub fn new(order_direction: OrderDirection) -> Self {
32 Self {
33 order_direction,
34 key: DiffKey::None,
35 }
36 }
37}
38
39impl KeyExt for TableArrow {
40 fn write_key(&mut self) -> &mut DiffKey {
41 &mut self.key
42 }
43}
44
45impl Render for TableArrow {
46 fn render(&self) -> impl IntoElement {
47 let TableTheme { arrow_fill, .. } = get_theme!(None::<TableThemePartial>, table);
48 let rotate = match self.order_direction {
49 OrderDirection::Down => 0.,
50 OrderDirection::Up => 180.,
51 };
52 ArrowIcon::new().rotate(rotate).fill(arrow_fill)
53 }
54
55 fn render_key(&self) -> DiffKey {
56 self.key.clone().or(self.default_key())
57 }
58}
59
60#[derive(PartialEq, Default)]
62pub struct TableHead {
63 pub children: Vec<Element>,
64 key: DiffKey,
65}
66
67impl TableHead {
68 pub fn new() -> Self {
69 Self::default()
70 }
71}
72
73impl ChildrenExt for TableHead {
74 fn get_children(&mut self) -> &mut Vec<Element> {
75 &mut self.children
76 }
77}
78
79impl KeyExt for TableHead {
80 fn write_key(&mut self) -> &mut DiffKey {
81 &mut self.key
82 }
83}
84
85impl Render for TableHead {
86 fn render(&self) -> impl IntoElement {
87 rect().width(Size::fill()).children(self.children.clone())
88 }
89
90 fn render_key(&self) -> DiffKey {
91 self.key.clone().or(self.default_key())
92 }
93}
94
95#[derive(PartialEq, Default)]
96pub struct TableBody {
97 pub children: Vec<Element>,
98 key: DiffKey,
99}
100
101impl TableBody {
102 pub fn new() -> Self {
103 Self::default()
104 }
105}
106impl ChildrenExt for TableBody {
107 fn get_children(&mut self) -> &mut Vec<Element> {
108 &mut self.children
109 }
110}
111
112impl KeyExt for TableBody {
113 fn write_key(&mut self) -> &mut DiffKey {
114 &mut self.key
115 }
116}
117
118impl Render for TableBody {
119 fn render(&self) -> impl IntoElement {
120 rect().width(Size::fill()).children(self.children.clone())
121 }
122
123 fn render_key(&self) -> DiffKey {
124 self.key.clone().or(self.default_key())
125 }
126}
127
128#[derive(PartialEq, Clone, Copy)]
129enum TableRowState {
130 Idle,
131 Hovering,
132}
133
134#[derive(PartialEq, Default)]
135pub struct TableRow {
136 pub theme: Option<TableThemePartial>,
137 pub children: Vec<Element>,
138 key: DiffKey,
139}
140
141impl TableRow {
142 pub fn new() -> Self {
143 Self::default()
144 }
145}
146
147impl ChildrenExt for TableRow {
148 fn get_children(&mut self) -> &mut Vec<Element> {
149 &mut self.children
150 }
151}
152
153impl KeyExt for TableRow {
154 fn write_key(&mut self) -> &mut DiffKey {
155 &mut self.key
156 }
157}
158
159impl Render for TableRow {
160 fn render(&self) -> impl IntoElement {
161 let theme = get_theme!(&self.theme, table);
162 let mut state = use_state(|| TableRowState::Idle);
163 let TableTheme {
164 divider_fill,
165 hover_row_background,
166 row_background,
167 ..
168 } = theme;
169 let background = if state() == TableRowState::Hovering {
170 hover_row_background
171 } else {
172 row_background
173 };
174
175 rect()
176 .on_pointer_enter(move |_| state.set(TableRowState::Hovering))
177 .on_pointer_leave(move |_| state.set(TableRowState::Idle))
178 .background(background)
179 .child(
180 rect()
181 .width(Size::fill())
182 .horizontal()
183 .children(self.children.clone()),
184 )
185 .child(
186 rect()
187 .height(Size::px(1.))
188 .width(Size::fill())
189 .background(divider_fill),
190 )
191 }
192
193 fn render_key(&self) -> DiffKey {
194 self.key.clone().or(self.default_key())
195 }
196}
197
198#[derive(PartialEq)]
199pub struct TableCell {
200 pub children: Vec<Element>,
201 pub on_press: Option<EventHandler<Event<PressEventData>>>,
203 pub order_direction: Option<OrderDirection>,
205 pub padding: Gaps,
207 pub height: Size,
209 key: DiffKey,
210}
211
212impl ChildrenExt for TableCell {
213 fn get_children(&mut self) -> &mut Vec<Element> {
214 &mut self.children
215 }
216}
217
218impl Default for TableCell {
219 fn default() -> Self {
220 Self {
221 children: vec![],
222 on_press: None,
223 order_direction: None,
224 padding: Gaps::new_all(5.0),
225 height: Size::px(35.0),
226 key: DiffKey::None,
227 }
228 }
229}
230
231impl TableCell {
232 pub fn new() -> Self {
233 Self::default()
234 }
235
236 pub fn padding(mut self, padding: Gaps) -> Self {
237 self.padding = padding;
238 self
239 }
240
241 pub fn height(mut self, height: impl Into<Size>) -> Self {
242 self.height = height.into();
243 self
244 }
245
246 pub fn on_press(mut self, handler: impl Into<EventHandler<Event<PressEventData>>>) -> Self {
247 self.on_press = Some(handler.into());
248 self
249 }
250
251 pub fn order_direction(mut self, dir: Option<OrderDirection>) -> Self {
252 self.order_direction = dir;
253 self
254 }
255}
256
257impl KeyExt for TableCell {
258 fn write_key(&mut self) -> &mut DiffKey {
259 &mut self.key
260 }
261}
262
263impl Render for TableCell {
264 fn render(&self) -> impl IntoElement {
265 let config = use_try_consume::<TableConfig>().unwrap_or(TableConfig::new(1));
266 let width_percent = 100.0 / (config.columns as f32);
267 let mut container = rect()
268 .overflow(Overflow::Clip)
269 .padding(self.padding)
270 .width(Size::percent(width_percent))
271 .main_align(Alignment::End)
272 .cross_align(Alignment::Center)
273 .height(self.height.clone())
274 .horizontal();
275
276 if let Some(on_press) = &self.on_press {
277 let handler = on_press.clone();
278 container = container.on_press(move |e| handler.call(e));
279 }
280
281 if let Some(order_direction) = self.order_direction {
282 container = container.child(
283 rect()
284 .margin(Gaps::new_all(10.0))
285 .width(Size::px(10.0))
286 .height(Size::px(10.0))
287 .child(TableArrow::new(order_direction)),
288 );
289 }
290
291 container.children(self.children.clone())
292 }
293
294 fn render_key(&self) -> DiffKey {
295 self.key.clone().or(self.default_key())
296 }
297}
298
299#[derive(PartialEq)]
300pub struct Table {
301 pub height: Size,
302 pub theme: Option<TableThemePartial>,
303 pub columns: usize,
304 pub children: Vec<Element>,
305 key: DiffKey,
306}
307
308impl Default for Table {
309 fn default() -> Self {
310 Self {
311 height: Size::fill(),
312 theme: None,
313 columns: 1,
314 children: vec![],
315 key: DiffKey::None,
316 }
317 }
318}
319
320impl Table {
321 pub fn new(columns: usize) -> Self {
322 Self {
323 columns,
324 ..Default::default()
325 }
326 }
327
328 pub fn height(mut self, height: impl Into<Size>) -> Self {
329 self.height = height.into();
330 self
331 }
332
333 pub fn theme(mut self, theme: TableThemePartial) -> Self {
334 self.theme = Some(theme);
335 self
336 }
337}
338
339impl ChildrenExt for Table {
340 fn get_children(&mut self) -> &mut Vec<Element> {
341 &mut self.children
342 }
343}
344
345impl KeyExt for Table {
346 fn write_key(&mut self) -> &mut DiffKey {
347 &mut self.key
348 }
349}
350
351#[derive(Clone)]
352pub struct TableConfig {
353 pub columns: usize,
354}
355
356impl TableConfig {
357 pub fn new(columns: usize) -> Self {
358 Self { columns }
359 }
360}
361
362impl Render for Table {
363 fn render(&self) -> impl IntoElement {
364 let TableTheme {
365 background,
366 corner_radius,
367 divider_fill,
368 color,
369 ..
370 } = get_theme!(&self.theme, table);
371
372 provide_context(TableConfig::new(self.columns));
373
374 rect()
375 .overflow(Overflow::Clip)
376 .color(color)
377 .background(background)
378 .corner_radius(corner_radius)
379 .height(self.height.clone())
380 .border(
381 Border::new()
382 .alignment(BorderAlignment::Outer)
383 .fill(divider_fill)
384 .width(1.0),
385 )
386 .children(self.children.clone())
387 }
388
389 fn render_key(&self) -> DiffKey {
390 self.key.clone().or(self.default_key())
391 }
392}