gpui_component/table/delegate.rs
1use std::ops::Range;
2
3use gpui::{
4 App, Context, Div, InteractiveElement as _, IntoElement, ParentElement as _, Stateful,
5 Styled as _, Window, div,
6};
7
8use crate::{
9 ActiveTheme as _, Icon, IconName, Size, h_flex,
10 menu::PopupMenu,
11 table::{Column, ColumnSort, TableState, loading::Loading},
12};
13
14/// A delegate trait for providing data and rendering for a table.
15#[allow(unused)]
16pub trait TableDelegate: Sized + 'static {
17 /// Return the number of columns in the table.
18 fn columns_count(&self, cx: &App) -> usize;
19
20 /// Return the number of rows in the table.
21 fn rows_count(&self, cx: &App) -> usize;
22
23 /// Returns the table column at the given index.
24 ///
25 /// This only call on Table prepare or refresh.
26 fn column(&self, col_ix: usize, cx: &App) -> &Column;
27
28 /// Perform sort on the column at the given index.
29 fn perform_sort(
30 &mut self,
31 col_ix: usize,
32 sort: ColumnSort,
33 window: &mut Window,
34 cx: &mut Context<TableState<Self>>,
35 ) {
36 }
37
38 /// Render the table head row.
39 fn render_header(
40 &mut self,
41 window: &mut Window,
42 cx: &mut Context<TableState<Self>>,
43 ) -> Stateful<Div> {
44 div().id("header")
45 }
46
47 /// Render the header cell at the given column index, default to the column name.
48 fn render_th(
49 &mut self,
50 col_ix: usize,
51 window: &mut Window,
52 cx: &mut Context<TableState<Self>>,
53 ) -> impl IntoElement {
54 div()
55 .size_full()
56 .child(self.column(col_ix, cx).name.clone())
57 }
58
59 /// Render the row at the given row and column.
60 ///
61 /// Not include the table head row.
62 fn render_tr(
63 &mut self,
64 row_ix: usize,
65 window: &mut Window,
66 cx: &mut Context<TableState<Self>>,
67 ) -> Stateful<Div> {
68 div().id(("row", row_ix))
69 }
70
71 /// Render the context menu for the row at the given row index.
72 fn context_menu(
73 &mut self,
74 row_ix: usize,
75 menu: PopupMenu,
76 window: &mut Window,
77 cx: &mut Context<TableState<Self>>,
78 ) -> PopupMenu {
79 menu
80 }
81
82 /// Render cell at the given row and column.
83 fn render_td(
84 &mut self,
85 row_ix: usize,
86 col_ix: usize,
87 window: &mut Window,
88 cx: &mut Context<TableState<Self>>,
89 ) -> impl IntoElement;
90
91 /// Move the column at the given `col_ix` to insert before the column at the given `to_ix`.
92 fn move_column(
93 &mut self,
94 col_ix: usize,
95 to_ix: usize,
96 window: &mut Window,
97 cx: &mut Context<TableState<Self>>,
98 ) {
99 }
100
101 /// Return a Element to show when table is empty.
102 fn render_empty(
103 &mut self,
104 window: &mut Window,
105 cx: &mut Context<TableState<Self>>,
106 ) -> impl IntoElement {
107 h_flex()
108 .size_full()
109 .justify_center()
110 .text_color(cx.theme().muted_foreground.opacity(0.6))
111 .child(Icon::new(IconName::Inbox).size_12())
112 .into_any_element()
113 }
114
115 /// Return true to show the loading view.
116 fn loading(&self, cx: &App) -> bool {
117 false
118 }
119
120 /// Return a Element to show when table is loading, default is built-in Skeleton loading view.
121 ///
122 /// The size is the size of the Table.
123 fn render_loading(
124 &mut self,
125 size: Size,
126 window: &mut Window,
127 cx: &mut Context<TableState<Self>>,
128 ) -> impl IntoElement {
129 Loading::new().size(size)
130 }
131
132 /// Return true to enable load more data when scrolling to the bottom.
133 ///
134 /// Default: true
135 fn is_eof(&self, cx: &App) -> bool {
136 true
137 }
138
139 /// Returns a threshold value (n rows), of course, when scrolling to the bottom,
140 /// the remaining number of rows triggers `load_more`.
141 /// This should smaller than the total number of first load rows.
142 ///
143 /// Default: 20 rows
144 fn load_more_threshold(&self) -> usize {
145 20
146 }
147
148 /// Load more data when the table is scrolled to the bottom.
149 ///
150 /// This will performed in a background task.
151 ///
152 /// This is always called when the table is near the bottom,
153 /// so you must check if there is more data to load or lock the loading state.
154 fn load_more(&mut self, window: &mut Window, cx: &mut Context<TableState<Self>>) {}
155
156 /// Render the last empty column, default to empty.
157 fn render_last_empty_col(
158 &mut self,
159 window: &mut Window,
160 cx: &mut Context<TableState<Self>>,
161 ) -> impl IntoElement {
162 h_flex().w_3().h_full().flex_shrink_0()
163 }
164
165 /// Called when the visible range of the rows changed.
166 ///
167 /// NOTE: Make sure this method is fast, because it will be called frequently.
168 ///
169 /// This can used to handle some data update, to only update the visible rows.
170 /// Please ensure that the data is updated in the background task.
171 fn visible_rows_changed(
172 &mut self,
173 visible_range: Range<usize>,
174 window: &mut Window,
175 cx: &mut Context<TableState<Self>>,
176 ) {
177 }
178
179 /// Called when the visible range of the columns changed.
180 ///
181 /// NOTE: Make sure this method is fast, because it will be called frequently.
182 ///
183 /// This can used to handle some data update, to only update the visible rows.
184 /// Please ensure that the data is updated in the background task.
185 fn visible_columns_changed(
186 &mut self,
187 visible_range: Range<usize>,
188 window: &mut Window,
189 cx: &mut Context<TableState<Self>>,
190 ) {
191 }
192}