1 package nl.tudelft.simulation.dsol.swing.gui.control;
2
3 import java.awt.Dimension;
4 import java.awt.FlowLayout;
5 import java.awt.Font;
6 import java.io.Serializable;
7 import java.util.Timer;
8 import java.util.TimerTask;
9
10 import javax.swing.JLabel;
11 import javax.swing.JPanel;
12
13 import org.djunits.value.vdouble.scalar.Duration;
14 import org.djunits.value.vfloat.scalar.FloatDuration;
15
16 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
17 import nl.tudelft.simulation.dsol.swing.gui.appearance.AppearanceControl;
18 import nl.tudelft.simulation.dsol.swing.gui.appearance.AppearanceControlLabel;
19
20 /**
21 * Panel that displays the simulation speed.
22 * <p>
23 * Copyright (c) 2020-2023 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
24 * for project information <a href="https://simulation.tudelft.nl/dsol/manual/" target="_blank">DSOL Manual</a>. The DSOL
25 * project is distributed under a three-clause BSD-style license, which can be found at
26 * <a href="https://https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">DSOL License</a>.
27 * </p>
28 * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
29 * @param <T> the time type
30 */
31 public abstract class SpeedPanel<T extends Number & Comparable<T>> extends JPanel implements AppearanceControl
32 {
33 /** */
34 private static final long serialVersionUID = 20141211L;
35
36 /** The JLabel that displays the simulation speed. */
37 @SuppressWarnings("checkstyle:visibilitymodifier")
38 public JLabel speedLabel;
39
40 /** the simulator. */
41 @SuppressWarnings("checkstyle:visibilitymodifier")
42 final SimulatorInterface<T> simulator;
43
44 /** Font used to display the clock. */
45 private Font timeFont = new Font("SansSerif", Font.BOLD, 18);
46
47 /** The timer (so we can cancel it). */
48 private Timer timer;
49
50 /** Timer update interval in msec. */
51 private long updateIntervalMs = 1000;
52
53 /** Simulation time time. */
54 private T prevSimTime;
55
56 /**
57 * Construct a clock panel.
58 * @param simulator SimulatorInterface<T>; the simulator
59 */
60 public SpeedPanel(final SimulatorInterface<T> simulator)
61 {
62 this.simulator = simulator;
63 setLayout(new FlowLayout(FlowLayout.LEFT));
64 setFont(getTimeFont());
65
66 this.speedLabel = new AppearanceControlLabel();
67 this.speedLabel.setFont(getTimeFont());
68 this.speedLabel.setMaximumSize(new Dimension(100, 35));
69 add(this.speedLabel);
70
71 this.timer = new Timer();
72 this.timer.scheduleAtFixedRate(new TimeUpdateTask(), 0, this.updateIntervalMs);
73 }
74
75 /**
76 * Cancel the timer task.
77 */
78 public void cancelTimer()
79 {
80 if (this.timer != null)
81 {
82 this.timer.cancel();
83 }
84 this.timer = null;
85 }
86
87 /** Updater for the clock panel. */
88 protected class TimeUpdateTask extends TimerTask implements Serializable
89 {
90 /** */
91 private static final long serialVersionUID = 20140000L;
92
93 /** {@inheritDoc} */
94 @Override
95 public void run()
96 {
97 T simulationTime = SpeedPanel.this.getSimulator().getSimulatorTime();
98 getSpeedLabel().setText(formatSpeed(simulationTime));
99 getSpeedLabel().repaint();
100 }
101
102 /** {@inheritDoc} */
103 @Override
104 public String toString()
105 {
106 return "TimeUpdateTask of SpeedPanel";
107 }
108 }
109
110 /**
111 * @return speedLabel
112 */
113 public JLabel getSpeedLabel()
114 {
115 return this.speedLabel;
116 }
117
118 /**
119 * @return simulator
120 */
121 public SimulatorInterface<T> getSimulator()
122 {
123 return this.simulator;
124 }
125
126 /**
127 * @return timeFont.
128 */
129 public Font getTimeFont()
130 {
131 return this.timeFont;
132 }
133
134 /**
135 * @return updateInterval
136 */
137 public long getUpdateIntervalMs()
138 {
139 return this.updateIntervalMs;
140 }
141
142 /**
143 * @return prevSimTime
144 */
145 public T getPrevSimTime()
146 {
147 return this.prevSimTime;
148 }
149
150 /**
151 * Set the new simulation time to be used in the next calculation for the speed.
152 * @param prevSimTime A; the new simulation time to be used in the next calculation for the speed
153 */
154 protected void setPrevSimTime(final T prevSimTime)
155 {
156 this.prevSimTime = prevSimTime;
157 }
158
159 /**
160 * Returns the simulation speed as a String.
161 * @param simulationTime A; simulation time
162 * @return simulation speed
163 */
164 protected abstract String formatSpeed(T simulationTime);
165
166 /** {@inheritDoc} */
167 @Override
168 public boolean isForeground()
169 {
170 return true;
171 }
172
173 /** {@inheritDoc} */
174 @Override
175 public String toString()
176 {
177 return "SpeedPanel";
178 }
179
180 /**
181 * SpeedPanel for a double time. The speed calculation can be adjusted.
182 * <p>
183 * Copyright (c) 2020-2023 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved.
184 * See for project information <a href="https://simulation.tudelft.nl/dsol/manual/" target="_blank">DSOL Manual</a>. The
185 * DSOL project is distributed under a three-clause BSD-style license, which can be found at
186 * <a href="https://https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">DSOL License</a>.
187 * </p>
188 * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
189 */
190 public static class TimeDouble extends SpeedPanel<Double>
191 {
192 /** */
193 private static final long serialVersionUID = 20201227L;
194
195 /**
196 * Construct a clock panel with a double time.
197 * @param simulator SimulatorInterface; the simulator
198 */
199 public TimeDouble(final SimulatorInterface<Double> simulator)
200 {
201 super(simulator);
202 setPrevSimTime(0.0);
203 }
204
205 /** {@inheritDoc} */
206 @Override
207 protected String formatSpeed(final Double simulationTime)
208 {
209 if (simulationTime == null)
210 {
211 return "0.0";
212 }
213 double speed = (simulationTime - getPrevSimTime()) / (0.001 * getUpdateIntervalMs());
214 setPrevSimTime(simulationTime);
215 return String.format("%6.2f x ", speed);
216 }
217 }
218
219 /**
220 * SpeedPanel for a float time. The speed calculation can be adjusted.
221 * <p>
222 * Copyright (c) 2020-2023 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved.
223 * See for project information <a href="https://simulation.tudelft.nl/dsol/manual/" target="_blank">DSOL Manual</a>. The
224 * DSOL project is distributed under a three-clause BSD-style license, which can be found at
225 * <a href="https://https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">DSOL License</a>.
226 * </p>
227 * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
228 */
229 public static class TimeFloat extends SpeedPanel<Float>
230 {
231 /** */
232 private static final long serialVersionUID = 20201227L;
233
234 /**
235 * Construct a clock panel with a float time.
236 * @param simulator SimulatorInterface; the simulator
237 */
238 public TimeFloat(final SimulatorInterface<Float> simulator)
239 {
240 super(simulator);
241 setPrevSimTime(0.0f);
242 }
243
244 /** {@inheritDoc} */
245 @Override
246 protected String formatSpeed(final Float simulationTime)
247 {
248 if (simulationTime == null)
249 {
250 return "0.0";
251 }
252 double speed = (simulationTime - getPrevSimTime()) / (0.001 * getUpdateIntervalMs());
253 setPrevSimTime(simulationTime);
254 return String.format("%6.2f x ", speed);
255 }
256 }
257
258 /**
259 * SpeedPanel for a long time. The speed calculation can be adjusted.
260 * <p>
261 * Copyright (c) 2020-2023 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved.
262 * See for project information <a href="https://simulation.tudelft.nl/dsol/manual/" target="_blank">DSOL Manual</a>. The
263 * DSOL project is distributed under a three-clause BSD-style license, which can be found at
264 * <a href="https://https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">DSOL License</a>.
265 * </p>
266 * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
267 */
268 public static class TimeLong extends SpeedPanel<Long>
269 {
270 /** */
271 private static final long serialVersionUID = 20201227L;
272
273 /**
274 * Construct a clock panel with a long time.
275 * @param simulator SimulatorInterface; the simulator
276 */
277 public TimeLong(final SimulatorInterface<Long> simulator)
278 {
279 super(simulator);
280 setPrevSimTime(0L);
281 }
282
283 /** {@inheritDoc} */
284 @Override
285 protected String formatSpeed(final Long simulationTime)
286 {
287 if (simulationTime == null)
288 {
289 return "0.0";
290 }
291 double speed = (simulationTime - getPrevSimTime()) / (0.001 * getUpdateIntervalMs());
292 setPrevSimTime(simulationTime);
293 return String.format("%6.2f x ", speed);
294 }
295 }
296
297 /**
298 * SpeedPanel for a djutils Duration. The speed calculation can be adjusted.
299 * <p>
300 * Copyright (c) 2020-2023 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved.
301 * See for project information <a href="https://simulation.tudelft.nl/dsol/manual/" target="_blank">DSOL Manual</a>. The
302 * DSOL project is distributed under a three-clause BSD-style license, which can be found at
303 * <a href="https://https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">DSOL License</a>.
304 * </p>
305 * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
306 */
307 public static class TimeDoubleUnit extends SpeedPanel<Duration>
308 {
309 /** */
310 private static final long serialVersionUID = 20201227L;
311
312 /**
313 * Construct a clock panel with a djutils Duration.
314 * @param simulator SimulatorInterface; the simulator
315 */
316 public TimeDoubleUnit(final SimulatorInterface<Duration> simulator)
317 {
318 super(simulator);
319 setPrevSimTime(Duration.ZERO);
320 }
321
322 /** {@inheritDoc} */
323 @Override
324 protected String formatSpeed(final Duration simulationTime)
325 {
326 if (simulationTime == null)
327 {
328 return "0.0";
329 }
330 double speed = (simulationTime.si - getPrevSimTime().si) / (0.001 * getUpdateIntervalMs());
331 setPrevSimTime(simulationTime);
332 return String.format("%6.2f x ", speed);
333 }
334 }
335
336 /**
337 * SpeedPanel for a djutils FloatDuration. The speed calculation can be adjusted.
338 * <p>
339 * Copyright (c) 2020-2023 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved.
340 * See for project information <a href="https://simulation.tudelft.nl/dsol/manual/" target="_blank">DSOL Manual</a>. The
341 * DSOL project is distributed under a three-clause BSD-style license, which can be found at
342 * <a href="https://https://simulation.tudelft.nl/dsol/docs/latest/license.html" target="_blank">DSOL License</a>.
343 * </p>
344 * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
345 */
346 public static class TimeFloatUnit extends SpeedPanel<FloatDuration>
347 {
348 /** */
349 private static final long serialVersionUID = 20201227L;
350
351 /**
352 * Construct a clock panel with a djutils Duration.
353 * @param simulator SimulatorInterface; the simulator
354 */
355 public TimeFloatUnit(final SimulatorInterface<FloatDuration> simulator)
356 {
357 super(simulator);
358 setPrevSimTime(FloatDuration.ZERO);
359 }
360
361 /** {@inheritDoc} */
362 @Override
363 protected String formatSpeed(final FloatDuration simulationTime)
364 {
365 if (simulationTime == null)
366 {
367 return "0.0";
368 }
369 double speed = (simulationTime.si - getPrevSimTime().si) / (0.001 * getUpdateIntervalMs());
370 setPrevSimTime(simulationTime);
371 return String.format("%6.2f x ", speed);
372 }
373 }
374
375 }