/*********************************************************/
//	NkILSampleView.cpp
//		Source file of ImageSDKLibrary Sample's View class.
//
//	Copyright(c) 2007, Nikon Corporation - All rights reserved.
/*********************************************************/

#include "stdafx.h"
#include "NkILSample.h"
#include "MainFrm.h"
#include "NkILSampleDoc.h"
#include "NkILSampleView.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define DEFAULT_SHOW_RATIO	1.0
#define UNIT_SHOW_RATIO		0.1
#define CHECK_PUSHKEY_ALT	0x8000
#define RGB_MAX				255
// CNkILSampleView

IMPLEMENT_DYNCREATE(CNkILSampleView, CScrollView)

BEGIN_MESSAGE_MAP(CNkILSampleView, CScrollView)
	// Standard printing commands	
	ON_COMMAND(ID_FILE_PRINT, OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, OnFilePrintPreview)	
	ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

// CNkILSampleView construction/destruction

CNkILSampleView::CNkILSampleView()
{
	m_dbDisplayRatio	= 0.0;
	m_pBufferDisp		= NULL;
	m_ulImageWidth		= 0;
	m_ulImageHeight		= 0;
}

CNkILSampleView::~CNkILSampleView()
{
	if( NULL != m_pBufferDisp )
	{
		delete [] m_pBufferDisp;
		m_pBufferDisp = NULL;
	}
}

BOOL CNkILSampleView::PreCreateWindow(CREATESTRUCT& cs)
{
	//  the CREATESTRUCT cs
	return CScrollView::PreCreateWindow(cs);
}

// CNkILSampleView drawing

bool CNkILSampleView::PrepareImageForDisp()
{
	CNkILSampleDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return true;	
	// check file opened
	if( !pDoc->IsOpenedFile() ) 
	{		
		return true;		// not opened file yet, do nothing
	}	

	if( NULL != m_pBufferDisp )
	{
		delete [] m_pBufferDisp;
		m_pBufferDisp = NULL;
	}
	// get image size
	NkIL_ImageInfo	StrInfo = {0};
	if( !pDoc->GetImageInfo( NULL, &StrInfo, NULL ))
	{		
		return false;
	}
	unsigned long ulShift	= 1;
	unsigned long ulRowByte	= StrInfo.ulWidth * BYTEPIXEL ;

	// prepare source data buffer
	unsigned char* pImage	= pDoc->GetImage();
	if( NULL == pImage )
	{		
		return false;
	}
	// 4 byte boundary	
	unsigned long ulDispRowByte	= StrInfo.ulWidth * BYTEPIXEL;
	long		  lPading		= ulDispRowByte % 4;
	if( lPading != 0 )
	{		
		ulDispRowByte += ( 4 - lPading );
	}	
	// prepare destination data buffer
	if( 0 == StrInfo.ulHeight * ulDispRowByte )
	{
		return false;
	}
	m_pBufferDisp = new unsigned char[ StrInfo.ulHeight * ulDispRowByte ];
	if( m_pBufferDisp == NULL )
	{		
		return false;
	}		

	// convert source data to destination data 	
	for( int i = 0; i < (int)StrInfo.ulHeight; ++i )
	{
		unsigned char* pRead = pImage + ulRowByte * i;
		unsigned char* pDraw = m_pBufferDisp + ulDispRowByte * i;

		// convert rgb to bgr
		for( int j = 0; j < (int)StrInfo.ulWidth; ++j )
		{
			*pDraw++ = *( pRead + (ulShift << 1) );
			*pDraw++ = *( pRead + ulShift );
			*pDraw++ = *( pRead );

			pRead += BYTEPIXEL;
		}			
	}	
	m_ulImageWidth	= StrInfo.ulWidth;
	m_ulImageHeight = StrInfo.ulHeight;

	return true;
}

void CNkILSampleView::OnDraw(CDC* pDC)
{
	CNkILSampleDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;		
	// check file opened
	if( !pDoc->IsOpenedFile() || NULL == m_pBufferDisp ) 
	{		
		((CMainFrame*)GetParentFrame())->SetFrameStrings( true );
		return;		// not opened file yet, do nothing
	}	
	
	//////////////////////////////////////////////////////
	// prepare info for display
	//////////////////////////////////////////////////////	
	
	// decide display size by display ratio
	unsigned long ulDispWidth	= (unsigned long)(m_ulImageWidth * m_dbDisplayRatio);	
	unsigned long ulDispHeight	= (unsigned long)(m_ulImageHeight * m_dbDisplayRatio);
	// 4 byte boundary
	long lPading = ulDispWidth % 4;
	if( 0 != lPading )
	{		
		ulDispWidth += ( 4 - lPading );
	}	

	// prepare BITMAPINFO structure
	BITMAPINFO BitMapInfo;
	BitMapInfo.bmiHeader.biSize				= sizeof(BITMAPINFOHEADER);
	BitMapInfo.bmiHeader.biWidth			= m_ulImageWidth;
	BitMapInfo.bmiHeader.biHeight			= -(long)m_ulImageHeight;
	BitMapInfo.bmiHeader.biPlanes			= 1;
	BitMapInfo.bmiHeader.biBitCount			= 24;
	BitMapInfo.bmiHeader.biCompression		= BI_RGB;
	BitMapInfo.bmiHeader.biSizeImage		= 0;
	BitMapInfo.bmiHeader.biXPelsPerMeter	= 0;
	BitMapInfo.bmiHeader.biYPelsPerMeter	= 0;
	BitMapInfo.bmiHeader.biClrImportant		= 0;
	BitMapInfo.bmiHeader.biClrUsed			= 0;
	
	SetStretchBltMode( pDC->GetSafeHdc(), HALFTONE );		// set bitmap mode to halftone
	SetBrushOrgEx( pDC->GetSafeHdc(), 0, 0, NULL );			// set starting point of brush

	// display image
	StretchDIBits( pDC->GetSafeHdc(),
			0, 0, 
			ulDispWidth, ulDispHeight,
			0, 0,
			m_ulImageWidth, m_ulImageHeight,
			m_pBufferDisp, &BitMapInfo, DIB_RGB_COLORS, SRCCOPY );
	
	// set scroll 
	CSize sizeTotal;
	sizeTotal.cx = ulDispWidth;
	sizeTotal.cy = ulDispHeight;
	SetScrollSizes(MM_TEXT, sizeTotal); // set scroll size		

	// set status bar and title
	((CMainFrame*)GetParentFrame())->SetFrameStrings();
}

