home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / C / OTL-MC7.DMS / in.adf / classsource.lha / ClassSource / BOOPSI / gadgets / radio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-12  |  12.0 KB  |  500 lines

  1. #include <classes/BOOPSI/gadgets.h>
  2. #include <classes/BOOPSI/boopsilib.h>
  3.  
  4. #pragma -
  5. #include <pragma/utility_lib.h>
  6. #include <clib/alib_protos.h>
  7. #include <pragma/intuition_lib.h>
  8. #include <pragma/graphics_lib.h>
  9. #pragma +
  10. #include <graphics/gfxmacros.h>
  11. #include <string.h>
  12.  
  13. struct InstanceData {
  14.     struct TextAttr *tattr;
  15.     struct TextFont *font;
  16.     ULONG labelsplace;
  17.     STRPTR *labels;
  18.     ULONG labelscount;
  19.     WORD leftborder;
  20.     WORD rightborder;
  21.     WORD topborder;
  22.     WORD bottomborder;
  23.     ULONG active;
  24.     UWORD lineheight;
  25.     WORD spacing;
  26.     UBYTE labelmark;
  27.     struct LabelText *label;
  28. };
  29.  
  30. RadioClass::RadioClass()
  31.     : BoopsiClass(sizeof(struct InstanceData),(ULONG (*)()) &dispatcher,GADGETCLASS,NULL)
  32. {
  33. }
  34.  
  35. ULONG RadioClass::dispatcher(Class *cl, Object *o, Msg msg)
  36. {
  37.     struct InstanceData *data;
  38.     ULONG retval = FALSE;
  39.     switch (msg->MethodID)
  40.     {
  41.         case OM_NEW:
  42.         {
  43.             Object *object;
  44.             if (object = (Object *) DoSuperMethodA(cl,o,msg))
  45.             {
  46.                 data = (struct InstanceData *) INST_DATA(cl,object);
  47.                 data->tattr = NULL;
  48.                 data->font = NULL;
  49.                 data->labelsplace = RD_LabelsRight;
  50.                 data->labels = NULL;
  51.                 data->leftborder = 0;
  52.                 data->rightborder = 0;
  53.                 data->topborder = 0;
  54.                 data->bottomborder = 0;
  55.                 data->active = 0;
  56.                 data->spacing = 0;
  57.                 data->labelmark = '_';
  58.                 TagItemCursorC tic(((struct opSet *) msg)->ops_AttrList);
  59.                 while (!tic.isDone()) {
  60.                     /* register */ ULONG ticData = tic.itemData();
  61.                     switch (tic.itemTag())
  62.                     {
  63.                         case RDA_Font:
  64.                             data->tattr = (struct TextAttr *) ticData;
  65.                             break;
  66.                         case RDA_LabelsPlace:
  67.                             data->labelsplace = (ULONG) ticData;
  68.                             break;
  69.                         case RDA_Labels:
  70.                             data->labels = (STRPTR *) ticData;
  71.                             break;
  72.                         case RDA_Active:
  73.                             data->active = (ULONG) ticData;
  74.                             break;
  75.                         case RDA_Spacing:
  76.                             data->spacing = (WORD) ticData;
  77.                             break;
  78.                         case RDA_LabelMark:
  79.                             data->labelmark = (UBYTE) ticData;
  80.                             break;
  81.                         default:
  82.                             break;
  83.                     };
  84.                     tic.next();
  85.                 };
  86.                 if (data->tattr)
  87.                 {
  88.                     data->font = OpenFont(data->tattr);
  89.                 };
  90.                 data->label = AllocLText(
  91.                     (STRPTR) ((struct Gadget *) object)->GadgetText,
  92.                     data->tattr,1,0,JAM2,data->labelmark);
  93.                 data->labelscount = countLabels(data->labels);
  94.                 calcBorders(cl,(struct Gadget *) object,data);
  95.                 retval = (ULONG) object;
  96.             };
  97.             break;
  98.         };
  99.         case OM_DISPOSE:
  100.         {
  101.             data = (struct InstanceData *) INST_DATA(cl,o);
  102.             if (data->font)
  103.                 CloseFont(data->font);
  104.             FreeLText(data->label);
  105.             retval = DoSuperMethodA(cl,o,msg);
  106.             break;
  107.         };
  108.         case OM_GET:
  109.         {
  110.             data = (struct InstanceData *) INST_DATA(cl,o);
  111.             switch (((struct opGet *) msg)->opg_AttrID)
  112.             {
  113.                 case GA_Left:
  114.                     *(((struct opGet *) msg)->opg_Storage) = ((struct Gadget *) o)->LeftEdge;
  115.                     retval = TRUE;
  116.                     break;
  117.                 case GA_Top:
  118.                     *(((struct opGet *) msg)->opg_Storage) = ((struct Gadget *) o)->TopEdge;
  119.                     retval = TRUE;
  120.                     break;
  121.                 case GA_Width:
  122.                     *(((struct opGet *) msg)->opg_Storage) = ((struct Gadget *) o)->Width;
  123.                     retval = TRUE;
  124.                     break;
  125.                 case GA_Height:
  126.                     *(((struct opGet *) msg)->opg_Storage) = ((struct Gadget *) o)->Height;
  127.                     retval = TRUE;
  128.                     break;
  129.                 case RDA_Font:
  130.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->tattr;
  131.                     retval = TRUE;
  132.                     break;
  133.                 case RDA_LabelsPlace:
  134.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->labelsplace;
  135.                     retval = TRUE;
  136.                     break;
  137.                 case RDA_Labels:
  138.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->labels;
  139.                     retval = TRUE;
  140.                     break;
  141.                 case RDA_LeftBorder:
  142.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->leftborder;
  143.                     retval = TRUE;
  144.                     break;
  145.                 case RDA_RightBorder:
  146.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->rightborder;
  147.                     retval = TRUE;
  148.                     break;
  149.                 case RDA_TopBorder:
  150.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->topborder;
  151.                     retval = TRUE;
  152.                     break;
  153.                 case RDA_BottomBorder:
  154.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->bottomborder;
  155.                     retval = TRUE;
  156.                     break;
  157.                 case RDA_AutoWidth:
  158.                     *(((struct opGet *) msg)->opg_Storage) =
  159.                         (ULONG) calcWidth(cl,(struct Gadget *) o, data);
  160.                     retval = TRUE;
  161.                     break;
  162.                 case RDA_AutoHeight:
  163.                     *(((struct opGet *) msg)->opg_Storage) =
  164.                         (ULONG) calcHeight(cl,(struct Gadget *) o, data);
  165.                     retval = TRUE;
  166.                     break;
  167.                 case RDA_Active:
  168.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->active;
  169.                     retval = TRUE;
  170.                     break;
  171.                 case RDA_Spacing:
  172.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->spacing;
  173.                     retval = TRUE;
  174.                     break;
  175.                 case RDA_LabelMark:
  176.                     *(((struct opGet *) msg)->opg_Storage) = (ULONG) data->labelmark;
  177.                     retval = TRUE;
  178.                     break;
  179.                 default:
  180.                     retval = DoSuperMethodA(cl,o,msg);
  181.                     break;
  182.             };
  183.             break;
  184.         };
  185.         case OM_SET:
  186.         {
  187.             data = (struct InstanceData *) INST_DATA(cl,o);
  188.             BOOL renderIt = FALSE;
  189.             TagItemCursorC tic(((struct opSet *) msg)->ops_AttrList);
  190.             while (!tic.isDone()) {
  191.                 /* register */ ULONG ticData = tic.itemData();
  192.                 switch (tic.itemTag())
  193.                 {
  194.                     case RDA_Font:
  195.                         data->tattr = (struct TextAttr *) ticData;
  196.                         if (data->font)
  197.                         {
  198.                             CloseFont(data->font);
  199.                             data->font = NULL;
  200.                         };
  201.                         if (data->tattr)
  202.                             data->font = OpenFont(data->tattr);
  203.                         ChangeLTextFont(data->label,data->tattr);
  204.                         calcBorders(cl,(struct Gadget *) o,data);
  205.                         break;
  206.                     case RDA_Active:
  207.                         data->active = (ULONG) ticData;
  208.                         renderIt = TRUE;
  209.                         break;
  210.                     case RDA_Next:
  211.                         (data->active)++;
  212.                         if (data->active >= data->labelscount)
  213.                             data->active = 0;
  214.                         renderIt = TRUE;
  215.                         break;
  216.                     case RDA_Prev:
  217.                         if (data->active == 0)
  218.                             data->active = data->labelscount - 1
  219.                         else
  220.                             (data->active)--;
  221.                         renderIt = TRUE;
  222.                         break;
  223.                     default:
  224.                         break;
  225.                 };
  226.                 tic.next();
  227.             };
  228.             retval = DoSuperMethodA(cl,o,msg);
  229.             if (renderIt)
  230.                 render(cl,(struct Gadget *) o,(struct gpRender *) msg,data);
  231.             break;
  232.         };
  233.         case GM_RENDER:
  234.         {
  235.             data = (struct InstanceData *) INST_DATA(cl,o);
  236.             retval = render(cl,(struct Gadget *) o,
  237.                 (struct gpRender *) msg,data);
  238.             break;
  239.         };
  240.         case GM_HITTEST:
  241.         {
  242.             retval = GMR_GADGETHIT;
  243.             break;
  244.         };
  245.         case GM_GOACTIVE:
  246.         {
  247.             data = (struct InstanceData *) INST_DATA(cl,o);
  248.             if (((struct gpInput *) msg)->gpi_IEvent)
  249.             {
  250.                 ((struct Gadget *) o)->Flags |= GFLG_SELECTED;
  251.                 if (data->labelscount > 0)
  252.                 {
  253.                     struct gpInput *gpi = (struct gpInput *) msg;
  254.                     UWORD pixelheight = ((struct Gadget *) o)->Height / data->labelscount;
  255.                     data->active = gpi->gpi_Mouse.Y / pixelheight
  256.                 };
  257.                 render(cl,(struct Gadget *) o,
  258.                     (struct gpRender *) msg,data);
  259.                 retval = GMR_NOREUSE;
  260.             }
  261.             else
  262.                 retval = GMR_NOREUSE;
  263.             break;
  264.         };
  265.         case GM_GOINACTIVE:
  266.         {
  267.             data = (struct InstanceData *) INST_DATA(cl,o);
  268.             ((struct Gadget *) o)->Flags &= ~GFLG_SELECTED;
  269.             render(cl,(struct Gadget *) o,
  270.                 (struct gpRender *) msg,data);
  271.             break;
  272.         };
  273.         case GM_HANDLEINPUT:
  274.         {
  275.             data = (struct InstanceData *) INST_DATA(cl,o);
  276.             struct gpInput *gpi = (struct gpInput *) msg;
  277.             struct InputEvent *ie = gpi->gpi_IEvent;
  278.             BOOL mouseOverGadget = ((gpi->gpi_Mouse.X >= 0) &&
  279.                     (gpi->gpi_Mouse.X < ((struct Gadget *) o)->Width) &&
  280.                     (gpi->gpi_Mouse.Y >= 0) &&
  281.                     (gpi->gpi_Mouse.Y < ((struct Gadget *) o)->Height));
  282.             if (mouseOverGadget)
  283.             {
  284.                 if (!(((struct Gadget *) o)->Flags & GFLG_SELECTED))
  285.                 {
  286.                     ((struct Gadget *) o)->Flags |= GFLG_SELECTED;
  287.                     render(cl,(struct Gadget *) o,
  288.                         (struct gpRender *) msg,data);
  289.                 };
  290.             };
  291.             else {
  292.                 if (((struct Gadget *) o)->Flags & GFLG_SELECTED)
  293.                 {
  294.                     ((struct Gadget *) o)->Flags &= ~GFLG_SELECTED;
  295.                     render(cl,(struct Gadget *) o,
  296.                         (struct gpRender *) msg,data);
  297.                 };
  298.             };
  299.             switch (ie->ie_Class)
  300.             {
  301.                 case IECLASS_RAWMOUSE:
  302.                 {
  303.                     switch (ie->ie_Code)
  304.                     {
  305.                         case SELECTUP:
  306.                             if (mouseOverGadget)
  307.                             {
  308.                                 retval = GMR_NOREUSE | GMR_VERIFY;
  309.                             }
  310.                             else {
  311.                                 retval = GMR_NOREUSE;
  312.                             };
  313.                             break;
  314.                         case MENUDOWN:
  315.                             retval = GMR_REUSE;
  316.                             break;
  317.                         default:
  318.                             retval = GMR_MEACTIVE;
  319.                             break;
  320.                     };
  321.                     break;
  322.                 };
  323.                 default:
  324.                     retval = GMR_MEACTIVE;
  325.                     break;
  326.             };
  327.             break;
  328.         };
  329.         default:
  330.         {
  331.             retval = DoSuperMethodA(cl,o,msg);
  332.             break;
  333.         };
  334.     };
  335.     return retval;
  336. }
  337.  
  338. ULONG RadioClass::render(Class *cl, struct Gadget *g,
  339.     struct gpRender *msg, struct InstanceData *data)
  340. {
  341.     struct RastPort *rp;
  342.     struct GadgetInfo *ginfo;
  343.     if (msg->MethodID == OM_SET || msg->MethodID == OM_UPDATE)
  344.         ginfo = ((struct opSet *) msg)->ops_GInfo
  345.     else
  346.         ginfo = msg->gpr_GInfo;
  347.     if (!ginfo)
  348.         return TRUE;
  349.     UWORD *pens = ginfo->gi_DrInfo->dri_Pens;
  350.     if (msg->MethodID == GM_RENDER)
  351.         rp = msg->gpr_RPort
  352.     else
  353.         rp = ObtainGIRPort(ginfo);
  354.     if (rp)
  355.     {
  356.         if (data->labelscount > 0 && data->font)
  357.         {
  358.             UWORD pixelheight = g->Height / data->labelscount;
  359.             Object *button = (Object *) NewObject(NULL,SYSICLASS,
  360.                 SYSIA_DrawInfo,ginfo->gi_DrInfo,
  361.                 SYSIA_ReferenceFont,data->font,
  362.                 SYSIA_Size,SYSISIZE_HIRES,
  363.                 SYSIA_Which,MXIMAGE,
  364.                 IA_Top,0,
  365.                 IA_Left,0,
  366.                 IA_Width,g->Width > 18 ? g->Width - 2 : g->Width,
  367.                 IA_Height,pixelheight > 10 ? pixelheight - 2 : pixelheight,
  368.                 TAG_END);
  369.             if (button)
  370.             {
  371.                 ChangeLTextPens(data->label,pens[TEXTPEN],pens[BACKGROUNDPEN],JAM2);
  372.                 PrintLText(rp,data->label,
  373.                     g->LeftEdge - data->leftborder, g->TopEdge - data->topborder,
  374.                     g->Width + data->rightborder, data->topborder - 4,
  375.                     STADJUST_Center);
  376.                 STRPTR *labels = data->labels;
  377.                 WORD y = g->TopEdge;
  378.                 ULONG i = 0;
  379.                 while (*labels != NULL)
  380.                 {
  381.                     DrawImageState(rp,(struct Image *) button,
  382.                         g->LeftEdge,y,
  383.                         i == data->active ? IDS_SELECTED : IDS_NORMAL,
  384.                         ginfo->gi_DrInfo);
  385.                     SetAPen(rp,pens[TEXTPEN]);
  386.                     SetBPen(rp,pens[BACKGROUNDPEN]);
  387.                     SetDrMd(rp,JAM2);
  388.                     SetFont(rp,data->font);
  389.                     switch (data->labelsplace)
  390.                     {
  391.                         case RD_LabelsLeft:
  392.                             Move(rp,g->LeftEdge - data->leftborder,
  393.                                 y + (pixelheight - data->font->tf_YSize + 1) / 2 +
  394.                                 data->font->tf_Baseline);
  395.                             Text(rp,*labels,strlen(*labels));
  396.                             break;
  397.                         case RD_LabelsRight:
  398.                             Move(rp,g->LeftEdge + g->Width + 4,
  399.                                 y + (pixelheight - data->font->tf_YSize + 1) / 2 +
  400.                                 data->font->tf_Baseline);
  401.                             Text(rp,*labels,strlen(*labels));
  402.                             break;
  403.                     };
  404.                     y += pixelheight;
  405.                     labels++;
  406.                     i++;
  407.                 };
  408.                 DisposeObject(button);
  409.             };
  410.         };
  411.         if (msg->MethodID != GM_RENDER)
  412.             ReleaseGIRPort(rp);
  413.         return TRUE;
  414.     };
  415.     return FALSE;
  416. }
  417.  
  418. VOID RadioClass::calcBorders(Class *cl, struct Gadget *g,
  419.         struct InstanceData *data)
  420. {
  421.     data->leftborder = 0;
  422.     data->rightborder = 0;
  423.     data->bottomborder = 0;
  424.     data->topborder = 0;
  425.     if (data->tattr && data->labelscount > 0)
  426.     {
  427.         STRPTR *labels = data->labels;
  428.         LONG maxwidth = 0;
  429.         struct IntuiText it;
  430.         it.ITextFont = data->tattr;
  431.         while (*labels != NULL)
  432.         {
  433.             it.IText = *labels;
  434.             LONG width = IntuiTextLength(&it);
  435.             if (width > maxwidth)
  436.                 maxwidth = width;
  437.             labels++;
  438.         };
  439.         maxwidth += 4;
  440.         if (g->GadgetText)
  441.         {
  442.             data->topborder = data->tattr->ta_YSize + 4;
  443.             LONG width = MeasureLText(data->label);
  444.             if (width - 17 > maxwidth)
  445.                 maxwidth = width;
  446.         };
  447.         switch (data->labelsplace)
  448.         {
  449.             case RD_LabelsLeft:
  450.                 data->leftborder = maxwidth;
  451.                 break;
  452.             case RD_LabelsRight:
  453.                 data->rightborder = maxwidth;
  454.                 break;
  455.         };
  456.     };
  457. }
  458.  
  459. ULONG RadioClass::countLabels(STRPTR *labels)
  460. {
  461.     if (!labels)
  462.         return 0;
  463.     ULONG retval = 0;
  464.     while (*labels != NULL)
  465.     {
  466.         labels++;
  467.         retval++;
  468.     };
  469.     return retval;
  470. }
  471.  
  472. WORD RadioClass::calcWidth(Class *cl, struct Gadget *g,
  473.         struct InstanceData *data)
  474. {
  475.     if (data->tattr)
  476.     {
  477.         WORD w = (data->tattr->ta_YSize * 17 / 9);
  478.         return w > 17 ? w : 17;
  479.     };
  480.     return 17;
  481. }
  482.  
  483. WORD RadioClass::calcHeight(Class *cl, struct Gadget *g,
  484.         struct InstanceData *data)
  485. {
  486.     if (data->tattr)
  487.     {
  488.         WORD h = data->tattr->ta_YSize * data->labelscount;
  489.         return h > 9 ? h : 9;
  490.     };
  491.     return 9 * data->labelscount;
  492. }
  493.  
  494. // *************************************************************
  495.  
  496. RadioClass BRadioC::rc;
  497.  
  498. // *************************************************************
  499.  
  500.