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}