home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / Misc / TRSICAT.LZX / CATS_CD2_TRSI / Reference_Library / lib_examples / RKMModel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-21  |  12.3 KB  |  205 lines

  1. ;/* RKMModel.c - A simple custom modelclass subclass.
  2. LC -cfist -b1 -y -v -j73 rkmmodel.c
  3. quit ;*/
  4.  
  5. #include <exec/types.h>
  6. #include <intuition/intuition.h>
  7. #include <intuition/classes.h>
  8. #include <intuition/classusr.h>
  9. #include <intuition/imageclass.h>
  10. #include <intuition/gadgetclass.h>
  11. #include <intuition/cghooks.h>
  12. #include <intuition/icclass.h>
  13. #include <utility/tagitem.h>
  14. #include <utility/hooks.h>
  15. #include <clib/intuition_protos.h>
  16. #include <clib/utility_protos.h>
  17. #include <clib/alib_protos.h>
  18. #include <clib/alib_stdio_protos.h>
  19.  
  20. extern struct Library *IntuitionBase, *UtilityBase;
  21.  
  22. /*************************************************************************************************/
  23. /****************  The attributes defined by this class  *****************************************/
  24. /*************************************************************************************************/
  25. #define RKMMOD_CurrVal  (TAG_USER + 1) /* This attribute is the current value of the model.*******/
  26.                                        /**********************************************************/
  27. #define RKMMOD_Up       (TAG_USER + 2) /* These two are fake attributes that rkmmodelclass *******/
  28. #define RKMMOD_Down     (TAG_USER + 3) /* uses as pulse values to increment/decrement the  *******/
  29.                                        /* rkmmodel's RKMMOD_CurrVal attribute.             *******/
  30.                                        /**********************************************************/
  31. #define RKMMOD_Limit    (TAG_USER + 4) /* This attribute contains the upper bound of the   *******/
  32.                                        /* rkmmodel's RKMMOD_CurrVal.  The rkmmodel has a   *******/
  33.                                        /* static lower bound of zero.                      *******/
  34. /*************************************************************************************************/
  35.  
  36. #define DEFAULTVALLIMIT 100L /* If the programmer doesn't set               */
  37.                              /* RKMMOD_Limit, it defaults to this.          */
  38. struct RKMModData {
  39.     ULONG currval;       /* The instance data for this class.               */
  40.     ULONG vallimit;
  41. };
  42.  
  43. /*************************************************************************************************/
  44. /**************************      The functions in this module     ********************************/
  45. /*************************************************************************************************/
  46. void    geta4(void);                                                              /***************/
  47. Class  *initRKMModClass(void);                                                    /***************/
  48. BOOL    freeRKMModClass(Class *);                                                 /***************/
  49. ULONG   dispatchRKMModel(Class *, Object *, Msg);                                 /***************/
  50. void    NotifyCurrVal(Class *, Object *, struct opUpdate *, struct RKMModData *); /***************/
  51. /*************************************************************************************************/
  52.  
  53. /*************************************************************************************************/
  54. /********************************   Initialize the class    **************************************/
  55. /*************************************************************************************************/
  56. Class   *initRKMModClass(void)                /* Make the class and set     */
  57. {                                             /* up the dispatcher's hook.  */
  58.     Class *cl;
  59.     extern ULONG HookEntry();  /*      <-------   defined in amiga.lib.     */
  60.  
  61.     if ( cl =  MakeClass( NULL,
  62.                 "modelclass", NULL,
  63.                 sizeof ( struct RKMModData ),
  64.                 0 ))
  65.     {
  66.         cl->cl_Dispatcher.h_Entry = HookEntry;           /* initialize the  */
  67.         cl->cl_Dispatcher.h_SubEntry = dispatchRKMModel; /* cl_Dispatcher   */
  68.                                                          /* Hook.           */
  69.     }
  70.     return ( cl );
  71. }
  72.  
  73. /*************************************************************************************************/
  74. /*********************************      Free the class     ***************************************/
  75. /*************************************************************************************************/
  76. BOOL freeRKMModClass( Class *cl )
  77. {
  78.     return (FreeClass(cl));
  79. }
  80.  
  81. /*************************************************************************************************/
  82. /********************************     The class Dispatcher     ***********************************/
  83. /*************************************************************************************************/
  84. ULONG dispatchRKMModel(Class *cl, Object *o, Msg msg)
  85. {
  86.     struct RKMModData *mmd;
  87.     APTR retval = NULL;  /* A generic return value used by this class's methods.  The            */
  88.                          /* meaning of this field depends on the method.  For example,           */
  89.                          /* OM_GET uses this a a boolean return value, while OM_NEW              */
  90.                          /* uses it as a pointer to the new object.                              */
  91.     geta4();    /* SAS/C and Manx function - makes sure A4 contains global data pointer.         */
  92.  
  93.     switch (msg->MethodID)
  94.     {
  95.         case OM_NEW:     /* Pass message onto superclass first so it can set aside the memory    */
  96.                          /* for the object and take care of superclass instance data.            */
  97.             if (retval = (APTR)DoSuperMethodA(cl, o, msg))
  98.             {            /************************************************************************/
  99.                          /* For the OM_NEW method, the object pointer passed to the dispatcher   */
  100.                          /* does not point to an object (how could it? The object doesn't exist  */
  101.                          /* yet.)  DoSuperMethodA() returns a pointer to a newly created         */
  102.                          /* object. INST_DATA() is a macro defined in <intuition/classes.h>      */
  103.                          /* that returns a pointer to the object's instance data that is local   */
  104.                          /* to this class. For example, the instance data local to this class    */
  105.                          /* is the RKMModData structure defined above.                           */
  106.                          /************************************************************************/
  107.                 mmd = INST_DATA(cl, retval);
  108.                 mmd->currval = GetTagData(RKMMOD_CurrVal, 0L, /* initialize object's attributes. */
  109.                                           ((struct opSet *)msg)->ops_AttrList);
  110.                 mmd->vallimit = GetTagData(RKMMOD_Limit, DEFAULTVALLIMIT,
  111.                                            ((struct opSet *)msg)->ops_AttrList);
  112.             }
  113.             break;
  114.         case OM_SET:
  115.         case OM_UPDATE:
  116.             mmd = INST_DATA(cl, o);
  117.             DoSuperMethodA(cl, o, msg);   /* Let the superclasses set their attributes first.    */
  118.             {
  119.                 struct TagItem *tstate, *ti;    /* grab some temp variables off of the stack.    */
  120.  
  121.                 ti = ((struct opSet *)msg)->ops_AttrList;
  122.                 tstate = ti;
  123.  
  124.                         /* Step through all of the attribute/value pairs in the list.  Use the   */
  125.                         /* utility.library tag functions to do this so they can properly process */
  126.                         /* special tag IDs like TAG_SKIP, TAG_IGNORE, etc.                       */
  127.  
  128.                 while (ti = NextTagItem(&tstate))    /* Step through all of the attribute/value  */
  129.                 {                 /* pairs in the list. Use the utility.library tag functions    */
  130.                                   /* to do this so they can properly process special tag IDs     */
  131.                                   /* like TAG_SKIP, TAG_IGNORE, etc.                             */
  132.                     switch (ti->ti_Tag)
  133.                     {
  134.                         case RKMMOD_CurrVal:
  135.                             if ((ti->ti_Data) > mmd->vallimit) ti->ti_Data =
  136.                                     mmd->vallimit;
  137.                             mmd->currval = ti->ti_Data;
  138.                             NotifyCurrVal(cl, o, msg, mmd);
  139.                             retval = (APTR)1L;  /* Changing RKMMOD_CurrVal can cause a visual    */
  140.                             break;              /* change to gadgets in the rkmmodel's broadcast */
  141.                                                 /* list.  The rkmmodel has to tell the applica-  */
  142.                                                 /* tion by returning a value besides zero.       */
  143.                         case RKMMOD_Up:
  144.                             mmd->currval++;
  145.  
  146.                                  /* Make sure the current value is not greater than value limit. */
  147.                             if ((mmd->currval) > mmd->vallimit) mmd->currval = mmd->vallimit;
  148.                             NotifyCurrVal(cl, o, msg, mmd);
  149.                             retval = (APTR)1L;  /* Changing RKMMOD_Up can cause a visual         */
  150.                             break;              /* change to gadgets in the rkmmodel's broadcast */
  151.                                                 /* list.  The rkmmodel has to tell the applica-  */
  152.                                                 /* tion by returning a value besides zero.       */
  153.                         case RKMMOD_Down:
  154.                             mmd->currval--;
  155.                                     /* Make sure currval didn't go negative. */
  156.                             if ((LONG)(mmd->currval) == -1L)
  157.                                 mmd->currval = 0L;
  158.                             NotifyCurrVal(cl, o, msg, mmd);
  159.                             retval = (APTR)1L;  /* Changing RKMMOD_Down can cause a visual       */
  160.                             break;              /* change to gadgets in the rkmmodel's broadcast */
  161.                                                 /* list.  The rkmmodel has to tell the applica-  */
  162.                                                 /* tion by returning a value besides zero.       */
  163.                         case RKMMOD_Limit:
  164.                             mmd->vallimit = ti->ti_Data; /* Set the limit.  Note that this does  */
  165.                             break;                       /* not do bounds checking on the        */
  166.                                                          /* current RKMModData.currval value.    */
  167.                     }
  168.                 }
  169.             }
  170.             break;
  171.         case OM_GET:                     /* The only attribute that is "gettable" in this        */
  172.             mmd = INST_DATA(cl, o);      /* class or its superclasses is RKMMOD_CurrVal.         */
  173.             if ((((struct opGet *)msg)->opg_AttrID) == RKMMOD_CurrVal)
  174.             {
  175.                 *(((struct opGet *)msg)->opg_Storage) = mmd->currval;
  176.                 retval = (Object *)TRUE;
  177.             }
  178.             else retval = (APTR)DoSuperMethodA(cl, o, msg);
  179.             break;
  180.         default:       /* rkmmodelclass does not recognize the methodID, so let the superclass's */
  181.                        /* dispatcher take a look at it.                                          */
  182.             retval = (APTR)DoSuperMethodA(cl, o, msg);
  183.             break;
  184.     }
  185.     return((ULONG)retval);
  186. }
  187.  
  188. void NotifyCurrVal(Class *cl, Object *o, struct opUpdate *msg, struct RKMModData *mmd)
  189. {
  190.     struct TagItem tt[2];
  191.  
  192.     tt[0].ti_Tag = RKMMOD_CurrVal; /* make a tag list.  */
  193.     tt[0].ti_Data = mmd->currval;
  194.     tt[1].ti_Tag = TAG_DONE;
  195.                                 /* If the RKMMOD_CurrVal changes, we want everyone to know about */
  196.     DoSuperMethod(cl, o,        /* it. Theoretically, the class is supposed to send itself a     */
  197.              OM_NOTIFY,         /* OM_NOTIFY message. Because this class lets its superclass     */
  198.              tt,                /* handle the OM_NOTIFY message, it skips the middleman and      */
  199.              msg->opu_GInfo,    /* sends the OM_NOTIFY directly to its superclass.               */
  200.  
  201.              ((msg->MethodID == OM_UPDATE) ? (msg->opu_Flags) : 0L)); /* If this is an OM_UPDATE */
  202.                                 /* method, make sure the part the OM_UPDATE message adds to the  */
  203.                                 /* OM_SET message gets added.  That lets the dispatcher handle   */
  204. }                               /* OM_UPDATE and OM_SET in the same case.                        */
  205.