popover_menu.rs

 1use gpui::{
 2    AnyView, Corner, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Subscription,
 3};
 4use ui::{
 5    App, ButtonCommon, FluentBuilder as _, IntoElement, PopoverMenu, PopoverMenuHandle,
 6    PopoverTrigger, RenderOnce, Window, px,
 7};
 8
 9use crate::{Picker, PickerDelegate};
10
11pub struct PickerPopoverMenu<T, TT, P>
12where
13    T: PopoverTrigger + ButtonCommon,
14    TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
15    P: PickerDelegate,
16{
17    picker: Entity<Picker<P>>,
18    trigger: T,
19    tooltip: TT,
20    handle: Option<PopoverMenuHandle<Picker<P>>>,
21    anchor: Corner,
22    _subscriptions: Vec<Subscription>,
23}
24
25impl<T, TT, P> PickerPopoverMenu<T, TT, P>
26where
27    T: PopoverTrigger + ButtonCommon,
28    TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
29    P: PickerDelegate,
30{
31    pub fn new(
32        picker: Entity<Picker<P>>,
33        trigger: T,
34        tooltip: TT,
35        anchor: Corner,
36        cx: &mut App,
37    ) -> Self {
38        Self {
39            _subscriptions: vec![cx.subscribe(&picker, |picker, &DismissEvent, cx| {
40                picker.update(cx, |_, cx| cx.emit(DismissEvent));
41            })],
42            picker,
43            trigger,
44            tooltip,
45            handle: None,
46            anchor,
47        }
48    }
49
50    pub fn with_handle(mut self, handle: PopoverMenuHandle<Picker<P>>) -> Self {
51        self.handle = Some(handle);
52        self
53    }
54}
55
56impl<T, TT, P> EventEmitter<DismissEvent> for PickerPopoverMenu<T, TT, P>
57where
58    T: PopoverTrigger + ButtonCommon,
59    TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
60    P: PickerDelegate,
61{
62}
63
64impl<T, TT, P> Focusable for PickerPopoverMenu<T, TT, P>
65where
66    T: PopoverTrigger + ButtonCommon,
67    TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
68    P: PickerDelegate,
69{
70    fn focus_handle(&self, cx: &App) -> FocusHandle {
71        self.picker.focus_handle(cx)
72    }
73}
74
75impl<T, TT, P> RenderOnce for PickerPopoverMenu<T, TT, P>
76where
77    T: PopoverTrigger + ButtonCommon,
78    TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
79    P: PickerDelegate,
80{
81    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
82        let picker = self.picker.clone();
83
84        PopoverMenu::new("popover-menu")
85            .menu(move |_window, _cx| Some(picker.clone()))
86            .trigger_with_tooltip(self.trigger, self.tooltip)
87            .anchor(self.anchor)
88            .when_some(self.handle, |menu, handle| menu.with_handle(handle))
89            .offset(gpui::Point {
90                x: px(0.0),
91                y: px(-2.0),
92            })
93    }
94}