home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Atlanta_1990 / Atlanta-Devcon.1 / Libraries / Intuition / boopsi / textbclass.c < prev   
Encoding:
C/C++ Source or Header  |  1992-08-26  |  10.3 KB  |  433 lines

  1. /*** textbclass.c *******************************************************
  2.  *
  3.  * textbclass.c -- (repeating) command button gadget class
  4.  *
  5.  *  $Header: 
  6.  *
  7.  *  Confidential Information: Commodore-Amiga, Inc.
  8.  *  Copyright (C) 1989, Commodore-Amiga, Inc.
  9.  *  All Rights Reserved
  10.  *
  11.  ****************************************************************************/
  12.  
  13. /*
  14. Copyright (c) 1989 Commodore-Amiga, Inc.
  15.  
  16. Executables based on this information may be used in software
  17. for Commodore Amiga computers. All other rights reserved.
  18. This information is provided "as is"; no warranties are made.
  19. All use is at your own risk, and no liability or responsibility
  20. is assumed.
  21. */
  22.  
  23. #include "sysall.h"
  24. #include <intuition/classes.h>
  25. #include <graphics/gfxmacros.h>
  26.  
  27. #define D(x)    ;
  28.  
  29. extern struct  IntuitionBase   *IntuitionBase;
  30. extern struct  GfxBase         *GfxBase;
  31. extern struct  Library         *UtilityBase;
  32.  
  33. /* transparent base class    */
  34. #define G(o)    ((struct Gadget *)(o))
  35.  
  36. /* jimm's peculiarities */
  37. #define testf(v,f) ((v) & (f))
  38. #define setf(v,f)    ((v) |= (f))
  39. #define clearf(v,f)    ((v) &= ~(f))
  40.  
  41. #define DH(x)    ;
  42.  
  43. /* this useful to convert a point structure to a 32 bit vanilla
  44.  * data type if you want to pass it via libcall to lattice.
  45.  * probably can fudge it some other way ...
  46.  */
  47. /* #define POINTLONG( pt )    (((pt).X<<16) + (pt).Y) */
  48.  
  49. #define POINTLONG( pt )    (*( (ULONG *)  &(pt) ))
  50.  
  51. /* private class    */
  52. #define PRIVATECLASS    TRUE
  53.  
  54. #if PRIVATECLASS
  55. #define MYCLASSID    (NULL)
  56. #else
  57. #define MYCLASSID    "textbclass"
  58. #endif
  59.  
  60. #define SUPERCLASSID    "buttongclass"
  61. extern struct Library    *IntuitionBase;
  62.  
  63. struct TextBData {
  64.  
  65.     /* this is the offset of the contents, relative
  66.      * (0,0) of the gadget and its frame
  67.      */
  68.     struct {
  69.     UWORD    X;
  70.     UWORD    Y;
  71.     }        tbd_Offset;
  72.     ULONG    tbd_Flags;
  73. #define TBDF_USEFRAME    (1<<0)
  74. };
  75.  
  76.  
  77. Class    *
  78. initTextBClass()
  79. {
  80.     ULONG __saveds    dispatchTextB();
  81.     ULONG    hookEntry();
  82.     Class    *cl;
  83.     Class    *MakeClass();
  84.  
  85.     if ( cl =  MakeClass( MYCLASSID, 
  86.         SUPERCLASSID, NULL,        /* superclass is public      */
  87.          sizeof( struct TextBData ),
  88.         0 ))
  89.     {
  90.     /* initialize the cl_Dispatcher Hook    */
  91.     cl->cl_Dispatcher.h_Entry = hookEntry;
  92.     cl->cl_Dispatcher.h_SubEntry = dispatchTextB;
  93.     cl->cl_Dispatcher.h_Data = (VOID *) 0xFACE;    /* unused */
  94.  
  95. #if !PRIVATECLASS
  96.     AddClass( cl );            /* make public and available    */
  97. #endif
  98.     }
  99.     return ( cl );
  100. }
  101.  
  102. freeTextBClass( cl )
  103. Class    *cl;
  104. {
  105.     return ( FreeClass( cl )  );
  106. }
  107.  
  108.  
  109. /*
  110.  * The main dispatcher for this class of custom gadgets
  111.  */
  112. ULONG __saveds 
  113. dispatchTextB( cl, o, msg )
  114. Class   *cl;
  115. Object  *o;
  116. Msg     msg;
  117. {
  118.     ULONG        DoMethod();
  119.     Object          *newobj;
  120.     struct  RastPort    *rp;
  121.     int            refresh;
  122.     struct TextBData     *tbd;
  123.     ULONG        SetSuperAttrs();
  124.  
  125.     struct  RastPort    *ObtainGIRPort();
  126.  
  127.     tbd = INST_DATA( cl, o );
  128.  
  129.     switch ( msg->MethodID )
  130.     {
  131.     case OM_NEW:
  132.     D( kprintf("textbclass new\n") );
  133.     if ( newobj = (Object *) DSM( cl, o, msg ) )
  134.     {
  135.         tbd = INST_DATA( cl, newobj );    /* want it for newobject */
  136.  
  137.         /* frame our text, if any text ... */
  138.         if ( G(newobj)->GadgetText )
  139.         {
  140.         struct IBox    contents;
  141.         struct IBox    framebox;
  142.         struct DrawInfo    *drinfo;
  143.  
  144.         /* get the contents    */
  145.         drinfo = (struct DrawInfo *) GetTagData( GA_DRAWINFO, NULL, 
  146.             ((struct opSet *) msg)->ops_AttrList );
  147.         getContentsExtent( newobj, drinfo, &contents );
  148.  
  149.         /* and if our image understands IM_FRAMEBOX    */
  150.         if ( DoMethod(  G(newobj)->GadgetRender, IM_FRAMEBOX,
  151.             &contents, &framebox, drinfo, 0 ) )
  152.         {
  153.             /* use the frame dimensions and offset    */
  154.             tbd->tbd_Flags |= TBDF_USEFRAME;
  155.             D( kprintf("call SSA to set width/height %lx/%lx\n",
  156.                 framebox.Width, framebox.Height ));
  157.  
  158.             SetSuperAttrs( cl, newobj, 
  159.                 GA_WIDTH, framebox.Width,
  160.             GA_HEIGHT, framebox.Height,
  161.             TAG_END );
  162.             D( kprintf(" SetSuperAttrs returns, gadget Height %\n"));
  163.  
  164.             /* when we draw the frame at 0,0, we
  165.              * need to offset the text contents 
  166.              * in the opposite direction.
  167.              */
  168.             tbd->tbd_Offset.X = -framebox.Left;
  169.             tbd->tbd_Offset.Y = -framebox.Top;
  170.         }
  171.         /* ZZZ: else just fail if not a frame? */
  172.         }
  173.  
  174.         /*  set attributes in general, which might force dims */
  175.         setTextBAttrs( cl, o, msg );
  176.     }
  177.     return ( (ULONG) newobj );
  178.  
  179.     case OM_UPDATE:    
  180.     case OM_SET:    
  181.     /* inherit atts, accumulated refresh    */
  182.     refresh = DSM( cl, o, msg );
  183.     refresh += setTextBAttrs( cl, o, msg );
  184.  
  185.     /* take responsibility here for refreshing visuals
  186.      * if I am the "true class."  It's sort of too bad
  187.      * that every class has to do this itself.
  188.      */
  189.     if ( refresh && ( OCLASS(o) == cl ) )
  190.     {
  191.         rp = ObtainGIRPort( ((struct opSet *)msg)->ops_GInfo );
  192.         if ( rp ) 
  193.         {
  194.         renderTextG( rp, ((struct opSet *)msg)->ops_GInfo, G(o), tbd,
  195.             GREDRAW_UPDATE );
  196.         }
  197.         ReleaseGIRPort( rp );
  198.         return ( 0 );        /* don't need refresh any more */
  199.     }
  200.     /* else */
  201.     return ( (ULONG) refresh );    /* return to subclass perhaps    */
  202.  
  203.     case GM_HITTEST:
  204.  
  205.  
  206. #if 1    /* use HITFRAME */
  207.     /* ask our frame if we have one  */
  208.     return ( DoMethod( G(o)->GadgetRender, 
  209.         IM_HITFRAME,    /* even non-frames will understand this */
  210.         POINTLONG( ((struct gpHitTest *) msg)->gpht_Mouse ),
  211.         *((ULONG *) &G(o)->Width) ) );    /* trick    */
  212.  
  213. #else
  214.     return ( (ULONG) PointInImage( pointlong, G(o)->GadgetRender ) );
  215. #endif  /* use HITFRAME */
  216.  
  217.     case GM_RENDER:
  218.     renderTextG( ((struct gpRender *) msg)->gpr_RPort,
  219.         ((struct gpRender *) msg)->gpr_GInfo, o, tbd,
  220.         ((struct gpRender *)msg)->gpr_Redraw );
  221.     break;
  222.  
  223.     OM_GET:    /* I'm not telling anyone about it yet    */
  224.     case GM_GOACTIVE:
  225.     case GM_GOINACTIVE:
  226.     case GM_HANDLEINPUT:    /* the big one    */
  227.     default:    /* let the superclass handle it */
  228.     return ( (ULONG) DSM( cl, o, msg ) );
  229.     }
  230.     return ( 0 );
  231. }
  232.  
  233.  
  234. renderTextG( rp, gi, o, tbd, redraw_mode )
  235. struct RastPort        *rp;
  236. struct GadgetInfo    *gi;
  237. Object            *o;
  238. struct TextBData     *tbd;
  239. {
  240.     int        state;
  241.  
  242.     if ( redraw_mode == GREDRAW_TOGGLE ) return;
  243.  
  244.     state = buttonDrawState( G(o), gi );
  245.  
  246.     /* draw frame    */
  247.     DoMethod( G(o)->GadgetRender, IM_DRAWFRAME, rp, 
  248.                 *((ULONG *) &G(o)->LeftEdge),
  249.             state,
  250.             gi->gi_DrInfo,
  251.                 *((ULONG *) &G(o)->Width) );    /* frame dimensions */
  252.             
  253.     displayContents( rp, o, gi->gi_DrInfo,
  254.         G(o)->LeftEdge + tbd->tbd_Offset.X,
  255.         G(o)->TopEdge + tbd->tbd_Offset.Y, state );
  256. }
  257.  
  258. /*
  259.  * WARNING: this might change!
  260.  *
  261.  * returns image drawstate suitable for
  262.  * gadget active/border circumstances
  263.  */
  264.  
  265. #define ALLBORDERS (RIGHTBORDER+LEFTBORDER+TOPBORDER+BOTTOMBORDER)
  266. buttonDrawState( g, gi )
  267. struct Gadget        *g;
  268. struct GadgetInfo    *gi;
  269. {
  270.     if ( g && testf( g->Flags, SELECTED ) )
  271.     return ( IDS_SELECTED );
  272.  
  273.     if ( g && gi && gi->gi_Window &&
  274.     ! testf( gi->gi_Window->Flags, WINDOWACTIVE ) &&
  275.     ( testf( g->Activation, ALLBORDERS ) ||
  276.       testf( g->GadgetType, 0xF0 ) ) )    /* a "system" gadget */
  277.     {
  278.     if ( testf( g->Flags, SELECTED ) )
  279.         return ( IDS_INACTIVESELECTED );
  280.     /* else */
  281.         return ( IDS_INACTIVENORMAL );
  282.     }
  283.  
  284.     else if ( g && testf( g->Flags, SELECTED ) )
  285.         return (IDS_SELECTED );
  286.     /* else */
  287.     return ( IDS_NORMAL );
  288. }
  289.  
  290. setTextBAttrs( cl, o, msg )
  291. Class        *cl;
  292. Object        *o;
  293. struct opSet    *msg;
  294. {
  295.     struct TagItem    *NextTagItem();
  296.     struct TagItem    *tags = msg->ops_AttrList;
  297.     struct TagItem    *tag;
  298.     ULONG        tidata;
  299.     struct TextBData     *tbd;
  300.  
  301.     int            refresh = 0;
  302.     struct DrawInfo    *drinfo;
  303.     struct IBox        newframe;
  304.  
  305.     tbd = INST_DATA( cl, o );
  306.  
  307.     /* only interested in Width/Height fields */
  308.     newframe.Width = G(o)->Width;
  309.     newframe.Height = G(o)->Height;
  310.  
  311.     /* process rest */
  312.     while ( tag = NextTagItem( &tags ) )
  313.     {
  314.     tidata = tag->ti_Data;
  315.     switch ( tag->ti_Tag )
  316.     {
  317.  
  318.     /* if forced dimension change, then
  319.      * center text, recalc offsets using FRAMEF_SPECIFY
  320.      */
  321.      case GA_WIDTH:
  322.         refresh = 1;
  323.         newframe.Width = tidata;
  324.         break;
  325.      case GA_HEIGHT:
  326.         refresh = 1;
  327.         newframe.Height = tidata;
  328.         break;
  329.     /* could also reset for a new GA_IMAGE here, if
  330.      * you wanted
  331.      */
  332.     }
  333.     }
  334.  
  335.     /* fix up changes which require some work    */
  336.     if ( refresh )
  337.     {
  338.     /* get new offsets from the specified frame dimensions    */
  339.  
  340.     if ( tbd->tbd_Flags & TBDF_USEFRAME )
  341.     {
  342.         struct IBox    contents;
  343.  
  344.         /* really need DrawInfo, if layout change    */
  345.         drinfo = msg->ops_GInfo? msg->ops_GInfo->gi_DrInfo: NULL;
  346.  
  347.         /* override with tags version */
  348.         drinfo = (struct DrawInfo *) GetTagData( GA_DRAWINFO, drinfo, tags);
  349.  
  350.         /* get contents box again */
  351.         getContentsExtent( o, drinfo, &contents );
  352.  
  353.         DoMethod(  G(o)->GadgetRender, IM_FRAMEBOX, &contents,
  354.             &newframe, drinfo, FRAMEF_SPECIFY );
  355.  
  356.         tbd->tbd_Offset.X = -newframe.Left;
  357.         tbd->tbd_Offset.Y = -newframe.Top;
  358.     }
  359.  
  360.     /* superclass knows about the new dimensions, and I don't
  361.      * have any reason to disagree, so no need to 
  362.      * override the values now.
  363.      */
  364.     }
  365.  
  366.     return ( refresh );
  367. }
  368.  
  369. /*
  370.  * This is going to be nifty.
  371.  * Right now, we'll use GadgetText as (UBYTE *),
  372.  * but we could conceivably code for this
  373.  * to be either simple text, or a pointer to
  374.  * a generic image Object which could be a text label,
  375.  * or glyph, or what have you.
  376.  *
  377.  * Then this class becomes the "button with label which is
  378.  * rendered by overdrawing some frame" class.
  379.  */
  380. getContentsExtent( o, drinfo, contents )
  381. Object        *o;
  382. struct DrawInfo    *drinfo;
  383. struct IBox    *contents;
  384. {
  385.     UBYTE    *label;
  386.     struct RastPort    rport;
  387.     struct TextExtent    textent;
  388.  
  389.     /* maybe look at some flags to handle other types of text someday */
  390.     if ( label = (UBYTE *) G(o)->GadgetText )
  391.     {
  392.     InitRastPort( &rport );
  393.     if ( drinfo && drinfo->dri_Font )
  394.     {
  395.         SetFont( &rport, drinfo->dri_Font );
  396.     }
  397.     TextExtent( &rport, label, strlen( label ), &textent );
  398.  
  399.     /* convert extent Rectangle to an IBox    */
  400.     contents->Left = textent.te_Extent.MinX;
  401.     contents->Top = textent.te_Extent.MinY;
  402.     contents->Width = textent.te_Extent.MaxX -  textent.te_Extent.MinX + 1;
  403.     contents->Height = textent.te_Extent.MaxY -  textent.te_Extent.MinY + 1;
  404.     }
  405.     else
  406.     {
  407.     contents->Left = contents->Top =
  408.         contents->Width = contents->Height = 0;
  409.     }
  410. }
  411.  
  412. /*
  413.  * show enclosed text label in correct color.
  414.  * always use textpen for now
  415.  */
  416. displayContents( rp, o, drinfo, offsetx, offsety, state )
  417. struct RastPort    *rp;
  418. Object        *o;
  419. struct DrawInfo    *drinfo;
  420. WORD        offsetx;
  421. WORD        offsety;
  422. {
  423.     UBYTE    *label;
  424.  
  425.     if ( label = (UBYTE *) G(o)->GadgetText )
  426.     {
  427.     SetDrMd( rp, JAM1 );
  428.     SetAPen( rp, drinfo->dri_Pens[ textPen ] );
  429.     Move( rp, offsetx, offsety );
  430.     Text( rp, label, strlen( label ) );
  431.     }
  432. }
  433.