1 package org.opentrafficsim.trafficcontrol.trafcod;
2
3 import java.awt.BorderLayout;
4 import java.awt.Color;
5 import java.awt.Component;
6 import java.awt.Dimension;
7 import java.awt.Graphics2D;
8 import java.awt.event.ActionEvent;
9 import java.awt.event.ActionListener;
10 import java.awt.image.BufferedImage;
11 import java.util.ArrayList;
12 import java.util.Comparator;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18
19 import javax.swing.BoxLayout;
20 import javax.swing.ImageIcon;
21 import javax.swing.JCheckBox;
22 import javax.swing.JFrame;
23 import javax.swing.JLabel;
24 import javax.swing.JPanel;
25 import javax.swing.JScrollPane;
26 import javax.swing.SwingUtilities;
27
28 import nl.tudelft.simulation.language.Throw;
29
30 import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLightException;
31 import org.opentrafficsim.trafficcontrol.TrafficController;
32
33
34
35
36
37
38
39
40
41
42
43
44
45 public class Diagram
46 {
47
48
49 final static int DIVIDER_1 = 0;
50
51
52 final static int CAR_ROUNDABOUT_LEFT = 1;
53
54
55 final static int PT_DIV_L = 3;
56
57
58 final static int DIVIDER_2 = 4;
59
60
61 final static int CAR_LEFT = 5;
62
63
64 final static int CAR_CENTER = 7;
65
66
67 final static int CAR_RIGHT = 9;
68
69
70 final static int DIVIDER_3 = 10;
71
72
73 final static int PT_RIGHT_BICYCLE = 11;
74
75
76 final static int DIVIDER_4 = 12;
77
78
79 final static int BICYCLE = 13;
80
81
82 final static int DIVIDER_5 = 14;
83
84
85 final static int PT_BICYCLE_SIDEWALK = 15;
86
87
88 final static int DIVIDER_6 = 16;
89
90
91 final static int SIDEWALK = 17;
92
93
94 final static int DIVIDER_7 = 18;
95
96
97 final static int PT_SIDEWALK_SHOULDER = 19;
98
99
100 final static int SHOULDER = 20;
101
102
103 final static int BOUNDARY = 21;
104
105
106 final List<Short> streams;
107
108
109 final Map<Short, XYPair[]> routes = new HashMap<>();
110
111
112
113
114
115
116 public Diagram(final Set<Short> streams) throws TrafficLightException
117 {
118 this.streams = new ArrayList<Short>(streams);
119 this.streams.sort(new Comparator<Short>()
120 {
121
122 @Override
123 public int compare(Short o1, Short o2)
124 {
125 return o1 - o2;
126 }
127 });
128
129
130
131
132
133
134
135
136
137 for (short stream = 1; stream <= 12; stream += 3)
138 {
139 int quadrant = (stream - 1) / 3;
140 this.routes.put(stream, rotateRoute(quadrant, assembleRoute(
141 new RouteStep(-BOUNDARY, CAR_RIGHT),
142 new RouteStep(-SHOULDER, CAR_RIGHT,Command.STOP_LINE_AND_ICON),
143 new RouteStep(-CAR_CENTER, CAR_RIGHT),
144 new RouteStep(-CAR_CENTER, BOUNDARY))));
145 this.routes.put((short) (stream + 1), rotateRoute(quadrant, assembleRoute(
146 new RouteStep(-BOUNDARY, CAR_CENTER),
147 new RouteStep(-SHOULDER, CAR_CENTER, Command.STOP_LINE_AND_ICON),
148 new RouteStep(Command.IF, stream + 1 + 60),
149 new RouteStep(-CAR_ROUNDABOUT_LEFT, CAR_CENTER),
150 new RouteStep(Command.ELSE),
151 new RouteStep(BOUNDARY, CAR_CENTER),
152 new RouteStep(Command.END_IF))));
153 this.routes.put((short) (stream + 2), rotateRoute(quadrant, assembleRoute(
154 new RouteStep(-BOUNDARY, CAR_LEFT),
155 new RouteStep(-SHOULDER, CAR_LEFT, Command.STOP_LINE_AND_ICON),
156 new RouteStep(Command.IF, stream + 2 + 60),
157 new RouteStep(-CAR_ROUNDABOUT_LEFT, CAR_LEFT),
158 new RouteStep(Command.ELSE_IF, (stream + 10) % 12 + 60),
159 new RouteStep(CAR_CENTER, CAR_LEFT),
160 new RouteStep(CAR_CENTER, CAR_ROUNDABOUT_LEFT),
161 new RouteStep(Command.ELSE),
162 new RouteStep(-CAR_LEFT, CAR_LEFT),
163 new RouteStep(-CAR_LEFT, PT_DIV_L),
164 new RouteStep(-CAR_ROUNDABOUT_LEFT, PT_DIV_L),
165 new RouteStep(-CAR_ROUNDABOUT_LEFT, -CAR_LEFT),
166 new RouteStep(PT_DIV_L, -CAR_LEFT),
167 new RouteStep(PT_DIV_L, -CAR_CENTER),
168 new RouteStep(CAR_CENTER, -CAR_CENTER),
169 new RouteStep(CAR_CENTER, -BOUNDARY),
170 new RouteStep(Command.END_IF))));
171 }
172
173 for (short stream = 21; stream <= 28; stream += 2)
174 {
175 int quadrant = (stream - 19) / 2 % 4;
176 this.routes.put(stream, rotateRoute(quadrant, assembleRoute(
177 new RouteStep(DIVIDER_1, BICYCLE, Command.ICON),
178 new RouteStep(SHOULDER, BICYCLE),
179 new RouteStep(BOUNDARY, BICYCLE, Command.ICON))));
180 this.routes.put((short) (stream + 1), rotateRoute(quadrant, assembleRoute(
181 new RouteStep(-BOUNDARY, BICYCLE),
182 new RouteStep(-DIVIDER_3, BICYCLE, Command.ICON),
183 new RouteStep(Command.IF, stream),
184 new RouteStep(-DIVIDER_1, BICYCLE, Command.ICON),
185 new RouteStep(Command.ELSE),
186 new RouteStep(SHOULDER, BICYCLE),
187 new RouteStep(BOUNDARY, BICYCLE, Command.ICON),
188 new RouteStep(Command.END_IF))));
189 }
190
191 for (short stream = 31; stream <= 38; stream += 2)
192 {
193 int quadrant = (stream - 29) / 2 % 4;
194 this.routes.put(stream, rotateRoute(quadrant, assembleRoute(
195 new RouteStep(DIVIDER_1, SIDEWALK),
196 new RouteStep(BOUNDARY, SIDEWALK))));
197 this.routes.put((short) (stream + 1), rotateRoute(quadrant, assembleRoute(
198 new RouteStep(-BOUNDARY, SIDEWALK),
199 new RouteStep(Command.IF, stream),
200 new RouteStep(-DIVIDER_1, SIDEWALK),
201 new RouteStep(Command.ELSE),
202 new RouteStep(BOUNDARY, SIDEWALK),
203 new RouteStep(Command.END_IF))));
204 }
205
206 for (short stream = 41; stream <= 52; stream += 3)
207 {
208 int quadrant = (stream - 41) / 3;
209 this.routes.put(stream, rotateRoute(quadrant, assembleRoute(
210 new RouteStep(-BOUNDARY, PT_DIV_L),
211 new RouteStep(-SHOULDER, PT_DIV_L, Command.STOP_LINE),
212 new RouteStep(-PT_SIDEWALK_SHOULDER, PT_DIV_L, Command.ICON),
213 new RouteStep(-CAR_RIGHT, PT_DIV_L),
214 new RouteStep(-CAR_RIGHT, CAR_LEFT),
215 new RouteStep(-PT_DIV_L, CAR_LEFT),
216 new RouteStep(-PT_DIV_L, SHOULDER),
217 new RouteStep(-PT_DIV_L, BOUNDARY, Command.ICON))));
218 this.routes.put((short) (stream + 1), rotateRoute(quadrant, assembleRoute(
219 new RouteStep(-BOUNDARY, PT_DIV_L),
220 new RouteStep(-SHOULDER, PT_DIV_L, Command.STOP_LINE),
221 new RouteStep(-PT_SIDEWALK_SHOULDER, PT_DIV_L, Command.ICON),
222 new RouteStep(SHOULDER, PT_DIV_L),
223 new RouteStep(BOUNDARY, PT_DIV_L))));
224 this.routes.put((short) (stream + 2), rotateRoute(quadrant, assembleRoute(
225 new RouteStep(-BOUNDARY, PT_DIV_L),
226 new RouteStep(-SHOULDER, PT_DIV_L, Command.STOP_LINE),
227 new RouteStep(-PT_SIDEWALK_SHOULDER, PT_DIV_L, Command.ICON),
228 new RouteStep(-CAR_RIGHT, PT_DIV_L),
229 new RouteStep(-CAR_RIGHT, CAR_ROUNDABOUT_LEFT),
230 new RouteStep(-PT_DIV_L, CAR_ROUNDABOUT_LEFT),
231 new RouteStep(Command.IF, (stream + 2 - 40) % 12 + 60),
232 new RouteStep(-PT_DIV_L, -PT_DIV_L),
233 new RouteStep(PT_DIV_L, -PT_DIV_L),
234 new RouteStep(Command.ELSE),
235 new RouteStep(-PT_DIV_L, -CAR_CENTER),
236 new RouteStep(CAR_ROUNDABOUT_LEFT, -CAR_CENTER),
237 new RouteStep(CAR_ROUNDABOUT_LEFT, -CAR_RIGHT),
238 new RouteStep(PT_DIV_L, -CAR_RIGHT),
239 new RouteStep(Command.END_IF),
240 new RouteStep(PT_DIV_L, -SHOULDER),
241 new RouteStep(PT_DIV_L, -BOUNDARY, Command.ICON))));
242 }
243
244 for (short stream = 62; stream <= 72; stream += 3)
245 {
246 int quadrant = (stream - 61) / 3;
247 this.routes.put(stream, rotateRoute(quadrant, assembleRoute(
248 new RouteStep(-CAR_ROUNDABOUT_LEFT, CAR_CENTER),
249 new RouteStep(CAR_ROUNDABOUT_LEFT, CAR_CENTER, Command.STOP_LINE_AND_ICON),
250 new RouteStep(BOUNDARY, CAR_CENTER))));
251 this.routes.put((short) (stream + 1), rotateRoute(quadrant, assembleRoute(
252 new RouteStep(-CAR_ROUNDABOUT_LEFT, CAR_LEFT),
253 new RouteStep(CAR_ROUNDABOUT_LEFT, CAR_LEFT, Command.STOP_LINE_AND_ICON),
254 new RouteStep(CAR_CENTER, CAR_LEFT),
255 new RouteStep(Command.IF, ((stream - 61) + 11) % 12 + 60),
256 new RouteStep(CAR_CENTER, CAR_ROUNDABOUT_LEFT),
257 new RouteStep(Command.ELSE),
258 new RouteStep(CAR_CENTER, -BOUNDARY),
259 new RouteStep(Command.END_IF))));
260 }
261
262 }
263
264
265
266
267
268
269 private boolean streamExists(final short stream)
270 {
271 return this.streams.contains(stream);
272 }
273
274
275
276
277
278
279 public final static boolean isGrass(final int i)
280 {
281 return i == DIVIDER_1 || i == DIVIDER_2 || i == DIVIDER_3 || i == DIVIDER_4 || i == DIVIDER_5 || i == DIVIDER_6
282 || i == DIVIDER_7 || i == SHOULDER;
283 }
284
285
286
287
288
289
290 final LaneType laneType(final int streamNumber)
291 {
292 if (streamNumber < 20 || streamNumber > 60 && streamNumber <= 80)
293 {
294 return LaneType.CAR_LANE;
295 }
296 if (streamNumber >= 20 && streamNumber < 30)
297 {
298 return LaneType.BICYCLE_LANE;
299 }
300 if (streamNumber >= 30 && streamNumber < 40)
301 {
302 return LaneType.PEDESTRIAN_LANE;
303 }
304 if (streamNumber > 40 && streamNumber <= 52 || streamNumber >= 81 && streamNumber <= 92)
305 {
306 return LaneType.PUBLIC_TRANSIT_LANE;
307 }
308 return null;
309 }
310
311
312
313
314 enum LaneType
315 {
316
317 CAR_LANE,
318
319 BICYCLE_LANE,
320
321 PUBLIC_TRANSIT_LANE,
322
323 PEDESTRIAN_LANE,
324 }
325
326
327
328
329
330
331
332 final int rotatedX(final XYPair xyPair, final int rotation)
333 {
334 switch (rotation % 4)
335 {
336 case 0:
337 return xyPair.getX();
338 case 1:
339 return -xyPair.getY();
340 case 2:
341 return -xyPair.getX();
342 case 3:
343 return xyPair.getY();
344 }
345 return 0;
346 }
347
348
349
350
351
352
353
354 final int rotatedY(final XYPair xyPair, final int rotation)
355 {
356 switch (rotation % 4)
357 {
358 case 0:
359 return xyPair.getY();
360 case 1:
361 return xyPair.getX();
362 case 2:
363 return -xyPair.getY();
364 case 3:
365 return -xyPair.getX();
366 }
367 return 0;
368 }
369
370
371
372
373 enum Command
374 {
375
376 NO_OP,
377
378 IF,
379
380 ELSE,
381
382 ELSE_IF,
383
384 END_IF,
385
386 STOP_LINE,
387
388 ICON,
389
390 STOP_LINE_AND_ICON,
391 }
392
393
394
395
396 class RouteStep
397 {
398
399 final private int x;
400
401
402 final private int y;
403
404
405 final private Command command;
406
407
408 final private int streamCondition;
409
410
411
412
413
414
415 public RouteStep(final int x, final int y)
416 {
417 this.x = x;
418 this.y = y;
419 this.command = Command.NO_OP;
420 this.streamCondition = TrafficController.NO_STREAM;
421 }
422
423
424
425
426
427
428
429
430
431 public RouteStep(final int x, final int y, final Command command) throws TrafficLightException
432 {
433 Throw.when(Command.STOP_LINE != command && Command.NO_OP != command && Command.ICON != command
434 && Command.STOP_LINE_AND_ICON != command, TrafficLightException.class,
435 "X and Y should only be provided with a NO_OP, STOP_LINE, ICON, or STOP_LINE_AND_ICON command; not with "
436 + command);
437 this.x = x;
438 this.y = y;
439 this.command = command;
440 this.streamCondition = TrafficController.NO_STREAM;
441 }
442
443
444
445
446
447
448
449
450 public RouteStep(final Command command, final int streamCondition) throws TrafficLightException
451 {
452 Throw.when(Command.IF != command && Command.ELSE_IF != command, TrafficLightException.class,
453 "RouteStep constructor with stream condition must use command IF or ELSE_IF");
454 this.x = TrafficController.NO_STREAM;
455 this.y = TrafficController.NO_STREAM;
456 this.command = command;
457 Throw.when(streamCondition == TrafficController.NO_STREAM, TrafficLightException.class,
458 "IF or ELSE_IF need a valid traffic stream number");
459 this.streamCondition = streamCondition;
460 }
461
462
463
464
465
466
467 public RouteStep(final Command command) throws TrafficLightException
468 {
469 Throw.when(Command.ELSE != command && Command.END_IF != command, TrafficLightException.class,
470 "RouteStep constructor with single command parameter requires ELSE or END_IF command");
471 this.x = TrafficController.NO_STREAM;
472 this.y = TrafficController.NO_STREAM;
473 this.command = command;
474 this.streamCondition = TrafficController.NO_STREAM;
475 }
476
477
478
479
480
481 public int getX()
482 {
483 return this.x;
484 }
485
486
487
488
489
490 public int getY()
491 {
492 return this.y;
493 }
494
495
496
497
498
499 public Command getCommand()
500 {
501 return this.command;
502 }
503
504
505
506
507
508 public int getStreamCondition()
509 {
510 return this.streamCondition;
511 }
512
513
514 @Override
515 public String toString()
516 {
517 return "RouteStep [x=" + this.x + ", y=" + this.y + ", command=" + this.command + ", streamCondition="
518 + this.streamCondition + "]";
519 }
520
521 }
522
523
524
525
526 class XYPair
527 {
528
529 private final int x;
530
531
532 private final int y;
533
534
535
536
537
538
539 public XYPair(final int x, final int y)
540 {
541 this.x = x;
542 this.y = y;
543 }
544
545
546
547
548
549 public XYPair(final RouteStep routeStep)
550 {
551 this.x = routeStep.getX();
552 this.y = routeStep.getY();
553 }
554
555
556
557
558
559
560 public XYPair(final XYPair in, final int quadrant)
561 {
562 this.x = rotatedX(in, quadrant);
563 this.y = rotatedY(in, quadrant);
564 }
565
566
567
568
569
570 public int getX()
571 {
572 return this.x;
573 }
574
575
576
577
578
579 public int getY()
580 {
581 return this.y;
582 }
583
584
585 @Override
586 public String toString()
587 {
588 return "XYPair [x=" + this.x + ", y=" + this.y + "]";
589 }
590
591 }
592
593
594
595
596
597
598
599
600 private XYPair[] rotateRoute(final int quadrant, final RouteStep... steps) throws TrafficLightException
601 {
602 List<XYPair> route = new ArrayList<>();
603 boolean on = true;
604
605 for (RouteStep step : steps)
606 {
607 switch (step.getCommand())
608 {
609 case NO_OP:
610 case STOP_LINE:
611 case ICON:
612 case STOP_LINE_AND_ICON:
613 if (on)
614 {
615 route.add(new XYPair(new XYPair(step), quadrant));
616 }
617 break;
618
619 default:
620 throw new TrafficLightException("Bad command in rotateRoute: " + step.getCommand());
621
622 }
623 }
624 return route.toArray(new XYPair[route.size()]);
625 }
626
627
628
629
630
631
632
633 private RouteStep[] assembleRoute(RouteStep... steps) throws TrafficLightException
634 {
635 List<RouteStep> result = new ArrayList<>();
636 RouteStep step;
637 for (int pointNo = 0; null != (step = routePoint(pointNo, steps)); pointNo++)
638 {
639 result.add(step);
640 }
641 return result.toArray(new RouteStep[result.size()]);
642 }
643
644
645
646
647
648
649
650
651 private RouteStep routePoint(final int pointNo, final RouteStep... steps) throws TrafficLightException
652 {
653 boolean active = true;
654 boolean beenActive = false;
655 int index = 0;
656
657 for (RouteStep routeStep : steps)
658 {
659 switch (routeStep.getCommand())
660 {
661 case NO_OP:
662 case STOP_LINE:
663 case ICON:
664 case STOP_LINE_AND_ICON:
665 if (active)
666 {
667 if (index++ == pointNo)
668 {
669 return routeStep;
670 }
671 }
672 break;
673
674 case IF:
675 active = streamExists((short) routeStep.getStreamCondition());
676 beenActive = active;
677 break;
678
679 case ELSE_IF:
680 if (active)
681 {
682 active = false;
683 }
684 else if (!beenActive)
685 {
686 active = this.streams.contains(routeStep.getStreamCondition());
687 }
688 if (active)
689 {
690 beenActive = true;
691 }
692 break;
693
694 case ELSE:
695 active = !beenActive;
696 break;
697
698 case END_IF:
699 active = true;
700 break;
701
702 default:
703 throw new TrafficLightException("Bad switch: " + routeStep);
704
705 }
706 }
707 return null;
708 }
709
710
711
712
713
714 public BufferedImage render()
715 {
716 int range = 2 * BOUNDARY + 1;
717 int cellSize = 10;
718 BufferedImage result = new BufferedImage(range * cellSize, range * cellSize, BufferedImage.TYPE_INT_RGB);
719 Graphics2D graphics = (Graphics2D) result.getGraphics();
720 graphics.setColor(Color.GREEN);
721 graphics.fillRect(0, 0, result.getWidth(), result.getHeight());
722 for (Short stream : this.streams)
723 {
724 switch (laneType(stream))
725 {
726 case BICYCLE_LANE:
727 graphics.setColor(Color.RED);
728 break;
729
730 case CAR_LANE:
731 graphics.setColor(Color.BLACK);
732 break;
733
734 case PEDESTRIAN_LANE:
735 graphics.setColor(Color.BLUE);
736 break;
737
738 case PUBLIC_TRANSIT_LANE:
739 graphics.setColor(Color.BLACK);
740 break;
741
742 default:
743 graphics.setColor(Color.WHITE);
744 break;
745
746 }
747 XYPair[] path = this.routes.get(stream);
748 if (null == path)
749 {
750 System.err.println("Cannot find path for stream " + stream);
751 continue;
752 }
753 XYPair prevPair = null;
754 for (XYPair xyPair : path)
755 {
756 if (null != prevPair)
757 {
758 int dx = (int) Math.signum(xyPair.getX() - prevPair.getX());
759 int dy = (int) Math.signum(xyPair.getY() - prevPair.getY());
760 int x = prevPair.getX() + dx;
761 int y = prevPair.getY() + dy;
762 while (x != xyPair.getX() || y != xyPair.getY())
763 {
764 fillXYPair(graphics, new XYPair(x, y));
765 if (x != xyPair.getX())
766 {
767 x += dx;
768 }
769 if (y != xyPair.getY())
770 {
771 y += dy;
772 }
773 }
774
775 }
776 fillXYPair(graphics, xyPair);
777 prevPair = xyPair;
778 }
779 }
780 return result;
781 }
782
783
784
785
786
787
788 private void fillXYPair(final Graphics2D graphics, final XYPair xyPair)
789 {
790 int cellSize = 10;
791 graphics.fillRect(cellSize * (BOUNDARY - xyPair.getX()), cellSize * (BOUNDARY - xyPair.getY()), cellSize, cellSize);
792 }
793
794
795
796
797
798 public static void main(final String[] args)
799 {
800 SwingUtilities.invokeLater(new Runnable()
801 {
802 @Override
803 public void run()
804 {
805 JFrame frame = new JFrame("Diagram test");
806 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
807 frame.setMinimumSize(new Dimension(1000, 1000));
808 JPanel mainPanel = new JPanel(new BorderLayout());
809 frame.add(mainPanel);
810 checkBoxPanel = new JPanel();
811 checkBoxPanel.setLayout(new BoxLayout(checkBoxPanel, BoxLayout.Y_AXIS));
812 JScrollPane scrollPane = new JScrollPane(checkBoxPanel);
813 scrollPane.setPreferredSize(new Dimension(150, 1000));
814 mainPanel.add(scrollPane, BorderLayout.LINE_START);
815 for (int stream = 1; stream <= 12; stream++)
816 {
817 checkBoxPanel.add(makeCheckBox(stream, stream % 3 == 2));
818 }
819 for (int stream = 21; stream <= 28; stream++)
820 {
821 checkBoxPanel.add(makeCheckBox(stream, false));
822 }
823 for (int stream = 31; stream <= 38; stream++)
824 {
825 checkBoxPanel.add(makeCheckBox(stream, false));
826 }
827 for (int stream = 41; stream <= 52; stream++)
828 {
829 checkBoxPanel.add(makeCheckBox(stream, false));
830 }
831 for (int stream = 61; stream <= 72; stream++)
832 {
833 if (stream % 3 == 1)
834 {
835 continue;
836 }
837 checkBoxPanel.add(makeCheckBox(stream, false));
838 }
839 testPanel = new JPanel();
840 rebuildTestPanel();
841 mainPanel.add(testPanel, BorderLayout.CENTER);
842 frame.setVisible(true);
843 }
844 });
845
846 }
847
848
849
850
851
852
853
854 public static JCheckBox makeCheckBox(final int stream, final boolean initialState)
855 {
856 JCheckBox result = new JCheckBox(String.format("Stream %02d", stream));
857 result.setSelected(initialState);
858 result.addActionListener(new ActionListener()
859 {
860
861 @Override
862 public void actionPerformed(ActionEvent e)
863 {
864 rebuildTestPanel();
865 }
866 });
867 return result;
868 }
869
870
871 static JPanel testPanel = null;
872
873
874 static JPanel checkBoxPanel = null;
875
876
877
878
879 static void rebuildTestPanel()
880 {
881 testPanel.removeAll();
882 Set<Short> streamList = new HashSet<>();
883 for (Component c : checkBoxPanel.getComponents())
884 {
885 if (c instanceof JCheckBox)
886 {
887 JCheckBox checkBox = (JCheckBox) c;
888 if (checkBox.isSelected())
889 {
890 String caption = checkBox.getText();
891 String streamText = caption.substring(caption.length() - 2);
892 Short stream = Short.parseShort(streamText);
893 streamList.add(stream);
894 }
895 }
896 }
897 try
898 {
899 Diagram diagram = new Diagram(streamList);
900 testPanel.add(new JLabel(new ImageIcon(diagram.render())));
901 }
902 catch (TrafficLightException exception)
903 {
904 exception.printStackTrace();
905 }
906 testPanel.repaint();
907 testPanel.revalidate();
908 }
909
910 }