/*------------------------------------------------------------------------------*
 * File Name: FitWizCoreBase.c													*
 * Creation: Jasmine 11/10/08													*
 * Purpose: Origin C Header Files												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * Iris/Sim 11/18/2008 v8.0974 FIX_FAIL_TO_GET_SOURCE_DATAPLOT_WHEN_PA_FIT_DO_RECALCULATE*
 *	Sim 12-04-2008 IMPROVE_XF_WIZ_FRAMEWORK										*
 *	Folger 12/11/08 QA80-12765 v8.0985 CHANGE_PARAMETER_FAILS_TO_REMEMBER_SETTINGS_FROM_LAST_CLOSE_IN_PA_FITTING
 *	Folger 12/30/08 v8.0992 NANOSIZER_USING_NEW_XFWIZARD_FRAMEWORK				*
 *	Folger 02/11/09 SHARE_WIZ_CORE_BASE_CODE_BETWEEN_PA_AND_NANOSIZER			*
 *	Folger 02/13/09 IGNORE_AUTO_INIT_STATUS_IF_AND_ONLY_IF_CHANGE_PARAM			*
 *	Jasmine 04/23/09 NANO_CENTRIALIZE_FUNCTION									*
 *	Jasmine 04/24/09 DEFINE_DATA_ID__USED_IN_PA_NANO_SIZER_FIT_TREE				*
 *	Folger 05/12/09 NANOSIZER_FITTING_BASED_SUPPORT								*
 *	Sim 06-23-2009 NANOSIZER_WIZ_AUTO_UPDATE_SUPPORT							*
 *	Jasmine 06/30/09 NANOSIZER_NEED_FITTYPE_TO_SHOW_SPEC_NODE_IN_GUI_TREE		*
 *	Folger 07/01/09 THEME_SAVED_IN_SR5_FAILS_TO_BE_APPLIED_AFTER_NEW_RESULTS_NODE_ADDED_IN_PA
 *	Sophy 7/6/2009 SUPPORT_NANOSIZER_OUTPUTGUIMANAGER							*
 *	Folger 10/20/09 NANOSIZER_FAILS_TO_SWITCH_LABEL_PLOT						*
 *	Folger 10/28/09 QA81-14552 WRONG_REPORT_STATUS_WHEN_CHANGE_PARAM_IN_PA		*
 *	Folger 12/18/09 QA81-14860 REUID_PA_OUTPUTS_FOR_AUTO_UPDATE					*
 *	Kyle 03/11/2010 PICK_PEAK_ROI_TOOL_SHARES_UTILS_FUNCTION_WITH_PA			*
 *------------------------------------------------------------------------------*/
#include <Origin.h>
#include <GetNBox.h>
#include <operation.h> 


#include <..\OriginLab\XFCore.h>
#include <..\OriginLab\XFWiz.h>
///---Sim 12-04-2008 IMPROVE_XF_WIZ_FRAMEWORK
//#include <..\OriginLab\XFWizDlgNavigation.h>
#include <..\OriginLab\XFWizNavigation.h>
///---END IMPROVE_XF_WIZ_FRAMEWORK

#include <..\OriginLab\graph_utils.h>			///Kyle 03/11/2010 PICK_PEAK_ROI_TOOL_SHARES_UTILS_FUNCTION_WITH_PA

#include <..\OriginLab\FitWizCoreBase.h>


////////////////////////////////////////////////////////
///////////////////	FitWizCoreBase	////////////////////
////////////////////////////////////////////////////////
FitWizCoreBase::FitWizCoreBase() : XFCore()
{
	m_bIsFinishButtonClicked = false; 
}

FitWizCoreBase::~FitWizCoreBase()
{
	///---Sim 06-23-2009 NANOSIZER_WIZ_AUTO_UPDATE_SUPPORT
	if(m_wpInterim)
	{
		m_wpInterim.Destroy();
	}
	///---END NANOSIZER_WIZ_AUTO_UPDATE_SUPPORT
}

void FitWizCoreBase::SetFinishButtonClicked(bool bClicked )//true
{
	m_bIsFinishButtonClicked = bClicked;
}

bool FitWizCoreBase::IsFinishButtonClicked()
{
	return m_bIsFinishButtonClicked;
}

