From 45b73046309a2e40728a1a82a74551ef43295795 Mon Sep 17 00:00:00 2001 From: Skylot Date: Fri, 8 May 2020 19:53:20 +0100 Subject: [PATCH] fix: workaround for link clicks in RSyntaxTextArea (#929) --- .../java/jadx/gui/ui/codearea/CodeArea.java | 22 +++++++- .../gui/ui/codearea/CodeLinkGenerator.java | 56 +++++++++++++------ 2 files changed, 57 insertions(+), 21 deletions(-) diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java index 8e75db620..867dae715 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java @@ -1,5 +1,9 @@ package jadx.gui.ui.codearea; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + import javax.swing.*; import org.fife.ui.rsyntaxtextarea.RSyntaxDocument; @@ -38,9 +42,21 @@ public final class CodeArea extends AbstractCodeArea { } setHyperlinksEnabled(true); - CodeLinkGenerator codeLinkProcessor = new CodeLinkGenerator(this); - setLinkGenerator(codeLinkProcessor); - addHyperlinkListener(codeLinkProcessor); + setLinkScanningMask(InputEvent.CTRL_DOWN_MASK); + CodeLinkGenerator codeLinkGenerator = new CodeLinkGenerator(this); + setLinkGenerator(codeLinkGenerator); + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.isControlDown()) { + int offs = viewToModel(e.getPoint()); + JumpPosition jump = codeLinkGenerator.getJumpLinkAtOffset(CodeArea.this, offs); + if (jump != null) { + contentPanel.getTabbedPane().codeJump(jump); + } + } + } + }); } @Override diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeLinkGenerator.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeLinkGenerator.java index 44dcdc2cf..54e7233dd 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeLinkGenerator.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeLinkGenerator.java @@ -3,52 +3,61 @@ package jadx.gui.ui.codearea; import java.util.Objects; import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkListener; +import javax.swing.text.BadLocationException; import org.fife.ui.rsyntaxtextarea.LinkGenerator; import org.fife.ui.rsyntaxtextarea.LinkGeneratorResult; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rsyntaxtextarea.Token; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import jadx.gui.treemodel.JNode; -import jadx.gui.ui.ContentPanel; import jadx.gui.utils.JumpPosition; -public class CodeLinkGenerator implements LinkGenerator, HyperlinkListener { +public class CodeLinkGenerator implements LinkGenerator { private static final Logger LOG = LoggerFactory.getLogger(CodeLinkGenerator.class); - private final ContentPanel contentPanel; private final CodeArea codeArea; private final JNode jNode; public CodeLinkGenerator(CodeArea codeArea) { - this.contentPanel = codeArea.getContentPanel(); this.codeArea = codeArea; this.jNode = codeArea.getNode(); } + @Nullable + public JumpPosition getJumpLinkAtOffset(RSyntaxTextArea textArea, int offset) { + try { + if (jNode.getCodeInfo() == null) { + return null; + } + int sourceOffset = getLinkSourceOffset(textArea, offset); + if (sourceOffset == -1) { + return null; + } + return getJumpBySourceOffset(textArea, sourceOffset); + } catch (Exception e) { + LOG.error("getJumpLinkAtOffset error", e); + return null; + } + } + @Override public LinkGeneratorResult isLinkAtOffset(RSyntaxTextArea textArea, int offset) { try { if (jNode.getCodeInfo() == null) { return null; } - Token token = textArea.modelToToken(offset); - int sourceOffset = codeArea.adjustOffsetForToken(token); + int sourceOffset = getLinkSourceOffset(textArea, offset); if (sourceOffset == -1) { return null; } - final JumpPosition defPos = codeArea.getDefPosForNodeAtOffset(sourceOffset); + JumpPosition defPos = getJumpBySourceOffset(textArea, sourceOffset); if (defPos == null) { return null; } - if (Objects.equals(defPos.getNode().getRootClass(), jNode) - && defPos.getLine() == textArea.getLineOfOffset(sourceOffset) + 1) { - // ignore self jump - return null; - } return new LinkGeneratorResult() { @Override public HyperlinkEvent execute() { @@ -67,11 +76,22 @@ public class CodeLinkGenerator implements LinkGenerator, HyperlinkListener { } } - @Override - public void hyperlinkUpdate(HyperlinkEvent e) { - Object obj = e.getSource(); - if (obj instanceof JumpPosition) { - contentPanel.getTabbedPane().codeJump((JumpPosition) obj); + private int getLinkSourceOffset(RSyntaxTextArea textArea, int offset) { + Token token = textArea.modelToToken(offset); + return codeArea.adjustOffsetForToken(token); + } + + @Nullable + private JumpPosition getJumpBySourceOffset(RSyntaxTextArea textArea, int sourceOffset) throws BadLocationException { + final JumpPosition defPos = codeArea.getDefPosForNodeAtOffset(sourceOffset); + if (defPos == null) { + return null; } + if (Objects.equals(defPos.getNode().getRootClass(), jNode) + && defPos.getLine() == textArea.getLineOfOffset(sourceOffset) + 1) { + // ignore self jump + return null; + } + return defPos; } }