Skip to content

Commit abdb93c

Browse files
ricardojlrufinoFederico Fissore
authored and
Federico Fissore
committed
hyperlinks enabled by default on comment
1 parent 4dde285 commit abdb93c

File tree

1 file changed

+175
-0
lines changed

1 file changed

+175
-0
lines changed

Diff for: app/src/processing/app/syntax/SketchTextArea.java

+175
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,28 @@
3333
import org.fife.ui.rsyntaxtextarea.Theme;
3434
import org.fife.ui.rsyntaxtextarea.Token;
3535
import org.fife.ui.rsyntaxtextarea.focusabletip.FocusableTip;
36+
import org.fife.ui.rtextarea.RTextArea;
3637
import org.fife.ui.rtextarea.RUndoManager;
38+
3739
import processing.app.*;
3840

3941
import javax.swing.*;
42+
import javax.swing.event.EventListenerList;
4043
import javax.swing.event.HyperlinkEvent;
44+
import javax.swing.event.HyperlinkListener;
4145
import javax.swing.text.BadLocationException;
4246
import javax.swing.text.Document;
4347
import javax.swing.text.Segment;
4448
import javax.swing.undo.UndoManager;
49+
4550
import java.awt.*;
4651
import java.awt.event.KeyEvent;
52+
import java.awt.event.MouseEvent;
4753
import java.io.File;
4854
import java.io.FileInputStream;
4955
import java.io.IOException;
56+
import java.net.MalformedURLException;
57+
import java.net.URL;
5058
import java.util.HashSet;
5159
import java.util.Map;
5260
import java.util.Set;
@@ -228,6 +236,11 @@ protected JPopupMenu createPopupMenu() {
228236
protected void configurePopupMenu(JPopupMenu popupMenu) {
229237
super.configurePopupMenu(popupMenu);
230238
}
239+
240+
@Override
241+
protected RTAMouseListener createMouseListener() {
242+
return new SketchTextAreaMouseListener(this);
243+
}
231244

232245
public void getTextLine(int line, Segment segment) {
233246
try {
@@ -296,5 +309,167 @@ public HyperlinkEvent execute() {
296309
return null;
297310
}
298311
}
312+
313+
314+
/**
315+
* Handles http hyperlinks.
316+
* NOTE (@Ricardo JL Rufino): Workaround to enable hyperlinks by default: https://github.com/bobbylight/RSyntaxTextArea/issues/119
317+
*/
318+
private class SketchTextAreaMouseListener extends RTextAreaMutableCaretEvent {
319+
320+
private Insets insets;
321+
private boolean isScanningForLinks;
322+
private int hoveredOverLinkOffset = -1;
323+
324+
protected SketchTextAreaMouseListener(RTextArea textArea) {
325+
super(textArea);
326+
insets = new Insets(0, 0, 0, 0);
327+
}
328+
329+
/**
330+
* Notifies all listeners that have registered interest for notification
331+
* on this event type. The listener list is processed last to first.
332+
*
333+
* @param e The event to fire.
334+
* @see EventListenerList
335+
*/
336+
private void fireHyperlinkUpdate(HyperlinkEvent e) {
337+
// Guaranteed to return a non-null array
338+
Object[] listeners = listenerList.getListenerList();
339+
// Process the listeners last to first, notifying
340+
// those that are interested in this event
341+
for (int i = listeners.length-2; i>=0; i-=2) {
342+
if (listeners[i]==HyperlinkListener.class) {
343+
((HyperlinkListener)listeners[i+1]).hyperlinkUpdate(e);
344+
}
345+
}
346+
}
347+
348+
private HyperlinkEvent createHyperlinkEvent(MouseEvent e) {
349+
HyperlinkEvent he = null;
350+
351+
Token t = viewToToken(e.getPoint());
352+
if (t!=null) {
353+
// Copy token, viewToModel() unfortunately modifies Token
354+
t = new TokenImpl(t);
355+
}
356+
357+
if (t != null && t.isHyperlink()) {
358+
URL url = null;
359+
String desc = null;
360+
try {
361+
String temp = t.getLexeme();
362+
// URI's need "http://" prefix for web URL's to work.
363+
if (temp.startsWith("www.")) {
364+
temp = "http://" + temp;
365+
}
366+
url = new URL(temp);
367+
} catch (MalformedURLException mue) {
368+
desc = mue.getMessage();
369+
}
370+
he = new HyperlinkEvent(SketchTextArea.this, HyperlinkEvent.EventType.ACTIVATED, url, desc);
371+
}
372+
373+
return he;
374+
}
375+
376+
@Override
377+
public void mouseClicked(MouseEvent e) {
378+
if (getHyperlinksEnabled()) {
379+
HyperlinkEvent he = createHyperlinkEvent(e);
380+
if (he!=null) {
381+
fireHyperlinkUpdate(he);
382+
}
383+
}
384+
}
385+
386+
@Override
387+
public void mouseMoved(MouseEvent e) {
388+
389+
super.mouseMoved(e);
390+
391+
if (!getHyperlinksEnabled()) {
392+
return;
393+
}
394+
395+
// LinkGenerator linkGenerator = getLinkGenerator();
396+
397+
// GitHub issue RSyntaxTextArea/#25 - links identified at "edges" of editor
398+
// should not be activated if mouse is in margin insets.
399+
insets = getInsets(insets);
400+
if (insets!=null) {
401+
int x = e.getX();
402+
int y = e.getY();
403+
if (x<=insets.left || y<insets.top) {
404+
if (isScanningForLinks) {
405+
stopScanningForLinks();
406+
}
407+
return;
408+
}
409+
}
410+
411+
isScanningForLinks = true;
412+
Token t = viewToToken(e.getPoint());
413+
if (t!=null) {
414+
// Copy token, viewToModel() unfortunately modifies Token
415+
t = new TokenImpl(t);
416+
}
417+
Cursor c2 = null;
418+
if (t!=null && t.isHyperlink()) {
419+
if (hoveredOverLinkOffset==-1 ||
420+
hoveredOverLinkOffset!=t.getOffset()) {
421+
hoveredOverLinkOffset = t.getOffset();
422+
repaint();
423+
}
424+
c2 = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
425+
}
426+
// else if (t!=null && linkGenerator!=null) {
427+
// int offs = viewToModel(e.getPoint());
428+
// LinkGeneratorResult newResult = linkGenerator.
429+
// isLinkAtOffset(SketchTextArea.this, offs);
430+
// if (newResult!=null) {
431+
// // Repaint if we're at a new link now.
432+
// if (linkGeneratorResult==null ||
433+
// !equal(newResult, linkGeneratorResult)) {
434+
// repaint();
435+
// }
436+
// linkGeneratorResult = newResult;
437+
// hoveredOverLinkOffset = t.getOffset();
438+
// c2 = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
439+
// }
440+
// else {
441+
// // Repaint if we've moved off of a link.
442+
// if (linkGeneratorResult!=null) {
443+
// repaint();
444+
// }
445+
// c2 = Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR);
446+
// hoveredOverLinkOffset = -1;
447+
// linkGeneratorResult = null;
448+
// }
449+
// }
450+
else {
451+
c2 = Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR);
452+
hoveredOverLinkOffset = -1;
453+
// linkGeneratorResult = null;
454+
}
455+
if (getCursor()!=c2) {
456+
setCursor(c2);
457+
// TODO: Repaint just the affected line(s).
458+
repaint(); // Link either left or went into.
459+
}
460+
}
461+
462+
private void stopScanningForLinks() {
463+
if (isScanningForLinks) {
464+
Cursor c = getCursor();
465+
isScanningForLinks = false;
466+
if (c != null && c.getType() == Cursor.HAND_CURSOR) {
467+
setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
468+
repaint(); // TODO: Repaint just the affected line.
469+
}
470+
}
471+
}
472+
473+
}
299474

300475
}

0 commit comments

Comments
 (0)