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