2020
2121package processing .app ;
2222
23- import javax .swing .JTextArea ;
23+ import java .io .IOException ;
24+ import java .net .URL ;
25+ import java .awt .Desktop ;
26+ import java .net .URLEncoder ;
27+
28+ import java .util .*;
29+ import java .util .regex .*;
30+
31+ import javax .swing .text .html .HTMLDocument ;
32+ import javax .swing .JEditorPane ;
33+ import javax .swing .JTextPane ;
2434import javax .swing .SwingUtilities ;
35+ import javax .swing .event .HyperlinkEvent ;
36+ import javax .swing .event .HyperlinkListener ;
2537import javax .swing .event .DocumentEvent ;
2638import javax .swing .event .DocumentListener ;
2739import javax .swing .text .BadLocationException ;
40+ import javax .swing .text .html .HTMLEditorKit ;
41+
42+ import cc .arduino .UpdatableBoardsLibsFakeURLsHandler ;
2843
29- public class TextAreaFIFO extends JTextArea implements DocumentListener {
44+ public class TextAreaFIFO extends JTextPane implements DocumentListener {
3045 private int maxChars ;
3146 private int trimMaxChars ;
3247
3348 private int updateCount ; // limit how often we trim the document
3449
3550 private boolean doTrim ;
51+ private final HTMLEditorKit kit ;
3652
3753 public TextAreaFIFO (int max ) {
3854 maxChars = max ;
3955 trimMaxChars = max / 2 ;
4056 updateCount = 0 ;
4157 doTrim = true ;
4258 getDocument ().addDocumentListener (this );
59+ setText ("" );
60+ kit = new HTMLEditorKit ();
61+ this .addHyperlinkListener (new UpdatableBoardsLibsFakeURLsHandler (Base .INSTANCE ));
4362 }
4463
4564 public void insertUpdate (DocumentEvent e ) {
46- if (++updateCount > 150 && doTrim ) {
47- updateCount = 0 ;
48- SwingUtilities .invokeLater (new Runnable () {
49- public void run () {
50- trimDocument ();
51- }
52- });
53- }
5465 }
5566
5667 public void removeUpdate (DocumentEvent e ) {
@@ -72,6 +83,61 @@ public void trimDocument() {
7283 }
7384 }
7485
86+ private static List <String > extractUrls (String input ) {
87+ List <String > result = new ArrayList <String >();
88+
89+ Pattern pattern = Pattern .compile (
90+ "(http|ftp|https)://([^\\ s]+)" );
91+
92+ Matcher matcher = pattern .matcher (input );
93+ while (matcher .find ()) {
94+ result .add (matcher .group ());
95+ }
96+
97+ return result ;
98+ }
99+
100+ static public final String WITH_DELIMITER = "((?<=%1$s)|(?=%1$s))" ;
101+
102+ public void append (String s ) {
103+ try {
104+ HTMLDocument doc = (HTMLDocument ) getDocument ();
105+
106+ String strings [] = s .split (String .format (WITH_DELIMITER , "\\ r?\\ n" ));
107+
108+ for (int l = 0 ; l < strings .length ; l ++) {
109+ String str = strings [l ];
110+ List <String > urls = extractUrls (str );
111+
112+ if (urls .size () > 0 ) {
113+
114+ for (int i = 0 ; i < urls .size (); i ++) {
115+ if (!((urls .get (i )).contains ("</a>" ))) {
116+ str = str .replace (urls .get (i ), "<a href='" + urls .get (i ) + "'>" + urls .get (i ) + "</a>" );
117+ }
118+ }
119+
120+ kit .insertHTML (doc , doc .getLength (), str , 0 , 0 , null );
121+ } else {
122+ doc .insertString (doc .getLength (), str , null );
123+ }
124+ }
125+ } catch (BadLocationException exc ) {
126+ exc .printStackTrace ();
127+ } catch (IOException exc ) {
128+ exc .printStackTrace ();
129+ }
130+
131+ if (++updateCount > 150 && doTrim ) {
132+ updateCount = 0 ;
133+ SwingUtilities .invokeLater (new Runnable () {
134+ public void run () {
135+ trimDocument ();
136+ }
137+ });
138+ }
139+ }
140+
75141 public void appendNoTrim (String s ) {
76142 int free = maxChars - getDocument ().getLength ();
77143 if (free <= 0 )
0 commit comments