This article is reprinted from the April 1990 edition of
TechNotes/Framework III.  Due to the limitations of this media,
certain graphic elements such as screen shots, illustrations and some
tables have been omitted.  Where possible, reference to such items has
been deleted.  As a result, continuity may be compromised.  

TechNotes is a monthly publication from the Ashton-Tate Software
Support Center.  For subscription information, call 800-545-9364.

Timely Graphs

Keith Swenson & Richard Bunter

The major thrust of the graphics in Framework III is to do business
graphics; you know, showing how much your stock has risen or fallen
with a line chart, how much of your tax dollar goes to pay for nuclear
missiles with a pie chart, and so on.  Few people ever get beyond
Framework's ability to draw graphs automatically and investigate just
how it does it.  Luckily, you're one of those few  an adventurer into
the realm of radius and arc.

We're going to explore a little bit of how FRED creates pie charts,
but we're not going to be doing anything so mundane as making pie
charts.  Instead, we'll use FRED's graphics primitives, ordinarily
used for those more mundane tasks, to create an analog clock. 
Furthermore, we'll learn a little about some other FRED functions so
that we can update the clock every minute.

The Clock

The clock face is made up of three pie charts with a common center
point.  Since a graphics frame has dimensions of 32000 by 32000
points, our center point will be at the x,y co-ordinate of
16000,16000.

The first pie chart is a complete circle and makes up the face of the
clock.  We'll make the radius of the face 15,000 points long so that
the circle will come fairly close to the edge of the frame.

The Hour Hand

The hour hand is our second pie slice.  We want this slice to be
relatively short and wide so we'll make its length, or radius, equal
to 9000 points.

In order to give it the right width (six degrees) we need to know the
angle at which our hour hand is going to be displayed.  And that, of
course depends on the time.  

Take a look at the listing for Clock.  Here's the part that determines
the angle of the hour hand: 

; Convert the hours to degrees.
h := @diffdate(t, @time(0, 0, 0), 3) * 30,

We'll discuss the angle in a moment; first let's talk about the trick
of getting the current time converted into a number.

The @time function, given no arguments, returns a date.  The same
function, given 0,0,0 as its arguments, will return midnight
(00:00:00) of the current date.  Using @diffdate we will get the
difference between the two times as a number.  The @diffdate function
is important to us here in that it's the only way to get the time in a
number type rather than a date type.

The way we arrive at the angle is to convert the time of day into a
decimal number and then multiply that number by 30.  For example,
converting 3:45 pm to a number would yield 15.75.  Now we pause and
ponder on why we multiply that by 30.

Think about it: a circle is divided into 360 degrees.  Dividing that
circle into twelve equal portions, as a clock does, gives us twelve
arcs of 30 degrees each.  Twelve o'clock, straight up, is zero
degrees.  One o'clock is 30 degrees, two o'clock is 60 degrees, etc.;
each hour adds another thirty degrees.  So, given that we have the
time, multiplying it by thirty will give us the angle.

Remember that we're dealing with floating point numbers here, and as a
result the hour hand will be positioned at the appropriate angle
rather than pointing directly to the hour.  At 3:15 it will be
one-quarter of the way between three and four, or 97.5 degrees.

Now that we have the angle, we'll start the slice at three degrees
before that angle and end it at three degrees after the angle, making
the slice six degrees wide.

The Minute Hand

We'll form the minute hand of the clock by creating a pie slice that's
long and relatively narrow; let's say that its radius will be 12000
and its width will be 2 degrees. 

The angle of the minute hand is determined by this formula:
m := @mod(h, 30) * 12,

An example is in order here, so let's say that it's 1:15 (doesn't
matter if it's am or pm).

The variable h equals the difference between midnight and 1:15
expressed, as a number, in hours (1.25) times 30, which equals 37.50. 
So, at 1:15 the hour hand will be at 37.50 degrees.  Now that we know
that, we can determine where the minute hand will be.

The variable m equals the remainder after h (37.50) is divided by 30
(7.50) times 12, which results in 90.  And 90 degrees also happens to
be where 15 minutes falls on the clock face.

Keeping the Clock Up-to-date

Using @alarm

Okay, now that we know what it takes to draw the clock, what's the
point of having one if it doesn't  update automatically?  This is
where @alarm comes in.

This almost unheard-of function executes a frame at some point in time
allowing you to go on with your work in the meantime.  In other words,
it makes our clock run in the background.

Updating on the Minute

We could take the easy way out and just have the @alarm function
recalculate our Clock frame every minute by using it this way:

@alarm(1, Clock)

but that would mean that it would execute every 60 seconds after you
recalculated the Clock frame.  If you recalculated the frame 45
seconds after the minute, your clock would be 45 seconds late.  We
can't let that happen (what would people think?).   Instead, we'll
give the @alarm function a time so that it will execute every minute
on the minute.  Here's how:

@alarm(@time(h/30, m/6+1, 0), Clock)

The @time function can take three arguments: hours, minutes and
seconds, in that order.  This line is telling Framework to recalculate
the Clock frame at the beginning of the next minute.  Remember that
the variables h and m contain, not hours and minutes, but the angles 
as part of this function we convert them back to hours and minutes.

Okay, now that we know what we're looking at, create an empty word
frame, name it "Clock", and in the formula area (reached by pressing
F2 then F9 to zoom) type in the formula for Clock (Listing 1).  You
may also want to take this opportunity to read up on the @draw
command, discussed on page 4-43 of FRED Framework III.

Listing 1: Clock

@local(t, h, m),   ; time (optional), hour, minute).

