/*
 * Xailer source code:
 *
 * ScrollBar.prg
 * Clase TScrollBar()
 *
 * Copyright 2003, 2007 Ignacio Ortiz de Zuņiga
 * Copyright 2003, 2007 Xailer.com
 * All rights reserved
 *
 */

#include "Xailer.ch"


//--------------------------------------------------------------------------

CLASS XScrollBar FROM TStdControl

PUBLISHED:
   PROPERTY nWidth            INIT 100
   PROPERTY nHeight           INIT 20
   PROPERTY nClrPane          INIT clScrollBar  EDITOR PE_Color

   PROPERTY nOrientation      INIT orHORIZONTAL VALUES orHORIZONTAL, orVERTICAL
   PROPERTY nPos              INIT 0   WRITE METHOD SetPos
   PROPERTY nMin              INIT 0   WRITE METHOD SetRange
   PROPERTY nMax              INIT 10  WRITE INLINE ::SetRange( ,Value )
   PROPERTY nPage             INIT 1   WRITE METHOD SetPage
   PROPERTY lDisableNoScroll  INIT .F.

   EVENT OnUp( oSender, nPos ) // --> nStep | Nil
   EVENT OnDown( oSender, nPos ) // --> nStep | Nil
   EVENT OnPageUp( oSender, nPage ) // --> nStep | Nil
   EVENT OnPageDown( oSender, nPage ) // --> nStep | Nil
   EVENT OnThumbPos( oSender, nTrackPos ) // --> nStep | Nil
   EVENT OnThumbTrack(oSender, nTrackPos ) // --> nStep | Nil
   EVENT OnChange( oSender, nPos, nOldPos ) // --> lResult

PUBLIC:
   PROPERTY oBrush AS TBrush

PROTECTED:
   DATA cWinClassName   INIT "SCROLLBAR"
   DATA nCtlStyle       INIT nOr( WS_CHILD, WS_CLIPCHILDREN, WS_CLIPSIBLINGS )
   PROPERTY cText

   PROPERTY l3D
   PROPERTY lBorder
   PROPERTY lParentFont
   PROPERTY nClrText
   PROPERTY oFont

PUBLIC:
   CONSTRUCTOR Create( oParent )
   METHOD Inc( nValue ) INLINE ( IIf( nValue == Nil, nValue := 1, ), ::nPos += nValue ) // --> Nil
   METHOD Dec( nValue ) INLINE ( IIf( nValue == Nil, nValue := 1, ), ::nPos -= nValue ) // --> Nil

RESERVED:
   METHOD SetRange( nMin, nMax )
   METHOD SetPos( nValue, lTriggerOnChange )
   METHOD SetPage( nValue )
   METHOD UpdateInfo()
   METHOD GetCtlColor( hDC )
   METHOD EnableButton( nButton ) INLINE EnableScrollBar( ::Handle, SB_CTL, nButton )
   METHOD WMHScroll() EXTERN TScrollBar_WMScroll( sbHORIZONTAL )
   METHOD WMVScroll() EXTERN TScrollBar_WMScroll( sbVERTICAL )

ENDCLASS

//--------------------------------------------------------------------------

METHOD Create( oParent ) CLASS XScrollBar

   IF ::nOrientation == orHORIZONTAL
      ::nCtlStyle := nOr( ::nCtlStyle, SBS_HORZ )
   ELSE
      ::nCtlStyle := nOr( ::nCtlStyle, SBS_VERT )
   ENDIF

   ::Super:Create( oParent )

   ::SetRange()
   ::SetPage()
   ::SetPos()

RETURN Self

//--------------------------------------------------------------------------

METHOD SetPos( nValue, lTriggerOnChange ) CLASS XScrollBar

   LOCAL nOld

   DEFAULT lTriggerOnChange TO .F.

   nOld := ::FnPos

   UPDATE ::FnPos TO nValue

   IF ! Empty( ::Handle )
      ::FnPos := SetScrollPos( ::Handle, SB_CTL, ::FnPos, ::lDisableNoScroll, .T. )
   ENDIF

   IF nOld != ::FnPos .AND. lTriggerOnChange
      ::OnChange( ::FnPos )
   ENDIF

