Skip to content

Commit 7d66a7d

Browse files
ricardojlrufinoFederico Fissore
authored and
Federico Fissore
committed
hyperlinks enabled by default on comment
1 parent 3d8219c commit 7d66a7d

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,18 +33,26 @@
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.IOException;
54+
import java.net.MalformedURLException;
55+
import java.net.URL;
4856
import java.util.HashSet;
4957
import java.util.Map;
5058
import java.util.Set;
@@ -219,6 +227,11 @@ protected JPopupMenu createPopupMenu() {
219227
protected void configurePopupMenu(JPopupMenu popupMenu) {
220228
super.configurePopupMenu(popupMenu);
221229
}
230+
231+
@Override
232+
protected RTAMouseListener createMouseListener() {
233+
return new SketchTextAreaMouseListener(this);
234+
}
222235

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

291466
}

0 commit comments

Comments
 (0)