Modifying a Program
We're going to add another class. This one, however, will be a subclass
of Rect
because our goal is to produce an object that
draws a rounded rectangle. A rounded rectangle requires the same
parameters as a rectangle with the addition of one more: the size of the
ovals whose curvature rounds the corners of our rectangle. The oval's
dimensions are determined by the number of pixels high and wide:
The Carbon framework call, FrameRoundRect
(also part of
QuickDraw), expects these dimensions as two integers (2-byte values).
Note that, while we pass the address of the Rect
data
(as for FrameRect
), we pass the actual values for
width and height (please see [../Reference/Chapter7.html Chapter 7] of
the Reference for more discussion of supplying parameters to Carbon
framework routines). We can conveniently store the oval's dimensions in
a class Point
instance variable, or ivar.
Since a rounded rectangle has so much in common with an ordinary
rectangle (i.e., objects created by class Rect
), the
logical approach would be a subclass of class Rect
called, say, class "RndRect
". It needs only the one
additional ivar which we will name "Ovalsize
". By
virtue of its inheritance from class Rect
then, an
object of class RndRect
will have a total of three
ivars: TopLeft
, BotRight
, and
Ovalsize
. TopLeft
and
BotRight
refer to the corners the
RndRect
would have if it wasn't rounded� that
is, the intersection points of the lines on which the sides lie. These
points, of course, will lie outside the rounded corners that will be
actually drawn on the display.
Next, the class needs a method to store the oval values its object
instances receive. The Ovalsize
value for this class is
stored by means of a PUT:
method (look familiar?),
which in addition to initializing our oval values, will initialize the
rectangle coordinate points TopLeft
and
BotRight
that our class inherited from
Rect
.
Finally, the subclass RndRect
needs a
DRAW:
method to act on the values stored in an object
created from its own class. In this particular DRAW:
method, \^BASE
retrieves the "base" address of the
current object, i.e. the address of the beginning of the object in
memory. In this case, it is the address of the rectangle coordinates
(which if you recall from a previous lesson, are stored as a record in
Rect
). The Carbon framework uses this address to locate
the values it uses as parameters. Next, the Ovalsize
values are put on the stack in a form the Carbon framework expects
(using the GET:
method of class
Point
), and then the proper Carbon framework routine
(FrameRoundRect
) is called to do the actual drawing on
the screen.
The subclass definition looks like this:
`:class RNDRECT super{ rect }`\
` point Ovalsize`
`:m PUT: put: Ovalsize put: super ;m ( l t r b w h -- )`
`:m DRAW: ^base get: Ovalsize FrameRoundRect ;m`
`:m DISP: put: self draw: self ;m`
`;class`\
That DISP:
method definition we use in our class is not
redundant with the definition used in the superclass.
SELF
always returns the address of the current
object. When SELF
was used in our class' superclass,
it returned the address for Rect
. In our class, it
returns the address of RndRect
.
Warning: If we did not redefine
DISP:
as we did, invoking aDISP:
message on any instance ofRndRect
would have usedRect
's definition forDISP:
, which in turn would have calledRect
'sPUT:
andDRAW:
methods (and not the new methods we defined in the subclassRndRect
).
Once the class is defined, it is now ready for the creation of an object:
RndRect Cynthia
To draw this object in window ww
, as we did in the
previous lesson, you can do this:
Window ww
test: ww
set: ww
20 20 100 60 20 30 disp: Cynthia
The values 20 and 30 are the width and height of the oval in the rounded
corners. The DISP:
method uses the
PUT:
methods defined in our class and its superclass to
take all six values off of the stack and store them in the ivars defined
in our class and the ones inherited from its superclass. Here is a
diagram of how the addition of this subclass works within the structure
of the overall program:
Next, you'll be introduced to the powerful building blocks of Mops: the predefined classes.