Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add action editor::OpenContextMenu #21494

Merged
merged 1 commit into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion assets/keymaps/default-linux.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@
"ctrl-'": "editor::ToggleHunkDiff",
"ctrl-\"": "editor::ExpandAllHunkDiffs",
"ctrl-i": "editor::ShowSignatureHelp",
"alt-g b": "editor::ToggleGitBlame"
"alt-g b": "editor::ToggleGitBlame",
"menu": "editor::OpenContextMenu",
"shift-f10": "editor::OpenContextMenu"
}
},
{
Expand Down
1 change: 1 addition & 0 deletions crates/editor/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ gpui::actions!(
NewlineBelow,
NextInlineCompletion,
NextScreen,
OpenContextMenu,
OpenExcerpts,
OpenExcerptsSplit,
OpenProposedChangesEditor,
Expand Down
38 changes: 27 additions & 11 deletions crates/editor/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13045,6 +13045,12 @@ impl Editor {
cx.write_to_clipboard(ClipboardItem::new_string(lines));
}

pub fn open_context_menu(&mut self, _: &OpenContextMenu, cx: &mut ViewContext<Self>) {
self.request_autoscroll(Autoscroll::newest(), cx);
let position = self.selections.newest_display(cx).start;
mouse_context_menu::deploy_context_menu(self, None, position, cx);
}

pub fn inlay_hint_cache(&self) -> &InlayHintCache {
&self.inlay_hint_cache
}
Expand Down Expand Up @@ -13266,6 +13272,23 @@ impl Editor {
.get(&type_id)
.and_then(|item| item.to_any().downcast_ref::<T>())
}

fn character_size(&self, cx: &mut ViewContext<Self>) -> gpui::Point<Pixels> {
let text_layout_details = self.text_layout_details(cx);
let style = &text_layout_details.editor_style;
let font_id = cx.text_system().resolve_font(&style.text.font());
let font_size = style.text.font_size.to_pixels(cx.rem_size());
let line_height = style.text.line_height_in_pixels(cx.rem_size());

let em_width = cx
.text_system()
.typographic_bounds(font_id, font_size, 'm')
.unwrap()
.size
.width;

gpui::Point::new(em_width, line_height)
}
}

fn char_len_with_expanded_tabs(offset: usize, text: &str, tab_size: NonZeroU32) -> usize {
Expand Down Expand Up @@ -14645,17 +14668,10 @@ impl ViewInputHandler for Editor {
cx: &mut ViewContext<Self>,
) -> Option<gpui::Bounds<Pixels>> {
let text_layout_details = self.text_layout_details(cx);
let style = &text_layout_details.editor_style;
let font_id = cx.text_system().resolve_font(&style.text.font());
let font_size = style.text.font_size.to_pixels(cx.rem_size());
let line_height = style.text.line_height_in_pixels(cx.rem_size());

let em_width = cx
.text_system()
.typographic_bounds(font_id, font_size, 'm')
.unwrap()
.size
.width;
let gpui::Point {
x: em_width,
y: line_height,
} = self.character_size(cx);

let snapshot = self.snapshot(cx);
let scroll_position = snapshot.scroll_position();
Expand Down
29 changes: 15 additions & 14 deletions crates/editor/src/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ impl EditorElement {

crate::rust_analyzer_ext::apply_related_actions(view, cx);
crate::clangd_ext::apply_related_actions(view, cx);
register_action(view, cx, Editor::open_context_menu);
register_action(view, cx, Editor::move_left);
register_action(view, cx, Editor::move_right);
register_action(view, cx, Editor::move_down);
Expand Down Expand Up @@ -594,7 +595,7 @@ impl EditorElement {
position_map.point_for_position(text_hitbox.bounds, event.position);
mouse_context_menu::deploy_context_menu(
editor,
event.position,
Some(event.position),
point_for_position.previous_valid,
cx,
);
Expand Down Expand Up @@ -2729,6 +2730,7 @@ impl EditorElement {
&self,
editor_snapshot: &EditorSnapshot,
visible_range: Range<DisplayRow>,
content_origin: gpui::Point<Pixels>,
cx: &mut WindowContext,
) -> Option<AnyElement> {
let position = self.editor.update(cx, |editor, cx| {
Expand All @@ -2746,16 +2748,11 @@ impl EditorElement {
let mouse_context_menu = editor.mouse_context_menu.as_ref()?;
let (source_display_point, position) = match mouse_context_menu.position {
MenuPosition::PinnedToScreen(point) => (None, point),
MenuPosition::PinnedToEditor {
source,
offset_x,
offset_y,
} => {
MenuPosition::PinnedToEditor { source, offset } => {
let source_display_point = source.to_display_point(editor_snapshot);
let mut source_point = editor.to_pixel_point(source, editor_snapshot, cx)?;
source_point.x += offset_x;
source_point.y += offset_y;
(Some(source_display_point), source_point)
let source_point = editor.to_pixel_point(source, editor_snapshot, cx)?;
let position = content_origin + source_point + offset;
(Some(source_display_point), position)
}
};

Expand Down Expand Up @@ -4330,8 +4327,8 @@ fn deploy_blame_entry_context_menu(
});

editor.update(cx, move |editor, cx| {
editor.mouse_context_menu = Some(MouseContextMenu::pinned_to_screen(
position,
editor.mouse_context_menu = Some(MouseContextMenu::new(
MenuPosition::PinnedToScreen(position),
context_menu,
cx,
));
Expand Down Expand Up @@ -5583,8 +5580,12 @@ impl Element for EditorElement {
);
}

let mouse_context_menu =
self.layout_mouse_context_menu(&snapshot, start_row..end_row, cx);
let mouse_context_menu = self.layout_mouse_context_menu(
&snapshot,
start_row..end_row,
content_origin,
cx,
);

cx.with_element_namespace("crease_toggles", |cx| {
self.prepaint_crease_toggles(
Expand Down
65 changes: 31 additions & 34 deletions crates/editor/src/mouse_context_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ pub enum MenuPosition {
/// Disappears when the position is no longer visible.
PinnedToEditor {
source: multi_buffer::Anchor,
offset_x: Pixels,
offset_y: Pixels,
offset: Point<Pixels>,
},
}

Expand All @@ -48,36 +47,22 @@ impl MouseContextMenu {
context_menu: View<ui::ContextMenu>,
cx: &mut ViewContext<Editor>,
) -> Option<Self> {
let context_menu_focus = context_menu.focus_handle(cx);
cx.focus(&context_menu_focus);

let _subscription = cx.subscribe(
&context_menu,
move |editor, _, _event: &DismissEvent, cx| {
editor.mouse_context_menu.take();
if context_menu_focus.contains_focused(cx) {
editor.focus(cx);
}
},
);

let editor_snapshot = editor.snapshot(cx);
let source_point = editor.to_pixel_point(source, &editor_snapshot, cx)?;
let offset = position - source_point;

Some(Self {
position: MenuPosition::PinnedToEditor {
source,
offset_x: offset.x,
offset_y: offset.y,
},
context_menu,
_subscription,
})
let content_origin = editor.last_bounds?.origin
+ Point {
x: editor.gutter_dimensions.width,
y: Pixels(0.0),
};
let source_position = editor.to_pixel_point(source, &editor_snapshot, cx)?;
let menu_position = MenuPosition::PinnedToEditor {
source,
offset: position - (source_position + content_origin),
};
return Some(MouseContextMenu::new(menu_position, context_menu, cx));
}

pub(crate) fn pinned_to_screen(
position: Point<Pixels>,
pub(crate) fn new(
position: MenuPosition,
context_menu: View<ui::ContextMenu>,
cx: &mut ViewContext<Editor>,
) -> Self {
Expand All @@ -95,7 +80,7 @@ impl MouseContextMenu {
);

Self {
position: MenuPosition::PinnedToScreen(position),
position,
context_menu,
_subscription,
}
Expand All @@ -119,7 +104,7 @@ fn display_ranges<'a>(

pub fn deploy_context_menu(
editor: &mut Editor,
position: Point<Pixels>,
position: Option<Point<Pixels>>,
point: DisplayPoint,
cx: &mut ViewContext<Editor>,
) {
Expand Down Expand Up @@ -213,8 +198,18 @@ pub fn deploy_context_menu(
})
};

editor.mouse_context_menu =
MouseContextMenu::pinned_to_editor(editor, source_anchor, position, context_menu, cx);
editor.mouse_context_menu = match position {
Some(position) => {
MouseContextMenu::pinned_to_editor(editor, source_anchor, position, context_menu, cx)
}
None => {
let menu_position = MenuPosition::PinnedToEditor {
source: source_anchor,
offset: editor.character_size(cx),
};
Some(MouseContextMenu::new(menu_position, context_menu, cx))
}
};
cx.notify();
}

Expand Down Expand Up @@ -248,7 +243,9 @@ mod tests {
}
"});
cx.editor(|editor, _app| assert!(editor.mouse_context_menu.is_none()));
cx.update_editor(|editor, cx| deploy_context_menu(editor, Default::default(), point, cx));
cx.update_editor(|editor, cx| {
deploy_context_menu(editor, Some(Default::default()), point, cx)
});

cx.assert_editor_state(indoc! {"
fn test() {
Expand Down
Loading