1use iced_widget::core::text as core_text;
4use iced_widget::core::{Length, Padding, alignment};
5use iced_widget::table::{self as iced_table, Column, Table};
6use iced_widget::text;
7use iced_widget::{Container, Text};
8
9use super::absolute_line_height;
10use crate::{Theme, text as text_style, tokens};
11
12const CELL_HORIZONTAL_PADDING: f32 = 16.0;
13pub const COMPACT_NUMERIC_COLUMN_WIDTH: f32 = 88.0;
14
15pub fn standard<'a, 'b, T, Message, Renderer>(
16 columns: impl IntoIterator<Item = Column<'a, 'b, T, Message, Theme, Renderer>>,
17 rows: impl IntoIterator<Item = T>,
18) -> Table<'a, Message, Theme, Renderer>
19where
20 T: Clone,
21 Renderer: iced_widget::core::Renderer,
22{
23 iced_table::table(columns, rows)
24 .width(Length::Fill)
25 .padding(0.0)
26 .separator(tokens::component::data_table::OUTLINE_WIDTH)
27}
28
29pub fn column<'a, 'b, T, F, Message, Renderer>(
30 header: impl text::IntoFragment<'a>,
31 view: impl Fn(T) -> F + 'b,
32) -> Column<'a, 'b, T, Message, Theme, Renderer>
33where
34 T: 'a,
35 F: text::IntoFragment<'a> + 'a,
36 Message: 'a,
37 Renderer: iced_widget::core::Renderer + core_text::Renderer + 'a,
38{
39 iced_table::column(header_cell(header), move |row| body_cell(view(row)))
40 .width(Length::Fill)
41 .align_y(alignment::Vertical::Center)
42}
43
44pub fn weighted_column<'a, 'b, T, F, Message, Renderer>(
45 weight: u16,
46 header: impl text::IntoFragment<'a>,
47 view: impl Fn(T) -> F + 'b,
48) -> Column<'a, 'b, T, Message, Theme, Renderer>
49where
50 T: 'a,
51 F: text::IntoFragment<'a> + 'a,
52 Message: 'a,
53 Renderer: iced_widget::core::Renderer + core_text::Renderer + 'a,
54{
55 column(header, view).width(Length::FillPortion(weight))
56}
57
58pub fn numeric_column<'a, 'b, T, F, Message, Renderer>(
59 header: impl text::IntoFragment<'a>,
60 view: impl Fn(T) -> F + 'b,
61) -> Column<'a, 'b, T, Message, Theme, Renderer>
62where
63 T: 'a,
64 F: text::IntoFragment<'a> + 'a,
65 Message: 'a,
66 Renderer: iced_widget::core::Renderer + core_text::Renderer + 'a,
67{
68 iced_table::column(header_cell_right(header), move |row| {
69 body_cell_right(view(row))
70 })
71 .width(Length::Fill)
72 .align_x(alignment::Horizontal::Right)
73 .align_y(alignment::Vertical::Center)
74}
75
76pub fn compact_numeric_column<'a, 'b, T, F, Message, Renderer>(
77 header: impl text::IntoFragment<'a>,
78 view: impl Fn(T) -> F + 'b,
79) -> Column<'a, 'b, T, Message, Theme, Renderer>
80where
81 T: 'a,
82 F: text::IntoFragment<'a> + 'a,
83 Message: 'a,
84 Renderer: iced_widget::core::Renderer + core_text::Renderer + 'a,
85{
86 numeric_column(header, view).width(Length::Fixed(COMPACT_NUMERIC_COLUMN_WIDTH))
87}
88
89pub fn header_cell<'a, Message, Renderer>(
90 label: impl text::IntoFragment<'a>,
91) -> Container<'a, Message, Theme, Renderer>
92where
93 Message: 'a,
94 Renderer: iced_widget::core::Renderer + core_text::Renderer + 'a,
95{
96 header_cell_aligned(label, alignment::Horizontal::Left)
97}
98
99pub fn header_cell_right<'a, Message, Renderer>(
100 label: impl text::IntoFragment<'a>,
101) -> Container<'a, Message, Theme, Renderer>
102where
103 Message: 'a,
104 Renderer: iced_widget::core::Renderer + core_text::Renderer + 'a,
105{
106 header_cell_aligned(label, alignment::Horizontal::Right)
107}
108
109pub fn body_cell<'a, Message, Renderer>(
110 label: impl text::IntoFragment<'a>,
111) -> Container<'a, Message, Theme, Renderer>
112where
113 Message: 'a,
114 Renderer: iced_widget::core::Renderer + core_text::Renderer + 'a,
115{
116 body_cell_aligned(label, alignment::Horizontal::Left)
117}
118
119pub fn body_cell_right<'a, Message, Renderer>(
120 label: impl text::IntoFragment<'a>,
121) -> Container<'a, Message, Theme, Renderer>
122where
123 Message: 'a,
124 Renderer: iced_widget::core::Renderer + core_text::Renderer + 'a,
125{
126 body_cell_aligned(label, alignment::Horizontal::Right)
127}
128
129fn header_cell_aligned<'a, Message, Renderer>(
130 label: impl text::IntoFragment<'a>,
131 align_x: alignment::Horizontal,
132) -> Container<'a, Message, Theme, Renderer>
133where
134 Message: 'a,
135 Renderer: iced_widget::core::Renderer + core_text::Renderer + 'a,
136{
137 let label_text = tokens::typography::LABEL_LARGE;
138
139 cell(
140 Text::new(label)
141 .size(label_text.size)
142 .line_height(absolute_line_height(label_text.line_height))
143 .style(text_style::surface_variant),
144 tokens::component::data_table::HEADER_CONTAINER_HEIGHT,
145 align_x,
146 )
147}
148
149fn body_cell_aligned<'a, Message, Renderer>(
150 label: impl text::IntoFragment<'a>,
151 align_x: alignment::Horizontal,
152) -> Container<'a, Message, Theme, Renderer>
153where
154 Message: 'a,
155 Renderer: iced_widget::core::Renderer + core_text::Renderer + 'a,
156{
157 let body_text = tokens::typography::BODY_MEDIUM;
158
159 cell(
160 Text::new(label)
161 .size(body_text.size)
162 .line_height(absolute_line_height(body_text.line_height))
163 .style(text_style::surface),
164 tokens::component::data_table::ROW_ITEM_CONTAINER_HEIGHT,
165 align_x,
166 )
167}
168
169fn cell<'a, Message, Renderer>(
170 content: Text<'a, Theme, Renderer>,
171 height: f32,
172 align_x: alignment::Horizontal,
173) -> Container<'a, Message, Theme, Renderer>
174where
175 Message: 'a,
176 Renderer: iced_widget::core::Renderer + core_text::Renderer + 'a,
177{
178 Container::new(content)
179 .width(Length::Shrink)
180 .height(Length::Fixed(height))
181 .padding(Padding::from([0.0, CELL_HORIZONTAL_PADDING]))
182 .align_x(align_x)
183 .align_y(alignment::Vertical::Center)
184}