//------ Folger 10/16/08 SAVE_PLOT_UIDS_IN_PA_CORE_TO_WORKAROUND_MISSING_PREVIEW_PLOT_IN_PA_FIT
bool FitWizCoreBase::AccessOriginalRangePlots(vector<uint>& vnPlots, bool bGet/* = true*/)
{
	if ( bGet )
		vnPlots = m_vnOriginalRangePlots;
	else
		m_vnOriginalRangePlots = vnPlots;
	
	return true;
}
//------ End SAVE_PLOT_UIDS_IN_PA_CORE_TO_WORKAROUND_MISSING_PREVIEW_PLOT_IN_PA_FIT

//------ Folger 12/30/08 v8.0992 NANOSIZER_USING_NEW_XFWIZARD_FRAMEWORK
bool FitWizCoreBase::GetTargetPage(Page& pg)
{
	XFWizNavigation *pXFWizNavg = (XFWizNavigation *)GetXFWizNavigation();
	if ( !pXFWizNavg )
	{
		ASSERT(FALSE);
		return error_report("Can't get navigation for xfcore");
	}
	
	XFWizInputOutputRange *pIORange = pXFWizNavg->GetXFWizInputOutputRange();
	if ( !pIORange )
	{
		ASSERT(FALSE);
		return error_report("Can't get io range for xfcore");
	}
	
	return pIORange->GetTargetPage(pg);
}
//------ End NANOSIZER_USING_NEW_XFWIZARD_FRAMEWORK

//virtual
void FitWizCoreBase::Destroy()
{
	///---Sim 12-04-2008 IMPROVE_XF_WIZ_FRAMEWORK
	/*
	bool bFinish = false;
	XFWizDlgNavigation *pXFWizDlgNavg = (XFWizNavigation *)GetXFWizNavigation();
	if ( pXFWizDlgNavg )
		bFinish = pXFWizDlgNavg->IsFinish();
	*/
	///---END IMPROVE_XF_WIZ_FRAMEWORK
}

virtual bool FitWizCoreBase::GetSourceRange(DataRange& drSource)
{	
	if(m_drSource)
	{
		drSource = m_drSource;
		
		return true;
	}
	
	return false;
}	
	
void FitWizCoreBase::SetSourceRange(const DataRange& drSource)
{
	/// Iris 11/06/2008 v8.0966b IMPROVE_GET_SOURCE_GRAPH_CODES, = here means copy referce
	//m_drSource = drSource;
	drSource.Clone(m_drSource);
	///end IMPROVE_GET_SOURCE_GRAPH_CODES
}

//virtual
bool FitWizCoreBase::HasBaseline()
{
	ASSERT(0);
	return false;
}

//------ Folger 12/11/08 QA80-12765 v8.0985 CHANGE_PARAMETER_FAILS_TO_REMEMBER_SETTINGS_FROM_LAST_CLOSE_IN_PA_FITTING
bool	FitWizCoreBase::IsAutoUpdated()
{
	return IsChangeParam() || IsRecalculate();
}
//------ End CHANGE_PARAMETER_FAILS_TO_REMEMBER_SETTINGS_FROM_LAST_CLOSE_IN_PA_FITTING

///------ Folger 02/13/09 IGNORE_AUTO_INIT_STATUS_IF_AND_ONLY_IF_CHANGE_PARAM
bool	FitWizCoreBase::IsChangeParam()
{
	return (m_dwXFMode & LTXF_CHANGE_PARAM);
}
///------ End IGNORE_AUTO_INIT_STATUS_IF_AND_ONLY_IF_CHANGE_PARAM

///------ Folger 10/28/09 QA81-14552 WRONG_REPORT_STATUS_WHEN_CHANGE_PARAM_IN_PA
bool	FitWizCoreBase::IsRecalculate()
{
	return (m_dwXFMode & LTXF_EXEC_RECALCULATE);
}
///------ End WRONG_REPORT_STATUS_WHEN_CHANGE_PARAM_IN_PA

///------ Folger 10/20/09 NANOSIZER_FAILS_TO_SWITCH_LABEL_PLOT
bool	FitWizCoreBase::AccessPeakLabelSettings(int& nLabelXYType, bool bGet/* = true*/)
{
	GraphLayer gl;
	if(!GetPreviewLayer(gl, !bGet) || !gl)
		return false;
	
	XYRange xyPeaksCenter;
	if(!GetPeaksCenterRange(xyPeaksCenter))
	{
		return false;
	}
	
	DataPlot dp;
	if( !get_plot_from_xyr_in_gl(gl, xyPeaksCenter, dp, IDM_PLOT_TEXT) )
		return false;
	
	return dp.LabTalk(STR_PLOT_DATA_LABEL_TYPE, &nLabelXYType, bGet ? false : true) == 0 ? true : false;
}
///------ End NANOSIZER_FAILS_TO_SWITCH_LABEL_PLOT

