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}