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

  1. ;/* RKMButClass.c - Example Boopsi gadget for RKRM:Libraries
  2. ; Execute me to compile me with Lattice 5.10b
  3. LC -b1 -d0 -cfistq -v -y -j73 RKMButClass.c
  4. Blink FROM LIB:c.o,RKMButClass.o TO TestBut LIBRARY LIB:LC.lib,LIB:Amiga.lib
  5. quit
  6. */
  7.  
  8. #include <exec/types.h>
  9. #include <intuition/intuition.h>
  10. #include <intuition/classes.h>
  11. #include <intuition/classusr.h>
  12. #include <intuition/imageclass.h>
  13. #include <intuition/gadgetclass.h>
  14. #include <intuition/cghooks.h>
  15. #include <intuition/icclass.h>
  16. #include <utility/tagitem.h>
  17. #include <utility/hooks.h>
  18. #include <clib/exec_protos.h>
  19. #include <clib/intuition_protos.h>
  20. #include <clib/graphics_protos.h>
  21. #include <clib/utility_protos.h>
  22. #include <clib/alib_protos.h>
  23. #include <clib/alib_stdio_protos.h>
  24.  
  25. #include <graphics/gfxmacros.h>
  26.  
  27. #ifdef LATTICE
  28. int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
  29. int chkabort(void) { return(0); }
  30. #endif
  31.  
  32. UBYTE *vers = "\0$VER: TestBut 37.1";
  33.  
  34. /***********************************************************/
  35. /****************      Class specifics      ****************/
  36. /***********************************************************/
  37. #define RKMBUT_Pulse   (TAG_USER + 1)
  38.  
  39. struct ButINST
  40. {
  41.     LONG midX, midY; /* Coordinates of middle of gadget */
  42. };
  43.  
  44. /* ButINST has one flag:  */
  45. #define ERASE_ONLY   0x00000001 /* Tells rendering routine to */
  46.                                 /* only erase the gadget, not */
  47.                                 /* rerender a new one.  This  */
  48.                                 /* lets the gadget erase it-  */
  49.                                 /* self before it rescales.   */
  50.  
  51. /* The functions in this module */
  52. Class *initRKMButGadClass(void);
  53. BOOL   freeRKMButGadClass(Class *);
  54. ULONG  dispatchRKMButGad(Class *, Object *, Msg);
  55. void   NotifyPulse(Class *, Object *, ULONG, LONG, struct gpInput *);
  56. ULONG  RenderRKMBut(Class *, struct Gadget *, struct gpRender *);
  57. void   geta4(void);
  58. void   MainLoop(ULONG, ULONG);
  59.  
  60. /*************************************************************************************************/
  61. /* The main() function connects an RKMButClass object to a Boopsi integer gadget, which displays */
  62. /* the RKMButClass gadget's RKMBUT_Pulse value.  The code scales and move the gadget while it is */
  63. /* in place.                                                                                     */
  64. /*************************************************************************************************/
  65.  
  66. struct TagItem pulse2int[] =
  67. {
  68.     {RKMBUT_Pulse, STRINGA_LongVal},
  69.     {TAG_END,}
  70. };
  71.  
  72. #define INTWIDTH  40
  73. #define INTHEIGHT 20
  74.  
  75. struct Library *IntuitionBase, *UtilityBase, *GfxBase;
  76. struct Window *w;
  77. Class *rkmbutcl;
  78. struct Gadget *integer, *but;
  79. struct IntuiMessage *msg;
  80.  
  81. void main(void)
  82. {
  83.     if (IntuitionBase = OpenLibrary("intuition.library", 37L))
  84.     {
  85.         if (UtilityBase = OpenLibrary("utility.library", 37L))
  86.         {
  87.             if (GfxBase = OpenLibrary("graphics.library", 37L))
  88.             {
  89.                 if (w = OpenWindowTags(NULL,
  90.                     WA_Flags,       WFLG_DEPTHGADGET | WFLG_DRAGBAR |
  91.                                         WFLG_CLOSEGADGET | WFLG_SIZEGADGET,
  92.                     WA_IDCMP,       IDCMP_CLOSEWINDOW,
  93.                     WA_Width,           640,
  94.                     WA_Height,          200,
  95.                     TAG_END))
  96.                 {
  97.                     WindowLimits(w, 450, 200, 640, 200);
  98.  
  99.                     if (rkmbutcl = initRKMButGadClass())
  100.                     {
  101.                         if (integer = (struct Gadget *)NewObject(NULL,
  102.                                        "strgclass",
  103.                                        GA_ID,            1L,
  104.                                        GA_Top,           (w->BorderTop) + 5L,
  105.                                        GA_Left,          (w->BorderLeft) + 5L,
  106.                                        GA_Width,         INTWIDTH,
  107.                                        GA_Height,        INTHEIGHT,
  108.                                        STRINGA_LongVal,  0L,
  109.                                        STRINGA_MaxChars, 5L,
  110.                                        TAG_END))
  111.                         {
  112.                             if (but = (struct Gadget *)NewObject(rkmbutcl,
  113.                                        NULL,
  114.                                        GA_ID,       2L,
  115.                                        GA_Top,      (w->BorderTop) + 5L,
  116.                                        GA_Left,     integer->LeftEdge +
  117.                                                         integer->Width + 5L,
  118.                                        GA_Width,    40L,
  119.                                        GA_Height,   INTHEIGHT,
  120.                                        GA_Previous, integer,
  121.                                        ICA_MAP,     pulse2int,
  122.                                        ICA_TARGET,  integer,
  123.                                        TAG_END))
  124.                             {
  125.                                 AddGList(w, integer, -1, -1, NULL);
  126.                                 RefreshGList(integer, w, NULL, -1);
  127.  
  128.                                 SetWindowTitles(w,
  129.                                     "<-- Click to resize gadget Height",
  130.                                     NULL);
  131.                                 MainLoop(TAG_DONE, 0L);
  132.  
  133.                                 SetWindowTitles(w,
  134.                                     "<-- Click to resize gadget Width",
  135.                                     NULL);
  136.                                 MainLoop(GA_Height, 100L);
  137.  
  138.                                 SetWindowTitles(w,
  139.                                     "<-- Click to resize gadget Y position",
  140.                                     NULL);
  141.                                 MainLoop(GA_Width, 100L);
  142.  
  143.                                 SetWindowTitles(w,
  144.                                     "<-- Click to resize gadget X position",
  145.                                     NULL);
  146.                                 MainLoop(GA_Top, but->TopEdge + 20);
  147.  
  148.                                 SetWindowTitles(w,
  149.                                     "<-- Click to quit", NULL);
  150.                                 MainLoop(GA_Left, but->LeftEdge + 20);
  151.  
  152.                                 RemoveGList(w, integer, -1);
  153.                                 DisposeObject(but);
  154.                             }
  155.                             DisposeObject(integer);
  156.                         }
  157.                         freeRKMButGadClass(rkmbutcl);
  158.                     }
  159.                     CloseWindow(w);
  160.                 }
  161.                 CloseLibrary(GfxBase);
  162.             }
  163.             CloseLibrary(UtilityBase);
  164.         }
  165.         CloseLibrary(IntuitionBase);
  166.     }
  167. }
  168.  
  169. void MainLoop(ULONG attr, ULONG value)
  170. {
  171.     ULONG done = FALSE;
  172.  
  173.     SetGadgetAttrs(but, w, NULL, attr, value, TAG_DONE);
  174.  
  175.     while (done == FALSE)
  176.     {
  177.         WaitPort((struct MsgPort *)w->UserPort);
  178.         while (msg = (struct IntuiMessage *)
  179.            GetMsg((struct MsgPort *)w->UserPort))
  180.         {
  181.             if (msg->Class == IDCMP_CLOSEWINDOW)
  182.             {
  183.                 done = TRUE;
  184.             }
  185.             ReplyMsg(msg);
  186.         }
  187.     }
  188. }
  189.  
  190. /***********************************************************/
  191. /**    Make the class and set up the dispatcher's hook    **/
  192. /***********************************************************/
  193. Class   *initRKMButGadClass(void)
  194. {
  195.     Class *cl = NULL;
  196.     extern ULONG HookEntry();     /* defined in amiga.lib */
  197.  
  198.     if ( cl =  MakeClass( NULL,
  199.                 "gadgetclass", NULL,
  200.                 sizeof ( struct ButINST ),
  201.                 0 ))
  202.     {
  203.         /* initialize the cl_Dispatcher Hook    */
  204.         cl->cl_Dispatcher.h_Entry = HookEntry;
  205.         cl->cl_Dispatcher.h_SubEntry = dispatchRKMButGad;
  206.     }
  207.     return ( cl );
  208. }
  209.  
  210. /***********************************************************/
  211. /******************     Free the class      ****************/
  212. /***********************************************************/
  213. BOOL freeRKMButGadClass( Class *cl )
  214. {
  215.     return (FreeClass(cl));
  216. }
  217.  
  218. /***********************************************************/
  219. /**********       The RKMBut class dispatcher      *********/
  220. /***********************************************************/
  221. ULONG dispatchRKMButGad(Class *cl, Object *o, Msg msg)
  222. {
  223.     struct ButINST *inst;
  224.     ULONG retval = FALSE;
  225.     Object *object;
  226.  
  227.     /* SAS/C and Manx function to make sure register A4
  228.        contains a pointer to global data */
  229.     geta4();
  230.  
  231.     switch (msg->MethodID)
  232.     {
  233.         case OM_NEW:       /* First, pass up to superclass */
  234.             if (object = (Object *)DoSuperMethodA(cl, o, msg))
  235.             {
  236.                 struct Gadget *g = (struct Gadget *)object;
  237.  
  238.                             /* Initial local instance data */
  239.                 inst = INST_DATA(cl, object);
  240.                 inst->midX   = g->LeftEdge + ( (g->Width) / 2);
  241.                 inst->midY   = g->TopEdge + ( (g->Height) / 2);
  242.  
  243.                 retval = (ULONG)object;
  244.             }
  245.             break;
  246.         case GM_HITTEST:
  247.                    /* Since this is a rectangular gadget this  */
  248.                    /* method always returns GMR_GADGETHIT.     */
  249.             retval = GMR_GADGETHIT;
  250.             break;
  251.         case GM_GOACTIVE:
  252.             inst = INST_DATA(cl, o);
  253.  
  254.                     /* Only become active if the GM_GOACTIVE   */
  255.                     /* was triggered by direct user input.     */
  256.             if (((struct gpInput *)msg)->gpi_IEvent)
  257.             {
  258.                        /* This gadget is now active, change    */
  259.                        /* visual state to selected and render. */
  260.                 ((struct Gadget *)o)->Flags |= GFLG_SELECTED;
  261.                                 RenderRKMBut(cl, (struct Gadget *)o, (struct gpRender *)msg);
  262.                 retval = GMR_MEACTIVE;
  263.             }
  264.             else            /* The GM_GOACTIVE was not         */
  265.                             /* triggered by direct user input. */
  266.                 retval = GMR_NOREUSE;
  267.             break;
  268.         case GM_RENDER:
  269.             retval = RenderRKMBut(cl, (struct Gadget *)o, (struct gpRender *)msg);
  270.             break;
  271.         case GM_HANDLEINPUT:   /* While it is active, this gadget sends its superclass an        */
  272.                                /* OM_NOTIFY pulse for every IECLASS_TIMER event that goes by     */
  273.                                /* (about one every 10th of a second).  Any object that is        */
  274.                                /* connected to this gadget will get A LOT of OM_UPDATE messages. */
  275.             {
  276.                 struct Gadget *g = (struct Gadget *)o;
  277.                 struct gpInput *gpi = (struct gpInput *)msg;
  278.                 struct InputEvent *ie = gpi->gpi_IEvent;
  279.  
  280.                 inst = INST_DATA(cl, o);
  281.  
  282.                 retval = GMR_MEACTIVE;
  283.  
  284.                 if (ie->ie_Class == IECLASS_RAWMOUSE)
  285.                 {
  286.                     switch (ie->ie_Code)
  287.                     {
  288.                         case SELECTUP: /* The user let go of the gadget so return GMR_NOREUSE    */
  289.                                        /* to deactivate and to tell Intuition not to reuse       */
  290.                                        /* this Input Event as we have already processed it.      */
  291.  
  292.                                        /*If the user let go of the gadget while the mouse was    */
  293.                                        /*over it, mask GMR_VERIFY into the return value so       */
  294.                                        /*Intuition will send a Release Verify (GADGETUP).        */
  295.                             if ( ((gpi->gpi_Mouse).X < g->LeftEdge) ||
  296.                                  ((gpi->gpi_Mouse).X > g->LeftEdge + g->Width) ||
  297.                                  ((gpi->gpi_Mouse).Y < g->TopEdge) ||
  298.                                  ((gpi->gpi_Mouse).Y > g->TopEdge + g->Height) )
  299.                                 retval = GMR_NOREUSE | GMR_VERIFY;
  300.                             else
  301.                                 retval = GMR_NOREUSE;
  302.  
  303.                                            /* Since the gadget is going inactive, send a final   */
  304.                                            /* notification to the ICA_TARGET.                    */
  305.                             NotifyPulse(cl , o, 0L, inst->midX, (struct gp_Input *)msg);
  306.                             break;
  307.                         case MENUDOWN: /* The user hit the menu button. Go inactive and let      */
  308.                                        /* Intuition reuse the menu button event so Intuition can */
  309.                                        /* pop up the menu bar.                                   */
  310.                             retval = GMR_REUSE;
  311.  
  312.                                            /* Since the gadget is going inactive, send a final   */
  313.                                            /* notification to the ICA_TARGET.                    */
  314.                             NotifyPulse(cl , o, 0L, inst->midX, (struct gp_Input *)msg);
  315.                             break;
  316.                         default:
  317.                             retval = GMR_MEACTIVE;
  318.                     }
  319.  
  320.                 }
  321.                 else if (ie->ie_Class == IECLASS_TIMER)
  322.                               /* If the gadget gets a timer event, it sends an interim OM_NOTIFY */
  323.                     NotifyPulse(cl, o, OPUF_INTERIM, inst->midX, gpi); /*     to its superclass. */
  324.             }
  325.             break;
  326.  
  327.         case GM_GOINACTIVE:           /* Intuition said to go inactive.  Clear the GFLG_SELECTED */
  328.                                       /* bit and render using unselected imagery.                */
  329.             ((struct Gadget *)o)->Flags &= ~GFLG_SELECTED;
  330.             RenderRKMBut(cl, (struct Gadget *)o, (struct gpRender *)msg);
  331.             break;
  332.         case OM_SET:/* Although this class doesn't have settable attributes, this gadget class   */
  333.                     /* does have scaleable imagery, so it needs to find out when its size and/or */
  334.                     /* position has changed so it can erase itself, THEN scale, and rerender.    */
  335.             if ( FindTagItem(GA_Width,  ((struct opSet *)msg)->ops_AttrList) ||
  336.                  FindTagItem(GA_Height, ((struct opSet *)msg)->ops_AttrList) ||
  337.                  FindTagItem(GA_Top,    ((struct opSet *)msg)->ops_AttrList) ||
  338.                  FindTagItem(GA_Left,   ((struct opSet *)msg)->ops_AttrList) )
  339.             {
  340.                 struct RastPort *rp;
  341.                 struct Gadget *g = (struct Gadget *)o;
  342.  
  343.                 WORD x,y,w,h;
  344.  
  345.                 x = g->LeftEdge;
  346.                 y = g->TopEdge;
  347.                 w = g->Width;
  348.                 h = g->Height;
  349.  
  350.                 inst = INST_DATA(cl, o);
  351.  
  352.                 retval = DoSuperMethodA(cl, o, msg);
  353.  
  354.                                                           /* Get pointer to RastPort for gadget. */
  355.                 if (rp = ObtainGIRPort( ((struct opSet *)msg)->ops_GInfo) )
  356.                 {
  357.                     UWORD *pens = ((struct opSet *)msg)->ops_GInfo->gi_DrInfo->dri_Pens;
  358.  
  359.                     SetAPen(rp, pens[BACKGROUNDPEN]);
  360.                     SetDrMd(rp, JAM1);                            /* Erase the old gadget.       */
  361.                     RectFill(rp, x, y, x+w, y+h);
  362.  
  363.                     inst->midX = g->LeftEdge + ( (g->Width) / 2); /* Recalculate where the       */
  364.                     inst->midY = g->TopEdge + ( (g->Height) / 2); /* center of the gadget is.    */
  365.  
  366.                                                                   /* Rerender the gadget.        */
  367.                     DoMethod(o, GM_RENDER, ((struct opSet *)msg)->ops_GInfo, rp, GREDRAW_REDRAW);
  368.                     ReleaseGIRPort(rp);
  369.                 }
  370.             }
  371.             else
  372.                 retval = DoSuperMethodA(cl, o, msg);
  373.             break;
  374.         default:          /* rkmmodelclass does not recognize the methodID, let the superclass's */
  375.                           /* dispatcher take a look at it.                                       */
  376.             retval = DoSuperMethodA(cl, o, msg);
  377.             break;
  378.     }
  379.     return(retval);
  380. }
  381.  
  382.  
  383.  
  384. /*************************************************************************************************/
  385. /************** Build an OM_NOTIFY message for RKMBUT_Pulse and send it to the superclass. *******/
  386. /*************************************************************************************************/
  387. void NotifyPulse(Class *cl, Object *o, ULONG flags, LONG mid, struct gpInput *gpi)
  388. {
  389.     struct TagItem tt[3];
  390.  
  391.     tt[0].ti_Tag = RKMBUT_Pulse;
  392.     tt[0].ti_Data = mid - ((gpi->gpi_Mouse).X + ((struct Gadget *)o)->LeftEdge);
  393.  
  394.     tt[1].ti_Tag = GA_ID;
  395.     tt[1].ti_Data = ((struct Gadget *)o)->GadgetID;
  396.  
  397.     tt[2].ti_Tag = TAG_DONE;
  398.  
  399.     DoSuperMethod(cl, o, OM_NOTIFY, tt, gpi->gpi_GInfo, flags);
  400. }
  401.  
  402.  
  403.  
  404. /*************************************************************************************************/
  405. /*******************************   Erase and rerender the gadget.   ******************************/
  406. /*************************************************************************************************/
  407. ULONG RenderRKMBut(Class *cl, struct Gadget *g, struct gpRender *msg)
  408. {
  409.     struct ButINST *inst = INST_DATA(cl, (Object *)g);
  410.     struct RastPort *rp;
  411.     ULONG retval = TRUE;
  412.     UWORD *pens = msg->gpr_GInfo->gi_DrInfo->dri_Pens;
  413.  
  414.     if (msg->MethodID == GM_RENDER)   /* If msg is truly a GM_RENDER message (not a gpInput that */
  415.                                       /* looks like a gpRender), use the rastport within it...   */
  416.         rp = msg->gpr_RPort;
  417.     else                              /* ...Otherwise, get a rastport using ObtainGIRPort().     */
  418.         rp = ObtainGIRPort(msg->gpr_GInfo);
  419.  
  420.     if (rp)
  421.     {
  422.         UWORD back, shine, shadow, w, h, x, y;
  423.  
  424.         if (g->Flags & GFLG_SELECTED) /* If the gadget is selected, reverse the meanings of the  */
  425.         {                             /* pens.                                                   */
  426.             back   = pens[FILLPEN];
  427.             shine  = pens[SHADOWPEN];
  428.             shadow = pens[SHINEPEN];
  429.         }
  430.         else
  431.         {
  432.             back   = pens[BACKGROUNDPEN];
  433.             shine  = pens[SHINEPEN];
  434.             shadow = pens[SHADOWPEN];
  435.         }
  436.         SetDrMd(rp, JAM1);
  437.  
  438.         SetAPen(rp, back);          /* Erase the old gadget.       */
  439.         RectFill(rp, g->LeftEdge,
  440.                      g->TopEdge,
  441.                      g->LeftEdge + g->Width,
  442.                      g->TopEdge + g->Height);
  443.  
  444.         SetAPen(rp, shadow);     /* Draw shadow edge.            */
  445.         Move(rp, g->LeftEdge + 1, g->TopEdge + g->Height);
  446.         Draw(rp, g->LeftEdge + g->Width, g->TopEdge + g->Height);
  447.         Draw(rp, g->LeftEdge + g->Width, g->TopEdge + 1);
  448.  
  449.         w = g->Width / 4;       /* Draw Arrows - Sorry, no frills imagery */
  450.         h = g->Height / 2;
  451.         x = g->LeftEdge + (w/2);
  452.         y = g->TopEdge + (h/2);
  453.  
  454.         Move(rp, x, inst->midY);
  455.         Draw(rp, x + w, y);
  456.         Draw(rp, x + w, y + (g->Height) - h);
  457.         Draw(rp, x, inst->midY);
  458.  
  459.         x = g->LeftEdge + (w/2) + g->Width / 2;
  460.  
  461.         Move(rp, x + w, inst->midY);
  462.         Draw(rp, x, y);
  463.         Draw(rp, x, y  + (g->Height) - h);
  464.         Draw(rp, x + w, inst->midY);
  465.  
  466.         SetAPen(rp, shine);    /* Draw shine edge.           */
  467.         Move(rp, g->LeftEdge, g->TopEdge + g->Height - 1);
  468.         Draw(rp, g->LeftEdge, g->TopEdge);
  469.         Draw(rp, g->LeftEdge + g->Width - 1, g->TopEdge);
  470.  
  471.         if (msg->MethodID != GM_RENDER) /* If we allocated a rastport, give it back.             */
  472.             ReleaseGIRPort(rp);
  473.     }
  474.     else retval = FALSE;
  475.     return(retval);
  476. }
  477.