XFWizInputOutputRange*   FitWizCoreBase::getIORange()
{
	XFWizNavigation *pXFWizNavg = (XFWizNavigation *)GetXFWizNavigation();
	ASSERT(pXFWizNavg);
	if ( !pXFWizNavg )
		return NULL;
	
	XFWizInputOutputRange*	pIORange = pXFWizNavg->GetXFWizInputOutputRange();
	if(!pIORange)
		return NULL;
	
	return pIORange;
}

///------ Folger 02/11/09 SHARE_WIZ_CORE_BASE_CODE_BETWEEN_PA_AND_NANOSIZER
//bool FitWizCoreBase::getContextRange(XYRange& xy, LPCSTR lpcszXFName, bool bIsInput, int nIndex)
bool FitWizCoreBase::getContextRange(DataRange& dr, LPCSTR lpcszXFName, bool bIsInput, int nIndex)
///------ End SHARE_WIZ_CORE_BASE_CODE_BETWEEN_PA_AND_NANOSIZER
{

	XFWizInputOutputRange	*pIORange = getIORange();
	if(!pIORange)
		return false;
	
	Array<DataRange&>	drs;
	
	if(!pIORange->Get(&drs, lpcszXFName, bIsInput))
		return false;
	
	if( nIndex >= drs.GetSize())
		return false;
	
	///------ Folger 02/11/09 SHARE_WIZ_CORE_BASE_CODE_BETWEEN_PA_AND_NANOSIZER
	///// Iris/Sim 11/18/2008 v8.0974 FIX_FAIL_TO_GET_SOURCE_DATAPLOT_WHEN_PA_FIT_DO_RECALCULATE
	//// before directly return the reference of input range, outside can change this input, after create preview graph, 
	//// changed input range from the plot on source graph to the plot on preview graph, so recalculate will fail to get source data plot.
	////xy = drs.GetAt(nIndex);
	//XYRange dr = drs.GetAt(nIndex);
	//dr.Clone(xy);
	/////end FIX_FAIL_TO_GET_SOURCE_DATAPLOT_WHEN_PA_FIT_DO_RECALCULATE
	//
	/////Sandy 2008-8-25 pa_goal input xyrange, so maybe no need to convert
	///*
	//// temp fix by Sim, wait for Yuri fix
	//DataRange tempdr;
	//tempdr = drs.GetAt(nIndex);
	//int r1, c1, r2, c2;
	//Datasheet ds;
	//if ( tempdr.GetRange(1, r1, c1, r2, c2, ds) ) // x column
	//{
		//tempdr.SetRange(1, ds, r1, c1, r2, c2, "Y");
	//}
	//xy = tempdr;
	//*/
	//
	//return xy.IsValid();
	DataRange drSrc;
	drSrc = drs.GetAt(nIndex);
	drSrc.Clone(dr);
	
	return dr.IsValid();
	///------ End SHARE_WIZ_CORE_BASE_CODE_BETWEEN_PA_AND_NANOSIZER
}

///---Sim 06-23-2009 NANOSIZER_WIZ_AUTO_UPDATE_SUPPORT
// move from PAWizCore.c

static	bool	_update_fitting_output_range(Array<DataRange&>& arrdrOutputs, const vector<int>& vnUIDs)
{
	arrdrOutputs.SetSize(0);
	for ( int ii=0; ii<vnUIDs.GetSize(); ++ii )
	{
		DataRange *pdr = new DataRange;
		*pdr = (DataRange)Project.GetObject(vnUIDs[ii]);
		
		if ( !pdr->IsValid() )
		{
			///------ Folger 01/19/09 QA80-12969 PA_FITTING_SUPPORT_ANALYSIS_TEMPLATE
			//delete pdr;
			//continue;
			pdr->Create();
			///------ End PA_FITTING_SUPPORT_ANALYSIS_TEMPLATE
		}
		
		pdr->SetName(PEAK_FITTING_OUTPUT_EMPTY_RANGE_NAME, FALSE);
		arrdrOutputs.Add(*pdr);
	}
	return true;
}

