Skip to main content

gpui_component/list/
delegate.rs

1use gpui::{AnyElement, App, Context, IntoElement, ParentElement as _, Styled as _, Task, Window};
2
3use crate::{
4    ActiveTheme as _, Icon, IconName, IndexPath, Selectable, h_flex,
5    list::{ListState, loading::Loading},
6};
7
8/// A delegate for the List.
9#[allow(unused)]
10pub trait ListDelegate: Sized + 'static {
11    type Item: Selectable + IntoElement;
12
13    /// When Query Input change, this method will be called.
14    /// You can perform search here.
15    fn perform_search(
16        &mut self,
17        query: &str,
18        window: &mut Window,
19        cx: &mut Context<ListState<Self>>,
20    ) -> Task<()> {
21        Task::ready(())
22    }
23
24    /// Return the number of sections in the list, default is 1.
25    ///
26    /// Min value is 1.
27    fn sections_count(&self, cx: &App) -> usize {
28        1
29    }
30
31    /// Return the number of items in the section at the given index.
32    ///
33    /// NOTE: Only the sections with items_count > 0 will be rendered. If the section has 0 items,
34    /// the section header and footer will also be skipped.
35    fn items_count(&self, section: usize, cx: &App) -> usize;
36
37    /// Render the item at the given index.
38    ///
39    /// Return None will skip the item.
40    ///
41    /// NOTE: Every item should have same height.
42    fn render_item(
43        &mut self,
44        ix: IndexPath,
45        window: &mut Window,
46        cx: &mut Context<ListState<Self>>,
47    ) -> Option<Self::Item>;
48
49    /// Render the section header at the given index, default is None.
50    ///
51    /// NOTE: Every header should have same height.
52    fn render_section_header(
53        &mut self,
54        section: usize,
55        window: &mut Window,
56        cx: &mut Context<ListState<Self>>,
57    ) -> Option<impl IntoElement> {
58        None::<AnyElement>
59    }
60
61    /// Render the section footer at the given index, default is None.
62    ///
63    /// NOTE: Every footer should have same height.
64    fn render_section_footer(
65        &mut self,
66        section: usize,
67        window: &mut Window,
68        cx: &mut Context<ListState<Self>>,
69    ) -> Option<impl IntoElement> {
70        None::<AnyElement>
71    }
72
73    /// Return a Element to show when list is empty.
74    fn render_empty(
75        &mut self,
76        window: &mut Window,
77        cx: &mut Context<ListState<Self>>,
78    ) -> impl IntoElement {
79        h_flex()
80            .size_full()
81            .justify_center()
82            .text_color(cx.theme().muted_foreground.opacity(0.6))
83            .child(Icon::new(IconName::Inbox).size_12())
84            .into_any_element()
85    }
86
87    /// Returns Some(AnyElement) to render the initial state of the list.
88    ///
89    /// This can be used to show a view for the list before the user has
90    /// interacted with it.
91    ///
92    /// For example: The last search results, or the last selected item.
93    ///
94    /// Default is None, that means no initial state.
95    fn render_initial(
96        &mut self,
97        window: &mut Window,
98        cx: &mut Context<ListState<Self>>,
99    ) -> Option<AnyElement> {
100        None
101    }
102
103    /// Returns the loading state to show the loading view.
104    fn loading(&self, cx: &App) -> bool {
105        false
106    }
107
108    /// Returns a Element to show when loading, default is built-in Skeleton
109    /// loading view.
110    fn render_loading(
111        &mut self,
112        window: &mut Window,
113        cx: &mut Context<ListState<Self>>,
114    ) -> impl IntoElement {
115        Loading
116    }
117
118    /// Set the selected index, just store the ix, don't confirm.
119    fn set_selected_index(
120        &mut self,
121        ix: Option<IndexPath>,
122        window: &mut Window,
123        cx: &mut Context<ListState<Self>>,
124    );
125
126    /// Set the index of the item that has been right clicked.
127    fn set_right_clicked_index(
128        &mut self,
129        ix: Option<IndexPath>,
130        window: &mut Window,
131        cx: &mut Context<ListState<Self>>,
132    ) {
133    }
134
135    /// Set the confirm and give the selected index,
136    /// this is means user have clicked the item or pressed Enter.
137    ///
138    /// This will always to `set_selected_index` before confirm.
139    fn confirm(&mut self, secondary: bool, window: &mut Window, cx: &mut Context<ListState<Self>>) {
140    }
141
142    /// Cancel the selection, e.g.: Pressed ESC.
143    fn cancel(&mut self, window: &mut Window, cx: &mut Context<ListState<Self>>) {}
144
145    /// Return true to enable load more data when scrolling to the bottom.
146    ///
147    /// Default: false
148    fn has_more(&self, cx: &App) -> bool {
149        false
150    }
151
152    /// Returns a threshold value (n entities), of course,
153    /// when scrolling to the bottom, the remaining number of rows
154    /// triggers `load_more`.
155    ///
156    /// This should smaller than the total number of first load rows.
157    ///
158    /// Default: 20 entities (section header, footer and row)
159    fn load_more_threshold(&self) -> usize {
160        20
161    }
162
163    /// Load more data when the table is scrolled to the bottom.
164    ///
165    /// This will performed in a background task.
166    ///
167    /// This is always called when the table is near the bottom,
168    /// so you must check if there is more data to load or lock
169    /// the loading state.
170    fn load_more(&mut self, window: &mut Window, cx: &mut Context<ListState<Self>>) {}
171}