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}