/* $Header$ */
/**************** Changes ******************
Date			Edit				Bug					Description
13-Mar-20	CRMAC1014							macOS changes for 10.14 SDK and later.
30-Jun-04	rmm5006								Multiple select knobs were missing from quite a few components.
22-Jun-04	rmm4999								Finished rmm4993: remote form fields now show $xxx correctly.
*******************************************/

#include <extcomp.he>
#include <extfval.he>
#include <hwnd.he>
#include <gdi.he>
#include "zoom.he"

#include <time.h>
#include <math.h>
#include <string.h>

#define COMPONENT_COUNT 	1				/* Number of controls within library */
#define LIB_RES_NAME  		1000		/* Resource id of library name */
#define ZOOMIN_ID					2000		/* Resource id of control within library */
#define ZOOMIN_ICON 			1				/* Resource bitmap id */

#define VERSION_MINOR			1				// Minor Version number - Update on release builds

const qshort
				cZoomInRatio 				= 1,
				cZoomInUpdateRate   = 2,
				cZoomAlwaysUpdate   = 3;
				// -----------------------


ECOproperty ZOOMINproperties[3] =
{ 
	cZoomInRatio, 		 4000, fftInteger, 0, 0, 0, 0,
	cZoomInUpdateRate, 4001, fftInteger, 0, 0, 0, 0,
	cZoomAlwaysUpdate, 4002, fftBoolean, 0, 0, 0, 0
};
               
// ---------------------------------------------------------------------------------------------------------


tqfZoomIn::tqfZoomIn( HWND pFieldHWnd )
{
	mHWnd = pFieldHWnd;
	
	qlong style = WNDgetWindowLong( mHWnd, GWL_EXSTYLE );
	style |= WND_REDRAWONSIZE;
	WNDsetWindowLong( mHWnd, GWL_EXSTYLE, style );
	
	mZoominRatio = 1;
	mZoominRate = 100;
	mAlwaysUpdate = qfalse;
	mZoomPt.h = mZoomPt.v = 0;
	mHasDrawn = qfalse;
	mLastMousePos.h = mLastMousePos.v = 0;
	mTrackingBmp = NULL;
}

tqfZoomIn::~tqfZoomIn()
{
}

qlong tqfZoomIn::attributeSupport( LPARAM pMessage, WPARAM wParam, LPARAM lParam, EXTCompInfo* eci )
{
	switch( pMessage )
	{ 
		case ECM_PROPERTYCANASSIGN: 
		{
			return 1L;
		}
		case ECM_SETPROPERTY: 
		{       
			EXTParamInfo* param = ECOfindParamNum( eci, 1 );
			if ( param )
			{
				EXTfldval fval( (qfldval)param->mData );
				switch( ECOgetId(eci) )
				{
					case cZoomInRatio: 				
					{
						mZoominRatio = (qshort)fval.getLong(); 
						if ( mZoominRatio<1 ) mZoominRatio = 1;
						else if ( mZoominRatio>20 ) mZoominRatio = 20;
						break; 			
					}
					case cZoomInUpdateRate:		
					{
						mZoominRate = fval.getLong(); 
						if ( mAlwaysUpdate )
						{
							WNDkillTimer( mHWnd, 100 );
							WNDsetTimer( mHWnd, 100, (qushort)mZoominRate );
						}
						break;
					}
					case cZoomAlwaysUpdate:
					{
						mAlwaysUpdate = (qbool)fval.getLong();
						if ( !mAlwaysUpdate ) WNDkillTimer( mHWnd, 100 );
						else WNDsetTimer( mHWnd, 100, (qushort)mZoominRate );
						break; 			
					}
				}       
				WNDinvalidateRect( mHWnd, NULL );
				WNDupdateWindow( mHWnd );
				return 1L;
			}
			break;
		}
		case ECM_GETPROPERTY: 
		{
			EXTfldval fval;
			switch( ECOgetId(eci) )
			{
				case cZoomInRatio: 				fval.setLong( (qlong)mZoominRatio ); break; 			
				case cZoomInUpdateRate: 	fval.setLong( mZoominRate ); break; 			
				case cZoomAlwaysUpdate:		fval.setLong( (qlong)mAlwaysUpdate ); break; 			
			}         
			ECOaddParam(eci,&fval);
			return 1L;
		}
	}
	return 0;
}

