2626import javax .swing .SwingUtilities ;
2727import javax .swing .border .EmptyBorder ;
2828import javax .swing .text .DefaultCaret ;
29+ import javax .swing .event .UndoableEditListener ;
30+ import javax .swing .text .AbstractDocument ;
31+ import javax .swing .text .Document ;
2932
3033import cc .arduino .packages .BoardPort ;
3134
@@ -34,14 +37,20 @@ public abstract class AbstractTextMonitor extends AbstractMonitor {
3437
3538 protected JLabel noLineEndingAlert ;
3639 protected TextAreaFIFO textArea ;
40+ protected HTMLTextAreaFIFO htmlTextArea ;
3741 protected JScrollPane scrollPane ;
42+ protected JScrollPane htmlScrollPane ;
3843 protected JTextField textField ;
3944 protected JButton sendButton ;
4045 protected JButton clearButton ;
4146 protected JCheckBox autoscrollBox ;
4247 protected JCheckBox addTimeStampBox ;
4348 protected JComboBox lineEndings ;
4449 protected JComboBox serialRates ;
50+ protected Container mainPane ;
51+ private long lastMessage ;
52+ private javax .swing .Timer updateTimer ;
53+ private boolean htmlView = true ;
4554
4655 private SimpleDateFormat logDateFormat ;
4756
@@ -55,6 +64,7 @@ protected void onCreateWindow(Container mainPane) {
5564 Font editorFont = PreferencesData .getFont ("editor.font" );
5665 Font font = Theme .scale (new Font (consoleFont .getName (), consoleFont .getStyle (), editorFont .getSize ()));
5766
67+ this .mainPane = mainPane ;
5868 mainPane .setLayout (new BorderLayout ());
5969
6070 textArea = new TextAreaFIFO (8000000 );
@@ -63,13 +73,89 @@ protected void onCreateWindow(Container mainPane) {
6373 textArea .setEditable (false );
6474 textArea .setFont (font );
6575
76+ htmlTextArea = new HTMLTextAreaFIFO (8000000 );
77+ htmlTextArea .setEditable (false );
78+ htmlTextArea .setFont (font );
79+ htmlTextArea .setOpaque (false );
80+
6681 // don't automatically update the caret. that way we can manually decide
6782 // whether or not to do so based on the autoscroll checkbox.
6883 ((DefaultCaret ) textArea .getCaret ()).setUpdatePolicy (DefaultCaret .NEVER_UPDATE );
84+ ((DefaultCaret ) htmlTextArea .getCaret ()).setUpdatePolicy (DefaultCaret .NEVER_UPDATE );
85+
86+ Document doc = textArea .getDocument ();
87+ if (doc instanceof AbstractDocument )
88+ {
89+ UndoableEditListener [] undoListeners =
90+ ( (AbstractDocument ) doc ).getUndoableEditListeners ();
91+ if (undoListeners .length > 0 )
92+ {
93+ for (UndoableEditListener undoListener : undoListeners )
94+ {
95+ doc .removeUndoableEditListener (undoListener );
96+ }
97+ }
98+ }
99+
100+ doc = htmlTextArea .getDocument ();
101+ if (doc instanceof AbstractDocument )
102+ {
103+ UndoableEditListener [] undoListeners =
104+ ( (AbstractDocument ) doc ).getUndoableEditListeners ();
105+ if (undoListeners .length > 0 )
106+ {
107+ for (UndoableEditListener undoListener : undoListeners )
108+ {
109+ doc .removeUndoableEditListener (undoListener );
110+ }
111+ }
112+ }
69113
70114 scrollPane = new JScrollPane (textArea );
115+ scrollPane .setVerticalScrollBarPolicy (JScrollPane .VERTICAL_SCROLLBAR_AS_NEEDED );
116+ htmlScrollPane = new JScrollPane (htmlTextArea );
117+ htmlScrollPane .setVerticalScrollBarPolicy (JScrollPane .VERTICAL_SCROLLBAR_AS_NEEDED );
118+
119+ ActionListener checkIfSteady = new ActionListener () {
120+ public void actionPerformed (ActionEvent evt ) {
121+ if (System .currentTimeMillis () - lastMessage > 200 ) {
122+ if (htmlView == false && textArea .getLength () < 1000 ) {
123+
124+ htmlTextArea .setText ("" );
125+ boolean res = htmlTextArea .append (textArea .getText ());
126+ if (res ) {
127+ htmlView = true ;
128+ mainPane .remove (scrollPane );
129+ if (textArea .getCaretPosition () > htmlTextArea .getDocument ().getLength ()) {
130+ htmlTextArea .setCaretPosition (htmlTextArea .getDocument ().getLength ());
131+ } else {
132+ htmlTextArea .setCaretPosition (textArea .getCaretPosition ());
133+ }
134+ mainPane .add (htmlScrollPane , BorderLayout .CENTER );
135+ scrollPane .setVisible (false );
136+ mainPane .validate ();
137+ mainPane .repaint ();
138+ }
139+ }
140+ } else {
141+ if (htmlView == true ) {
142+ htmlView = false ;
143+ mainPane .remove (htmlScrollPane );
144+ mainPane .add (scrollPane , BorderLayout .CENTER );
145+ scrollPane .setVisible (true );
146+ mainPane .validate ();
147+ mainPane .repaint ();
148+ }
149+ }
150+ }
151+ };
152+
153+ updateTimer = new javax .swing .Timer (33 , checkIfSteady );
71154
72155 mainPane .add (scrollPane , BorderLayout .CENTER );
156+
157+ htmlTextArea .setVisible (true );
158+ htmlScrollPane .setVisible (true );
73159
74160 JPanel upperPane = new JPanel ();
75161 upperPane .setLayout (new BoxLayout (upperPane , BoxLayout .X_AXIS ));
@@ -146,19 +232,26 @@ public void actionPerformed(ActionEvent e) {
146232 pane .add (clearButton );
147233
148234 mainPane .add (pane , BorderLayout .SOUTH );
235+
236+ updateTimer .start ();
149237 }
150238
151239 protected void onEnableWindow (boolean enable )
152240 {
153241 textArea .setEnabled (enable );
154242 clearButton .setEnabled (enable );
243+ htmlTextArea .setEnabled (enable );
155244 scrollPane .setEnabled (enable );
245+ htmlScrollPane .setEnabled (enable );
156246 textField .setEnabled (enable );
157247 sendButton .setEnabled (enable );
158248 autoscrollBox .setEnabled (enable );
159249 addTimeStampBox .setEnabled (enable );
160250 lineEndings .setEnabled (enable );
161251 serialRates .setEnabled (enable );
252+ if (enable == false ) {
253+ htmlTextArea .setText ("" );
254+ }
162255 }
163256
164257 public void onSendCommand (ActionListener listener ) {
@@ -173,8 +266,9 @@ public void onClearCommand(ActionListener listener) {
173266 public void onSerialRateChange (ActionListener listener ) {
174267 serialRates .addActionListener (listener );
175268 }
176-
269+
177270 public void message (final String s ) {
271+ lastMessage = System .currentTimeMillis ();
178272 SwingUtilities .invokeLater (new Runnable () {
179273 // Pre-allocate all objects used for streaming data
180274 Date t = new Date ();
0 commit comments