1 package org.opentrafficsim.core.animation;
2
3 import java.awt.Color;
4 import java.awt.Dimension;
5 import java.awt.Font;
6 import java.awt.FontMetrics;
7 import java.awt.Graphics2D;
8 import java.awt.geom.Point2D;
9 import java.awt.geom.Rectangle2D;
10 import java.awt.image.ImageObserver;
11 import java.io.Serializable;
12 import java.rmi.RemoteException;
13
14 import javax.media.j3d.Bounds;
15 import javax.naming.NamingException;
16
17 import org.opentrafficsim.core.logger.SimLogger;
18
19 import nl.tudelft.simulation.dsol.animation.Locatable;
20 import nl.tudelft.simulation.dsol.animation.D2.Renderable2D;
21 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
22 import nl.tudelft.simulation.language.d3.BoundingBox;
23 import nl.tudelft.simulation.language.d3.DirectedPoint;
24
25
26
27
28
29
30
31
32
33
34
35
36
37 public abstract class TextAnimation implements Locatable, Serializable
38 {
39
40 private static final long serialVersionUID = 20161211L;
41
42
43 private final Locatable source;
44
45
46 private String text;
47
48
49 private final float dx;
50
51
52 private final float dy;
53
54
55 private final TextAlignment textAlignment;
56
57
58 private Color color;
59
60
61 private final float fontSize;
62
63
64 private final AnimationImpl animationImpl;
65
66
67 private Font font;
68
69
70 private Rectangle2D fontRectangle = null;
71
72
73
74
75
76
77
78
79
80
81
82
83
84 @SuppressWarnings("checkstyle:parameternumber")
85 public TextAnimation(final Locatable source, final String text, final float dx, final float dy,
86 final TextAlignment textAlignment, final Color color, final float fontSize,
87 final SimulatorInterface.TimeDoubleUnit simulator) throws RemoteException, NamingException
88 {
89 this.source = source;
90 this.text = text;
91 this.dx = dx;
92 this.dy = dy;
93 this.textAlignment = textAlignment;
94 this.color = color;
95 this.fontSize = fontSize;
96
97 this.font = new Font("SansSerif", Font.PLAIN, 2);
98 if (this.fontSize != 2.0f)
99 {
100 this.font = this.font.deriveFont(this.fontSize);
101 }
102
103 this.animationImpl = new AnimationImpl(this, simulator);
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117 public TextAnimation(final Locatable source, final String text, final float dx, final float dy,
118 final TextAlignment textAlignment, final Color color, final SimulatorInterface.TimeDoubleUnit simulator)
119 throws RemoteException, NamingException
120 {
121 this(source, text, dx, dy, textAlignment, color, 2.0f, simulator);
122 }
123
124
125 @Override
126 @SuppressWarnings("checkstyle:designforextension")
127 public DirectedPoint getLocation() throws RemoteException
128 {
129
130 DirectedPoint p = this.source.getLocation();
131 return new DirectedPoint(p.x, p.y, Double.MAX_VALUE, 0.0, 0.0, p.getRotZ());
132 }
133
134
135 @Override
136 public final Bounds getBounds() throws RemoteException
137 {
138 return new BoundingBox(0.0, 0.0, 0.0);
139 }
140
141
142
143
144
145
146
147 @SuppressWarnings("checkstyle:designforextension")
148 public void paint(final Graphics2D graphics, final ImageObserver observer) throws RemoteException
149 {
150 graphics.setFont(this.font);
151 synchronized (this.font)
152 {
153 if (this.fontRectangle == null)
154 {
155 FontMetrics fm = graphics.getFontMetrics();
156 this.fontRectangle = fm.getStringBounds(this.text, graphics);
157 }
158 graphics.setColor(this.color);
159 float dxText =
160 this.textAlignment.equals(TextAlignment.LEFT) ? 0.0f : this.textAlignment.equals(TextAlignment.CENTER)
161 ? (float) -this.fontRectangle.getWidth() / 2.0f : (float) -this.fontRectangle.getWidth();
162 graphics.drawString(this.text, dxText + this.dx, this.fontSize / 2.0f - this.dy);
163 }
164 }
165
166
167
168
169 public final void destroy()
170 {
171 try
172 {
173 this.animationImpl.destroy();
174 }
175 catch (NamingException exception)
176 {
177 SimLogger.always().warn(exception, "Tried to destroy Text for GTU animation of GTU {}", this.source.toString());
178 }
179 }
180
181
182
183
184
185
186
187
188
189 public abstract TextAnimation clone(Locatable newSource, SimulatorInterface.TimeDoubleUnit newSimulator)
190 throws RemoteException, NamingException;
191
192
193
194
195
196 protected final Locatable getSource()
197 {
198 return this.source;
199 }
200
201
202
203
204
205 protected final float getDx()
206 {
207 return this.dx;
208 }
209
210
211
212
213
214 protected final float getDy()
215 {
216 return this.dy;
217 }
218
219
220
221
222
223 protected final TextAlignment getTextAlignment()
224 {
225 return this.textAlignment;
226 }
227
228
229
230
231
232 protected final float getFontSize()
233 {
234 return this.fontSize;
235 }
236
237
238
239
240
241 protected final Font getFont()
242 {
243 return this.font;
244 }
245
246
247
248
249
250 protected final String getText()
251 {
252 return this.text;
253 }
254
255
256
257
258
259 protected final void setText(final String text)
260 {
261 this.text = text;
262 synchronized (this.font)
263 {
264 this.fontRectangle = null;
265 }
266 }
267
268
269
270
271
272 protected final Color getColor()
273 {
274 return this.color;
275 }
276
277
278
279
280
281 protected final void setColor(final Color color)
282 {
283 this.color = color;
284 }
285
286
287
288
289
290 public final boolean isFlip()
291 {
292 return this.animationImpl.isFlip();
293 }
294
295
296
297
298
299 public final void setFlip(final boolean flip)
300 {
301 this.animationImpl.setFlip(flip);
302 }
303
304
305
306
307
308 public final boolean isRotate()
309 {
310 return this.animationImpl.isRotate();
311 }
312
313
314
315
316
317 public final void setRotate(final boolean rotate)
318 {
319 this.animationImpl.setRotate(rotate);
320
321 }
322
323
324
325
326
327 public final boolean isScale()
328 {
329 return this.animationImpl.isScale();
330 }
331
332
333
334
335
336 public final void setScale(final boolean scale)
337 {
338 this.animationImpl.setScale(scale);
339 }
340
341
342
343
344
345 public final boolean isTranslate()
346 {
347 return this.animationImpl.isTranslate();
348 }
349
350
351
352
353
354 public final void setTranslate(final boolean translate)
355 {
356 this.animationImpl.setTranslate(translate);
357 }
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372 private static class AnimationImpl extends Renderable2D<Locatable> implements Serializable
373 {
374
375 private static final long serialVersionUID = 20170400L;
376
377
378
379
380
381
382
383
384 AnimationImpl(final Locatable source, final SimulatorInterface.TimeDoubleUnit simulator)
385 throws NamingException, RemoteException
386 {
387 super(source, simulator);
388 }
389
390
391 @Override
392 public final void paint(final Graphics2D graphics, final ImageObserver observer) throws RemoteException
393 {
394 TextAnimation ta = ((TextAnimation) getSource());
395 ta.paint(graphics, observer);
396 }
397
398
399 @Override
400 public boolean contains(final Point2D pointWorldCoordinates, final Rectangle2D extent, final Dimension screen)
401 {
402 return false;
403 }
404
405
406 @Override
407 public final String toString()
408 {
409 return "TextAnimation.AnimationImpl []";
410 }
411
412 }
413 }