//---------------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include <math.h>

#include "VmxCustomScrollbar.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
// floor

static inline void ValidCtrCheck(TVmxCustomScrollbar *)
{
        new TVmxCustomScrollbar(NULL);
}
//---------------------------------------------------------------------------

void __fastcall DrawGripper (Graphics::TBitmap *Bmp, int X, int Y, int BH, int H, TCanvas *Canvas, Graphics::TBitmap *Gripper = NULL, int FMG = 5)
{
  if (H <= 0)
  {
    Bmp->Transparent=true;
    Bmp->TransparentColor=Bmp->Canvas->Pixels[0][0];
    Canvas->StretchDraw(TRect(X,Y,X+Bmp->Width,Y+H+2*BH),Bmp);
    return;
  }
  Graphics::TBitmap *Tmp = new Graphics::TBitmap;
  Tmp->Width=Bmp->Width;
  Tmp->Height=Bmp->Height-2*BH;
  Tmp->Canvas->CopyRect(TRect(0,0,Bmp->Width,Tmp->Height),Bmp->Canvas,TRect(0,BH,Bmp->Width,Bmp->Height-BH));
  for (int i = 0; i < BH; i++)
  {
    for (int j = 0; j < Bmp->Width; j++)
      if (Bmp->Canvas->Pixels[j][i]!=Bmp->Canvas->Pixels[0][0])
        Canvas->Pixels[X+j][Y+i]=Bmp->Canvas->Pixels[j][i];
  }
  Canvas->StretchDraw(TRect(X,Y+BH,X+Bmp->Width,Y+H+BH),Tmp);
  for (int i = 0; i < BH; i++)
  {
    for (int j = 0; j < Bmp->Width; j++)
      if (Bmp->Canvas->Pixels[j][Bmp->Height-BH+i]!=Bmp->Canvas->Pixels[0][0])
        Canvas->Pixels[X+j][Y+H+i+1]=Bmp->Canvas->Pixels[j][Bmp->Height-BH+i];
  }
  if (Gripper!=NULL&&!Gripper->Empty&&Gripper->Height+2*BH<H)
  {
    Gripper->Transparent=true;
    int Ngs = (H-3*BH)/Gripper->Height;
    if (Ngs < 0) Ngs = 0;
    if (Ngs > FMG) Ngs = FMG;
    for (int i = 0; i < Ngs; i++)
      Canvas->Draw (X+Bmp->Width/2-Gripper->Width/2,Y+BH/2+H/2-Gripper->Height*Ngs/2+i*Gripper->Height,Gripper);
  }
  delete Tmp;
}

__fastcall TVmxCustomScrollbar::TVmxCustomScrollbar(TComponent* Owner)
        : TGraphicControl(Owner)
{
  FUN = new Graphics::TBitmap;
  FUO = new Graphics::TBitmap;
  FUP = new Graphics::TBitmap;
  FDN = new Graphics::TBitmap;
  FDO = new Graphics::TBitmap;
  FDP = new Graphics::TBitmap;
  FGN = new Graphics::TBitmap;
  FGO = new Graphics::TBitmap;
  FGP = new Graphics::TBitmap;
  FB = new Graphics::TBitmap;
  FGripper = new Graphics::TBitmap;
  FMax = 5;
  FBH = 5;
  US = viNormal;
  DS = viNormal;
  GS = viNormal;
  Ct = 0;
  FMaxGrippers = 5;
}

void __fastcall TVmxCustomScrollbar::SetPos (int New)
{
  int o = FPos;
  if (New >= FMax)
    FPos = FMax-1;
  else if (New < 0)
    return;
  else
    FPos = New;
  if (FPos != o)
  {
    Paint ();
    if (FOnChangePos!=NULL)
      FOnChangePos (this);
  }
}

void __fastcall TVmxCustomScrollbar::SetMaxGrippers (int New)
{
  FMaxGrippers = New;
  Paint();
}

