1 package org.opentrafficsim.trafficcontrol.trafcod;
2
3 import java.awt.Color;
4 import java.awt.Dimension;
5 import java.awt.Graphics;
6 import java.awt.Graphics2D;
7 import java.awt.event.MouseEvent;
8 import java.awt.event.MouseListener;
9 import java.awt.event.MouseMotionListener;
10 import java.awt.geom.Point2D;
11 import java.awt.image.BufferedImage;
12 import java.rmi.RemoteException;
13 import java.util.HashSet;
14 import java.util.Set;
15
16 import javax.media.j3d.Bounds;
17 import javax.swing.JPanel;
18 import javax.swing.ToolTipManager;
19
20 import org.djunits.value.vdouble.scalar.Length;
21 import org.opentrafficsim.core.geometry.OTSLine3D;
22 import org.opentrafficsim.core.network.LongitudinalDirectionality;
23 import org.opentrafficsim.road.network.lane.Lane;
24 import org.opentrafficsim.road.network.lane.object.sensor.NonDirectionalOccupancySensor;
25 import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLight;
26 import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLightColor;
27
28 import nl.tudelft.simulation.event.EventInterface;
29 import nl.tudelft.simulation.event.EventListenerInterface;
30 import nl.tudelft.simulation.event.EventType;
31 import nl.tudelft.simulation.language.d3.DirectedPoint;
32
33
34
35
36
37
38
39
40
41
42 public class TrafCODDisplay extends JPanel implements MouseMotionListener, MouseListener
43 {
44
45 private static final long serialVersionUID = 20161115L;
46
47
48 private final BufferedImage image;
49
50
51 private Set<TrafCODObject> trafCODObjects = new HashSet<>();
52
53
54 final int defaultInitialDelay = ToolTipManager.sharedInstance().getInitialDelay();
55
56
57
58
59
60
61
62 public TrafCODDisplay(final BufferedImage image)
63 {
64 this.image = image;
65 super.setPreferredSize(new Dimension(this.image.getWidth(), this.image.getHeight()));
66 addMouseMotionListener(this);
67 }
68
69
70
71
72
73
74 public DetectorImage getDetectorImage(final String id)
75 {
76 for (TrafCODObject tco : this.trafCODObjects)
77 {
78 if (tco instanceof DetectorImage && ((DetectorImage) tco).getId().equals(id))
79 {
80 return (DetectorImage) tco;
81 }
82 }
83 return null;
84 }
85
86 @Override
87 protected void paintComponent(final Graphics g)
88 {
89 super.paintComponent(g);
90 g.drawImage(this.image, 0, 0, null);
91 for (TrafCODObject tco : this.trafCODObjects)
92 {
93 tco.draw((Graphics2D) g);
94 }
95 }
96
97
98
99
100
101 void addTrafCODObject(final TrafCODObject trafCODObject)
102 {
103 this.trafCODObjects.add(trafCODObject);
104 }
105
106
107 @Override
108 public void mouseDragged(MouseEvent e)
109 {
110 mouseMoved(e);
111 }
112
113
114 @Override
115 public void mouseMoved(MouseEvent e)
116 {
117 String toolTipText = null;
118 for (TrafCODObject tco : this.trafCODObjects)
119 {
120 toolTipText = tco.toolTipHit(e.getX(), e.getY());
121 if (null != toolTipText)
122 {
123 break;
124 }
125 }
126
127 setToolTipText(toolTipText);
128 }
129
130
131 @Override
132 public void mouseClicked(MouseEvent e)
133 {
134
135 }
136
137
138 @Override
139 public void mousePressed(MouseEvent e)
140 {
141
142 }
143
144
145 @Override
146 public void mouseReleased(MouseEvent e)
147 {
148
149 }
150
151
152 @Override
153 public void mouseEntered(MouseEvent e)
154 {
155 ToolTipManager.sharedInstance().setInitialDelay(0);
156 }
157
158
159 @Override
160 public void mouseExited(MouseEvent e)
161 {
162 ToolTipManager.sharedInstance().setInitialDelay(this.defaultInitialDelay);
163 }
164
165 }
166
167
168
169
170
171 interface TrafCODObject
172 {
173
174
175
176
177 void draw(Graphics2D g2);
178
179
180
181
182
183
184
185
186 String toolTipHit(int testX, int testY);
187
188 }
189
190
191
192
193 class DetectorImage implements TrafCODObject, EventListenerInterface
194 {
195
196 private final TrafCODDisplay display;
197
198
199 private final int x;
200
201
202 private final int y;
203
204
205 private final String description;
206
207
208 private final String id;
209
210
211 private Color fillColor = Color.WHITE;
212
213
214 private static final int BOX_SIZE = 13;
215
216
217 private static final int xOffset = 5;
218
219
220 private static final int yOffset = 5;
221
222
223
224
225
226
227
228
229 public DetectorImage(final TrafCODDisplay display, Point2D center, String id, String description)
230 {
231 this.display = display;
232 this.x = (int) center.getX();
233 this.y = (int) center.getY();
234 this.id = id;
235 this.description = description;
236 display.addTrafCODObject(this);
237 }
238
239
240 @Override
241 public void draw(Graphics2D g2)
242 {
243 g2.setColor(this.fillColor);
244 g2.fillRect(xOffset + this.x - BOX_SIZE / 2, yOffset + this.y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
245 g2.setColor(Color.BLACK);
246 g2.drawRect(xOffset + this.x - BOX_SIZE / 2, yOffset + this.y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
247 }
248
249
250 @Override
251 public void notify(EventInterface event) throws RemoteException
252 {
253 if (event.getType().equals(NonDirectionalOccupancySensor.NON_DIRECTIONAL_OCCUPANCY_SENSOR_TRIGGER_ENTRY_EVENT))
254 {
255 this.fillColor = Color.BLUE;
256 }
257 else if (event.getType().equals(NonDirectionalOccupancySensor.NON_DIRECTIONAL_OCCUPANCY_SENSOR_TRIGGER_EXIT_EVENT))
258 {
259 this.fillColor = Color.WHITE;
260 }
261 this.display.repaint();
262 }
263
264
265 @Override
266 public String toolTipHit(final int testX, final int testY)
267 {
268 if (testX < xOffset + this.x - BOX_SIZE / 2 || testX >= xOffset + this.x + BOX_SIZE / 2
269 || testY < yOffset - BOX_SIZE / 2 + this.y || testY >= yOffset + this.y + BOX_SIZE / 2)
270 {
271 return null;
272 }
273 return this.description;
274 }
275
276
277
278
279
280 public String getId()
281 {
282 return this.id;
283 }
284
285 }
286
287
288
289
290
291 class TrafficLightImage implements TrafficLight, TrafCODObject
292 {
293
294 private final TrafCODDisplay display;
295
296
297 private final int x;
298
299
300 private final int y;
301
302
303 private final String description;
304
305
306 private TrafficLightColor color = TrafficLightColor.BLACK;
307
308
309
310
311
312
313
314 public TrafficLightImage(final TrafCODDisplay display, final Point2D center, final String description)
315 {
316 this.display = display;
317 this.x = (int) center.getX();
318 this.y = (int) center.getY();
319 this.description = description;
320 display.addTrafCODObject(this);
321 }
322
323
324 @Override
325 public String toolTipHit(int testX, int testY)
326 {
327 if (testX < this.x - DISC_SIZE / 2 || testX >= this.x + DISC_SIZE / 2 || testY < this.y - DISC_SIZE / 2
328 || testY >= this.y + DISC_SIZE / 2)
329 {
330 return null;
331 }
332 return this.description;
333 }
334
335
336 @Override
337 public DirectedPoint getLocation()
338 {
339 return null;
340 }
341
342
343 @Override
344 public Bounds getBounds()
345 {
346 return null;
347 }
348
349
350 @Override
351 public Lane getLane()
352 {
353 return null;
354 }
355
356
357 @Override
358 public LongitudinalDirectionality getDirection()
359 {
360 return LongitudinalDirectionality.DIR_NONE;
361 }
362
363
364 @Override
365 public Length getLongitudinalPosition()
366 {
367 return null;
368 }
369
370
371 @Override
372 public OTSLine3D getGeometry()
373 {
374 return null;
375 }
376
377
378 @Override
379 public Length getHeight()
380 {
381 return null;
382 }
383
384
385 @Override
386 public String getId()
387 {
388 return null;
389 }
390
391
392 @Override
393 public String getFullId()
394 {
395 return null;
396 }
397
398
399 @Override
400 public boolean addListener(EventListenerInterface listener, EventType eventType) throws RemoteException
401 {
402 return false;
403 }
404
405
406 @Override
407 public boolean addListener(EventListenerInterface listener, EventType eventType, boolean weak) throws RemoteException
408 {
409 return false;
410 }
411
412
413 @Override
414 public boolean addListener(EventListenerInterface listener, EventType eventType, short position) throws RemoteException
415 {
416 return false;
417 }
418
419
420 @Override
421 public boolean addListener(EventListenerInterface listener, EventType eventType, short position, boolean weak)
422 throws RemoteException
423 {
424 return false;
425 }
426
427
428 @Override
429 public boolean removeListener(EventListenerInterface listener, EventType eventType) throws RemoteException
430 {
431 return false;
432 }
433
434
435 @Override
436 public TrafficLightColor getTrafficLightColor()
437 {
438 return null;
439 }
440
441
442 @Override
443 public void setTrafficLightColor(TrafficLightColor trafficLightColor)
444 {
445 this.color = trafficLightColor;
446 this.display.repaint();
447 }
448
449
450 private static final int DISC_SIZE = 11;
451
452
453 @Override
454 public void draw(Graphics2D g2)
455 {
456 Color lightColor;
457 switch (this.color)
458 {
459 case BLACK:
460 lightColor = Color.BLACK;
461 break;
462
463 case GREEN:
464 lightColor = Color.green;
465 break;
466
467 case YELLOW:
468 lightColor = Color.YELLOW;
469 break;
470
471 case RED:
472 lightColor = Color.RED;
473 break;
474
475 default:
476 System.err.println("Unhandled TrafficLightColor: " + this.color);
477 return;
478 }
479 g2.setColor(lightColor);
480 g2.fillOval(this.x - DISC_SIZE / 2, this.y - DISC_SIZE / 2, DISC_SIZE, DISC_SIZE);
481
482 }
483
484 }