Allow to reuse PickerPopoverMenu outside of the model selector (#31684)

LSP button preparation step: move out the component that will be used to
build the button's context menu.

Release Notes:

- N/A
This commit is contained in:
Kirill Bulatov 2025-05-29 15:55:47 +03:00 committed by GitHub
parent 45f9edcbb9
commit f792827a01
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 243 additions and 235 deletions

View file

@ -1,3 +1,7 @@
mod head;
pub mod highlighted_match_with_paths;
pub mod popover_menu;
use anyhow::Result;
use editor::{
Editor,
@ -20,9 +24,6 @@ use ui::{
use util::ResultExt;
use workspace::ModalView;
mod head;
pub mod highlighted_match_with_paths;
enum ElementContainer {
List(ListState),
UniformList(UniformListScrollHandle),

View file

@ -0,0 +1,93 @@
use gpui::{
AnyView, Corner, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Subscription,
};
use ui::{
App, ButtonCommon, FluentBuilder as _, IntoElement, PopoverMenu, PopoverMenuHandle,
PopoverTrigger, RenderOnce, Window, px,
};
use crate::{Picker, PickerDelegate};
pub struct PickerPopoverMenu<T, TT, P>
where
T: PopoverTrigger + ButtonCommon,
TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
P: PickerDelegate,
{
picker: Entity<Picker<P>>,
trigger: T,
tooltip: TT,
handle: Option<PopoverMenuHandle<Picker<P>>>,
anchor: Corner,
_subscriptions: Vec<Subscription>,
}
impl<T, TT, P> PickerPopoverMenu<T, TT, P>
where
T: PopoverTrigger + ButtonCommon,
TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
P: PickerDelegate,
{
pub fn new(
picker: Entity<Picker<P>>,
trigger: T,
tooltip: TT,
anchor: Corner,
cx: &mut App,
) -> Self {
Self {
_subscriptions: vec![cx.subscribe(&picker, |picker, &DismissEvent, cx| {
picker.update(cx, |_, cx| cx.emit(DismissEvent));
})],
picker,
trigger,
tooltip,
handle: None,
anchor,
}
}
pub fn with_handle(mut self, handle: PopoverMenuHandle<Picker<P>>) -> Self {
self.handle = Some(handle);
self
}
}
impl<T, TT, P> EventEmitter<DismissEvent> for PickerPopoverMenu<T, TT, P>
where
T: PopoverTrigger + ButtonCommon,
TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
P: PickerDelegate,
{
}
impl<T, TT, P> Focusable for PickerPopoverMenu<T, TT, P>
where
T: PopoverTrigger + ButtonCommon,
TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
P: PickerDelegate,
{
fn focus_handle(&self, cx: &App) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
impl<T, TT, P> RenderOnce for PickerPopoverMenu<T, TT, P>
where
T: PopoverTrigger + ButtonCommon,
TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
P: PickerDelegate,
{
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let picker = self.picker.clone();
PopoverMenu::new("popover-menu")
.menu(move |_window, _cx| Some(picker.clone()))
.trigger_with_tooltip(self.trigger, self.tooltip)
.anchor(self.anchor)
.when_some(self.handle.clone(), |menu, handle| menu.with_handle(handle))
.offset(gpui::Point {
x: px(0.0),
y: px(-2.0),
})
}
}