/*
 * Xailer source code:
 *
 * TrackBar.prg
 * Clase TTrackBar
 *
 * Copyright 2003, 2007 Jose Lalin
 * Copyright 2003, 2007 Xailer.com
 * All rights reserved
 *
 */

#include "Xailer.ch"
#include "CommCtrl.api"


//--------------------------------------------------------------------------

CLASS XTrackBar FROM TStdControl

PUBLISHED:
   PROPERTY nWidth         INIT 120
   PROPERTY nHeight        INIT 30

   PROPERTY nValue         INIT   0 READ GetPos WRITE INLINE ::SetPos( Value, .T. )
   PROPERTY nMin           INIT   0 WRITE INLINE ::SetRangeMin( Value, .T. )
   PROPERTY nMax           INIT 100 WRITE INLINE ::SetRangeMax( Value, .T. )

   PROPERTY nLineSize      INIT   1 READ GetLineSize  WRITE SetLineSize
   PROPERTY nPageSize      INIT  10 READ GetPageSize  WRITE SetPageSize

   PROPERTY nSelStart      INIT   0 READ GetSelStart  WRITE INLINE ::SetSelStart( Value, .T. )
   PROPERTY nSelEnd        INIT   0 READ GetSelEnd    WRITE INLINE ::SetSelEnd( Value, .T. )

   PROPERTY lAutoTicks     INIT .T.
   PROPERTY lNoTicks       INIT .F.
   PROPERTY lSelRange      INIT .F.
   PROPERTY lNoThumb       INIT .F.
   PROPERTY lFixedLength   INIT .F.
   PROPERTY lReversed      INIT .F.
   PROPERTY lTooltips      INIT .F.
   PROPERTY lDownIsLeft    INIT .F.
   PROPERTY nOrientation   INIT orHORIZONTAL VALUES orHORIZONTAL, orVERTICAL
   PROPERTY nTickStyle     INIT tbtTOP       VALUES tbtTOP, tbtBOTTOM, tbtLEFT, tbtRIGHT, tbtBOTH
   PROPERTY nTipSide       INIT tbsBOTTOM    VALUES tbsTOP, tbsLEFT, tbsBOTTOM, tbsRIGHT
   PROPERTY nTickFreq      INIT 10  WRITE SetTickFreq

   PROPERTY lTransparent   INIT .F.

   EVENT OnChange( oSender )  // --> Nil

PUBLIC:
	PROPERTY cText

PROTECTED:
   PROPERTY l3D
   PROPERTY lBorder
   PROPERTY oFont
   PROPERTY lParentFont       INIT .F.
   PROPERTY lDragAcceptFiles  INIT .F.

   DATA lSelecting   INIT .F.
   DATA cWinClassName INIT TRACKBAR_CLASS

   EVENT OnClick
   EVENT OnDblClick

PUBLIC:
   METHOD Create( oParent ) CONSTRUCTOR

   METHOD SetTick( nPos )           INLINE ::SendMsg( TBM_SETTIC, 0, nPos ) // --> Nil
   METHOD GetTick( nTic )           INLINE ::SendMsg( TBM_GETTIC, nTic - 1, 0 ) // --> nPosition
   METHOD GetTickPos( nTic )        INLINE ::SendMsg( TBM_GETTICPOS, nTic - 1, 0 ) // --> nPosition
   METHOD GetNumTicks()             INLINE ::SendMsg( TBM_GETNUMTICS, 0, 0 ) // --> nResult
   METHOD GetTicks() // --> aTick
   METHOD ClearTicks( lRedraw )     INLINE ::SendMsg( TBM_CLEARTICS, lRedraw, 0 ) // --> Nil

