#include "FiveWin.ch"

#define SB_HORZ 0
#define SB_VERT 1
#define SB_CTL  2

#define COLOR_SCROLLBAR 0
#define COLOR_WINDOW    5

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

CLASS TScrollBar FROM TControl

   DATA   lVertical, lReDraw, lIsChild, nMin, nMax, nPgStep
   DATA   bGoUp, bGoDown, bGoTop, bGoBottom, bPageUp, bPageDown, bPos

   METHOD New( nRow, nCol, nMin, nMax, nPgStep, lVertical, oWnd, nWidth,;
               nHeight, bUpAction, bDownAction, bPgUp, bPgDown,;
               bPos, lPixel, nClrText, nClrBack ) CONSTRUCTOR

   METHOD WinNew( nMin, nMax, nPgStep, lVertical, oWnd, bUpAction,;
                  bDownAction, bPgUp, bPgDown, bPos, nClrText, nClrBack ) ;
                                                                CONSTRUCTOR

   METHOD Redefine( nID, nMin, nMax, nPgStep, oWnd, bUpAction, bDownAction, ;
                    bPgUp, bPgDown, bPos, nClrText, nClrBack ) CONSTRUCTOR

   METHOD cToChar() INLINE Super:cToChar( "SCROLLBAR" )

   METHOD GetPos() INLINE GetScrollPos( if( ::lIsChild, ::oWnd:hWnd, ::hWnd ),;
            if( ::lIsChild, If( ::lVertical, SB_VERT, SB_HORZ ), SB_CTL ) )

   METHOD GetRange() INLINE GetScrollRange( if( ::lIsChild, ::oWnd:hWnd, ::hWnd ),;
            if( ::lIsChild, If( ::lVertical, SB_VERT, SB_HORZ ), SB_CTL ) )

   METHOD HandleEvent( nMsg, nWParam, nLParam )

   METHOD Init( hDlg ) INLINE  Super:Init( hDlg ), ;
                               ::SetRange( ::nMin, ::nMax ),;
                               ::SetPos( ::nMin )

   // These two have to be BLOCK

   METHOD GoUp()   BLOCK { | Self, nPos | nPos := ::GetPos(),;
                                          if( nPos > ::GetRange()[ 1 ],;
                                              ::SetPos( --nPos ), ),;
                          If( ::bGoUp != nil, Eval( ::bGoUp ),) }

   METHOD GoDown() BLOCK { | Self, nPos | nPos := ::GetPos(),;
                                          if( nPos < ::nMax,;
                                              ::SetPos( ++nPos ), ),;
                          If( ::bGoDown != nil, Eval( ::bGoDown ),) }


   METHOD GoTop() INLINE  ::SetPos( ::nMin ),;
                          If( ::bGoTop != nil, Eval( ::bGoTop ),)

   METHOD GoBottom() INLINE  ::SetPos( ::nMax ),;
                             If( ::bGoBottom != nil, Eval( ::bGoBottom ),)

   METHOD PageUp() INLINE  If( ::bPageUp != nil, Eval( ::bPageUp ),),;
                           ::SetPos( ::GetPos() - ::nPgStep )

   METHOD PageDown() INLINE  If( ::bPageDown != nil, Eval( ::bPageDown ),),;
                                 ::SetPos( ::GetPos() + ::nPgStep )

   METHOD SetPos( nPos ) INLINE ;
                 SetScrollPos( if( ::lIsChild, ::oWnd:hWnd, ::hWnd ),;
                 If( ::lIsChild, If( ::lVertical, SB_VERT, SB_HORZ ), SB_CTL ),;
                 nPos, ::lReDraw )

   METHOD SetRange( nMin, nMax ) INLINE ;
                                  ::nMin := nMin, ::nMax := nMax, ;
           SetScrollRange( if( ::lIsChild, ::oWnd:hWnd, ::hWnd ), ;
               if( ::lIsChild, If( ::lVertical, SB_VERT, SB_HORZ ), SB_CTL ), ;
                    nMin, nMax, ::lReDraw )

   METHOD ThumbPos( nPos ) INLINE  If( ::bPos != nil, Eval( ::bPos, nPos ),)

   METHOD MouseMove( nRow, nCol, nKeyFlags )

ENDCLASS

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