void CNkILSampleView::OnInitialUpdate()
{
	CSize sizeTotal;	
	sizeTotal.cx = sizeTotal.cy = 100;
	SetScrollSizes(MM_TEXT, sizeTotal);

	CScrollView::OnInitialUpdate();
}

// CNkILSampleView printing

BOOL CNkILSampleView::OnPreparePrinting(CPrintInfo* pInfo)
{	
	return DoPreparePrinting(pInfo);	// default preparation
}

// CNkILSampleView diagnostics

#ifdef _DEBUG
void CNkILSampleView::AssertValid() const
{
	CScrollView::AssertValid();
}

void CNkILSampleView::Dump(CDumpContext& dc) const
{
	CScrollView::Dump(dc);
}

CNkILSampleDoc* CNkILSampleView::GetDocument() const // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CNkILSampleDoc)));
	return (CNkILSampleDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////
// OnLButtonDown
// check pushed key with lbuttondown, and change display ration
void CNkILSampleView::OnLButtonDown( UINT nFlags, CPoint point )
{		
	double dbOldRatio = m_dbDisplayRatio;
	// check key pushed with LButtonDown
	if( nFlags & MK_CONTROL )
	{
		// with Ctrl key, expansion display ratio by 10%
		m_dbDisplayRatio += UNIT_SHOW_RATIO;
		// upper bound is 150%
		if( m_dbDisplayRatio > 1.5 )
		{
			m_dbDisplayRatio = 1.5;
		}
	}
	else if( GetKeyState( VK_MENU ) & CHECK_PUSHKEY_ALT )
	{
		// with Alt(menu) key, reducation display ratio by 10%
		m_dbDisplayRatio -= UNIT_SHOW_RATIO;
		// lower bound is 10%
		if( m_dbDisplayRatio < 0.1 )
		{
			m_dbDisplayRatio = 0.1;
		}		
	}	

	// check need rewrite
	if( dbOldRatio != m_dbDisplayRatio )
	{
		Invalidate();
		UpdateWindow();					// rewrite Image
	}

	CScrollView::OnLButtonDown(nFlags, point);
}
// OnLButtonDown
/////////////////////////////////////////////////////////////////////////

//====================================================================
// function name		FSetDispayRatio
// function abstract	Fcalculate ratio of Image shown at display
// parameter			Fnone
// return value			Fnone
//====================================================================
void CNkILSampleView::SetDispayRatio()
{	
	// get document class
	CNkILSampleDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;		
	// get image size
	NkIL_ImageInfo StrInfo = {0};
	if( !pDoc->GetImageInfo( NULL, &StrInfo, NULL ))
	{
		return;
	}

	// get current cliant size from rect
	CRect rc;
	GetClientRect( &rc );
	unsigned long ulClientWidth		= rc.Width();
	unsigned long ulClientHeight	= rc.Height();

	m_dbDisplayRatio = DEFAULT_SHOW_RATIO;		// set deault ratio 100%
	// check need reducation
	if( ulClientWidth < StrInfo.ulWidth || ulClientHeight < StrInfo.ulHeight )
	{
		double dbTemp = m_dbDisplayRatio;
		while(dbTemp > 0)
		{
			dbTemp -= UNIT_SHOW_RATIO;	// reduce displayed image size by 10% 
			unsigned long ulTempWidth	= (unsigned long)(StrInfo.ulWidth * dbTemp);
			unsigned long ulTempWHeight = (unsigned long)(StrInfo.ulHeight * dbTemp);
			if( ulClientWidth >= ulTempWidth && ulClientHeight >= ulTempWHeight )
			{
				break;					// match display ratio
			}
		}
		if( 0.1 > dbTemp )
		{
			dbTemp = 0.1;				// lower bound is 10%			
		}
		m_dbDisplayRatio = dbTemp;		// set fitting ratio
	}
}
// SetDispayRatio
/////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////
// DisplayAllDlg
// for display Setting1&2dialog and information dialog
void CNkILSampleView::DisplayAllDlg()
{
	CMainFrame* pFrame = (CMainFrame*)GetParentFrame();
	if( NULL != pFrame )
	{
		pFrame->DisplayAllDlg();
	}
}
// DisplayAllDlg
/////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////
// DeleteAllDlg
// for delete Setting1&2dialog and information dialog
void CNkILSampleView::DeleteAllDlg()
{
	CMainFrame* pFrame = (CMainFrame*)GetParentFrame();
	if( NULL != pFrame )
	{
		pFrame->DeleteAllDlg();

		if( NULL != m_pBufferDisp )
		{
			delete [] m_pBufferDisp;
			m_pBufferDisp = NULL;
		}
	}	
}
// DeleteAllDlg
/////////////////////////////////////////////////////////////////////////