void __fastcall TVmxCustomScrollbar::SetMax (int New)
{
  if (New <= 0)
    return;
  FMax = New;
  if (FPos >= FMax)
  {
    FPos = FMax-1;
    Ct = (Height-FUN->Height-FDN->Height)*FPos/FMax;
  }
  Paint ();
}

void __fastcall TVmxCustomScrollbar::SetUN (Graphics::TBitmap *New)
{
  FUN->Assign(New);
  Paint ();
}

void __fastcall TVmxCustomScrollbar::SetB (Graphics::TBitmap *New)
{
  FB->Assign(New);
  Paint ();
}

void __fastcall TVmxCustomScrollbar::SetDN (Graphics::TBitmap *New)
{
  FDN->Assign(New);
  Paint ();
}

void __fastcall TVmxCustomScrollbar::SetGN (Graphics::TBitmap *New)
{
  FGN->Assign(New);
  Paint ();
}

void __fastcall TVmxCustomScrollbar::SetGripper (Graphics::TBitmap *New)
{
  FGripper->Assign(New);
  Paint ();
}

void __fastcall TVmxCustomScrollbar::SetUO (Graphics::TBitmap *New)
{
  FUO->Assign(New);
}

void __fastcall TVmxCustomScrollbar::SetUP (Graphics::TBitmap *New)
{
  FUP->Assign(New);
}

void __fastcall TVmxCustomScrollbar::SetDO (Graphics::TBitmap *New)
{
  FDO->Assign(New);
}

void __fastcall TVmxCustomScrollbar::SetDP (Graphics::TBitmap *New)
{
  FDP->Assign(New);
}

void __fastcall TVmxCustomScrollbar::SetGP (Graphics::TBitmap *New)
{
  FGP->Assign(New);
}

void __fastcall TVmxCustomScrollbar::SetGO (Graphics::TBitmap *New)
{
  FGO->Assign(New);
}

void __fastcall TVmxCustomScrollbar::Paint (void)
{
  if (FUN->Empty||FGN->Empty||FDN->Empty||FB->Empty||
      FUO->Empty||FGO->Empty||FDO->Empty||
      FUP->Empty||FGP->Empty||FDP->Empty)
    return;
  Graphics::TBitmap *Bmp;
  switch (US)
  {
    case viNormal: Bmp = FUN; break;
    case viHover: Bmp = FUO; break;
    case viDown: Bmp = FUP; break;
    default: Bmp = FUN; break;
  }
  Bmp->Transparent=true;
  Bmp->TransparentColor=Bmp->Canvas->Pixels[0][0];
  Canvas->Draw(0,0,Bmp);
  switch (DS)
  {
    case viNormal: Bmp = FDN; break;
    case viHover: Bmp = FDO; break;
    case viDown: Bmp = FDP; break;
    default: Bmp = FDN; break;
  }
  Bmp->Transparent=true;
  Bmp->TransparentColor=Bmp->Canvas->Pixels[0][0];
  Canvas->Draw(0,Height-Bmp->Height,Bmp);
  for (int i = FUN->Height; i < Height-FDN->Height-FB->Height; i+=FB->Height)
    Canvas->Draw(0,i,FB);
  Canvas->Draw(0,Height-FDN->Height-FB->Height,FB);
  switch (GS)
  {
    case viNormal: Bmp = FGN; break;
    case viHover: Bmp = FGO; break;
    case viDown: Bmp = FGP; break;
    default: Bmp = FGN; break;
  }
  DrawGripper (Bmp, 0,FUN->Height+Ct/*(Height-FUN->Height-FDN->Height)*FPos/FMax*/,FBH,(Height-FUN->Height-FDN->Height)/FMax-FBH,Canvas,FGripper,FMaxGrippers);
}

void __fastcall TVmxCustomScrollbar::CMMouseLeave (TMessage &Msg)
{
  TVIState ou, od, og;
  ou = US;
  od = DS;
  og = GS;
  if (GS != viDown)
    GS = viNormal;
  if (DS != viDown)
    DS = viNormal;
  if (US != viDown)
    US = viNormal;
  if (US != ou || GS != og || DS != od)
    Paint ();
}

