Cargo.lock 🔗
@@ -6088,6 +6088,7 @@ dependencies = [
"collections",
"command_palette",
"contacts_panel",
+ "context_menu",
"ctor",
"diagnostics",
"dirs 3.0.1",
Antonio Scandurra created
Cargo.lock | 1
crates/context_menu/src/context_menu.rs | 51 +++++++++++++++++++-------
crates/gpui/src/app.rs | 2
crates/zed/Cargo.toml | 1
crates/zed/src/main.rs | 1
5 files changed, 41 insertions(+), 15 deletions(-)
@@ -6088,6 +6088,7 @@ dependencies = [
"collections",
"command_palette",
"contacts_panel",
+ "context_menu",
"ctor",
"diagnostics",
"dirs 3.0.1",
@@ -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");
- self.items = items.collect();
- self.position = position;
- self.visible = true;
- cx.focus_self();
+ 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()
@@ -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);
}
@@ -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" }
@@ -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);