//********
//
// TButClass.c
//
// Note : this is the LITE version
// No UPDATE or NOTIFY
// All methods inlined
//
// Date : 19 June 1996
//
//********

//****************

//******** Header files

//** OS3.1 Definitions
#include <intuition/imageclass.h>
#include <exec/lists.h>
#ifndef INTUITION_CLASSES_H
#include <intuition/classes.h>
#endif

#ifndef INTUITION_GADGETCLASS_H
#include <intuition/gadgetclass.h>
#endif

#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif

#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif

#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif


//** OS3.1 function Prototypes
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <clib/macros.h>

#ifndef  CLIB_ALIB_PROTOS_H
#include <clib/alib_protos.h>
#endif

#ifndef  CLIB_INTUITION_PROTOS_H
#include <clib/intuition_protos.h>
#endif


//OS3.1 Inline code
#include <pragmas/graphics_pragmas.h>
#include <pragmas/utility_pragmas.h>
#include <pragmas/intuition_pragmas.h>

#include <string.h>

#include "Librarian.h"
#include "TBUTClass.h"


//******** Structures

typedef ULONG (*HookFunction)(void);

typedef struct {
  struct  Image *FrameImage;
  STRPTR  GadgetText;
} TBUTData;

#define TBUT_SetTagArg(tag, id, data)   {tag.ti_Tag = (ULONG)(id);\
					tag.ti_Data = (ULONG)(data);}

//******** Dispatcher

