diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 5bf855e72..51253e4e6 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -435,7 +435,13 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se private Map abcExplorerDialogs = new WeakHashMap<>(); private Map breakpointsListDialogs = new WeakHashMap<>(); + + private boolean loadingScrollPosEnabled = true; + public synchronized void setLoadingScrollPosEnabled(boolean loadingScrollPosEnabled) { + this.loadingScrollPosEnabled = loadingScrollPosEnabled; + } + public void savePins() { pinsPanel.save(); } @@ -6361,16 +6367,19 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se folderPreviewPanel.setSelectedItems(folderItems); folderPreviewScrollBar.setValue(scrollValue); } - - View.execInEventDispatchLater(new Runnable() { - @Override - public void run() { - scrollPosStorage.loadScrollPos(oldItem); - } - }); - + + if (loadingScrollPosEnabled) { + View.execInEventDispatchLater(new Runnable() { + @Override + public void run() { + scrollPosStorage.loadScrollPos(oldItem); + } + }); + } } + + public void repaintTree() { tagTree.repaint(); tagListTree.repaint(); diff --git a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java index 51c68a9af..52f505ae4 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java @@ -1040,7 +1040,7 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL } @Override - public synchronized void setText(String t) { + public void setText(String t) { super.setText(t); setCaretPosition(0); } @@ -1076,7 +1076,7 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL } @Override - public synchronized void setCaretPosition(int position) { + public void setCaretPosition(int position) { super.setCaretPosition(position); } } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java b/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java index 50d90b308..ec520cea0 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.usages.multinames.MultinameUsage; import com.jpexs.decompiler.flash.abc.usages.multinames.TraitMultinameUsage; import com.jpexs.decompiler.flash.gui.AppDialog; import com.jpexs.decompiler.flash.gui.FasterScrollPane; +import com.jpexs.decompiler.flash.gui.Main; import com.jpexs.decompiler.flash.gui.View; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import java.awt.BorderLayout; @@ -36,6 +37,8 @@ import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.List; +import java.util.Timer; +import java.util.TimerTask; import javax.swing.JButton; import javax.swing.JList; import javax.swing.JPanel; @@ -142,9 +145,17 @@ public class UsageFrame extends AppDialog implements MouseListener { } else { decompiledTextArea.gotoClassHeader(); } + Timer tim = new Timer(); + tim.schedule(new TimerTask() { + @Override + public void run() { + Main.getMainFrame().getPanel().setLoadingScrollPosEnabled(true); + } + }, 500); } }; + Main.getMainFrame().getPanel().setLoadingScrollPosEnabled(false); if (decompiledTextArea.getClassIndex() == icu.getClassIndex() && abcPanel.abc == newAbc) { setTrait.run(); } else { diff --git a/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java b/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java index 2d5b63c62..e8e6fa8fa 100644 --- a/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java @@ -21,19 +21,11 @@ import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.simpleparser.SimpleParser; import com.jpexs.helpers.Reference; import java.awt.Color; -import java.awt.Cursor; import java.awt.FontMetrics; import java.awt.Graphics; -import java.awt.KeyEventPostProcessor; -import java.awt.KeyboardFocusManager; import java.awt.Point; import java.awt.Rectangle; import java.awt.Shape; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; import java.awt.geom.Rectangle2D; import java.util.Collections; import java.util.HashMap; @@ -76,8 +68,6 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan private Token lastUnderlined = null; - private static final HighlightPainter underLinePainter = new UnderLinePainter(new Color(0, 0, 255)); - private LinkHandler linkHandler = this; private Point lastCursorPos = new Point(0, 0); @@ -338,29 +328,7 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan } } - }); - final LinkAdapter la = new LinkAdapter(); - addMouseMotionListener(la); - addMouseListener(la); - - //No standard AddKeyListener as we want to catch Ctrl globally no matter of focus - KeyboardFocusManager.getCurrentKeyboardFocusManager() - .addKeyEventPostProcessor(new KeyEventPostProcessor() { - @Override - public boolean postProcessKeyEvent(KeyEvent e) { - if (e.getID() == KeyEvent.KEY_PRESSED) { - la.keyPressed(e); - } - if (e.getID() == KeyEvent.KEY_RELEASED) { - la.keyReleased(e); - } - if (e.getID() == KeyEvent.KEY_TYPED) { - la.keyTyped(e); - } - return false; - } - }); - + }); } public Token tokenAtPos(Point lastPos) { @@ -399,85 +367,7 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan public Token getTokenUnderCursor() { return tokenAtPos(lastCursorPos); } - - private class LinkAdapter extends MouseAdapter implements KeyListener { - - private boolean ctrlDown = false; - - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_CONTROL) { - ctrlDown = true; - update(); - } - } - - @Override - public void keyTyped(KeyEvent e) { - - } - - @Override - public void keyReleased(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_CONTROL) { - ctrlDown = false; - update(); - } - } - - private void update() { - if (ctrlDown) { - Token t = tokenAtPos(lastCursorPos); - - if (t != lastUnderlined) { - if (t == null || lastUnderlined == null || !t.equals(lastUnderlined)) { - MyMarkers.removeMarkers(LineMarkedEditorPane.this, underLinePainter); - - if (t != null && linkHandler.isLink(t)) { - lastUnderlined = t; - setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); - - } else { - lastUnderlined = null; - } - } else { - lastUnderlined = null; - } - } - - if (lastUnderlined != null) { - MyMarkers.markToken(LineMarkedEditorPane.this, lastUnderlined, underLinePainter); - } else { - setCursor(Cursor.getDefaultCursor()); - } - repaint(); - } else { - lastUnderlined = null; - MyMarkers.removeMarkers(LineMarkedEditorPane.this, underLinePainter); - setCursor(Cursor.getDefaultCursor()); - repaint(); - } - } - - @Override - public void mouseClicked(MouseEvent e) { - if (ctrlDown) { - Token t = tokenAtPos(lastCursorPos); - if (t != null && linkHandler.isLink(t)) { - linkHandler.handleLink(t); - } - } - } - - @Override - public void mouseMoved(MouseEvent e) { - - ctrlDown = (e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0; - lastCursorPos = e.getPoint(); - update(); - - } - } + public void setLinkHandler(LinkHandler linkHandler) { if (linkHandler == null) { @@ -492,7 +382,7 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan @Override public HighlightPainter linkPainter() { - return underLinePainter; + return null; } @Override @@ -586,78 +476,7 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan } } - public static class UnderLinePainter extends DefaultHighlighter.DefaultHighlightPainter { - - public UnderLinePainter(Color color) { - super(color); - } - - @Override - public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) { - try { - // --- determine locations --- - TextUI mapper = c.getUI(); - - Color col = getColor(); - if (col == null) { - col = Color.black; - } - g.setColor(col); - for (int i = offs0; i < offs1; i++) { - - Rectangle2D r = com.jpexs.decompiler.flash.gui.View.textUIModelToView(mapper, c, i, Position.Bias.Forward); - Rectangle2D r1 = com.jpexs.decompiler.flash.gui.View.textUIModelToView(mapper, c, i + 1, Position.Bias.Forward); - if (r1.getY() == r.getY()) { - g.drawLine((int) r.getX(), (int) (r.getY() + r.getHeight() - 3), (int) r1.getX(), (int) (r.getY() + r.getHeight() - 3)); - } - } - - } catch (BadLocationException e) { - // can't render - } - } - - @Override - public Shape paintLayer(Graphics g, int offs0, int offs1, - Shape bounds, JTextComponent c, View view) { - - g.setColor(c.getSelectionColor()); - - Rectangle r; - - if (offs0 == view.getStartOffset() - && offs1 == view.getEndOffset()) { - // Contained in view, can just use bounds. - if (bounds instanceof Rectangle) { - r = (Rectangle) bounds; - } else { - r = bounds.getBounds(); - } - } else { - // Should only render part of View. - try { - // --- determine locations --- - Shape shape = view.modelToView(offs0, Position.Bias.Forward, - offs1, Position.Bias.Backward, - bounds); - r = (shape instanceof Rectangle) - ? (Rectangle) shape : shape.getBounds(); - } catch (BadLocationException e) { - // can't render - r = null; - } - } - - if (r != null) { - r.width = Math.max(r.width, 1); - - paint(g, offs0, offs1, r, c); - - } - - return r; - } - } + private int cut(double val) { int ival = (int) Math.round(val); diff --git a/src/com/jpexs/decompiler/flash/gui/editor/UnderlinePainter.java b/src/com/jpexs/decompiler/flash/gui/editor/UnderlinePainter.java new file mode 100644 index 000000000..e63203ed4 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/editor/UnderlinePainter.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2025 JPEXS + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.jpexs.decompiler.flash.gui.editor; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.geom.Rectangle2D; +import javax.swing.plaf.TextUI; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.JTextComponent; +import javax.swing.text.Position; +import javax.swing.text.View; + +/** + * + * @author JPEXS + */ +public class UnderlinePainter extends OccurencesMarker { + + private final Color underlineColor; + + public UnderlinePainter(Color underLineColor, Color backgroundColor) { + super(backgroundColor); + this.underlineColor = underLineColor; + } + + @Override + public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) { + if (getColor() != null) { + super.paint(g, offs0, offs1, bounds, c); + } + + try { + // --- determine locations --- + TextUI mapper = c.getUI(); + + Color col = underlineColor; + if (col == null) { + col = Color.black; + } + g.setColor(col); + for (int i = offs0; i < offs1; i++) { + + Rectangle2D r = com.jpexs.decompiler.flash.gui.View.textUIModelToView(mapper, c, i, Position.Bias.Forward); + Rectangle2D r1 = com.jpexs.decompiler.flash.gui.View.textUIModelToView(mapper, c, i + 1, Position.Bias.Forward); + if (r1.getY() == r.getY()) { + g.drawLine((int) r.getX(), (int) (r.getY() + r.getHeight() - 3), (int) r1.getX(), (int) (r.getY() + r.getHeight() - 3)); + } + } + + } catch (BadLocationException e) { + // can't render + } + } + + @Override + public Shape paintLayer(Graphics g, int offs0, int offs1, + Shape bounds, JTextComponent c, View view) { + + g.setColor(c.getSelectionColor()); + + Rectangle r; + + if (offs0 == view.getStartOffset() + && offs1 == view.getEndOffset()) { + // Contained in view, can just use bounds. + if (bounds instanceof Rectangle) { + r = (Rectangle) bounds; + } else { + r = bounds.getBounds(); + } + } else { + // Should only render part of View. + try { + // --- determine locations --- + Shape shape = view.modelToView(offs0, Position.Bias.Forward, + offs1, Position.Bias.Backward, + bounds); + r = (shape instanceof Rectangle) + ? (Rectangle) shape : shape.getBounds(); + } catch (BadLocationException e) { + // can't render + r = null; + } + } + + if (r != null) { + r.width = Math.max(r.width, 1); + + paint(g, offs0, offs1, r, c); + + } + + return r; + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/editor/VariableMarker.java b/src/com/jpexs/decompiler/flash/gui/editor/VariableMarker.java index 582ba6fe1..18ffc453c 100644 --- a/src/com/jpexs/decompiler/flash/gui/editor/VariableMarker.java +++ b/src/com/jpexs/decompiler/flash/gui/editor/VariableMarker.java @@ -20,6 +20,14 @@ import com.jpexs.decompiler.flash.simpleparser.SimpleParseException; import com.jpexs.decompiler.flash.simpleparser.SimpleParser; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Cursor; +import java.awt.KeyEventPostProcessor; +import java.awt.KeyboardFocusManager; +import java.awt.Point; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.beans.PropertyChangeEvent; @@ -35,11 +43,9 @@ import java.util.Timer; import java.util.TimerTask; import java.util.logging.Logger; import javax.swing.JEditorPane; -import javax.swing.JLayer; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JScrollPane; -import javax.swing.ScrollPaneConstants; import javax.swing.SwingUtilities; import javax.swing.event.CaretEvent; import javax.swing.event.CaretListener; @@ -93,6 +99,17 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC private ScrollBarUI originalScrollBarUI; + private LinkAdapter linkAdapter; + + private KeyEventPostProcessor kevEventPostProcessor; + + private Set occurencesPositions = new HashSet<>(); + + private UnderlinePainter underLinePainter = new UnderlinePainter(new Color(0, 0, 255), null); + private UnderlinePainter underLineMarkOccurencesPainter = new UnderlinePainter(new Color(0, 0, 255), DEFAULT_COLOR); + + private Token lastUnderlined; + /** * Constructs a new Token highlighter */ @@ -127,6 +144,9 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC */ public void removeMarkers() { Markers.removeMarkers(pane, marker); + Markers.removeMarkers(pane, underLinePainter); + Markers.removeMarkers(pane, underLineMarkOccurencesPainter); + occurencesPositions.clear(); } public void removeErrorMarkers() { @@ -158,14 +178,14 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC private Token getNearestTokenAt(SyntaxDocument sDoc, int pos) { Token thisToken = sDoc.getTokenAt(pos); if (thisToken != null) { - + if (thisToken.length == 1) { Token nextToken = sDoc.getTokenAt(pos + 1); if (nextToken != null && nextToken.start == pos && nextToken.length > 1) { return nextToken; } } - + return thisToken; } @@ -185,7 +205,7 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC void addErrorMarkers() { highlightsPanel.setErrors(errors); - + SyntaxDocument doc = ActionUtils.getSyntaxDocument(pane); if (doc == null) { return; @@ -216,11 +236,13 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC Token definitionToken = getIdentifierTokenAt(sDoc, definitionPos < 0 ? -(definitionPos + 1) : definitionPos); if (definitionToken != null) { if (definitionPosToReferences.containsKey(definitionPos)) { - Markers.markToken(pane, definitionToken, marker); + Markers.markToken(pane, definitionToken, lastUnderlined == definitionToken ? underLineMarkOccurencesPainter : marker); + occurencesPositions.add(definitionToken.start); for (int i : definitionPosToReferences.get(definitionPos)) { Token referenceToken = getIdentifierTokenAt(sDoc, i); if (referenceToken != null) { - Markers.markToken(pane, referenceToken, marker); + Markers.markToken(pane, referenceToken, lastUnderlined == referenceToken ? underLineMarkOccurencesPainter : marker); + occurencesPositions.add(referenceToken.start); } } } @@ -255,9 +277,9 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC editor.addCaretListener(this); editor.addPropertyChangeListener(this); editor.getDocument().addDocumentListener(this); - if (editor instanceof LineMarkedEditorPane) { + /*if (editor instanceof LineMarkedEditorPane) { ((LineMarkedEditorPane) editor).setLinkHandler(this); - } + }*/ mouseMotionAdapter = new MouseMotionAdapter() { @Override public void mouseMoved(MouseEvent e) { @@ -282,11 +304,128 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC JPanel panel = (JPanel) SwingUtilities.getAncestorOfClass(JPanel.class, scrollPane); panel.add(highlightsPanel, BorderLayout.EAST); + linkAdapter = new LinkAdapter(); + + pane.addMouseListener(linkAdapter); + pane.addMouseMotionListener(linkAdapter); + + //No standard AddKeyListener as we want to catch Ctrl globally no matter of focus + kevEventPostProcessor = new KeyEventPostProcessor() { + @Override + public boolean postProcessKeyEvent(KeyEvent e) { + if (e.getID() == KeyEvent.KEY_PRESSED) { + linkAdapter.keyPressed(e); + } + if (e.getID() == KeyEvent.KEY_RELEASED) { + linkAdapter.keyReleased(e); + } + if (e.getID() == KeyEvent.KEY_TYPED) { + linkAdapter.keyTyped(e); + } + return false; + } + }; + KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventPostProcessor(kevEventPostProcessor); + documentUpdated(); markTokenAt(editor.getCaretPosition()); status = Status.INSTALLING; } + private class LinkAdapter extends MouseAdapter implements KeyListener { + + private boolean ctrlDown = false; + + private Point lastCursorPos; + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_CONTROL) { + ctrlDown = true; + update(); + } + } + + @Override + public void keyTyped(KeyEvent e) { + + } + + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_CONTROL) { + ctrlDown = false; + update(); + } + } + + private void update() { + if (ctrlDown) { + Token t = ((LineMarkedEditorPane) pane).tokenAtPos(lastCursorPos); + + if (t != lastUnderlined) { + if (t == null || lastUnderlined == null || !t.equals(lastUnderlined)) { + MyMarkers.removeMarkers(pane, underLinePainter); + MyMarkers.removeMarkers(pane, underLineMarkOccurencesPainter); + + if (t != null && isLink(t)) { + lastUnderlined = t; + pane.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + + } else { + lastUnderlined = null; + + removeMarkers(); + markTokenAt(pane.getCaretPosition()); + } + } else { + lastUnderlined = null; + } + } + + if (lastUnderlined != null) { + Highlighter.HighlightPainter painter = underLinePainter; + if (occurencesPositions.contains(lastUnderlined.start)) { + painter = underLineMarkOccurencesPainter; + removeMarkers(); + markTokenAt(pane.getCaretPosition()); + } else { + MyMarkers.markToken(pane, lastUnderlined, painter); + } + } else { + pane.setCursor(Cursor.getDefaultCursor()); + } + } else { + lastUnderlined = null; + MyMarkers.removeMarkers(pane, underLinePainter); + MyMarkers.removeMarkers(pane, underLineMarkOccurencesPainter); + removeMarkers(); + markTokenAt(pane.getCaretPosition()); + pane.setCursor(Cursor.getDefaultCursor()); + } + } + + @Override + public void mouseClicked(MouseEvent e) { + if (ctrlDown) { + Token t = ((LineMarkedEditorPane) pane).tokenAtPos(lastCursorPos); + if (t != null && isLink(t)) { + e.consume(); + handleLink(t); + } + } + } + + @Override + public void mouseMoved(MouseEvent e) { + + ctrlDown = (e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0; + lastCursorPos = e.getPoint(); + update(); + + } + } + private void editorMouseMoved(MouseEvent e) { if (pane instanceof LineMarkedEditorPane) { Token token = ((LineMarkedEditorPane) pane).getTokenUnderCursor(); @@ -313,10 +452,13 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC pane.getDocument().removeDocumentListener(this); pane.removeCaretListener(this); pane.removeMouseMotionListener(mouseMotionAdapter); + pane.removeMouseMotionListener(linkAdapter); + pane.removeMouseListener(linkAdapter); + KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventPostProcessor(kevEventPostProcessor); mouseMotionAdapter = null; - if (editor instanceof LineMarkedEditorPane) { + /*if (editor instanceof LineMarkedEditorPane) { ((LineMarkedEditorPane) editor).setLinkHandler(null); - } + }*/ JScrollPane scrollPane = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, editor); JPanel panel = (JPanel) SwingUtilities.getAncestorOfClass(JPanel.class, scrollPane); panel.remove(highlightsPanel); @@ -376,7 +518,7 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC } catch (SimpleParseException ex) { definitionPosToReferences.clear(); referenceToDefinition.clear(); - errors.put((int) ex.position, ex.getMessage()); + errors.put((int) ex.position, ex.getMessage()); } Timer tim = errorsTimer; if (tim != null) { @@ -412,14 +554,27 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC @Override public boolean isLink(Token token) { - return referenceToDefinition.containsKey(token.start) && referenceToDefinition.get(token.start) >= 0; + boolean linkBasic = referenceToDefinition.containsKey(token.start) && referenceToDefinition.get(token.start) >= 0; + if (linkBasic) { + return true; + } + if (pane.isEditable()) { + return false; + } + return ((LineMarkedEditorPane) pane).getLinkHandler().isLink(token); } @Override public void handleLink(Token token) { Integer definition = referenceToDefinition.get(token.start); - if (definition != null) { + if (definition != null && definition >= 0) { pane.setCaretPosition(definition); + } else if (!pane.isEditable()) { + lastUnderlined = null; + removeErrorMarkers(); + removeMarkers(); + pane.repaint(); + ((LineMarkedEditorPane) pane).getLinkHandler().handleLink(token); } }