[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

So far this chapter has only hinted at what is possible with Boopsi. Its
power lies in its extensibility.  Boopsi grants the application programmer
the power to add custom features to existing classes.  If an existing
class comes close to your needs, you can build on that class so it does
exactly what you want.  If you want a class that is unlike an existing
class, you can create it.

The heart of a Boopsi class is its method Dispatcher function. According
to the OOP metaphor, when an application wants a Boopsi object to perform
a method, it sends the object a message.  In reality, that object is only
a data structure, so it does not have the power to do anything.  When an
object receives a Boopsi message, a Boopsi message structure is passed to
the dispatcher of that object's class.  The dispatcher examines the
message and figures out what to do about it.

For example, when an application calls SetGadgetAttrs() on an integer
gadget:

    SetGadgetAttrs(myintegergadget, mywindow, NULL,
                   STRINGA_LongVal, 75L,
                   GA_ID,           2L,
                   TAG_END));

the SetGadgetAttrs() function calls the strgclass dispatcher.  A Boopsi
dispatcher receives three arguments: a pointer to the dispatcher's Class
(defined in <intuition/classes.h>), a pointer to the object that is going
to perform the method, and a pointer to the Boopsi message.  In this case,
the SetGadgetAttrs() function builds an OM_SET message, finds the
strgclass dispatcher, and "sends" the dispatcher the OM_SET message.
SetGadgetAttrs() can find the dispatcher because an object contains a
reference to its dispatcher.

When the dispatcher function "gets" the message, it examines the message
to find out its corresponding method.  In this case, the dispatcher
recognizes the message as an OM_SET message and proceeds to set
myintegergadget's attributes.

An OM_SET message looks like this (defined in <intuition/classusr.h>):

    struct opSet {
        ULONG MethodID;               /* This will be set to OM_SET      */
        struct TagItem *ops_AttrList; /* A tag list containing the       */
                                      /*     attribute/value pairs of    */
                                      /*     the attributes to set.      */
        struct GadgetInfo *ops_GInfo; /* Special information for gadgets */
    }

The OM_SET message contains a pointer to a tag list in ops_AttrList that
looks like this:

    {STRINGA_LongVal, 75L},
    {GA_ID, 2L},
    {TAG_END,}

The strgclass dispatcher scans through this tag list and recognizes the
STRINGA_LongVal attribute.  The dispatcher sets myintegergadget's internal
STRINGA_LongVal value to the corresponding value (75L) from the
attribute/value pair.

The strgclass dispatcher continues to scan through the tag list.  When it
finds GA_ID, it does not process it like STRINGA_LongVal.  The strgclass
dispatcher's OM_SET method does not recognize the GA_ID attribute because
strgclass inherited the GA_ID attribute from gadgetclass.  To handle
setting the GA_ID attribute, the strgclass dispatcher passes on the OM_SET
message to its superclass's dispatcher.  The strgclass dispatcher passes
control to the gadgetclass dispatcher, which knows about the GA_ID
attribute.

 Building On Existing Public Classes 
 Writing the Dispatcher 
 White Boxes - The Transparent Base Classes