Skip to content

Commit ab92e42

Browse files
committed
Merge branch 'master' into ide-1.5.x
Conflicts: app/src/processing/app/Serial.java app/src/processing/app/SerialMonitor.java
2 parents 588f9f1 + 8e0a311 commit ab92e42

File tree

6 files changed

+190
-24
lines changed

6 files changed

+190
-24
lines changed

app/src/processing/app/AbstractMonitor.java

+62-10
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,53 @@
11
package processing.app;
22

3-
import processing.app.debug.MessageConsumer;
4-
import processing.app.legacy.PApplet;
3+
import static processing.app.I18n._;
54

6-
import javax.swing.*;
7-
import javax.swing.border.EmptyBorder;
8-
import javax.swing.text.DefaultCaret;
9-
import java.awt.*;
5+
import java.awt.BorderLayout;
6+
import java.awt.Dimension;
7+
import java.awt.Font;
8+
import java.awt.Rectangle;
9+
import java.awt.Toolkit;
1010
import java.awt.event.ActionEvent;
1111
import java.awt.event.ActionListener;
1212
import java.awt.event.WindowAdapter;
1313
import java.awt.event.WindowEvent;
1414

15-
import static processing.app.I18n._;
15+
import javax.swing.AbstractAction;
16+
import javax.swing.Box;
17+
import javax.swing.BoxLayout;
18+
import javax.swing.JButton;
19+
import javax.swing.JCheckBox;
20+
import javax.swing.JComboBox;
21+
import javax.swing.JComponent;
22+
import javax.swing.JFrame;
23+
import javax.swing.JLabel;
24+
import javax.swing.JPanel;
25+
import javax.swing.JScrollPane;
26+
import javax.swing.JTextField;
27+
import javax.swing.KeyStroke;
28+
import javax.swing.SwingUtilities;
29+
import javax.swing.Timer;
30+
import javax.swing.border.EmptyBorder;
31+
import javax.swing.text.DefaultCaret;
32+
33+
import processing.app.debug.TextAreaFIFO;
34+
import processing.app.legacy.PApplet;
1635

