/* ==========================================================================
**
**                   EmbossedGadget.c
**
** ©1991 WILLISoft
**
** ==========================================================================
*/

#include <stdlib.h>
#include <stdio.h>
#include <exec/types.h>
#include <proto/intuition.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include "AmigaMem.h"

#include "EmbossedGadget.h"
#include "EmbossedGadgetClass.h"
#include "minmax.h"
#include "Precognition_Utils.h"

#define WAITING 0
#define PRESSED 1

#ifdef BUILDER

EmbossedGadget *EmbossedGadget_New( EmbossedGadget *self )
{
   EmbossedGadget *new_gadget;
   void GiveItAName( PObject *obj );

   if (new_gadget = (EmbossedGadget *) Amalloc( sizeof(EmbossedGadget) ))
   {
       EmbossedGadget_Init( new_gadget,
          self->Location.x, self->Location.y,
          self->Size.x,     self->Size.y,
          self->g.Flags,    self->g.Activation, self->g.GadgetType,
          self->Pens,       Title(self) );

      GiveItAName( new_gadget );
   }
   return new_gadget;
}

#endif

void EmbossedGadget_CleanUp( EmbossedGadget *self )
{
   Afree( self->BoxBorder );
   self->BoxBorder = NULL;
}


tPoint EmbossedGadget_SetLocation(  EmbossedGadget *self,
                                    PIXELS          LeftEdge,
                                    PIXELS          TopEdge )
{
   Forbid(); /* Don't want Intuition looking at these while we modify em. */
   self->Location.x  = self->g.LeftEdge = LeftEdge;
   self->Location.y  = self->g.TopEdge  = TopEdge;
   Permit();

   return self->Location;
}




tPoint EmbossedGadget_AskSize( EmbossedGadget *self,
                               PIXELS          Width,
                               PIXELS          Height )
{
   tPoint size;

   size.x = MAX( Width,  6 );
   size.y = MAX( Height, 6 );

   return size;
}


tPoint EmbossedGadget_SetSize( EmbossedGadget *self,
                               PIXELS          Width,
                               PIXELS          Height )
{
   tPoint size;

   size = AskSize( self, Width, Height );

   Forbid(); /* Don't want Intuition looking at these while we modify em. */
   self->Size     = size;
   self->g.Width  = size.x;
   self->g.Height = size.y;

   pcg_Init3DBox(  self->BoxBorder, 0, 0, size.x, size.y,
                   self->Pens.BrightPen,  self->Pens.DarkPen,
                   self->BoxBorder->BottomRight.NextBorder );
   Permit();

   AlignText( &self->LabelText, Size(self) );

   return size;
}


Gadget *EmbossedGadget_FirstGadget( EmbossedGadget *self )
{
   return &self->g;
}


USHORT EmbossedGadget_nGadgets( EmbossedGadget *self )
{
   return 1;
}


ULONG EmbossedGadget_IDCMPFlags( EmbossedGadget *self )
{
   ULONG flags;
   UWORD activation;

   activation = self->g.Activation;
   flags =    ((activation & GADGIMMEDIATE) ? GADGETDOWN :0)
            | ((activation & RELVERIFY)     ? GADGETUP   :0)
            | ((activation & FOLLOWMOUSE)   ? MOUSEMOVE  :0);
   return flags;
}


USHORT EmbossedGadget_ClaimEvent( EmbossedGadget *self,
                                  IntuiMessage   *event )
{
   USHORT response = 0;

   switch (event->Class)
   {
      case REFRESHWINDOW:
         response = RESPONDED;
         break;

      case GADGETDOWN:
      case GADGETUP:
         if (event->IAddress == (void*) &self->g)
         {
            response = RESPONDED | CONSUMED_EVENT | CHANGED_STATE;
         }
         break;

      case MOUSEBUTTONS: /* Duration events. */
      case INTUITICKS:
         if (self->state)
         {
            response = RESPONDED | CHANGED_STATE;
         }
         break;
   }

   return response;
}