///------ Folger 12/18/09 QA81-14860 REUID_PA_OUTPUTS_FOR_AUTO_UPDATE
/// virtual
BOOL	FitWizCoreBase::CheckUpdateOperationTree(DWORD dwUIDOp)
{
	Operation&		opWiz = (Operation&)Project.GetOperationObject(dwUIDOp);
	if ( !opWiz )
		return FALSE;

	if ( m_vnIdsToUIDs.GetSize() > 0 )
		opWiz.SetIdsToUIDsMap(m_vnIdsToUIDs);
	
	Tree		trOp;
	opWiz.GetTree(trOp);
	
	if ( m_vnSourceGraphUID.GetSize() > 0 )
		trOp.Operation.SourceGraphUID.nVals = m_vnSourceGraphUID;


	if ( m_vnReportLayerUID.GetSize() > 0 )
		trOp.Operation.ReportLayer.nVals = m_vnReportLayerUID;

	opWiz.SetTree(trOp);
	
	return TRUE;
}

BOOL	FitWizCoreBase::UpdateGetNFromWizOp(TreeNode& trGetN)
{
	Operation&		opWiz = (Operation&)Project.GetOperationObject(GetXFWizOp());
	if ( !opWiz )
		return FALSE;

	vector<uint>		vnIdsToUIDs;
	opWiz.GetIdsToUIDsMap(vnIdsToUIDs);
	trGetN.trUID.graph_uid.nVals = vnIdsToUIDs;
	
	Tree		trOp;
	opWiz.GetTree(trOp);

	TreeNode	trSourceGraphUID = trOp.Operation.SourceGraphUID;
	if ( trSourceGraphUID )
		trGetN.trAdv.SourceGraphUID.nVals = trSourceGraphUID.nVals;

	TreeNode	trReportLayerUID = trOp.Operation.ReportLayer;
	if ( trReportLayerUID )
	{
		vector<int>&		vn = trReportLayerUID.nVals;
		if ( vn.GetSize() > 0 )
			trGetN.trAdv.OutputGraph.LayerUID.nVal = vn[0];
	}

	return TRUE;
}

BOOL	FitWizCoreBase::UpdateFittingOutputs(TreeNode& trGetN)
{
	vector<int>		vnUIDs;
	vnUIDs = m_trGetN.trUID.range_uid.nVals;
	_update_fitting_output_range(m_arrdrOutputs, vnUIDs);

	TreeNode	trSourceGraphUID = trGetN.trAdv.SourceGraphUID;
	if ( trSourceGraphUID )
		m_vnSourceGraphUID = trSourceGraphUID.nVals;

	TreeNode	trIdsToUIDs = trGetN.trUID.graph_uid;
	if ( trIdsToUIDs )
		m_vnIdsToUIDs = trIdsToUIDs.nVals;

	TreeNode	trReportLayerUID = trGetN.trAdv.OutputGraph.LayerUID;
	if ( trReportLayerUID )
	{
		m_vnReportLayerUID.SetSize(1);
		m_vnReportLayerUID = trReportLayerUID.nVal;
	}
	
	return TRUE;
}
///------ End REUID_PA_OUTPUTS_FOR_AUTO_UPDATE

//virtual
bool FitWizCoreBase::Apply()
{
	//------ Folger 12/04/08 v8.0982b LASE_USED_FOR_PA_FIT_FAIL_TO_CREATE_NEW_REPORT_SHEETS
	///---Sim 06-23-2009 NANOSIZER_WIZ_AUTO_UPDATE_SUPPORT
	//XFWizNavigation		*pXFWizNavg = (XFWizNavigation *)GetXFWizNavigation();
	//bool				bIsPaFitStep = pXFWizNavg && pXFWizNavg->GetXFName(pXFWizNavg->GetStep()).CompareNoCase(STR_PA_XFNAME_FIT) == 0;
	bool bIsFitStep = IsFitStep();
	///---END NANOSIZER_WIZ_AUTO_UPDATE_SUPPORT
	
	//if ( bIsPaFitStep )
	if ( bIsFitStep )
	{
		if ( !IsAutoUpdated() )
		{
			vector<int>		vnEmpty;
			m_trGetN.trUID.range_uid.nVals = vnEmpty;
			m_trGetN.trUID.graph_uid.nVals = vnEmpty;
			m_trGetN.trAdv.OutputGraph.LayerUID.nVal = 0;
		}
	}
	//------ End LASE_USED_FOR_PA_FIT_FAIL_TO_CREATE_NEW_REPORT_SHEETS
	
	bool bRet = XFCore::Apply();
	
	if ( bRet )
	{
		//------ Folger 12/04/08 v8.0982b LASE_USED_FOR_PA_FIT_FAIL_TO_CREATE_NEW_REPORT_SHEETS
		//if ( pXFWizNavg && pXFWizNavg->GetXFName(pXFWizNavg->GetStep()).CompareNoCase(STR_PA_XFNAME_FIT) == 0 )
		//if ( bIsPaFitStep )
		if ( bIsFitStep )
		//------
		{
			//------ Folger 11/13/08 QA80-12488 v8.970 PA_FITTING_AUTO_UPDATE_SUPPORT_USE_VECTOR_FOR_UIDS_STORAGE
			//_update_fitting_output_range(m_arrdrOutputs, PA_FIT_OUTPUT_OY1, m_trGetN.oy1);
			//_update_fitting_output_range(m_arrdrOutputs, PA_FIT_OUTPUT_OY2, m_trGetN.oy2);
			//_update_fitting_output_range(m_arrdrOutputs, PA_FIT_OUTPUT_OY3, m_trGetN.oy3);
			///------ Folger 12/18/09 QA81-14860 REUID_PA_OUTPUTS_FOR_AUTO_UPDATE
			//vector<int>		vnUIDs;
			//vnUIDs = m_trGetN.trUID.range_uid.nVals;
			//_update_fitting_output_range(m_arrdrOutputs, vnUIDs);
			UpdateFittingOutputs(m_trGetN);
			///------ End REUID_PA_OUTPUTS_FOR_AUTO_UPDATE
			//------ End PA_FITTING_AUTO_UPDATE_SUPPORT_USE_VECTOR_FOR_UIDS_STORAGE
		}
	}
	
	return bRet;
}
///---END NANOSIZER_WIZ_AUTO_UPDATE_SUPPORT

