/*
 * Xailer source code:
 *
 * GestureControl.prg
 * Clase GestureControl()
 *
 * Copyright 2016 Jose F. Gimenez
 * Copyright 2016 Xailer.com
 * All rights reserved
 *
 */

#include "Xailer.ch"
#include "Gestures.ch"

//------------------------------------------------------------------------------

CLASS XGestureControl FROM TScrollingWinControl

PROTECTED:
   DATA nGestureX
   DATA nGestureY

RESERVED:
   METHOD Create( oParent )
   METHOD SetGestureConfig()
   METHOD Gesture( nId, nFlags, x, y, nInfo )
   METHOD VAdjust( lRedraw )
   METHOD HAdjust( lRedraw )
   METHOD WMMouseWheel( nWParam, nLParam )
   METHOD WMGesture( nWParam, nLParam )

ENDCLASS

//------------------------------------------------------------------------------

METHOD Create( oParent ) CLASS XGestureControl

   ::Super:Create( oParent )
   ::SetGestureConfig()

RETURN Self

//------------------------------------------------------------------------------

METHOD Gesture( nId, nFlags, x, y, nInfo ) CLASS XGestureControl

   IF nId == GID_PAN
      IF lAnd( nFlags, GF_BEGIN )
         ::nGestureX := x - ::nClientLeft
         ::nGestureY := y - ::nClientTop
         IF ::lVScroll
            Screen:oTouchScrollBarV:Show()
         ENDIF
         IF ::lHScroll
            Screen:oTouchScrollBarH:Show()
         ENDIF
      ELSEIF lAnd( nFlags, GF_END )
         ::nGestureX := Nil
         ::nGestureY := Nil
         Screen:oTouchScrollBarH:Hide()
         Screen:oTouchScrollBarV:Hide()
      ELSE
         IF ::lHScroll
            ::nClientLeft := Min( 0, x - ::nGestureX )
         ENDIF
         IF ::lVScroll
            ::nClientTop := Min( 0, y - ::nGestureY )
         ENDIF
         ::Adjust()
         ::Refresh()
      ENDIF
   ENDIF

RETURN ::Super:Gesture( nId, nFlags, x, y, nInfo )

//------------------------------------------------------------------------------

METHOD VAdjust( lRedraw ) CLASS XGestureControl

   LOCAL lScrolled := .F.
   LOCAL nLeft, nTop

   IF ! Empty( ::Handle ) .AND. ::FlAutoScroll
      IF ::FnClientTop + ::FnVirtualHeight < ::nClientHeight
         ::FnClientTop := Min( ::nClientHeight - ::FnVirtualHeight, 0 )
         lScrolled := .T.
      ENDIF
      ::lVScroll := ::FnVirtualHeight > ::nClientHeight
      IF Screen:lTouch
         IF ::lVScroll
            WITH OBJECT Screen:oTouchScrollBarV
               IF :lVisible
                  nLeft := 0
                  nTop := 0
                  ::ClientToScreen( @nLeft, @nTop )
                  :SetBounds( nLeft + ::nWidth - 12, nTop - MulDiv( ::nClientTop, ::nClientHeight, ::nVirtualHeight ), 6, MulDiv( ::nHeight, ::nClientHeight, ::nVirtualHeight ) )
               ENDIF
            END
         ENDIF
      ELSEIF !::IsHideScrollBars()
         SetScrollInfo( ::Handle, SB_VERT, 0, ::FnVirtualHeight - 1, ::nClientHeight, -::FnClientTop, .F., lRedraw )
      ENDIF
   ENDIF

RETURN lScrolled

//--------------------------------------------------------------------------

METHOD HAdjust( lRedraw ) CLASS XGestureControl

   LOCAL lScrolled := .F.
   LOCAL nLeft, nTop

   IF ! Empty( ::Handle ) .AND. ::FlAutoScroll
      IF ::FnClientLeft + ::FnVirtualWidth < ::nClientWidth
         ::FnClientLeft := Min( ::nClientWidth - ::FnVirtualWidth, 0 )
         lScrolled := .T.
      ENDIF
      ::lHScroll := ::FnVirtualWidth > ::nClientWidth
      IF Screen:lTouch
         IF ::lHScroll
            WITH OBJECT Screen:oTouchScrollBarH
               nLeft := 0
               nTop := 0
               ::ClientToScreen( @nLeft, @nTop )
               :SetBounds( nLeft - MulDiv( ::nClientLeft, ::nClientWidth, ::nVirtualWidth ), nTop + ::nHeight - 12, MulDiv( ::nWidth, ::nClientWidth, ::nVirtualWidth ), 6 )
               IF !:lVisible
                  :Show()
               ENDIF
            END
         ENDIF
      ELSEIF !::IsHideScrollBars()
         SetScrollInfo( ::Handle, SB_HORZ, 0, ::FnVirtualWidth - 1, ::nClientWidth, -::FnClientLeft, .F., lRedraw )
      ENDIF
   ENDIF

RETURN lScrolled

//--------------------------------------------------------------------------

METHOD WMMouseWheel( nWParam, nLParam ) CLASS XGestureControl

   IF Screen:lTouch
      IF lAnd( nWParam, MK_SHIFT ) .OR. !::lVScroll
         IF ::lHScroll
            ::nClientLeft := Min( 0, ::nClientLeft + ::nScrollIncrement * IIF( HiInt( nWParam ) > 0, 1, -1 ) )
         ENDIF
      ELSEIF ::lVScroll
         ::nClientTop := Min( 0, ::nClientTop + ::nScrollIncrement * IIF( HiInt( nWParam ) > 0, 1, -1 ) )
      ENDIF
      ::Refresh()
      RETURN 0
   ENDIF

