mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 14:23:28 +07:00
tweak editor popup handlers for RemDev
1. Use groups instead of imperative popup handlers 2. Provide editor-local id for editor popup action 3. Encode EditorMouseEvent into that local id 4. Avoid breaking API changes, stick to `ContextMenuPopupHandler` Fixes GTW-7427 Git blame actions are missing GTW-6380 No context menu options in consoles inside LUXed windows GitOrigin-RevId: d9e109dac3268ab94e6bc64e4e156f8506872739
This commit is contained in:
committed by
intellij-monorepo-bot
parent
eefe73501c
commit
f6aa793f4d
@@ -22,6 +22,7 @@ import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehavior
|
||||
import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehaviorSpecification
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.impl.EditorImpl
|
||||
@@ -66,7 +67,9 @@ class ShowSettingsWithAddedPattern : AnAction() {
|
||||
}
|
||||
}
|
||||
|
||||
class ShowParameterHintsSettings : AnAction(), ActionRemoteBehaviorSpecification.Frontend {
|
||||
class ShowParameterHintsSettings : AnAction(), ActionRemoteBehaviorSpecification {
|
||||
|
||||
override fun getBehavior(): ActionRemoteBehavior = ActionRemoteBehavior.BackendOnly
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
|
||||
|
||||
@@ -263,7 +266,9 @@ private fun InlayParameterHintsProvider.hasDisabledOptionHintInfo(element: PsiEl
|
||||
}
|
||||
|
||||
|
||||
class ToggleInlineHintsAction : AnAction(), ActionRemoteBehaviorSpecification.Frontend {
|
||||
class ToggleInlineHintsAction : AnAction(), ActionRemoteBehaviorSpecification {
|
||||
|
||||
override fun getBehavior(): ActionRemoteBehavior = ActionRemoteBehavior.BackendOnly
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
|
||||
|
||||
|
||||
@@ -6,11 +6,19 @@ import com.intellij.openapi.actionSystem.ActionUpdateThread;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.ToggleAction;
|
||||
import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehavior;
|
||||
import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehaviorSpecification;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class ToggleCompletionHintsAction extends ToggleAction implements ActionRemoteBehaviorSpecification.Frontend {
|
||||
public final class ToggleCompletionHintsAction extends ToggleAction implements ActionRemoteBehaviorSpecification {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ActionRemoteBehavior getBehavior() {
|
||||
return ActionRemoteBehavior.BackendOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ActionUpdateThread getActionUpdateThread() {
|
||||
return ActionUpdateThread.BGT;
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.intellij.injected.editor.DocumentWindow;
|
||||
import com.intellij.injected.editor.EditorWindow;
|
||||
import com.intellij.injected.editor.MarkupModelWindow;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
@@ -823,6 +824,11 @@ final class EditorWindowImpl extends UserDataHolderBase implements EditorWindow,
|
||||
myDelegate.installPopupHandler(popupHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ActionGroup getPopupActionGroup(@NotNull EditorMouseEvent event) {
|
||||
return myDelegate.getPopupActionGroup(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCustomCursor(@NotNull Object requestor, @Nullable Cursor cursor) {
|
||||
myDelegate.setCustomCursor(requestor, cursor);
|
||||
|
||||
@@ -74,7 +74,6 @@ file.not.found=File not found: {0}
|
||||
guarded.block.modification.attempt.error.message=Unable to perform an action since it changes read-only fragments of the current document
|
||||
guarded.block.modification.attempt.error.title=Guarded Block Modification Attempt
|
||||
close.editor.annotations.action.name=Close Annotations
|
||||
editor.annotations.action.group.name=Annotations
|
||||
move.cursor.command.name=Move Cursor
|
||||
paste.command.name=Paste
|
||||
move.selection.command.name=Move Selection
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.ide.CutProvider;
|
||||
import com.intellij.ide.DeleteProvider;
|
||||
import com.intellij.ide.PasteProvider;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.editor.*;
|
||||
@@ -343,6 +344,10 @@ public interface EditorEx extends Editor {
|
||||
*/
|
||||
void uninstallPopupHandler(@NotNull EditorPopupHandler popupHandler);
|
||||
|
||||
default @Nullable ActionGroup getPopupActionGroup(@NotNull EditorMouseEvent event) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* If {@code cursor} parameter value is not {@code null}, sets custom cursor to {@link #getContentComponent() editor's content component},
|
||||
* otherwise restores default editor cursor management logic ({@code requestor} parameter value should be the same in both setting and
|
||||
|
||||
@@ -34,6 +34,8 @@ import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil;
|
||||
import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehavior;
|
||||
import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehaviorSpecification;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -43,6 +45,7 @@ import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.colors.EditorFontType;
|
||||
import com.intellij.openapi.editor.event.CaretEvent;
|
||||
import com.intellij.openapi.editor.event.CaretListener;
|
||||
import com.intellij.openapi.editor.event.EditorMouseEvent;
|
||||
import com.intellij.openapi.editor.event.EditorMouseEventArea;
|
||||
import com.intellij.openapi.editor.ex.*;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUIUtil;
|
||||
@@ -2458,11 +2461,17 @@ final class EditorGutterComponentImpl extends EditorGutterComponentEx implements
|
||||
updateSize();
|
||||
}
|
||||
|
||||
private final class CloseAnnotationsAction extends DumbAwareAction {
|
||||
private final class CloseAnnotationsAction extends DumbAwareAction implements ActionRemoteBehaviorSpecification {
|
||||
CloseAnnotationsAction() {
|
||||
super(EditorBundle.messagePointer("close.editor.annotations.action.name"));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ActionRemoteBehavior getBehavior() {
|
||||
return ActionRemoteBehavior.BackendOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
closeAllAnnotations();
|
||||
@@ -2572,74 +2581,68 @@ final class EditorGutterComponentImpl extends EditorGutterComponentEx implements
|
||||
if (info != null) {
|
||||
logGutterIconClick(info.renderer);
|
||||
}
|
||||
myLastActionableClick = new ClickInfo(logicalLineAtCursor, info == null ? point : info.iconCenterPosition);
|
||||
final ActionManager actionManager = ActionManager.getInstance();
|
||||
if (myEditor.getMouseEventArea(e) == EditorMouseEventArea.ANNOTATIONS_AREA) {
|
||||
final List<AnAction> addActions = getTextAnnotationPopupActions(logicalLineAtCursor);
|
||||
if (!addActions.isEmpty()) {
|
||||
e.consume();
|
||||
DefaultActionGroup actionGroup = DefaultActionGroup.createPopupGroup(
|
||||
EditorBundle.messagePointer("editor.annotations.action.group.name"));
|
||||
for (AnAction addAction : addActions) {
|
||||
actionGroup.add(addAction);
|
||||
}
|
||||
JPopupMenu menu = actionManager.createActionPopupMenu(ActionPlaces.EDITOR_ANNOTATIONS_AREA_POPUP, actionGroup).getComponent();
|
||||
menu.show(this, e.getX(), e.getY());
|
||||
}
|
||||
ClickInfo clickInfo = new ClickInfo(logicalLineAtCursor, info == null ? point : info.iconCenterPosition);
|
||||
EditorMouseEventArea editorArea = myEditor.getMouseEventArea(e);
|
||||
myLastActionableClick = clickInfo;
|
||||
|
||||
AnAction rightButtonAction = info == null ? null : info.renderer.getRightButtonClickAction();
|
||||
if (rightButtonAction != null) {
|
||||
e.consume();
|
||||
performAction(rightButtonAction, e, ActionPlaces.EDITOR_GUTTER_POPUP, myEditor.getDataContext(), info);
|
||||
return;
|
||||
}
|
||||
EditorMouseEvent editorMouseEvent = new EditorMouseEvent(
|
||||
myEditor, e, editorArea, 0, new LogicalPosition(logicalLineAtCursor, 0),
|
||||
new VisualPosition(0, 0), true, null, null, null);
|
||||
ActionGroup group = info != null ? info.renderer.getPopupMenuActions() :
|
||||
getPopupActionGroup(editorMouseEvent);
|
||||
if (group == null) {
|
||||
// nothing
|
||||
}
|
||||
else if (!checkDumbAware(group)) {
|
||||
notifyNotDumbAware();
|
||||
}
|
||||
else {
|
||||
if (info != null) {
|
||||
AnAction rightButtonAction = info.renderer.getRightButtonClickAction();
|
||||
if (rightButtonAction != null) {
|
||||
e.consume();
|
||||
performAction(rightButtonAction, e, ActionPlaces.EDITOR_GUTTER_POPUP, myEditor.getDataContext(), info);
|
||||
}
|
||||
else {
|
||||
ActionGroup actionGroup = info.renderer.getPopupMenuActions();
|
||||
if (actionGroup != null) {
|
||||
e.consume();
|
||||
if (checkDumbAware(actionGroup)) {
|
||||
addLoadingIconForGutterMark(info);
|
||||
actionManager.createActionPopupMenu(ActionPlaces.EDITOR_GUTTER_POPUP, actionGroup)
|
||||
.getComponent()
|
||||
.show(this, e.getX(), e.getY());
|
||||
}
|
||||
else {
|
||||
notifyNotDumbAware();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (info != null) addLoadingIconForGutterMark(info);
|
||||
String place = editorArea == EditorMouseEventArea.ANNOTATIONS_AREA ?
|
||||
ActionPlaces.EDITOR_ANNOTATIONS_AREA_POPUP : ActionPlaces.EDITOR_GUTTER_POPUP;
|
||||
showGutterContextMenu(group, e, place);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable ActionGroup getPopupActionGroup(@NotNull EditorMouseEvent event) {
|
||||
List<AnAction> actions;
|
||||
if (event.getArea() == EditorMouseEventArea.ANNOTATIONS_AREA) {
|
||||
actions = getTextAnnotationPopupActions(event.getLogicalPosition().line);
|
||||
}
|
||||
else {
|
||||
actions = new ArrayList<>();
|
||||
if (ExperimentalUI.isNewUI() &&
|
||||
event.getArea() == EditorMouseEventArea.LINE_NUMBERS_AREA &&
|
||||
getClientProperty("line.number.hover.icon.context.menu") instanceof ActionGroup g) {
|
||||
actions.add(g);
|
||||
}
|
||||
else {
|
||||
List<AnAction> actions = new ArrayList<>();
|
||||
if (ExperimentalUI.isNewUI() &&
|
||||
myEditor.getMouseEventArea(e) == EditorMouseEventArea.LINE_NUMBERS_AREA &&
|
||||
getClientProperty("line.number.hover.icon.context.menu") instanceof ActionGroup g) {
|
||||
actions.add(g);
|
||||
}
|
||||
if (myCustomGutterPopupGroup != null) {
|
||||
if (myCustomGutterPopupGroup != null) {
|
||||
actions.add(Separator.getInstance());
|
||||
actions.add(myCustomGutterPopupGroup);
|
||||
}
|
||||
else if (myShowDefaultGutterPopup) {
|
||||
ActionGroup g = (ActionGroup)CustomActionsSchema.getInstance().getCorrectedAction(IdeActions.GROUP_EDITOR_GUTTER);
|
||||
if (g != null) {
|
||||
actions.add(Separator.getInstance());
|
||||
actions.add(myCustomGutterPopupGroup);
|
||||
}
|
||||
else if (myShowDefaultGutterPopup) {
|
||||
ActionGroup g = (ActionGroup)CustomActionsSchema.getInstance().getCorrectedAction(IdeActions.GROUP_EDITOR_GUTTER);
|
||||
if (g != null) {
|
||||
actions.add(Separator.getInstance());
|
||||
actions.add(g);
|
||||
}
|
||||
}
|
||||
if (!actions.isEmpty()) {
|
||||
showGutterContextMenu(new DefaultActionGroup(actions), e);
|
||||
actions.add(g);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (actions.isEmpty()) return null;
|
||||
return new EditorMousePopupActionGroup(actions, event);
|
||||
}
|
||||
|
||||
private static final String EDITOR_GUTTER_CONTEXT_MENU_KEY = "editor.gutter.context.menu";
|
||||
|
||||
private void showGutterContextMenu(@NotNull ActionGroup group, MouseEvent e) {
|
||||
private void showGutterContextMenu(@NotNull ActionGroup group, MouseEvent e, String place) {
|
||||
e.consume();
|
||||
ActionPopupMenu popupMenu = ActionManager.getInstance().createActionPopupMenu(ActionPlaces.EDITOR_GUTTER_POPUP, group);
|
||||
ActionPopupMenu popupMenu = ActionManager.getInstance().createActionPopupMenu(place, group);
|
||||
putClientProperty(EDITOR_GUTTER_CONTEXT_MENU_KEY, popupMenu);
|
||||
popupMenu.getComponent().addPopupMenuListener(new PopupMenuListenerAdapter() {
|
||||
@Override
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.application.options.EditorFontsConstants;
|
||||
import com.intellij.codeWithMe.ClientId;
|
||||
import com.intellij.diagnostic.Dumpable;
|
||||
import com.intellij.ide.*;
|
||||
import com.intellij.ide.dnd.DnDManager;
|
||||
@@ -36,7 +37,6 @@ import com.intellij.openapi.editor.ex.util.EmptyEditorHighlighter;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.editor.highlighter.HighlighterClient;
|
||||
import com.intellij.openapi.editor.impl.event.MarkupModelListener;
|
||||
import com.intellij.openapi.editor.impl.stickyLines.StickyLinesPanel;
|
||||
import com.intellij.openapi.editor.impl.stickyLines.StickyLinesManager;
|
||||
import com.intellij.openapi.editor.impl.stickyLines.StickyLinesPanel;
|
||||
import com.intellij.openapi.editor.impl.view.EditorView;
|
||||
@@ -858,6 +858,22 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
myPopupHandlers.remove(popupHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ActionGroup getPopupActionGroup(@NotNull EditorMouseEvent event) {
|
||||
if (event.getArea() == EditorMouseEventArea.EDITING_AREA) {
|
||||
for (int i = myPopupHandlers.size() - 1; i >= 0; i--) {
|
||||
EditorPopupHandler handler = myPopupHandlers.get(i);
|
||||
ActionGroup group = handler instanceof ContextMenuPopupHandler o ? o.getActionGroup(event) : null;
|
||||
if (group instanceof DefaultActionGroup o && o.getChildrenCount() == 0) return group;
|
||||
if (group != null) return new EditorMousePopupActionGroup(group, event);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return myGutterComponent.getPopupActionGroup(event);
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable Cursor getCustomCursor() {
|
||||
return ContainerUtil.getFirstItem(myCustomCursors.values());
|
||||
}
|
||||
@@ -5320,9 +5336,27 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
|
||||
private void invokePopupIfNeeded(@NotNull EditorMouseEvent event) {
|
||||
if (myPopupHandlers.isEmpty()) return;
|
||||
|
||||
if (event.getArea() == EditorMouseEventArea.EDITING_AREA && event.getMouseEvent().isPopupTrigger() && !event.isConsumed()) {
|
||||
for (int i = myPopupHandlers.size() - 1; i >= 0; i--) {
|
||||
if (myPopupHandlers.get(i).handlePopup(event)) break;
|
||||
if (ContainerUtil.all(myPopupHandlers, o -> o instanceof ContextMenuPopupHandler)) {
|
||||
ActionGroup group = getPopupActionGroup(event);
|
||||
if (group == null) return;
|
||||
if (group instanceof DefaultActionGroup o && o.getChildrenCount() == 0) return;
|
||||
new ContextMenuPopupHandler.Simple(group).handlePopup(event);
|
||||
}
|
||||
else {
|
||||
String message = "Non-ContextMenuPopupHandler popup handler detected: " +
|
||||
ContainerUtil.map(myPopupHandlers, o -> o.getClass().getName());
|
||||
if (ClientId.isCurrentlyUnderLocalId()) {
|
||||
LOG.warn(message);
|
||||
}
|
||||
else {
|
||||
LOG.error(message);
|
||||
}
|
||||
for (int i = myPopupHandlers.size() - 1; i >= 0; i--) {
|
||||
if (myPopupHandlers.get(i).handlePopup(event)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5369,7 +5403,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
private final class DefaultPopupHandler extends ContextMenuPopupHandler {
|
||||
@Override
|
||||
public @Nullable ActionGroup getActionGroup(@NotNull EditorMouseEvent event) {
|
||||
public @Nullable ActionGroup getActionGroup(@NotNull EditorMouseEvent event) { //TODO ! renderer, collapsed-host
|
||||
String contextMenuGroupId = myState.getContextMenuGroupId();
|
||||
Inlay<?> inlay = event.getInlay();
|
||||
if (inlay != null) {
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.editor.event.EditorMouseEvent;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author gregsh
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public class EditorMousePopupActionGroup extends DefaultActionGroup {
|
||||
|
||||
private final EditorMouseEvent myEvent;
|
||||
private final boolean myResetChildPopupFlag;
|
||||
|
||||
public EditorMousePopupActionGroup(@NotNull List<AnAction> actions, @NotNull EditorMouseEvent event) {
|
||||
addAll(actions);
|
||||
myEvent = event;
|
||||
myResetChildPopupFlag = false;
|
||||
}
|
||||
|
||||
public EditorMousePopupActionGroup(@NotNull ActionGroup group, @NotNull EditorMouseEvent event) {
|
||||
add(group);
|
||||
myEvent = event;
|
||||
myResetChildPopupFlag = true;
|
||||
}
|
||||
|
||||
public @NotNull EditorMouseEvent getEvent() {
|
||||
return myEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnAction @NotNull [] getChildren(@Nullable AnActionEvent e) {
|
||||
AnAction[] children = super.getChildren(e);
|
||||
if (e != null && myResetChildPopupFlag) {
|
||||
Presentation presentation = e.getUpdateSession().presentation(children[0]);
|
||||
presentation.setPopupGroup(false);
|
||||
}
|
||||
return children;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user