METHOD New( nRow, nCol, nMin, nMax, nPgStep, lVertical, oWnd, nWidth, nHeight,;
            bUpAct, bDownAct, bPgUp, bPgDown, bPos, lPixel, nClrText,;
            nClrBack ) CLASS TScrollBar

   DEFAULT nMin := 0, nMax := 0, nPgStep := 1,;
           lVertical := .t., nWidth := If( lVertical, 16, 200 ),;
           nHeight   := If( lVertical, 200, 17 ),;
           lPixel    := .f.,;
           nClrText  := GetSysColor( COLOR_WINDOW ),;
           nClrBack  := GetSysColor( COLOR_SCROLLBAR )

   ::cCaption   = ""
   ::nTop       = nRow * If( lPixel, 1, 14 )
   ::nLeft      = nCol * If( lPixel, 1,  8 )
   ::nBottom    = ::nTop + nHeight - 1
   ::nRight     = ::nLeft + nWidth - 1
   ::nMin       = nMin
   ::nMax       = nMax
   ::nPgStep    = nPgStep
   ::lVertical  = lVertical
   ::lReDraw    = .t.
   ::nStyle     = nOR( WS_CHILD, WS_VISIBLE, WS_TABSTOP,;
                       If( lVertical, SBS_VERT, SBS_HORZ ) )
   ::bGoUp      = bUpAct
   ::bGoDown    = bDownAct
   ::bPageUp    = bPgUp
   ::bPageDown  = bPgDown
   ::bPos       = bPos
   ::oWnd       = oWnd
   ::lIsChild   = .f.
   ::lDrag      = .f.
   ::lCaptured  = .f.

   ::SetColor( nClrText, nClrBack )

   if oWnd:lVisible
      ::Create( "SCROLLBAR" )
      ::SetRange( ::nMin, ::nMax )
      ::SetPos( ::nMin )
   else
      oWnd:DefControl( Self )
   endif

return nil


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

// Constructor for non-true ScrollBar Controls
// ( when using WS_VSCROLL, WS_HSCROLL styles in a Window )
// They are NOT controls but we consider them as real Objects!

METHOD WinNew( nMin, nMax, nPgStep, lVertical, oWnd, bUpAction,;
               bDownAction, bPgUp, bPgDown, bPos, nClrText, nClrBack ) CLASS TScrollBar

   DEFAULT nMin := 1, nMax := 2, nPgStep := 1, lVertical := .t.,;
           nClrText  := GetSysColor( COLOR_WINDOW ),;
           nClrBack  := GetSysColor( COLOR_SCROLLBAR )


   ::oWnd      = oWnd
   ::lVertical = lVertical
   ::lReDraw   = .t.
   ::lIsChild  = .t.
   ::nMin      = nMin
   ::nMax      = nMax
   ::nPgStep   = nPgStep
   ::bGoUp     = bUpAction
   ::bGoDown   = bDownAction
   ::bPageUp   = bPgUp
   ::bPageDown = bPgDown
   ::bPos      = bPos

   ::SetColor( nClrText, nClrBack )
   ::SetRange( nMin, nMax )
   ::SetPos( nMin )

return nil

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

METHOD Redefine( nID, nMin, nMax, nPgStep, oWnd, bUpAction, bDownAction, ;
                 bPgUp, bPgDown, bPos, nClrText, nClrBack ) CLASS TScrollbar

   DEFAULT nMin := 0, nMax := 0, nPgStep := 1,;
           nClrText  := GetSysColor( COLOR_WINDOW ),;
           nClrBack  := GetSysColor( COLOR_SCROLLBAR )


   ::nID        = nID
   ::nMin       = nMin
   ::nMax       = nMax
   ::nPgStep    = nPgStep
   ::lVertical  = .f.
   ::lReDraw    = .t.
   ::bGoUp      = bUpAction
   ::bGoDown    = bDownAction
   ::bPageUp    = bPgUp
   ::bPageDown  = bPgDown
   ::bPos       = bPos
   ::oWnd       = oWnd
   ::lIsChild   = .f. // .t. only for Windows with WS_HSCROLL ¢ WS_VSCROLL style
   ::lRedraw    = .t.
   ::oWnd       = oWnd
   ::lDrag      = .f.
   ::lCaptured  = .f.

   ::SetColor( nClrText, nClrBack )
   oWnd:DefControl( Self )

return nil

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

METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS TScrollBar

   do case
      case nMsg == WM_SCROLLUP
           ::GoUp()
           return 0

      case nMsg == WM_SCROLLDOWN
           ::GoDown()
           return 0

      case nMsg == WM_SCROLLPGUP
           ::PageUp()
           return 0

      case nMsg == WM_SCROLLPGDN
           ::PageDown()
           return 0

      case nMsg == FW_THUMBPOS
           ::ThumbPos( nWParam )
           return 0
   endcase

return Super:HandleEvent( nMsg, nWParam, nLParam )

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

METHOD MouseMove( nRow, nCol, nKeyFlags ) CLASS TScrollBar

   local nResult := Super:MouseMove( nRow, nCol, nKeyFlags )

return If( ::lDrag, nResult, nil )    // We want standard behavior !!!

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