RETURN ::Super:WMMouseWheel( nWParam, nLParam )

//--------------------------------------------------------------------------

#pragma BEGINDUMP

#include "Windows.h"
#include "Xailer.h"

typedef struct _GESTUREINFO {
  UINT      cbSize;
  DWORD     dwFlags;
  DWORD     dwID;
  HWND      hwndTarget;
  POINTS    ptsLocation;
  DWORD     dwInstanceID;
  DWORD     dwSequenceID;
  ULONGLONG ullArguments;
  UINT      cbExtraArgs;
} GESTUREINFO, *PGESTUREINFO;

typedef struct _GESTURECONFIG {
  DWORD dwID;
  DWORD dwWant;
  DWORD dwBlock;
} GESTURECONFIG, *PGESTURECONFIG;

typedef BOOL (WINAPI * GETGESTUREINFO)( HANDLE, PGESTUREINFO );
typedef BOOL (WINAPI * CLOSEGESTUREINFOHANDLE)( HANDLE );
typedef BOOL (WINAPI * GETGESTURECONFIG)( HWND, DWORD, DWORD, PUINT, PGESTURECONFIG, UINT );
typedef BOOL (WINAPI * SETGESTURECONFIG)( HWND, DWORD, UINT, PGESTURECONFIG, UINT );

//------------------------------------------------------------------------------

BOOL GetGestureInfo( HANDLE hGestureInfo, PGESTUREINFO pGestureInfo )
{
   BOOL bSuccess = FALSE;
   GETGESTUREINFO fnGetGestureInfo = GetProcAddress( GetModuleHandle( "user32.dll" ), "GetGestureInfo" );

   if( fnGetGestureInfo )
      bSuccess = fnGetGestureInfo( hGestureInfo, pGestureInfo );

   return bSuccess;
}

//------------------------------------------------------------------------------

BOOL CloseGestureInfoHandle( HANDLE hGestureInfo )
{
   BOOL bSuccess = FALSE;
   CLOSEGESTUREINFOHANDLE fnCloseGestureInfoHandle = GetProcAddress( GetModuleHandle( "user32.dll" ), "CloseGestureInfoHandle" );

   if( fnCloseGestureInfoHandle )
      bSuccess = fnCloseGestureInfoHandle( hGestureInfo );

   return bSuccess;
}

//------------------------------------------------------------------------------

BOOL GetGestureConfig( HWND hWnd, DWORD dwReserved, DWORD dwFlags, PUINT pcIDs, PGESTURECONFIG pGestureConfig, UINT cbSize )
{
   BOOL bSuccess = FALSE;
   GETGESTURECONFIG fnGetGestureConfig = GetProcAddress( GetModuleHandle( "user32.dll" ), "GetGestureConfig" );

   if( fnGetGestureConfig )
      bSuccess = fnGetGestureConfig( hWnd, dwReserved, dwFlags, pcIDs, pGestureConfig, cbSize );

   return bSuccess;
}

//------------------------------------------------------------------------------

BOOL SetGestureConfig( HWND hWnd, DWORD dwReserved, UINT cIDs, PGESTURECONFIG pGestureConfig, UINT cbSize )
{
   BOOL bSuccess = FALSE;
   SETGESTURECONFIG fnSetGestureConfig = GetProcAddress( GetModuleHandle( "user32.dll" ), "SetGestureConfig" );

   if( fnSetGestureConfig )
      bSuccess = fnSetGestureConfig( hWnd, dwReserved, cIDs, pGestureConfig, cbSize );

   return bSuccess;
}

//------------------------------------------------------------------------------

HB_FUNC_STATIC( XGESTURECONTROL_WMGESTURE )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HANDLE hGesture = (HANDLE) hb_parnl( 2 );
   GESTUREINFO gInfo;
   PHB_DYNS pMethod = hb_dynsymFindName( "Gesture" );

   memset( &gInfo, 0, sizeof( GESTUREINFO ) );
   gInfo.cbSize = sizeof( GESTUREINFO );
   GetGestureInfo( hGesture, &gInfo );

   if( pMethod )
   {
      hb_vmPushDynSym( pMethod );
      hb_vmPush( Self );
      hb_vmPushLong( gInfo.dwID );
      hb_vmPushLong( gInfo.dwFlags );
      hb_vmPushLong( gInfo.ptsLocation.x );
      hb_vmPushLong( gInfo.ptsLocation.y );
      hb_vmPushNumInt( gInfo.ullArguments );
      hb_vmSend( 5 );
   }

   CloseGestureInfoHandle( hGesture );
   hb_ret();
}

//------------------------------------------------------------------------------

HB_FUNC_STATIC( XGESTURECONTROL_SETGESTURECONFIG )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hWnd = (HWND) GetHandleOf( Self );
   GESTURECONFIG GestureConfig;
   BOOL bSuccess = FALSE;

   if( hWnd )
      {
      GestureConfig.dwID = 0;
      GestureConfig.dwWant = 1;
      GestureConfig.dwBlock = 0;
      bSuccess = SetGestureConfig( hWnd, 0, 1, &GestureConfig, sizeof( GESTURECONFIG ) );
      }

   hb_retl( bSuccess );
}

//------------------------------------------------------------------------------

#pragma ENDDUMP
