1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.diyefi.openlogviewer.graphing;
24
25 import java.awt.Color;
26 import java.awt.Graphics;
27 import java.awt.Graphics2D;
28 import java.awt.event.HierarchyBoundsListener;
29 import java.awt.event.HierarchyEvent;
30 import java.beans.PropertyChangeEvent;
31 import java.beans.PropertyChangeListener;
32
33 import javax.swing.JPanel;
34 import org.diyefi.openlogviewer.OpenLogViewer;
35 import org.diyefi.openlogviewer.genericlog.GenericDataElement;
36
37
38
39
40
41
42
43
44
45 public class SingleGraphPanel extends JPanel implements HierarchyBoundsListener, PropertyChangeListener {
46 private static final long serialVersionUID = 1L;
47
48 private static final double GRAPH_TRACE_SIZE_AS_PERCENTAGE_OF_TOTAL_GRAPH_SIZE = 0.95;
49 private GenericDataElement GDE;
50 private double[] dataPointsToDisplay;
51 private int availableDataRecords;
52
53 public SingleGraphPanel() {
54 this.setOpaque(false);
55 this.setLayout(null);
56 this.GDE = null;
57 dataPointsToDisplay = null;
58 }
59
60 @Override
61 public void ancestorMoved(final HierarchyEvent e) {
62 }
63
64 @Override
65 public final void ancestorResized(final HierarchyEvent e) {
66 if (e.getID() == HierarchyEvent.ANCESTOR_RESIZED) {
67 sizeGraph();
68 }
69 }
70
71 @Override
72 public final void propertyChange(final PropertyChangeEvent evt) {
73 if (evt.getPropertyName().equalsIgnoreCase("Split")) {
74 sizeGraph();
75 }
76 }
77
78 @Override
79 public final void paint(final Graphics g) {
80 boolean zoomedOut = OpenLogViewer.getInstance().getEntireGraphingPanel().isZoomedOutBeyondOneToOne();
81 if(zoomedOut){
82 initGraphZoomedOut();
83 } else{
84 initGraphZoomed();
85 }
86 if (hasDataPointToDisplay()) {
87 paintDataPointsAndTraces(g);
88 }
89 }
90
91 private void paintDataPointsAndTraces(final Graphics g) {
92
93
94 final Graphics2D g2d = (Graphics2D) g;
95 g2d.setColor(GDE.getDisplayColor());
96
97
98 double leftOfTraceData = -Double.MAX_VALUE;
99 double traceData = -Double.MAX_VALUE;
100 double rightOfTraceData = dataPointsToDisplay[0];
101
102
103 boolean beforeGraphBeginning = true;
104 boolean atGraphBeginning = false;
105 boolean atGraphEnd = false;
106
107
108 final boolean zoomedOut = OpenLogViewer.getInstance().getEntireGraphingPanel().isZoomedOutBeyondOneToOne();
109 int zoom = OpenLogViewer.getInstance().getEntireGraphingPanel().getZoom();
110 if(zoomedOut){
111 zoom = 1;
112 }
113 final double graphPosition = OpenLogViewer.getInstance().getEntireGraphingPanel().getGraphPosition();
114 final double offset = (graphPosition % 1) * zoom;
115 int screenPositionXCoord = -(int)Math.round(offset);
116 int screenPositionYCoord = Integer.MIN_VALUE;
117 int nextScreenPositionYCoord = getScreenPositionYCoord(rightOfTraceData, GDE.getDisplayMinValue(), GDE.getDisplayMaxValue());
118
119
120 for (int i = 0; i < dataPointsToDisplay.length; i++) {
121
122
123 try{
124 leftOfTraceData = dataPointsToDisplay[i - 1];
125 } catch (ArrayIndexOutOfBoundsException e){
126 leftOfTraceData = -Double.MAX_VALUE;
127 }
128 traceData = dataPointsToDisplay[i];
129 try{
130 rightOfTraceData = dataPointsToDisplay[i + 1];
131 } catch (ArrayIndexOutOfBoundsException e){
132 rightOfTraceData = -Double.MAX_VALUE;
133 }
134
135
136 atGraphBeginning = false;
137 if(leftOfTraceData == -Double.MAX_VALUE && traceData != -Double.MAX_VALUE){
138 atGraphBeginning = true;
139 beforeGraphBeginning = false;
140 }
141 if(traceData != -Double.MAX_VALUE && rightOfTraceData == -Double.MAX_VALUE){
142 atGraphEnd = true;
143 }
144
145
146 screenPositionYCoord = nextScreenPositionYCoord;
147 nextScreenPositionYCoord = getScreenPositionYCoord(rightOfTraceData, GDE.getDisplayMinValue(), GDE.getDisplayMaxValue());
148
149
150 if(!zoomedOut && zoom > 5){
151
152
153 if (traceData != leftOfTraceData || traceData != rightOfTraceData) {
154 g2d.fillRect(screenPositionXCoord - 1, screenPositionYCoord - 1, 3, 3);
155 } else if (atGraphBeginning){
156 g2d.fillRect(screenPositionXCoord - 1, screenPositionYCoord - 1, 3, 3);
157 }
158 } else {
159
160
161 g2d.drawLine(screenPositionXCoord, screenPositionYCoord, screenPositionXCoord, screenPositionYCoord);
162 }
163
164
165 if (!beforeGraphBeginning && !atGraphEnd){
166 g2d.drawLine(screenPositionXCoord, screenPositionYCoord, screenPositionXCoord + zoom, nextScreenPositionYCoord);
167 }
168
169
170 screenPositionXCoord += zoom;
171 }
172 }
173
174 private int getScreenPositionYCoord(final Double traceData, final double minValue, final double maxValue) {
175 int point = 0;
176 final int height = (int) (this.getHeight() * GRAPH_TRACE_SIZE_AS_PERCENTAGE_OF_TOTAL_GRAPH_SIZE);
177 if (maxValue != minValue) {
178 point = (int) (height - (height * ((traceData - minValue) / (maxValue - minValue))));
179 }
180 return point;
181 }
182
183 private boolean hasDataPointToDisplay() {
184 boolean result = false;
185 if ((dataPointsToDisplay != null) && (dataPointsToDisplay.length > 0)) {
186 result = true;
187 }
188 return result;
189 }
190
191
192
193
194
195 public final void setData(final GenericDataElement GDE) {
196 this.GDE = GDE;
197 this.availableDataRecords = GDE.size() + 1;
198
199 sizeGraph();
200 }
201
202 public final GenericDataElement getData() {
203 return GDE;
204 }
205
206
207
208
209
210
211
212 public final Double getMouseInfo(final int cursorPosition) {
213 boolean zoomedOut = OpenLogViewer.getInstance().getEntireGraphingPanel().isZoomedOutBeyondOneToOne();
214 Double info = null;
215 if(zoomedOut){
216 info = getMouseInfoZoomedOut(cursorPosition);
217 } else {
218 info = getMouseInfoZoomed(cursorPosition);
219 }
220 return info;
221 }
222
223
224
225
226
227
228
229 private final Double getMouseInfoZoomed(final int cursorPosition){
230 final double graphPosition = OpenLogViewer.getInstance().getEntireGraphingPanel().getGraphPosition();
231 final int zoom = OpenLogViewer.getInstance().getEntireGraphingPanel().getZoom();
232 final double offset = (graphPosition % 1) * zoom;
233 final int cursorPositionPlusOffset = cursorPosition + (int) offset;
234 double numSnapsFromCenter = ((double) cursorPositionPlusOffset / (double) zoom);
235 numSnapsFromCenter = Math.round(numSnapsFromCenter);
236 final int dataLocation = (int) graphPosition + (int) numSnapsFromCenter;
237 if ((dataLocation >= 0) && (dataLocation < availableDataRecords)) {
238 return GDE.get(dataLocation);
239 } else {
240 return null;
241 }
242 }
243
244
245
246
247
248
249
250 private final Double getMouseInfoZoomedOut(int cursorPosition){
251 final double graphPosition = OpenLogViewer.getInstance().getEntireGraphingPanel().getGraphPosition();
252 final int zoom = OpenLogViewer.getInstance().getEntireGraphingPanel().getZoom();
253 final int dataLocation = (int) graphPosition + (cursorPosition * zoom);
254 if ((dataLocation >= 0) && (dataLocation < availableDataRecords)) {
255 return GDE.get(dataLocation);
256 } else {
257 return null;
258 }
259 }
260
261 public final Color getColor() {
262 return GDE.getDisplayColor();
263 }
264
265 public final void setColor(final Color c) {
266 GDE.setDisplayColor(c);
267 }
268
269
270
271
272 public final void initGraphZoomed() {
273 if (GDE != null) {
274 final int graphPosition = (int)OpenLogViewer.getInstance().getEntireGraphingPanel().getGraphPosition();
275 int graphWindowWidth = OpenLogViewer.getInstance().getEntireGraphingPanel().getWidth();
276 final int zoom = OpenLogViewer.getInstance().getEntireGraphingPanel().getZoom();
277 int numberOfPointsThatFitInDisplay = graphWindowWidth / zoom;
278 numberOfPointsThatFitInDisplay += 3;
279 dataPointsToDisplay = new double[numberOfPointsThatFitInDisplay];
280 int position = graphPosition;
281
282
283 for (int i = 0; i < numberOfPointsThatFitInDisplay; i++) {
284 if (position >= 0 && position < availableDataRecords) {
285 dataPointsToDisplay[i] = GDE.get(position);
286 } else {
287 dataPointsToDisplay[i] = -Double.MAX_VALUE;
288 }
289 position++;
290 }
291 }
292 }
293
294
295
296
297 public final void initGraphZoomedOut() {
298 if (GDE != null) {
299 final int graphPosition = (int)OpenLogViewer.getInstance().getEntireGraphingPanel().getGraphPosition();
300 int graphWindowWidth = OpenLogViewer.getInstance().getEntireGraphingPanel().getWidth();
301 final int zoom = OpenLogViewer.getInstance().getEntireGraphingPanel().getZoom();
302 dataPointsToDisplay = new double[graphWindowWidth + 1];
303 final int numberOfRealPointsThatFitInDisplay = (graphWindowWidth * zoom) + zoom;
304 final int rightGraphPosition = graphPosition + numberOfRealPointsThatFitInDisplay;
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322 int nextAarrayIndex = 0;
323 double leftOfNewData = GDE.get(0);
324 for (int i = graphPosition; i < rightGraphPosition; i+=zoom) {
325
326 if (i >= 0 && i < availableDataRecords) {
327 double minData = Double.MAX_VALUE;
328 double maxData = -Double.MAX_VALUE;
329 double newData = 0.0;
330 double acummulateData = 0.0;
331 int divisor = 0;
332
333 for (int j = 0; j < zoom; j++){
334 if (i + j >= 0 && i + j < availableDataRecords) {
335 newData = GDE.get(i + j);
336 acummulateData += newData;
337 divisor++;
338 if (newData < minData){
339 minData = newData;
340 }
341 if (newData > maxData){
342 maxData = newData;
343 }
344 }
345 }
346 double averageData = acummulateData / divisor;
347 if (averageData > leftOfNewData){
348 dataPointsToDisplay[nextAarrayIndex] = maxData;
349 leftOfNewData = maxData;
350 } else if (averageData < leftOfNewData){
351 dataPointsToDisplay[nextAarrayIndex] = minData;
352 leftOfNewData = minData;
353 } else {
354 dataPointsToDisplay[nextAarrayIndex] = averageData;
355 leftOfNewData = averageData;
356 }
357 nextAarrayIndex++;
358 } else {
359 dataPointsToDisplay[nextAarrayIndex] = -Double.MAX_VALUE;
360 nextAarrayIndex++;
361 }
362 }
363 }
364 }
365
366
367
368
369 public final void sizeGraph() {
370 final MultiGraphLayeredPane lg = OpenLogViewer.getInstance().getMultiGraphLayeredPane();
371 int wherePixel = 0;
372 if (lg.getTotalSplits() > 1) {
373 if (GDE.getSplitNumber() <= lg.getTotalSplits()) {
374 wherePixel += lg.getHeight() / lg.getTotalSplits() * GDE.getSplitNumber() - (lg.getHeight() / lg.getTotalSplits());
375 } else {
376 wherePixel += lg.getHeight() / lg.getTotalSplits() * lg.getTotalSplits() - (lg.getHeight() / lg.getTotalSplits());
377 }
378 }
379
380 this.setBounds(0, wherePixel, lg.getWidth(), lg.getHeight() / (lg.getTotalSplits()));
381 final boolean zoomedOut = OpenLogViewer.getInstance().getEntireGraphingPanel().isZoomedOutBeyondOneToOne();
382 if(zoomedOut){
383 initGraphZoomedOut();
384 } else {
385 initGraphZoomed();
386 }
387 }
388
389
390
391
392
393 public final int graphSize() {
394 return availableDataRecords;
395 }
396 }