home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / prog / c / butclas1.lha / buttonclass.c next >
C/C++ Source or Header  |  1993-02-24  |  11KB  |  462 lines

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