///---Sim 06-23-2009 NANOSIZER_WIZ_AUTO_UPDATE_SUPPORT
Worksheet FitWizCoreBase::CheckGetInterimResult(string strInterimSheet)
{
	
	if ( !m_wpInterim )
	{
		string strPageName = GetTempBookPrefix() + (string)m_nInstanceID;
		WorksheetPage wp(strPageName);
		if(!wp.IsValid())
		{
#ifdef _DEBUG
			wp.Create("Origin",  CREATE_HIDDEN);
#else
			wp.Create("Origin",  CREATE_HIDDEN|CREATE_SET_MISSING_IN_MANAGER);
#endif			
			wp.Rename(strPageName);
		}
		m_wpInterim = wp;
		
		Worksheet wks = m_wpInterim.Layers();
		if ( wks )
		{
			wks.SetName(strInterimSheet);
			return wks;
		}
	}
	
	Worksheet wks = m_wpInterim.Layers(strInterimSheet);	
	if(!wks)
	{
		int nSheet = m_wpInterim.AddLayer(strInterimSheet);	
		wks = m_wpInterim.Layers(nSheet);
	}
	
	return wks;
		
}
///---END NANOSIZER_WIZ_AUTO_UPDATE_SUPPORT

/*
put util function shared in PA&Nanosizer here
I want to put them in XFWizard_utils, 
but it need GetN.h
*/
////////////////////////////////////////////////////////
///////////////////	util functin	////////////////////
////////////////////////////////////////////////////////
void xf_turnon_user_event_receiver(TreeNode& trGetN)
{
	if(!trGetN)
		return;
	trGetN.SetAttribute(STR_ATTRIB_POST_USER_MESSAGE, 1);
}


///Jasmine 04/23/09 NANO_CENTRIALIZE_FUNCTION

