gpui_component/list/
delegate.rs

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