3131import javax .swing .border .EmptyBorder ;
3232import javax .swing .text .DefaultCaret ;
3333import javax .swing .text .DefaultEditorKit ;
34+ import javax .swing .event .UndoableEditListener ;
35+ import javax .swing .text .AbstractDocument ;
36+ import javax .swing .text .Document ;
3437
3538import cc .arduino .packages .BoardPort ;
3639
@@ -39,14 +42,20 @@ public abstract class AbstractTextMonitor extends AbstractMonitor {
3942
4043 protected JLabel noLineEndingAlert ;
4144 protected TextAreaFIFO textArea ;
45+ protected HTMLTextAreaFIFO htmlTextArea ;
4246 protected JScrollPane scrollPane ;
47+ protected JScrollPane htmlScrollPane ;
4348 protected JTextField textField ;
4449 protected JButton sendButton ;
4550 protected JButton clearButton ;
4651 protected JCheckBox autoscrollBox ;
4752 protected JCheckBox addTimeStampBox ;
4853 protected JComboBox <String > lineEndings ;
4954 protected JComboBox <String > serialRates ;
55+ protected Container mainPane ;
56+ private long lastMessage ;
57+ private javax .swing .Timer updateTimer ;
58+ private boolean htmlView = true ;
5059
5160 public AbstractTextMonitor (BoardPort boardPort ) {
5261 super (boardPort );
@@ -68,21 +77,97 @@ public synchronized void addKeyListener(KeyListener l) {
6877 @ Override
6978 protected void onCreateWindow (Container mainPane ) {
7079
80+ this .mainPane = mainPane ;
7181 mainPane .setLayout (new BorderLayout ());
7282
7383 textArea = new TextAreaFIFO (8_000_000 );
7484 textArea .setRows (16 );
7585 textArea .setColumns (40 );
7686 textArea .setEditable (false );
7787
88+ htmlTextArea = new HTMLTextAreaFIFO (8000000 );
89+ htmlTextArea .setEditable (false );
90+ htmlTextArea .setOpaque (false );
91+
7892 // don't automatically update the caret. that way we can manually decide
7993 // whether or not to do so based on the autoscroll checkbox.
8094 ((DefaultCaret ) textArea .getCaret ()).setUpdatePolicy (DefaultCaret .NEVER_UPDATE );
95+ ((DefaultCaret ) htmlTextArea .getCaret ()).setUpdatePolicy (DefaultCaret .NEVER_UPDATE );
96+
97+ Document doc = textArea .getDocument ();
98+ if (doc instanceof AbstractDocument )
99+ {
100+ UndoableEditListener [] undoListeners =
101+ ( (AbstractDocument ) doc ).getUndoableEditListeners ();
102+ if (undoListeners .length > 0 )
103+ {
104+ for (UndoableEditListener undoListener : undoListeners )
105+ {
106+ doc .removeUndoableEditListener (undoListener );
107+ }
108+ }
109+ }
110+
111+ doc = htmlTextArea .getDocument ();
112+ if (doc instanceof AbstractDocument )
113+ {
114+ UndoableEditListener [] undoListeners =
115+ ( (AbstractDocument ) doc ).getUndoableEditListeners ();
116+ if (undoListeners .length > 0 )
117+ {
118+ for (UndoableEditListener undoListener : undoListeners )
119+ {
120+ doc .removeUndoableEditListener (undoListener );
121+ }
122+ }
123+ }
81124
82125 scrollPane = new JScrollPane (textArea );
126+ scrollPane .setVerticalScrollBarPolicy (JScrollPane .VERTICAL_SCROLLBAR_AS_NEEDED );
127+ htmlScrollPane = new JScrollPane (htmlTextArea );
128+ htmlScrollPane .setVerticalScrollBarPolicy (JScrollPane .VERTICAL_SCROLLBAR_AS_NEEDED );
129+
130+ ActionListener checkIfSteady = new ActionListener () {
131+ public void actionPerformed (ActionEvent evt ) {
132+ if (System .currentTimeMillis () - lastMessage > 200 ) {
133+ if (htmlView == false && textArea .getLength () < 1000 ) {
134+
135+ htmlTextArea .setText ("" );
136+ boolean res = htmlTextArea .append (textArea .getText ());
137+ if (res ) {
138+ htmlView = true ;
139+ mainPane .remove (scrollPane );
140+ if (textArea .getCaretPosition () > htmlTextArea .getDocument ().getLength ()) {
141+ htmlTextArea .setCaretPosition (htmlTextArea .getDocument ().getLength ());
142+ } else {
143+ htmlTextArea .setCaretPosition (textArea .getCaretPosition ());
144+ }
145+ mainPane .add (htmlScrollPane , BorderLayout .CENTER );
146+ scrollPane .setVisible (false );
147+ mainPane .validate ();
148+ mainPane .repaint ();
149+ }
150+ }
151+ } else {
152+ if (htmlView == true ) {
153+ htmlView = false ;
154+ mainPane .remove (htmlScrollPane );
155+ mainPane .add (scrollPane , BorderLayout .CENTER );
156+ scrollPane .setVisible (true );
157+ mainPane .validate ();
158+ mainPane .repaint ();
159+ }
160+ }
161+ }
162+ };
163+
164+ updateTimer = new javax .swing .Timer (33 , checkIfSteady );
83165
84166 mainPane .add (scrollPane , BorderLayout .CENTER );
85167
168+ htmlTextArea .setVisible (true );
169+ htmlScrollPane .setVisible (true );
170+
86171 JPanel upperPane = new JPanel ();
87172 upperPane .setLayout (new BoxLayout (upperPane , BoxLayout .X_AXIS ));
88173 upperPane .setBorder (new EmptyBorder (4 , 4 , 4 , 4 ));
@@ -167,20 +252,27 @@ public void windowGainedFocus(WindowEvent e) {
167252 applyPreferences ();
168253
169254 mainPane .add (pane , BorderLayout .SOUTH );
255+
256+ updateTimer .start ();
170257 }
171258
172259 @ Override
173260 protected void onEnableWindow (boolean enable )
174261 {
175262 textArea .setEnabled (enable );
176263 clearButton .setEnabled (enable );
264+ htmlTextArea .setEnabled (enable );
177265 scrollPane .setEnabled (enable );
266+ htmlScrollPane .setEnabled (enable );
178267 textField .setEnabled (enable );
179268 sendButton .setEnabled (enable );
180269 autoscrollBox .setEnabled (enable );
181270 addTimeStampBox .setEnabled (enable );
182271 lineEndings .setEnabled (enable );
183272 serialRates .setEnabled (enable );
273+ if (enable == false ) {
274+ htmlTextArea .setText ("" );
275+ }
184276 }
185277
186278 public void onSendCommand (ActionListener listener ) {
@@ -198,6 +290,7 @@ public void onSerialRateChange(ActionListener listener) {
198290
199291 @ Override
200292 public void message (String msg ) {
293+ lastMessage = System .currentTimeMillis ();
201294 SwingUtilities .invokeLater (() -> updateTextArea (msg ));
202295 }
203296
0 commit comments