RESERVED:
   METHOD SetPos( nPos, lRedraw )
   METHOD GetPos()
   METHOD VerifyPos( nPos )         INLINE ::SendMsg( TBM_SETPOS, .F., nPos )

   METHOD SetRange( nMin, nMax, lRedraw ) INLINE ::SendMsg( TBM_SETRANGE, lRedraw, MakeLong( nMin, nMax ) )
   METHOD SetRangeMax( nValue, lRedraw )  INLINE ::FnMax := nValue, ::SendMsg( TBM_SETRANGEMAX, lRedraw, nValue )
   METHOD SetRangeMin( nValue, lRedraw )  INLINE ::FnMin := nValue, ::SendMsg( TBM_SETRANGEMIN, lRedraw, nValue )
   METHOD GetRangeMax()                   INLINE ::SendMsg( TBM_GETRANGEMAX, 0, 0 )
   METHOD GetRangeMin()                   INLINE ::SendMsg( TBM_GETRANGEMIN, 0, 0 )
   METHOD SetTickFreq( nFreq )            INLINE ::FnTickFreq := nFreq, ::SendMsg( TBM_SETTICFREQ, nFreq, 0 )

   METHOD SetLineSize( nSize )            INLINE ::SendMsg( TBM_SETLINESIZE, 0, nSize ), ::FnLineSize := nSize
   METHOD GetLineSize()                   INLINE ::SendMsg( TBM_GETLINESIZE, 0, 0 )

   METHOD SetPageSize( nSize )            INLINE ::SendMsg( TBM_SETPAGESIZE, 0, nSize ), ::FnPageSize := nSize
   METHOD GetPageSize()                   INLINE ::SendMsg( TBM_GETPAGESIZE, 0, 0 )

   METHOD SetSel( nMin, nMax, lRedraw )   INLINE ::SendMsg( TBM_SETSEL, lRedraw, MakeLong( nMin, nMax ) )
   METHOD SetSelStart( nValue, lRedraw )  INLINE ::SendMsg( TBM_SETSELSTART, lRedraw, nValue )
   METHOD SetSelEnd( nValue, lRedraw )    INLINE ::SendMsg( TBM_SETSELEND, lRedraw, nValue )
   METHOD GetSelStart()                   INLINE ::SendMsg( TBM_GETSELSTART, 0, 0 )
   METHOD GetSelEnd()                     INLINE ::SendMsg( TBM_GETSELEND, 0, 0 )
   METHOD ClearSel( lRedraw )             INLINE ::SendMsg( TBM_CLEARSEL, lRedraw, 0 )

   METHOD GetChannelRect()
   METHOD GetThumbRect()
   METHOD SetThumbLength( nLen )    INLINE ::SendMsg( TBM_SETTHUMBLENGTH, nLen, 0 )
   METHOD GetThumbLength()          INLINE ::SendMsg( TBM_GETTHUMBLENGTH, 0, 0 )

   METHOD SetBuddy( lLeft, hBuddy ) INLINE ::SendMsg( TBM_SETBUDDY, lLeft, hBuddy )
   METHOD GetBuddy( lLeft )         INLINE ::SendMsg( TBM_GETBUDDY, lLeft, 0 )

   METHOD SetTooltips( hTooltip )   INLINE ::SendMsg( TBM_SETTOOLTIPS, hToolTip, 0 )
   METHOD GetTooltips()             INLINE ::SendMsg( TBM_GETTOOLTIPS, 0, 0 )

   METHOD SetTipSide( nSide )       INLINE ::SendMsg( TBM_SETTIPSIDE, nSide, 0 )

   METHOD Notify( nWParam, nLParam )

   METHOD Change() INLINE IIf( ! Empty( ::Handle ), ::OnChange(), )

   METHOD WMLButtonUp( nWParam, nLParam )
   METHOD WMLButtonDown( nWParam, nLParam )
   METHOD WMKeyDown( nKey, nFlags, hWnd )
   METHOD WMMouseMove( nWParam, nLParam )
   METHOD WMMouseWheel( nWParam, nLParam )

   METHOD WMEraseBkgnd() INLINE 1
   METHOD WMPaint() EXTERN XControl_EraseAndPaint()

ENDCLASS

//--------------------------------------------------------------------------

METHOD WMKeyDown( nWParam, nLParam, hWnd ) CLASS XTrackBar

   LOCAL nPos := ::nValue

   PrevWindowProc( ::Handle, WM_KEYDOWN, nWParam, nLParam )

   IF nPos != ::nValue
      ::Change()
   ENDIF

   ::Super:WMKeyDown( nWParam, nLParam, hWnd )

RETURN 0

//--------------------------------------------------------------------------

METHOD Create( oParent ) CLASS XTrackBar

   InitCommonControls( ICC_BAR_CLASSES )

   ::ChangeCtlStyle( TBS_AUTOTICKS, ::lAutoTicks )
   ::ChangeCtlStyle( TBS_NOTICKS, ::lNoTicks )
   ::ChangeCtlStyle( TBS_NOTHUMB, ::lNoThumb )
   ::ChangeCtlStyle( TBS_ENABLESELRANGE, ::lSelRange )
   ::ChangeCtlStyle( TBS_FIXEDLENGTH, ::lFixedLength )
   ::ChangeCtlStyle( TBS_TOOLTIPS, ::lToolTips )
   ::ChangeCtlStyle( TBS_REVERSED, ::lReversed )
   ::ChangeCtlStyle( TBS_DOWNISLEFT, ::lDownIsLeft )
   ::ChangeCtlStyle( TBS_HORZ, ::nOrientation == orHORIZONTAL )
   ::ChangeCtlStyle( TBS_VERT, ::nOrientation == orVERTICAL )

   IF ::nTickStyle != 0
      ::nCtlStyle := nOr( ::nCtlStyle, ::nTickStyle )
   ENDIF

   IF ::lToolTips
      ::SetTipSide( ::FnTipSide )
   ENDIF

   ::Super:Create( oParent )

   ::SetRange( ::FnMin, ::FnMax )
   ::SetLineSize( ::FnLineSize )
   ::SetPageSize( ::FnPageSize )
   ::SetPos( ::FnValue )
   ::SetTickFreq( ::FnTickFreq )

