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