RETURN ::FnPos

//--------------------------------------------------------------------------

METHOD SetPage( nValue ) CLASS XScrollBar

   LOCAL nOld

   nOld := ::FnPage

   UPDATE ::FnPage TO nValue

   IF ! Empty( ::Handle )
      SetScrollPage( ::Handle, SB_CTL, ::FnPage, ::lDisableNoScroll, .T. )
   ENDIF

RETURN nOld

//--------------------------------------------------------------------------

METHOD SetRange( nMin, nMax ) CLASS XScrollBar

   LOCAL nOldMin, nOldMax

   nOldMin := nMin
   nOldMax := nMax

   UPDATE ::FnMin TO nMin
   UPDATE ::FnMax TO nMax

   IF ! Empty( ::Handle )
      SetScrollRange( ::Handle, SB_CTL, ::FnMin, ::FnMax, ::lDisableNoScroll, .T. )
   ENDIF

RETURN { nOldMin, nOldMax }

//--------------------------------------------------------------------------

METHOD UpdateInfo() CLASS XScrollBar

   LOCAL aInfo

   IF ! Empty( ::Handle )
      aInfo    := GetScrollInfo( ::Handle, SB_CTL )
      ::FnMin  := aInfo[ 1 ]
      ::FnMax  := aInfo[ 2 ]
      ::FnPage := aInfo[ 3 ]
      ::FnPos  := aInfo[ 4 ]
   ENDIF

RETURN Nil

//--------------------------------------------------------------------------

METHOD GetCtlColor( hDC ) CLASS XScrollBar

   IF ::nClrPane == clScrollBar
      RETURN Nil
   ENDIF

RETURN ::Super:GetCtlColor( hDC )

//--------------------------------------------------------------------------

#pragma BEGINDUMP

#include <windows.h>
#include <xailer.h>

//--------------------------------------------------------------------------

HB_FUNC_STATIC( TSCROLLBAR_WMSCROLL )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hWnd     = GetHandleOf( Self );
   int iCode     = LOWORD( hb_parnl( 1 ) );
   int nInc;
   SCROLLINFO si;

   si.cbSize = sizeof( SCROLLINFO );
   si.fMask = SIF_POS | SIF_PAGE | SIF_TRACKPOS | SIF_RANGE;
   GetScrollInfo( hWnd, SB_CTL, &si );

   hb_ret();

   if ( hb_parnl( 2 ) == 0 )
   {
   switch ( iCode )
      {
      case SB_LINEUP:
         XA_ObjSendNL( Self, "OnUp", si.nPos );
         nInc = ( HB_ISNUM( -1 ) ? hb_parnl( -1 ) : 1 );
         XA_ObjSendNL2( Self, "OnChange", max( si.nPos - nInc, si.nMin ), si.nPos );
         if( HB_ISNIL( -1 ) || hb_parl( -1 ) )
            XA_ObjSendNL( Self, "Dec", nInc );
         break;
      case SB_LINEDOWN:
         XA_ObjSendNL( Self, "OnDown", si.nPos );
         nInc = ( HB_ISNUM( -1 ) ? hb_parnl( -1 ) : 1 );
         XA_ObjSendNL2( Self, "OnChange", min( si.nPos + nInc, si.nMax ), si.nPos );
         if( HB_ISNIL( -1 ) || hb_parl( -1 ) )
            XA_ObjSendNL( Self, "Inc", nInc );
         break;
      case SB_PAGEUP:
         XA_ObjSendNL( Self, "OnPageUp", si.nPos );
         nInc = ( HB_ISNUM( -1 ) ? hb_parnl( -1 ) : (int) si.nPage );
         XA_ObjSendNL2( Self, "OnChange", max( si.nPos - nInc, si.nMin ), si.nPos );
         if( HB_ISNIL( -1 ) || hb_parl( -1 ) )
            XA_ObjSendNL( Self, "Dec", nInc );
         break;
      case SB_PAGEDOWN:
         XA_ObjSendNL( Self, "OnPageDown", si.nPos );
         nInc = ( HB_ISNUM( -1 ) ? hb_parnl( -1 ) : (int) si.nPage );
         XA_ObjSendNL2( Self, "OnChange", min( si.nPos + nInc, si.nMax ), si.nPos );
         if( HB_ISNIL( -1 ) || hb_parl( -1 ) )
            XA_ObjSendNL( Self, "Inc", nInc );
         break;
      case SB_THUMBTRACK:
         {
         XA_ObjSendNL( Self, "OnThumbTrack", si.nTrackPos );
         nInc = ( HB_ISNUM( -1 ) ? hb_parnl( -1 ) : si.nTrackPos );
         XA_ObjSendNL2( Self, "OnChange", nInc, si.nPos );
         if( HB_ISNIL( -1 ) || hb_parl( -1 ) )
            XA_ObjSendNL( Self, "SetPos", nInc );
         break;
         }
      case SB_THUMBPOSITION:
         {
         XA_ObjSendNL( Self, "OnThumbPos", si.nTrackPos );
         nInc = ( HB_ISNUM( -1 ) ? hb_parnl( -1 ) : si.nTrackPos );
         XA_ObjSendNL2( Self, "OnChange", nInc, si.nPos );
         if( HB_ISNIL( -1 ) || hb_parl( -1 ) )
            XA_ObjSendNL( Self, "SetPos", si.nTrackPos );
         break;
         }
      default:
         break;
      }
   }
}