qrect tqfZoomIn::getZoomRect( qpoint* pPt )
{                             
	qrect zoom, client, screenRect;	
	
	WNDgetClientRect( mHWnd, &client );
	if ( mZoominRatio>1 )
	{
		client.right = client.left + ( client.right / mZoominRatio ) + 1;
		client.bottom = client.top + ( client.bottom / mZoominRatio ) + 1;
	}
	zoom.left = pPt->h - ( client.right / 2 ); zoom.right = zoom.left + client.right;
	zoom.top = pPt->v - ( client.bottom / 2 ); zoom.bottom = zoom.top + client.bottom;
	
	WNDgetWindowRect( HWND_DESKTOP, &screenRect );

	if ( zoom.left<screenRect.left ) 
		GDIoffsetRect( &zoom, screenRect.left-zoom.left, 0 );
	else if ( zoom.right>screenRect.right ) 
		GDIoffsetRect( &zoom, screenRect.right-zoom.right, 0 );

	if ( zoom.top<screenRect.top ) 
		GDIoffsetRect( &zoom, 0, screenRect.top-zoom.top );
	else if ( zoom.bottom>screenRect.bottom ) 
		GDIoffsetRect( &zoom, 0, screenRect.bottom-zoom.bottom );

	return zoom;
}

void tqfZoomIn::checkZoominPt()
{ 
	qrect windowrect, screenRect;
	WNDgetWindowRect( mHWnd, &windowrect );
	GDIgetScreenRect( GDI_SCR_GET_ALL, &screenRect );
	screenRect.right -= windowrect.width();
	screenRect.bottom -= windowrect.height();
	if ( mZoomPt.h<screenRect.left ) mZoomPt.h = screenRect.left;
	if ( mZoomPt.v<screenRect.top ) mZoomPt.v = screenRect.top;
	if ( mZoomPt.h>screenRect.right ) mZoomPt.h = screenRect.right;
	if ( mZoomPt.v>screenRect.bottom ) mZoomPt.v = screenRect.bottom;      
}

void tqfZoomIn::drawDesktopSelectRect( qpoint* pPoint )
{
	BLOCKVAR qrect zoom = getZoomRect( pPoint );	// CRMAC1014
	HDC desktop = WNDstartDraw( HWND_DESKTOP );
	GDIdrawFocusRect( desktop,&zoom );
	WNDendDraw( HWND_DESKTOP, desktop );	
	mLastMousePos = *pPoint;
}

void tqfZoomIn::doDraw( qpoint* pNewPoint, qbool pDrawNewSelection, qbool pUpdate )
{
	if ( mHasDrawn )
	{
		drawDesktopSelectRect( &mLastMousePos );
		mHasDrawn = qfalse;
	}
	mZoomPt = *pNewPoint;
	WNDmapWindowPoint( mHWnd, HWND_DESKTOP, &mZoomPt );	
	if ( pUpdate ) update();
	if ( pDrawNewSelection ) 
	{
		drawDesktopSelectRect( &mZoomPt ); 
		mHasDrawn = qtrue;
	}

}

void tqfZoomIn::doMouse( LPARAM message, qpoint* pPoint )
{
	switch( message )
	{
		case WM_LBUTTONDOWN:
		{
			ECOhideTooltip( mHWnd );
			startTracking();
			WNDsetCapture( mHWnd, WND_CAPTURE_MOUSE );
			doDraw( pPoint, qtrue, qtrue );
			break;
		}
		case WM_MOUSEMOVE:                       
		{       
			doDraw( pPoint, qtrue, qtrue );
			break;
		}
		case WM_LBUTTONUP:
		{
			WNDreleaseCapture( WND_CAPTURE_MOUSE );
			doDraw( pPoint, qfalse, qfalse );
			endTracking();
			break;
		}
	}
}


void tqfZoomIn::startTracking()
{
	qrect client;
	WNDgetClientRect( mHWnd, &client ); 
	mTrackingBmp = GDIcreateBitmap( client.width(), client.height(), 0 );
}

void tqfZoomIn::endTracking()
{                            
	if ( mTrackingBmp ) 
		GDIdeleteBitmap( mTrackingBmp );
	mTrackingBmp = NULL;
}

