001package myproject.model.swing;
002
003import java.awt.Color;
004import java.awt.Graphics;
005import java.util.ArrayList;
006import java.util.List;
007import myproject.model.AnimatorBuilder;
008import myproject.model.Car;
009import myproject.model.Light;
010import myproject.model.MP;
011import myproject.model.Road;
012import myproject.util.Animator;
013import myproject.util.SwingAnimator;
014import myproject.util.SwingAnimatorPainter;
015
016/**
017 * A class for building Animators.
018 */
019public class SwingAnimatorBuilder implements AnimatorBuilder {
020        MyPainter painter;
021        public SwingAnimatorBuilder() {
022                painter = new MyPainter();
023        }
024        public Animator getAnimator() {
025                if (painter == null) { throw new IllegalStateException(); }
026                Animator returnValue = new SwingAnimator(painter, "Traffic Simulator",
027                                VP.displayWidth, VP.displayHeight, VP.displayDelay);
028                painter = null;
029                return returnValue;
030        }
031        private static double skipInit = VP.gap;
032        private static double skipRoad = VP.gap + MP.roadLength;
033        private static double skipCar = VP.gap + VP.elementWidth;
034        private static double skipRoadCar = skipRoad + skipCar;
035        public void addLight(Light d, int i, int j) {
036                double x = skipInit + skipRoad + j*skipRoadCar;
037                double y = skipInit + skipRoad + i*skipRoadCar;
038                Translator t = new TranslatorWE(x, y, MP.carLength, VP.elementWidth, VP.scaleFactor);
039                painter.addLight(d,t);
040        }
041        public void addHorizontalRoad(Road l, int i, int j, boolean eastToWest) {
042                double x = skipInit + j*skipRoadCar;
043                double y = skipInit + skipRoad + i*skipRoadCar;
044                Translator t = eastToWest ? new TranslatorEW(x, y, MP.roadLength, VP.elementWidth, VP.scaleFactor)
045                                : new TranslatorWE(x, y, MP.roadLength, VP.elementWidth, VP.scaleFactor);
046                painter.addRoad(l,t);
047        }
048        public void addVerticalRoad(Road l, int i, int j, boolean southToNorth) {
049                double x = skipInit + skipRoad + j*skipRoadCar;
050                double y = skipInit + i*skipRoadCar;
051                Translator t = southToNorth ? new TranslatorSN(x, y, MP.roadLength, VP.elementWidth, VP.scaleFactor)
052                                : new TranslatorNS(x, y, MP.roadLength, VP.elementWidth, VP.scaleFactor);
053                painter.addRoad(l,t);
054        }
055
056
057        /** Class for drawing the Model. */
058        private static class MyPainter implements SwingAnimatorPainter {
059
060                /** Pair of a model element <code>x</code> and a translator <code>t</code>. */
061                private static class Element<T> {
062                        T x;
063                        Translator t;
064                        Element(T x, Translator t) {
065                                this.x = x;
066                                this.t = t;
067                        }
068                }
069
070                private List<Element<Road>> roadElements;
071                private List<Element<Light>> lightElements;
072                MyPainter() {
073                        roadElements = new ArrayList<Element<Road>>();
074                        lightElements = new ArrayList<Element<Light>>();
075                }
076                void addLight(Light x, Translator t) {
077                        lightElements.add(new Element<Light>(x,t));
078                }
079                void addRoad(Road x, Translator t) {
080                        roadElements.add(new Element<Road>(x,t));
081                }
082
083                public void paint(Graphics g) {
084                        // This method is called by the swing thread, so may be called
085                        // at any time during execution...
086
087                        // First draw the background elements
088                        for (Element<Light> e : lightElements) {
089                                if (e.x.getState()) {
090                                        g.setColor(Color.BLUE);
091                                } else {
092                                        g.setColor(Color.YELLOW);
093                                }
094                                XGraphics.fillOval(g, e.t, 0, 0, MP.carLength, VP.elementWidth);
095                        }
096                        g.setColor(Color.BLACK);
097                        for (Element<Road> e : roadElements) {
098                                XGraphics.fillRect(g, e.t, 0, 0, MP.roadLength, VP.elementWidth);
099                        }
100
101                        // Then draw the foreground elements
102                        for (Element<Road> e : roadElements) {
103                                // iterate through a copy because e.x.getCars() may change during iteration...
104                                for (Car d : e.x.getCars().toArray(new Car[0])) {
105                                        g.setColor(d.getColor());
106                                        XGraphics.fillOval(g, e.t, d.getPosition(), 0, MP.carLength, VP.elementWidth);
107                                }
108                        }
109                }
110        }
111}
112