1736
@SuppressWarnings("serial")
18-
public abstract class AbstractMonitor extends JFrame implements MessageConsumer {
37+
public abstract class AbstractMonitor extends JFrame implements ActionListener {
1938

2039
protected final JLabel noLineEndingAlert;
21-
protected JTextArea textArea;
40+
protected TextAreaFIFO textArea;
2241
protected JScrollPane scrollPane;
2342
protected JTextField textField;
2443
protected JButton sendButton;
2544
protected JCheckBox autoscrollBox;
2645
protected JComboBox lineEndings;
2746
protected JComboBox serialRates;
2847

48+
private Timer updateTimer;
49+
private StringBuffer updateBuffer;
50+
2951
public AbstractMonitor(String title) {
3052
super(title);
3153

@@ -59,7 +81,9 @@ public void actionPerformed(ActionEvent event) {
5981
Font editorFont = Preferences.getFont("editor.font");
6082
Font font = new Font(consoleFont.getName(), consoleFont.getStyle(), editorFont.getSize());
6183

62-
textArea = new JTextArea(16, 40);
84+
textArea = new TextAreaFIFO(8000000);
85+
textArea.setRows(16);
86+
textArea.setColumns(40);
6387
textArea.setEditable(false);
6488
textArea.setFont(font);
6589

@@ -149,6 +173,10 @@ public void actionPerformed(ActionEvent event) {
149173
}
150174
}
151175
}
176+
177+
updateBuffer = new StringBuffer(1048576);
178+
updateTimer = new Timer(33, this); // redraw serial monitor at 30 Hz
179+
updateTimer.start();
152180
}
153181

154182
public void onSerialRateChange(ActionListener listener) {
@@ -199,4 +227,28 @@ public String getAuthorizationKey() {
199227
public abstract void open() throws Exception;
200228

201229
public abstract void close() throws Exception;
230+
231+
public synchronized void addToUpdateBuffer(char buff[], int n) {
232+
updateBuffer.append(buff, 0, n);
233+
}
234+
235+
private synchronized String consumeUpdateBuffer() {
236+
String s = updateBuffer.toString();
237+
updateBuffer.setLength(0);
238+
return s;
239+
}
240+
241+
public void actionPerformed(ActionEvent e) {
242+
final String s = consumeUpdateBuffer();
243+
if (s.length() > 0) {
244+
//System.out.println("gui append " + s.length());
245+
if (autoscrollBox.isSelected()) {
246+
textArea.appendTrim(s);
247+
textArea.setCaretPosition(textArea.getDocument().getLength());
248+
} else {
249+
textArea.appendNoTrim(s);
250+
}
251+
}
252+
}
253+
202254
}

app/src/processing/app/NetworkMonitor.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
import cc.arduino.packages.ssh.SSHClientSetupChainRing;
66
import cc.arduino.packages.ssh.SSHConfigFileSetup;
77
import cc.arduino.packages.ssh.SSHPwdSetup;
8+
89
import com.jcraft.jsch.*;
10+
11+
import processing.app.debug.MessageConsumer;
912
import processing.app.debug.MessageSiphon;
1013

1114
import javax.swing.*;
15+
1216
import java.awt.event.ActionEvent;
1317
import java.awt.event.ActionListener;
1418
import java.io.IOException;
@@ -18,7 +22,7 @@
1822
import static processing.app.I18n._;
1923

2024
@SuppressWarnings("serial")
21-
public class NetworkMonitor extends AbstractMonitor {
25+
public class NetworkMonitor extends AbstractMonitor implements MessageConsumer {
2226

2327
private static final int MAX_CONNECTION_ATTEMPTS = 5;
2428

app/src/processing/app/SerialMonitor.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,12 @@ private void send(String s) {
9191
public void open() throws Exception {
9292
if (serial != null) return;
9393

94-
serial = new Serial(port, serialRate);
95-
serial.addListener(this);
94+
serial = new Serial(port, serialRate) {
95+
@Override
96+
protected void message(char buff[], int n) {
97+
addToUpdateBuffer(buff, n);
98+
}
99+
};
96100
}
97101

98102
public void close() throws Exception {
@@ -105,4 +109,5 @@ public void close() throws Exception {
105109
serial = null;
106110
}
107111
}
112+
108113
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
Copyright (c) 2014 Paul Stoffregen <[email protected]>
3+
4+
This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation; either version 2 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program; if not, write to the Free Software Foundation,
16+
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+
18+
$Id$
19+
*/
20+
21+
// adapted from https://community.oracle.com/thread/1479784
22+
23+
package processing.app.debug;
24+
25+
import javax.swing.JTextArea;
26+
import javax.swing.SwingUtilities;
27+
import javax.swing.event.DocumentEvent;
28+
import javax.swing.event.DocumentListener;
29+
import javax.swing.text.BadLocationException;
30+
31+
public class TextAreaFIFO extends JTextArea implements DocumentListener {
32+
private int maxChars;
33+
private int trimMaxChars;
34+
35+
private int updateCount; // limit how often we trim the document
36+
37+
private boolean doTrim;
38+
39+
public TextAreaFIFO(int max) {
40+
maxChars = max;
41+
trimMaxChars = max / 2;
42+
updateCount = 0;
43+
doTrim = true;
44+
getDocument().addDocumentListener(this);
45+
}
46+
47+
public void insertUpdate(DocumentEvent e) {
48+
if (++updateCount > 150 && doTrim) {
49+
updateCount = 0;
50+
SwingUtilities.invokeLater(new Runnable() {
51+
public void run() {
52+
trimDocument();
53+
}
54+
});
55+
}
56+
}
57+
58+
public void removeUpdate(DocumentEvent e) {
59+
}
60+
61+
public void changedUpdate(DocumentEvent e) {
62+
}
63+
64+
public void trimDocument() {
65+
int len = 0;
66+
len = getDocument().getLength();
67+
if (len > trimMaxChars) {
68+
int n = len - trimMaxChars;
69+
//System.out.println("trimDocument: remove " + n + " chars");
70+
try {
71+
getDocument().remove(0, n);
72+
} catch (BadLocationException ble) {
73+
}
74+
}
75+
}
76+
77+
public void appendNoTrim(String s) {
78+
int free = maxChars - getDocument().getLength();
79+
if (free <= 0)
80+
return;
81+
if (s.length() > free)
82+
append(s.substring(0, free));
83+
else
84+
append(s);
85+
doTrim = false;
86+
}
87+
88+
public void appendTrim(String str) {
89+
append(str);
90+
doTrim = true;
91+
}
92+
}

arduino-core/src/processing/app/Serial.java

+14-11
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import jssc.SerialPortEvent;
3535
import jssc.SerialPortEventListener;
3636
import jssc.SerialPortException;
37-
import processing.app.debug.MessageConsumer;
3837

3938

4039
public class Serial implements SerialPortEventListener {
@@ -60,8 +59,6 @@ public class Serial implements SerialPortEventListener {
6059
int bufferIndex;
6160
int bufferLast;
6261

63-
MessageConsumer consumer;
64-
6562
public Serial(boolean monitor) throws SerialException {
6663
this(PreferencesData.get("serial.port"),
6764
PreferencesData.getInteger("serial.debug_rate"),
@@ -168,10 +165,6 @@ public void dispose() throws IOException {
168165
}
169166
}
170167

171-
public void addListener(MessageConsumer consumer) {
172-
this.consumer = consumer;
173-
}
174-
175168
public synchronized void serialEvent(SerialPortEvent serialEvent) {
176169
if (serialEvent.isRXCHAR()) {
177170
try {
@@ -182,19 +175,29 @@ public synchronized void serialEvent(SerialPortEvent serialEvent) {
182175
System.arraycopy(buffer, 0, temp, 0, bufferLast);
183176
buffer = temp;
184177
}
178+
String msg = new String(buf);
185179
if (monitor) {
186-
System.out.print(new String(buf));
187-
}
188-
if (this.consumer != null) {
189-
this.consumer.message(new String(buf));
180+
System.out.print(msg);
190181
}
182+
char[] chars = msg.toCharArray();
183+
message(chars, chars.length);
191184
}
192185
} catch (SerialPortException e) {
193186
errorMessage("serialEvent", e);
194187
}
195188
}
196189
}
197190

191+
/**
192+
* This method is intented to be extended to receive messages
193+
* coming from serial port.
194+
*
195+
* @param chars
196+
* @param length
197+
*/
198+
protected void message(char[] chars, int length) {
199+
// Empty
200+
}
198201

199202
/**
200203
* Returns the number of bytes that have been read from serial

build/shared/revisions.txt

+10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11

2+
ARDUINO 1.6.0rc2
3+
4+
The following changes are included also in the Arduino IDE 1.0.7:
5+
6+
[ide]
7+
* Mitigated Serial Monitor resource exhaustion when the connected device sends a lot of data (Paul Stoffregen)
8+
29
ARDUINO 1.6.0rc1
310

411
* IDE internals have been refactored and sorted out. (Claudio Indellicati)
@@ -379,6 +386,9 @@ ARDUINO 1.0.7
379386
* Fixed missing NOT_AN_INTERRUPT constant in digitalPinToInterrupt() macro
380387
* Fixed performance regression in HardwareSerial::available() introduced with https://github.com/arduino/Arduino/pull/2057
381388

389+
[ide]
390+
* Mitigated Serial Monitor resource exhaustion when the connected device sends a lot of data (Paul Stoffregen)
391+
382392
ARDUINO 1.0.6 - 2014.09.16
383393

384394
[core]

0 commit comments

Comments
 (0)