Skip to content

Commit 4cb72ce

Browse files
author
Federico Fissore
committed
Code cleanup
SerialPlotter now uses min/2 and max*2 instead of plain min and max Ticks works also when min == max Fixes #3767
1 parent a4a7e3e commit 4cb72ce

File tree

3 files changed

+121
-131
lines changed

3 files changed

+121
-131
lines changed

app/src/processing/app/SerialPlotter.java

Lines changed: 74 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -19,54 +19,55 @@
1919
package processing.app;
2020

2121
import cc.arduino.packages.BoardPort;
22+
import processing.app.helpers.CircularBuffer;
23+
import processing.app.helpers.Ticks;
2224
import processing.app.legacy.PApplet;
2325

24-
import processing.app.helpers.*;
25-
import static processing.app.I18n.tr;
26-
27-
import java.awt.*;
28-
import java.awt.event.*;
29-
import java.awt.geom.*;
3026
import javax.swing.*;
31-
import javax.swing.border.*;
27+
import javax.swing.border.EmptyBorder;
28+
import java.awt.*;
29+
import java.awt.event.ActionListener;
30+
import java.awt.geom.AffineTransform;
31+
import java.awt.geom.Rectangle2D;
32+
33+
import static processing.app.I18n.tr;
3234

3335
public class SerialPlotter extends AbstractMonitor {
34-
private StringBuffer messageBuffer;
35-
private CircularBuffer buffer;
36-
private GraphPanel graphPanel;
37-
private JComboBox serialRates;
3836

37+
private final StringBuffer messageBuffer;
38+
private CircularBuffer buffer;
39+
private JComboBox<String> serialRates;
3940
private Serial serial;
4041
private int serialRate;
4142

4243
private class GraphPanel extends JPanel {
4344
private double minY, maxY, rangeY;
4445
private Rectangle bounds;
4546
private int xOffset;
46-
private Font font;
47-
private Color graphColor;
48-
47+
private final Font font;
48+
private final Color graphColor;
49+
4950
public GraphPanel() {
5051
font = Theme.getFont("console.font");
5152
graphColor = Theme.getColor("header.bgcolor");
5253
xOffset = 20;
5354
}
54-
55+
5556
@Override
5657
public void paintComponent(Graphics g1) {
57-
Graphics2D g = (Graphics2D)g1;
58+
Graphics2D g = (Graphics2D) g1;
5859
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
5960
g.setFont(font);
6061
super.paintComponent(g);
61-
62+
6263
bounds = g.getClipBounds();
6364
setBackground(Color.WHITE);
64-
if(buffer.isEmpty()) {
65+
if (buffer.isEmpty()) {
6566
return;
6667
}
67-
68-
minY = buffer.min();
69-
maxY = buffer.max();
68+
69+
minY = buffer.min() / 2;
70+
maxY = buffer.max() * 2;
7071
Ticks ticks = new Ticks(minY, maxY, 3);
7172
minY = Math.min(minY, ticks.getTick(0));
7273
maxY = Math.max(maxY, ticks.getTick(ticks.getTickCount() - 1));
@@ -77,45 +78,45 @@ public void paintComponent(Graphics g1) {
7778

7879
g.setStroke(new BasicStroke(1.0f));
7980
FontMetrics fm = g.getFontMetrics();
80-
for(int i = 0; i < ticks.getTickCount(); ++i) {
81+
for (int i = 0; i < ticks.getTickCount(); ++i) {
8182
double tick = ticks.getTick(i);
8283
Rectangle2D fRect = fm.getStringBounds(String.valueOf(tick), g);
83-
xOffset = Math.max(xOffset, (int)fRect.getWidth() + 15);
84+
xOffset = Math.max(xOffset, (int) fRect.getWidth() + 15);
8485

8586
// draw tick
86-
g.drawLine(xOffset - 5, (int)transformY(tick), xOffset + 2, (int)transformY(tick));
87+
g.drawLine(xOffset - 5, (int) transformY(tick), xOffset + 2, (int) transformY(tick));
8788
// draw tick label
88-
g.drawString(String.valueOf(tick), xOffset - (int)fRect.getWidth() - 10, transformY(tick) - (float)fRect.getHeight() * 0.5f + fm.getAscent());
89+
g.drawString(String.valueOf(tick), xOffset - (int) fRect.getWidth() - 10, transformY(tick) - (float) fRect.getHeight() * 0.5f + fm.getAscent());
8990
}
9091

9192
g.drawLine(bounds.x + xOffset, bounds.y + 5, bounds.x + xOffset, bounds.y + bounds.height - 10);
92-
93-
g.setTransform(AffineTransform.getTranslateInstance(xOffset, 0));
94-
float xstep = (float)(bounds.width - xOffset) / (float)buffer.capacity();
95-
93+
94+
g.setTransform(AffineTransform.getTranslateInstance(xOffset, 0));
95+
float xstep = (float) (bounds.width - xOffset) / (float) buffer.capacity();
96+
9697
g.setColor(graphColor);
9798
g.setStroke(new BasicStroke(0.75f));
98-
99-
for(int i = 0; i < buffer.size() - 1; ++i) {
99+
100+
for (int i = 0; i < buffer.size() - 1; ++i) {
100101
g.drawLine(
101-
(int)(i * xstep), (int)transformY(buffer.get(i)),
102-
(int)((i + 1) * xstep), (int)transformY(buffer.get(i + 1))
102+
(int) (i * xstep), (int) transformY(buffer.get(i)),
103+
(int) ((i + 1) * xstep), (int) transformY(buffer.get(i + 1))
103104
);
104105
}
105106
}
106-
107+
107108
@Override
108109
public Dimension getMinimumSize() {
109110
return new Dimension(200, 100);
110111
}
111-
112+
112113
@Override
113114
public Dimension getPreferredSize() {
114115
return new Dimension(500, 250);
115116
}
116-
117+
117118
private float transformY(double rawY) {
118-
return (float)(5 + (bounds.height - 10) * (1.0 - (rawY - minY) / rangeY));
119+
return (float) (5 + (bounds.height - 10) * (1.0 - (rawY - minY) / rangeY));
119120
}
120121
}
121122

@@ -124,93 +125,80 @@ public SerialPlotter(BoardPort port) {
124125

125126
serialRate = PreferencesData.getInteger("serial.debug_rate");
126127
serialRates.setSelectedItem(serialRate + " " + tr("baud"));
127-
onSerialRateChange(new ActionListener() {
128-
public void actionPerformed(ActionEvent event) {
129-
String wholeString = (String) serialRates.getSelectedItem();
130-
String rateString = wholeString.substring(0, wholeString.indexOf(' '));
131-
serialRate = Integer.parseInt(rateString);
132-
PreferencesData.set("serial.debug_rate", rateString);
133-
try {
134-
close();
135-
Thread.sleep(100); // Wait for serial port to properly close
136-
open();
137-
} catch (InterruptedException e) {
138-
// noop
139-
} catch (Exception e) {
140-
System.err.println(e);
141-
}
128+
onSerialRateChange(event -> {
129+
String wholeString = (String) serialRates.getSelectedItem();
130+
String rateString = wholeString.substring(0, wholeString.indexOf(' '));
131+
serialRate = Integer.parseInt(rateString);
132+
PreferencesData.set("serial.debug_rate", rateString);
133+
try {
134+
close();
135+
Thread.sleep(100); // Wait for serial port to properly close
136+
open();
137+
} catch (Exception e) {
138+
// ignore
142139
}
143140
});
144141

145142
messageBuffer = new StringBuffer();
146143
}
147-
144+
148145
protected void onCreateWindow(Container mainPane) {
149146
mainPane.setLayout(new BorderLayout());
150-
151-
Font consoleFont = Theme.getFont("console.font");
152-
Font editorFont = PreferencesData.getFont("editor.font");
153-
Font font = new Font(consoleFont.getName(), consoleFont.getStyle(), editorFont.getSize());
154-
147+
155148
buffer = new CircularBuffer(500);
156-
graphPanel = new GraphPanel();
157-
149+
GraphPanel graphPanel = new GraphPanel();
150+
158151
mainPane.add(graphPanel, BorderLayout.CENTER);
159-
152+
160153
JPanel pane = new JPanel();
161154
pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS));
162155
pane.setBorder(new EmptyBorder(4, 4, 4, 4));
163-
164-
serialRates = new JComboBox();
165-
for (int i = 0; i < serialRateStrings.length; i++)
166-
serialRates.addItem(serialRateStrings[i] + " " + tr("baud"));
167-
156+
157+
serialRates = new JComboBox<>();
158+
for (String serialRateString : serialRateStrings) serialRates.addItem(serialRateString + " " + tr("baud"));
159+
168160
serialRates.setMaximumSize(serialRates.getMinimumSize());
169161

170162
pane.add(Box.createRigidArea(new Dimension(8, 0)));
171163
pane.add(serialRates);
172-
164+
173165
mainPane.add(pane, BorderLayout.SOUTH);
174166
}
175-
176-
protected void onEnableWindow(boolean enable)
177-
{
178-
serialRates.setEnabled(enable);
167+
168+
protected void onEnableWindow(boolean enable) {
169+
serialRates.setEnabled(enable);
179170
}
180-
181-
public void onSerialRateChange(ActionListener listener) {
171+
172+
private void onSerialRateChange(ActionListener listener) {
182173
serialRates.addActionListener(listener);
183174
}
184-
175+
185176
public void message(final String s) {
186177
messageBuffer.append(s);
187-
while(true) {
178+
while (true) {
188179
int linebreak = messageBuffer.indexOf("\n");
189-
if(linebreak == -1) {
180+
if (linebreak == -1) {
190181
break;
191182
}
192-
183+
193184
String line = messageBuffer.substring(0, linebreak);
194185
line = line.trim();
195186
messageBuffer.delete(0, linebreak + 1);
196-
187+
197188
try {
198189
double value = Double.valueOf(line);
199190
buffer.add(value);
200-
} catch(NumberFormatException e) {
201-
continue; // ignore lines that can't be cast to a number
191+
} catch (NumberFormatException e) {
192+
// ignore
202193
}
203194
}
204195

205-
SwingUtilities.invokeLater(new Runnable() {
206-
public void run() {
207-
SerialPlotter.this.repaint();
208-
}});
196+
SwingUtilities.invokeLater(SerialPlotter.this::repaint);
209197
}
210-
198+
211199
public void open() throws Exception {
212200
super.open();
213-
201+
214202
if (serial != null) return;
215203

216204
serial = new Serial(getBoardPort().getAddress(), serialRate) {

app/src/processing/app/helpers/CircularBuffer.java

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,77 +3,74 @@
33
import java.util.NoSuchElementException;
44

55
public class CircularBuffer {
6-
private double[] elements;
6+
7+
private final double[] elements;
78
private int start = -1;
89
private int end = -1;
9-
private int capacity;
10-
10+
private final int capacity;
11+
1112
public void add(double num) {
1213
end = (end + 1) % capacity;
1314
elements[end] = num;
14-
if(start == end || start == -1) {
15+
if (start == end || start == -1) {
1516
start = (start + 1) % capacity;
1617
}
1718
}
18-
19+
1920
public double get(int index) {
20-
if(index >= capacity) {
21+
if (index >= capacity) {
2122
throw new IndexOutOfBoundsException();
2223
}
23-
if(index >= size()) {
24+
if (index >= size()) {
2425
throw new IndexOutOfBoundsException();
2526
}
26-
27+
2728
return elements[(start + index) % capacity];
2829
}
29-
30+
3031
public boolean isEmpty() {
3132
return start == -1 && end == -1;
3233
}
33-
34-
public void clear() {
35-
start = end = -1;
36-
}
37-
34+
3835
public CircularBuffer(int capacity) {
3936
this.capacity = capacity;
4037
elements = new double[capacity];
4138
}
42-
39+
4340
public double min() {
44-
if(size() == 0) {
41+
if (size() == 0) {
4542
throw new NoSuchElementException();
4643
}
47-
44+
4845
double out = get(0);
49-
for(int i = 1; i < size(); ++i) {
46+
for (int i = 1; i < size(); ++i) {
5047
out = Math.min(out, get(i));
5148
}
52-
49+
5350
return out;
5451
}
55-
52+
5653
public double max() {
57-
if(size() == 0) {
54+
if (size() == 0) {
5855
throw new NoSuchElementException();
5956
}
60-
57+
6158
double out = get(0);
62-
for(int i = 1; i < size(); ++i) {
59+
for (int i = 1; i < size(); ++i) {
6360
out = Math.max(out, get(i));
6461
}
65-
62+
6663
return out;
6764
}
68-
65+
6966
public int size() {
70-
if(end == -1) {
67+
if (end == -1) {
7168
return 0;
7269
}
73-
70+
7471
return (end - start + capacity) % capacity + 1;
7572
}
76-
73+
7774
public int capacity() {
7875
return capacity;
7976
}

0 commit comments

Comments
 (0)