/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/

// SrfCurvaDlg.cpp : インプリメンテーション ファイル

#include "stdafx.h"
#include <afxpriv.h>  // for AfxSetWindowText
#include "fugen.h"
#include "SrfCurvaDlg.h"
#include "EvalCmd/EvalSurfGauss.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// CSrfCurvaDlg ダイアログ


CSrfCurvaDlg::CSrfCurvaDlg(MGEvalSurfGaussTool* tool)
: mgModelessDialogue(tool), m_bModified(FALSE){
	//{{AFX_DATA_INIT(CSrfCurvaDlg)
	m_dMin = -0.00001;
	m_dMax = 0.00001;
	m_strMean = _T("0");
	//}}AFX_DATA_INIT

	Create(IDD_SRFCURVA_DLG);
}

namespace{
	const int nSizeGcvt = 5;

	// CSrfCurvaDlg::DoDataExchange helper function.
	void SetCurvaMinMaxEdit(CDataExchange* pDX, int nIDC, double dVal)	{
		TCHAR szBuffer[32];
		_stprintf_s(szBuffer, 32, _T("%.*g"), nSizeGcvt, dVal);
		AfxSetWindowText(pDX->PrepareEditCtrl(nIDC), szBuffer);
	}
}

void CSrfCurvaDlg::DoDataExchange(CDataExchange* pDX){
	CDialog::DoDataExchange(pDX);
	if(pDX->m_bSaveAndValidate){
		DDX_Text(pDX, IDC_SRFCURVA_MIN, m_dMin);
		DDX_Text(pDX, IDC_SRFCURVA_MAX, m_dMax);
	}else{
		SetCurvaMinMaxEdit(pDX, IDC_SRFCURVA_MIN, m_dMin);
		SetCurvaMinMaxEdit(pDX, IDC_SRFCURVA_MAX, m_dMax);	
	}
	DDX_Text(pDX, IDC_SRFCURVA_STA, m_strMean);
}

MGCL::SURFACE_CURVATURE_KIND CSrfCurvaDlg::GetCurvaKind() const{
	CComboBox* pCb = (CComboBox*)GetDlgItem(IDC_SRFCURVA_COMBO);
	int nCur = pCb->GetCurSel();
	if(nCur == CB_ERR) nCur = 0; // gaussian

	MGCL::SURFACE_CURVATURE_KIND kind;
	switch(nCur){
	case 0:	kind = MGCL::GAUSSIAN_CURVATURE; break;
	case 1:	kind = MGCL::MEAN_CURVATURE; break;
	case 2:	kind = MGCL::MINIMUM_CURVATURE; break;
	case 3:	kind = MGCL::MAXIMUM_CURVATURE; break;
	default: ASSERT(FALSE);
	}
	return kind;

}

void CSrfCurvaDlg::UpdateGradientArea(){
	CRect rc;
	GetDlgItem(IDC_STATIC_GRADIENT)->GetWindowRect(rc);
	ScreenToClient(rc);

	const double dPitch = static_cast<double>(rc.Height()) / 4;
	TRIVERTEX vert[5] ={
		{rc.left, 0, 0xFF00, 0x0000, 0x0000, 0},
		{rc.right, 0, 0xFF00, 0xFF00, 0x0000, 0},
		{rc.left, 0, 0x0000, 0xFF00, 0x0000, 0},
		{rc.right, 0, 0x0000, 0xFF00, 0xFF00, 0},
		{rc.left, 0, 0x0000, 0x0000, 0xFF00, 0},
	};
	for(int i = 0; i < 5; ++i){
		vert[i].y = long(rc.top + dPitch * i);
	}
	GRADIENT_RECT gr[4] = {{0, 1}, {1, 2}, {2, 3}, {3, 4}};

	std::copy(vert, vert + 5, m_vert);
	std::copy(gr, gr + 4, m_gr);
}

