View Javadoc
1   package au.gov.amsa.geo.distance;
2   
3   import java.awt.Color;
4   import java.awt.Dimension;
5   import java.awt.FlowLayout;
6   import java.awt.Graphics;
7   import java.awt.Graphics2D;
8   import java.awt.event.ComponentEvent;
9   import java.awt.event.KeyEvent;
10  import java.awt.event.KeyListener;
11  import java.awt.event.MouseEvent;
12  import java.awt.event.MouseListener;
13  import java.io.File;
14  
15  import javax.swing.JFrame;
16  import javax.swing.JPanel;
17  import javax.swing.SwingUtilities;
18  
19  import org.apache.log4j.Logger;
20  
21  import rx.Observable;
22  import au.gov.amsa.geo.distance.DistanceTravelledCalculator.CalculationResult;
23  import au.gov.amsa.geo.model.Bounds;
24  import au.gov.amsa.geo.model.Options;
25  
26  /**
27   * Swing application that allows viewing of traffic density plots. Supports
28   * zooming via double-click.
29   *
30   */
31  public class DisplayPanel extends JPanel {
32  
33  	private static final long serialVersionUID = 7844558863774822599L;
34  
35  	private static Logger log = Logger.getLogger(DisplayPanel.class);
36  
37  	private Options options;
38  	private int numStandardDeviations;
39  
40  	private CalculationResult calculationResult;
41  
42  	public DisplayPanel(int numberStandardDeviations, final CellsUpdater updater) {
43  		this.numStandardDeviations = numberStandardDeviations;
44  		setPreferredSize(java.awt.Toolkit.getDefaultToolkit().getScreenSize());
45  		setBackground(Color.white);
46  		setFocusable(true);
47  		addKeyListener(createKeyListener());
48  		addMouseListener(createMouseListener(updater));
49  	}
50  
51  	public void setCalculationResult(CalculationResult calculationResult,
52  			Options options) {
53  		this.calculationResult = calculationResult;
54  		this.options = options;
55  		repaint();
56  	}
57  
58  	@Override
59  	protected void paintComponent(Graphics gOld) {
60  		super.paintComponent(gOld);
61  		Graphics2D g = (Graphics2D) gOld;
62  		Renderer.paintAll(g, options, numStandardDeviations, getWidth(),
63  				getHeight(), calculationResult, true, true);
64  	}
65  
66  	public static interface CellsUpdater {
67  
68  		void update(DisplayPanel display, Bounds bounds);
69  	}
70  
71  	private KeyListener createKeyListener() {
72  		return new KeyListener() {
73  
74  			@Override
75  			public void keyTyped(KeyEvent e) {
76  
77  			}
78  
79  			@Override
80  			public void keyPressed(KeyEvent e) {
81  				int keyCode = e.getKeyCode();
82  				if (keyCode == 49) {
83  					numStandardDeviations = 1;
84  					repaint();
85  				} else if (keyCode == 50) {
86  					numStandardDeviations = 2;
87  					repaint();
88  				} else if (keyCode == 51) {
89  					numStandardDeviations = 3;
90  					repaint();
91  				}
92  			}
93  
94  			@Override
95  			public void keyReleased(KeyEvent e) {
96  
97  			}
98  		};
99  	}
100 
101 	private MouseListener createMouseListener(final CellsUpdater updater) {
102 		return new MouseListener() {
103 
104 			@Override
105 			public void mouseClicked(final MouseEvent e) {
106 				if (e.getClickCount() == 2) {
107 					log.info("double clicked");
108 					Thread t = new Thread(new Runnable() {
109 
110 						@Override
111 						public void run() {
112 							log.info("updating cells");
113 							double propX = (double) e.getX() / getWidth();
114 							double propY = (double) e.getY() / getHeight();
115 							double zoomFactor = 0.5;
116 							Bounds b = options.getBounds();
117 							double topLeftLat = b.getTopLeftLat() - propY
118 									* (b.getHeightDegrees()) + zoomFactor
119 									* b.getHeightDegrees() / 2;
120 							double topLeftLon = b.getTopLeftLon() + propX
121 									* b.getWidthDegrees() - zoomFactor
122 									* b.getWidthDegrees() / 2;
123 							double bottomRightLat = topLeftLat - zoomFactor
124 									* b.getHeightDegrees();
125 							double bottomRightLon = topLeftLon + zoomFactor
126 									* b.getWidthDegrees();
127 							updater.update(DisplayPanel.this, new Bounds(
128 									topLeftLat, topLeftLon, bottomRightLat,
129 									bottomRightLon));
130 							repaint();
131 						}
132 					});
133 					t.start();
134 				}
135 			}
136 
137 			@Override
138 			public void mousePressed(MouseEvent e) {
139 
140 			}
141 
142 			@Override
143 			public void mouseReleased(MouseEvent e) {
144 
145 			}
146 
147 			@Override
148 			public void mouseEntered(MouseEvent e) {
149 
150 			}
151 
152 			@Override
153 			public void mouseExited(MouseEvent e) {
154 
155 			}
156 		};
157 	}
158 
159 	public void run() {
160 		SwingUtilities.invokeLater(new Runnable() {
161 
162 			@Override
163 			public void run() {
164 				final JFrame f = new JFrame("Vessel Traffic Density");
165 				// Sets the behavior for when the window is closed
166 				f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
167 				// Add a layout manager so that the button is not placed on top
168 				// of the
169 				// label
170 				f.setLayout(new FlowLayout());
171 				// // Add a label and a button
172 				// f.add(new JLabel("Hello, world!"));
173 				// f.add(new JButton("Press me!"));
174 				f.add(DisplayPanel.this);
175 				// Arrange the components inside the window
176 				f.pack();
177 				// By default, the window is not visible. Make it visible.
178 				f.setVisible(true);
179 
180 				f.addComponentListener(new java.awt.event.ComponentAdapter() {
181 					@Override
182 					public void componentResized(ComponentEvent e) {
183 						DisplayPanel.this.setPreferredSize(new Dimension(f
184 								.getWidth(), f.getHeight()));
185 					}
186 				});
187 			}
188 		});
189 
190 	}
191 
192 	public static void displayGui(final Observable<File> files,
193 			final Options options, final CalculationResult calculationResult) {
194 		final DisplayPanel display = new DisplayPanel(2, new CellsUpdater() {
195 			@Override
196 			public void update(DisplayPanel display, Bounds bounds) {
197 				// decrease cell size by 0.8 beyond the normal proportional
198 				// decrease
199 				double cellSizeDegrees = bounds.getWidthDegrees()
200 						/ options.getBounds().getWidthDegrees()
201 						* options.getCellSizeDegreesAsDouble() * 0.8;
202 				Options o2 = Options.builder().cellSizeDegrees(cellSizeDegrees)
203 						.bounds(bounds).build();
204 				display.setCalculationResult(DistanceTravelledCalculator
205 						.calculateTrafficDensity(o2, files), o2);
206 			}
207 		});
208 		display.setCalculationResult(calculationResult, options);
209 		display.run();
210 	}
211 
212 }