//--------------------------------------------------------------------------

XA_FUNC( SETSCROLLPOS ) // SetScrollPos( <hWnd>, <nType>, <nPosition>, <lDisableNoScroll>, <lRedraw> ) --> nOldPosition
{
   SCROLLINFO si;

   si.cbSize = sizeof( SCROLLINFO );
   si.fMask = SIF_POS;
   si.nPos = hb_parnl( 3 );
   if ( hb_parl( 4 ) )
      si.fMask |= SIF_DISABLENOSCROLL;

   hb_retnl( SetScrollInfo( (HWND) hb_parnl( 1 ), hb_parni( 2 ), &si, (BOOL) hb_parl( 5 ) ) );
}

//--------------------------------------------------------------------------

XA_FUNC( GETSCROLLPOS ) // GetScrollPos( <hWnd>, <nType> ) --> nResult
{
   SCROLLINFO si;

   si.cbSize = sizeof( SCROLLINFO );
   si.fMask = SIF_POS;

   GetScrollInfo( (HWND) hb_parnl( 1 ), hb_parni( 2 ), &si );
   hb_retnl( si.nPos );
}

//--------------------------------------------------------------------------

XA_FUNC( SETSCROLLRANGE ) // SetScrollRange( <hWnd>, <nType>, <nMin>, <nMax>, <lDisableNoScroll>, <lRedraw> ) --> nPosition
{
   SCROLLINFO si;

   si.cbSize = sizeof( SCROLLINFO );
   si.fMask = SIF_RANGE;
   si.nMin = hb_parnl( 3 );
   si.nMax = hb_parnl( 4 );
   if ( hb_parl( 5 ) )
      si.fMask |= SIF_DISABLENOSCROLL;

   hb_retnl( SetScrollInfo( (HWND) hb_parnl( 1 ), hb_parni( 2 ), &si, (BOOL) hb_parl( 6 ) ) );
}

//--------------------------------------------------------------------------

XA_FUNC( GETSCROLLRANGE ) // GetScrollRange( <hWnd>, <nType> ) --> aRange
{
   SCROLLINFO si;

   si.cbSize = sizeof( SCROLLINFO );
   si.fMask = SIF_RANGE;

   GetScrollInfo( (HWND) hb_parnl( 1 ), hb_parni( 2 ), &si );
   hb_reta( 2 );
   hb_storvnl( si.nMin, -1, 1 );
   hb_storvnl( si.nMax, -1, 2 );
}

