freya_components/
table.rs

1use 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/// TableHead props (manual)
61#[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    /// optional press handler
202    pub on_press: Option<EventHandler<Event<PressEventData>>>,
203    /// optional visual order direction
204    pub order_direction: Option<OrderDirection>,
205    /// padding as typed Gaps
206    pub padding: Gaps,
207    /// height as typed Size
208    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}