2121import javax .swing .SwingUtilities ;
2222import javax .swing .border .EmptyBorder ;
2323import javax .swing .text .DefaultCaret ;
24+ import javax .swing .event .UndoableEditListener ;
25+ import javax .swing .text .AbstractDocument ;
26+ import javax .swing .text .Document ;
2427
2528import cc .arduino .packages .BoardPort ;
2629
@@ -29,12 +32,18 @@ public abstract class AbstractTextMonitor extends AbstractMonitor {
2932
3033 protected JLabel noLineEndingAlert ;
3134 protected TextAreaFIFO textArea ;
35+ protected HTMLTextAreaFIFO htmlTextArea ;
3236 protected JScrollPane scrollPane ;
37+ protected JScrollPane htmlScrollPane ;
3338 protected JTextField textField ;
3439 protected JButton sendButton ;
3540 protected JCheckBox autoscrollBox ;
3641 protected JComboBox lineEndings ;
3742 protected JComboBox serialRates ;
43+ protected Container mainPane ;
44+ private long lastMessage ;
45+ private javax .swing .Timer updateTimer ;
46+ private boolean htmlView = true ;
3847
3948 public AbstractTextMonitor (BoardPort boardPort ) {
4049 super (boardPort );
@@ -45,6 +54,7 @@ protected void onCreateWindow(Container mainPane) {
4554 Font editorFont = PreferencesData .getFont ("editor.font" );
4655 Font font = Theme .scale (new Font (consoleFont .getName (), consoleFont .getStyle (), editorFont .getSize ()));
4756
57+ this .mainPane = mainPane ;
4858 mainPane .setLayout (new BorderLayout ());
4959
5060 textArea = new TextAreaFIFO (8000000 );
@@ -53,13 +63,89 @@ protected void onCreateWindow(Container mainPane) {
5363 textArea .setEditable (false );
5464 textArea .setFont (font );
5565
66+ htmlTextArea = new HTMLTextAreaFIFO (8000000 );
67+ htmlTextArea .setEditable (false );
68+ htmlTextArea .setFont (font );
69+ htmlTextArea .setOpaque (false );
70+
5671 // don't automatically update the caret. that way we can manually decide
5772 // whether or not to do so based on the autoscroll checkbox.
5873 ((DefaultCaret ) textArea .getCaret ()).setUpdatePolicy (DefaultCaret .NEVER_UPDATE );
74+ ((DefaultCaret ) htmlTextArea .getCaret ()).setUpdatePolicy (DefaultCaret .NEVER_UPDATE );
75+
76+ Document doc = textArea .getDocument ();
77+ if (doc instanceof AbstractDocument )
78+ {
79+ UndoableEditListener [] undoListeners =
80+ ( (AbstractDocument ) doc ).getUndoableEditListeners ();
81+ if (undoListeners .length > 0 )
82+ {
83+ for (UndoableEditListener undoListener : undoListeners )
84+ {
85+ doc .removeUndoableEditListener (undoListener );
86+ }
87+ }
88+ }
89+
90+ doc = htmlTextArea .getDocument ();
91+ if (doc instanceof AbstractDocument )
92+ {
93+ UndoableEditListener [] undoListeners =
94+ ( (AbstractDocument ) doc ).getUndoableEditListeners ();
95+ if (undoListeners .length > 0 )
96+ {
97+ for (UndoableEditListener undoListener : undoListeners )
98+ {
99+ doc .removeUndoableEditListener (undoListener );
100+ }
101+ }
102+ }
59103
60104 scrollPane = new JScrollPane (textArea );
105+ scrollPane .setVerticalScrollBarPolicy (JScrollPane .VERTICAL_SCROLLBAR_AS_NEEDED );
106+ htmlScrollPane = new JScrollPane (htmlTextArea );
107+ htmlScrollPane .setVerticalScrollBarPolicy (JScrollPane .VERTICAL_SCROLLBAR_AS_NEEDED );
108+
109+ ActionListener checkIfSteady = new ActionListener () {
110+ public void actionPerformed (ActionEvent evt ) {
111+ if (System .currentTimeMillis () - lastMessage > 200 ) {
112+ if (htmlView == false && textArea .getLength () < 1000 ) {
113+
114+ htmlTextArea .setText ("" );
115+ boolean res = htmlTextArea .append (textArea .getText ());
116+ if (res ) {
117+ htmlView = true ;
118+ mainPane .remove (scrollPane );
119+ if (textArea .getCaretPosition () > htmlTextArea .getDocument ().getLength ()) {
120+ htmlTextArea .setCaretPosition (htmlTextArea .getDocument ().getLength ());
121+ } else {
122+ htmlTextArea .setCaretPosition (textArea .getCaretPosition ());
123+ }
124+ mainPane .add (htmlScrollPane , BorderLayout .CENTER );
125+ scrollPane .setVisible (false );
126+ mainPane .validate ();
127+ mainPane .repaint ();
128+ }
129+ }
130+ } else {
131+ if (htmlView == true ) {
132+ htmlView = false ;
133+ mainPane .remove (htmlScrollPane );
134+ mainPane .add (scrollPane , BorderLayout .CENTER );
135+ scrollPane .setVisible (true );
136+ mainPane .validate ();
137+ mainPane .repaint ();
138+ }
139+ }
140+ }
141+ };
142+
143+ updateTimer = new javax .swing .Timer (33 , checkIfSteady );
61144
62145 mainPane .add (scrollPane , BorderLayout .CENTER );
146+
147+ htmlTextArea .setVisible (true );
148+ htmlScrollPane .setVisible (true );
63149
64150 JPanel upperPane = new JPanel ();
65151 upperPane .setLayout (new BoxLayout (upperPane , BoxLayout .X_AXIS ));
@@ -115,17 +201,24 @@ public void actionPerformed(ActionEvent event) {
115201 pane .add (serialRates );
116202
117203 mainPane .add (pane , BorderLayout .SOUTH );
204+
205+ updateTimer .start ();
118206 }
119207
120208 protected void onEnableWindow (boolean enable )
121209 {
122210 textArea .setEnabled (enable );
211+ htmlTextArea .setEnabled (enable );
123212 scrollPane .setEnabled (enable );
213+ htmlScrollPane .setEnabled (enable );
124214 textField .setEnabled (enable );
125215 sendButton .setEnabled (enable );
126216 autoscrollBox .setEnabled (enable );
127217 lineEndings .setEnabled (enable );
128218 serialRates .setEnabled (enable );
219+ if (enable == false ) {
220+ htmlTextArea .setText ("" );
221+ }
129222 }
130223
131224 public void onSendCommand (ActionListener listener ) {
@@ -136,8 +229,9 @@ public void onSendCommand(ActionListener listener) {
136229 public void onSerialRateChange (ActionListener listener ) {
137230 serialRates .addActionListener (listener );
138231 }
139-
232+
140233 public void message (final String s ) {
234+ lastMessage = System .currentTimeMillis ();
141235 SwingUtilities .invokeLater (new Runnable () {
142236 public void run () {
143237 textArea .append (s );
0 commit comments