; If no time was passed as parameter, assign the clock time to t.
t := @if(@item1 = #NULL!, @time, @item1),

; Convert the hours to degrees.
h := @diffdate(t, @time(0, 0, 0), 3) * 30,

; Convert the minutes to degrees.
m := @mod(h, 30) * 12,

; Make this frame recalc at the beginning of the next minute.
@alarm(@time(h/30, m/6+1, 0), Clock),

; Draw the clock.
@draw(
        ; clock face
        12, 0,  ; fill pattern.
        11, 12, ; fill color.
        13, 16000, 16000, 15000, 0, 360,        ; wedge.
        
        ; hour hand
        12, 4,  ; fill pattern.
        11, 13, ; fill color.
        13, 16000, 16000, 9000, h-3, h+3,       ; wedge.

        ; minute hand
        11, 11, ; fill color.
        13, 16000, 16000, 12000, m-2, m+2,      ; wedge.

        ; Write the time
        4, 16000, 5000, ; move to x,y.
        18, 3000, 3000, ; char size.
        19, 12, ; char color.
        21, 1,  ; centered.
        @time1(t)
)

Expanding Your Horizons

You may have wonder why our clock macro checks to see if a parameter
was passed to it.  That's so we can use this clock as part of another
procedure, say...

A Four Time Zone Clock

Creating a rack of four clocks (so that you can see all of the
important times around the world) is pretty easy.  First, size your
clock frame so that it's relatively small.  Now, create an empty word
frame and name it "Clocks".  Move your Clock into the Clocks frame. 
Now, turn Allow Free Dragging on from the Frames menu so that we can
copy the clock three times, placing them side-by-side as we go.  You
can rename your clocks as you wish; the clocks in this example are for
Los Angeles, New York, London and Sydney.

All we need to do now is have our containing frame pass each of the
clocks a different hour so that they will reflect different time
zones.  When looking at the formula for Clocks, note that our alarm
statement has changed a bit.  The Clocks frame doesn't need to
calculate the angle because it doesn't draw anything.  Instead, it
just converts the time into numbers.  Therefore, our alarm statement
doesn't need to adjust the numbers to find the hour and minutes from
the angle.

Listing 2: Clocks

; Clocks
; This macro passes the time to the clocks.
@local(h, m),
h := @diffdate(@today, @time(0,0,0), 3), ; Calculate the hour.
m := @mod(h, 1) * 60,                    ; Calculate the minutes.

@Clocks.Los Angeles(@time(h, m, 0)),
@Clocks.New York(@time(h+2, m, 0)),
@Clocks.London(@time(h+7, m, 0)),
@Clocks.Sydney(@time(h-7, m, 0)),
@alarm( @time(h, m+1, 0), Clocks)    ;t the alarm for the next time.

Things You Can Do for Fun

Having typed these formulas in, there is no reason for you to stop
there.  There are a number of possible modifications that you can make
to stylize the clock to your liking.

Try coloring different parts of the clock with different colors.  Some
clocks have hands that extend for a short way on the other side of the
shaft.  Try for a modernistic look with hands that are formed by pie
segments that start at zero and extend to the current time.  Add a
date at the bottom.  It's fairly easy to add a second hand (actually a
third hand), but having the clock update every second could prove
somewhat annoying.  Or try making a clock that keeps track of elapsed
time with start, stop and reset buttons.        

You might want to look over the functions that we use here in the FRED
Framework III manual.  The @diffdate function is discussed on page
4-27,  @time is on page 4-148, @alarm function is on page 4-4 and
@draw is on 4-31.

I am indebted to Peter Stahl for passing this idea along to me in
January of 1989.  I modified his original program so that it would run
in the background. -KS