//move from PAWizCore.c
///Kyle 11/13/2008 KEEP_TREE_DATA_ID_SAME_AS_THE_OLD_XF
//typedef void(*pfn_remove_pointers_node_in_output)(TreeNode& trGUI, bool bOperationPointer = true, bool bGUIMngrPointer = true );
typedef void(*pfn_reset_pointers_in_output)(TreeNode& trGUI, bool bOperationPointer = true, bool bGUIMngrPointer = true );
///End KEEP_TREE_DATA_ID_SAME_AS_THE_OLD_XF
///Sophy 9/25/2008 NEW_PA move static tree s_trOp to xf
//static bool	_create_op_get_gui_tree(TreeNode& trGUI)
///Sophy 7/6/2009 SUPPORT_NANOSIZER_OUTPUTGUIMANAGER
//bool	create_op_get_gui_tree(TreeNode& trOp, TreeNode& trGUI, LPCSTR lpcszOperation, int nOption/*= 0*/)///Jasmine 06/30/09 NANOSIZER_NEED_FITTYPE_TO_SHOW_SPEC_NODE_IN_GUI_TREE
bool	create_op_get_gui_tree(TreeNode& trOp, TreeNode& trGUI, LPCSTR lpcszOperation, XFInfo* xfInfo/*= NULL*/)///Jasmine 06/30/09 NANOSIZER_NEED_FITTYPE_TO_SHOW_SPEC_NODE_IN_GUI_TREE
///end SUPPORT_NANOSIZER_OUTPUTGUIMANAGER
///end NEW_PA
{
	if(!trOp.FirstNode)//if( 0 == trOp.GetNodeCount() )
	{
		bool bInitOK;
		///Sophy 7/6/2009 SUPPORT_NANOSIZER_OUTPUTGUIMANAGER
		int nOption = 0;
		if ( xfInfo )
			nOption = get_fit_type(xfInfo->strSetInfoFromXF);
		///end SUPPORT_NANOSIZER_OUTPUTGUIMANAGER
		Operation& op = (Operation &)op_create(lpcszOperation, bInitOK, nOption); 		
		if( NULL == op || !bInitOK )
			return false;
		
		///Sophy 7/6/2009 SUPPORT_NANOSIZER_OUTPUTGUIMANAGER
		if ( xfInfo )
			op.SetInfoFromXF(nOption, xfInfo->strSetInfoFromXF, xfInfo->saOptions, xfInfo->saNames, xfInfo->strCategory);
		///end SUPPORT_NANOSIZER_OUTPUTGUIMANAGER
		
		op.GetTree(trOp);		
		
		///Iris 4/10/2008 PEAK_FIT_REPORT_PEAK_CHARACTERISTICS_TO_SEPARATE_SHEET
		// in order to call GUIPrepareOutputBranch
		op.OperationtoGUI(trOp, true, NULL, false); 
		///end PEAK_FIT_REPORT_PEAK_CHARACTERISTICS_TO_SEPARATE_SHEET
		///Sophy 9/24/2008 NEW_PA if don't remove pointer, when do two consecutive pa fit, origin will crash
		///Kyle 11/13/2008 KEEP_TREE_DATA_ID_SAME_AS_THE_OLD_XF
		//pfn_remove_pointers_node_in_output pfn =  Project.FindFunction("remove_pointers_node_in_output", "OriginLab\\wksoperation.c", true);
		pfn_reset_pointers_in_output pfn =  Project.FindFunction("reset_pointers_in_output", "OriginLab\\wksoperation.c", true);
		///End KEEP_TREE_DATA_ID_SAME_AS_THE_OLD_XF
		ASSERT(pfn);
		if(pfn)
			pfn( trOp.GUI.Output );
		///end NEW_PA
		///Sophy 9/25/2008 NEW_PA
		//op.SetTree(s_trOp);
		op_destroy_on_cancel( op );
		///end NEW_PA
	}
	
	trGUI = trOp.GUI;
	return true;
}

///Jasmine 04/24/09 DEFINE_DATA_ID__USED_IN_PA_NANO_SIZER_FIT_TREE
///Kyle 11/13/2008 KEEP_TREE_DATA_ID_SAME_AS_THE_OLD_XF
//static bool _assign_new_ID(TreeNode& tr, int nID) 
//bool assign_new_ID(TreeNode& tr, int& nID) 
int assign_new_ID(TreeNode& tr, int& nID) 
///End KEEP_TREE_DATA_ID_SAME_AS_THE_OLD_XF
{
	if(!tr)
		return -1;
	_backup_data_id(tr);
	
	tree_remove_attribute(tr, STR_REPEAT_ID_ATTRIB);
	tree_remove_attribute(tr, STR_DATAID_ATTRIB);	
	
	///------ Folger 02/12/09 QA80-12962 PROPER_ASSIGN_ID_FOR_NEW_ADDED_NODES
	//_construct_theme_dataid(tr, nID);
	Array<TreeNode&>	arrTr(TRUE);
	_construct_theme_dataid(tr, nID, arrTr);
	
	for ( int ii=0; ii<arrTr.GetSize(); ++ii )
	{
		TreeNode trNode = arrTr.GetAt(ii);
		_construct_theme_dataid(trNode, nID);
	}
	///------ End PROPER_ASSIGN_ID_FOR_NEW_ADDED_NODES
	
	int nNextID = nID;
	return nNextID;
}
///End DEFINE_DATA_ID__USED_IN_PA_NANO_SIZER_FIT_TREE
static void _backup_data_id(TreeNode tr)
{
	tr.SetAttribute(STR_BACKUP_ID_ATTRIB, tr.DataID);
	foreach(TreeNode trChild in tr.Children)
	{
		_backup_data_id(trChild);
	}
}

