head.rs

 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}