popover_button.rs

 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}