view Navigator.cpp @ 0:a6a46af64546

first upload
author wenx <xue.wen@eecs.qmul.ac.uk>
date Wed, 10 Aug 2011 14:55:38 +0100
parents
children
line wrap: on
line source
/*
    Harmonic Visualiser

    An audio file viewer and editor.
    Centre for Digital Music, Queen Mary, University of London.
    This file copyright 2011 Wen Xue.

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version. 
*/
//---------------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

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

static inline void ValidCtrCheck(TNavigator *)
{
  new TNavigator(NULL);
}
//---------------------------------------------------------------------------
__fastcall TNavigator::TNavigator(TComponent* Owner)
  : TCustomControl(Owner)
{
  x1=y1=0;
  x2=y2=1;
  FOnBackground=0;
  BkgBmp=new Graphics::TBitmap;
}

__fastcall TNavigator::~TNavigator()
{
	delete BkgBmp;
}

void TNavigator::DrawArea()
{
  Canvas->Brush->Style=bsClear;
  Canvas->Pen->Mode=pmXor;
  Canvas->Pen->Color=AreaColorX;
  X1=x1*Width, X2=x2*Width, Y1=y1*Height, Y2=y2*Height;
  if (X1+1<X2 && Y1+1<Y2)
    Canvas->Rectangle(X1, Y1, X2, Y2);
  else if (X1+1>=X2)
  {
    Canvas->MoveTo(X1, Y1);
    Canvas->LineTo(X1, Y2);
  }
  else
  {
    Canvas->MoveTo(X1, Y1);
    Canvas->LineTo(X2, Y1);
  }
}

TNavigatorHitTest TNavigator::HitTest(int X, int Y)
{
  int Xa=1, Ya=1; //borderouter
  int Xb=1, Yb=1; //borderinner
  if (X2-X1<=3) Xb=0;
  if (Y2-Y1<=3) Yb=0;
  if (X2-X1<=1) Xb=-1;
  if (Y2-Y1<=1) Yb=-1;

  TNavigatorHitTest XTest, YTest;

  if (X<X1-Xa || X>X2+Xa) XTest=htOuter;
  else if (X1-Xa<=X && X<=X1+Xb) XTest=htLeft;
  else if (X1+Xb<X && X<X2-Xb) XTest=htInner;
  else XTest=htRight;

  if (Y<Y1-Ya || Y>Y2+Ya) YTest=htOuter;
  else if (Y1-Ya<=Y && Y<=Y1+Yb) YTest=htTop;
  else if (Y1+Yb<Y & Y<Y2-Yb) YTest=htInner;
  else YTest=htBottom;

  if (XTest==htInner && YTest==htInner)
    return htInner;
  if (YTest==htInner && XTest!=htOuter)
    return XTest;
  if (XTest==htInner && YTest!=htOuter)
    return YTest;
  return htOuter;
}

void __fastcall TNavigator::MouseDown(TMouseButton Button, TShiftState Shift, int X, int Y)
{
  if (Button==mbLeft)
  {
    X0=X, Y0=Y;
    x01=x1, x02=x2, y01=y1, y02=y2;

    FMouseAction=maNoAction;

    FHitTest=HitTest(X, Y);
    if (FHitTest!=htOuter) FMouseAction=maMove;

    if (Shift.Contains(ssCtrl))
    {
      switch (FHitTest)
      {
        case htInner:
          break;
        case htLeft:
        case htTop:
        case htRight:
        case htBottom:
        case htTopLeft:
        case htTopRight:
        case htBottomRight:
        case htBottomLeft:
          FMouseAction=maSize; break;
      }
    }

    if (FMouseAction==maMove)
      Cursor=crSizeAll;
    else if (FMouseAction==maSize)
    {
      if (FHitTest==htLeft || FHitTest==htRight)
        Cursor=crSizeWE;
      else
        Cursor=crSizeNS;
    }
    ::SetCursor(Screen->Cursors[Cursor]);
  }
  if (Button==mbRight)
  {
    TPoint P=ClientToScreen(TPoint((X1+X2)/2, (Y1+Y2)/2));
    SetCursorPos(P.x, P.y);
  }
}

