/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/
/**
 * @file EvalCurveCurvatureTool.cpp
 * @brief MGEvalCurveCurvatureTool クラスのインプリメンテーション
 */
#include "stdafx.h"
#include "fugenDoc.h"
#include "fugenView.h"
#include "CurvaDlg.h"
#include "EvalCmd/EvalCurveCurvatureTool.h"

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

// MGEvalCurveCurvatureTool

MGEvalCurveCurvatureTool::MGEvalCurveCurvatureTool(fugenDoc* pDoc)
:MGSelectState(pDoc, ID_SYSD_CURVA_ON, MULTIPLE_SELECT, mgAll_Curve){
	// ダイアログを準備する
	attachModelessDialogue<CCurvaDlg>(this);
}

void MGEvalCurveCurvatureTool::extractCurvesFromtCurrent(MGPickObjects& curves){
	const MGPickObjects& cobjs = current_objects();
	curves.clear();
	cobjs.select_curves(curves);
}

void MGEvalCurveCurvatureTool::draw_graph(){
	erase_temporary(nullptr, false);

	CCurvaDlg& dialog = *(static_cast<CCurvaDlg*>(getModelessDialogPointer()));
	double scale= dialog.GetScale();
	int density= dialog.GetDensity();
	bool use_radius= dialog.GetLengthType()==1, negate= dialog.Negate()==TRUE;

	MGPickObjects curves;
	extractCurvesFromtCurrent(curves);
	size_t n = curves.size();
	for(size_t i=0; i<n; i++){
		const MGGel* gel= curves[i].top_object();
		draw_temporary(
			new MGEvalCurveCurvatureToolSysGL(gel, scale, density, use_radius, negate)
			,false,false);
	}
	InvalidateAllStdViews();
}

MGCommandBase* MGEvalCurveCurvatureTool::initial_clone(fugenDoc* pDoc)const{
	return new MGEvalCurveCurvatureTool(pDoc);
}

bool MGEvalCurveCurvatureTool::initiate_tool(){
	MGSelectState::initiate_tool();
	draw_graph();
	if(is_breaking_command())
		return true;

	getModelessDialogPointer()->ShowWindow(SW_SHOW);
	// Selection message.
	SetStatusMessage(IDS_PROMPT_CURVE);
	return false;
}

bool MGEvalCurveCurvatureTool::terminate_tool(bool cancel){
	// ヒゲイメージを消去したくないので
	// 常に false 引数で終わる。
	return MGSelectState::terminate_tool(false);
}

bool MGEvalCurveCurvatureTool::OnCommandEnd(
	UINT nIDS,	//=0: erase the current message, and display no messages.
				//=1: display "xxxx" normally end.
				//otherwise: nIDS is a string id, and load the message from string table to display.
	bool erase_temporary_display
){
	return MGSelectState::OnCommandEnd(1,false);//Curvature pictures stay displayed.
}

bool MGEvalCurveCurvatureTool::OnCommandCanceled(
		UINT nIDS//=0: erase the current message, and display no messages.
				//=1: display "xxxx" cancelled.
				//otherwise: nIDS is a string id, and load the message from string table to display.
){
	// 本来はキャンセル終了だが、ヒゲのイメージを画面に残したいので
	// 通常終了のよう振る舞ってもらう。
	return MGSelectState::OnCommandEnd(nIDS, false);
}

bool MGEvalCurveCurvatureTool::OnSelected(
	fugenView* window,//The fugenView pointer where point input event took place.
	MGPickObjects&	selected_objects,	//selected objects at this selection operation.
	MGPickObjects&	unselected_objects	//unselected objects at this selection operation.
		//unselected_objects.size()>=1 only when the already selected objects are selected
		//when add mode is set(or when operation is done with a crtl key pressed).
){
	draw_graph();
	return false;
}

// 描画クラスの実装

MGEvalCurveCurvatureToolSysGL::MGEvalCurveCurvatureToolSysGL(
	const MGGel* curve,double scale,int density,bool use_radius,bool bNegate)
:mgSysGL(ID_SYSD_CURVA_ON, curve),m_scale(scale),m_density(density),
m_use_radius(use_radius),m_bNegate(bNegate){}

//Construct new object by copying to newed area.
//User must delete this copied object by "delete".
mgSysGL* MGEvalCurveCurvatureToolSysGL::clone()const{
	return new MGEvalCurveCurvatureToolSysGL(*this);
}

//Draw this Sysgl.
//This draw is used to draw the pictures for Undo(, Redo) operations.
void MGEvalCurveCurvatureToolSysGL::drawSysGL(){
	MGColor::get_instance(MGColor::White).exec(*this);
	auto obj = dynamic_cast<const MGObject*>(object_id());
	if(obj) obj->display_curvatures(
		*this, m_density, m_use_radius,
		m_bNegate ? -m_scale : m_scale);
}
