freya_components/
table.rs1use freya_core::prelude::*;
2use torin::{
3 content::Content,
4 gaps::Gaps,
5 node::Node,
6 prelude::Alignment,
7 size::Size,
8};
9
10use crate::{
11 define_theme,
12 get_theme,
13};
14
15define_theme! {
16 for = Table;
17 theme_field = theme;
18
19 %[component]
20 pub Table {
21 %[fields]
22 background: Color,
23 hover_row_background: Color,
24 row_background: Color,
25 divider_fill: Color,
26 corner_radius: CornerRadius,
27 color: Color,
28 }
29}
30
31#[derive(Clone)]
33pub struct TableConfig {
34 pub theme: TableTheme,
35 pub column_widths: Option<Vec<Size>>,
36}
37
38#[derive(PartialEq)]
39pub struct TableRow {
40 pub children: Vec<Element>,
41 layout: LayoutData,
42 key: DiffKey,
43}
44
45impl Default for TableRow {
46 fn default() -> Self {
47 Self::new()
48 }
49}
50
51impl TableRow {
52 pub fn new() -> Self {
53 Self {
54 children: vec![],
55 layout: Node {
56 width: Size::fill(),
57 ..Default::default()
58 }
59 .into(),
60 key: DiffKey::None,
61 }
62 }
63}
64
65impl LayoutExt for TableRow {
66 fn layout_mut(&mut self) -> &mut LayoutData {
67 &mut self.layout
68 }
69}
70
71impl ContainerExt for TableRow {}
72
73impl ChildrenExt for TableRow {
74 fn children_mut(&mut self) -> &mut Vec<Element> {
75 &mut self.children
76 }
77}
78
79impl KeyExt for TableRow {
80 fn key_mut(&mut self) -> &mut DiffKey {
81 &mut self.key
82 }
83}
84
85impl Component for TableRow {
86 fn render(&self) -> impl IntoElement {
87 let TableConfig {
88 theme,
89 column_widths,
90 } = use_try_consume::<TableConfig>().unwrap_or_else(|| TableConfig {
91 theme: get_theme!(None::<TableThemePartial>, TableThemePreference, "table"),
92 column_widths: None,
93 });
94 let mut hovering = use_state(|| false);
95 let background = if hovering() {
96 theme.hover_row_background
97 } else {
98 theme.row_background
99 };
100
101 rect()
102 .layout(self.layout.clone())
103 .horizontal()
104 .content(Content::Flex)
105 .cross_align(Alignment::Center)
106 .background(background)
107 .border(Border::new().fill(theme.divider_fill).width(BorderWidth {
108 bottom: 1.,
109 ..Default::default()
110 }))
111 .on_pointer_enter(move |_| hovering.set(true))
112 .on_pointer_leave(move |_| hovering.set(false))
113 .children(self.children.iter().enumerate().map(|(index, child)| {
114 let width = column_widths
115 .as_ref()
116 .and_then(|widths| widths.get(index).cloned())
117 .unwrap_or_else(|| Size::flex(1.));
118
119 rect()
120 .width(width)
121 .overflow(Overflow::Clip)
122 .padding(Gaps::new_all(5.0))
123 .horizontal()
124 .main_align(Alignment::End)
125 .cross_align(Alignment::Center)
126 .child(child.clone())
127 }))
128 }
129
130 fn render_key(&self) -> DiffKey {
131 self.key.clone().or(self.default_key())
132 }
133}
134
135#[derive(PartialEq, Default)]
151pub struct Table {
152 pub theme: Option<TableThemePartial>,
153 pub column_widths: Option<Vec<Size>>,
154 pub children: Vec<Element>,
155 layout: LayoutData,
156 key: DiffKey,
157}
158
159impl Table {
160 pub fn new() -> Self {
161 Self::default()
162 }
163
164 pub fn theme(mut self, theme: TableThemePartial) -> Self {
165 self.theme = Some(theme);
166 self
167 }
168
169 pub fn column_widths(mut self, widths: impl Into<Vec<Size>>) -> Self {
173 self.column_widths = Some(widths.into());
174 self
175 }
176}
177
178impl ChildrenExt for Table {
179 fn children_mut(&mut self) -> &mut Vec<Element> {
180 &mut self.children
181 }
182}
183
184impl KeyExt for Table {
185 fn key_mut(&mut self) -> &mut DiffKey {
186 &mut self.key
187 }
188}
189
190impl LayoutExt for Table {
191 fn layout_mut(&mut self) -> &mut LayoutData {
192 &mut self.layout
193 }
194}
195
196impl ContainerExt for Table {}
197
198impl Component for Table {
199 fn render(&self) -> impl IntoElement {
200 let theme = get_theme!(&self.theme, TableThemePreference, "table");
201 provide_context(TableConfig {
202 theme: theme.clone(),
203 column_widths: self.column_widths.clone(),
204 });
205
206 rect()
207 .layout(self.layout.clone())
208 .overflow(Overflow::Clip)
209 .color(theme.color)
210 .background(theme.background)
211 .corner_radius(theme.corner_radius)
212 .border(
213 Border::new()
214 .alignment(BorderAlignment::Outer)
215 .fill(theme.divider_fill)
216 .width(1.0),
217 )
218 .children(self.children.clone())
219 }
220
221 fn render_key(&self) -> DiffKey {
222 self.key.clone().or(self.default_key())
223 }
224}