void tqfZoomIn::update()
{                            
	BLOCKVAR qrect client;	// CRMAC1014
	qbool doEndTracking = qfalse;
	
	WNDgetClientRect( mHWnd, &client ); 
	BLOCKVAR qrect zoomrect = getZoomRect( &mZoomPt );	// CRMAC1014

	if ( mTrackingBmp==NULL )
	{
		startTracking();
		doEndTracking = qtrue;
	}
	
	HDC hdc = GDIgetTempDC();
	HBITMAP oldBmp = GDIselectBitmap( hdc, mTrackingBmp );
	
	HDC desktop = WNDstartDraw( HWND_DESKTOP );
	GDIcopyBits( desktop, hdc, &zoomrect, &client, qtrue );
	WNDendDraw( HWND_DESKTOP, desktop );

	HDC fieldhdc = WNDstartDraw( mHWnd );
	ECOexcludeToolTipRect( mHWnd, fieldhdc );	// PK4712
	GDIcopyBits( hdc, fieldhdc, &client, &client, qfalse );
	// Start rmm4999
	if (ECOisShowNumber(mHWnd))
		ECOdrawNumberEx(mHWnd, fieldhdc, qtrue);
	// End rmm4999
	ECOdrawMultiKnobs(mHWnd, fieldhdc); // rmm5006
	WNDendDraw( mHWnd, fieldhdc );
	
	GDIselectBitmap( hdc, oldBmp );

	if ( doEndTracking )
		endTracking();
}       


qbool tqfZoomIn::paint()
{
	WNDpaintStruct paintStruct;
	WNDbeginPaint( mHWnd, &paintStruct );
	WNDendPaint( mHWnd, &paintStruct );	
	update();
	return qtrue;
}



extern "C" LRESULT OMNISWNDPROC GenericWndProc( HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, EXTCompInfo* eci )
{
   ECOsetupCallbacks(hwnd, eci);
	 switch (Msg)
	 {
			case WM_LBUTTONDOWN:
			case WM_MOUSEMOVE:
			case WM_LBUTTONUP:
			{
				qpoint pt;
				if ( !ECOisDesign( hwnd ) )
				{           
					if ( Msg==WM_MOUSEMOVE && !WNDhasCapture( hwnd, WND_CAPTURE_MOUSE ) ) break;
					WNDmakePoint( lParam, &pt );
					tqfZoomIn* object = (tqfZoomIn*)ECOfindObject( eci, hwnd );
					if ( object ) 
					{
						object->doMouse(Msg, &pt);
						return qtrue;
					}
				}
				break; 	
			}
			case WM_TIMER:							
			{	           
				tqfZoomIn* object = (tqfZoomIn*)ECOfindObject( eci, hwnd );
				if ( object )
					object->update(); 
				return qfalse;
      }
			case WM_PAINT:							
			{
				tqfZoomIn* object = (tqfZoomIn*)ECOfindObject( eci, hwnd );
				if ( object && object->paint() )
					return qtrue;
				break;
			}
			case ECM_OBJCONSTRUCT:				/* Construct an object */
			{
				tqfZoomIn* object = new tqfZoomIn( hwnd );
				ECOinsertObject( eci, hwnd, (void*)object );
				return qtrue;
			}
			case ECM_OBJDESTRUCT:					/* Destruct the object */
			{
				WNDkillTimer( hwnd, 100 );
				tqfZoomIn* object = (tqfZoomIn*)ECOremoveObject( eci, hwnd );
				if ( object ) delete object;              
				return qtrue;
			}
			case WM_ERASEBKGND:
			{
				return 1L;  
			}
			case ECM_PROPERTYCANASSIGN:  	/* Object: Is the property assignable (ie readonly?) */
			case ECM_SETPROPERTY: 				/* Object: Assignment to a property */
			case ECM_GETPROPERTY:					/* Object: Retrieve value from property */
			{
				tqfZoomIn* object = (tqfZoomIn*)ECOfindObject( eci, hwnd );
				if ( object )
					return object->attributeSupport( Msg, wParam, lParam, eci );
				return 0L;
			}
      case ECM_GETCOMPLIBINFO:
      {
      	return ECOreturnCompInfo( gInstLib, eci, LIB_RES_NAME, COMPONENT_COUNT );
      }
			case ECM_GETCOMPICON:
			{ 	
				if ( eci->mCompId==ZOOMIN_ID ) return ECOreturnIcon( gInstLib, eci, ZOOMIN_ICON );
				return qfalse;
			}
			case ECM_GETCOMPID:
			{
				if ( wParam==1 )
					return ECOreturnCompID( gInstLib, eci, ZOOMIN_ID, cObjType_Basic );
				return 0L;
			}
			case ECM_GETPROPNAME:
			{
				return ECOreturnProperties( gInstLib, eci, &ZOOMINproperties[0], 3 );
			}
			case ECM_GETVERSION:
			{
				return ECOreturnVersion(1,VERSION_MINOR);
			}                                                                 
	 }
	 return WNDdefWindowProc(hwnd,Msg,wParam,lParam,eci);
}

	
