1 package org.opentrafficsim.gui;
2
3 import java.awt.BorderLayout;
4 import java.awt.Container;
5 import java.awt.Dimension;
6 import java.awt.event.ActionEvent;
7 import java.awt.event.ActionListener;
8 import java.awt.event.WindowEvent;
9 import java.awt.event.WindowListener;
10 import java.awt.geom.Rectangle2D;
11 import java.rmi.RemoteException;
12 import java.text.NumberFormat;
13 import java.util.ArrayList;
14
15 import javax.swing.BoxLayout;
16 import javax.swing.ImageIcon;
17 import javax.swing.JButton;
18 import javax.swing.JFrame;
19 import javax.swing.JLabel;
20 import javax.swing.JPanel;
21
22 import org.opentrafficsim.base.modelproperties.PropertyException;
23 import org.opentrafficsim.core.gtu.animation.GTUColorer;
24 import org.opentrafficsim.simulationengine.SimpleAnimator;
25 import org.opentrafficsim.simulationengine.WrappableAnimation;
26
27 import nl.tudelft.simulation.dsol.animation.D2.AnimationPanel;
28 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
29 import nl.tudelft.simulation.event.Event;
30 import nl.tudelft.simulation.language.io.URLResource;
31
32
33
34
35
36
37
38
39
40
41
42
43 public class OTSAnimationPanel extends OTSSimulationPanel implements ActionListener, WindowListener
44 {
45
46 private static final long serialVersionUID = 20150617L;
47
48
49 private final AnimationPanel animationPanel;
50
51
52 private final JPanel borderPanel;
53
54
55 private GTUColorer gtuColorer = null;
56
57
58 private ColorControlPanel colorControlPanel = null;
59
60
61 private final JLabel coordinateField;
62
63
64 private final ArrayList<JButton> buttons = new ArrayList<JButton>();
65
66
67 private static final NumberFormat FORMATTER = NumberFormat.getInstance();
68
69
70 @SuppressWarnings("checkstyle:visibilitymodifier")
71 protected boolean closeHandlerRegistered = false;
72
73
74 @SuppressWarnings("checkstyle:visibilitymodifier")
75 protected boolean windowExited = false;
76
77
78 static
79 {
80 FORMATTER.setMaximumFractionDigits(3);
81 }
82
83
84
85
86
87
88
89
90
91
92
93 public OTSAnimationPanel(final Rectangle2D extent, final Dimension size, final SimpleAnimator simulator,
94 final WrappableAnimation wrappableAnimation, final GTUColorer gtuColorer) throws RemoteException, PropertyException
95 {
96 super(simulator, wrappableAnimation);
97
98
99 this.animationPanel = new AnimationPanel(extent, size, simulator);
100 this.borderPanel = new JPanel(new BorderLayout());
101 this.borderPanel.add(this.animationPanel, BorderLayout.CENTER);
102 getTabbedPane().addTab(0, "animation", this.borderPanel);
103 getTabbedPane().setSelectedIndex(0);
104
105
106 this.gtuColorer = gtuColorer;
107 this.colorControlPanel = new ColorControlPanel(this.gtuColorer);
108 JPanel buttonPanel = new JPanel();
109 buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
110 this.borderPanel.add(buttonPanel, BorderLayout.NORTH);
111 buttonPanel.add(this.colorControlPanel);
112
113
114 buttonPanel.add(new JLabel(" "));
115 buttonPanel.add(makeButton("allButton", "/Expand.png", "ZoomAll", "Zoom whole network", true));
116 buttonPanel.add(makeButton("homeButton", "/Home.png", "Home", "Zoom to original extent", true));
117 buttonPanel.add(makeButton("gridButton", "/Grid.png", "Grid", "Toggle grid on/off", true));
118 buttonPanel.add(new JLabel(" "));
119 this.coordinateField = new JLabel("Mouse: ");
120 this.coordinateField.setMinimumSize(new Dimension(250, 10));
121 this.coordinateField.setPreferredSize(new Dimension(250, 10));
122 buttonPanel.add(this.coordinateField);
123
124
125 this.animationPanel.notify(new Event(SimulatorInterface.START_REPLICATION_EVENT, simulator, null));
126
127
128 this.animationPanel.setShowToolTip(false);
129
130
131 new UpdateTimer().start();
132
133
134 installWindowCloseHandler();
135 }
136
137
138
139
140
141
142
143
144
145
146 private JButton makeButton(final String name, final String iconPath, final String actionCommand,
147 final String toolTipText, final boolean enabled)
148 {
149
150 JButton result = new JButton(new ImageIcon(URLResource.getResource(iconPath)));
151 result.setName(name);
152 result.setEnabled(enabled);
153 result.setActionCommand(actionCommand);
154 result.setToolTipText(toolTipText);
155 result.addActionListener(this);
156 this.buttons.add(result);
157 return result;
158 }
159
160
161 @Override
162 public final void actionPerformed(final ActionEvent actionEvent)
163 {
164 String actionCommand = actionEvent.getActionCommand();
165 try
166 {
167 if (actionCommand.equals("Home"))
168 {
169 this.animationPanel.home();
170 }
171 if (actionCommand.equals("ZoomAll"))
172 {
173 this.animationPanel.zoomAll();
174 }
175 if (actionCommand.equals("Grid"))
176 {
177 this.animationPanel.showGrid(!this.animationPanel.isShowGrid());
178 }
179 }
180 catch (Exception exception)
181 {
182 exception.printStackTrace();
183 }
184 }
185
186
187
188
189
190 public final AnimationPanel getAnimationPanel()
191 {
192 return this.animationPanel;
193 }
194
195
196
197
198 protected final void updateWorldCoordinate()
199 {
200 String worldPoint =
201 "(x=" + FORMATTER.format(this.animationPanel.getWorldCoordinate().getX()) + " ; y="
202 + FORMATTER.format(this.animationPanel.getWorldCoordinate().getY()) + ")";
203 this.coordinateField.setText("Mouse: " + worldPoint);
204 this.coordinateField.repaint();
205 }
206
207
208
209
210
211
212 public final GTUColorer getGTUColorer()
213 {
214 return this.gtuColorer;
215 }
216
217
218
219
220
221
222 public final ColorControlPanel getColorControlPanel()
223 {
224 return this.colorControlPanel;
225 }
226
227
228
229
230 public final void installWindowCloseHandler()
231 {
232 if (this.closeHandlerRegistered)
233 {
234 return;
235 }
236
237
238 new DisposeOnCloseThread(this).start();
239 }
240
241
242 protected class DisposeOnCloseThread extends Thread
243 {
244
245 private OTSAnimationPanel panel;
246
247
248
249
250 public DisposeOnCloseThread(final OTSAnimationPanel panel)
251 {
252 super();
253 this.panel = panel;
254 }
255
256
257 @Override
258 public final void run()
259 {
260 Container root = this.panel;
261 while (!(root instanceof JFrame))
262 {
263 try
264 {
265 Thread.sleep(10);
266 }
267 catch (InterruptedException exception)
268 {
269
270 }
271
272
273 root = this.panel;
274 while (null != root.getParent() && !(root instanceof JFrame))
275 {
276 root = root.getParent();
277 }
278 }
279 JFrame frame = (JFrame) root;
280 frame.addWindowListener(this.panel);
281 this.panel.closeHandlerRegistered = true;
282 }
283
284
285 @Override
286 public final String toString()
287 {
288 return "DisposeOnCloseThread of OTSAnimationPanel [panel=" + this.panel + "]";
289 }
290 }
291
292
293 @Override
294 public void windowOpened(final WindowEvent e)
295 {
296
297 }
298
299
300 @Override
301 public final void windowClosing(final WindowEvent e)
302 {
303
304 }
305
306
307 @Override
308 public final void windowClosed(final WindowEvent e)
309 {
310 this.windowExited = true;
311 }
312
313
314 @Override
315 public final void windowIconified(final WindowEvent e)
316 {
317
318 }
319
320
321 @Override
322 public final void windowDeiconified(final WindowEvent e)
323 {
324
325 }
326
327
328 @Override
329 public final void windowActivated(final WindowEvent e)
330 {
331
332 }
333
334
335 @Override
336 public final void windowDeactivated(final WindowEvent e)
337 {
338
339 }
340
341
342
343
344 protected class UpdateTimer extends Thread
345 {
346
347 @Override
348 public final void run()
349 {
350 while (!OTSAnimationPanel.this.windowExited)
351 {
352 if (OTSAnimationPanel.this.isShowing())
353 {
354 OTSAnimationPanel.this.updateWorldCoordinate();
355 }
356 try
357 {
358 Thread.sleep(50);
359 }
360 catch (InterruptedException exception)
361 {
362
363 }
364 }
365 }
366
367
368 @Override
369 public final String toString()
370 {
371 return "UpdateTimer thread for OTSAnimationPanel";
372 }
373
374 }
375 }