home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / BUTCLAS3.ZIP / BUTTONCL.C next >
C/C++ Source or Header  |  1993-11-07  |  13KB  |  526 lines

  1. #include "headers.h"
  2.  
  3. #include "buttonclass.h"
  4.  
  5. #define FLAG_DRAWER    1
  6.  
  7. struct ButtonData {
  8.     BOOL  lastState;        // Refresh only if state changes
  9.     UWORD color;            // Foreground color
  10.     UWORD backcolor;        // Background color
  11.     UWORD flags;            // Currently only DRAWER
  12.     UBYTE *text;            // Text for gadget
  13.     struct Image *image;    // Image for gadget
  14.     struct Image *simage;    // Select Image for gadget
  15. };
  16.  
  17. struct ClassGlobalData {
  18.     struct Library *SysBase;
  19.     struct Library *IntuitionBase;
  20.     struct Library *UtilityBase;
  21.     struct Library *GfxBase;
  22.     struct TextFont *textFont;
  23. };
  24. typedef struct ClassGlobalData CGLOB;
  25.  
  26.  
  27. #define D(x) ;
  28.  
  29. #define REG(x) register __ ## x
  30.  
  31. extern ULONG __stdargs DoSuperMethodA( struct IClass *cl, Object *obj, Msg message );
  32. extern ULONG DoMethod( Object *obj, unsigned long MethodID, ... );
  33. static ULONG __asm dispatchButtonGadget(REG(a0) Class *cl, REG(a2) Object *o, REG(a1) Msg msg);
  34. static ULONG RenderButton(CGLOB *z, Class *cl, struct Gadget *g, struct gpRender *msg, struct ButtonData *inst, BOOL sel);
  35.  
  36. #define IntuitionBase    z->IntuitionBase
  37. #define UtilityBase        z->UtilityBase
  38. #define GfxBase            z->GfxBase
  39.  
  40. Class *initButtonGadgetClass(struct Library *IBase, struct Library *UBase, struct Library *GBase)
  41. {
  42.   Class *cl;
  43.   CGLOB *z;
  44.   struct Library *SysBase= *((void **)4L);
  45.  
  46.     z= AllocVec(sizeof(CGLOB), MEMF_CLEAR);
  47.     if( z )
  48.         {
  49.         z->SysBase   = SysBase;
  50.         IntuitionBase= IBase;
  51.         UtilityBase  = UBase;
  52.         GfxBase      = GBase;
  53.         if( cl = MakeClass( NULL, "gadgetclass", NULL, sizeof(struct ButtonData), 0) )
  54.             {
  55.             cl->cl_Dispatcher.h_Entry = (ULONG(*)()) dispatchButtonGadget;
  56.             cl->cl_Dispatcher.h_Data  = z;
  57.             return(cl);
  58.             }
  59.         FreeVec(z);
  60.         }
  61.     return(NULL);
  62. }
  63. #define SysBase            z->SysBase
  64.  
  65. BOOL freeButtonGadgetClass( Class *cl )
  66. {
  67.   CGLOB *z= cl->cl_Dispatcher.h_Data;
  68.   BOOL retval;
  69.  
  70.     retval= FreeClass(cl);
  71.     FreeVec(z);
  72.     return( retval );
  73. }
  74.  
  75. static ULONG __asm dispatchButtonGadget(REG(a0) Class *cl, REG(a2) Object *o, REG(a1) Msg msg)
  76. {
  77.   CGLOB  *z= cl->cl_Dispatcher.h_Data;
  78.   struct Gadget *g= (struct Gadget *)o;
  79.   struct gpInput *gpi = (struct gpInput *)msg;
  80.   struct InputEvent *ie;
  81.   struct RastPort *rp;
  82.   struct ButtonData *inst;
  83.   struct TagItem *ti;
  84.   struct opGet *opget;
  85.   ULONG retval;
  86.   Object *object;
  87.  
  88.  
  89.     switch( msg->MethodID )
  90.         {
  91.         case OM_NEW:
  92.             D( kprintf("OM_NEW\n"); )
  93.             if( object = (Object *)DoSuperMethodA(cl, o, msg) )
  94.                 {
  95.                 ti= ((struct opSet *)msg)->ops_AttrList;
  96.  
  97.                 inst= INST_DATA(cl, object);
  98.                 inst->lastState=0;
  99.                 inst->text = (UBYTE *)GetTagData(BUT_Text, NULL, ti);
  100.                 inst->color= (UWORD)GetTagData(BUT_Color, ~0, ti);
  101.                 inst->backcolor= (UWORD) GetTagData(BUT_BackColor, ~0, ti);
  102.                 inst->image = (struct Image *) GetTagData(BUT_Image, 0, ti);
  103.                 inst->simage= (struct Image *) GetTagData(BUT_SelectImage, 0, ti);
  104.                 inst->flags = (WORD)(GetTagData(BUT_Drawer, 0, ti) ? FLAG_DRAWER : 0);
  105.                 z->textFont= (struct TextFont *) GetTagData(BUT_TextFont, 0, ti);
  106.                 }
  107.             retval= (ULONG)object;
  108.             break;
  109.         case GM_HITTEST:
  110.             D( kprintf("GM_HITEST\n"); )
  111.             retval = GMR_GADGETHIT;
  112.             break;
  113.         case GM_GOACTIVE:
  114.             D( kprintf("GM_GOACTIVE\n"); )
  115.             inst= INST_DATA(cl, o);
  116.             if( gpi->gpi_IEvent && !(g->Flags & GFLG_DISABLED) )
  117.                 {
  118.                 g->Flags |= GFLG_SELECTED;
  119.                 RenderButton(z, cl, g, (struct gpRender *)msg, inst, g->Flags & GFLG_SELECTED);
  120.                 retval=  GMR_MEACTIVE;
  121.                 }
  122.             else
  123.                 {
  124.                 retval= GMR_NOREUSE;
  125.                 }
  126.             break;
  127.         case GM_RENDER:
  128.             D( kprintf("GM_RENDER\n"); )
  129.             inst= INST_DATA(cl, o);
  130.             retval= RenderButton(z, cl, g, (struct gpRender *)msg, inst, g->Flags & GFLG_SELECTED);
  131.             break;
  132.         case GM_HANDLEINPUT:
  133.             D( kprintf("GM_HANDLEINPUT\n"); )
  134.             retval= GMR_MEACTIVE;
  135.  
  136.             ie= gpi->gpi_IEvent;
  137.             if( ie == NULL ) break;
  138.             switch( ie->ie_Class )
  139.                 {
  140.                 case IECLASS_RAWMOUSE:
  141.                     switch( ie->ie_Code )
  142.                         {
  143.                         case SELECTUP:
  144.                             if( (gpi->gpi_Mouse.X < 0 ) ||
  145.                                 (gpi->gpi_Mouse.X > g->Width) ||
  146.                                 (gpi->gpi_Mouse.Y < 0 ) ||
  147.                                 (gpi->gpi_Mouse.Y > g->Height) )
  148.                                 {
  149.                                 retval= GMR_REUSE;
  150.                                 }
  151.                             else
  152.                                 {
  153.                                 retval= GMR_NOREUSE | GMR_VERIFY;
  154.                                 }
  155.                             break;
  156.                         case MENUDOWN:
  157.                             retval= GMR_NOREUSE;
  158.                             break;
  159.                         case IECODE_NOBUTTON:
  160.                             inst= INST_DATA(cl, o);
  161.  
  162.                             if( (gpi->gpi_Mouse.X < 0 ) ||
  163.                                 (gpi->gpi_Mouse.X > g->Width) ||
  164.                                 (gpi->gpi_Mouse.Y < 0 ) ||
  165.                                 (gpi->gpi_Mouse.Y > g->Height) )
  166.                                 {
  167.                                 if( inst->lastState )
  168.                                     {
  169.                                     g->Flags &= ~GFLG_SELECTED;
  170.                                     RenderButton(z, cl, g, (struct gpRender *)msg, inst, FALSE);
  171.                                     inst->lastState=FALSE;
  172.                                     }
  173.                                 }
  174.                             else
  175.                                 {
  176.                                 if( !inst->lastState )
  177.                                     {
  178.                                     g->Flags |= GFLG_SELECTED;
  179.                                     RenderButton(z, cl, g, (struct gpRender *)msg, inst, TRUE);
  180.                                     inst->lastState=TRUE;
  181.                                     }
  182.                                 }
  183.                             break;
  184.                         }
  185.                     break;
  186.                 }
  187.             break;
  188.         case GM_GOINACTIVE:
  189.             D( kprintf("GM_GOINACTIVE\n"); )
  190.             g->Flags &= ~GFLG_SELECTED;
  191.             inst= INST_DATA(cl, o);
  192.             retval= RenderButton(z, cl, g, (struct gpRender *)msg, inst, g->Flags & GFLG_SELECTED);
  193.             break;            
  194.         case OM_SET:
  195.             D( kprintf("OM_SET\n"); )
  196.             ti= ((struct opSet *)msg)->ops_AttrList;
  197.             if( FindTagItem(GA_Width,  ti) ||
  198.                 FindTagItem(GA_Height, ti) ||
  199.                 FindTagItem(GA_Top,    ti) ||
  200.                 FindTagItem(GA_Left,   ti) ||
  201.                 FindTagItem(BUT_Text,  ti) ||
  202.                 FindTagItem(BUT_Color, ti) ||
  203.                 FindTagItem(BUT_BackColor, ti) ||
  204.                 FindTagItem(BUT_Image, ti) ||
  205.                 FindTagItem(BUT_SelectImage, ti) ||
  206.                 FindTagItem(BUT_Drawer, ti) )
  207.                 {
  208.                 WORD x,y,w,h;
  209.                 
  210.                 x= g->LeftEdge;
  211.                 y= g->TopEdge;
  212.                 w= g->Width;
  213.                 h= g->Height;
  214.                 
  215.                 retval= DoSuperMethodA(cl, o, msg);
  216.  
  217.                 if( rp=ObtainGIRPort( ((struct opSet *)msg)->ops_GInfo) )
  218.                     {
  219.                     UWORD *pens= ((struct opSet *)msg)->ops_GInfo->gi_DrInfo->dri_Pens;
  220.                     struct TagItem *tmp;
  221.                     
  222.                     if( x!=g->LeftEdge || y!=g->TopEdge || w!=g->Width || h!=g->Height )
  223.                         {
  224.                         SetAPen(rp, pens[BACKGROUNDPEN]);
  225.                         SetDrMd(rp, JAM1);
  226.                         RectFill(rp, x, y, x+w, y+h);
  227.                         }
  228.  
  229.                     inst= INST_DATA(cl, o);
  230.                     inst->text = (UBYTE *)GetTagData(BUT_Text, (ULONG)inst->text, ti);
  231.                     inst->color= (UWORD)GetTagData(BUT_Color, inst->color, ti);
  232.                     inst->backcolor= (UWORD) GetTagData(BUT_BackColor, inst->backcolor, ti);
  233.                     z->textFont= (struct TextFont *)GetTagData(BUT_TextFont, (ULONG)z->textFont, ti);
  234.                     inst->image = (struct Image *) GetTagData(BUT_Image, (ULONG)inst->image, ti);
  235.                     inst->simage= (struct Image *) GetTagData(BUT_SelectImage, (ULONG)inst->simage, ti);
  236.                     if( tmp=FindTagItem(BUT_Drawer, ti) )
  237.                         {
  238.                         inst->flags = ( tmp->ti_Data ? FLAG_DRAWER : 0);
  239.                         }
  240.  
  241.                     DoMethod(o, GM_RENDER, ((struct opSet *)msg)->ops_GInfo, rp, GREDRAW_REDRAW);
  242.                     ReleaseGIRPort(rp);
  243.                     }
  244.                 }
  245.             else if( FindTagItem(GA_Selected, ti) ||
  246.                      FindTagItem(GA_Disabled, ti) )
  247.                 {
  248.                 /*
  249.                  * GA_Selected and GA_Disabled need a refresh of the gadget.
  250.                  * The parent class will set the selected or disabled bits
  251.                  * of the gadget->Flags.
  252.                  */
  253.                 retval= DoSuperMethodA(cl, o, msg);
  254.  
  255.                 if( rp=ObtainGIRPort( ((struct opSet *)msg)->ops_GInfo) )
  256.                     {
  257.                     DoMethod(o, GM_RENDER, ((struct opSet *)msg)->ops_GInfo, rp, GREDRAW_REDRAW);
  258.                     ReleaseGIRPort(rp);
  259.                     }
  260.                 }
  261.             else
  262.                 {
  263.                 retval= DoSuperMethodA(cl, o, msg);
  264.                 }
  265.             break;
  266.         case OM_GET:
  267.             D( kprintf("OM_GET\n"); )
  268.             opget= (struct opGet *)msg;
  269.             inst= INST_DATA(cl, o);
  270.             retval= TRUE;
  271.             switch( opget->opg_AttrID )
  272.                 {
  273.                 case BUT_Text:
  274.                     *(opget->opg_Storage)= (ULONG)inst->text;
  275.                     break;
  276.                 case BUT_Color:
  277.                     *(opget->opg_Storage)= (ULONG)inst->color;
  278.                     break;
  279.                 case BUT_BackColor:
  280.                     *(opget->opg_Storage)= (ULONG)inst->backcolor;
  281.                     break;
  282.                 case BUT_Image:
  283.                     *(opget->opg_Storage)= (ULONG)inst->image;
  284.                     break;
  285.                 case BUT_SelectImage:
  286.                     *(opget->opg_Storage)= (ULONG)inst->simage;
  287.                     break;
  288.                 case BUT_Drawer:
  289.                     *(opget->opg_Storage)= (ULONG)( inst->flags & FLAG_DRAWER );
  290.                     break;
  291.                 case BUT_TextFont:
  292.                     *(opget->opg_Storage)= (ULONG)z->textFont;
  293.                     break;
  294.                 default:
  295.                     retval= DoSuperMethodA(cl, o, msg);
  296.                 }
  297.             break;
  298.         default:
  299.             D( kprintf("DEFAULT\n"); )
  300.             retval= DoSuperMethodA(cl, o ,msg);
  301.             break;
  302.         }
  303.     return( retval );
  304. }
  305.  
  306. static void drawPoints(CGLOB *z, struct RastPort *rp, WORD b_x, WORD b_y, WORD n, const WORD *pt)
  307. {
  308.     while( n-- )
  309.         {
  310.         Draw(rp, b_x + *pt, b_y + *(pt+1));
  311.         pt += 2;
  312.         }
  313. }
  314.  
  315. static const WORD draw_points[] = { 11,0, 11,-6, 9,-8, 6,-8, 4,-6, 0,-6, 0,-1, 1,-1, 1,-5, 5,-5, 6,-4, 10,-4};
  316.  
  317. static UWORD strUcpy(UBYTE *dest, UBYTE *src)
  318. {
  319.   UBYTE *start=src;
  320.   UWORD uline=0;
  321.  
  322.     while( *src )
  323.         {
  324.         if( *src == '_' )
  325.             {
  326.             uline = src - start + 1;
  327.             src++;
  328.             }
  329.         else
  330.             {
  331.             *dest++ = *src++;
  332.             }
  333.         }
  334.     return(uline);
  335. }
  336.  
  337. static ULONG RenderButton(CGLOB *z, Class *cl, struct Gadget *g, struct gpRender *msg, struct ButtonData *inst, BOOL sel)
  338. {
  339.   struct RastPort *rp;
  340.   ULONG retval=TRUE;
  341.   UWORD *pens= msg->gpr_GInfo->gi_DrInfo->dri_Pens;
  342.   UWORD slen;
  343.   struct TextExtent te;
  344.  
  345.     if( msg->MethodID == GM_RENDER )
  346.         {
  347.         rp= msg->gpr_RPort;
  348.         }
  349.     else
  350.         {
  351.         rp= ObtainGIRPort(msg->gpr_GInfo);
  352.         }
  353.  
  354.     if( rp )
  355.         {
  356.         UBYTE back, shine, shadow, text;
  357.         UWORD x, y, w, h, text_x, text_y;
  358.         UBYTE *str=NULL;
  359.         UWORD underline;
  360.         UWORD depth= 1 << rp->BitMap->Depth;
  361.         UBYTE oldAPen, oldDrMd;
  362.         struct TextFont *oldTextFont;
  363.         ULONG state;
  364.  
  365.         oldAPen= rp->FgPen;
  366.         oldDrMd= rp->DrawMode;
  367.         oldTextFont= rp->Font;
  368.  
  369.         if( sel )
  370.             {
  371.             back  = pens[FILLPEN];
  372.             shine = pens[SHADOWPEN];
  373.             shadow= pens[SHINEPEN];
  374.             text  = pens[FILLTEXTPEN];
  375.             }
  376.         else
  377.             {
  378.             back  = pens[BACKGROUNDPEN];
  379.             shine = pens[SHINEPEN];
  380.             shadow= pens[SHADOWPEN];
  381.             text  = pens[TEXTPEN];
  382.             if( inst->backcolor != (UWORD)~0 )
  383.                 {
  384.                 back= inst->backcolor;
  385.                 }
  386.             }
  387.         if( inst->color != (UWORD)~0 )
  388.             {
  389.             text= inst->color;
  390.             }
  391.         if( (back % depth) == (text % depth) )
  392.             {
  393.             if( (back % depth) == 0 )
  394.                 {
  395.                 text= 1;
  396.                 }
  397.             else
  398.                 {
  399.                 text= 0;
  400.                 }
  401.             }
  402.  
  403.  
  404.         x= g->LeftEdge;    
  405.         y= g->TopEdge;
  406.         w= g->Width-1;
  407.         h= g->Height-1;
  408.  
  409.         if( inst->text )
  410.             {
  411.             if( z->textFont ) SetFont(rp, z->textFont);
  412.             slen= strlen(inst->text);
  413.  
  414.             if( str = AllocVec(slen, MEMF_ANY) )
  415.                 {
  416.                 underline = strUcpy(str, inst->text);
  417.                 if( underline ) slen--;
  418.  
  419.                 TextExtent(rp, str, slen, &te);
  420.                 text_x= x + (w+1)/2 - te.te_Width/2;
  421.                 text_y= y + (h+1)/2 - (te.te_Extent.MaxY - te.te_Extent.MinY + 1)/2 - te.te_Extent.MinY;
  422.                 }
  423.             }
  424.  
  425.         SetDrMd(rp, JAM1);
  426.         SetAPen(rp, back);
  427.         RectFill( rp, x+2, y+1, x+w-2, y+h-1 );
  428.  
  429.         SetAPen(rp, shadow);
  430.         RectFill(rp, x+1, y+h, x+w, y+h);
  431.         RectFill(rp, x+w-1, y+1, x+w-1, y+h);
  432.         RectFill(rp, x+w, y, x+w, y+h);
  433.         
  434.         if( str )
  435.             {
  436.             SetAPen(rp, text);
  437.             Move(rp, text_x, text_y);
  438.             Text(rp, str, slen);
  439.  
  440.             if( underline )
  441.                 {
  442.                 slen= TextLength(rp, str, underline - 1);
  443.                 text_x += slen;
  444.                 slen= TextLength(rp, str + underline - 1, 1);
  445.                 RectFill(rp, text_x, text_y + te.te_Extent.MaxY,
  446.                             text_x + slen - 1, text_y + te.te_Extent.MaxY);
  447.                 }
  448.             }
  449.  
  450.         if( inst->image || inst->simage )
  451.             {
  452.             UWORD image_x, image_y;
  453.             struct Image *image;
  454.  
  455.             if( g->Flags & GFLG_SELECTED )
  456.                 {
  457.                 if( inst->simage )
  458.                     {
  459.                     state= IDS_NORMAL;
  460.                     image= inst->simage;
  461.                     }
  462.                 else
  463.                     {
  464.                     state= IDS_SELECTED;
  465.                     image= inst->image;
  466.                     }
  467.                 }
  468.             else
  469.                 {
  470.                 state= IDS_NORMAL;
  471.                 image= inst->image;
  472.                 }
  473.             image_x= x + (w+1)/2 - image->Width/2;
  474.             image_y= y + (h+1)/2 - image->Height/2;
  475.             DrawImageState(rp, image, image_x, image_y, state, msg->gpr_GInfo->gi_DrInfo);
  476.             }
  477.         if( inst->flags & FLAG_DRAWER )
  478.             {
  479.             WORD b_x, b_y;
  480.  
  481.             SetAPen(rp, text);
  482.             b_x = x + (w+1)/2 - 6;
  483.             b_y = y + (h+1)/2 + 3;
  484.             Move(rp, b_x, b_y );
  485.             drawPoints(z, rp, b_x, b_y, 12, draw_points);
  486.             }
  487.  
  488.         SetAPen(rp, shine);
  489.         RectFill(rp, x, y, x+w-1, y);
  490.         RectFill(rp, x, y+1, x, y+h);
  491.         RectFill(rp, x+1, y+1, x+1, y+h-1);
  492.  
  493.         if( g->Flags & GFLG_DISABLED )
  494.             {
  495.             UWORD area_pattern[]= {0x1111, 0x4444};
  496.             UWORD *oldAfPt;
  497.             UBYTE oldAfSize;
  498.  
  499.             oldAfPt= rp->AreaPtrn;
  500.             oldAfSize= rp->AreaPtSz;
  501.  
  502.             SetAPen(rp, text);
  503.             SetAfPt(rp, area_pattern, 1);
  504.             RectFill(rp, x, y, x+w, y+h);
  505.  
  506.             SetAfPt(rp, oldAfPt, oldAfSize);
  507.             }
  508.  
  509.         SetAPen(rp, oldAPen);
  510.         SetDrMd(rp, oldDrMd);
  511.         SetFont(rp, oldTextFont);
  512.  
  513.         FreeVec(str);
  514.  
  515.         if( msg->MethodID != GM_RENDER )
  516.             {
  517.             ReleaseGIRPort(rp);
  518.             }
  519.         }
  520.     else
  521.         {
  522.         retval= FALSE;
  523.         }
  524.     return( retval );
  525. }
  526.