1use std::sync::Arc;
2
3use editor::{Editor, EditorEvent};
4use gpui::{prelude::*, AppContext, FocusHandle, FocusableView, View};
5use ui::prelude::*;
6
7/// The head of a [`Picker`](crate::Picker).
8pub(crate) enum Head {
9 /// Picker has an editor that allows the user to filter the list.
10 Editor(View<Editor>),
11
12 /// Picker has no head, it's just a list of items.
13 Empty(View<EmptyHead>),
14}
15
16impl Head {
17 pub fn editor<V: 'static>(
18 placeholder_text: Arc<str>,
19 edit_handler: impl FnMut(&mut V, View<Editor>, &EditorEvent, &mut ViewContext<V>) + 'static,
20 cx: &mut ViewContext<V>,
21 ) -> Self {
22 let editor = cx.new_view(|cx| {
23 let mut editor = Editor::single_line(cx);
24 editor.set_placeholder_text(placeholder_text, cx);
25 editor
26 });
27 cx.subscribe(&editor, edit_handler).detach();
28 Self::Editor(editor)
29 }
30
31 pub fn empty<V: 'static>(
32 blur_handler: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
33 cx: &mut ViewContext<V>,
34 ) -> Self {
35 let head = cx.new_view(EmptyHead::new);
36 cx.on_blur(&head.focus_handle(cx), blur_handler).detach();
37 Self::Empty(head)
38 }
39}
40
41/// An invisible element that can hold focus.
42pub(crate) struct EmptyHead {
43 focus_handle: FocusHandle,
44}
45
46impl EmptyHead {
47 fn new(cx: &mut ViewContext<Self>) -> Self {
48 Self {
49 focus_handle: cx.focus_handle(),
50 }
51 }
52}
53
54impl Render for EmptyHead {
55 fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
56 div().track_focus(&self.focus_handle(cx))
57 }
58}
59
60impl FocusableView for EmptyHead {
61 fn focus_handle(&self, _: &AppContext) -> FocusHandle {
62 self.focus_handle.clone()
63 }
64}