diff --git a/app/src/processing/app/SerialPlotter.java b/app/src/processing/app/SerialPlotter.java index 035005ac362..ebbd23f2cbe 100644 --- a/app/src/processing/app/SerialPlotter.java +++ b/app/src/processing/app/SerialPlotter.java @@ -41,6 +41,7 @@ public class SerialPlotter extends AbstractMonitor { private final StringBuffer messageBuffer; private JComboBox serialRates; + private JSpinner graphWidth; private Serial serial; private int serialRate, xCount; @@ -50,15 +51,18 @@ public class SerialPlotter extends AbstractMonitor { private JComboBox lineEndings; private ArrayList graphs; - private final static int BUFFER_CAPACITY = 500; + private final static int BUFFER_CAPACITY_DEFAULT = 500; + private final static int BUFFER_CAPACITY_MAX = 5000; + private final static int BUFFER_CAPACITY_MIN = 10; + private int buffer_capacity = BUFFER_CAPACITY_DEFAULT; private static class Graph { public CircularBuffer buffer; private Color color; public String label; - public Graph(int id) { - buffer = new CircularBuffer(BUFFER_CAPACITY); + public Graph(int id, int capacity) { + buffer = new CircularBuffer(capacity); color = Theme.getColorCycleColor("plotting.graphcolor", id); } @@ -156,12 +160,12 @@ public void paintComponent(Graphics g1) { } // handle data count - int cnt = xCount - BUFFER_CAPACITY; - if (xCount < BUFFER_CAPACITY) cnt = 0; + int cnt = xCount - buffer_capacity; + if (xCount < buffer_capacity) cnt = 0; double zeroTick = ticks.getTick(0); double lastTick = ticks.getTick(ticks.getTickCount() - 1); - double xTickRange = BUFFER_CAPACITY / ticks.getTickCount(); + double xTickRange = buffer_capacity / ticks.getTickCount(); for (int i = 0; i < ticks.getTickCount() + 1; i++) { String s; @@ -177,7 +181,7 @@ public void paintComponent(Graphics g1) { s = String.valueOf((int)(xTickRange * i)+cnt); fBounds = fm.getStringBounds(s, g); sWidth = (int)fBounds.getWidth()/2; - xValue = (int)((bounds.width - xOffset - xPadding) * ((xTickRange * i) / BUFFER_CAPACITY) + xOffset); + xValue = (int)((bounds.width - xOffset - xPadding) * ((xTickRange * i) / buffer_capacity) + xOffset); } // draw graph x axis, ticks and labels g.setColor(boundsColor); @@ -194,8 +198,8 @@ public void paintComponent(Graphics g1) { g.drawLine(xOffset, (int) transformY(zeroTick), bounds.width - xPadding, (int)transformY(zeroTick)); g.setTransform(AffineTransform.getTranslateInstance(xOffset, 0)); - float xstep = (float) (bounds.width - xOffset - xPadding) / (float) BUFFER_CAPACITY; - + float xstep = (float) (bounds.width - xOffset - xPadding) / (float) buffer_capacity; + // draw legend int legendXOffset = 0; for(int i = 0; i < graphs.size(); ++i) { @@ -255,6 +259,8 @@ public SerialPlotter(BoardPort port) { messageBuffer = new StringBuffer(); graphs = new ArrayList<>(); + + graphWidth.addChangeListener(cl -> {setNewBufferCapacity((int)graphWidth.getValue()); } ); } protected void onCreateWindow(Container mainPane) { @@ -273,9 +279,20 @@ protected void onCreateWindow(Container mainPane) { serialRates.setMaximumSize(serialRates.getMinimumSize()); + graphWidth = new JSpinner(new SpinnerNumberModel( + BUFFER_CAPACITY_DEFAULT, //initial value + BUFFER_CAPACITY_MIN, //min + BUFFER_CAPACITY_MAX, //max + 1)); //step + graphWidth.setMaximumSize(graphWidth.getMinimumSize()); + JSpinner.NumberEditor editor = new JSpinner.NumberEditor(graphWidth); + editor.getFormat().setGroupingUsed(false); + graphWidth.setEditor(editor); + pane.add(Box.createHorizontalGlue()); pane.add(Box.createRigidArea(new Dimension(8, 0))); pane.add(serialRates); + pane.add(graphWidth); mainPane.add(pane, BorderLayout.SOUTH); @@ -373,7 +390,7 @@ public void onSendCommand(ActionListener listener) { sendButton.addActionListener(listener); } - public void appyPreferences() { + public void applyPreferences() { // Apply line endings. if (PreferencesData.get("serial.line_ending") != null) { lineEndings.setSelectedIndex(PreferencesData.getInteger("serial.line_ending")); @@ -382,13 +399,30 @@ public void appyPreferences() { protected void onEnableWindow(boolean enable) { textField.setEnabled(enable); + serialRates.setEnabled(enable); sendButton.setEnabled(enable); + graphWidth.setEnabled(enable); } private void onSerialRateChange(ActionListener listener) { serialRates.addActionListener(listener); } + private void setNewBufferCapacity(int capacity){ + if(buffer_capacity != capacity) { + + if(capacity > BUFFER_CAPACITY_MAX) buffer_capacity = BUFFER_CAPACITY_MAX; + else if(capacity < BUFFER_CAPACITY_MIN) buffer_capacity = BUFFER_CAPACITY_MIN; + else buffer_capacity = capacity; + + for(int i = 0; i < graphs.size(); i++) { + graphs.get(i).buffer.newCapacity(buffer_capacity); + } + + xCount = 0; + } + } + public void message(final String s) { messageBuffer.append(s); while (true) { @@ -451,14 +485,14 @@ public void message(final String s) { if(value != null) { if(validParts >= graphs.size()) { - graphs.add(new Graph(validParts)); + graphs.add(new Graph(validParts, buffer_capacity)); } graphs.get(validParts).buffer.add(value); validParts++; } if(label != null) { if(validLabels >= graphs.size()) { - graphs.add(new Graph(validLabels)); + graphs.add(new Graph(validLabels, BUFFER_CAPACITY_DEFAULT)); } graphs.get(validLabels).label = label; validLabels++; diff --git a/app/src/processing/app/helpers/CircularBuffer.java b/app/src/processing/app/helpers/CircularBuffer.java index 8396c8fd2e1..b4a2bada888 100644 --- a/app/src/processing/app/helpers/CircularBuffer.java +++ b/app/src/processing/app/helpers/CircularBuffer.java @@ -4,10 +4,10 @@ public class CircularBuffer { - private final double[] elements; + private double[] elements; private int start = -1; private int end = -1; - private final int capacity; + private int capacity; public void add(double num) { end = (end + 1) % capacity; @@ -37,6 +37,12 @@ public CircularBuffer(int capacity) { elements = new double[capacity]; } + public void newCapacity(int capacity) { + elements = new double[capacity]; + this.capacity = capacity; + start = end = 0; + } + public double min() { if (size() == 0) { throw new NoSuchElementException();