USHORT EmbossedGadget_Respond( EmbossedGadget   *self,
                               IntuiMessage     *Event )
{
   USHORT response = 0;
   Window *window;

   switch (Event->Class)
   {
      case REFRESHWINDOW:
         Refresh( self );
         response = RESPONDED;
         break;

      case GADGETDOWN:
         if (Event->IAddress == (void*) FirstGadget(self))
         {
            if (self->g.Activation & GADGDURATION)
            {
               window = Event->IDCMPWindow;
               self->state = PRESSED;
               /* Save the original IDCMP settings. */
               self->IDCMPbuf = window->IDCMPFlags;

               if (! (self->g.Activation & FOLLOWMOUSE))
               {
                  /*
                  ** For Duration gadgets, on GADGETDOWN, INTUITICKS
                  ** are turned on so the EmbossedGadget can get
                  ** continuous messages.
                  */
                  ModifyIDCMP( window,
                        window->IDCMPFlags | INTUITICKS | MOUSEBUTTONS );
               }
            }
            response = RESPONDED | CONSUMED_EVENT | CHANGED_STATE;
         }
         break;

      case GADGETUP:
         if (Event->IAddress == (void*) FirstGadget(self))
         {
            window = Event->IDCMPWindow;
            if (self->state) /* Duration turned on */
            {
               self->state = WAITING;
               ModifyIDCMP( window, self->IDCMPbuf );
            }

            response = RESPONDED | CONSUMED_EVENT | CHANGED_STATE;
         }
         break;

      case INTUITICKS:
         if (self->state)
         {  /* User is still pressing gadget */
            response = RESPONDED | CHANGED_STATE;
         }
         break;

      case MOUSEBUTTONS:
         /* MouseButtons happen when the User moves the mouse off
          * off the gadget before releasing.
          */
         if (self->state)
         {
            window      = Event->IDCMPWindow;
            self->state = WAITING;
            ModifyIDCMP( window, self->IDCMPbuf );

            response = RESPONDED | CHANGED_STATE;
         }
         break;

      case MOUSEMOVE:
         if (self->state)
         {
            response = RESPONDED | CONSUMED_EVENT | CHANGED_STATE;
         }
         break;

   }
   return response;
}


void EmbossedGadget_Refresh( EmbossedGadget *self )
{
   pcgWindow *window;
   RastPort  *rport;
   Point loc;

   if (window = InteractorWindow(self))
   {
      RefreshGList( FirstGadget(self), iWindow(window), NULL,
                     nGadgets(self) );
      if (self->LabelText.IText)
      {
         rport = RPort( window );
         loc   = Location(self);
         PrintIText( rport, &self->LabelText, loc.x, loc.y );
      }
   }
}

void EmbossedGadget_Render( EmbossedGadget *self, RastPort *rport )
{
   PIXELS x, y;
   Point loc;

   x = self->g.LeftEdge;
   y = self->g.TopEdge;

   if (self->g.GadgetRender)
   {
      if (self->g.Flags & GADGIMAGE)
      {
         DrawImage( rport, (struct Image *) self->g.GadgetRender, x, y );
      }
      else
      {
         DrawBorder( rport, (struct Border *) self->g.GadgetRender, x, y );
      }
   }

   if (self->g.GadgetText)
   {
      PrintIText( rport, self->g.GadgetText, x, y );
   }

   if (self->LabelText.IText)
   {
      loc = Location(self);
      PrintIText( rport, &self->LabelText, loc.x, loc.y );
   }
}


BOOL EmbossedGadget_EnableIactor( EmbossedGadget *self,
                            BOOL            enable )
{
   struct pcgWindow *window;
   struct Window    *iwindow;
   RastPort *rport;
   Gadget *g;
   PIXELS xmin, xmax, ymin, ymax;
   short i, ngadgets;

   window   = InteractorWindow(self);
   g        = FirstGadget(self);
   ngadgets = nGadgets(self);

   if (enable)
   {
      if (window && (rport = RPort(window))) /* Window is open */
      {
         for ( i=0; i<ngadgets; i++, g=g->NextGadget)
         {
            xmin  = g->LeftEdge;
            ymin  = g->TopEdge;
            xmax  = xmin + g->Width - 1;
            ymax  = ymin + g->Height - 1;

            OnGadget( g, window->Window, NULL );

            SetDrMd( rport, JAM1 );
            SetAPen( rport, self->Pens.BackPen );
            RectFill( rport, xmin, ymin, xmax, ymax );
            Refresh(self);
         }
      }
      else
      {
         for ( i=0; i<ngadgets; i++, g=g->NextGadget)
         {
            g->Flags &= (~ GADGDISABLED);
         }
      }
   }
   else
   {
      if (window && (iwindow = iWindow(window))) /* window is open. */
      {
         for ( i=0; i<ngadgets; i++, g=g->NextGadget)
         {
            OffGadget( g, iwindow, NULL );
         }
      }
      else
      {
         for ( i=0; i<ngadgets; i++, g=g->NextGadget)
         {
            g->Flags |= GADGDISABLED;
         }
      }
   }

   return enable;
}


BOOL EmbossedGadget_isEnabled( Interactor *self,
                               BOOL       enable )
{
   Gadget *g;

   if (g = FirstGadget(self))
      return (BOOL) (! (g->Flags & GADGDISABLED));
   else
      return FALSE;
}


