2323import processing .app .helpers .Ticks ;
2424import processing .app .legacy .PApplet ;
2525
26+ import java .util .ArrayList ;
2627import javax .swing .*;
2728import javax .swing .border .EmptyBorder ;
2829import java .awt .*;
3536public class SerialPlotter extends AbstractMonitor {
3637
3738 private final StringBuffer messageBuffer ;
38- private CircularBuffer buffer ;
3939 private JComboBox <String > serialRates ;
4040 private Serial serial ;
4141 private int serialRate ;
4242
43+ private ArrayList <Graph > graphs ;
44+ private final static int BUFFER_CAPACITY = 500 ;
45+
46+ private static class Graph {
47+ public CircularBuffer buffer ;
48+ private Color color ;
49+
50+ public Graph (int id ) {
51+ buffer = new CircularBuffer (BUFFER_CAPACITY );
52+ color = Theme .getColorCycleColor ("plotting.graphcolor" , id );
53+ }
54+
55+ public void paint (Graphics2D g , float xstep , double minY ,
56+ double maxY , double rangeY , double height ) {
57+ g .setColor (color );
58+ g .setStroke (new BasicStroke (1.0f ));
59+
60+ for (int i = 0 ; i < buffer .size () - 1 ; ++i ) {
61+ g .drawLine (
62+ (int ) (i * xstep ), (int ) transformY (buffer .get (i ), minY , rangeY , height ),
63+ (int ) ((i + 1 ) * xstep ), (int ) transformY (buffer .get (i + 1 ), minY , rangeY , height )
64+ );
65+ }
66+ }
67+
68+ private float transformY (double rawY , double minY , double rangeY , double height ) {
69+ return (float ) (5 + (height - 10 ) * (1.0 - (rawY - minY ) / rangeY ));
70+ }
71+ }
72+
4373 private class GraphPanel extends JPanel {
4474 private double minY , maxY , rangeY ;
4575 private Rectangle bounds ;
4676 private int xOffset ;
4777 private final Font font ;
48- private final Color graphColor ;
78+ private final Color bgColor ;
4979
5080 public GraphPanel () {
5181 font = Theme .getFont ("console.font" );
52- graphColor = Theme .getColor ("header .bgcolor" );
82+ bgColor = Theme .getColor ("plotting .bgcolor" );
5383 xOffset = 20 ;
5484 }
5585
86+ private Ticks computeBounds () {
87+ minY = Double .POSITIVE_INFINITY ;
88+ maxY = Double .NEGATIVE_INFINITY ;
89+ for (Graph g : graphs ) {
90+ double bMin = g .buffer .min () / 2.0 ;
91+ double bMax = g .buffer .max () * 2.0 ;
92+ minY = bMin < minY ? bMin : minY ;
93+ maxY = bMax > maxY ? bMax : maxY ;
94+ }
95+
96+ Ticks ticks = new Ticks (minY , maxY , 3 );
97+ minY = Math .min (minY , ticks .getTick (0 ));
98+ maxY = Math .max (maxY , ticks .getTick (ticks .getTickCount () - 1 ));
99+ rangeY = maxY - minY ;
100+ minY -= 0.05 * rangeY ;
101+ maxY += 0.05 * rangeY ;
102+ rangeY = maxY - minY ;
103+ return ticks ;
104+ }
105+
56106 @ Override
57107 public void paintComponent (Graphics g1 ) {
58108 Graphics2D g = (Graphics2D ) g1 ;
@@ -61,20 +111,12 @@ public void paintComponent(Graphics g1) {
61111 super .paintComponent (g );
62112
63113 bounds = g .getClipBounds ();
64- setBackground (Color . WHITE );
65- if (buffer .isEmpty ()) {
114+ setBackground (bgColor );
115+ if (graphs .isEmpty ()) {
66116 return ;
67117 }
68118
69- minY = buffer .min () / 2 ;
70- maxY = buffer .max () * 2 ;
71- Ticks ticks = new Ticks (minY , maxY , 3 );
72- minY = Math .min (minY , ticks .getTick (0 ));
73- maxY = Math .max (maxY , ticks .getTick (ticks .getTickCount () - 1 ));
74- rangeY = maxY - minY ;
75- minY -= 0.05 * rangeY ;
76- maxY += 0.05 * rangeY ;
77- rangeY = maxY - minY ;
119+ Ticks ticks = computeBounds ();
78120
79121 g .setStroke (new BasicStroke (1.0f ));
80122 FontMetrics fm = g .getFontMetrics ();
@@ -92,19 +134,21 @@ public void paintComponent(Graphics g1) {
92134 g .drawLine (bounds .x + xOffset , bounds .y + 5 , bounds .x + xOffset , bounds .y + bounds .height - 10 );
93135
94136 g .setTransform (AffineTransform .getTranslateInstance (xOffset , 0 ));
95- float xstep = (float ) (bounds .width - xOffset ) / (float ) buffer .capacity ();
96-
97- g .setColor (graphColor );
98- g .setStroke (new BasicStroke (0.75f ));
99-
100- for (int i = 0 ; i < buffer .size () - 1 ; ++i ) {
101- g .drawLine (
102- (int ) (i * xstep ), (int ) transformY (buffer .get (i )),
103- (int ) ((i + 1 ) * xstep ), (int ) transformY (buffer .get (i + 1 ))
104- );
137+ float xstep = (float ) (bounds .width - xOffset ) / (float ) BUFFER_CAPACITY ;
138+ int legendLength = graphs .size () * 10 + (graphs .size () - 1 ) * 3 ;
139+
140+ for (int i = 0 ; i < graphs .size (); ++i ) {
141+ graphs .get (i ).paint (g , xstep , minY , maxY , rangeY , bounds .height );
142+ if (graphs .size () > 1 ) {
143+ g .fillRect (bounds .width - (xOffset + legendLength + 10 ) + i * 13 , 10 , 10 , 10 );
144+ }
105145 }
106146 }
107147
148+ private float transformY (double rawY ) {
149+ return (float ) (5 + (bounds .height - 10 ) * (1.0 - (rawY - minY ) / rangeY ));
150+ }
151+
108152 @ Override
109153 public Dimension getMinimumSize () {
110154 return new Dimension (200 , 100 );
@@ -114,10 +158,6 @@ public Dimension getMinimumSize() {
114158 public Dimension getPreferredSize () {
115159 return new Dimension (500 , 250 );
116160 }
117-
118- private float transformY (double rawY ) {
119- return (float ) (5 + (bounds .height - 10 ) * (1.0 - (rawY - minY ) / rangeY ));
120- }
121161 }
122162
123163 public SerialPlotter (BoardPort port ) {
@@ -140,12 +180,12 @@ public SerialPlotter(BoardPort port) {
140180 });
141181
142182 messageBuffer = new StringBuffer ();
183+ graphs = new ArrayList <Graph >();
143184 }
144185
145186 protected void onCreateWindow (Container mainPane ) {
146187 mainPane .setLayout (new BorderLayout ());
147188
148- buffer = new CircularBuffer (500 );
149189 GraphPanel graphPanel = new GraphPanel ();
150190
151191 mainPane .add (graphPanel , BorderLayout .CENTER );
@@ -182,14 +222,26 @@ public void message(final String s) {
182222 }
183223
184224 String line = messageBuffer .substring (0 , linebreak );
185- line = line .trim ();
186225 messageBuffer .delete (0 , linebreak + 1 );
187226
188- try {
189- double value = Double .valueOf (line );
190- buffer .add (value );
191- } catch (NumberFormatException e ) {
192- // ignore
227+ line = line .trim ();
228+ String [] parts = line .split ("[, \t ]+" );
229+ if (parts .length == 0 ) {
230+ continue ;
231+ }
232+
233+ int validParts = 0 ;
234+ for (int i = 0 ; i < parts .length ; ++i ) {
235+ try {
236+ double value = Double .valueOf (parts [i ]);
237+ if (i >= graphs .size ()) {
238+ graphs .add (new Graph (validParts ));
239+ }
240+ graphs .get (validParts ).buffer .add (value );
241+ validParts ++;
242+ } catch (NumberFormatException e ) {
243+ // ignore
244+ }
193245 }
194246 }
195247
0 commit comments