//--------------------------------------------------------------------------

XA_FUNC( SETSCROLLPAGE ) // SetScrollPage( <hWnd>, <nType>, <nPage>, <lDisableNoScroll>, <lRedraw> ) --> nPage
{
   SCROLLINFO si;

   si.cbSize = sizeof( SCROLLINFO );
   si.fMask = SIF_PAGE;
   si.nPage = hb_parnl( 3 );
   if ( hb_parl( 4 ) )
      si.fMask |= SIF_DISABLENOSCROLL;

   hb_retnl( SetScrollInfo( (HWND) hb_parnl( 1 ), hb_parni( 2 ), &si, (BOOL) hb_parl( 5 ) ) );
}

//--------------------------------------------------------------------------

XA_FUNC( GETSCROLLPAGE ) // GetScrollRange( <hWnd>, <nType> ) --> nPage
{
   SCROLLINFO si;

   si.cbSize = sizeof( SCROLLINFO );
   si.fMask = SIF_PAGE;

   GetScrollInfo( (HWND) hb_parnl( 1 ), hb_parni( 2 ), &si );
   hb_retnl( si.nPage );
}

//--------------------------------------------------------------------------

XA_FUNC( SETSCROLLINFO ) // SetScrollInfo( <hWnd>, <nType>, <nMin>, <nMax>, <nPage>, <nPos>, <lDisableNoScroll>, <lRedraw> ) --> nPosition
{
   SCROLLINFO si;

   si.cbSize = sizeof( SCROLLINFO );
   si.fMask = 0;
   if ( HB_ISNUM( 3 ) )
      {
      si.nMin  = hb_parnl( 3 );
      si.fMask |= SIF_RANGE;
      }
   if ( HB_ISNUM( 4 ) )
      {
      si.nMax  = hb_parnl( 4 );
      si.fMask |= SIF_RANGE;
      }
   if ( HB_ISNUM( 5 ) )
      {
      si.nPage = hb_parnl( 5 );
      si.fMask |= SIF_PAGE;
      }
   if ( HB_ISNUM( 6 ) )
      {
      si.nPos  = hb_parnl( 6 );
      si.fMask |= SIF_POS;
      }
   if ( HB_ISLOG( 7 ) && hb_parl( 7 ) )
      {
      si.fMask |= SIF_DISABLENOSCROLL;
      }

   hb_retnl( SetScrollInfo( (HWND) hb_parnl( 1 ), hb_parni( 2 ), &si, (BOOL) hb_parl( 8 ) ) );
}

//--------------------------------------------------------------------------

XA_FUNC( GETSCROLLINFO ) // GetScrollInfo( <hWnd>, <nType> ) --> aScrollInfo
{
   SCROLLINFO si;

   si.cbSize = sizeof( SCROLLINFO );
   si.fMask = SIF_ALL;

   GetScrollInfo( (HWND) hb_parnl( 1 ), hb_parni( 2 ), &si );
   hb_reta( 5 );
   hb_storvnl( si.nMin, -1, 1 );
   hb_storvnl( si.nMax, -1, 2 );
   hb_storvnl( si.nPage, -1, 3 );
   hb_storvnl( si.nPos, -1, 4 );
   hb_storvnl( si.nTrackPos, -1, 5 );
}

//--------------------------------------------------------------------------

XA_FUNC( SHOWSCROLLBAR ) // ShowScrollBar( <hWnd>, <nType>, <lShow> ) --> lSuccess
{
   hb_retl( ShowScrollBar( (HWND) hb_parnl( 1 ), hb_parni( 2 ), (BOOL) hb_parl( 3 ) ) );
}

//--------------------------------------------------------------------------

XA_FUNC( ENABLESCROLLBAR ) // EnableScrollBar( <hWnd>, <nType>, <nArrows> ) --> lSuccess
{
   hb_retl( EnableScrollBar( (HWND) hb_parnl( 1 ), hb_parni( 2 ), hb_parni( 3 ) ) );
}

#pragma ENDDUMP

//--------------------------------------------------------------------------
