Step 2: The Size Fields

Before we draw anything, we need to know the sizes of the clock face and hands. Because the applet's size isn't fixed (it can be adjusted by the person designing the Web page), we can't just hardcode all the coordinates. Instead, we need to calculate the sizes during initialization.

In the previous step, we already defined two size fields, size and halfSize. Remember that size is the smaller of the width and height of the applet. Also, halfSize is equal to (size / 2). The purpose of halfSize is to define the center of the applet. If the applet is square, the coordinates (halfSize, halfSize) will be right at the center. If the applet is not square, though, the clock will be aligned to the left, like this:

So, (halfSize, halfSize) will still be at the center of the clock. We'll be making use of this fact extensively later on, when we draw the clock face.

Now, let's move on to the other size fields. Make the following changes to ClockApplet.java (note the comma in the first line):

private int size, halfSize, // Size of the applet
	tickRadius, tickSize,   // tickSize = tickRadius * 2
	hourHSize,              // Length of the hour hand
	minHSize,               // Length of the minute hand
	secHSize;               // Length of the second hand
private Color backColor, tickColor, hrHColor, minHColor, secHColor;

private boolean drawSmallTicks;

The tickSize integer field holds the size of the five-minute-interval "tick" marks on the clock, and tickRadius is half that. The other three fields for the clock hands are self-explanatory.

We also declare a variable of type boolean called drawSmallTicks. This "flag" will determine whether or not we draw the one-minute-interval tick marks. If the applet is too small, we set it to false ("don't draw them") so the clock won't be too crammed. Otherwise, it will be true. This is done in the new init() method, shown below:

public void init() {
	Dimension bounds = size(); // Find the size of the largest square
	size = bounds.width >= bounds.height ? bounds.height : bounds.width;
	halfSize = size / 2;
	drawSmallTicks = (size >= 100); // Don't draw small ticks if too little

	// Initialize sizes
	tickRadius = size / 50;
	tickSize = tickRadius * 2;
	if(tickSize < 1) tickSize = 1;

	hourHSize = halfSize / 2;
	minHSize = halfSize - tickSize * 3;
	secHSize = halfSize - tickSize * 2;

	// Initialize colors
	backColor = initColor("bgcolor", getBackground());
	setBackground(backColor);

	tickColor = initColor("tickcolor", new Color(0, 0x80, 0x80));
	hrHColor = initColor("hrcolor", tickColor);
	minHColor = initColor("mincolor", tickColor);
	secHColor = initColor("seccolor", Color.black);

	createFace();
	faceBuffer = createImage(size, size);
}

init in Detail

Let's dissect the additions to init() line by line, starting where our discussion just left off:

drawSmallTicks = (size >= 100); // Don't draw small ticks if too little

The >= operator compares our size field to 100. If size is at least 100, the operator evaluates to true, and if not, false. We then assign this result to drawSmallTicks.

Next come the statements that set the size fields. The numbers used are really quite arbitrary—the results look good at different applet sizes, in my opinion. Note that we make sure tickSize has a minimum value of 1:

if(tickSize < 1) tickSize = 1;

The last modification is a call to the new createFace() method, which draws the clock face without the hands. Before we get to that though, we're going to meet our dear math and trig functions, in the next step.


1