View Javadoc

1   /* OpenLogViewer
2    *
3    * Copyright 2011
4    *
5    * This file is part of the OpenLogViewer project.
6    *
7    * OpenLogViewer software is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as published by
9    * the Free Software Foundation, either version 3 of the License, or
10   * (at your option) any later version.
11   *
12   * OpenLogViewer software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with any OpenLogViewer software.  If not, see http://www.gnu.org/licenses/
19   *
20   * I ask that if you make any changes to this file you fork the code on github.com!
21   *
22   */
23  package org.diyefi.openlogviewer.graphing;
24  
25  import java.awt.Dimension;
26  import java.awt.event.ActionEvent;
27  import java.awt.event.ActionListener;
28  import java.awt.event.InputEvent;
29  import java.awt.event.KeyEvent;
30  import java.awt.event.KeyListener;
31  import java.awt.event.MouseEvent;
32  import java.awt.event.MouseListener;
33  import java.awt.event.MouseMotionListener;
34  import java.awt.event.MouseWheelEvent;
35  import java.awt.event.MouseWheelListener;
36  
37  import javax.swing.JPanel;
38  import javax.swing.Timer;
39  
40  import org.diyefi.openlogviewer.OpenLogViewerApp;
41  import org.diyefi.openlogviewer.genericlog.GenericLog;
42  import org.diyefi.openlogviewer.graphing.MultiGraphLayeredPane;
43  
44  /**
45   *
46   * @author Ben Fenner
47   */
48  public class EntireGraphingPanel extends JPanel implements ActionListener, MouseMotionListener, MouseListener, MouseWheelListener, KeyListener {
49  
50  	public EntireGraphingPanel() {
51          super();
52          init();
53      }
54  
55      private void init() {
56      	this.setName("Graphing Panel");
57          this.setLayout(new java.awt.BorderLayout());
58          multiGraph = new MultiGraphLayeredPane();
59          multiGraph.setPreferredSize(new Dimension(600, 400));
60          this.add(multiGraph, java.awt.BorderLayout.CENTER);
61          graphPositionPanel = new GraphPositionPanel();
62          graphPositionPanel.setPreferredSize(new Dimension(600, 20));
63          this.add(graphPositionPanel, java.awt.BorderLayout.SOUTH);
64          resetGraphPosition();
65          setGraphPositionMax();
66          playing = false;
67          wasPlaying = false;
68          playTimer = new Timer(10, this);
69          playTimer.setInitialDelay(0);
70          flingTimer = new Timer(10, this);
71          flingTimer.setInitialDelay(0);
72          addMouseListener(this);
73          addMouseMotionListener(this);
74          addMouseWheelListener(this);
75          addMouseListener(multiGraph.getInfoPanel());
76          addMouseMotionListener(multiGraph.getInfoPanel());
77          stopDragging();
78          stopFlinging();
79          thePast = System.currentTimeMillis();
80          zoom = 1;
81      }
82  
83      public void actionPerformed(ActionEvent e) {
84          if (playing && graphPosition < graphPositionMax) {
85          	moveGraphPosition(1);
86          } else if (flinging && graphPosition < graphPositionMax && graphPosition > 0){
87          	if(flingInertia == 0){
88          		stopFlinging();
89          	} else{
90          		int center = this.getWidth() / 2;
91          		moveEntireGraphingPanel(center + flingInertia);
92  	        	if(flingInertia > 0){
93  	        		flingInertia--;
94  	        	} else {
95  	        		flingInertia++;
96  	        	}
97          	}
98          }
99      }
100 
101     public MultiGraphLayeredPane getMultiGraphLayeredPane(){
102     	return multiGraph;
103     }
104 
105     public GraphPositionPanel getGraphPositionPanel(){
106     	return graphPositionPanel;
107     }
108 
109     public void setLog(GenericLog genLog) {
110     	playing = false;
111     	resetGraphPosition();
112     	multiGraph.setLog(genLog);
113     	graphPositionPanel.setLog(genLog);
114     }
115 
116     public void zoomIn() {
117     	if (zoom < 500) {
118     		zoom++;
119     	}
120     	repaint();
121     }
122 
123 	public void zoomOut() {
124 		if (zoom > 1) {
125 			zoom--;
126 		}
127 		repaint();
128 	}
129 
130     public void play(){
131     	if (playing) {
132             pause();
133         } else {
134         	playing = true;
135         	stopDragging();
136     		stopFlinging();
137             playTimer.start();
138         }
139     }
140 
141     public void pause(){
142     	playing = false;
143     	playTimer.stop();
144     	stopDragging();
145 		stopFlinging();
146     }
147 
148     /**
149      * increases speed of the graph by 1 ms until 0, at which speed cannot be advanced any further and will essentially update as fast as possible
150      */
151     public void fastForward() {
152     	int currentDelay = playTimer.getDelay();
153     	if(currentDelay > 0){
154     		playTimer.setDelay(currentDelay - 1);
155     	}
156     }
157 
158     public void eject() {
159         resetGraphPosition();
160     }
161 
162     public void stop(){
163     	playing = false;
164     	wasPlaying = false;
165     	playTimer.stop();
166     	resetGraphPosition();
167     }
168 
169     /**
170      * Slows the speed of playback by 1 ms
171      */
172     public void slowDown() {
173     	int currentDelay = playTimer.getDelay();
174     	playTimer.setDelay(currentDelay + 1);
175     }
176 
177     public void fling(){
178 		flinging = true;
179 		flingTimer.start();
180     }
181 
182     public double getGraphPosition(){
183     	return graphPosition;
184     }
185 
186     public int getGraphPositionMax(){
187     	return graphPositionMax;
188     }
189 
190     public int getZoom(){
191     	return zoom;
192     }
193 
194     private void moveGraphPosition(double amount){
195     	double newPos = graphPosition + amount;
196     	setGraphPosition(newPos);
197     }
198 
199     public void setGraphPosition(double newPos){
200     	graphPosition = newPos;
201     	repaint();
202     }
203 
204     public void setGraphPositionMax(){
205     	boolean found = false;
206         for (int i = 0; i < multiGraph.getComponentCount() && !found; i++) {
207             if (multiGraph.getComponent(i) instanceof SingleGraphPanel) {
208                 SingleGraphPanel gl = (SingleGraphPanel) multiGraph.getComponent(i);
209                 graphPositionMax = gl.graphSize() - 1;
210                 found = true;
211             }
212         }
213     }
214 
215     private void resetGraphPosition(){
216     	setGraphPosition(0);
217     }
218 
219     private void goToLastGraphPosition(){
220     	setGraphPosition(graphPositionMax);
221     }
222 
223     public boolean isPlaying(){
224     	return playing;
225     }
226 
227     private void moveEntireGraphingPanel(double newPosition){
228     	double graphPosition = OpenLogViewerApp.getInstance().getEntireGraphingPanel().getGraphPosition();
229     	int graphPositionMax = OpenLogViewerApp.getInstance().getEntireGraphingPanel().getGraphPositionMax();
230     	double center = this.getWidth() / 2;
231     	double move = (newPosition - center) / zoom;
232         if (move + graphPosition < graphPositionMax) {
233             if (move + graphPosition < 0) {
234             	OpenLogViewerApp.getInstance().getEntireGraphingPanel().resetGraphPosition();
235             } else {
236             	OpenLogViewerApp.getInstance().getEntireGraphingPanel().moveGraphPosition(move);
237             }
238         } else {
239         	OpenLogViewerApp.getInstance().getEntireGraphingPanel().setGraphPosition(graphPositionMax);
240         }
241     }
242 
243     private void stopDragging(){
244     	dragging = false;
245         prevDragXCoord = -1;
246     }
247 
248     private void stopFlinging(){
249     	flinging = false;
250     	flingInertia = 0;
251     }
252 
253   //MOUSE LISTENER FUNCTIONALITY
254     @Override
255     public void mouseClicked(MouseEvent e) {
256     	if (!dragging) {
257         	moveEntireGraphingPanel(e.getX());
258     	} else {
259     		stopDragging();
260     		stopFlinging();
261         }
262     }
263 
264     @Override
265     public void mouseDragged(MouseEvent e) {
266     	dragging = true;
267     	int center = this.getWidth() / 2;
268     	int xMouseCoord = e.getX();
269     	if(prevDragXCoord > 0 && prevDragXCoord != xMouseCoord){
270     		moveEntireGraphingPanel(center + (prevDragXCoord - xMouseCoord));
271     		flingInertia = ((prevDragXCoord - xMouseCoord) * 2);
272         	thePast = System.currentTimeMillis();
273     	}
274     	prevDragXCoord = xMouseCoord;
275     }
276 
277     @Override
278     public void mouseMoved(MouseEvent e) {
279 
280     }
281 
282     @Override
283     public void mouseEntered(MouseEvent e) {
284 
285     }
286 
287     @Override
288     public void mouseExited(MouseEvent e) {
289 
290     }
291 
292     @Override
293     public void mousePressed(MouseEvent e) {
294     	wasPlaying = playing;
295     	if(playing){
296     		pause();
297     	}
298     	stopDragging();
299     	stopFlinging();
300     }
301 
302     @Override
303     public void mouseReleased(MouseEvent e) {
304     	stopDragging();
305     	long now = System.currentTimeMillis();
306     	if(now - thePast > 50){
307     		stopFlinging();  //if over 50 milliseconds since dragging then don't fling
308     	}
309     	if(flingInertia != 0){
310     		fling();
311     	}
312     	if(wasPlaying){
313     		play();
314     	}
315     }
316 
317 	@Override
318 	public void mouseWheelMoved(MouseWheelEvent e) {
319 		int center = this.getWidth() / 2;
320 		int zoomInMove = center + ((e.getX() - center) / (zoom));
321 		int zoomOutMove = center - ((e.getX() - center) / (zoom));
322 		int notches = e.getWheelRotation();
323 		if(notches < 0){
324 			zoomIn();
325 			moveEntireGraphingPanel(zoomInMove);
326 		} else if (zoom > 1){
327 			zoomOut();
328 			moveEntireGraphingPanel(zoomOutMove);
329 		}
330 	}
331 
332 	//KEY LISTENER FUNCTIONALITY
333 	@Override
334 	public void keyPressed(KeyEvent e) {
335 		switch (e.getKeyCode()) {
336 			//Play key bindings
337 			case KeyEvent.VK_SPACE: 	play(); 					break;
338 
339 			//Home key bindings
340 			case KeyEvent.VK_HOME:  	resetGraphPosition(); 		break;
341 
342 			//End key bindings
343 			case KeyEvent.VK_END:   	goToLastGraphPosition(); 	break;
344 
345 			//Scroll left key bindings
346 			case KeyEvent.VK_PAGE_UP:   {
347 				//Big scroll
348 				moveEntireGraphingPanel(-(this.getWidth() / 4) / zoom);
349 			} 														break;
350 			case KeyEvent.VK_LEFT:   	{
351 				if(e.getModifiers() == InputEvent.CTRL_MASK){
352 					//Big scroll
353 					moveEntireGraphingPanel(-(this.getWidth() / 4) / zoom);
354 				} else {
355 					int center = this.getWidth() / 2;
356 					moveEntireGraphingPanel(center - (1 * zoom));
357 				}
358 			}														break;
359 			case KeyEvent.VK_KP_LEFT:   	{
360 				if(e.getModifiers() == InputEvent.CTRL_MASK){
361 					//Big scroll
362 					moveEntireGraphingPanel(-(this.getWidth() / 4) / zoom);
363 				} else {
364 					int center = this.getWidth() / 2;
365 					moveEntireGraphingPanel(center - (1 * zoom));
366 				}
367 			}														break;
368 
369 			//Scroll right key bindings
370 			case KeyEvent.VK_PAGE_DOWN: {
371 				//Big scroll
372 				moveEntireGraphingPanel(this.getWidth() + (this.getWidth() / 4) / zoom);
373 			} 														break;
374 			case KeyEvent.VK_RIGHT:   	{
375 				if(e.getModifiers() == InputEvent.CTRL_MASK){
376 					//Big scroll
377 					moveEntireGraphingPanel(this.getWidth() + (this.getWidth() / 4) / zoom);
378 				} else {
379 					int center = this.getWidth() / 2;
380 					moveEntireGraphingPanel(center + (1 * zoom));
381 				}
382 			}														break;
383 			case KeyEvent.VK_KP_RIGHT:   	{
384 				if(e.getModifiers() == InputEvent.CTRL_MASK){
385 					//Big scroll
386 					moveEntireGraphingPanel(this.getWidth() + (this.getWidth() / 4) / zoom);
387 				} else {
388 					int center = this.getWidth() / 2;
389 					moveEntireGraphingPanel(center + (1 * zoom));
390 				}
391 			}														break;
392 
393 			//Zoom in key bindings
394 			case KeyEvent.VK_UP: 		zoomIn();					break;
395 			case KeyEvent.VK_KP_UP: 	zoomIn();					break;
396 			case KeyEvent.VK_ADD:   	{
397 				if(e.getModifiers() == InputEvent.CTRL_MASK){
398 					zoomIn();
399 				}
400 			}														break;
401 
402 			//Zoom out key bindings
403 			case KeyEvent.VK_DOWN: 		zoomOut();					break;
404 			case KeyEvent.VK_KP_DOWN: 	zoomOut();					break;
405 			case KeyEvent.VK_SUBTRACT:   	{
406 				if(e.getModifiers() == InputEvent.CTRL_MASK){
407 					zoomOut();
408 				}
409 			}														break;
410 
411 		}
412 	}
413 
414 	@Override
415 	public void keyReleased(KeyEvent e) {
416 
417 	}
418 
419 	@Override
420 	public void keyTyped(KeyEvent e) {
421 
422 	}
423 
424     private MultiGraphLayeredPane multiGraph;
425     private GraphPositionPanel graphPositionPanel;
426     private double graphPosition;
427     private int graphPositionMax;
428     private boolean playing;
429     private boolean wasPlaying;
430     private Timer playTimer;
431     private Timer flingTimer;
432     private boolean dragging;
433     private boolean flinging;
434     private long thePast;
435     private int prevDragXCoord;
436     private int flingInertia;
437     private int zoom;
438     private static final long serialVersionUID = 6880240079754110792L;
439 
440 }