void __fastcall TVmxCustomScrollbar::MouseMove (TShiftState Shift, int X, int Y)
{
  TVIState ou, od, og;
  ou = US;
  od = DS;
  og = GS;
  if (GS != viDown)
    GS = viNormal;
  if (DS != viDown)
    DS = viNormal;
  if (US != viDown)
    US = viNormal;
  if (GS == viDown)
  {
    Pos = (Y-FUN->Height)*FMax/(Height-FUN->Height-FDN->Height);
    Ct = (Y+tmp>Height-FDN->Height-((Height-FUN->Height-FDN->Height)/FMax)?Height-FUN->Height-FDN->Height-((Height-FUN->Height-FDN->Height)/FMax):Y+tmp-FUN->Height);
    if (Ct < 0)
      Ct = 0;
    Paint ();
    return;
  }
  if (PtInRect (TRect(0,0,FUN->Width,FUN->Height),TPoint(X,Y)))
  {
    if (GS != viDown)
      GS = viNormal;
    if (DS != viDown)
      DS = viNormal;
    US = viHover;
  }
  else if (PtInRect (TRect(0,Height-FDN->Height,FDN->Width,Height),TPoint(X,Y)))
  {
    if (US != viDown)
      US = viNormal;
    if (GS != viDown)
      GS = viNormal;
    DS = viHover;
  }
  else if (PtInRect (TRect(0,FUN->Height+Ct,FGN->Width,FUN->Height+Ct+(Height-FUN->Height-FDN->Height)/FMax),TPoint(X,Y)))
  {
    if (US != viDown)
      US = viNormal;
    if (DS != viDown)
      DS = viNormal;
    GS = viHover;
  }
  if (US != ou || GS != og || DS != od)
    Paint ();
}

void __fastcall TVmxCustomScrollbar::MouseDown (TMouseButton Button, TShiftState Shift, int X, int Y)
{
  TVIState ou, od, og;
  ou = US;
  od = DS;
  og = GS;
  if (PtInRect (TRect(0,0,FUN->Width,FUN->Height),TPoint(X,Y)))
  {
    US = viDown;
    Pos--;
    Ct = (Height-FUN->Height-FDN->Height)*FPos/FMax;
  }
  else if (PtInRect (TRect(0,Height-FDN->Height,FDN->Width,Height),TPoint(X,Y)))
  {
    DS = viDown;
    Pos++;
    Ct = (Height-FUN->Height-FDN->Height)*FPos/FMax;
  }
  else if (PtInRect (TRect(0,FUN->Height+Ct/*(Height-FUN->Height-FDN->Height)*FPos/FMax*/,FGN->Width,FUN->Height+Ct+(Height-FUN->Height-FDN->Height)/FMax/*(Height-FUN->Height-FDN->Height)*(FPos+1)/FMax*/),TPoint(X,Y)))
  {
    GS = viDown;
    tmp = Ct-Y+FUN->Height;
  }
  if (US != ou || GS != og || DS != od)
    Paint ();
}

void __fastcall TVmxCustomScrollbar::MouseUp (TMouseButton Button, TShiftState Shift, int X, int Y)
{
  TVIState ou, od, og;
  ou = US;
  od = DS;
  og = GS;
  if (US==viDown)
  {
    US = viHover;
  }
  else if (DS==viDown)
  {
    DS = viHover;
  }
  else if (GS==viDown)
  {
    GS = viHover;
  }
  if (US != ou || GS != og || DS != od)
    Paint ();
}

//---------------------------------------------------------------------------
namespace Vmxcustomscrollbar
{
        void __fastcall PACKAGE Register()
        {
                 TComponentClass classes[1] = {__classid(TVmxCustomScrollbar)};
                 RegisterComponents("VMX", classes, 0);
        }
}
//---------------------------------------------------------------------------
 