ui: Use popover menus for tab bar in panes (#16497)
Closes #ISSUE Release Notes: - N/A
This commit is contained in:
parent
72b5cda356
commit
182b7af299
6 changed files with 326 additions and 358 deletions
|
@ -17,9 +17,9 @@ use collections::{BTreeSet, HashMap, HashSet, VecDeque};
|
|||
use futures::{stream::FuturesUnordered, StreamExt};
|
||||
use gpui::{
|
||||
actions, anchored, deferred, impl_actions, prelude::*, Action, AnchorCorner, AnyElement,
|
||||
AppContext, AsyncWindowContext, ClickEvent, ClipboardItem, DismissEvent, Div, DragMoveEvent,
|
||||
EntityId, EventEmitter, ExternalPaths, FocusHandle, FocusOutEvent, FocusableView, KeyContext,
|
||||
Model, MouseButton, MouseDownEvent, NavigationDirection, Pixels, Point, PromptLevel, Render,
|
||||
AppContext, AsyncWindowContext, ClickEvent, ClipboardItem, Div, DragMoveEvent, EntityId,
|
||||
EventEmitter, ExternalPaths, FocusHandle, FocusOutEvent, FocusableView, KeyContext, Model,
|
||||
MouseButton, MouseDownEvent, NavigationDirection, Pixels, Point, PromptLevel, Render,
|
||||
ScrollHandle, Subscription, Task, View, ViewContext, VisualContext, WeakFocusHandle, WeakView,
|
||||
WindowContext,
|
||||
};
|
||||
|
@ -43,7 +43,7 @@ use theme::ThemeSettings;
|
|||
|
||||
use ui::{
|
||||
prelude::*, right_click_menu, ButtonSize, Color, IconButton, IconButtonShape, IconName,
|
||||
IconSize, Indicator, Label, Tab, TabBar, TabPosition, Tooltip,
|
||||
IconSize, Indicator, Label, PopoverMenu, PopoverMenuHandle, Tab, TabBar, TabPosition, Tooltip,
|
||||
};
|
||||
use ui::{v_flex, ContextMenu};
|
||||
use util::{debug_panic, maybe, truncate_and_remove_front, ResultExt};
|
||||
|
@ -250,8 +250,6 @@ pub struct Pane {
|
|||
last_focus_handle_by_item: HashMap<EntityId, WeakFocusHandle>,
|
||||
nav_history: NavHistory,
|
||||
toolbar: View<Toolbar>,
|
||||
pub new_item_menu: Option<View<ContextMenu>>,
|
||||
split_item_menu: Option<View<ContextMenu>>,
|
||||
pub(crate) workspace: WeakView<Workspace>,
|
||||
project: Model<Project>,
|
||||
drag_split_direction: Option<SplitDirection>,
|
||||
|
@ -269,6 +267,8 @@ pub struct Pane {
|
|||
display_nav_history_buttons: Option<bool>,
|
||||
double_click_dispatch_action: Box<dyn Action>,
|
||||
save_modals_spawned: HashSet<EntityId>,
|
||||
pub new_item_context_menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
split_item_context_menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
}
|
||||
|
||||
pub struct ActivationHistoryEntry {
|
||||
|
@ -369,8 +369,6 @@ impl Pane {
|
|||
next_timestamp,
|
||||
}))),
|
||||
toolbar: cx.new_view(|_| Toolbar::new()),
|
||||
new_item_menu: None,
|
||||
split_item_menu: None,
|
||||
tab_bar_scroll_handle: ScrollHandle::new(),
|
||||
drag_split_direction: None,
|
||||
workspace,
|
||||
|
@ -380,7 +378,7 @@ impl Pane {
|
|||
can_split: true,
|
||||
should_display_tab_bar: Rc::new(|cx| TabBarSettings::get_global(cx).show),
|
||||
render_tab_bar_buttons: Rc::new(move |pane, cx| {
|
||||
if !pane.has_focus(cx) {
|
||||
if !pane.has_focus(cx) && !pane.context_menu_focused(cx) {
|
||||
return (None, None);
|
||||
}
|
||||
// Ideally we would return a vec of elements here to pass directly to the [TabBar]'s
|
||||
|
@ -389,10 +387,16 @@ impl Pane {
|
|||
// Instead we need to replicate the spacing from the [TabBar]'s `end_slot` here.
|
||||
.gap(Spacing::Small.rems(cx))
|
||||
.child(
|
||||
IconButton::new("plus", IconName::Plus)
|
||||
.icon_size(IconSize::Small)
|
||||
.on_click(cx.listener(|pane, _, cx| {
|
||||
let menu = ContextMenu::build(cx, |menu, _| {
|
||||
PopoverMenu::new("pane-tab-bar-popover-menu")
|
||||
.trigger(
|
||||
IconButton::new("plus", IconName::Plus)
|
||||
.icon_size(IconSize::Small)
|
||||
.tooltip(|cx| Tooltip::text("New...", cx)),
|
||||
)
|
||||
.anchor(AnchorCorner::TopRight)
|
||||
.with_handle(pane.new_item_context_menu_handle.clone())
|
||||
.menu(move |cx| {
|
||||
Some(ContextMenu::build(cx, |menu, _| {
|
||||
menu.action("New File", NewFile.boxed_clone())
|
||||
.action(
|
||||
"Open File",
|
||||
|
@ -412,37 +416,27 @@ impl Pane {
|
|||
)
|
||||
.separator()
|
||||
.action("New Terminal", NewTerminal.boxed_clone())
|
||||
});
|
||||
cx.subscribe(&menu, |pane, _, _: &DismissEvent, cx| {
|
||||
pane.focus(cx);
|
||||
pane.new_item_menu = None;
|
||||
})
|
||||
.detach();
|
||||
pane.new_item_menu = Some(menu);
|
||||
}))
|
||||
.tooltip(|cx| Tooltip::text("New...", cx)),
|
||||
}))
|
||||
}),
|
||||
)
|
||||
.when_some(pane.new_item_menu.as_ref(), |el, new_item_menu| {
|
||||
el.child(Self::render_menu_overlay(new_item_menu))
|
||||
})
|
||||
.child(
|
||||
IconButton::new("split", IconName::Split)
|
||||
.icon_size(IconSize::Small)
|
||||
.on_click(cx.listener(|pane, _, cx| {
|
||||
let menu = ContextMenu::build(cx, |menu, _| {
|
||||
PopoverMenu::new("pane-tab-bar-split")
|
||||
.trigger(
|
||||
IconButton::new("split", IconName::Split)
|
||||
.icon_size(IconSize::Small)
|
||||
.tooltip(|cx| Tooltip::text("Split Pane", cx)),
|
||||
)
|
||||
.anchor(AnchorCorner::TopRight)
|
||||
.with_handle(pane.split_item_context_menu_handle.clone())
|
||||
.menu(move |cx| {
|
||||
ContextMenu::build(cx, |menu, _| {
|
||||
menu.action("Split Right", SplitRight.boxed_clone())
|
||||
.action("Split Left", SplitLeft.boxed_clone())
|
||||
.action("Split Up", SplitUp.boxed_clone())
|
||||
.action("Split Down", SplitDown.boxed_clone())
|
||||
});
|
||||
cx.subscribe(&menu, |pane, _, _: &DismissEvent, cx| {
|
||||
pane.focus(cx);
|
||||
pane.split_item_menu = None;
|
||||
})
|
||||
.detach();
|
||||
pane.split_item_menu = Some(menu);
|
||||
}))
|
||||
.tooltip(|cx| Tooltip::text("Split Pane", cx)),
|
||||
.into()
|
||||
}),
|
||||
)
|
||||
.child({
|
||||
let zoomed = pane.is_zoomed();
|
||||
|
@ -461,9 +455,6 @@ impl Pane {
|
|||
)
|
||||
})
|
||||
})
|
||||
.when_some(pane.split_item_menu.as_ref(), |el, split_item_menu| {
|
||||
el.child(Self::render_menu_overlay(split_item_menu))
|
||||
})
|
||||
.into_any_element()
|
||||
.into();
|
||||
(None, right_children)
|
||||
|
@ -474,6 +465,8 @@ impl Pane {
|
|||
_subscriptions: subscriptions,
|
||||
double_click_dispatch_action,
|
||||
save_modals_spawned: HashSet::default(),
|
||||
split_item_context_menu_handle: Default::default(),
|
||||
new_item_context_menu_handle: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -557,11 +550,9 @@ impl Pane {
|
|||
}
|
||||
}
|
||||
|
||||
fn context_menu_focused(&self, cx: &mut ViewContext<Self>) -> bool {
|
||||
self.new_item_menu
|
||||
.as_ref()
|
||||
.or(self.split_item_menu.as_ref())
|
||||
.map_or(false, |menu| menu.focus_handle(cx).is_focused(cx))
|
||||
pub fn context_menu_focused(&self, cx: &mut ViewContext<Self>) -> bool {
|
||||
self.new_item_context_menu_handle.is_focused(cx)
|
||||
|| self.split_item_context_menu_handle.is_focused(cx)
|
||||
}
|
||||
|
||||
fn focus_out(&mut self, _event: FocusOutEvent, cx: &mut ViewContext<Self>) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue