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

The IDCMP_IDCMPUPDATE scheme presents a problem to an application that
wants to make gadgets talk to each other and talk to the application.
Boopsi gadgets only have one ICA_TARGET.  One Boopsi gadget can talk to
either another Boopsi object or its window's IDCMP port, but not both.
Using this scheme alone would force the application to update the integer
value of the gadgets, which is what we are trying to avoid in the first
place.

One of the standard Boopsi classes, icclass, is a class of information
forwarders.  An icclass object receives OM_UPDATE messages from one object
and passes those messages on to its own ICA_TARGET.  If it needs to map
any incoming attributes, it can use its own ICA_MAP to do so.

Icclass has a subclass called modelclass.  Using a modelclass object, an
application can chain a series of these objects together to set up a
"broadcast list" of icclass objects.  The modelclass object is similar to
the icclass object in that it has its own ICA_TARGET and ICA_MAP.  It
differs in that an application can use the modelclass OM_ADDMEMBER method
to add icclass objects to the modelclass object's broadcast list.

The OM_ADDMEMBER method is defined by rootclass.  It adds one Boopsi
object to the personal list of another Boopsi object.  It is up to the
Boopsi object's class to determine the purpose of the objects in the list.
Unlike the other methods mentioned so far in this chapter, OM_ADDMEMBER
does not have an Intuition function equivalent.  To pass an OM_ADDMEMBER
message to an object use the amiga.lib function DoMethodA(), or its
stack-based equivalent, DoMethod():

    ULONG DoMethodA(Object *myobject, Msg boopsimessage);
    ULONG DoMethod(Object *myobject, ULONG methodID, ...);

The return value is class-dependent.  The first argument to both of these
functions points to the object that will receive the Boopsi message.

For DoMethodA(), boopsimessage is the actual Boopsi message.  The layout
of it depends on the method.  Every method's message starts off with an
Msg (from <intuition/classusr.h>):

    typedef struct {
        ULONG MethodID; /* Method-specific data may follow this field */
    } *Msg;

The message that the OM_ADDMEMBER method uses looks like this (from
<intuition/classusr.h>):

    struct opMember {
        ULONG    MethodID;
        Object   *opam_Object;
    };

where MethodID is OM_ADDMEMBER and opam_Object points to the object to add
to myobject's list.

DoMethod() uses the stack to build a message.  To use DoMethod(), just
pass the elements of the method's message structure as arguments to
DoMethod() in the order that they appear in the structure.  For example,
to ask the Boopsi object myobject to add the object addobject to its
personal list:

    DoMethod(myobject, OM_ADDMEMBER, addobject);

To rearrange Talk2boopsi.c so that it uses a modelclass object (also known
as a model):

  * Create the integer and prop gadget.

  * Create the model.

  * Create two icclass objects, one called int2prop and the other called
    prop2int.

  * Make the model the ICA_TARGET of both the integer gadget and the prop
    gadget.  The gadgets do not need an ICA_MAP.

  * Using DoMethod() to call OM_ADDMEMBER, add the icclass objects to the
    model's personal list.

  * Make the prop gadget the ICA_TARGET of int2prop.  Make the integer
    gadget the ICA_TARGET of prop2int.

  * Create an ICA_MAP map list for int2prop that maps STRINGA_LongVal to
    PGA_Top.  Create an ICA_MAP map list for prop2int that maps PGA_Top
    to STRINGA_LongVal.  Make the ICA_TARGET of the model ICTARGET_IDCMP.

Diagrammatically, the new Talk2boopsi.c should look something like this:

     Figure 12-4: ICC Diagram 

When either of these gadgets has some interim state change (caused by the
user manipulating the gadgets), it sends an OM_UPDATE message to its
ICA_TARGET, which in this case is the modelclass object.  When this model
gets the message, it does two things.  It sends an IDCMP_IDCMPUPDATE to
the IDCMP port of the gadget's window and it also sends OM_UPDATE messages
to all of the objects in its personal list.  When int2prop gets an
OM_UPDATE message, it forwards that message to its ICA_TARGET, the prop
gadget.  Similarly, when prop2int gets an OM_UPDATE message, it forwards
that message to its ICA_TARGET, the integer gadget.

Although in this case it isn't a problem, icclass and modelclass objects
contain loop inhibition capabilities.  If an icclass object (or modelclass
object) receives an OM_UPDATE message, it forwards the message to its
target.  If somehow that forwarded message gets forwarded (or broadcast)
back to the icclass object, the icclass object ignores the message.  This
prevents the possibility of an infinite OM_UPDATE loop.