Restore focus when closing context menu

This commit is contained in:
Antonio Scandurra 2022-05-26 15:21:02 +02:00
parent a5044ccbba
commit 82ddac8e7e
5 changed files with 41 additions and 15 deletions

1
Cargo.lock generated
View file

@ -6088,6 +6088,7 @@ dependencies = [
"collections",
"command_palette",
"contacts_panel",
"context_menu",
"ctor",
"diagnostics",
"dirs 3.0.1",

View file

@ -1,9 +1,18 @@
use gpui::{
elements::*, geometry::vector::Vector2F, platform::CursorStyle, Action, Axis, Entity,
RenderContext, SizeConstraint, View, ViewContext,
elements::*, geometry::vector::Vector2F, impl_internal_actions, platform::CursorStyle, Action,
Axis, Entity, MutableAppContext, RenderContext, SizeConstraint, View, ViewContext,
};
use settings::Settings;
pub fn init(cx: &mut MutableAppContext) {
cx.add_action(ContextMenu::dismiss);
}
#[derive(Clone)]
struct Dismiss;
impl_internal_actions!(context_menu, [Dismiss]);
pub enum ContextMenuItem {
Item {
label: String,
@ -25,11 +34,13 @@ impl ContextMenuItem {
}
}
#[derive(Default)]
pub struct ContextMenu {
position: Vector2F,
items: Vec<ContextMenuItem>,
selected_index: Option<usize>,
visible: bool,
previously_focused_view_id: Option<usize>,
}
impl Entity for ContextMenu {
@ -72,11 +83,13 @@ impl View for ContextMenu {
impl ContextMenu {
pub fn new() -> Self {
Self {
position: Default::default(),
items: Default::default(),
selected_index: Default::default(),
visible: false,
Default::default()
}
fn dismiss(&mut self, _: &Dismiss, cx: &mut ViewContext<Self>) {
if cx.handle().is_focused(cx) {
let window_id = cx.window_id();
(**cx).focus(window_id, self.previously_focused_view_id.take());
}
}
@ -87,11 +100,15 @@ impl ContextMenu {
cx: &mut ViewContext<Self>,
) {
let mut items = items.into_iter().peekable();
assert!(items.peek().is_some(), "must have at least one item");
if items.peek().is_some() {
self.items = items.collect();
self.position = position;
self.visible = true;
self.previously_focused_view_id = cx.focused_view_id(cx.window_id());
cx.focus_self();
} else {
self.visible = false;
}
cx.notify();
}
@ -107,7 +124,10 @@ impl ContextMenu {
&Default::default(),
Some(ix) == self.selected_index,
);
Label::new(label.to_string(), style.label.clone()).boxed()
Label::new(label.to_string(), style.label.clone())
.contained()
.with_style(style.container)
.boxed()
}
ContextMenuItem::Separator => Empty::new()
.collapsed()
@ -180,7 +200,10 @@ impl ContextMenu {
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(move |_, _, cx| cx.dispatch_any_action(action.boxed_clone()))
.on_click(move |_, _, cx| {
cx.dispatch_any_action(action.boxed_clone());
cx.dispatch_action(Dismiss);
})
.boxed()
}
ContextMenuItem::Separator => Empty::new()

View file

@ -2407,7 +2407,7 @@ impl MutableAppContext {
})
}
fn focus(&mut self, window_id: usize, view_id: Option<usize>) {
pub fn focus(&mut self, window_id: usize, view_id: Option<usize>) {
if let Some(pending_focus_index) = self.pending_focus_index {
self.pending_effects.remove(pending_focus_index);
}

View file

@ -22,6 +22,7 @@ chat_panel = { path = "../chat_panel" }
cli = { path = "../cli" }
collections = { path = "../collections" }
command_palette = { path = "../command_palette" }
context_menu = { path = "../context_menu" }
client = { path = "../client" }
clock = { path = "../clock" }
contacts_panel = { path = "../contacts_panel" }

View file

@ -134,6 +134,7 @@ fn main() {
let mut languages = languages::build_language_registry(login_shell_env_loaded);
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http.clone(), cx));
context_menu::init(cx);
auto_update::init(http, client::ZED_SERVER_URL.clone(), cx);
project::Project::init(&client);
client::Channel::init(&client);