RETURN Self

//--------------------------------------------------------------------------

METHOD GetPos() CLASS XTrackBar

   IF ! Empty( ::Handle )
      ::FnValue := ::SendMsg( TBM_GETPOS, 0, 0 )
   ENDIF

RETURN ::FnValue

//--------------------------------------------------------------------------

METHOD SetPos( Value, lRedraw ) CLASS XTrackBar

   ::FnValue := Value

   IF ! Empty( ::Handle )
      ::SendMsg( TBM_SETPOS, lRedraw, Value )
   ENDIF

RETURN Nil

//--------------------------------------------------------------------------

METHOD WMLButtonDown( nWParam, nLParam ) CLASS XTrackBar

   IF ::lSelRange
      IF lAnd( nWParam, MK_SHIFT )
         IF ! ::lSelecting
            ::FnSelStart := ::GetPos()
            ::SetSelStart( ::FnSelStart, .T. )
            ::lSelecting := .T.
            RETURN .T.
         ENDIF
      ENDIF
   ENDIF

RETURN ::Super:WMLButtonDown( nWParam, nLParam )

//--------------------------------------------------------------------------

METHOD WMLButtonUp( nWParam, nLParam ) CLASS XTrackBar

   IF ::lSelRange
      IF lAnd( nWParam, MK_SHIFT )
         IF ::lSelecting
            IF ::FnSelStart != ::GetPos()
               ::FnSelEnd   := ::GetPos()
               ::lSelecting := .F.
               ::SetSelEnd( ::FnSelEnd, .T. )
               RETURN .T.
            ENDIF
         ENDIF
      ENDIF
   ENDIF

RETURN ::Super:WMLButtonUp( nWParam, nLParam )

//--------------------------------------------------------------------------

METHOD WMMouseMove( nWParam, nLParam ) CLASS XTrackBar

   LOCAL nValue := ::nValue

   PrevWindowProc( ::Handle, WM_MOUSEMOVE, nWParam, nLParam )
   IF nValue != ::nValue
      ::Change()
   ENDIF

RETURN ::Super:WMMouseMove( nWParam, nLParam )

//--------------------------------------------------------------------------

METHOD WMMouseWheel( nWParam, nLParam ) CLASS XTrackBar

   LOCAL nValue := ::nValue

   PrevWindowProc( ::Handle, WM_MOUSEWHEEL, nWParam, nLParam )
   IF nValue != ::nValue
      ::Change()
   ENDIF

RETURN 0

//--------------------------------------------------------------------------

#pragma BEGINDUMP

#include <windows.h>
#include <commctrl.h>
#include <xailer.h>

//--------------------------------------------------------------------------

void XTrackBar_Notify( PHB_ITEM, LPNMHDR );

HB_FUNC_STATIC( XTRACKBAR_NOTIFY )
{
   LPNMHDR nmhdr = (LPNMHDR) hb_parnl( 2 );
   PHB_ITEM Self = hb_stackSelfItem();

   hb_ret();
   switch( nmhdr->code )
   {
      case NM_RELEASEDCAPTURE:
         XA_ObjSend( Self, "Change" );
         break;
      default:
         XTrackBar_Notify( Self, nmhdr );
   }
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XTRACKBAR_GETCHANNELRECT )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hwnd = GetHandleOf( Self );
   RECT rc;

   SendMessage( hwnd, TBM_GETCHANNELRECT, 0, (LPARAM) &rc );

   hb_reta( 4 );
   hb_storvni( rc.left  , -1, 1 );
   hb_storvni( rc.top   , -1, 2 );
   hb_storvni( rc.bottom, -1, 3 );
   hb_storvni( rc.right , -1, 4 );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XTRACKBAR_GETTHUMBRECT )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HANDLE hwnd = GetHandleOf( Self );
   RECT rc;

   SendMessage( hwnd, TBM_GETTHUMBRECT, 0, (LPARAM) &rc );

   hb_reta( 4 );
   hb_storvnl( rc.left  , -1, 1 );
   hb_storvnl( rc.top   , -1, 2 );
   hb_storvnl( rc.bottom, -1, 3 );
   hb_storvnl( rc.right , -1, 4 );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XTRACKBAR_GETTICKS )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HANDLE hwnd = GetHandleOf( Self );
   LONG lTicks = SendMessage( hwnd, TBM_GETNUMTICS, 0, 0 ) - 2;

   if( lTicks )
   {
      DWORD * dwTicks = (DWORD *) SendMessage( hwnd, TBM_GETPTICS, 0, 0 );
      LONG i;

      hb_reta( lTicks );
      for( i = 0; i < lTicks; i++ )
         hb_storvnl( dwTicks[ i ], -1, i + 1 );
   }
   else
      hb_reta( 0 );
}

#pragma ENDDUMP

//--------------------------------------------------------------------------
