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    fn sections_count(&self, cx: &App) -> usize {
26        1
27    }
28
29    /// Return the number of items in the section at the given index.
30    fn items_count(&self, section: usize, cx: &App) -> usize;
31
32    /// Render the item at the given index.
33    ///
34    /// Return None will skip the item.
35    ///
36    /// NOTE: Every item should have same height.
37    fn render_item(
38        &mut self,
39        ix: IndexPath,
40        window: &mut Window,
41        cx: &mut Context<ListState<Self>>,
42    ) -> Option<Self::Item>;
43
44    /// Render the section header at the given index, default is None.
45    ///
46    /// NOTE: Every header should have same height.
47    fn render_section_header(
48        &mut self,
49        section: usize,
50        window: &mut Window,
51        cx: &mut Context<ListState<Self>>,
52    ) -> Option<impl IntoElement> {
53        None::<AnyElement>
54    }
55
56    /// Render the section footer at the given index, default is None.
57    ///
58    /// NOTE: Every footer should have same height.
59    fn render_section_footer(
60        &mut self,
61        section: usize,
62        window: &mut Window,
63        cx: &mut Context<ListState<Self>>,
64    ) -> Option<impl IntoElement> {
65        None::<AnyElement>
66    }
67
68    /// Return a Element to show when list is empty.
69    fn render_empty(
70        &mut self,
71        window: &mut Window,
72        cx: &mut Context<ListState<Self>>,
73    ) -> impl IntoElement {
74        h_flex()
75            .size_full()
76            .justify_center()
77            .text_color(cx.theme().muted_foreground.opacity(0.6))
78            .child(Icon::new(IconName::Inbox).size_12())
79            .into_any_element()
80    }
81
82    /// Returns Some(AnyElement) to render the initial state of the list.
83    ///
84    /// This can be used to show a view for the list before the user has
85    /// interacted with it.
86    ///
87    /// For example: The last search results, or the last selected item.
88    ///
89    /// Default is None, that means no initial state.
90    fn render_initial(
91        &mut self,
92        window: &mut Window,
93        cx: &mut Context<ListState<Self>>,
94    ) -> Option<AnyElement> {
95        None
96    }
97
98    /// Returns the loading state to show the loading view.
99    fn loading(&self, cx: &App) -> bool {
100        false
101    }
102
103    /// Returns a Element to show when loading, default is built-in Skeleton
104    /// loading view.
105    fn render_loading(
106        &mut self,
107        window: &mut Window,
108        cx: &mut Context<ListState<Self>>,
109    ) -> impl IntoElement {
110        Loading
111    }
112
113    /// Set the selected index, just store the ix, don't confirm.
114    fn set_selected_index(
115        &mut self,
116        ix: Option<IndexPath>,
117        window: &mut Window,
118        cx: &mut Context<ListState<Self>>,
119    );
120
121    /// Set the confirm and give the selected index,
122    /// this is means user have clicked the item or pressed Enter.
123    ///
124    /// This will always to `set_selected_index` before confirm.
125    fn confirm(&mut self, secondary: bool, window: &mut Window, cx: &mut Context<ListState<Self>>) {
126    }
127
128    /// Cancel the selection, e.g.: Pressed ESC.
129    fn cancel(&mut self, window: &mut Window, cx: &mut Context<ListState<Self>>) {}
130
131    /// Return true to enable load more data when scrolling to the bottom.
132    ///
133    /// Default: true
134    fn is_eof(&self, cx: &App) -> bool {
135        true
136    }
137
138    /// Returns a threshold value (n entities), of course,
139    /// when scrolling to the bottom, the remaining number of rows
140    /// triggers `load_more`.
141    ///
142    /// This should smaller than the total number of first load rows.
143    ///
144    /// Default: 20 entities (section header, footer and row)
145    fn load_more_threshold(&self) -> usize {
146        20
147    }
148
149    /// Load more data when the table is scrolled to the bottom.
150    ///
151    /// This will performed in a background task.
152    ///
153    /// This is always called when the table is near the bottom,
154    /// so you must check if there is more data to load or lock
155    /// the loading state.
156    fn load_more(&mut self, window: &mut Window, cx: &mut Context<ListState<Self>>) {}
157}