void __fastcall TNavigator::MouseMove(TShiftState Shift, int X, int Y)
{
  if (Shift.Contains(ssLeft))
  {
    double destx1=x1, destx2=x2, desty1=y1, desty2=y2;

    int dX=X-X0;
    int dY=Y-Y0;

    double dx=dX*1.0/Width;
    double dy=dY*1.0/Height;

    if (FMouseAction==maMove)
    {
      if (x01+dx<0) dx=-x01;
      if (x02+dx>1) dx=1-x02;
      if (y01+dy<0) dy=-y01;
      if (y02+dy>1) dy=1-y02;
      destx1=x01+dx;
      destx2=x02+dx;
      desty1=y01+dy;
      desty2=y02+dy;
    }
    else if (FMouseAction==maSize)
    {
      switch(FHitTest)
      {
        case htLeft:
          if (x01+dx<0) dx=-x01;
          if (x01+dx>1) dx=1-x01;
          destx1=x01+dx;
          if (destx1>x02) {destx2=destx1; destx1=x02;}
          break;
        case htRight:
          if (x02+dx<0) dx=-x02;
          if (x02+dx>1) dx=1-x02;
          destx2=x02+dx;
          if (x01>destx2) {destx1=destx2; destx2=x01;}
          break;
        case htTop:
          if (y01+dy<0) dy=-y01;
          if (y01+dy>1) dy=1-y01;
          desty1=y01+dy;
          if (desty1>y02) {desty2=desty1; desty1=y02;}
          break;
        case htBottom:
          if (y02+dy<0) dy=-y02;
          if (y02+dy>1) dy=1-y02;
          desty2=y02+dy;
          if (y01>desty2) {desty1=desty2; desty2=y01;}
          break;
      }
    }

    if (destx1!=x1 || destx2!=x2 || desty1!=y1 || desty2!=y2)
    {
      SetArea(destx1, destx2, desty1, desty2);
      FOnAreaChange(this);
    }
  }
  else if (Shift.Contains(ssCtrl))
  {
    TCursor NewCursor;
    FHitTest=HitTest(X, Y);
    if (FHitTest==htLeft || FHitTest==htRight)
      NewCursor=crSizeWE;
    else if (FHitTest==htTop || FHitTest==htBottom)
      NewCursor=crSizeNS;
    else if (FHitTest==htInner)
      NewCursor=crSizeAll;
    else
      NewCursor=crArrow;
    if (Cursor!=NewCursor)
    {
      Cursor=NewCursor;
      ::SetCursor(Screen->Cursors[Cursor]);
    }
  }
  else
  {
    if (Cursor!=crArrow)
    {
      Cursor=crArrow;
      ::SetCursor(Screen->Cursors[Cursor]);
    }
  }
}

void __fastcall TNavigator::MouseUp(TMouseButton Button, TShiftState, int, int)
{
  if (Button==mbLeft)
  {
    Cursor=crArrow;
    ::SetCursor(Screen->Cursors[Cursor]);
  }
}

void __fastcall TNavigator::Paint()
{
  Canvas->CopyRect(ClientRect, BkgBmp->Canvas, ClientRect);//  if (FOnBackground) FOnBackground(this);
  DrawArea();
}

void __fastcall TNavigator::Resize()
{
  BkgBmp->Width=Width;
  BkgBmp->Height=Height;
  if (FOnBackground) FOnBackground(this);
  Invalidate();
  TControl::Resize();
}

void TNavigator::SetArea(double ax1, double ax2, double ay1, double ay2)
{
  if (x1==ax1 && x2==ax2 && y1==ay1 && y2==ay2) return;
  DrawArea();
  x1=ax1, x2=ax2, y1=ay1, y2=ay2;
  DrawArea();
}
//---------------------------------------------------------------------------
namespace Navigator
{
  void __fastcall PACKAGE Register()
  {
    TComponentClass classes[1] = {__classid(TNavigator)};
    RegisterComponents("Samples", classes, 0);
  }
}
//---------------------------------------------------------------------------