static ULONG __saveds __asm TBUT_Dispatcher(register __a0 Class *cl,
				     register __a2 Object *o,
				     register __a1 Msg msg)
{
  ULONG rc=0;
  TBUTData *inst = INST_DATA( cl, o );
  struct Gadget *gad=(struct Gadget *)o;
  struct TagItem tags;
  struct RastPort *rp;
  Object *object;
  struct Image *image;
  struct TagItem *tistate;
  struct TagItem *ti;


  switch( msg->MethodID ) {
    case OM_NEW:
      image=(struct Image *)NewObject(NULL,FRAMEICLASS,
	IA_Recessed,    FALSE, IA_EdgesOnly,   FALSE,
	IA_FrameType,   FRAME_BUTTON,        TAG_DONE);

      if (image) {
	if (object = (Object *)DoSuperMethodA(cl, o, msg)) {
	  inst = (TBUTData *) INST_DATA(cl, object);
	  inst->FrameImage=image;
	  inst->GadgetText  = (STRPTR)GetTagData( TBUT_GadgetText, NULL, ((struct opSet *)msg)->ops_AttrList);
	} else {
	  DisposeObject(image);
	}
      } // if image
      rc=(ULONG)object;
      break;
    case OM_DISPOSE:
      if (inst->FrameImage) DisposeObject(inst->FrameImage);
      rc=(ULONG)(DoSuperMethodA(cl, o, msg));
      break;
    case OM_SET:
      DoSuperMethodA(cl,o,msg);
      tistate=ti=((struct opSet *)msg)->ops_AttrList;
      while (ti=NextTagItem(&tistate)) {
	switch (ti->ti_Tag) {
	  case TBUT_GadgetText:
	    inst->GadgetText=(STRPTR)(ti->ti_Data);
	  case GA_Selected:
	    if (rp=ObtainGIRPort(((struct opSet *)msg)->ops_GInfo)) {
	      DoMethod(o,GM_RENDER,((struct opSet *)msg)->ops_GInfo,rp,GREDRAW_REDRAW);
	      rc=1;
	      ReleaseGIRPort(rp);
	    }
	    break;
	  default:
	    break;
	} // switch
      } // while
      break;
    case OM_GET:
      rc=1;
      switch (((struct opGet *)msg)->opg_AttrID) {
	case TBUT_GadgetText:
	  *(((struct opGet *)msg)->opg_Storage)=(ULONG)inst->GadgetText;
	  break;
	case GA_Selected:
	  *(((struct opGet *)msg)->opg_Storage)= ((struct Gadget *)o)->Flags&GFLG_SELECTED?1:0;
	  break;
	default:
	  rc=DoSuperMethodA(cl,o,msg);
      } // switch
      break;
    case GM_HITTEST:
      rc = GMR_GADGETHIT;
      break;
    case GM_GOACTIVE:
      if (gad->Flags & GFLG_DISABLED) {
	rc=GMR_NOREUSE;
      } else {
	(void)DoSuperMethodA(cl, o, msg);
	gad->Flags ^= GFLG_SELECTED;
	if (rp = ObtainGIRPort( ((struct gpInput *)msg)->gpi_GInfo  )) {
	  DoMethod( o, GM_RENDER, ((struct gpInput *)msg)->gpi_GInfo, rp, GREDRAW_UPDATE );
	  ReleaseGIRPort( rp );
	}
	rc=GMR_MEACTIVE;
      }
      break;
    case GM_HANDLEINPUT:
      TBUT_SetTagArg(tags, TAG_END, NULL);
      (void)DoMethod( o, OM_NOTIFY, &tags, ((struct gpInput *)msg)->gpi_GInfo, 0);
      *(((struct gpInput *)msg)->gpi_Termination) = (gad->Flags&GFLG_SELECTED)?1:0;
      rc = GMR_NOREUSE | GMR_VERIFY;
      break;
    case GM_RENDER:
      {
      struct GadgetInfo *gi=((struct gpRender *)msg)->gpr_GInfo;
      struct DrawInfo *dri= gi->gi_DrInfo;
      LONG L,T,W,H;
      ULONG State, Len, numch;
      struct TextExtent te;

      L = gad->LeftEdge;
      T = gad->TopEdge;
      W = gad->Width;
      H = gad->Height;

      if (gi) {
	if (gad->Flags & GFLG_RELRIGHT ) L += gi->gi_Domain.Width  - 1;
	if (gad->Flags & GFLG_RELBOTTOM) T += gi->gi_Domain.Height - 1;
	if (gad->Flags & GFLG_RELWIDTH ) W += gi->gi_Domain.Width;
	if (gad->Flags & GFLG_RELHEIGHT) H += gi->gi_Domain.Height;
      }

      if (GM_RENDER == ((struct gpRender *)msg)->MethodID) rp = ((struct gpRender *)msg)->gpr_RPort;
      else                            rp = ObtainGIRPort(((struct gpRender *)msg)->gpr_GInfo);

      if (rp) {
	if (gad->Flags & GFLG_DISABLED)      State = IDS_DISABLED;
	else if (gad->Flags & GFLG_SELECTED) State = IDS_SELECTED;
	else                               State = IDS_NORMAL;

	SetAttrs( inst->FrameImage,
	  IA_Left,    L,           IA_Top,     T,
	  IA_Width,   W,           IA_Height,  H,
	  TAG_END);

	DrawImageState( rp, inst->FrameImage, 0, 0, State, dri);

	SetAPen(rp,(dri?dri->dri_Pens[TEXTPEN]:1));
	numch=strlen(inst->GadgetText);
	numch=TextFit(rp,inst->GadgetText,numch,&te,NULL,1,W-4,H);
	Len=te.te_Width;


//        Len=TextLength(rp,inst->GadgetText,numch);
	Move(rp,L+(W-Len)/2,T+(H-rp->Font->tf_YSize)/2+rp->Font->tf_Baseline);
	Text(rp,inst->GadgetText,numch);

	if (msg->MethodID != GM_RENDER) ReleaseGIRPort(rp);
	rc=1;
      } // if rp
      }
      break;
    case GM_GOINACTIVE:
      break;
    default:
      rc = DoSuperMethodA(cl, o, msg);
      break;
  } // switch

  return rc;
} // TBUT_Dispatcher


//******** Public create/dispose functions

Class *TBUT_CreateClass( void ) {
  Class *cl;
  extern ULONG HookEntry();     /* defined in amiga.lib */

  if (cl = MakeClass (NULL, GADGETCLASS, NULL, sizeof(TBUTData), 0) ) {
    cl->cl_Dispatcher.h_Entry = (HookFunction)TBUT_Dispatcher;
  }

  return (cl);
} // TBUT_CreateClass


BOOL   TBUT_DisposeClass( Class *cl ) {
  return (FreeClass(cl)) ;
} // TBUT DisposeClass


//******** End of file