char *EmbossedGadget_Title( EmbossedGadget *self )
{
   return (char *) self->LabelText.IText;
}

BOOL EmbossedGadget_SetTitle( EmbossedGadget *self,
                              char           *title )
{
   Afree(self->LabelText.IText);
   self->LabelText.IText  = Astrdup(title);
   AlignText( &self->LabelText, Size(self) );

   return TRUE;
}


AlignInfo EmbossedGadget_TextAlignment( EmbossedGadget *self )
{
   return self->LabelText.alignment;
}

AlignInfo EmbossedGadget_SetTextAlignment( EmbossedGadget *self,
                                           UBYTE     Flags,
                                           BYTE      Xpad,
                                           BYTE      Ypad )
{
   self->LabelText.alignment.Flags = Flags;
   self->LabelText.alignment.Xpad  = Xpad;
   self->LabelText.alignment.Ypad  = Ypad;
   AlignText( &self->LabelText, Size(self) );
   return self->LabelText.alignment;
}


BOOL EmbossedGadget_elaborated = FALSE;

struct InteractorClass EmbossedGadget_Class;

void EmbossedGadgetClass_Init( struct InteractorClass *class )
{
   InteractorClass_Init( class );
   class->isa         = InteractorClass();
   class->ClassName   = "EmbossedGadget";
   class->CleanUp     = EmbossedGadget_CleanUp;
   class->SetLocation = EmbossedGadget_SetLocation;
   class->SetSize     = EmbossedGadget_SetSize;
   class->AskSize     = EmbossedGadget_AskSize;
   class->Render      = EmbossedGadget_Render;
   class->FirstGadget = EmbossedGadget_FirstGadget;
   class->nGadgets    = EmbossedGadget_nGadgets;
   class->IDCMPFlags  = EmbossedGadget_IDCMPFlags;
   class->ClaimEvent  = EmbossedGadget_ClaimEvent;
   class->Respond     = EmbossedGadget_Respond;
   class->Refresh     = EmbossedGadget_Refresh;
   class->EnableIactor= EmbossedGadget_EnableIactor;
   class->isEnabled   = EmbossedGadget_isEnabled;
   class->Activate    = NULL;
   class->isActive    = NULL;
   class->Title       = EmbossedGadget_Title;
   class->SetTitle    = EmbossedGadget_SetTitle;
   class->TextAlignment = EmbossedGadget_TextAlignment;
   class->SetTextAlignment = EmbossedGadget_SetTextAlignment;
}


struct InteractorClass *EmbossedGadgetClass( void )
{
   if (! EmbossedGadget_elaborated)
   {
      EmbossedGadgetClass_Init( &EmbossedGadget_Class );
      EmbossedGadget_elaborated = TRUE;
   }

   return &EmbossedGadget_Class;
}



void EmbossedGadget_Init( EmbossedGadget *self,
                          SHORT           LeftEdge,
                          SHORT           TopEdge,
                          SHORT           Width,
                          SHORT           Height,
                          USHORT          Flags,
                          USHORT          Activation,
                          USHORT          GadgetType,
                          pcg_3DPens      Pens,
                          char           *Label )
{
   Interactor_Init( self );

   self->isa             = EmbossedGadgetClass();
   self->Pens            = Pens;
   self->BoxBorder       = (pcg_3DBox *) Acalloc( 1, sizeof( pcg_3DBox ) );
   self->state           = WAITING;

   self->LabelText.FrontPen  = Pens.FrontPen;
   self->LabelText.BackPen   = Pens.BackPen;
   self->LabelText.DrawMode  = JAM1;
   self->LabelText.ITextFont = &pcg_Topaz80;
   self->LabelText.IText     = NULL;
   self->LabelText.NextText  = NULL;
   self->LabelText.alignment.Flags = tx_INSIDE | tx_LEFT | tx_YCENTER;
   self->LabelText.alignment.Xpad  = STD_XPAD;
   self->LabelText.alignment.Ypad  = STD_YPAD;

   self->g.NextGadget    = NULL;
   self->g.Flags         = Flags;
   self->g.Activation    = Activation;
   self->g.GadgetType    = GadgetType;
   self->g.GadgetRender  = (APTR) &self->BoxBorder->TopLeft;
   self->g.SelectRender  = NULL;
   self->g.MutualExclude = 0L;
   self->g.SpecialInfo   = NULL;
   self->g.GadgetID      = 0;
   self->g.UserData      = NULL;
   self->g.GadgetText    = NULL;

   SetLocation( self, LeftEdge, TopEdge );
   SetSize( self, Width, Height );
   SetTitle( self, Label );

}

