home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 18 / amigaformatcd18.iso / mui / mui_developer / c / examples / inputhandler.c < prev    next >
C/C++ Source or Header  |  1997-03-10  |  8KB  |  317 lines

  1. #include "demo.h"
  2. #include <devices/timer.h>
  3.  
  4.  
  5. /* Instance Data */
  6.  
  7. struct MyData
  8. {
  9.     struct MsgPort     *port;
  10.     struct timerequest *req;
  11.  
  12.     struct MUI_InputHandlerNode ihnode;
  13.  
  14.     LONG index;
  15. };
  16.  
  17.  
  18. /* Attributes and methods for the custom class */
  19.  
  20. #define MUISERIALNR_STUNTZI 1
  21. #define TAGBASE_STUNTZI (TAG_USER | ( MUISERIALNR_STUNTZI << 16))
  22. #define MUIM_Class5_Trigger (TAGBASE_STUNTZI | 0x0001)
  23.  
  24.  
  25. /* IO macros */
  26.  
  27. #define IO_SIGBIT(req)    ((LONG)(((struct IORequest *)req)->io_Message.mn_ReplyPort->mp_SigBit))
  28. #define IO_SIGMASK(req) ((LONG)(1L<<IO_SIGBIT(req)))
  29.  
  30.  
  31. /* Some strings to display */
  32.  
  33. static const char *LifeOfBrian[] =
  34. {
  35.     "Cheer up, Brian. You know what they say.",
  36.     "Some things in life are bad,",
  37.     "They can really make you mad.",
  38.     "Other things just make you swear and curse.",
  39.     "When you're chewing on life's grissle,",
  40.     "Don't grumble, give a whistle.",
  41.     "And this'll help things turn out for the best,",
  42.     "And...",
  43.     "Always look on the bright side of life",
  44.     "Always look on the light side of life",
  45.     "If life seems jolly rotten,",
  46.     "There's something you've forgotten,",
  47.     "And that's to laugh, and smile, and dance, and sing.",
  48.     "When you're feeling in the dumps,",
  49.     "Don't be silly chumps,",
  50.     "Just purse your lips and whistle, that's the thing.",
  51.     "And...",
  52.     "Always look on the bright side of life, come on!",
  53.     "Always look on the right side of life",
  54.     "For life is quite absurd,",
  55.     "And death's the final word.",
  56.     "You must always face the curtain with a bow.",
  57.     "Forget about your sin,",
  58.     "Give the audience a grin.",
  59.     "Enjoy it, it's your last chance anyhow,",
  60.     "So...",
  61.     "Always look on the bright side of death",
  62.     "Just before you draw your terminal breath.",
  63.     "Life's a piece of shit,",
  64.     "When you look at it.",
  65.     "Life's a laugh, and death's a joke, it's true.",
  66.     "You'll see it's all a show,",
  67.     "Keep 'em laughing as you go,",
  68.     "Just remember that the last laugh is on you.",
  69.     "And...",
  70.     "Always look on the bright side of life !",
  71.     "...",
  72.     "*** THE END ***",
  73.     "",
  74.     NULL,
  75. };
  76.  
  77.  
  78.  
  79. /***************************************************************************/
  80. /* Here is the beginning of our new class...                               */
  81. /***************************************************************************/
  82.  
  83.  
  84. ULONG mNew(struct IClass *cl,Object *obj,Msg msg)
  85. {
  86.     struct MyData *data;
  87.  
  88.     if (!(obj = (Object *)DoSuperMethodA(cl,obj,msg)))
  89.         return(0);
  90.  
  91.     data = INST_DATA(cl,obj);
  92.  
  93.     if (data->port = CreateMsgPort())
  94.     {
  95.         if (data->req = CreateIORequest(data->port,sizeof(struct timerequest)))
  96.         {
  97.             if (!OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)data->req,0))
  98.             {
  99. /*
  100.                 data->ihnode.ihn_Object  = obj;
  101.                 data->ihnode.ihn_Signals = IO_SIGMASK(data->req);
  102.                 data->ihnode.ihn_Method  = MUIM_Class5_Trigger;
  103.                 data->ihnode.ihn_Flags   = 0;
  104. */
  105.  
  106.                 data->ihnode.ihn_Object  = obj;
  107.                 data->ihnode.ihn_Millis  = 1000;
  108.                 data->ihnode.ihn_Method  = MUIM_Class5_Trigger;
  109.                 data->ihnode.ihn_Flags   = MUIIHNF_TIMER;
  110.  
  111.                 data->index = 0;
  112.  
  113.                 return((ULONG)obj);
  114.             }
  115.         }
  116.     }
  117.  
  118.     CoerceMethod(cl,obj,OM_DISPOSE);
  119.     return(0);
  120. }
  121.  
  122.  
  123. ULONG mDispose(struct IClass *cl,Object *obj,Msg msg)
  124. {
  125.     struct MyData *data = INST_DATA(cl,obj);
  126.  
  127.     if (data->req)
  128.     {
  129.         if (data->req->tr_node.io_Device)
  130.         {
  131.             CloseDevice((struct IORequest *)data->req);
  132.         }
  133.         DeleteIORequest(data->req);
  134.     }
  135.  
  136.     if (data->port)
  137.         DeleteMsgPort(data->port);
  138.  
  139.     return(DoSuperMethodA(cl,obj,msg));
  140. }
  141.  
  142.  
  143. ULONG mSetup(struct IClass *cl,Object *obj,Msg msg)
  144. {
  145.     struct MyData *data = INST_DATA(cl,obj);
  146.  
  147.     if (!DoSuperMethodA(cl,obj,msg))
  148.         return(FALSE);
  149.  
  150.     data->req->tr_node.io_Command = TR_ADDREQUEST;
  151.     data->req->tr_time.tv_secs    = 1;
  152.     data->req->tr_time.tv_micro   = 0;
  153.     SendIO((struct IORequest *)data->req);
  154.  
  155.     DoMethod(_app(obj),MUIM_Application_AddInputHandler,&data->ihnode);
  156.  
  157.     return(TRUE);
  158. }
  159.  
  160.  
  161. ULONG mCleanup(struct IClass *cl,Object *obj,Msg msg)
  162. {
  163.     struct MyData *data = INST_DATA(cl,obj);
  164.  
  165.     DoMethod(_app(obj),MUIM_Application_RemInputHandler,&data->ihnode);
  166.  
  167.     if (!CheckIO(data->req)) AbortIO(data->req);
  168.     WaitIO(data->req);
  169.  
  170.     return(DoSuperMethodA(cl,obj,msg));
  171. }
  172.  
  173.  
  174. ULONG mTrigger(struct IClass *cl,Object *obj,Msg msg)
  175. {
  176.     struct MyData *data = INST_DATA(cl,obj);
  177.  
  178. /*
  179.     if (CheckIO(data->req))
  180.     {
  181.         WaitIO(data->req);
  182.  
  183.         data->req->tr_node.io_Command = TR_ADDREQUEST;
  184.         data->req->tr_time.tv_secs    = 3;
  185.         data->req->tr_time.tv_micro   = 0;
  186.         SendIO((struct IORequest *)data->req);
  187.  
  188.         set(obj,MUIA_Text_Contents,LifeOfBrian[data->index]);
  189.  
  190.         if (!LifeOfBrian[++data->index])
  191.             data->index = 0;
  192.  
  193.         return(TRUE);
  194.     }
  195. */
  196.  
  197.         set(obj,MUIA_Text_Contents,LifeOfBrian[data->index]);
  198.  
  199.         if (!LifeOfBrian[++data->index])
  200.             data->index = 0;
  201.  
  202.     return(FALSE);
  203. }
  204.  
  205.  
  206. /*
  207. ** Here comes the dispatcher for our custom class.
  208. */
  209.  
  210. SAVEDS ASM ULONG MyDispatcher(REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) Msg msg)
  211. {
  212.     switch (msg->MethodID)
  213.     {
  214.         case OM_NEW             : return(mNew    (cl,obj,(APTR)msg));
  215.         case OM_DISPOSE         : return(mDispose(cl,obj,(APTR)msg));
  216.         case MUIM_Setup         : return(mSetup  (cl,obj,(APTR)msg));
  217.         case MUIM_Cleanup       : return(mCleanup(cl,obj,(APTR)msg));
  218.         case MUIM_Class5_Trigger: return(mTrigger(cl,obj,(APTR)msg));
  219.     }
  220.  
  221.     return(DoSuperMethodA(cl,obj,msg));
  222. }
  223.  
  224.  
  225. /***************************************************************************/
  226. /* Thats all there is about it. Now lets see how things are used...        */
  227. /***************************************************************************/
  228.  
  229. int main(int argc,char *argv[])
  230. {
  231.     Object *app,*window,*MyObj;
  232.     struct MUI_CustomClass *mcc;
  233.  
  234.     init();
  235.  
  236.     /* Create the new custom class with a call to MUI_CreateCustomClass(). */
  237.     /* Caution: This function returns not a struct IClass, but a           */
  238.     /* struct MUI_CustomClass which contains a struct IClass to be         */
  239.     /* used with NewObject() calls.                                        */
  240.     /* Note well: MUI creates the dispatcher hook for you, you may         */
  241.     /* *not* use its h_Data field! If you need custom data, use the        */
  242.     /* cl_UserData of the IClass structure!                                */
  243.  
  244.     if (!(mcc = MUI_CreateCustomClass(NULL,MUIC_Text,NULL,sizeof(struct MyData),MyDispatcher)))
  245.         fail(NULL,"Could not create custom class.");
  246.  
  247.     app = ApplicationObject,
  248.         MUIA_Application_Title      , "Class5",
  249.         MUIA_Application_Version    , "$VER: Class5 19.5 (12.02.97)",
  250.         MUIA_Application_Copyright  , "©1993, Stefan Stuntz",
  251.         MUIA_Application_Author     , "Stefan Stuntz",
  252.         MUIA_Application_Description, "Demonstrate the use of custom classes.",
  253.         MUIA_Application_Base       , "Class5",
  254.  
  255.         SubWindow, window = WindowObject,
  256.             MUIA_Window_Title, "Input Handler Class",
  257.             MUIA_Window_ID   , MAKE_ID('C','L','S','5'),
  258.             WindowContents, VGroup,
  259.  
  260.                 Child, TextObject,
  261.                     TextFrame,
  262.                     MUIA_Background, MUII_TextBack,
  263.                     MUIA_Text_Contents, "\33cDemonstration of a class that reacts on\nevents (here: timer signals) automatically.",
  264.                     End,
  265.  
  266.                 Child, MyObj = NewObject(mcc->mcc_Class,NULL,
  267.                     TextFrame,
  268.                     MUIA_Background, MUII_BACKGROUND,
  269.                     MUIA_Text_PreParse, "\33c",
  270.                     TAG_DONE),
  271.  
  272.                 End,
  273.  
  274.             End,
  275.         End;
  276.  
  277.     if (!app)
  278.         fail(app,"Failed to create Application.");
  279.  
  280.     DoMethod(window,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
  281.         app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
  282.  
  283. /*
  284. ** This is the ideal input loop for an object oriented MUI application.
  285. ** Everything is encapsulated in classes, no return ids need to be used,
  286. ** we just check if the program shall terminate.
  287. ** Note that MUIM_Application_NewInput expects sigs to contain the result
  288. ** from Wait() (or 0). This makes the input loop significantly faster.
  289. */
  290.  
  291.     set(window,MUIA_Window_Open,TRUE);
  292.  
  293.     {
  294.         ULONG sigs = 0;
  295.  
  296.         while (DoMethod(app,MUIM_Application_NewInput,&sigs) != MUIV_Application_ReturnID_Quit)
  297.         {
  298.             if (sigs)
  299.             {
  300.                 sigs = Wait(sigs | SIGBREAKF_CTRL_C);
  301.                 if (sigs & SIGBREAKF_CTRL_C) break;
  302.             }
  303.         }
  304.     }
  305.  
  306.     set(window,MUIA_Window_Open,FALSE);
  307.  
  308.  
  309. /*
  310. ** Shut down...
  311. */
  312.  
  313.     MUI_DisposeObject(app);     /* dispose all objects. */
  314.     MUI_DeleteCustomClass(mcc); /* delete the custom class. */
  315.     fail(NULL,NULL);            /* exit, app is already disposed. */
  316. }
  317.