OOP2

ClockAnalogView.java

1
import java.awt.Color;
2
import java.awt.Dimension;
3
import java.awt.Graphics;
4
import java.awt.Graphics2D;
5
import java.awt.RenderingHints;
6
import java.awt.geom.AffineTransform;
7
import java.awt.geom.Ellipse2D;
8
import java.awt.geom.GeneralPath;
9
import java.util.Calendar;
10
import java.util.Observable;
11
import javax.swing.JComponent;
12
13
/**
14
 * An analog clock View for the ClockModel. This View has no user inputs, so
15
 * no controller is required. This class implements the View interface, and
16
 * subclasses JComponent directly, to illustrate that not all Views need to
17
 * inherit from AbstractView.
18
 *
19
 * Note: it is not necessary to understand all the details of the rendering 
20
 * of the analog clock.
21
 *
22
 * @author jvermeulen (inspired by IBM Java2D tutorial)
23
 */
24
public class ClockAnalogView extends JComponent implements View {
25
26
    private Observable mModel;
27
    private Controller mController;
28
29
    int mHour;
30
    int mMinute;
31
    int mSecond;
32
33
    ClockAnalogView(Observable model, Controller controller) {
34
        mModel = model;
35
        mController = controller;
36
    }
37
38
    @Override
39
    public void setController(Controller controller) {
40
        mController = controller;
41
    }
42
43
    @Override
44
    public Controller getController() {
45
        return mController;
46
    }
47
48
    @Override
49
    public void setModel(Observable model) {
50
        mModel = model;
51
    }
52
53
    @Override
54
    public Observable getModel() {
55
        return mModel;
56
    }
57
58
    @Override
59
    public Controller defaultController(Observable model) {
60
        return null;
61
    }
62
63
    @Override
64
    public void update(Observable o, Object info) {
65
        // Cast info to ClockUpdate type.
66
        ClockUpdate clockInfo = (ClockUpdate) info;
67
68
        // Store hour, minute, second for repainting.
69
        mHour = clockInfo.getHour()+5; // +5 Geeft een latere tijdzone weer. Dit is namelijk opdracht 3.
70
        mMinute = clockInfo.getMinute();
71
        mSecond = clockInfo.getSecond();
72
73
        // Using a little trigonometry, set the transforms to rotate
74
        // each hand into the proper position.  Center the rotation
75
        // around the pivot point (50, 50) instead of the origin
76
        hourTransform.setToRotation(((double) mHour) *
77
                                            (Math.PI / 6.0), 50, 50);
78
        minuteTransform.setToRotation(((double) mMinute) *
79
                                            (Math.PI / 30.0), 50, 50);
80
        secondTransform.setToRotation(((double) mSecond) *
81
                                            (Math.PI / 30.0), 50, 50);
82
83
        repaint();
84
    }
85
86
87
    /**
88
     * Sets this components preferred size to 150x150.
89
     * @return
90
     */
91
    @Override
92
    public Dimension getPreferredSize() {
93
        return new Dimension(100, 100);
94
    }
95
96
    // Create a shape for the face of the clock
97
    protected static Ellipse2D face = new Ellipse2D.Float(3, 3, 94, 94);
98
99
    // Create a path that represents a tick mark
100
    protected static GeneralPath tick = new GeneralPath();
101
    static // http://www.jusfortechies.com/java/core-java/static-blocks.php
102
    {
103
        tick.moveTo(100, 100);
104
        tick.moveTo(49, 0);
105
        tick.lineTo(51, 0);
106
        tick.lineTo(51, 6);
107
        tick.lineTo(49, 6);
108
        tick.lineTo(49, 0);
109
    }
110
111
    // Create a cool hour hand
112
    protected static GeneralPath hourHand = new GeneralPath();
113
    static
114
    {
115
        hourHand.moveTo(50, 15);
116
        hourHand.lineTo(53, 50);
117
        hourHand.lineTo(50, 53);
118
        hourHand.lineTo(47, 50);
119
        hourHand.lineTo(50, 15);
120
    }
121
122
    // Create a cool minute hand
123
    protected static GeneralPath minuteHand = new GeneralPath();
124
    static
125
    {
126
        minuteHand.moveTo(50, 2);
127
        minuteHand.lineTo(53, 50);
128
        minuteHand.lineTo(50, 58);
129
        minuteHand.lineTo(47, 50);
130
        minuteHand.lineTo(50, 2);
131
    }
132
133
    // And a cool second hand
134
    protected static GeneralPath secondHand = new GeneralPath();
135
    static
136
    {
137
        secondHand.moveTo(49, 5);
138
        secondHand.lineTo(51, 5);
139
        secondHand.lineTo(51, 62);
140
        secondHand.lineTo(49, 62);
141
        secondHand.lineTo(49, 5);
142
    }
143
144
    // Create some colors for the pieces of the clock
145
    protected static Color faceColor = new Color(220, 220, 220);
146
    protected static Color hourColor = Color.red.darker();
147
    protected static Color minuteColor = Color.blue.darker();
148
    protected static Color secondColor = new Color(180, 180, 0);
149
    protected static Color pinColor = Color.gray.brighter();
150
151
    // Create circles for the pivot and center pin
152
    protected Ellipse2D pivot = new Ellipse2D.Float(47, 47, 6, 6);
153
    protected Ellipse2D centerPin = new Ellipse2D.Float(49, 49, 2, 2);
154
155
156
    // Create three transforms that center around the pivot point
157
    protected AffineTransform hourTransform =
158
                    AffineTransform.getRotateInstance(0, 50, 50);
159
    protected AffineTransform minuteTransform =
160
                    AffineTransform.getRotateInstance(0, 50, 50);
161
    protected AffineTransform secondTransform =
162
                    AffineTransform.getRotateInstance(0, 50, 50);
163
164
    // Create a timer that fires once a second and a Calendar
165
    // instance for getting the time values
166
    // protected Timer timer = new Timer(1000, this);
167
    protected Calendar calendar = Calendar.getInstance();
168
169
    // This is an alternative to creating a UI delegate.  Since JPanel's
170
    // paint() method only paints the border and backgound, we can just
171
    // override the paint method of the component to do the graphics.
172
    public void paint(Graphics g)
173
    {
174
        // Call the superclass first to paint the border (if one is assigned)
175
        super.paint(g);
176
177
178
        // Get the graphics context and turn on anti-aliasing
179
        Graphics2D g2 = (Graphics2D) g;
180
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
181
                            RenderingHints.VALUE_ANTIALIAS_ON);
182
183
        // Set the paint for the clock face and fill it in
184
        g2.setPaint(faceColor);
185
        g2.fill(face);
186
187
        // Set the paint to black and draw the clock's outline
188
        g2.setPaint(Color.black);
189
        g2.draw(face);
190
191
        // Fill in the 12 ticks around the face of the clock
192
        for (double p = 0.0; p < 12.0; p += 1.0)
193
        {
194
            // This is probably terribly inefficient and should be
195
            // done statically or in the constructor - draw the
196
            // tick as a transformed shape that is rotated.
197
            g2.fill(tick.createTransformedShape(
198
                AffineTransform.getRotateInstance((Math.PI / 6.0)  * p,
199
                        50, 50)));
200
        }
201
202
        // Set the paint and draw the hour hand.  It is lowest in the
203
        // 'z-order' so will appear underneath the other hands.  Notice
204
        // how each hand is transformed by a different <AffineTransform>.
205
        g2.setPaint(hourColor);
206
        g2.fill(hourHand.createTransformedShape(hourTransform));
207
208
        // Set the paint and draw the minute hand, the second hand,
209
        // the pivot and the center pin
210
        g2.setPaint(minuteColor);
211
        g2.fill(minuteHand.createTransformedShape(minuteTransform));
212
        g2.setPaint(secondColor);
213
        g2.fill(secondHand.createTransformedShape(secondTransform));
214
        g2.fill(pivot);
215
        g2.setPaint(pinColor);
216
        g2.fill(centerPin);
217
    }
218
}
219