///------ Folger 07/01/09 THEME_SAVED_IN_SR5_FAILS_TO_BE_APPLIED_AFTER_NEW_RESULTS_NODE_ADDED_IN_PA
static	void	_check_add_backup_node(Array<TreeNode&>& arrTr, TreeNode& tr, int nVer)
{
	TreeNode*		pNode = new TreeNode(tr);
	for ( int ii=0; ii<arrTr.GetSize(); ++ii )
	{
		TreeNode&	trNode = arrTr.GetAt(ii);
		int			nVerTmp = 1;
		trNode.GetAttribute(STR_DELAY_DATAID_ASSIGN_ATTRIB, nVerTmp);
		if ( nVer < nVerTmp )
			break;
	}
	arrTr.SetSize(arrTr.GetSize() + 1);
	for ( int jj=arrTr.GetSize()-1; jj>ii;  --jj )
	{
		TreeNode*	pNodeTmp = new TreeNode(arrTr.GetAt(jj-1));
		arrTr.SetAt(jj, *pNodeTmp);
	}
	arrTr.SetAt(jj, *pNode);
}
///------ End THEME_SAVED_IN_SR5_FAILS_TO_BE_APPLIED_AFTER_NEW_RESULTS_NODE_ADDED_IN_PA

///---Sim 11-17-2007 HARD_CODE_TO_REMOVE_REPEAT_ID
///------ Folger 02/12/09 QA80-12962 PROPER_ASSIGN_ID_FOR_NEW_ADDED_NODES
//static void _construct_theme_dataid(TreeNode tr, int& nID)
static void _construct_theme_dataid(TreeNode tr, int& nID, Array<TreeNode&>& arrTr = NULL)
///------ End PROPER_ASSIGN_ID_FOR_NEW_ADDED_NODES
{
	///------ Folger 02/12/09 QA80-12962 PROPER_ASSIGN_ID_FOR_NEW_ADDED_NODES
	int		nVer = 1;
	if ( NULL != arrTr && tr.GetAttribute(STR_DELAY_DATAID_ASSIGN_ATTRIB, nVer) )
	{
		///------ Folger 07/01/09 THEME_SAVED_IN_SR5_FAILS_TO_BE_APPLIED_AFTER_NEW_RESULTS_NODE_ADDED_IN_PA
		//TreeNode* pNode = new TreeNode(tr);
		//arrTr.Add(*pNode);
		_check_add_backup_node(arrTr, tr, nVer);
		///------ End THEME_SAVED_IN_SR5_FAILS_TO_BE_APPLIED_AFTER_NEW_RESULTS_NODE_ADDED_IN_PA
	}
	else
	{
	///------ End PROPER_ASSIGN_ID_FOR_NEW_ADDED_NODES
		tr.SetAttribute(STR_DATAID_ATTRIB, GET_USER_DATAID(nID));
		nID++;
		foreach(TreeNode trChild in tr.Children)
		{
			//if ( trChild.GetNodeCount() > 0 )
			//{
				///------ Folger 02/12/09 QA80-12962 PROPER_ASSIGN_ID_FOR_NEW_ADDED_NODES
				//_construct_theme_dataid(trChild, nID);
				_construct_theme_dataid(trChild, nID, arrTr);
				///------ End PROPER_ASSIGN_ID_FOR_NEW_ADDED_NODES
			//}
			//else
			//{
				//trChild.SetAttribute(STR_DATAID_ATTRIB, GET_USER_DATAID(nID));
				//nID++;
			//}
		}
	}	///------ Folger 02/12/09 QA80-12962 PROPER_ASSIGN_ID_FOR_NEW_ADDED_NODES
}

///End NANO_CENTRIALIZE_FUNCTION

///------ Folger 05/12/09 NANOSIZER_FITTING_BASED_SUPPORT
typedef bool (* PFMDLG_FUNC)(PeakFitHelperBase *pFitHelperBase, int nOption, DWORD dwCntrl);
bool access_peak_params_dlg(PeakFitHelperBase *pFitHelperBase, int nOption, DWORD dwCntrl/* = 0*/)
{
	string 	strFile = GetAppPath(true) + "OriginC\\Originlab\\PeakFitParameterDlg.cpp";
	
	PFMDLG_FUNC pfm = Project.FindFunction("FitPeakDlg", strFile, true);
	if( pfm )
	{
		return pfm(pFitHelperBase, nOption, dwCntrl);
	}
	return false;
}
///------ End NANOSIZER_FITTING_BASED_SUPPORT


