3232import javax .swing .border .EmptyBorder ;
3333import javax .swing .text .DefaultCaret ;
3434import javax .swing .text .DefaultEditorKit ;
35+ import javax .swing .event .UndoableEditListener ;
36+ import javax .swing .text .AbstractDocument ;
37+ import javax .swing .text .Document ;
3538
3639import cc .arduino .packages .BoardPort ;
3740
@@ -40,14 +43,20 @@ public abstract class AbstractTextMonitor extends AbstractMonitor {
4043
4144 protected JLabel noLineEndingAlert ;
4245 protected TextAreaFIFO textArea ;
46+ protected HTMLTextAreaFIFO htmlTextArea ;
4347 protected JScrollPane scrollPane ;
48+ protected JScrollPane htmlScrollPane ;
4449 protected JTextField textField ;
4550 protected JButton sendButton ;
4651 protected JButton clearButton ;
4752 protected JCheckBox autoscrollBox ;
4853 protected JCheckBox addTimeStampBox ;
4954 protected JComboBox <String > lineEndings ;
5055 protected JComboBox <String > serialRates ;
56+ protected Container mainPane ;
57+ private long lastMessage ;
58+ private javax .swing .Timer updateTimer ;
59+ private boolean htmlView = true ;
5160
5261 public AbstractTextMonitor (BoardPort boardPort ) {
5362 super (boardPort );
@@ -69,21 +78,97 @@ public synchronized void addKeyListener(KeyListener l) {
6978 @ Override
7079 protected void onCreateWindow (Container mainPane ) {
7180
81+ this .mainPane = mainPane ;
7282 mainPane .setLayout (new BorderLayout ());
7383
7484 textArea = new TextAreaFIFO (8_000_000 );
7585 textArea .setRows (16 );
7686 textArea .setColumns (40 );
7787 textArea .setEditable (false );
7888
89+ htmlTextArea = new HTMLTextAreaFIFO (8000000 );
90+ htmlTextArea .setEditable (false );
91+ htmlTextArea .setOpaque (false );
92+
7993 // don't automatically update the caret. that way we can manually decide
8094 // whether or not to do so based on the autoscroll checkbox.
8195 ((DefaultCaret ) textArea .getCaret ()).setUpdatePolicy (DefaultCaret .NEVER_UPDATE );
96+ ((DefaultCaret ) htmlTextArea .getCaret ()).setUpdatePolicy (DefaultCaret .NEVER_UPDATE );
97+
98+ Document doc = textArea .getDocument ();
99+ if (doc instanceof AbstractDocument )
100+ {
101+ UndoableEditListener [] undoListeners =
102+ ( (AbstractDocument ) doc ).getUndoableEditListeners ();
103+ if (undoListeners .length > 0 )
104+ {
105+ for (UndoableEditListener undoListener : undoListeners )
106+ {
107+ doc .removeUndoableEditListener (undoListener );
108+ }
109+ }
110+ }
111+
112+ doc = htmlTextArea .getDocument ();
113+ if (doc instanceof AbstractDocument )
114+ {
115+ UndoableEditListener [] undoListeners =
116+ ( (AbstractDocument ) doc ).getUndoableEditListeners ();
117+ if (undoListeners .length > 0 )
118+ {
119+ for (UndoableEditListener undoListener : undoListeners )
120+ {
121+ doc .removeUndoableEditListener (undoListener );
122+ }
123+ }
124+ }
82125
83126 scrollPane = new JScrollPane (textArea );
127+ scrollPane .setVerticalScrollBarPolicy (JScrollPane .VERTICAL_SCROLLBAR_AS_NEEDED );
128+ htmlScrollPane = new JScrollPane (htmlTextArea );
129+ htmlScrollPane .setVerticalScrollBarPolicy (JScrollPane .VERTICAL_SCROLLBAR_AS_NEEDED );
130+
131+ ActionListener checkIfSteady = new ActionListener () {
132+ public void actionPerformed (ActionEvent evt ) {
133+ if (System .currentTimeMillis () - lastMessage > 200 ) {
134+ if (htmlView == false && textArea .getLength () < 1000 ) {
135+
136+ htmlTextArea .setText ("" );
137+ boolean res = htmlTextArea .append (textArea .getText ());
138+ if (res ) {
139+ htmlView = true ;
140+ mainPane .remove (scrollPane );
141+ if (textArea .getCaretPosition () > htmlTextArea .getDocument ().getLength ()) {
142+ htmlTextArea .setCaretPosition (htmlTextArea .getDocument ().getLength ());
143+ } else {
144+ htmlTextArea .setCaretPosition (textArea .getCaretPosition ());
145+ }
146+ mainPane .add (htmlScrollPane , BorderLayout .CENTER );
147+ scrollPane .setVisible (false );
148+ mainPane .validate ();
149+ mainPane .repaint ();
150+ }
151+ }
152+ } else {
153+ if (htmlView == true ) {
154+ htmlView = false ;
155+ mainPane .remove (htmlScrollPane );
156+ mainPane .add (scrollPane , BorderLayout .CENTER );
157+ scrollPane .setVisible (true );
158+ mainPane .validate ();
159+ mainPane .repaint ();
160+ }
161+ }
162+ }
163+ };
164+
165+ updateTimer = new javax .swing .Timer (33 , checkIfSteady );
84166
85167 mainPane .add (scrollPane , BorderLayout .CENTER );
86168
169+ htmlTextArea .setVisible (true );
170+ htmlScrollPane .setVisible (true );
171+
87172 JPanel upperPane = new JPanel ();
88173 upperPane .setLayout (new BoxLayout (upperPane , BoxLayout .X_AXIS ));
89174 upperPane .setBorder (new EmptyBorder (4 , 4 , 4 , 4 ));
@@ -168,6 +253,8 @@ public void windowGainedFocus(WindowEvent e) {
168253 applyPreferences ();
169254
170255 mainPane .add (pane , BorderLayout .SOUTH );
256+
257+ updateTimer .start ();
171258 }
172259
173260 @ Override
@@ -190,9 +277,21 @@ protected void onEnableWindow(boolean enable) {
190277 textArea .setBackground (new Color (238 , 238 , 238 ));
191278 }
192279 textArea .invalidate ();
280+
281+ clearButton .setEnabled (enable );
282+ htmlTextArea .setEnabled (enable );
193283 scrollPane .setEnabled (enable );
284+ htmlScrollPane .setEnabled (enable );
194285 textField .setEnabled (enable );
195286 sendButton .setEnabled (enable );
287+
288+ autoscrollBox .setEnabled (enable );
289+ addTimeStampBox .setEnabled (enable );
290+ lineEndings .setEnabled (enable );
291+ serialRates .setEnabled (enable );
292+ if (enable == false ) {
293+ htmlTextArea .setText ("" );
294+ }
196295 }
197296
198297 public void onSendCommand (ActionListener listener ) {
@@ -210,6 +309,7 @@ public void onSerialRateChange(ActionListener listener) {
210309
211310 @ Override
212311 public void message (String msg ) {
312+ lastMessage = System .currentTimeMillis ();
213313 SwingUtilities .invokeLater (() -> updateTextArea (msg ));
214314 }
215315
0 commit comments