1use gpui::{AnyView, Corner, Entity, ManagedView};
2
3use crate::{prelude::*, PopoverMenu, PopoverMenuHandle, PopoverTrigger};
4
5pub trait TriggerablePopover: ManagedView {
6 fn menu_handle(
7 &mut self,
8 window: &mut Window,
9 cx: &mut gpui::Context<Self>,
10 ) -> PopoverMenuHandle<Self>;
11}
12
13pub struct PopoverButton<T, B, F> {
14 selector: Entity<T>,
15 button: B,
16 tooltip: F,
17 corner: Corner,
18}
19
20impl<T, B, F> PopoverButton<T, B, F> {
21 pub fn new(selector: Entity<T>, corner: Corner, button: B, tooltip: F) -> Self
22 where
23 F: Fn(&mut Window, &mut App) -> AnyView + 'static,
24 {
25 Self {
26 selector,
27 button,
28 tooltip,
29 corner,
30 }
31 }
32}
33
34impl<T: TriggerablePopover, B: PopoverTrigger + ButtonCommon, F> RenderOnce
35 for PopoverButton<T, B, F>
36where
37 F: Fn(&mut Window, &mut App) -> AnyView + 'static,
38{
39 fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
40 let menu_handle = self
41 .selector
42 .update(cx, |selector, cx| selector.menu_handle(window, cx));
43
44 PopoverMenu::new("popover-button")
45 .menu({
46 let selector = self.selector.clone();
47 move |_window, _cx| Some(selector.clone())
48 })
49 .trigger_with_tooltip(self.button, self.tooltip)
50 .anchor(self.corner)
51 .with_handle(menu_handle)
52 .offset(gpui::Point {
53 x: px(0.0),
54 y: px(-2.0),
55 })
56 }
57}