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 Component 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 Component 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 Component 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 Component 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 Component 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#[cfg_attr(feature = "docs",
326 doc = embed_doc_image::embed_image!("table", "images/gallery_table.png"),
327)]
328#[derive(PartialEq)]
329pub struct Table {
330 pub height: Size,
331 pub theme: Option<TableThemePartial>,
332 pub columns: usize,
333 pub children: Vec<Element>,
334 key: DiffKey,
335}
336
337impl Default for Table {
338 fn default() -> Self {
339 Self {
340 height: Size::Inner,
341 theme: None,
342 columns: 1,
343 children: vec![],
344 key: DiffKey::None,
345 }
346 }
347}
348
349impl Table {
350 pub fn new(columns: usize) -> Self {
351 Self {
352 columns,
353 ..Default::default()
354 }
355 }
356
357 pub fn height(mut self, height: impl Into<Size>) -> Self {
358 self.height = height.into();
359 self
360 }
361
362 pub fn theme(mut self, theme: TableThemePartial) -> Self {
363 self.theme = Some(theme);
364 self
365 }
366}
367
368impl ChildrenExt for Table {
369 fn get_children(&mut self) -> &mut Vec<Element> {
370 &mut self.children
371 }
372}
373
374impl KeyExt for Table {
375 fn write_key(&mut self) -> &mut DiffKey {
376 &mut self.key
377 }
378}
379
380#[derive(Clone)]
381pub struct TableConfig {
382 pub columns: usize,
383}
384
385impl TableConfig {
386 pub fn new(columns: usize) -> Self {
387 Self { columns }
388 }
389}
390
391impl Component for Table {
392 fn render(&self) -> impl IntoElement {
393 let TableTheme {
394 background,
395 corner_radius,
396 divider_fill,
397 color,
398 ..
399 } = get_theme!(&self.theme, table);
400
401 provide_context(TableConfig::new(self.columns));
402
403 rect()
404 .overflow(Overflow::Clip)
405 .color(color)
406 .background(background)
407 .corner_radius(corner_radius)
408 .height(self.height.clone())
409 .border(
410 Border::new()
411 .alignment(BorderAlignment::Outer)
412 .fill(divider_fill)
413 .width(1.0),
414 )
415 .children(self.children.clone())
416 }
417
418 fn render_key(&self) -> DiffKey {
419 self.key.clone().or(self.default_key())
420 }
421}