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 @Override
70 protected void paintComponent(final Graphics g)
71 {
72 super.paintComponent(g);
73 g.drawImage(this.image, 0, 0, null);
74 for (TrafCODObject tco : this.trafCODObjects)
75 {
76 tco.draw((Graphics2D) g);
77 }
78 }
79
80
81
82
83
84 void addTrafCODObject(final TrafCODObject trafCODObject)
85 {
86 this.trafCODObjects.add(trafCODObject);
87 }
88
89
90 @Override
91 public void mouseDragged(MouseEvent e)
92 {
93 mouseMoved(e);
94 }
95
96
97 @Override
98 public void mouseMoved(MouseEvent e)
99 {
100 String toolTipText = null;
101 for (TrafCODObject tco : this.trafCODObjects)
102 {
103 toolTipText = tco.toolTipHit(e.getX(), e.getY());
104 if (null != toolTipText)
105 {
106 break;
107 }
108 }
109
110 setToolTipText(toolTipText);
111 }
112
113
114 @Override
115 public void mouseClicked(MouseEvent e)
116 {
117
118 }
119
120
121 @Override
122 public void mousePressed(MouseEvent e)
123 {
124
125 }
126
127
128 @Override
129 public void mouseReleased(MouseEvent e)
130 {
131
132 }
133
134
135 @Override
136 public void mouseEntered(MouseEvent e)
137 {
138 ToolTipManager.sharedInstance().setInitialDelay(0);
139 }
140
141
142 @Override
143 public void mouseExited(MouseEvent e)
144 {
145 ToolTipManager.sharedInstance().setInitialDelay(this.defaultInitialDelay);
146 }
147
148 }
149
150
151
152
153
154 interface TrafCODObject
155 {
156
157
158
159
160 void draw(Graphics2D g2);
161
162
163
164
165
166
167
168
169 String toolTipHit(int testX, int testY);
170
171 }
172
173
174
175
176 class DetectorImage implements TrafCODObject, EventListenerInterface
177 {
178
179 private final TrafCODDisplay display;
180
181
182 private final int x;
183
184
185 private final int y;
186
187
188 private final String description;
189
190
191 private Color fillColor = Color.WHITE;
192
193
194 private static final int BOX_SIZE = 13;
195
196
197 private static final int xOffset = 5;
198
199
200 private static final int yOffset = 5;
201
202
203
204
205
206
207
208 public DetectorImage(final TrafCODDisplay display, Point2D center, String description)
209 {
210 this.display = display;
211 this.x = (int) center.getX();
212 this.y = (int) center.getY();
213 this.description = description;
214 display.addTrafCODObject(this);
215 }
216
217
218 @Override
219 public void draw(Graphics2D g2)
220 {
221 g2.setColor(this.fillColor);
222 g2.fillRect(xOffset + this.x - BOX_SIZE / 2, yOffset + this.y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
223 g2.setColor(Color.BLACK);
224 g2.drawRect(xOffset + this.x - BOX_SIZE / 2, yOffset + this.y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
225 }
226
227
228 @Override
229 public void notify(EventInterface event) throws RemoteException
230 {
231 if (event.getType().equals(NonDirectionalOccupancySensor.NON_DIRECTIONAL_OCCUPANCY_SENSOR_TRIGGER_ENTRY_EVENT))
232 {
233 this.fillColor = Color.BLUE;
234 }
235 else if (event.getType().equals(NonDirectionalOccupancySensor.NON_DIRECTIONAL_OCCUPANCY_SENSOR_TRIGGER_EXIT_EVENT))
236 {
237 this.fillColor = Color.WHITE;
238 }
239 this.display.repaint();
240 }
241
242
243 @Override
244 public String toolTipHit(final int testX, final int testY)
245 {
246 if (testX < xOffset + this.x - BOX_SIZE / 2 || testX >= xOffset + this.x + BOX_SIZE / 2
247 || testY < yOffset - BOX_SIZE / 2 + this.y || testY >= yOffset + this.y + BOX_SIZE / 2)
248 {
249 return null;
250 }
251 return this.description;
252 }
253
254 }
255
256
257
258
259
260 class TrafficLightImage implements TrafficLight, TrafCODObject
261 {
262
263 private final TrafCODDisplay display;
264
265
266 private final int x;
267
268
269 private final int y;
270
271
272 private final String description;
273
274
275 private TrafficLightColor color = TrafficLightColor.BLACK;
276
277
278
279
280
281
282
283 public TrafficLightImage(final TrafCODDisplay display, final Point2D center, final String description)
284 {
285 this.display = display;
286 this.x = (int) center.getX();
287 this.y = (int) center.getY();
288 this.description = description;
289 display.addTrafCODObject(this);
290 }
291
292
293 @Override
294 public String toolTipHit(int testX, int testY)
295 {
296 if (testX < this.x - DISC_SIZE / 2 || testX >= this.x + DISC_SIZE / 2 || testY < this.y - DISC_SIZE / 2
297 || testY >= this.y + DISC_SIZE / 2)
298 {
299 return null;
300 }
301 return this.description;
302 }
303
304
305 @Override
306 public DirectedPoint getLocation()
307 {
308 return null;
309 }
310
311
312 @Override
313 public Bounds getBounds()
314 {
315 return null;
316 }
317
318
319 @Override
320 public Lane getLane()
321 {
322 return null;
323 }
324
325
326 @Override
327 public LongitudinalDirectionality getDirection()
328 {
329 return LongitudinalDirectionality.DIR_NONE;
330 }
331
332
333 @Override
334 public Length getLongitudinalPosition()
335 {
336 return null;
337 }
338
339
340 @Override
341 public OTSLine3D getGeometry()
342 {
343 return null;
344 }
345
346
347 @Override
348 public Length getHeight()
349 {
350 return null;
351 }
352
353
354 @Override
355 public String getId()
356 {
357 return null;
358 }
359
360
361 @Override
362 public String getFullId()
363 {
364 return null;
365 }
366
367
368 @Override
369 public boolean addListener(EventListenerInterface listener, EventType eventType) throws RemoteException
370 {
371 return false;
372 }
373
374
375 @Override
376 public boolean addListener(EventListenerInterface listener, EventType eventType, boolean weak) throws RemoteException
377 {
378 return false;
379 }
380
381
382 @Override
383 public boolean addListener(EventListenerInterface listener, EventType eventType, short position) throws RemoteException
384 {
385 return false;
386 }
387
388
389 @Override
390 public boolean addListener(EventListenerInterface listener, EventType eventType, short position, boolean weak)
391 throws RemoteException
392 {
393 return false;
394 }
395
396
397 @Override
398 public boolean removeListener(EventListenerInterface listener, EventType eventType) throws RemoteException
399 {
400 return false;
401 }
402
403
404 @Override
405 public TrafficLightColor getTrafficLightColor()
406 {
407 return null;
408 }
409
410
411 @Override
412 public void setTrafficLightColor(TrafficLightColor trafficLightColor)
413 {
414 this.color = trafficLightColor;
415 this.display.repaint();
416 }
417
418
419 private static final int DISC_SIZE = 11;
420
421
422 @Override
423 public void draw(Graphics2D g2)
424 {
425 Color lightColor;
426 switch (this.color)
427 {
428 case BLACK:
429 lightColor = Color.BLACK;
430 break;
431
432 case GREEN:
433 lightColor = Color.green;
434 break;
435
436 case YELLOW:
437 lightColor = Color.YELLOW;
438 break;
439
440 case RED:
441 lightColor = Color.RED;
442 break;
443
444 default:
445 System.err.println("Unhandled TrafficLightColor: " + this.color);
446 return;
447 }
448 g2.setColor(lightColor);
449 g2.fillOval(this.x - DISC_SIZE / 2, this.y - DISC_SIZE / 2, DISC_SIZE, DISC_SIZE);
450
451 }
452
453 }