diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index ae763f2ea0..c7141fe587 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -63,6 +63,7 @@ use language::{ use lazy_static::lazy_static; use link_go_to_definition::{GoToDefinitionLink, InlayHighlight, LinkGoToDefinitionState}; use lsp::{DiagnosticSeverity, LanguageServerId}; +use mouse_context_menu::MouseContextMenu; use movement::TextLayoutDetails; use multi_buffer::ToOffsetUtf16; pub use multi_buffer::{ @@ -505,8 +506,6 @@ pub struct Editor { ime_transaction: Option, active_diagnostics: Option, soft_wrap_mode_override: Option, - // get_field_editor_theme: Option>, - // override_text_style: Option>, project: Option>, collaboration_hub: Option>, blink_manager: Model, @@ -520,7 +519,7 @@ pub struct Editor { inlay_background_highlights: TreeMap, InlayBackgroundHighlight>, nav_history: Option, context_menu: RwLock>, - // mouse_context_menu: View, + mouse_context_menu: Option, completion_tasks: Vec<(CompletionId, Task>)>, next_completion_id: CompletionId, available_code_actions: Option<(Model, Arc<[CodeAction]>)>, @@ -1719,7 +1718,6 @@ impl Editor { ime_transaction: Default::default(), active_diagnostics: None, soft_wrap_mode_override, - // get_field_editor_theme, collaboration_hub: project.clone().map(|project| Box::new(project) as _), project, blink_manager: blink_manager.clone(), @@ -1733,8 +1731,7 @@ impl Editor { inlay_background_highlights: Default::default(), nav_history: None, context_menu: RwLock::new(None), - // mouse_context_menu: cx - // .add_view(|cx| context_menu::ContextMenu::new(editor_view_id, cx)), + mouse_context_menu: None, completion_tasks: Default::default(), next_completion_id: 0, next_inlay_id: 0, @@ -1743,7 +1740,6 @@ impl Editor { document_highlights_task: Default::default(), pending_rename: Default::default(), searchable: true, - // override_text_style: None, cursor_shape: Default::default(), autoindent_mode: Some(AutoindentMode::EachLine), collapse_matches: false, diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 76bdebac44..3abe5a37f9 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -13,6 +13,7 @@ use crate::{ update_go_to_definition_link, update_inlay_link_and_hover_points, GoToDefinitionTrigger, LinkGoToDefinitionState, }, + mouse_context_menu, scroll::scroll_amount::ScrollAmount, CursorShape, DisplayPoint, Editor, EditorMode, EditorSettings, EditorSnapshot, EditorStyle, HalfPageDown, HalfPageUp, LineDown, LineUp, MoveDown, OpenExcerpts, PageDown, PageUp, Point, @@ -22,11 +23,11 @@ use anyhow::Result; use collections::{BTreeMap, HashMap}; use git::diff::DiffHunkStatus; use gpui::{ - div, point, px, relative, size, transparent_black, Action, AnyElement, AsyncWindowContext, - AvailableSpace, BorrowWindow, Bounds, ContentMask, Corners, CursorStyle, DispatchPhase, Edges, - Element, ElementId, ElementInputHandler, Entity, EntityId, Hsla, InteractiveBounds, - InteractiveElement, IntoElement, LineLayout, ModifiersChangedEvent, MouseButton, - MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, RenderOnce, + div, overlay, point, px, relative, size, transparent_black, Action, AnchorCorner, AnyElement, + AsyncWindowContext, AvailableSpace, BorrowWindow, Bounds, ContentMask, Corners, CursorStyle, + DispatchPhase, Edges, Element, ElementId, ElementInputHandler, Entity, EntityId, Hsla, + InteractiveBounds, InteractiveElement, IntoElement, LineLayout, ModifiersChangedEvent, + MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, RenderOnce, ScrollWheelEvent, ShapedLine, SharedString, Size, StackingOrder, StatefulInteractiveElement, Style, Styled, TextRun, TextStyle, View, ViewContext, WeakView, WindowContext, WrappedLine, }; @@ -362,7 +363,7 @@ impl EditorElement { false } - fn mouse_down( + fn mouse_left_down( editor: &mut Editor, event: &MouseDownEvent, position_map: &PositionMap, @@ -415,25 +416,25 @@ impl EditorElement { true } - // fn mouse_right_down( - // editor: &mut Editor, - // position: gpui::Point, - // position_map: &PositionMap, - // text_bounds: Bounds, - // cx: &mut EventContext, - // ) -> bool { - // if !text_bounds.contains_point(position) { - // return false; - // } - // let point_for_position = position_map.point_for_position(text_bounds, position); - // mouse_context_menu::deploy_context_menu( - // editor, - // position, - // point_for_position.previous_valid, - // cx, - // ); - // true - // } + fn mouse_right_down( + editor: &mut Editor, + event: &MouseDownEvent, + position_map: &PositionMap, + text_bounds: Bounds, + cx: &mut ViewContext, + ) -> bool { + if !text_bounds.contains_point(&event.position) { + return false; + } + let point_for_position = position_map.point_for_position(text_bounds, event.position); + mouse_context_menu::deploy_context_menu( + editor, + event.position, + point_for_position.previous_valid, + cx, + ); + true + } fn mouse_up( editor: &mut Editor, @@ -1190,6 +1191,22 @@ impl EditorElement { } } } + + if let Some(mouse_context_menu) = + self.editor.read(cx).mouse_context_menu.as_ref() + { + let element = overlay() + .position(mouse_context_menu.position) + .child(mouse_context_menu.context_menu.clone()) + .anchor(AnchorCorner::TopLeft) + .snap_to_window(); + element.draw( + gpui::Point::default(), + size(AvailableSpace::MinContent, AvailableSpace::MinContent), + cx, + |_, _| {}, + ); + } }) }, ) @@ -2337,10 +2354,10 @@ impl EditorElement { return; } - let should_cancel = editor.update(cx, |editor, cx| { + let handled = editor.update(cx, |editor, cx| { Self::scroll(editor, event, &position_map, &interactive_bounds, cx) }); - if should_cancel { + if handled { cx.stop_propagation(); } } @@ -2356,19 +2373,25 @@ impl EditorElement { return; } - let should_cancel = editor.update(cx, |editor, cx| { - Self::mouse_down( - editor, - event, - &position_map, - text_bounds, - gutter_bounds, - &stacking_order, - cx, - ) - }); + let handled = match event.button { + MouseButton::Left => editor.update(cx, |editor, cx| { + Self::mouse_left_down( + editor, + event, + &position_map, + text_bounds, + gutter_bounds, + &stacking_order, + cx, + ) + }), + MouseButton::Right => editor.update(cx, |editor, cx| { + Self::mouse_right_down(editor, event, &position_map, text_bounds, cx) + }), + _ => false, + }; - if should_cancel { + if handled { cx.stop_propagation() } } @@ -2380,7 +2403,7 @@ impl EditorElement { let stacking_order = cx.stacking_order().clone(); move |event: &MouseUpEvent, phase, cx| { - let should_cancel = editor.update(cx, |editor, cx| { + let handled = editor.update(cx, |editor, cx| { Self::mouse_up( editor, event, @@ -2391,26 +2414,11 @@ impl EditorElement { ) }); - if should_cancel { + if handled { cx.stop_propagation() } } }); - //todo!() - // on_down(MouseButton::Right, { - // let position_map = layout.position_map.clone(); - // move |event, editor, cx| { - // if !Self::mouse_right_down( - // editor, - // event.position, - // position_map.as_ref(), - // text_bounds, - // cx, - // ) { - // cx.propagate_event(); - // } - // } - // }); cx.on_mouse_event({ let position_map = layout.position_map.clone(); let editor = self.editor.clone(); diff --git a/crates/editor2/src/mouse_context_menu.rs b/crates/editor2/src/mouse_context_menu.rs index b70a826bf8..fdeec9110b 100644 --- a/crates/editor2/src/mouse_context_menu.rs +++ b/crates/editor2/src/mouse_context_menu.rs @@ -1,5 +1,14 @@ -use crate::{DisplayPoint, Editor, EditorMode, SelectMode}; -use gpui::{Pixels, Point, ViewContext}; +use crate::{ + DisplayPoint, Editor, EditorMode, FindAllReferences, GoToDefinition, GoToTypeDefinition, + Rename, RevealInFinder, SelectMode, ToggleCodeActions, +}; +use gpui::{DismissEvent, Pixels, Point, Subscription, View, ViewContext}; + +pub struct MouseContextMenu { + pub(crate) position: Point, + pub(crate) context_menu: View, + _subscription: Subscription, +} pub fn deploy_context_menu( editor: &mut Editor, @@ -7,50 +16,57 @@ pub fn deploy_context_menu( point: DisplayPoint, cx: &mut ViewContext, ) { - todo!(); + if !editor.is_focused(cx) { + editor.focus(cx); + } - // if !editor.focused { - // cx.focus_self(); - // } + // Don't show context menu for inline editors + if editor.mode() != EditorMode::Full { + return; + } - // // Don't show context menu for inline editors - // if editor.mode() != EditorMode::Full { - // return; - // } + // Don't show the context menu if there isn't a project associated with this editor + if editor.project.is_none() { + return; + } - // // Don't show the context menu if there isn't a project associated with this editor - // if editor.project.is_none() { - // return; - // } + // Move the cursor to the clicked location so that dispatched actions make sense + editor.change_selections(None, cx, |s| { + s.clear_disjoint(); + s.set_pending_display_range(point..point, SelectMode::Character); + }); - // // Move the cursor to the clicked location so that dispatched actions make sense - // editor.change_selections(None, cx, |s| { - // s.clear_disjoint(); - // s.set_pending_display_range(point..point, SelectMode::Character); - // }); + let context_menu = ui::ContextMenu::build(cx, |menu, cx| { + menu.action("Rename Symbol", Box::new(Rename), cx) + .action("Go to Definition", Box::new(GoToDefinition), cx) + .action("Go to Type Definition", Box::new(GoToTypeDefinition), cx) + .action("Find All References", Box::new(FindAllReferences), cx) + .action( + "Code Actions", + Box::new(ToggleCodeActions { + deployed_from_indicator: false, + }), + cx, + ) + .separator() + .action("Reveal in Finder", Box::new(RevealInFinder), cx) + }); + let context_menu_focus = context_menu.focus_handle(cx); + cx.focus(&context_menu_focus); - // editor.mouse_context_menu.update(cx, |menu, cx| { - // menu.show( - // position, - // AnchorCorner::TopLeft, - // vec![ - // ContextMenuItem::action("Rename Symbol", Rename), - // ContextMenuItem::action("Go to Definition", GoToDefinition), - // ContextMenuItem::action("Go to Type Definition", GoToTypeDefinition), - // ContextMenuItem::action("Find All References", FindAllReferences), - // ContextMenuItem::action( - // "Code Actions", - // ToggleCodeActions { - // deployed_from_indicator: false, - // }, - // ), - // ContextMenuItem::Separator, - // ContextMenuItem::action("Reveal in Finder", RevealInFinder), - // ], - // cx, - // ); - // }); - // cx.notify(); + let _subscription = cx.subscribe(&context_menu, move |this, _, event: &DismissEvent, cx| { + this.mouse_context_menu.take(); + if context_menu_focus.contains_focused(cx) { + this.focus(cx); + } + }); + + editor.mouse_context_menu = Some(MouseContextMenu { + position, + context_menu, + _subscription, + }); + cx.notify(); } // #[cfg(test)]