//----- Iris 2008-10-09 NEW_PA
//bool xf_check_is_user_event(TreeNode& trGetN, int& nUserEventID )
bool xf_check_is_user_event(TreeNode& trGetN, int& nUserEventID, int* pnUserEventInfo)
//-----
{
	if(!trGetN)
		return false;
	
	int id = -1;
	if(trGetN.GetAttribute(STR_GO_MSG_INFO_1_ATTRIB, id))
	{
		trGetN.RemoveAttribute(STR_GO_MSG_INFO_1_ATTRIB);
		
		if(nUserEventID != NULL)
			nUserEventID = id;
		
		//----- Iris 2008-10-09 NEW_PA
		if( trGetN.GetAttribute(STR_GO_MSG_INFO_2_ATTRIB, id) && pnUserEventInfo )
		{
			trGetN.RemoveAttribute(STR_GO_MSG_INFO_2_ATTRIB);
			*pnUserEventInfo = id;
		}
		//-----
		
		return true;
	}
	else
		return false;
}


///Sandy  2008-9-4 ADD_UTIL_FUNC_construct_tree_from_xyrange_FOR_FITTING
bool construct_tree_from_xyrange(TreeNode& trXYR, const DataRange& xy)
{

	if( !xy || !trXYR )
    {
        ASSERT(FALSE);
        return false;
    }
    
    string strRangeString;
 	///for adding row index and show on gui
    if( !xy.GetRangeString(strRangeString,  NTYPE_ADD_ROW_RANGE))
        return false;   
        
	Tree tr;
	tr.AddNode(IMPTREE_NODE_DATA_RANGE);
	TreeNode trDataRange = tree_check_get_node(tr, IMPTREE_NODE_DATA_RANGE);
	xy.GetTree(trDataRange);//each ranges as a treenode of the tree
	
	TreeNode trRange1 = trXYR.Range1;
	if(!trRange1)
    {
         trXYR.RemoveChildrenWithPrefix(NULL);
         trRange1 = trXYR.AddNode("Range1");
    }
    trXYR.Range1.Replace(trDataRange, true, true, false); 

    trXYR.Range1.SetAttribute(STR_DATA_ATTRIB, strRangeString);
  	//trXYR.Range1.SetAttribute(STR_PLOTOBJ_UID_ATTRIB, (int)dpData.GetUID());

	// --------------------------------------------------	
	// this function call is replication of logic of sub-dyna control.
	// it is responsibility of sub-dyna control to update this attribute in the root level
	// you have to do it manually here
	trXYR.SetAttribute(STR_DATA_ATTRIB, strRangeString);
	// ----------------------------------------------------
	
	return true;
}

///Kyle 03/11/2010 PICK_PEAK_ROI_TOOL_SHARES_UTILS_FUNCTION_WITH_PA
/*
///------ Folger 10/20/09 NANOSIZER_FAILS_TO_SWITCH_LABEL_PLOT
bool get_plot_from_xyr_in_gl(GraphLayer gl, XYRange& xy, DataPlot& dp, int nPlotType)
{
	if(!xy||!gl)
	{
		//error_report("In PAWizCore.c, get_plot_from_xyr_in_gl(), Invalid xyrange or gl!");
		return false;
	}
	
	vector<int> vnPlotIndices;	
	
	///Sandy 2008-10-9 waitting for yuri
	//if(0>check_has_plotted_in_graph(xy, gl, vnPlotIndices) || vnPlotIndices.GetSize() <= 0)
	if(0>check_has_plotted_in_graph(xy, gl, vnPlotIndices, NTYPE_BOOKSHEET_XY_RANGE) || vnPlotIndices.GetSize() <= 0)
	{
		//error_report("In PAWizCore.c, get_plot_from_xyr_in_gl(), no dataplot!");
		return false;
	}
	
	if(nPlotType == -1)
	{
		int nplot = vnPlotIndices[0];
		dp = gl.DataPlots(nplot);
		return true;
	}
	else
	{
		for(int ii = 0; ii < vnPlotIndices.GetSize(); ii++)
		{
			DataPlot dpTemp;
			int nplot = vnPlotIndices[ii];
			dpTemp = gl.DataPlots(nplot);
			int nType = dpTemp.GetPlotType();
			if(nType == nPlotType)
			{
				dp = dpTemp;
				return true;
			}
		}
	}
	return false;
}
///------ End NANOSIZER_FAILS_TO_SWITCH_LABEL_PLOT
*/
///End PICK_PEAK_ROI_TOOL_SHARES_UTILS_FUNCTION_WITH_PA