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

  1. /* AROS frameiclass implementation
  2.  * 10/24/96 caldi@usa.nai.net
  3.  */
  4.  
  5. #include <exec/types.h>
  6.  
  7. #include <dos/dos.h>
  8. #include <dos/dosextens.h>
  9.  
  10. #include <intuition/intuition.h>
  11. #include <intuition/intuitionbase.h>
  12. #include <intuition/classes.h>
  13. #include <intuition/classusr.h>
  14. #include <intuition/imageclass.h>
  15. #include <intuition/cghooks.h>
  16. #include <intuition/icclass.h>
  17.  
  18. #include <graphics/gfxbase.h>
  19. #include <graphics/gfxmacros.h>
  20.  
  21. #include <utility/tagitem.h>
  22. #include <utility/hooks.h>
  23.  
  24. #include <clib/macros.h>
  25.  
  26. #include <proto/exec.h>
  27. #include <proto/intuition.h>
  28. #include <proto/graphics.h>
  29. #include <proto/utility.h>
  30.  
  31. #ifdef _AROS
  32. #include <aros/asmcall.h>
  33. #include <proto/alib.h>
  34. #include "intuition_intern.h"
  35. #endif
  36.  
  37. /****************************************************************************/
  38.  
  39. /* Some handy transparent base class object casting defines.
  40.  */
  41. #define G(o)  ((struct Gadget *)o)
  42. #define EG(o) ((struct ExtGadget *)o)
  43. #define IM(o) ((struct Image *)o)
  44.  
  45. /****************************************************************************/
  46.  
  47. /* FrameIClass specific instance data.
  48.  */
  49. struct FrameIData
  50. {
  51.     /* render bevel only with no fill? */
  52.     BOOL fid_EdgesOnly;
  53.  
  54.     /* inverted bevel pens? */
  55.     BOOL fid_Recessed;
  56.  
  57.     /* frame style? */
  58.     WORD fid_FrameType;
  59. };
  60.  
  61. /****************************************************************************/
  62.  
  63. #undef IntuitionBase
  64. #define IntuitionBase    ((struct IntuitionBase *)(cl->cl_UserData))
  65.  
  66. /* This is utility function used by frameiclass to draw a simple
  67.  * bevel.
  68.  */
  69. static void DrawFrame(
  70.     Class * cl,
  71.     struct RastPort *rport,
  72.     UWORD shine, UWORD shadow,
  73.     WORD left, WORD top, WORD width, WORD height,
  74.     BOOL thicken)
  75. {
  76.     /*
  77.     Here we attempt to render a bevel as quickly as possible using
  78.     as few system calls as possible. Note the ORDER of the rendering
  79.     and pen (or lack of) setting in important. This routine can be
  80.     useful alone as a basis for GadTools DrawBevelBox() perhaps, but
  81.     its real function is rendering the frameiclass components for the
  82.     various supported styles.
  83.  
  84.     It should be futher noted, on the native Amiga chipset, rendering
  85.     bevels via serious of RectFill()'s is potentially as much as two
  86.     times faster. However, in the case of AROS the implementation
  87.     of the graphics drivers would ofcourse be the determining factor.
  88.     Just as on the native OS, 3rd party gfx boards would be a factor.
  89.  
  90.     Additionally, if the frame metrics are changed here for whatever
  91.     reasons, you MUST also compensate the change in the frame class
  92.     render method, and framebox specifically the offset values.
  93.     */
  94.     height -= 1;
  95.     width  -= 1;
  96.  
  97.     /* Top/Left */
  98.     SetABPenDrMd(rport, shine, 0, JAM1);
  99.     Move(rport, left, top + height);
  100.     Draw(rport, left, top);
  101.     Draw(rport, left + width, top);
  102.  
  103.     /* Bottom/Right */
  104.     SetAPen(rport, shadow);
  105.     Draw(rport, left + width, top + height);
  106.     Draw(rport, left, top + height);
  107.  
  108.     if (thicken != FALSE)
  109.     {
  110.     /* Thicken Right Side */
  111.     Move(rport, left + width - 1, top + height - 1);
  112.     Draw(rport, left + width - 1, top + 1);
  113.  
  114.     /* Thicken Left Side */
  115.     SetAPen(rport, shine);
  116.     Move(rport, left + 1, top + height - 1);
  117.     Draw(rport, left + 1, top + 1);
  118.     } /* if */
  119. } /* DrawFrame */
  120.  
  121. /****************************************************************************/
  122.  
  123. /* frame render method */
  124. static ULONG draw_frameiclass(Class *cl, Object *o, struct impDraw *msg)
  125. {
  126.     struct FrameIData *fid = INST_DATA(cl, o);
  127.  
  128.     /*
  129.     Default pen array, this should be globally accessable from
  130.     all the boopsi objects, unless someone as a better idea...
  131.     */
  132.     UWORD default_pens[] =
  133.     {
  134.     1, /* detailPen      */
  135.     0, /* blockPen         */
  136.     1, /* textPen         */
  137.     2, /* shinePen         */
  138.     1, /* shadowPen      */
  139.     3, /* hiFillPen      */
  140.     1, /* hifilltextPen  */
  141.     0, /* backgroundPen  */
  142.     2  /* hilighttextPen */
  143.     };
  144.     ULONG retval;
  145.  
  146.     /* we will check the rastport present */
  147.     if(msg->imp_RPort != NULL)
  148.     {
  149.     UWORD *pens = default_pens;
  150.     UWORD loffset = 0, toffset = 0;
  151.     UWORD left, top;
  152.     UWORD shine, shadow;
  153.     BOOL selected;
  154.  
  155.     /* set up our rendering pens */
  156.     if (msg->imp_DrInfo)
  157.     {
  158.         /*
  159.         This test may not be necessary - and if that is the
  160.         case then this logic could be optimized a bit more.
  161.         */
  162.         if (msg->imp_DrInfo->dri_Pens)
  163.         {
  164.         pens = msg->imp_DrInfo->dri_Pens;
  165.         } /* if */
  166.  
  167.         /*
  168.         Fall back to mono color bevels if depth is only 1 bitplane.
  169.         */
  170.         if (msg->imp_DrInfo->dri_Depth == 1)
  171.         {
  172.         shine  = pens[SHADOWPEN];
  173.         }
  174.         else
  175.         {
  176.         shine  = pens[SHINEPEN];
  177.         } /* if */
  178.     }
  179.     else
  180.     {
  181.         shine  = pens[SHINEPEN];
  182.     } /* if */
  183.  
  184.     shadow    = pens[SHADOWPEN];
  185.  
  186.     switch(msg->imp_State)
  187.     {
  188.     case IDS_SELECTED:
  189.     case IDS_INACTIVESELECTED:
  190.         selected = TRUE;
  191.         break;
  192.  
  193.     default:
  194.         selected = FALSE;
  195.         break;
  196.     } /* switch */
  197.  
  198.     /*
  199.         I'm so clever :) We want to check if either of selected or
  200.         recessed is TRUE, and if so, swap the pens. However, if both
  201.         are true, they effectivly cancel each other out and we do
  202.         nothing. Rather than two compares against TRUE and a OR of the
  203.         results, pls the additional check to ignore the case where both
  204.         are TRUE, we will do an XOR of the bool's and check the result.
  205.         This should prove most efficient too.
  206.  
  207.  
  208.         Recess|select| XOR'd result
  209.         ------|------|-------
  210.           0   |  0     |  0
  211.         ------|------|-------
  212.           0   |  1     |  1
  213.         ------|------|-------
  214.           1   |  0     |  1
  215.         ------|------|-------
  216.           1   |  1     |  0
  217.         ------|------|-------
  218.     */
  219.  
  220.     if ( (fid->fid_Recessed ^ selected) != FALSE )
  221.     {
  222.         /* swap pens */
  223.         shine  ^= shadow;
  224.         shadow ^= shine;
  225.         shine  ^= shadow;
  226.     } /* if */
  227.  
  228.     left = IM(o)->LeftEdge + msg->imp_Offset.X;
  229.     top  = IM(o)->TopEdge  + msg->imp_Offset.Y;
  230.  
  231.     switch(fid->fid_FrameType)
  232.     {
  233.     case FRAME_DEFAULT:
  234.         toffset = 1;
  235.         loffset = 1;
  236.         DrawFrame(
  237.         cl,
  238.         msg->imp_RPort,
  239.         shine, shadow,
  240.         left, top,
  241.         IM(o)->Width, IM(o)->Height,
  242.         FALSE
  243.         );
  244.         break;
  245.  
  246.     case FRAME_BUTTON:
  247.         toffset = 1;
  248.         loffset = 2;
  249.         DrawFrame(
  250.         cl,
  251.         msg->imp_RPort,
  252.         shine, shadow,
  253.         left, top,
  254.         IM(o)->Width, IM(o)->Height,
  255.         TRUE
  256.         );
  257.         break;
  258.  
  259.     case FRAME_RIDGE:
  260.         toffset = 1;
  261.         loffset = 2;
  262.  
  263.         /* render outer pen-inverted thick bevel */
  264.         DrawFrame(
  265.         cl,
  266.         msg->imp_RPort,
  267.         shine, shadow,
  268.         left, top,
  269.         IM(o)->Width, IM(o)->Height,
  270.         TRUE
  271.         );
  272.  
  273.         /* render inner thick bevel */
  274.         DrawFrame(
  275.         cl,
  276.         msg->imp_RPort,
  277.         shadow, shine,
  278.         left + loffset, top + toffset,
  279.         IM(o)->Width - (loffset + loffset), IM(o)->Height - (toffset + toffset),
  280.         TRUE
  281.         );
  282.  
  283.         toffset += 1;
  284.         loffset += 2;
  285.         break;
  286.  
  287.     case FRAME_ICONDROPBOX:
  288.         toffset = 6;
  289.         loffset = 10;
  290.         /* not supported yet */
  291.         break;
  292.  
  293.     } /* switch */
  294.  
  295.     if(fid->fid_EdgesOnly == FALSE)
  296.     {
  297.         if(selected)
  298.         {
  299.         SetABPenDrMd(msg->imp_RPort, pens[FILLPEN], pens[BACKGROUNDPEN], JAM1);
  300.         }
  301.         else
  302.         {
  303.         SetABPenDrMd(msg->imp_RPort, pens[BACKGROUNDPEN], pens[BACKGROUNDPEN], JAM1);
  304.         } /* if */
  305.  
  306.         RectFill(msg->imp_RPort,
  307.         IM(o)->LeftEdge + loffset,
  308.         IM(o)->TopEdge  + toffset,
  309.         IM(o)->LeftEdge + IM(o)->Width  - (loffset+loffset),
  310.         IM(o)->TopEdge  + IM(o)->Height - (toffset+toffset)
  311.         );
  312.     } /* if */
  313.  
  314.     retval = 1UL;
  315.     }
  316.     else
  317.     {
  318.     /* return failure */
  319.     retval = 0UL;
  320.     } /* if */
  321.  
  322.     return retval;
  323. } /* draw_frameiclass */
  324.  
  325.  
  326. /****************************************************************************/
  327.  
  328. /* frame attribute setting method */
  329. static ULONG set_frameiclass(Class *cl, Object *o, struct opSet *msg)
  330. {
  331.     struct FrameIData *fid = INST_DATA(cl, o);
  332.  
  333.     struct TagItem *tstate = msg->ops_AttrList;
  334.     struct TagItem *tag;
  335.     ULONG retval = 0UL;
  336.  
  337.     while ((tag = NextTagItem(&tstate)))
  338.     {
  339.     switch(tag->ti_Tag)
  340.     {
  341.     case IA_Recessed:
  342.         fid->fid_Recessed    = (BOOL)( ( (BOOL)tag->ti_Data != FALSE ) ? TRUE : FALSE );
  343.         break;
  344.  
  345.     case IA_EdgesOnly:
  346.         fid->fid_EdgesOnly    = (BOOL)( ( (BOOL)tag->ti_Data != FALSE ) ? TRUE : FALSE );
  347.         break;
  348.  
  349.     case IA_FrameType:
  350.         /*
  351.         Data values for IA_FrameType (recognized by FrameIClass)
  352.  
  353.         FRAME_DEFAULT:    The standard V37-type frame, which has
  354.             thin edges.
  355.         FRAME_BUTTON:  Standard button gadget frames, having thicker
  356.             sides and edged corners.
  357.         FRAME_RIDGE:  A ridge such as used by standard string gadgets.
  358.             You can recess the ridge to get a groove image.
  359.         FRAME_ICONDROPBOX: A broad ridge which is the standard imagery
  360.             for areas in AppWindows where icons may be dropped.
  361.         */
  362.         fid->fid_FrameType = (WORD)tag->ti_Data;
  363.         break;
  364.  
  365.     } /* switch */
  366.     } /* while */
  367.  
  368.     return(retval);
  369. } /* set_frameiclass */
  370.  
  371. /****************************************************************************/
  372.  
  373. /* frameiclass framebox method */
  374. static ULONG framebox_frameiclass(Class *cl, Object *o, struct impFrameBox *msg)
  375. {
  376.     struct FrameIData *fid = INST_DATA(cl, o);
  377.  
  378.     if (msg->imp_FrameFlags & FRAMEF_SPECIFY)
  379.     {
  380.     /*
  381.         Would someone kindly explain RKM Libs page 898/899 in english :)
  382.         I'll just forget about this for the time being until I have
  383.         made more sence out of what is the "right thing" to do here.
  384.     */
  385.     }
  386.     else
  387.     {
  388.     switch(fid->fid_FrameType)
  389.     {
  390.     case FRAME_DEFAULT:
  391.         msg->imp_ContentsBox->Top     = msg->imp_FrameBox->Top    - 1;
  392.         msg->imp_ContentsBox->Left     = msg->imp_FrameBox->Left   - 1;
  393.         msg->imp_ContentsBox->Height = msg->imp_FrameBox->Height + 2;
  394.         msg->imp_ContentsBox->Width  = msg->imp_FrameBox->Width  + 2;
  395.         break;
  396.  
  397.     case FRAME_BUTTON:
  398.         msg->imp_ContentsBox->Top     = msg->imp_FrameBox->Top    - 1;
  399.         msg->imp_ContentsBox->Left     = msg->imp_FrameBox->Left   - 2;
  400.         msg->imp_ContentsBox->Height = msg->imp_FrameBox->Height + 2;
  401.         msg->imp_ContentsBox->Width  = msg->imp_FrameBox->Width  + 4;
  402.         break;
  403.  
  404.     case FRAME_RIDGE:
  405.         msg->imp_ContentsBox->Top     = msg->imp_FrameBox->Top    - 2;
  406.         msg->imp_ContentsBox->Left     = msg->imp_FrameBox->Left   - 4;
  407.         msg->imp_ContentsBox->Height = msg->imp_FrameBox->Height + 4;
  408.         msg->imp_ContentsBox->Width  = msg->imp_FrameBox->Width  + 8;
  409.         break;
  410.  
  411.     case FRAME_ICONDROPBOX:
  412.         msg->imp_ContentsBox->Top     = msg->imp_FrameBox->Top    - 6;
  413.         msg->imp_ContentsBox->Left     = msg->imp_FrameBox->Left   - 6;
  414.         msg->imp_ContentsBox->Height = msg->imp_FrameBox->Height + 12;
  415.         msg->imp_ContentsBox->Width  = msg->imp_FrameBox->Width  + 12;
  416.         break;
  417.     }
  418.     } /* if */
  419.  
  420.     return 1UL;
  421. } /* framebox_frameiclass */
  422.  
  423. /****************************************************************************/
  424.  
  425. /* frameiclass boopsi dispatcher
  426.  */
  427. AROS_UFH3(static IPTR, dispatch_frameiclass,
  428.     AROS_UFHA(Class *,  cl,  A0),
  429.     AROS_UFHA(Object *, o,   A2),
  430.     AROS_UFHA(Msg,      msg, A1)
  431. )
  432. {
  433.     IPTR retval = 0UL;
  434.  
  435.     switch(msg->MethodID)
  436.     {
  437.     case IM_FRAMEBOX:
  438.     retval = framebox_frameiclass(cl, o, (struct impFrameBox *)msg);
  439.     break;
  440.  
  441.     case IM_DRAWFRAME:
  442.     /* For this release, drawframe (wrongly) handled the same as... */
  443.  
  444.     case IM_DRAW:
  445.     retval = draw_frameiclass(cl, o, (struct impDraw *)msg);
  446.     break;
  447.  
  448.     case OM_SET:
  449.     retval = DoSuperMethodA(cl, o, msg);
  450.     retval += (IPTR)set_frameiclass(cl, o, (struct opSet *)msg);
  451.     break;
  452.  
  453.     case OM_NEW:
  454.     retval = DoSuperMethodA(cl, o, msg);
  455.     if (retval)
  456.     {
  457.         struct FrameIData *fid = INST_DATA(cl, retval);
  458.  
  459.         /* set some defaults */
  460.         fid->fid_EdgesOnly = TRUE;
  461.         fid->fid_Recessed  = FALSE;
  462.         fid->fid_FrameType = FRAME_DEFAULT;
  463.  
  464.         /* Handle our special tags - overrides defaults */
  465.         set_frameiclass(cl, (Object*)retval, (struct opSet *)msg);
  466.     }
  467.     break;
  468.  
  469.     default:
  470.     retval = DoSuperMethodA(cl, o, msg);
  471.     break;
  472.     } /* switch */
  473.  
  474.     return retval;
  475. }  /* dispatch_frameiclass */
  476.  
  477. #undef IntuitionBase
  478.  
  479. /****************************************************************************/
  480.  
  481. /* Initialize our image class. */
  482. struct IClass *InitFrameIClass (struct IntuitionBase * IntuitionBase)
  483. {
  484.     struct IClass *cl = NULL;
  485.  
  486.     /* This is the code to make the frameiclass...
  487.     */
  488.     if ((cl = MakeClass(FRAMEICLASS, IMAGECLASS, NULL, sizeof(struct FrameIData), 0)))
  489.     {
  490.     cl->cl_Dispatcher.h_Entry    = (APTR)AROS_ASMSYMNAME(dispatch_frameiclass);
  491.     cl->cl_Dispatcher.h_SubEntry = NULL;
  492.     cl->cl_UserData          = (IPTR)IntuitionBase;
  493.  
  494.     AddClass (cl);
  495.     }
  496.  
  497.     return (cl);
  498. }
  499.  
  500.