head.rs

 1use std::sync::Arc;
 2
 3use gpui::{App, Entity, FocusHandle, Focusable, prelude::*};
 4use ui::prelude::*;
 5use ui_input::{ErasedEditor, ErasedEditorEvent};
 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(Arc<dyn ErasedEditor>),
11
12    /// Picker has no head, it's just a list of items.
13    Empty(Entity<EmptyHead>),
14}
15
16impl Head {
17    pub fn editor<V: 'static>(
18        placeholder_text: Arc<str>,
19        mut edit_handler: impl FnMut(&mut V, &ErasedEditorEvent, &mut Window, &mut Context<V>) + 'static,
20        window: &mut Window,
21        cx: &mut Context<V>,
22    ) -> Self {
23        let editor = (ui_input::ERASED_EDITOR_FACTORY.get().unwrap())(window, cx);
24
25        editor.set_placeholder_text(placeholder_text.as_ref(), window, cx);
26        let this = cx.weak_entity();
27        editor
28            .subscribe(
29                Box::new(move |event, window, cx| {
30                    this.update(cx, |this, cx| (edit_handler)(this, &event, window, cx))
31                        .ok();
32                }),
33                window,
34                cx,
35            )
36            .detach();
37        // cx.subscribe_in(&editor, window, |v, _, event, window, cx| {
38        //     edit_handler(v, event, window, cx);
39        // })
40        // .detach();
41        Self::Editor(editor)
42    }
43
44    pub fn empty<V: 'static>(
45        blur_handler: impl FnMut(&mut V, &mut Window, &mut Context<V>) + 'static,
46        window: &mut Window,
47        cx: &mut Context<V>,
48    ) -> Self {
49        let head = cx.new(EmptyHead::new);
50        cx.on_blur(&head.focus_handle(cx), window, blur_handler)
51            .detach();
52        Self::Empty(head)
53    }
54}
55
56/// An invisible element that can hold focus.
57pub(crate) struct EmptyHead {
58    focus_handle: FocusHandle,
59}
60
61impl EmptyHead {
62    fn new(cx: &mut Context<Self>) -> Self {
63        Self {
64            focus_handle: cx.focus_handle(),
65        }
66    }
67}
68
69impl Render for EmptyHead {
70    fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
71        div().track_focus(&self.focus_handle(cx))
72    }
73}
74
75impl Focusable for EmptyHead {
76    fn focus_handle(&self, _: &App) -> FocusHandle {
77        self.focus_handle.clone()
78    }
79}