home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / rom / intuition / buttongclass.c < prev    next >
C/C++ Source or Header  |  1997-01-27  |  10KB  |  412 lines

  1. /* AROS buttongclass implementation
  2.  * (frameless button, no window border support yet)
  3.  * 10/26/96 caldi@usa.nai.net
  4.  */
  5.  
  6. #include <exec/types.h>
  7.  
  8. #include <dos/dos.h>
  9. #include <dos/dosextens.h>
  10.  
  11. #include <intuition/intuition.h>
  12. #include <intuition/intuitionbase.h>
  13. #include <intuition/classes.h>
  14. #include <intuition/classusr.h>
  15. #include <intuition/gadgetclass.h>
  16. #include <intuition/cghooks.h>
  17. #include <intuition/icclass.h>
  18. #include <intuition/imageclass.h>
  19.  
  20. #include <graphics/gfxbase.h>
  21. #include <graphics/gfxmacros.h>
  22.  
  23. #include <utility/tagitem.h>
  24. #include <utility/hooks.h>
  25.  
  26. #include <clib/macros.h>
  27.  
  28. #include <proto/exec.h>
  29. #include <proto/intuition.h>
  30. #include <proto/graphics.h>
  31. #include <proto/utility.h>
  32.  
  33. #ifdef _AROS
  34. #include <aros/asmcall.h>
  35. #include <proto/alib.h>
  36. #include "intuition_intern.h"
  37. #include "gadgets.h"
  38. #endif
  39.  
  40. /****************************************************************************/
  41.  
  42. /* Some handy transparent base class object casting defines.
  43.  */
  44. #define G(o)  ((struct Gadget *)o)
  45. #define EG(o) ((struct ExtGadget *)o)
  46. #define IM(o) ((struct Image *)o)
  47.  
  48. /****************************************************************************/
  49.  
  50.  
  51. #undef IntuitionBase
  52. #define IntuitionBase    ((struct IntuitionBase *)(cl->cl_UserData))
  53.  
  54. /* buttongclass boopsi dispatcher
  55.  */
  56. AROS_UFH3(static IPTR, dispatch_buttongclass,
  57.     AROS_UFHA(Class *,  cl,  A0),
  58.     AROS_UFHA(Object *, o,   A2),
  59.     AROS_UFHA(Msg,      msg, A1)
  60. )
  61. {
  62.     IPTR retval = 0UL;
  63.  
  64.     switch(msg->MethodID)
  65.     {
  66.     case GM_RENDER:
  67.     /* We will let the AROS gadgetclass test if it is safe to render */
  68.     if ( DoSuperMethodA(cl, o, msg) != 0)
  69.     {
  70.         UWORD *pens = ((struct gpRender *)msg)->gpr_GInfo->gi_DrInfo->dri_Pens;
  71.         struct RastPort *rp = ((struct gpRender *)msg)->gpr_RPort;
  72.         struct IBox container;
  73.  
  74.         GetGadgetIBox(o, ((struct gpRender *)msg)->gpr_GInfo, &container);
  75.  
  76.         if (container.Width <= 1 || container.Height <= 1)
  77.         return(retval);
  78.  
  79.         if ( EG(o)->Flags & GFLG_SELECTED )
  80.         {
  81.         SetAPen( rp, pens[FILLPEN] );
  82.         }
  83.         else
  84.         {
  85.         SetAPen( rp, pens[BACKGROUNDPEN] );
  86.         } /* if */
  87.  
  88.         SetDrMd( rp, JAM1 );
  89.  
  90.         RectFill( rp,
  91.         container.Left,
  92.         container.Top,
  93.         container.Left + container.Width - 1,
  94.         container.Top + container.Height - 1
  95.         );
  96.  
  97.         if ( (EG(o)->Flags & GFLG_GADGIMAGE) == 0 )
  98.         {
  99.         if ( ( EG(o)->SelectRender != NULL ) && ( EG(o)->Flags & GFLG_SELECTED ) )
  100.         {
  101.             DrawBorder(rp, ((struct Border *)EG(o)->SelectRender), container.Left, container.Top );
  102.         }
  103.         else if ( EG(o)->GadgetRender != NULL )
  104.         {
  105.             DrawBorder(rp, ((struct Border *)EG(o)->GadgetRender), container.Left, container.Top );
  106.         }
  107.         }
  108.         else if ( EG(o)->Flags & GFLG_GADGIMAGE )
  109.         {
  110.         if ( ( EG(o)->SelectRender != NULL ) && ( EG(o)->Flags & GFLG_SELECTED ) )
  111.         {
  112.             /* center image position, we assume image top and left is 0 */
  113.             ULONG x = container.Left + ((container.Width / 2) - (IM(EG(o)->SelectRender)->Width / 2));
  114.             ULONG y = container.Top + ((container.Height / 2) - (IM(EG(o)->SelectRender)->Height / 2));
  115.  
  116.             DrawImageState( rp,
  117.             IM(EG(o)->SelectRender),
  118.             x, y,
  119.             ( (EG(o)->Flags & GFLG_SELECTED) ? IDS_SELECTED : IDS_NORMAL ),
  120.             ((struct gpRender *)msg)->gpr_GInfo->gi_DrInfo );
  121.         }
  122.         else if ( EG(o)->GadgetRender != NULL )
  123.         {
  124.             /* center image position, we assume image top and left is 0 */
  125.             ULONG x = container.Left + ((container.Width / 2) - (IM(EG(o)->GadgetRender)->Width / 2));
  126.             ULONG y = container.Top + ((container.Height / 2) - (IM(EG(o)->GadgetRender)->Height / 2));
  127.  
  128.             DrawImageState( rp,
  129.             IM(EG(o)->GadgetRender),
  130.             x, y,
  131.             ( (EG(o)->Flags & GFLG_SELECTED) ? IDS_SELECTED : IDS_NORMAL ),
  132.             ((struct gpRender *)msg)->gpr_GInfo->gi_DrInfo );
  133.         }
  134.         }
  135.  
  136.         switch (EG(o)->Flags & GFLG_LABELMASK)
  137.         {
  138.         case GFLG_LABELITEXT:
  139.             PrintIText( rp, EG(o)->GadgetText, container.Left, container.Top );
  140.             break;
  141.  
  142.         case GFLG_LABELSTRING:
  143.             if( EG(o)->GadgetText != NULL )
  144.             {
  145.             ULONG len;
  146.  
  147.             if ((len = strlen ((STRPTR) EG(o)->GadgetText)) > 0UL)
  148.             {
  149.                 ULONG x;
  150.                 ULONG y;
  151.  
  152.                 x = container.Left + (container.Width / 2);
  153.                 x -= LabelWidth (rp, (STRPTR) EG(o)->GadgetText, len, IntuitionBase) / 2;
  154.  
  155.                 y = container.Top + (container.Height / 2) + rp->Font->tf_Baseline;
  156.                 y -= rp->Font->tf_YSize / 2;
  157.  
  158.                 SetAPen (rp, pens[TEXTPEN] );
  159.  
  160.                 Move (rp, x, y );
  161.                 RenderLabel (rp, (STRPTR) EG(o)->GadgetText, len, IntuitionBase);
  162.             }
  163.             }
  164.             break;
  165.  
  166.         case GFLG_LABELIMAGE:
  167.             {
  168.             /* center image position, we assume image top and left is 0 */
  169.             ULONG x = container.Left + ((container.Width / 2) - (IM(EG(o)->GadgetText)->Width / 2));
  170.             ULONG y = container.Top + ((container.Height / 2) - (IM(EG(o)->GadgetText)->Height / 2));
  171.  
  172.             DrawImageState( rp,
  173.                 IM(EG(o)->GadgetText),
  174.                 x, y,
  175.                 ( (EG(o)->Flags & GFLG_SELECTED) ? IDS_SELECTED : IDS_NORMAL ),
  176.                 ((struct gpRender *)msg)->gpr_GInfo->gi_DrInfo );
  177.             }
  178.             break;
  179.         }
  180.  
  181.         if ( EG(o)->Flags & GFLG_DISABLED )
  182.         {
  183.         UWORD pattern[] = { 0x8888, 0x2222 };
  184.  
  185.         SetDrMd( rp, JAM1 );
  186.         SetAPen( rp, pens[SHADOWPEN] );
  187.         SetAfPt( rp, pattern, 1);
  188.  
  189.         /* render disable pattern */
  190.         RectFill( rp,
  191.             container.Left,
  192.             container.Top,
  193.             container.Left + container.Width - 1,
  194.             container.Top + container.Height - 1 );
  195.         } /* if */
  196.     } /* if */
  197.     break;
  198.  
  199.     case GM_LAYOUT:
  200.     break;
  201.  
  202.     case GM_DOMAIN:
  203.     break;
  204.  
  205.     case GM_GOACTIVE:
  206.     {
  207.         struct GadgetInfo *gi = ((struct gpInput *)msg)->gpi_GInfo;
  208.  
  209.         if (gi)
  210.         {
  211.         struct RastPort *rp = ObtainGIRPort(gi);
  212.         if (rp)
  213.         {
  214.             EG(o)->Flags |= GFLG_SELECTED;
  215.  
  216.             DoMethod(o, GM_RENDER, gi, rp, GREDRAW_REDRAW);
  217.             ReleaseGIRPort(rp);
  218.  
  219.             DoMethod(o, OM_NOTIFY, gi, NULL, OPUF_INTERIM);
  220.  
  221.             retval = GMR_MEACTIVE;
  222.         } /* if */
  223.         } /* if */
  224.     } /* if */
  225.     break;
  226.  
  227.     case GM_HANDLEINPUT:
  228.     {
  229.         struct GadgetInfo *gi = ((struct gpInput *)msg)->gpi_GInfo;
  230.  
  231.         if (gi)
  232.         {
  233.         struct InputEvent *ie = ((struct gpInput *)msg)->gpi_IEvent;
  234.  
  235.         retval = GMR_MEACTIVE;
  236.  
  237.         switch( ie->ie_Class )
  238.         {
  239.         case IECLASS_RAWMOUSE:
  240.             switch( ie->ie_Code )
  241.             {
  242.             case MENUDOWN:
  243.             retval = GMR_REUSE;
  244.             *((struct gpInput *)msg)->gpi_Termination = 0UL;
  245.             break;
  246.  
  247.             case SELECTUP:
  248.             if( EG(o)->Flags & GFLG_SELECTED )
  249.             {
  250.                 retval = GMR_NOREUSE | GMR_VERIFY;
  251.                 *((struct gpInput *)msg)->gpi_Termination = 1UL;
  252.             }
  253.             else
  254.             {
  255.                 retval = GMR_NOREUSE;
  256.                 *((struct gpInput *)msg)->gpi_Termination = 0UL;
  257.             } /* if */
  258.             break;
  259.  
  260.             case IECODE_NOBUTTON: {
  261.             struct gpHitTest gpht;
  262.  
  263.             gpht.MethodID      = GM_HITTEST;
  264.             gpht.gpht_GInfo   = gi;
  265.             gpht.gpht_Mouse.X = ((struct gpInput *)msg)->gpi_Mouse.X;
  266.             gpht.gpht_Mouse.Y = ((struct gpInput *)msg)->gpi_Mouse.Y;
  267.  
  268.             /*
  269.                 This case handles selection state toggling when the
  270.                 left button is depressed and the mouse is moved
  271.                 around on/off the gadget bounds.
  272.             */
  273.             if ( DoMethodA(o, (Msg)&gpht) == GMR_GADGETHIT )
  274.             {
  275.                 if ( (EG(o)->Flags & GFLG_SELECTED) == 0 )
  276.                 {
  277.                 struct RastPort *rp;
  278.  
  279.                 /* mouse is over gadget */
  280.                 EG(o)->Flags |= GFLG_SELECTED;
  281.  
  282.                 if ((rp = ObtainGIRPort(gi)))
  283.                 {
  284.                     DoMethod(o, GM_RENDER, gi, rp, GREDRAW_UPDATE);
  285.                     ReleaseGIRPort(rp);
  286.                 } /* if */
  287.                 } /* if */
  288.             }
  289.             else
  290.             {
  291.                 if ( (EG(o)->Flags & GFLG_SELECTED) != 0 )
  292.                 {
  293.                 struct RastPort *rp;
  294.  
  295.                 /* mouse is not over gadget */
  296.                 EG(o)->Flags &= ~GFLG_SELECTED;
  297.  
  298.                 if ((rp = ObtainGIRPort(gi)))
  299.                 {
  300.                     DoMethod(o, GM_RENDER, gi, rp, GREDRAW_UPDATE);
  301.                     ReleaseGIRPort(rp);
  302.                 } /* if */
  303.                 } /* if */
  304.             } /* if */
  305.             break; }
  306.  
  307.             } /* switch */
  308.  
  309.             break;
  310.  
  311.         case IECLASS_TIMER:
  312.             if (EG(o)->Flags & GFLG_SELECTED)
  313.             {
  314.             DoMethod(o, OM_NOTIFY, NULL, gi, OPUF_INTERIM);
  315.             } /* if */
  316.             break;
  317.         } /* switch */
  318.         }
  319.         else
  320.         {
  321.         /* if we get here something is *really* wrong */
  322.         retval = GMR_NOREUSE;
  323.         } /* if */
  324.     } /* if */
  325.     break;
  326.  
  327.     case GM_GOINACTIVE:
  328.     EG(o)->Flags &= ~GFLG_SELECTED;
  329.     {
  330.         struct GadgetInfo *gi = ((struct gpGoInactive *)msg)->gpgi_GInfo;
  331.  
  332.         if (gi)
  333.         {
  334.         struct RastPort *rp = ObtainGIRPort(gi);
  335.         if (rp)
  336.         {
  337.             DoMethod(o, GM_RENDER, gi, rp, GREDRAW_REDRAW);
  338.             ReleaseGIRPort(rp);
  339.  
  340.             DoMethod(o, OM_NOTIFY, NULL, gi, 0);
  341.         } /* if */
  342.         } /* if */
  343.     } /* if */
  344.     break;
  345.  
  346.     case OM_NEW:
  347.     retval = DoSuperMethodA(cl, o, msg);
  348.  
  349.     if (retval)
  350.     {
  351.         /* Handle our special tags - overrides defaults */
  352.         /* set_buttongclass(cl, (Object *)retval, (struct opSet *)msg); */
  353.     } /* if */
  354.     break;
  355.  
  356.     case OM_SET:
  357.     case OM_UPDATE:
  358.     retval = DoSuperMethodA(cl, o, msg);
  359.  
  360.     /* If we have been subclassed, OM_UPDATE should not cause a GM_RENDER
  361.         * because it would circumvent the subclass from fully overriding it.
  362.         * The check of cl == OCLASS(o) should fail if we have been
  363.         * subclassed, and we have gotten here via DoSuperMethodA().
  364.         */
  365.     if ( retval && ( msg->MethodID == OM_UPDATE ) && ( cl == OCLASS(o) ) )
  366.     {
  367.         struct GadgetInfo *gi = ((struct opSet *)msg)->ops_GInfo;
  368.         if (gi)
  369.         {
  370.         struct RastPort *rp = ObtainGIRPort(gi);
  371.         if (rp)
  372.         {
  373.             DoMethod(o, GM_RENDER, gi, rp, GREDRAW_REDRAW);
  374.             ReleaseGIRPort(rp);
  375.         } /* if */
  376.         } /* if */
  377.     } /* if */
  378.     break;
  379.  
  380.     default:
  381.     retval = DoSuperMethodA(cl, o, msg);
  382.     break;
  383.     } /* switch */
  384.  
  385.     return retval;
  386. }  /* dispatch_buttongclass */
  387.  
  388.  
  389. #undef IntuitionBase
  390.  
  391. /****************************************************************************/
  392.  
  393. /* Initialize our image class. */
  394. struct IClass *InitButtonGClass (struct IntuitionBase * IntuitionBase)
  395. {
  396.     struct IClass *cl = NULL;
  397.  
  398.     /* This is the code to make the buttongclass...
  399.     */
  400.     if ( (cl = MakeClass(BUTTONGCLASS, GADGETCLASS, NULL, 0, 0)) )
  401.     {
  402.     cl->cl_Dispatcher.h_Entry    = (APTR)AROS_ASMSYMNAME(dispatch_buttongclass);
  403.     cl->cl_Dispatcher.h_SubEntry = NULL;
  404.     cl->cl_UserData          = (IPTR)IntuitionBase;
  405.  
  406.     AddClass (cl);
  407.     }
  408.  
  409.     return (cl);
  410. }
  411.  
  412.