Brian's Superbly Incredible, Amazingly Functional Readme October 2001 For Program 4 I designed Brian's Superbly Incredible, Amazingly Functional Clock. This clock has many classes, which are described briefly below. More documentation can be found within the classes themselves. -=-=- AnalogClock AnalogClock is the class that the nice square analog clock comes from. It is derived from Clock, and is comprised of an AnalogClockFace and a HandGroup. By deriving it from Clock, I was able to make an array of Clock objects that I could cycle through to show my various clocks. AnalogClockFace This class is the face of an AnalogClock; that is, the rounded rectangular frame and the twelve dots marking off the hours. It is combined with a HandGroup to form an AnalogClock. Clock This abstract class is used to define a common set of methods that every Clock can perform. I found it easiest to cycle through my various clocks by making them all derive from a single abstract class, which I called Clock. Incidentally, Clock derives from AView. Digit Six Digits are placed on a DigitalClockDisplay to display the current time on my handsome clock radio thing. This class extends AView. DigitalClock A DigitalClock, which derives from Clock, displays a DigitalClockDisplay upon a DigitalClockFace to make a very nifty bedside alarm radio thing. DigitalClockDisplay Objects of this class, which extends AView, are placed on a DigitalClockFace to make a DigitalClock. A DigitalClockDisplay is basically an AView with six Digits on it. DigitalClockFace A DigitalClockFace is what makes a DigitalClock look like a DigitalClock. Without this DigitalClockFace, a DigitalClock would just look like some numbers on the screen. Bleah. Director The Director class is the main class where all my generally cool stuff is. All my specifically cool stuff, on the other hand, is in the other classes. Director just ties it all together. Coincidentally, Director is also the window that everything is placed upon. It also implements Serializable and Runnable, for reasons closely tied in with IncredibleTask. See my ramblings toward the bottom for more detailed analysis. Hand The Hand class, one of the most amazingly awesome classes ever written (perhaps), is a very robust class that can do a bunch of stuff. Unfortunately, my HandGroup class doesn't take full advantage of the capabilities of the Hand class, so most of the really really cool things that Hand can do can't be seen in my Program 4. Feel free to read through Hand.java yourself and look at really cool things, like logical angles and physical angles, and sweeps and ticks, and that sort of stuff. HandGroup A HandGroup takes a bunch of Hands (three in this case) and puts them together into one mechanism. This way we only have to mess with the second hand--the minute hand and the hour hand go by magic. A HandGroup is placed upon an AnalogClockFace to make an AnalogClock. IncredibleTask This really annoying little class was necessary to get java.util.Timer to work with Director. I rant about it later. If you want to know, it extends java.util.TimerTask, and implements Runnable. Timekeeper The Timekeeper class is like all those bogus classes that Java has all over the place, such as java.lang.Math and java.lang.System. You can't instantiate a Timekeeper object, and all Timekeeper functions are static. It's actually a library of non-OO functions, but since Java prides itself on being completely object-oriented, you have to declare it as a "class." UpcClock A UpcClock is tremendously cool. It creates an actual UPC, following real UPC rules, based on the current time. You can find more information at http://www.howstuffworks.com/upc.htm or by reading the UpcClock class. UpcDigit This isn't a digit in the normal sense of the term; it's actually more like a bunch of lines that can be interpreted as a digit if you're a grocery scanner. In fact, that's exactly what it is. Amazing. These things are built up to make a UpcClock. -=-=- My Reasoning Well, after realizing that I needed to have more than one clock and that I should cycle through them, an array seemed like the most logical choice. But an array needs to have all its elements be of the same type, so I decided that I would need an abstract Clock class that defined a bunch of basic methods like showTime() and getDescription(). This was how I started out, and it worked well. A few tweaks to the Clock class later, and I had found the best way to lay things out. From there it was easy to define an AnalogClock class, a DigitalClock class, and a UpcClock class. The hardest part here was getting the graphics to look right while still making them scalable (or at least sizable when instantiated). The very hardest thing programming-wise of the whole project was figuring out how to get java.util.Timer to work with my Director class. java.util.Timer expects to have a java.util.TimerTask, since it wants to execute the TimerTask's run() method whenever its little timer goes off. So I needed some class to extend TimerTask, which is an abstract class. However, Director was already extending AWindow! Java stinks at supporting multiple inheritance; it only provides support for implementing interfaces, which was not generally intuitively obvious to the problem at hand. However, I got it to work, with a little finagling. I ended up creating an IncredibleTask class, which extended TimerTask. Then I set about instantiating a Timer in Director. I told it to run IncredibleTask's run() method, since after all, IncredibleTask is_a TimerTask. But I didn't want IncredibleTask's run() method to run; I wanted a method in Director to run. So I had to pass in a Director object, such as "this," to IncredibleTask, to tell it what to run. And now I had to make Director implement Runnable, so that IncredibleTask knew it had a run() method. Actually, IncredibleTask didn't want a Director, it wanted a Runnable. This whole chain of events is ridiculously complicated, and I can't think about more than half of it at one time or my head starts to explode, which is bad. It's too bad I couldn't have just made Director extend both AWindow and TimerTask. That would have made things a lot easier. But Java just doesn't support that, so I had to kludge my way around it. Kludging also came into play with my Timekeeper class. Apparently kludging is an acceptable way of getting things done in Java, because java.lang.Math and java.lang.System use the same kludge technique I used in Timekeeper. It's basically a way of getting some nice functions into a "true object-oriented environment" without having any objects. Oh well. Timekeeper came in very handy to get the number of seconds since midnight, and also to do some other nifty calculations. Figuring out how to create a UPC was the last major challenge of the program, since UPCs are inherently weird. But luckily I was able to find a very informative page on the Web, http://www.howstuffworks.com/upc.htm, that discussed UPCs in detail. This was extremely helpful, and I was able to get my UPCs working with a minimum of hassle. So that's the story of Program 4. For more ranting and raving, take a look at some of the comments I liberally sprinkled throughout my code. Brian Kell