mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-237977 Rendered JavaDoc not selectable
GitOrigin-RevId: e9250377047c1fe84d5bd8c3e5c72f713fec0f10
This commit is contained in:
committed by
intellij-monorepo-bot
parent
ae0f480588
commit
71cd340039
@@ -30,9 +30,8 @@ import java.util.EventObject;
|
||||
* dispatching, and is not guaranteed to be actual by the time some event listener receives the event (if previously called listener has
|
||||
* modified the editor state).
|
||||
* <p>
|
||||
* The additional information is currently provided for the following types of events: {@link MouseEvent#MOUSE_MOVED MOUSE_MOVED},
|
||||
* {@link MouseEvent#MOUSE_PRESSED MOUSE_PRESSED}, {@link MouseEvent#MOUSE_RELEASED MOUSE_RELEASED} and
|
||||
* {@link MouseEvent#MOUSE_CLICKED MOUSE_CLICKED}. For other events, return values of corresponding event getters are unspecified.
|
||||
* The additional information is not provided for {@link MouseEvent#MOUSE_ENTERED MOUSE_ENTERED} and
|
||||
* {@link MouseEvent#MOUSE_EXITED MOUSE_EXITED} events. Return values of corresponding event getters are unspecified for those events.
|
||||
*/
|
||||
public class EditorMouseEvent extends EventObject {
|
||||
@NotNull
|
||||
@@ -88,52 +87,33 @@ public class EditorMouseEvent extends EventObject {
|
||||
return myEditorArea;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link EditorMouseEvent class documentation} with regard to the availability of this information.
|
||||
*/
|
||||
public int getOffset() {
|
||||
return myOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link EditorMouseEvent class documentation} with regard to the availability of this information.
|
||||
*/
|
||||
public @NotNull LogicalPosition getLogicalPosition() {
|
||||
return myLogicalPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link EditorMouseEvent class documentation} with regard to the availability of this information.
|
||||
*/
|
||||
public @NotNull VisualPosition getVisualPosition() {
|
||||
return myVisualPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code false} if mouse is below the last line of text, to the right of the last character on the line, or over an inlay.
|
||||
* See {@link EditorMouseEvent class documentation} with regard to the availability of this information.
|
||||
*/
|
||||
public boolean isOverText() {
|
||||
return myIsOverText;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link EditorMouseEvent class documentation} with regard to the availability of this information.
|
||||
*/
|
||||
public @Nullable FoldRegion getCollapsedFoldRegion() {
|
||||
return myCollapsedFoldRegion == null || !myCollapsedFoldRegion.isValid() ? null : myCollapsedFoldRegion;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link EditorMouseEvent class documentation} with regard to the availability of this information.
|
||||
*/
|
||||
public @Nullable Inlay getInlay() {
|
||||
return myInlay == null || !myInlay.isValid() ? null : myInlay;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link EditorMouseEvent class documentation} with regard to the availability of this information.
|
||||
*/
|
||||
public @Nullable GutterIconRenderer getGutterIconRenderer() {
|
||||
return myGutterIconRenderer;
|
||||
}
|
||||
|
||||
@@ -196,6 +196,7 @@ doc.render.dumb.mode.text=<i>Cannot render documentation during indexing</i>
|
||||
doc.render.loading.text=Loading...
|
||||
doc.render.not.available.text=<i>Not available</i>
|
||||
doc.render.gutter.icon.setting=Documentation comments in-place rendering
|
||||
doc.render.copy.action.text=Copy Selection
|
||||
declaration.navigation.title=Choose Declaration
|
||||
declaration.navigation.nowhere.to.go=Cannot find declaration to go to
|
||||
template.shortcut.enter=Enter
|
||||
|
||||
+48
-17
@@ -13,30 +13,39 @@ import org.jetbrains.annotations.Nullable;
|
||||
import sun.awt.AWTAccessor;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
class DocRenderMouseEventBridge implements EditorMouseListener, EditorMouseMotionListener {
|
||||
private DocRenderer.EditorPane myCurrentPane;
|
||||
private DocRenderer.EditorPane myMouseOverPane;
|
||||
private DocRenderer.EditorPane myDragPane;
|
||||
|
||||
@Override
|
||||
public void mouseMoved(@NotNull EditorMouseEvent event) {
|
||||
if (event.getArea() != EditorMouseEventArea.EDITING_AREA) return;
|
||||
|
||||
DocRenderer.EditorPane currentPane = redispatchEvent(event, MouseEvent.MOUSE_MOVED);
|
||||
DocRenderer.EditorPane currentPane = redispatchEvent(event, MouseEvent.MOUSE_MOVED, null);
|
||||
if (currentPane == null) {
|
||||
restoreCursor();
|
||||
}
|
||||
else {
|
||||
((EditorEx)event.getEditor()).setCustomCursor(DocRenderMouseEventBridge.class, currentPane.getCursor());
|
||||
if (currentPane != myCurrentPane) {
|
||||
if (myCurrentPane != null) {
|
||||
dispatchMouseExitEvent(myCurrentPane);
|
||||
if (currentPane != myMouseOverPane) {
|
||||
if (myMouseOverPane != null) {
|
||||
dispatchMouseExitEvent(myMouseOverPane);
|
||||
}
|
||||
myCurrentPane = currentPane;
|
||||
myMouseOverPane = currentPane;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(@NotNull EditorMouseEvent e) {
|
||||
if (e.getArea() != EditorMouseEventArea.EDITING_AREA) return;
|
||||
|
||||
redispatchEvent(e, MouseEvent.MOUSE_DRAGGED, myDragPane);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(@NotNull EditorMouseEvent event) {
|
||||
if (event.getArea() != EditorMouseEventArea.EDITING_AREA) return;
|
||||
@@ -44,23 +53,42 @@ class DocRenderMouseEventBridge implements EditorMouseListener, EditorMouseMotio
|
||||
restoreCursor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(@NotNull EditorMouseEvent event) {
|
||||
if (event.getArea() != EditorMouseEventArea.EDITING_AREA) return;
|
||||
|
||||
myDragPane = redispatchEvent(event, MouseEvent.MOUSE_PRESSED, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(@NotNull EditorMouseEvent event) {
|
||||
if (event.getArea() != EditorMouseEventArea.EDITING_AREA) return;
|
||||
|
||||
redispatchEvent(event, MouseEvent.MOUSE_RELEASED, null);
|
||||
myDragPane = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(@NotNull EditorMouseEvent event) {
|
||||
if (event.getArea() != EditorMouseEventArea.EDITING_AREA) return;
|
||||
|
||||
redispatchEvent(event, MouseEvent.MOUSE_CLICKED);
|
||||
redispatchEvent(event, MouseEvent.MOUSE_CLICKED, null);
|
||||
}
|
||||
|
||||
private void restoreCursor() {
|
||||
if (myCurrentPane != null) {
|
||||
dispatchMouseExitEvent(myCurrentPane);
|
||||
((EditorEx)myCurrentPane.getEditor()).setCustomCursor(DocRenderMouseEventBridge.class, null);
|
||||
myCurrentPane = null;
|
||||
if (myMouseOverPane != null) {
|
||||
dispatchMouseExitEvent(myMouseOverPane);
|
||||
((EditorEx)myMouseOverPane.getEditor()).setCustomCursor(DocRenderMouseEventBridge.class, null);
|
||||
myMouseOverPane = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static DocRenderer.EditorPane redispatchEvent(@NotNull EditorMouseEvent event, int eventId) {
|
||||
private static DocRenderer.EditorPane redispatchEvent(@NotNull EditorMouseEvent event,
|
||||
// we need a separately passed eventId because EditorImpl dispatches MOUSE_RELEASED
|
||||
// events to both 'mouseReleased' and 'mouseClicked' methods in listeners
|
||||
int eventId,
|
||||
@Nullable DocRenderer.EditorPane targetPane) {
|
||||
MouseEvent mouseEvent = event.getMouseEvent();
|
||||
Point mousePoint = mouseEvent.getPoint();
|
||||
Inlay inlay = event.getInlay();
|
||||
@@ -74,11 +102,14 @@ class DocRenderMouseEventBridge implements EditorMouseListener, EditorMouseMotio
|
||||
int y = mousePoint.y - inlayBounds.y - relativeBounds.y;
|
||||
if (x >= 0 && x < relativeBounds.width && y >= 0 && y < relativeBounds.height) {
|
||||
DocRenderer.EditorPane editorPane = ((DocRenderer)renderer).getRendererComponent(inlay, relativeBounds.width);
|
||||
int button = mouseEvent.getButton();
|
||||
dispatchEvent(editorPane, new MouseEvent(editorPane, eventId, 0, 0, x, y, mouseEvent.getClickCount(), false,
|
||||
// hack to process middle-button clicks (JEditorPane ignores them)
|
||||
button == MouseEvent.BUTTON2 ? MouseEvent.BUTTON1 : button));
|
||||
return editorPane;
|
||||
if (targetPane == null || targetPane == editorPane) {
|
||||
int button = mouseEvent.getButton();
|
||||
int modifiers = eventId == MouseEvent.MOUSE_DRAGGED && button == MouseEvent.BUTTON1 ? InputEvent.BUTTON1_DOWN_MASK : 0;
|
||||
dispatchEvent(editorPane, new MouseEvent(editorPane, eventId, 0, modifiers, x, y, mouseEvent.getClickCount(), false,
|
||||
// hack to process middle-button clicks (JEditorPane ignores them)
|
||||
button == MouseEvent.BUTTON2 ? MouseEvent.BUTTON1 : button));
|
||||
return editorPane;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+39
-6
@@ -9,10 +9,7 @@ import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.IdeEventQueue;
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.actionSystem.MouseShortcut;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
@@ -22,8 +19,10 @@ import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.markup.GutterIconRenderer;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.ide.CopyPasteManager;
|
||||
import com.intellij.openapi.keymap.KeymapManager;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -42,6 +41,7 @@ import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.StartupUiUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
@@ -50,6 +50,7 @@ import javax.swing.text.html.HTMLEditorKit;
|
||||
import javax.swing.text.html.ImageView;
|
||||
import javax.swing.text.html.StyleSheet;
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.image.ImageObserver;
|
||||
@@ -159,7 +160,12 @@ class DocRenderer implements EditorCustomElementRenderer {
|
||||
|
||||
@Override
|
||||
public ActionGroup getContextMenuGroup(@NotNull Inlay inlay) {
|
||||
return new DefaultActionGroup(myItem.createToggleAction(), new DocRenderItem.ChangeFontSize());
|
||||
DefaultActionGroup group = new DefaultActionGroup();
|
||||
group.add(new CopySelection());
|
||||
group.addSeparator();
|
||||
group.add(myItem.createToggleAction());
|
||||
group.add(new DocRenderItem.ChangeFontSize());
|
||||
return group;
|
||||
}
|
||||
|
||||
private static int scale(int value) {
|
||||
@@ -200,6 +206,7 @@ class DocRenderer implements EditorCustomElementRenderer {
|
||||
clearCachedComponent();
|
||||
myPane = new EditorPane();
|
||||
myPane.setEditable(false);
|
||||
myPane.getCaret().setSelectionVisible(true);
|
||||
myPane.putClientProperty("caretWidth", 0); // do not reserve space for caret (making content one pixel narrower than component)
|
||||
myPane.setEditorKit(createEditorKit(editor));
|
||||
myPane.setBorder(JBUI.Borders.empty());
|
||||
@@ -208,7 +215,10 @@ class DocRenderer implements EditorCustomElementRenderer {
|
||||
// disable kerning for now - laying out all fragments in a file with it takes too much time
|
||||
fontAttributes.put(TextAttribute.KERNING, 0);
|
||||
myPane.setFont(myPane.getFont().deriveFont(fontAttributes));
|
||||
myPane.setForeground(getTextColor(editor.getColorsScheme()));
|
||||
Color textColor = getTextColor(editor.getColorsScheme());
|
||||
myPane.setForeground(textColor);
|
||||
myPane.setSelectedTextColor(textColor);
|
||||
myPane.setSelectionColor(editor.getSelectionModel().getTextAttributes().getBackgroundColor());
|
||||
UIUtil.enableEagerSoftWrapping(myPane);
|
||||
String textToRender = myItem.textToRender;
|
||||
if (textToRender == null) {
|
||||
@@ -330,6 +340,10 @@ class DocRenderer implements EditorCustomElementRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable String getSelectedText() {
|
||||
return myPane == null ? null : myPane.getSelectedText();
|
||||
}
|
||||
|
||||
private static EditorKit createEditorKit(@NotNull Editor editor) {
|
||||
HTMLEditorKit editorKit = new MyEditorKit();
|
||||
editorKit.getStyleSheet().addStyleSheet(getStyleSheet(editor));
|
||||
@@ -568,4 +582,23 @@ class DocRenderer implements EditorCustomElementRenderer {
|
||||
super.paint(scalingGraphics, a);
|
||||
}
|
||||
}
|
||||
|
||||
private class CopySelection extends DumbAwareAction {
|
||||
CopySelection() {
|
||||
super(CodeInsightBundle.messagePointer("doc.render.copy.action.text"), AllIcons.Actions.Copy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
e.getPresentation().setVisible(!StringUtil.isEmpty(getSelectedText()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
String text = getSelectedText();
|
||||
if (!StringUtil.isEmpty(text)) {
|
||||
CopyPasteManager.getInstance().setContents(new StringSelection(text));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4284,7 +4284,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
validateMousePointer(e, null);
|
||||
((TransactionGuardImpl)TransactionGuard.getInstance()).performUserActivity(() -> runMouseDraggedCommand(e));
|
||||
EditorMouseEvent event = new EditorMouseEvent(EditorImpl.this, e, getMouseEventArea(e));
|
||||
EditorMouseEvent event = createEditorMouseEvent(e);
|
||||
if (event.getArea() == EditorMouseEventArea.LINE_MARKERS_AREA) {
|
||||
myGutterComponent.mouseDragged(e);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user