BEGIN_MESSAGE_MAP(CSrfCurvaDlg, mgModelessDialogue)
	//{{AFX_MSG_MAP(CSrfCurvaDlg)
	ON_WM_PAINT()
	ON_BN_CLICKED(IDC_SRFCURVA_BTN_AUTO, ResetAutoRange)
	ON_BN_CLICKED(IDC_SRFCURVA_BTN_MAX, ResetMinMaxRange)
	ON_EN_UPDATE(IDC_SRFCURVA_MAX, OnUpdateEditCtrl)
	ON_EN_UPDATE(IDC_SRFCURVA_MIN, OnUpdateEditCtrl)
	ON_CBN_SELCHANGE(IDC_SRFCURVA_COMBO, ResetAutoRange)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSrfCurvaDlg メッセージ ハンドラ

BOOL CSrfCurvaDlg::OnInitDialog(){
	mgModelessDialogue::OnInitDialog();

	CComboBox* pCb = (CComboBox*)GetDlgItem(IDC_SRFCURVA_COMBO);
	pCb->SetCurSel(0);

	double mean = (m_dMin + m_dMax)*.5;
	m_strMean.Format(_T("%f"), mean);
	UpdateData(FALSE);

	UpdateGradientArea();
	return TRUE;
}

void CSrfCurvaDlg::OnPaint(){
	CPaintDC dc(this);
	dc.GradientFill(m_vert, 5, m_gr, 4, GRADIENT_FILL_RECT_V);

	CDialog::OnPaint();
}

void CSrfCurvaDlg::OnOK(){
	if(IsModified()){
		UpdateShadingView();
	}
}

void CSrfCurvaDlg::OnUpdateEditCtrl(){
	SetModifiedFlag(TRUE);
}

void CSrfCurvaDlg::OnBtnRefresh(){
	UpdateShadingView();
}

BOOL CSrfCurvaDlg::PreTranslateMessage(MSG* pMsg){
	switch(pMsg->message){
	case WM_MOUSEWHEEL:
		return -1;
	}
	return CDialog::PreTranslateMessage(pMsg);
}

void CSrfCurvaDlg::ResetAutoRange(){
	MGEvalSurfGaussTool* tool=getEvalSurfGaussToolPointer();

	MGCL::SURFACE_CURVATURE_KIND kind = GetCurvaKind();
	double dMin = tool->minimum_curvature(kind);
	double dMax = tool->maximum_curvature(kind);

	dMin = fabs(dMin);
	dMax = fabs(dMax);
	if(dMin < dMax){
		m_dMin = -dMax;
		m_dMax = dMax;
	} else{
		m_dMin = -dMin;
		m_dMax = dMin;
	}
	ASSERT(-m_dMin == m_dMax);
	UpdateData(FALSE);

	SetModifiedFlag(TRUE);
	UpdateShadingView();
}

void CSrfCurvaDlg::ResetMinMaxRange(){
	MGEvalSurfGaussTool* tool = getEvalSurfGaussToolPointer();

	MGCL::SURFACE_CURVATURE_KIND kind = GetCurvaKind();
	m_dMin = tool->minimum_curvature(kind);
	m_dMax = tool->maximum_curvature(kind);
	UpdateData(FALSE);
	SetModifiedFlag(TRUE);
	UpdateShadingView();
}

void CSrfCurvaDlg::UpdateShadingView(){
	if(IsModified()){
		UpdateData();

		double mean = (m_dMin + m_dMax)*.5;
		m_strMean.Format(IDS_FORMAT_FLOAT, mean);

		MGEvalSurfGaussTool* tool = getEvalSurfGaussToolPointer();
		tool->draw_pictures(GetCurvaKind(), m_dMin, m_dMax);
		UpdateData(FALSE);
		SetModifiedFlag(FALSE);
	}
}

MGEvalSurfGaussTool * CSrfCurvaDlg::getEvalSurfGaussToolPointer(){
	return static_cast<MGEvalSurfGaussTool*>(getCmdTool());
}
