allow inlays to define their own context menu

This commit is contained in:
Dmitry Batrak
2016-10-05 12:50:57 +03:00
parent 5121f446a5
commit b568afc7d1
6 changed files with 61 additions and 5 deletions

View File

@@ -16,6 +16,7 @@
package com.intellij.openapi.editor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
@@ -35,4 +36,13 @@ public interface EditorCustomElementRenderer {
* Implements painting for the custom region. Rectangle passed as a parameter defines target region where painting should be performed.
*/
void paint(@NotNull Editor editor, @NotNull Graphics g, @NotNull Rectangle r);
/**
* Returns a registered id of action group, which is to be used for displaying context menu for the given custom element.
* If <code>null</code> is returned, standard editor's context menu will be displayed upon corresponding mouse event.
*/
@Nullable
default String getContextMenuGroupId() {
return null;
}
}

View File

@@ -20,6 +20,7 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.EventListener;
import java.util.List;
@@ -56,6 +57,13 @@ public interface InlayModel {
*/
boolean hasInlineElementAt(@NotNull VisualPosition visualPosition);
/**
* Return a custom visual element at given coordinates in editor's coordinate space,
* or <code>null</code> if there's no element at given point.
*/
@Nullable
Inlay getElementAt(@NotNull Point point);
/**
* Adds a listener that will be notified after adding, updating and removal of custom visual elements.
*/

View File

@@ -24,6 +24,7 @@ import com.intellij.openapi.editor.VisualPosition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.Collections;
import java.util.List;
@@ -56,6 +57,13 @@ public class InlayModelWindow implements InlayModel {
return false;
}
@Nullable
@Override
public Inlay getElementAt(@NotNull Point point) {
logUnsupported();
return null;
}
@Override
public void addListener(@NotNull Listener listener, @NotNull Disposable disposable) {
logUnsupported();

View File

@@ -7148,7 +7148,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
event.getArea() == EditorMouseEventArea.EDITING_AREA &&
event.getMouseEvent().isPopupTrigger() &&
!event.isConsumed()) {
AnAction action = CustomActionsSchema.getInstance().getCorrectedAction(myContextMenuGroupId);
String contextMenuGroupId = myContextMenuGroupId;
Inlay inlay = myInlayModel.getElementAt(event.getMouseEvent().getPoint());
if (inlay != null) {
String inlayContextMenuGroupId = inlay.getRenderer().getContextMenuGroupId();
if (inlayContextMenuGroupId != null) contextMenuGroupId = inlayContextMenuGroupId;
}
AnAction action = CustomActionsSchema.getInstance().getCorrectedAction(contextMenuGroupId);
if (action instanceof ActionGroup) {
ActionPopupMenu popupMenu = ActionManager.getInstance().createActionPopupMenu(ActionPlaces.EDITOR_POPUP, (ActionGroup)action);
MouseEvent e = event.getMouseEvent();

View File

@@ -17,10 +17,7 @@ package com.intellij.openapi.editor.impl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.EditorCustomElementRenderer;
import com.intellij.openapi.editor.Inlay;
import com.intellij.openapi.editor.InlayModel;
import com.intellij.openapi.editor.VisualPosition;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.PrioritizedDocumentListener;
@@ -30,6 +27,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -139,6 +137,25 @@ public class InlayModelImpl implements InlayModel, Disposable {
return visualPosition.equals(inlayStartPosition);
}
@Nullable
@Override
public Inlay getElementAt(@NotNull Point point) {
if (myInlayTree.size() == 0) return null;
int offset = myEditor.logicalPositionToOffset(myEditor.xyToLogicalPosition(point));
List<Inlay> inlays = getInlineElementsInRange(offset, offset);
if (inlays.isEmpty()) return null;
VisualPosition startVisualPosition = myEditor.offsetToVisualPosition(offset);
int x = myEditor.visualPositionToXY(startVisualPosition).x;
for (Inlay inlay : inlays) {
int endX = x + inlay.getWidthInPixels();
if (point.x >= x && point.x < endX) return inlay;
x = endX;
}
return null;
}
@Override
public void addListener(@NotNull Listener listener, @NotNull Disposable disposable) {
myDispatcher.addListener(listener, disposable);

View File

@@ -23,6 +23,7 @@ import com.intellij.openapi.editor.VisualPosition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.Collections;
import java.util.List;
@@ -49,6 +50,12 @@ public class TextComponentInlayModel implements InlayModel {
return false;
}
@Nullable
@Override
public Inlay getElementAt(@NotNull Point point) {
return null;
}
@Override
public void addListener(@NotNull Listener listener, @NotNull Disposable disposable) {
}