#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	weight_none,
	weight_instrumental,
	weight_statistical,
	weight_arbitrary_dataset,
	weight_direct,
};

//put additional include files here
#include <..\OriginLab\pawizcore.h>
#include <..\OriginLab\curve_utils.h>
#include <..\OriginLab\XFWizard_utils.h>
/// Iris 11/11/2008 v8.0968 MOVE_PA_ENUM_TO_NEW_HEADER_PA_UTILS
#include <..\OriginLab\PFM_utils.h>///Sophy 11/27/2008 v8.980d QA80-12680 SHOW_ERR_MSG_WHEN_PEAK_FIT_FUNC_IS_NOT_IN_PFW

#include <..\OriginLab\pa_utils.h>
///end MOVE_PA_ENUM_TO_NEW_HEADER_PA_UTILS
#include <..\OriginLab\PeakFitHelper.h>
//#include <..\OriginLab\PeakFitParameterDlg.h>
#include <event_utils.h>

#include <o8dlg.h>

//put your own support static functions here
/*------------------------------------------------------------------------------*
 * Modification Log:  															*
 * Iris 10/30/2008 v8.0963b CORRECT_ENABLE_FIT_BUTTON_CONDITION					*
 * Sim 10-31-2008 INDICATE_THEME_ON_PA_FIT_PARAM_CHANGE							*
 *	Folger 11/06/08 NO_NEED_TO_CHECK_FILE_EXISTENCE_BEFORE_FIND_FUNCTION		*
 *  Iris 11/12/2008 v8.0969 OUTPUT_BASELINE_AND_SUBTRACTED_DATA_IN_FIT_PEAK_OP	*
 *	Hong 11/14/08 v8.0971b DISABLE_OPTIONS_INSTEAD_OF_HIDDEN_IT_FOR_BASELINE_OUTPUT_OPTIONS
 *	Folger 11/15/08 QA80-12488 v8.0972 NEED_TO_BRING_BACK_REPORT_GRAPHS_UID_FOR_AUTO_UPDATE
 *	Hong 11/18/08 QA80-12603 v8.0974 PA_SUPPORT_LEGEND_UPDATE_OPTION			*
 *	Sophy 11/26/2008 v8.980 PA_CHANGE_PARAMS_SHOULD_DISABLE_OUTPUT_DESTINATION_AS_OTHER_FITTING_TOOLS
 *	Sophy 11/27/2008 v8.980d QA80-12680 SHOW_ERR_MSG_WHEN_PEAK_FIT_FUNC_IS_NOT_IN_PFW
 *	Sophy 11/28/2008 v8.0980d CHECK_FIT_FUNCTIONS_ON_PARAMS_CHANGE				*
 *  Iris 12/01/2008 v8.0981 FIX_CHANGE_PARAM_ALWAYS_REPLOT_ON_SOURCE_GRAPH		*
 *	Folger 12/03/08 v8.0982 CLEAR_BASELINE_PLOT_CREATED_BY_PREVIOUS_STEPS_BEFORE_ENTER_PA_FIT
 *	Folger 12/11/08 QA80-12765 v8.0985 CHANGE_PARAMETER_FAILS_TO_REMEMBER_SETTINGS_FROM_LAST_CLOSE_IN_PA_FITTING
 *	Folger 12/24/08 v8.0990c SUPPORT_SPECIFIC_NODE_TO_SKIP_EVENT1_IN_PA_FIT		*
 *  Iris 01/04/2008 ADD_ERR_CHECK_FOR_FIT_HELPER_INIT							*
 *	Sim 01-07-2008 QA80-12833 FIX_APPLY_XF_WIZ_XF_TWICE							*
 *	Kyle 01/16/2009 XF_CHECK_CHECK_SET_LAST_OUTCOME_MESSAGE						*
 *	Folger 02/04/09 QA80-12962 ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM
 *  Iris 3/05/2009 FIX_WEIGHT_DATA_STILL_EMPTY_WHEN_INPUT_INCLUDED_YERR			*
 *	Folger 03/06/09 WEIGHT_DATA_NOT_UPDATED_WHEN_CHANGE_PARAM_IN_PA_FITTING		*
 *	Folger 05/12/09 NANOSIZER_FITTING_BASED_SUPPORT								*
 *	Folger 06/22/09 QA80-13814 PA_FITTING_VALUES_FAILS_TO_BE_SAVED_IN_THEME		*
 *	Sophy 7/22/2009 v8.1073 NANOSIZER_NEED_TO_GET_ORIGINAL_INPUTDATA			*
 *	Folger 09/05/09 FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
 *	Folger 10/24/09 LCL_UCL_FAILS_TO_BE_CALCULATE_IN_PA							*
 *	Folger 11/25/09 QA81-14734-P1 PA_FITTING_FAILS_TO_UPDATE_FIT_CURVE_POINTS_AFTER_CHANGE_AUTO
 *	Jasmine 04/15/10 QA81-15304 ANNOUNCE_FITTING_FUNC_CHANGE					*
 *------------------------------------------------------------------------------*/

#define		GETNE_BUTTON_FIT_CONTROL	GETNE_ON_CUSTOM_BUTTON1
#define		GETNE_BUTTON_FIT			GETNE_ON_CUSTOM_BUTTON2

#define		ENABLE_FIT_BUTTON(_bEnable)	bBTN2Enable = _bEnable

#define _ERROR_CODE_ATTRIB		"ErrorCode"
#define _ERROR_CODE_ATTRIB2		"ErrorCode2"

#define _STR_BUTTON_LIST 	("Add|Modify/Del")   //sandy 2008-4-18 add modify/del buttons 

///////////////////////////////////////////////////////////////////////////
/// PeakFitParameterDlg Access
///////////////////////////////////////////////////////////////////////////
static bool _access_params_dlg(PeakFitHelper *pFitHelper, int nOption, DWORD dwCntrl = 0)
{
	///------ Folger 05/12/09 NANOSIZER_FITTING_BASED_SUPPORT
	//string 	strFile = GetAppPath(true) + "OriginC\\Originlab\\PeakFitParameterDlg.cpp";
//
	////------ Folger 11/06/08 NO_NEED_TO_CHECK_FILE_EXISTENCE_BEFORE_FIND_FUNCTION
	////if( !strFile.IsFile() )
		////return error_report("fail to find file " + strFile);
	////------
	//
	//PFMDLG_FUNC pfm = Project.FindFunction("FitPeakDlg", strFile, true);
	//if( pfm )
	//{
		//return pfm(pFitHelper, nOption, dwCntrl);
	//}
	//return false;
	return access_peak_params_dlg(pFitHelper, nOption, dwCntrl);
	///------ End NANOSIZER_FITTING_BASED_SUPPORT
}
///////////////////////////////////////////////////////////////////////////
/// End PeakFitParameterDlg Access
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
/// PeakFitHelper Access
///////////////////////////////////////////////////////////////////////////

//static	void	_create_peak_fit_helper(TreeNode& trGetN)
//{
	//PeakFitHelper	*pPeakFitHelper = new PeakFitHelper();
	//
	//PAWizCore *paCore = (PAWizCore*)get_xf_core_handler(trGetN);
	//
	//paCore->SetPeakFitHelper(pPeakFitHelper);
//}

//static	void	_destroy_peak_fit_helper(TreeNode& trGetN)
//{
	//delete _check_get_peak_fit_helper(trGetN);
//}
static	PeakFitHelper*	_check_get_peak_fit_helper(TreeNode& trGetN)
{
	PAWizCore *paCore = (PAWizCore*)get_xf_core_handler(trGetN);
	if( NULL == paCore)
		return NULL;
	return paCore->CheckGetPeakFitHelper();
}

///////////////////////////////////////////////////////////////////////////
/// End PeakFitHelper Access
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
/// GUI Event 
///////////////////////////////////////////////////////////////////////////
static void _addbackbaseline_checkbox_set_show_event(TreeNode& trGetN)
{
	PAWizCore		*paCore = (PAWizCore*)get_xf_core_handler(trGetN);
	bool			bBaselineSubtracted = paCore->GetSubtractedMode();
	
	TreeNode		trAddBackBaseline = trGetN.result.gpconfig.Graph1.AddBackBaseline;
	ASSERT(trAddBackBaseline);	
	if(trAddBackBaseline)
	{
		trAddBackBaseline.Show = bBaselineSubtracted;
	}	

	_update_baseline_subtracted_data_output_gui_display_status(trGetN, paCore->HasBaseline(), bBaselineSubtracted);
}

/// Iris 11/12/2008 v8.0969 OUTPUT_BASELINE_AND_SUBTRACTED_DATA_IN_FIT_PEAK_OP
static void _update_baseline_subtracted_data_output_gui_display_status(TreeNode& trGetN, bool bHasBaseline, bool bBaselineSubtracted)
{	
	/// Hong 11/14/08 v8.0971b DISABLE_OPTIONS_INSTEAD_OF_HIDDEN_IT_FOR_BASELINE_OUTPUT_OPTIONS
	bool			bAddBackBaselineEnabled = trGetN.result.gpconfig.Graph1.Use;
	/// end DISABLE_OPTIONS_INSTEAD_OF_HIDDEN_IT_FOR_BASELINE_OUTPUT_OPTIONS
	TreeNode		trAddBackBaseline = trGetN.result.gpconfig.Graph1.AddBackBaseline;
	ASSERT(trAddBackBaseline);
	
	bool			bAddBackBaselineShow = trAddBackBaseline && trAddBackBaseline.Show;
	bool			bAddBackBaselineChecked = trAddBackBaseline && trAddBackBaseline.nVal;	
	TreeNode 		trOutBaseline = trGetN.result.Output.BaselineData;
	ASSERT(trOutBaseline);
	if(trOutBaseline)
	{
		/// Hong 11/14/08 v8.0971b DISABLE_OPTIONS_INSTEAD_OF_HIDDEN_IT_FOR_BASELINE_OUTPUT_OPTIONS
		//trOutBaseline.Show = trAddBackBaseline && trAddBackBaseline.Show && trAddBackBaseline.nVal;
		trOutBaseline.Show = bHasBaseline && (!bBaselineSubtracted || bAddBackBaselineShow);
		trOutBaseline.Enable = bHasBaseline && (!bBaselineSubtracted || bAddBackBaselineEnabled && bAddBackBaselineShow && bAddBackBaselineChecked);
		/// end DISABLE_OPTIONS_INSTEAD_OF_HIDDEN_IT_FOR_BASELINE_OUTPUT_OPTIONS
	}
	
	/// Hong 11/14/08 v8.0971b DISABLE_OPTIONS_INSTEAD_OF_HIDDEN_IT_FOR_BASELINE_OUTPUT_OPTIONS
	TreeNode 		trOutSubtracted = trGetN.result.Output.SubtractedData;
	ASSERT(trOutSubtracted);
	if(trOutSubtracted)
	{
		trOutSubtracted.Show = bHasBaseline && bAddBackBaselineShow;
		trOutSubtracted.Enable = bHasBaseline && (bAddBackBaselineEnabled && bAddBackBaselineShow && !bAddBackBaselineChecked);
	}
	/// end DISABLE_OPTIONS_INSTEAD_OF_HIDDEN_IT_FOR_BASELINE_OUTPUT_OPTIONS
		
}
///end OUTPUT_BASELINE_AND_SUBTRACTED_DATA_IN_FIT_PEAK_OP

/// Hong 11/18/08 QA80-12603 v8.0974 PA_SUPPORT_LEGEND_UPDATE_OPTION
static void _update_legend_update_option(TreeNode& trGetN)
{
	TreeNode		trGraph1 = trGetN.result.gpconfig.Graph1;
	TreeNode 		trPlotCurveTo = tree_get_node_by_tagname(trGetN, "PlotCurveTo", true);
	BOOL			bEnable;
	if ( trPlotCurveTo && PLOT_TO_SOURCE_GRAPH == trPlotCurveTo.nVal )
		bEnable = true;
	else
		bEnable = false;
	
	if ( trGraph1.UpdateLegend )
		trGraph1.UpdateLegend.Enable = bEnable ? ENABLE : DISABLE;
}
/// end PA_SUPPORT_LEGEND_UPDATE_OPTION

///Kyle 09/26/08 ADD_ON_AFTER_GUI_CHANGE
static bool _check_range(const Range& rData)
{
	return 0 < rData.GetNumData();
}

static bool _check_range(const TreeNode& trRange)
{
	if ( !trRange )
		return false;	
	Range rData;
	okxf_resolve_tree_construct_range(&trRange, &rData);
	if(!rData)
		return false;
	return _check_range(rData);
}

static int _check_weight_data(const TreeNode& trData)
{
	int nErr = CER_NO_ERROR;
	if(trData.Show)
	{
		if(!trData.IsEmpty() && PDS_OPTIONAL != okutil_cvt_str_to_predefined_type(trData.strVal))
		{
			if(!_check_range(trData))
				nErr = XFERR_INVALID_RANGE;
		}
	}
	return nErr;
}

///Kyle 10/27/08 CHECK_WEIGHT_DATA_SHOW_HIDE_ON_INIT
static int _update_data(TreeNode& trGetN, bool bUpdateWeightMethod, bool bUpdateWeightData, bool bUpdatePreview = true)
///End CHECK_WEIGHT_DATA_SHOW_HIDE_ON_INIT
{
	int nErr = CER_NO_ERROR;
	TreeNode trW = tree_get_node_by_tagname(trGetN.trAdv.InputData, "W", true);
	TreeNode trWeight = trGetN.weight;
	TreeNode trData = trGetN.data;
	
	if(bUpdateWeightMethod)
	{
		int nWeightMethod = trWeight.nVal;
		bool bShowData = WEIGHT_NONE != nWeightMethod && WEIGHT_STATISTICAL != nWeightMethod;
		trData.Show = bShowData;//clean data?
		
		if( bShowData )
		{
			trData.RemoveAttribute(STR_ATTRIB_DYNACONTROL_USE_CHECK);
		}
		else
		{
			trData.SetAttribute(STR_ATTRIB_DYNACONTROL_USE_CHECK, 0);
		}

		if(bShowData && PDS_OPTIONAL == okutil_cvt_str_to_predefined_type(trData.strVal))
		{
			trData.Reset(true);
			bUpdateWeightData = true;
		}
		if(trW)		
			trW.SetAttribute(STR_FITTER_WEIGHT_METHOD_ATTRIB, nWeightMethod);
	}	

	nErr = _check_weight_data(trData);
	
	if(CER_NO_ERROR == nErr && bUpdateWeightData)
	{
		if(trW)
			trW.Replace(trData, true, true, true);
	}

	if(CER_NO_ERROR == nErr)
	{
		PeakFitHelper* pFitHelper = _check_get_peak_fit_helper( trGetN );
		if(NULL != pFitHelper)
		{
			bool bEnableFit = pFitHelper->UpdateData(trGetN.trAdv.InputData);
			if(!bEnableFit)
			{
				/// Iris 3/05/2009 FIX_WEIGHT_DATA_STILL_EMPTY_WHEN_INPUT_INCLUDED_YERR
				//nErr = CER_INPUT_RANGE_EMPTY;
				nErr = CER_PA_WEIGHT_DATA_RANGE_EMPTY;
				///end FIX_WEIGHT_DATA_STILL_EMPTY_WHEN_INPUT_INCLUDED_YERR
			}

			DWORD dwUpdateBits = FITPREVIEW_REPLOT;
			///Kyle 10/07/08 USE_REPLOT_AND_NO_NEED_TO_RESET_PREVIEW_LAYER
			//bool 	bShowResidual = trGetN.residual.nVal,
					//bShow2ndDervi = trGetN.derivative.nVal;
			//pFitHelper->UpdatePreview( dwUpdateBits, & bShowResidual, & bShow2ndDervi);
			if(bUpdatePreview)				///Kyle 10/27/08 CHECK_WEIGHT_DATA_SHOW_HIDE_ON_INIT
				pFitHelper->UpdatePreview( dwUpdateBits);
			///End USE_REPLOT_AND_NO_NEED_TO_RESET_PREVIEW_LAYER
		}
	}
	return nErr;
}

static void _update_report_field_result_table(TreeNode& trGetN)
{
	TreeNode trPlotCurveTo = tree_get_node_by_tagname(trGetN, "PlotCurveTo", true);
	TreeNode trPeakReportField = tree_get_node_by_tagname(trGetN, "PeakReportField", true);
	if(trPlotCurveTo && trPeakReportField)
		trPeakReportField.Enable = false != trPlotCurveTo.Show && PLOT_TO_NEW_GRAPH == trPlotCurveTo.nVal;

	TreeNode trPasteResultTable = tree_get_node_by_tagname(trGetN, "PasteResultTable", true);
	if(trPlotCurveTo && trPasteResultTable)
		trPasteResultTable.Enable = false != trPlotCurveTo.Show && PLOT_TO_NONE != trPlotCurveTo.nVal;
}

///------ Folger 02/04/09 QA80-12962 ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM
static	void	_update_plot_curve_option(PeakFitHelper* pFitHelper, TreeNode& trGraph1)
{
	int		nPlotCurve = trGraph1.PLotCurves.nVal;		
	pFitHelper->SetUpdatePreviewInfo(nPlotCurve == PLOT_CURVE_INDIVIDUAL || nPlotCurve == PLOT_CURVE_BOTH,
									nPlotCurve == PLOT_CURVE_CUMULATIVE || nPlotCurve == PLOT_CURVE_BOTH);
									
	if ( !pFitHelper->GetFitWizCoreBase()->IsAutoUpdated() )
	{
		trGraph1.UseSepX.Enable = nPlotCurve != PLOT_CURVE_CUMULATIVE;
		trGraph1.XPtsForEachPeak.Enable = trGraph1.UseSepX.Enable && trGraph1.UseSepX.nVal == 1;
	}
}

static	void	_update_use_smartx(PeakFitHelper* pFitHelper, TreeNode& trGraph1)
{
	if ( !pFitHelper->GetFitWizCoreBase()->IsAutoUpdated() )
		trGraph1.XPtsForEachPeak.Enable = trGraph1.UseSepX.nVal == 1;
	
	pFitHelper->SetUseSmartX(trGraph1.UseSepX.nVal);
}

static	void	_update_smartx_pts_for_each_peak(PeakFitHelper* pFitHelper, TreeNode& trGraph1)
{
	pFitHelper->SetXPtsForEachPeak(trGraph1.XPtsForEachPeak.nVal);
}
///------ End ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM

int on_after_gui_change(TreeNode& trGetN, LPCSTR lpcszNodeName, bool& bBTN2Enable)
{
	PAWizCore *paCore = (PAWizCore*)get_xf_core_handler(trGetN);
	PeakFitHelper* pFitHelper = _check_get_peak_fit_helper(trGetN);
	bool bPeaksChanged = false;
	
	///------ Folger 02/04/09 QA80-12962 ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM
	TreeNode	trGraph1 = trGetN.result.gpconfig.Graph1;
	if ( lstrcmpi(lpcszNodeName, "PLotCurves") == 0 )
	{
		_update_plot_curve_option(pFitHelper, trGraph1);
	}	
	if ( lstrcmpi(lpcszNodeName, "UseSepX") == 0 || lstrcmpi(lpcszNodeName, "XPtsForEachPeak") ==  0 )
	{
		if ( lstrcmpi(lpcszNodeName, "UseSepX") == 0 )
			_update_use_smartx(pFitHelper, trGraph1);
		else
			_update_smartx_pts_for_each_peak(pFitHelper, trGraph1);
		
		pFitHelper->CalculateFitCurvePoints(trGraph1);
		pFitHelper->UpdateFitCurveOptions(trGraph1, true);
	}
	///------ End ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM
	
	// residual & derivative
	if(lstrcmpi(lpcszNodeName, "residual") == 0 || lstrcmpi(lpcszNodeName, "derivative") == 0 )
	{
		DWORD dwUpdateBits = FITPREVIEW_REPLOT;			// or others, wait for the method UpdatePreview ready
		if(NULL != pFitHelper)
		{
			bool 	bShowResidual = trGetN.residual.nVal,
					bShow2ndDervi = trGetN.derivative.nVal;
			pFitHelper->UpdatePreview( dwUpdateBits, & bShowResidual, & bShow2ndDervi);
		}
	}

	// weight
	else if(lstrcmpi(lpcszNodeName, "weight") == 0 || lstrcmpi(lpcszNodeName, "data") == 0)
	{
		bool bUpdateWeightMethod = lstrcmpi(lpcszNodeName, "weight") == 0;
		bool bUpdateWeightData = lstrcmpi(lpcszNodeName, "data") == 0;
		_update_data(trGetN, bUpdateWeightMethod, bUpdateWeightData);
	}

	// result
	else if(lstrcmpi(lpcszNodeName, "XDataType") == 0 || lstrcmpi(lpcszNodeName, "N") == 0 || lstrcmpi(lpcszNodeName, "Range") == 0
		 || lstrcmpi(lpcszNodeName, "Min") == 0 || lstrcmpi(lpcszNodeName, "Max") == 0 || lstrcmpi(lpcszNodeName, "RangeMargin") == 0)
	{
		TreeNode trGraph1 = tree_get_node_by_tagname(trGetN.result, "Graph1", true);
		if(trGraph1)
		{
			if(NULL != pFitHelper)
			{
				///------ Folger 11/25/09 QA81-14734-P1 PA_FITTING_FAILS_TO_UPDATE_FIT_CURVE_POINTS_AFTER_CHANGE_AUTO
				if ( 0 == lstrcmpi(lpcszNodeName, "N") )
				{
					pFitHelper->CalculateFitCurvePoints(trGraph1);
				}
				///------ End PA_FITTING_FAILS_TO_UPDATE_FIT_CURVE_POINTS_AFTER_CHANGE_AUTO
				bool bUpdateXDataMinMaxByAuto = (lstrcmpi(lpcszNodeName, "Min") == 0 || lstrcmpi(lpcszNodeName, "Max") == 0);					
				pFitHelper->UpdateFitCurveOptions(trGraph1, bUpdateXDataMinMaxByAuto);
			}
		}
	}
	
	// fit control
	else if(lstrcmpi(lpcszNodeName, "MaxNum") == 0 || lstrcmpi(lpcszNodeName, "Tolerance") == 0 || lstrcmpi(lpcszNodeName, "Constraints") == 0 || lstrcmpi(lpcszNodeName, "EnableConstraints") == 0)
	{
		if(NULL != pFitHelper)
		{
			if(lstrcmpi(lpcszNodeName, "MaxNum") == 0)
			{
				pFitHelper->SetNumMaxIter(trGetN.FitControl.MaxNum.dVal);
			}
			else if(lstrcmpi(lpcszNodeName, "Tolerance") == 0)
			{
				pFitHelper->SetTolerance(trGetN.FitControl.Tolerance.dVal);
			}
			else if(lstrcmpi(lpcszNodeName, "Constraints") == 0 || lstrcmpi(lpcszNodeName, "EnableConstraints") == 0)
			{
				trGetN.FitControl.Constraints.Enable = trGetN.FitControl.EnableConstraints.nVal;
				pFitHelper->SetLinearConstraints(trGetN.FitControl.Constraints, trGetN.FitControl.EnableConstraints.nVal);
			}
			
			_access_params_dlg(pFitHelper, OMSG_UPDATE, PARAM_DLG_ENABLE_FIT);
			/// Iris 10/30/2008 v8.0963b CORRECT_ENABLE_FIT_BUTTON_CONDITION
			//ENABLE_FIT_BUTTON(!pFitHelper->IsFitConverged());
			ENABLE_FIT_BUTTON(pFitHelper->IsReadyIterations());
			///end CORRECT_ENABLE_FIT_BUTTON_CONDITION
		}
	}
	
	else if(lstrcmpi(lpcszNodeName, "LCL") == 0 || lstrcmpi(lpcszNodeName, "UCL") == 0 || lstrcmpi(lpcszNodeName, "Confidence") == 0 )
	{
		if(NULL != pFitHelper)
			pFitHelper->SetIsGetParamsConf(trGetN.result.wbconfig.Quantities);
	}
	
	else if(lstrcmpi(lpcszNodeName, "PlotCurveTo") == 0 )
	{
		_update_report_field_result_table(trGetN);
		_update_legend_update_option(trGetN); /// Hong 11/18/08 QA80-12603 v8.0974 PA_SUPPORT_LEGEND_UPDATE_OPTION
	}
	
	/// Iris 11/06/2008 v8.0966b TALK_WITH_MAX_NO_NEED_REMOVE_SOURCE_OPTION_IF_NOT_ADD_BACK_BASELINE
	/*
	/// Iris 11/05/2008 v8.0965d NOT_ALLOW_REPORT_TO_SOURCE_GRAPH_IF_SUBTRACTED_BASELINE
	else if(lstrcmpi(lpcszNodeName, "AddBackBaseline") == 0 )
	{
		if(NULL != pFitHelper)
			pFitHelper->UpdatePlotCurveTo(trGetN.result.gpconfig);
	}	
	///end NOT_ALLOW_REPORT_TO_SOURCE_GRAPH_IF_SUBTRACTED_BASELINE
	*/
	///end TALK_WITH_MAX_NO_NEED_REMOVE_SOURCE_OPTION_IF_NOT_ADD_BACK_BASELINE
	
	/// Iris 11/12/2008 v8.0969 OUTPUT_BASELINE_AND_SUBTRACTED_DATA_IN_FIT_PEAK_OP
	/// Hong 11/14/08 v8.0971b DISABLE_OPTIONS_INSTEAD_OF_HIDDEN_IT_FOR_BASELINE_OUTPUT_OPTIONS
	//else if(lstrcmpi(lpcszNodeName, "AddBackBaseline") == 0 )		
	else if ( 0 == lstrcmpi(lpcszNodeName, "AddBackBaseline") || 0 == lstrcmpi(lpcszNodeName, "Graph1") )
	/// end DISABLE_OPTIONS_INSTEAD_OF_HIDDEN_IT_FOR_BASELINE_OUTPUT_OPTIONS
	{
		_update_baseline_subtracted_data_output_gui_display_status(trGetN, paCore->HasBaseline(), paCore->GetSubtractedMode());
	}
	///end OUTPUT_BASELINE_AND_SUBTRACTED_DATA_IN_FIT_PEAK_OP
	
	// Add & Modify/Del peaks button
	else if (lstrcmpi(lpcszNodeName, "trbtns") == 0)
	{	
		GraphLayer gl;
		paCore->GetPreviewLayer(gl);
		if(!gl)
			return false;
		GraphPage gp = gl.GetPage();
			
		int nButtonID = trGetN.trbtns.nVal;	
		switch ( nButtonID )
		{				
		case STR_BTN_ADD:
			int nPeaks = pFitHelper->GetPeaksInfo();
			//page_xf_dynadlg_shown_control(gp, 0, false); //close dlg during getting points from graph
			
			modify_peaks_centers_buttons(paCore, trGetN.otr, trGetN.distr, nButtonID);			
			bPeaksChanged = trGetN.otr.xc.dVals.GetSize() != nPeaks;
			
			//page_xf_dynadlg_shown_control(gp, 1, false); //open again after get points sucessfully			
			break;
			
		case STR_BTN_MODIFY:
			//page_xf_dynadlg_shown_control(gp, 0, false);//close dlg during getting points from graph			
			modify_peaks_centers_buttons(paCore, trGetN.otr, trGetN.distr, nButtonID);			
			return true; // must directly resutn here and wait user event WPARAM_DONE_DLG_COSE to enter envet1 again to continue...
			
		default:
			return false;
		}
	}	

	// user event for modify/del points done
	/*
	int	nUserEvent = -1;
	int nModifiedPeakIndex = -1;
	if( xf_check_is_user_event(trGetN, nUserEvent, &nModifiedPeakIndex) && nUserEvent == WPARAM_DONE_DLG_COSE ) 
	{		
		bPeaksChanged = resume_peaks_centers_plot_after_modify_done(paCore, trGetN.otr) && nModifiedPeakIndex >= 0 ;
	}
	*/
	int		nModifiedPeakIndex = -2;		/// invalid peak index, since WPARAM_NONE_ANCHOR == -1
	bool	bLastPeakDeleted = false;
	if ( xf_check_is_user_event(trGetN, nModifiedPeakIndex) && nModifiedPeakIndex >= WPARAM_NONE_ANCHOR )
	{
		if ( nModifiedPeakIndex == WPARAM_DONE_DLG_COSE )
		{
			return resume_peaks_centers_plot_after_modify_done(paCore, trGetN.otr);
		}
		
		if ( nModifiedPeakIndex == WPARAM_NONE_ANCHOR )
		{
			bLastPeakDeleted = true;
			nModifiedPeakIndex = 0;
		}
		
		bPeaksChanged = resume_peaks_centers_plot_after_modify_done(paCore, trGetN.otr, false, false);
	}
	
	// do set function, param reinit and update preview after add, modify or delete peak
	if( bPeaksChanged )
	{
		int nPeakUpdateType = pFitHelper->OnAfterModifyPeaksCenter(trGetN.otr, nModifiedPeakIndex);
		if ( nPeakUpdateType == PEAK_DELETE )
		{
			if ( trGetN.otr.xc.dVals.GetSize() )		/// needs at least one peak that reattach the plot
				modify_peaks_centers_buttons(paCore, trGetN.otr, trGetN.distr, STR_BTN_MODIFY, true);
			if ( bLastPeakDeleted )
				bPeaksChanged = resume_peaks_centers_plot_after_modify_done(paCore, trGetN.otr, true, false);
		}
		_access_params_dlg(pFitHelper, OMSG_UPDATE, PARAM_DLG_UPDATE_GRID);
	}
	return true;
}

static int _check_source_data(const TreeNode& trGetN)
{
	if(trGetN.tradv)
	{
		TreeNode trInputData = trGetN.tradv.InputData;
		if(trInputData && !trInputData.IsEmpty())
			return CER_NO_ERROR ;
	}
	return XFERR_FAILED_GET_DATAPLOT_FROM_XYRANGE;
}

/// Iris 01/04/2008 ADD_ERR_CHECK_FOR_FIT_HELPER_INIT
static int _check_init_peak_fit_helper_error(TreeNode &trGetN, PeakFitHelper *pPeakHelper, string &strErrMsg, bool &bOKEnable)
{
	if(NULL == pPeakHelper)
	{
		ASSERT(0);
		return CER_NO_ERROR; // if pPeakHelper pointer is NULL, no need check, so no init error
	}
	
	int nErr = pPeakHelper->GetInitRuntimeError();	
	if(CER_NO_ERROR != nErr)
	{
		strErrMsg = nErr;
		bOKEnable = false;
	}
	return nErr;
}
///end ADD_ERR_CHECK_FOR_FIT_HELPER_INIT

static void _check_xf_error(TreeNode & trGetN, string & strErrMsg, bool & bOKEnable)
{
	int 	nErr 	= CER_NO_ERROR;
	string 	strErr 	= "";
	trGetN.SetAttribute(_ERROR_CODE_ATTRIB, nErr);	///Jasmine 04/23/08 WIZZARD_XF_CANNOT_ABORT_UNTIL_nGetNDialog_IS_MINUS_2

	// check number of points
	TreeNode trN;
	TreeNode trGraph1 = tree_get_node_by_tagname(trGetN.result, "Graph1", true);
	if(trGraph1)
		trN = tree_get_node_by_tagname(trGraph1, "N", true);
	if(trN && 1 > trN.nVal)
	{
		nErr = CER_INVALID_POSITIVE_INTEGER;
		//strErr = STR_POINTS_NUM;
	}		

	// check tolerance
	if(CER_NO_ERROR == nErr)
	{
		TreeNode trTolerance = tree_get_node_by_tagname(trGetN.FitControl, "Tolerance", true);
		if(trTolerance && 0 > trTolerance.dVal)
		{
			nErr = CER_INVALID_TOLERANCE;
		}
	}
	
	// check max number of iterations
	if(CER_NO_ERROR == nErr)
	{
		TreeNode trMaxNum = tree_get_node_by_tagname(trGetN.FitControl, "MaxNum", true);
		if(trMaxNum && 1 > trMaxNum.nVal)
		{
			nErr = CER_INVALID_POSITIVE_INTEGER;
			//strErr = STR_MAX_INTR_NUM;
		}			
	}
	
	// check source data
	if(CER_NO_ERROR == nErr)
		nErr = _check_source_data(trGetN);
	
	// check weight data
	if(CER_NO_ERROR == nErr)
		nErr = _check_weight_data(trGetN.data);
	
	// check input data
	if(CER_NO_ERROR == nErr)
	{
		TreeNode trInputData = trGetN.tradv.InputData;
		if(!okutil_is_fitter_data_node_ready(&trInputData))
		{
			/// Iris 3/05/2009 FIX_WEIGHT_DATA_STILL_EMPTY_WHEN_INPUT_INCLUDED_YERR
			//nErr = CER_INPUT_RANGE_EMPTY;
			nErr = CER_PA_WEIGHT_DATA_RANGE_EMPTY;
			///end FIX_WEIGHT_DATA_STILL_EMPTY_WHEN_INPUT_INCLUDED_YERR
		}
	}
	// check output book
	if( CER_NO_ERROR == nErr)
	{
		nErr = check_report_book_curve_book( trGetN, strErr );
	}
	// check confidence
	if(CER_NO_ERROR == nErr)
	{
		TreeNode trQuan = trGetN.result.wbconfig.Quantities;
		TreeNode trConfidence =  trQuan.Parameters.Confidence;
		if(0 >= trConfidence.dVal || 100 <= trConfidence.dVal)
			nErr = CER_INVALID_CONF_LEV; 
	}
	// check xdatatype
	///Sophy 11/21/2008 v8.976 QA80-12591-P3 ADD_ERRMSG_WHEN_FITCURVE_XDATATYPE_IS_LOG_WITH_NEGATIVE_INPUT
	if( nErr == CER_NO_ERROR )
	{
		TreeNode trInputData = trGetN.tradv.InputData;
		nErr = check_input_logx_datatype(trInputData, trGraph1.XDataType);
	}
	
	if( CER_NO_ERROR == nErr )
	{
		nErr = check_logx_customize_x_range(trGraph1.XDataType);
	}
	///end ADD_ERRMSG_WHEN_FITCURVE_XDATATYPE_IS_LOG_WITH_NEGATIVE_INPUT
	///Sophy 11/27/2008 v8.980d QA80-12680 SHOW_ERR_MSG_WHEN_PEAK_FIT_FUNC_IS_NOT_IN_PFW
	// check peak fit function
	if( CER_NO_ERROR == nErr )
	{
		PeakFitHelper* pFitHelper = _check_get_peak_fit_helper(trGetN);
		if( pFitHelper )
		{
			nErr = pFitHelper->CheckErrorOnFitFunctions(strErr); 
		}
	}
	///end SHOW_ERR_MSG_WHEN_PEAK_FIT_FUNC_IS_NOT_IN_PFW
	// set error message
	if(CER_NO_ERROR != nErr)
	{
		strErrMsg = nErr;
		if( CER_SAME_REPORT_DATA_BOOKNAME == nErr ||  CER_INVALID_POSITIVE_INTEGER == nErr)
			strErrMsg += ":" + strErr;
		///Sophy 11/27/2008 v8.980d QA80-12680 SHOW_ERR_MSG_WHEN_PEAK_FIT_FUNC_IS_NOT_IN_PFW
		else if(  XFERR_PEAK_FUNC == nErr)
		{
			//Sophy, currently xf_load_err_msg don't support error-string with two string params.
			string strArg1, strArg2;
			strArg1 = strErr.GetToken(0, '|');
			strArg2 = strErr.GetToken(1, '|');
			ocu_load_msg_str(nErr, &strErrMsg, strArg1, NULL, strArg2);
		}
		///end SHOW_ERR_MSG_WHEN_PEAK_FIT_FUNC_IS_NOT_IN_PFW
		bOKEnable = false;
	}
}
///End ADD_ON_AFTER_GUI_CHANGE

///Kyle 01/16/2009 XF_CHECK_CHECK_SET_LAST_OUTCOME_MESSAGE
void _check_last_iterate_outcome(TreeNode &trGetN, PeakFitHelper *pPeakHelper, string &strErrMsg, bool &bOKEnable)
{
	string strOutCome;
	int nOutCome = pPeakHelper->GetLastIterateOutCome(strOutCome);
	if(nOutCome == FITITER_FAILED_GENERAL_LINEAR_CONSTRAINTS)		// for now just show this one
	{
		strErrMsg = strOutCome;
		bOKEnable = false;
	}
}
///End XF_CHECK_CHECK_SET_LAST_OUTCOME_MESSAGE

///Sophy 11/26/2008 v8.980 PA_CHANGE_PARAMS_SHOULD_DISABLE_OUTPUT_DESTINATION_AS_OTHER_FITTING_TOOLS
typedef OutputGUIManagerBase* (*GET_OUTPUT_MANAGER_POINTER)(TreeNode& trGetN);
static void _disable_output_destination_on_change_param(TreeNode& trGetN)
{
	GET_OUTPUT_MANAGER_POINTER pfn = Project.FindFunction("get_output_GUI_manager_pointer", "OriginLab\\wksOperation.c", true);
	if( pfn )
	{
		TreeNode trOutput = trGetN.result.Output;
		OutputGUIManagerBase* pOutputManager = pfn(trGetN);
		if( pOutputManager )
		{
			pOutputManager->DisableOutputDestination(trOutput);
			pOutputManager->SetIsChangeParam(true);
		}
	}
}
///PA_CHANGE_PARAMS_SHOULD_DISABLE_OUTPUT_DESTINATION_AS_OTHER_FITTING_TOOLS

///////////////////////////////////////////////////////////////////////////
/// End GUI Event 
///////////////////////////////////////////////////////////////////////////



///////////////////////////////////////////////////////////////////////////
/// Preview
///////////////////////////////////////////////////////////////////////////

//static	bool	_update_peak_fit_preview( TreeNode& trGetN, DWORD dwUpdateBits = FITPREVIEW_INIT )
//{
	//PAWizCore		*paCore = (PAWizCore*)get_xf_core_handler(trGetN);
	//PeakFitHelper 	*pFitHelper = _check_get_peak_fit_helper(trGetN);
	//
	//Tree trCurveOption;
	//trCurveOption = trGetN.result.gpconfig.Graph1;
	//
	//if( FITPREVIEW_INIT == dwUpdateBits )
	//{
		//GraphLayer		gl;
		//paCore->GetPreviewLayer(gl);
		//pFitHelper->InitPreview(trCurveOption, gl);
	//}
	//
	//pFitHelper->UpdatePreview( dwUpdateBits );
	//
	//return false;
//}

///////////////////////////////////////////////////////////////////////////
/// End Preview
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
/// Peak Fitting
///////////////////////////////////////////////////////////////////////////

//static	bool	_peak_fitting(TreeNode& trGetN)
//{
	//return _check_get_peak_fit_helper(trGetN)->Fit();
//}

///////////////////////////////////////////////////////////////////////////
/// End Peak Fitting
///////////////////////////////////////////////////////////////////////////

//------ Folger 12/03/08 v8.0982 CLEAR_BASELINE_PLOT_CREATED_BY_PREVIOUS_STEPS_BEFORE_ENTER_PA_FIT
static	void	_check_show_baseline_plot_created_by_previous_step(PAWizCore* paCore, bool bShow = false)
{
	if ( paCore == NULL )
	{
		ASSERT(false);
		return;
	}
	
	DataPlot dpBase;
	paCore->CheckCreateBaselinePlot(false, &dpBase);
	
	if ( dpBase )
		dpBase.Show = bShow;
}
//------ End CLEAR_BASELINE_PLOT_CREATED_BY_PREVIOUS_STEPS_BEFORE_ENTER_PA_FIT

///------ Folger 12/24/08 v8.0990c SUPPORT_SPECIFIC_NODE_TO_SKIP_EVENT1_IN_PA_FIT
static	bool	_is_ok_to_skip_event1(TreeNode& trGetN, int nRow)
{
	vector<int>		vnBranchIDs = {IDST_FIT_PARAMS_OPTIONS, IDST_FIT_STATS_OPTIONS, IDE_PARAMS_SUMMARY, IDE_PFM_REPORT_BRANCH};
	///------ Folger 10/24/09 LCL_UCL_FAILS_TO_BE_CALCULATE_IN_PA
	//vector<int>		vnNodeDataIDsToSkipChecking = {IDE_FIT_CONF_PERCENT};
	vector<int>		vnNodeDataIDsToSkipChecking = { IDE_PARAM_LCL
		, IDE_PARAM_UCL
		, IDE_SUMMARY_PARAM_LCL
		, IDE_SUMMARY_PARAM_UCL
		, IDE_FIT_CONF_PERCENT
	};	
	///------ End LCL_UCL_FAILS_TO_BE_CALCULATE_IN_PA
	
	TreeNode		trNode = tree_get_node(trGetN, nRow);
	if ( !trNode )
		return false;
	
	int		nDataID = 0;
	trNode.GetAttribute(STR_BACKUP_ID_ATTRIB, nDataID);
	vector<uint>	vnIndices;
	if ( vnNodeDataIDsToSkipChecking.Find(vnIndices, nDataID) > 0 )
		return false;
	
	TreeNode	trParent = trNode.Parent();
	if ( !trParent )
		return false;
	
	trParent.GetAttribute(STR_BACKUP_ID_ATTRIB, nDataID);
	return vnBranchIDs.Find(vnIndices, nDataID) > 0 ? true : false;
}

class PAFitEvent1UpdateHelper
{
public:
	PAFitEvent1UpdateHelper(PeakFitHelper* pFitHelper, PAWizCore* paCore, string* pstrErrMsg, bool* pbOKEnable, bool* pbBTN1Enable, bool* pbBTN2Enable)
	{
		m_pFitHelper = pFitHelper;
		m_paCore = paCore;
		m_pstrErrMsg = pstrErrMsg;
		m_pbOKEnable = pbOKEnable;
		m_pbBTN1Enable = pbBTN1Enable;
		m_pbBTN2Enable = pbBTN2Enable;
		
		m_pstrErrMsg->Empty();
	}
	~PAFitEvent1UpdateHelper()
	{
		*m_pbBTN1Enable = !m_paCore->IsFinishButtonClicked();
		
		DWORD dwEnableOK = *m_pbOKEnable ? PARAM_DLG_ENABLE_OK : PARAM_DLG_DISABLE_OK;
		_access_params_dlg(m_pFitHelper, OMSG_UPDATE, dwEnableOK);
		
		*m_pbBTN2Enable = *m_pbOKEnable && m_pFitHelper->IsReadyIterations();
		
		DWORD dwCtrl = *m_pbBTN2Enable? PARAM_DLG_ENABLE_FIT : PARAM_DLG_DISABLE_FIT;
		_access_params_dlg(m_pFitHelper, OMSG_UPDATE, dwCtrl);//update parameter dlg's button status
		
		XFEventStatus*	pp = m_pFitHelper->GetXFEventStatus();
		pp->m_strXFErrMsg = *m_pstrErrMsg;
		pp->m_bOKEnable = *m_pbOKEnable;
	}

private:
	PeakFitHelper* 	m_pFitHelper;
	PAWizCore*		m_paCore;
	string*			m_pstrErrMsg;
	bool*			m_pbOKEnable;
	bool*			m_pbBTN1Enable;
	bool*			m_pbBTN2Enable;
};
///------ End SUPPORT_SPECIFIC_NODE_TO_SKIP_EVENT1_IN_PA_FIT


void pa_fit(const int& trbtns, const int& weight, const Range& data, const int& residual, const int& derivative, const TreeNode& FitControl, const TreeNode& result, const int& nofit, const TreeNode& PFMParams, TreeNode& trAdv, const int& nXFCorePointer, TreeNode& otr, TreeNode& distr, TreeNode& trUID, const TreeNode& FitWorkArea, const int& fixbase)
{
	
	Tree trGetN;
	TreeNode tr1 = trGetN.AddNode("PFMParams");
	tr1.Replace(PFMParams.Clone(), TRUE, TRUE);
	
	TreeNode tr2 = trGetN.AddNode("trAdv");
	tr2.Replace(trAdv.Clone(), TRUE, TRUE);
	
	TreeNode tr3 = trGetN.AddNode("result");
	tr3.Replace(result.Clone(), TRUE, TRUE);
	
	///Jasmine 03/11/08 SHOW_FITCONTROL_BRANCH_IN_XF_NOT_IN_PARAMDLG_BY_CP_REQUEST
	TreeNode tr4 = trGetN.AddNode("FitControl");
	tr4.Replace(FitControl.Clone(), TRUE, TRUE);
	///End SHOW_FITCONTROL_BRANCH_IN_XF_NOT_IN_PARAMDLG_BY_CP_REQUEST
	
	trGetN.AddNumericNode(nofit, "nofit");///---Sim 02-25-2008 NO_FIT_AGAIN_CHECK_BOX
	
	///---Sim 01-07-2008 QA80-12833 FIX_APPLY_XF_WIZ_XF_TWICE
	//PeakFitHelper 	*pFitHelper = _check_get_peak_fit_helper(getnhandler);
	//PAWizCore* paCore = (PAWizCore*)get_xf_core_handler(getnhandler);
	PAWizCore* paCore = (PAWizCore*)get_xf_core_handler(NODE_NAME_XF_WIZ_CORE_POINTER);
	if(!paCore)
		XF_THROW(XF_ERR_INVALID_PA_INSTANCE);	
		
	TreeNode getnhandler;
	bool bRet = paCore->GetGetN(getnhandler);
	ASSERT(bRet);
	
	PeakFitHelper 	*pFitHelper = _check_get_peak_fit_helper(getnhandler);
	///---END QA80-12833 FIX_APPLY_XF_WIZ_XF_TWICE
	
	bool bFinishClicked = paCore->IsFinishButtonClicked();		//Kyle 09/26/08
	
	if( NULL != pFitHelper && NULL != paCore /*&& !bFinishClicked*/ )	// Kyle, bFinishClicked always false and was set true in the function for only once
	{
		/// Iris 11/04/2008 v8.0965b NEW_PA_SUPPORT_CREATE_REPORT_GRAPH_ON_SOURCE
		DataPlot dp;  
		if( paCore->GetSourceDataPlot(dp) )
		{
			pFitHelper->SetSourcePlotUID(dp.GetUID(true));
		}
		///end NEW_PA_SUPPORT_CREATE_REPORT_GRAPH_ON_SOURCE
		
		//------ Folger 12/11/08 QA80-12765 v8.0985 CHANGE_PARAMETER_FAILS_TO_REMEMBER_SETTINGS_FROM_LAST_CLOSE_IN_PA_FITTING
		pFitHelper->UpdateFitWorkArea(getnhandler.FitWorkArea);
		//------
		
		///Sophy 10/20/2008 FIX_RUNTIME_WHEN_CLICK_REPORT_PA_WITH_BASELINE_SUBTRACTED
		//int nErr = pFitHelper->ExecuteOperation(paCore->GetOriginalGraph(), trGetN);
		GraphLayer gl;
		paCore->GetPreviewLayer(gl);
		int nErr = pFitHelper->ExecuteOperation( gl, trGetN, /*oy1, oy2, oy3*/trUID);
		
		//getnhandler.oy1.SetAttribute(TREE_UID, (int)oy1.GetUID());
		//getnhandler.oy2.SetAttribute(TREE_UID, (int)oy2.GetUID());
		//getnhandler.oy3.SetAttribute(TREE_UID, (int)oy3.GetUID());
		
		//------ Folger 11/15/08 QA80-12488 v8.0972 NEED_TO_BRING_BACK_REPORT_GRAPHS_UID_FOR_AUTO_UPDATE
		getnhandler.trUID.range_uid.nVals = trUID.range_uid.nVals;
		getnhandler.trUID.graph_uid.nVals = trUID.graph_uid.nVals;
		///------ Folger 09/05/09 FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
		getnhandler.trUID.result_table_uid.nVal = trUID.result_table_uid.nVal;
		///------ End FAILS_TO_PASTE_RESULTS_TABLE_TO_REPORT_GRAPH_DURING_CHANGE_PARAM_IN_PA
		//------
		
		///end FIX_RUNTIME_WHEN_CLICK_REPORT_PA_WITH_BASELINE_SUBTRACTED
		if( CER_NO_ERROR != nErr )
			XF_THROW(nErr);
		
		/// Iris 11/15/2008 v8.0972 FIX_ALWAYS_NEW_REPORT_GRAPH_WHEN_RECALCULATE
		TreeNode trGetNOutLayerUID = trGetN.trAdv.OutputGraph.LayerUID;
		if( trGetNOutLayerUID && !trGetNOutLayerUID.IsEmpty() )
		{
			getnhandler.trAdv.OutputGraph.LayerUID.nVal = trGetNOutLayerUID.nVal;
		}
		///end FIX_ALWAYS_NEW_REPORT_GRAPH_WHEN_RECALCULATE
		
		/// Iris 12/01/2008 v8.0981 FIX_CHANGE_PARAM_ALWAYS_REPLOT_ON_SOURCE_GRAPH
		TreeNode trSourceGraphIDMap = trGetN.trAdv.SourceGraphIDMap;
		TreeNode trSourceGraphUID = trGetN.trAdv.SourceGraphUID;
		if(trSourceGraphIDMap && !trSourceGraphIDMap.IsEmpty() && trSourceGraphUID && !trSourceGraphUID.IsEmpty())
		{
			getnhandler.trAdv.SourceGraphIDMap.nVals = trSourceGraphIDMap.nVals;
			getnhandler.trAdv.SourceGraphUID.nVals = trSourceGraphUID.nVals;
		}
		///end FIX_CHANGE_PARAM_ALWAYS_REPLOT_ON_SOURCE_GRAPH
		
		///Kyle 09/26/08 ADD_ON_AFTER_GUI_CHANGE
		bool bClicked = true;
		paCore->SetFinishButtonClicked( bClicked );
		///End ADD_ON_AFTER_GUI_CHANGE
	}
	
}

//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int pa_fit_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return pa_fit_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	PeakFitHelper 	*pFitHelper = _check_get_peak_fit_helper(trGetN);
	PAWizCore		*paCore = (PAWizCore*)get_xf_core_handler(trGetN);
	
	///------ Folger 12/24/08 v8.0990c SUPPORT_SPECIFIC_NODE_TO_SKIP_EVENT1_IN_PA_FIT
	PAFitEvent1UpdateHelper		updateHelper(pFitHelper, paCore, &strErrMsg, &bOKEnable, &bBTN1Enable, &bBTN2Enable);
	
	if ( _is_ok_to_skip_event1(trGetN, nRow) )
	{
		XFEventStatus*	pp = pFitHelper->GetXFEventStatus();
		strErrMsg = pp->m_strXFErrMsg;
		bOKEnable = pp->m_bOKEnable;
		return true;
	}
	///------ End SUPPORT_SPECIFIC_NODE_TO_SKIP_EVENT1_IN_PA_FIT
	
	switch ( nEventID )
	{
	case GETNE_ON_INIT:
		xf_turnon_user_event_receiver(trGetN);
		
		///------ Folger 03/06/09 WEIGHT_DATA_NOT_UPDATED_WHEN_CHANGE_PARAM_IN_PA_FITTING
		//_update_data( trGetN, true, false, false);			///Kyle 10/27/08 CHECK_WEIGHT_DATA_SHOW_HIDE_ON_INIT
		_update_data( trGetN, true, true, false);
		///------ End WEIGHT_DATA_NOT_UPDATED_WHEN_CHANGE_PARAM_IN_PA_FITTING
		
		//_update_peak_fit_preview( trGetN, FITPREVIEW_INIT );
		if( pFitHelper )
		{
			bool 	bShowResidual = trGetN.residual.nVal,
					bShow2ndDervi = trGetN.derivative.nVal;
			pFitHelper->UpdatePreview( FITPREVIEW_INIT, & bShowResidual, & bShow2ndDervi);
		}
		
		_addbackbaseline_checkbox_set_show_event(trGetN);
		
		trGetN.FitControl.Constraints.Enable = trGetN.FitControl.EnableConstraints.nVal;
		
		_update_legend_update_option(trGetN); /// Hong 11/18/08 QA80-12603 v8.0974 PA_SUPPORT_LEGEND_UPDATE_OPTION
		
		//------ Folger 12/03/08 v8.0982 CLEAR_BASELINE_PLOT_CREATED_BY_PREVIOUS_STEPS_BEFORE_ENTER_PA_FIT
		_check_show_baseline_plot_created_by_previous_step(paCore, false);
		//------
		
		break;
		
	case GETNE_BUTTON_FIT_CONTROL:
		if( pFitHelper )
		{
			DWORD 			dwCtrl = PARAM_DLG_MULTI_FUNC;
			_access_params_dlg(pFitHelper, OMSG_OPEN, dwCtrl);
		}
		break;
		
	case GETNE_BUTTON_FIT:
		if( pFitHelper )
		{			
			bool			bFitButtonEnable;
			if( pFitHelper->OnClickFit(&bFitButtonEnable) )
				ENABLE_FIT_BUTTON(bFitButtonEnable);			
			
			DWORD dwCtrl = PARAM_DLG_UPDATE_GRID;
			dwCtrl |= bFitButtonEnable? PARAM_DLG_ENABLE_FIT : PARAM_DLG_DISABLE_FIT;
			_access_params_dlg(pFitHelper, OMSG_UPDATE, dwCtrl);
		}
		break;
		
	case GETNE_ON_UNDO:
		if( pFitHelper )
		{
			///Kyle 09/10/08 DELETE_THE_PARAMS_DLG_BEFORE_DESTROY_PEAK_FIT_HELPER
			_access_params_dlg(pFitHelper, OMSG_CLOSE);
			///End DELETE_THE_PARAMS_DLG_BEFORE_DESTROY_PEAK_FIT_HELPER
			//_destroy_peak_fit_helper(trGetN);
			//_update_peak_fit_preview( trGetN, FITPREVIEW_REMOVE_FITS );
			bool bShowResidual = false, bShow2ndDervi = false;
			pFitHelper->UpdatePreview( FITPREVIEW_REMOVE_FITS, & bShowResidual, &bShow2ndDervi );
			//------ Folger 12/03/08 v8.0982 CLEAR_BASELINE_PLOT_CREATED_BY_PREVIOUS_STEPS_BEFORE_ENTER_PA_FIT
			_check_show_baseline_plot_created_by_previous_step(paCore, true);
			//------
		}
		break;		
	
	case GETNE_ON_EXTERNAL_MSG:
		int nMsg, nUserEventInfo;
		if( !xf_check_is_user_event( trGetN, nMsg, &nUserEventInfo ) )
			break;
		
		bool bNeedUpdateSettings = false;
		switch(nMsg)
		{
		case EXTERNAL_MSG_CHECK_AUTOINIT:
			/// check auto init should not actually init params
			//if(pFitHelper)
				//pFitHelper->InitParams();
			ENABLE_FIT_BUTTON(true);
			bNeedUpdateSettings = true;	
			break;
			
		case EXTERNAL_MSG_PARA_CHANGE:
			// edit param gird control will real time update param manager pointer, so no need do any here again
			ENABLE_FIT_BUTTON(true);
			///Kyle 10/07/08 USE_REPLOT_AND_NO_NEED_TO_RESET_PREVIEW_LAYER
			///Iris 10/22/2008 UPDATE_PREVIEW_FOLLOW_RETURN_VAL_OF_PARAMMANAGER_ONEDIT 
			//if(pFitHelper)
			if(pFitHelper && nUserEventInfo) // nUserEventInfo == 1: update preivew, 0: no need update preview
			///end UPDATE_PREVIEW_FOLLOW_RETURN_VAL_OF_PARAMMANAGER_ONEDIT
			{
				pFitHelper->UpdatePreview( FITPREVIEW_REPLOT);
			}
			///End USE_REPLOT_AND_NO_NEED_TO_RESET_PREVIEW_LAYER
			bNeedUpdateSettings = true;
			break;
			
		case EXTERNAL_MSG_AFT_ITR:
			if( !trGetN.nofit.Enable )
			{
				trGetN.nofit.Enable = true;
				GETN_CHANGE_GRID
			}
			if(pFitHelper)
			{
				///Kyle 10/07/08 USE_REPLOT_AND_NO_NEED_TO_RESET_PREVIEW_LAYER
				//bool 	bShowResidual = trGetN.residual.nVal,
						//bShow2ndDervi = trGetN.derivative.nVal;
	//
				//pFitHelper->UpdatePreview( FITPREVIEW_UPDATE, & bShowResidual, & bShow2ndDervi );
				pFitHelper->UpdatePreview( FITPREVIEW_REPLOT);
				///End USE_REPLOT_AND_NO_NEED_TO_RESET_PREVIEW_LAYER
				/// Iris 10/30/2008 v8.0963b CORRECT_ENABLE_FIT_BUTTON_CONDITION
				//ENABLE_FIT_BUTTON(!pFitHelper->IsFitConverged());
				ENABLE_FIT_BUTTON(pFitHelper->IsReadyIterations());
				///end CORRECT_ENABLE_FIT_BUTTON_CONDITION
			}
			bNeedUpdateSettings = true;		///------ Folger 06/22/09 QA80-13814 PA_FITTING_VALUES_FAILS_TO_BE_SAVED_IN_THEME
			break;
			
		case EXTERNAL_MSG_FUNC_CHANGE:
			ENABLE_FIT_BUTTON(true);
			//_update_peak_fit_preview( trGetN, FITPREVIEW_REPLOT );
			if(pFitHelper)
			{
				///Kyle 10/07/08 USE_REPLOT_AND_NO_NEED_TO_RESET_PREVIEW_LAYER
				//bool 	bShowResidual = trGetN.residual.nVal,
						//bShow2ndDervi = trGetN.derivative.nVal;
				//pFitHelper->UpdatePreview( FITPREVIEW_REPLOT, & bShowResidual, & bShow2ndDervi );
				pFitHelper->UpdatePreview( FITPREVIEW_REPLOT );
				///End USE_REPLOT_AND_NO_NEED_TO_RESET_PREVIEW_LAYER
			}
			bNeedUpdateSettings = true;
			break;
			
		/// Iris 10/24/2008 v8.0959 UPDATE_PARAMS_SETTINGS_ON_CHANGE
		////------ Folger 10/17/08 NEED_TO_UPDATE_PARAMS_TREE_INTO_PA_FIT_GETNTREE_WHEN_PEAK_FIT_DIALOG_CLOSE
		//case EXTERNAL_MSG_DIALOG_CLOSE:
			//bNeedUpdateSettings = true;
			//break;
		////------ End NEED_TO_UPDATE_PARAMS_TREE_INTO_PA_FIT_GETNTREE_WHEN_PEAK_FIT_DIALOG_CLOSE
		///end UPDATE_PARAMS_SETTINGS_ON_CHANGE
		
		///Jasmine 04/15/10 QA81-15304 ANNOUNCE_FITTING_FUNC_CHANGE
		case EXTERNAL_MSG_FO_CHANGE_FUNC:
			NLParametersManager *pNLParamsMngr = pFitHelper-> GetFitSession()->GetNLParamsMngr();
			if(pNLParamsMngr)
				pNLParamsMngr->SetFDFTree(NULL);
			bNeedUpdateSettings = true;
			break;
		///End ANNOUNCE_FITTING_FUNC_CHANGE
		
		default:
			break;
		}
		if(bNeedUpdateSettings)
		{ ///---Sim 10-31-2008 INDICATE_THEME_ON_PA_FIT_PARAM_CHANGE
			pFitHelper->UpdateSettingOnChange(trGetN);
		///---Sim 10-31-2008 INDICATE_THEME_ON_PA_FIT_PARAM_CHANGE
			NOTIFY_DLG_NEED_INDICATE_THEME
		}
		///---END INDICATE_THEME_ON_PA_FIT_PARAM_CHANGE
		
		break;
		
	default:
		break;
	}
	
	
	///Kyle 09/26/08 ADD_ON_AFTER_GUI_CHANGE
	on_after_gui_change( trGetN, lpcszNodeName, bBTN2Enable);
	
	if(nEventID == GETNE_ON_INIT || nEventID == GETNE_ON_THEME)
	{
		_update_report_field_result_table(trGetN);
	}
	
	if( CER_NO_ERROR == _check_init_peak_fit_helper_error(trGetN, pFitHelper, strErrMsg, bOKEnable) ) /// Iris 01/04/2008 ADD_ERR_CHECK_FOR_FIT_HELPER_INIT
		_check_xf_error(trGetN, strErrMsg, bOKEnable);	
	
	///Kyle 01/16/2009 XF_CHECK_CHECK_SET_LAST_OUTCOME_MESSAGE
	if(bOKEnable)
		_check_last_iterate_outcome(trGetN, pFitHelper, strErrMsg, bOKEnable);
	///End XF_CHECK_CHECK_SET_LAST_OUTCOME_MESSAGE
	
	///------ Folger 12/24/08 v8.0990c SUPPORT_SPECIFIC_NODE_TO_SKIP_EVENT1_IN_PA_FIT
	/*
	bBTN1Enable = !paCore->IsFinishButtonClicked();
	///Sophy 11/2/2008 v8.981b UPDATE_OK_BUTTON_AND_RELATIVE_FIT_BUTTONS_ON_ERROR
	DWORD dwEnableOK = bOKEnable ? PARAM_DLG_ENABLE_OK : PARAM_DLG_DISABLE_OK;
	_access_params_dlg(pFitHelper, OMSG_UPDATE, dwEnableOK);
	///end UPDATE_OK_BUTTON_AND_RELATIVE_FIT_BUTTONS_ON_ERROR
	
	/// Iris 10/30/2008 v8.0963b CORRECT_ENABLE_FIT_BUTTON_CONDITION
	//bBTN2Enable = bOKEnable && !pFitHelper->IsFitConverged();
	bBTN2Enable = bOKEnable && pFitHelper->IsReadyIterations();
	///end CORRECT_ENABLE_FIT_BUTTON_CONDITION
	DWORD dwCtrl = bBTN2Enable? PARAM_DLG_ENABLE_FIT : PARAM_DLG_DISABLE_FIT;
	_access_params_dlg(pFitHelper, OMSG_UPDATE, dwCtrl);//update parameter dlg's button status
	///End ADD_ON_AFTER_GUI_CHANGE
	*/
	///------ End SUPPORT_SPECIFIC_NODE_TO_SKIP_EVENT1_IN_PA_FIT
	
	return true;

}

int pa_fit_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	/// Iris 9/17/2008 NEW_PA
	///Sophy 9/25/2008 NEw_PA move static tree to xf
	//construct_GUI_from_operation(tr, lpcszVarName); 
	static Tree s_trOp;
	construct_GUI_from_operation( s_trOp, tr, lpcszVarName); 
	///end Sophy NEW_PA
	///end NEW_PA    
	return 0;
}
//nGetNDialog = 0,1,2, corresponding to the XF GetN dropdown, 0 = dialog is not used
//you can change nRet to be one of XFEVT_PROCEED (defualt), XFEVT_ABORT, XFEVT_PROCEED_NO_DLG or XFEVT_PROCEED_WITH_DLG(when nGetNDialog = 0)
//nGetNDialog = -1 when Ok on GetN dialog to allow handler to preocess <auto> etc variables
//dwCntrl is combination of bits
//LTXF_FROM_GUI_MENU, LTXF_FROM_GUI_PROMPT, LTXF_FROM_AUTO_UPDATE, LTXF_FROM_FUNCTION, LTXF_THEME_USED, LTXF_CHANGE_PARAM
void pa_fit_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	///Kyle 09/26/08 HANDLE_ERROR_ON_BEFORE_EXECUTE
	int 	nErr = CER_NO_ERROR;
	string 	strErrMsg;
	///End HANDLE_ERROR_ON_BEFORE_EXECUTE
	
	if ( is_xf_startup(nGetNDialog, dwCntrl) )
	{
		trGetN.SetAttribute(STR_HELPID_ATTRIB, IDD_PA_RE_FITP);
		//_create_peak_fit_helper(trGetN);
		
		///Sophy 9/23/2008 NEW_PA
		/*
		/// set functions
		_set_peak_fit_functions(trGetN);
		
		/// set data
		_set_peak_fit_data(trGetN);
		
		/// set parameters
		_init_peak_fit_params(trGetN);
		*/
		PeakFitHelper	*pFitHelper = _check_get_peak_fit_helper(trGetN);
		if( NULL == pFitHelper)
			return; // should replae with xf throw later
		
		// construct trPFMParams for apply theme
		pFitHelper->ConstructPFMParamsTree(trGetN.PFMParams);	
		
		///------ Folger 02/04/09 QA80-12962 ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM
		TreeNode	trGraph1 = trGetN.result.gpconfig.Graph1;
		_update_plot_curve_option(pFitHelper, trGraph1);
		_update_use_smartx(pFitHelper, trGraph1);
		_update_smartx_pts_for_each_peak(pFitHelper, trGraph1);
		if ( pFitHelper->GetFitWizCoreBase()->IsAutoUpdated() )
		{
			trGraph1.UseSepX.Enable = trGraph1.XPtsForEachPeak.Enable = DISABLE;
		}
		///------ End ADD_OPTION_IN_PA_FIT_TO_SWTICH_BACK_TO_OLD_FIT_CURVE_DATA_GENERATION_MECHANISM
		
		// will set function, set data, init and set parameter
		if( !pFitHelper->Init(trGetN) )
		{
			/// Iris 01/04/2008 ADD_ERR_CHECK_FOR_FIT_HELPER_INIT
			XF_THROW(pFitHelper->GetInitRuntimeError());
			///end ADD_ERR_CHECK_FOR_FIT_HELPER_INIT
		}
		
		///end Sophy NEW_PA
		///Sophy 11/26/2008 v8.980 PA_CHANGE_PARAMS_SHOULD_DISABLE_OUTPUT_DESTINATION_AS_OTHER_FITTING_TOOLS called after Init( prepare operation pointer and outputguimanager pointer )
		if( nGetNDialog > 0 && (dwCntrl & LTXF_CHANGE_PARAM) )
			_disable_output_destination_on_change_param(trGetN);
		///end PA_CHANGE_PARAMS_SHOULD_DISABLE_OUTPUT_DESTINATION_AS_OTHER_FITTING_TOOLS
	
		///Sandy 2008-4-18 add modify/del buttons
		trGetN.trbtns.SetAttribute(STR_ID_ATTRIB, ONODETYPE_PUSHBUTTON_GROUP);
		trGetN.trbtns.SetAttribute(STR_COMBO_ATTRIB, _STR_BUTTON_LIST);			
		trGetN.trbtns.SetAttribute(STR_ATTRIB_DISPFMT, DISPLAY_EDITOR_HORZ);
		//end
		
		///Kyle 09/26/08 HANDLE_ERROR_ON_BEFORE_EXECUTE
		trGetN.SetAttribute(_ERROR_CODE_ATTRIB, nErr);	///Jasmine 04/23/08 WIZZARD_XF_CANNOT_ABORT_UNTIL_nGetNDialog_IS_MINUS_2
		trGetN.SetAttribute(_ERROR_CODE_ATTRIB2, strErrMsg);
		///End HANDLE_ERROR_ON_BEFORE_EXECUTE
		
		/// Hong 11/14/08 v8.0971b DISABLE_OPTIONS_INSTEAD_OF_HIDDEN_IT_FOR_BASELINE_OUTPUT_OPTIONS
		_addbackbaseline_checkbox_set_show_event(trGetN);
		/// end DISABLE_OPTIONS_INSTEAD_OF_HIDDEN_IT_FOR_BASELINE_OUTPUT_OPTIONS
		/// Hong 11/18/08 QA80-12603 v8.0974 PA_SUPPORT_LEGEND_UPDATE_OPTION
		_update_legend_update_option(trGetN);
		/// end PA_SUPPORT_LEGEND_UPDATE_OPTION
		///Sophy 11/24/2008 v8.978c CHECK_SET_XDATATYPE_VALUE_ON_APPLY_THEME
		PAWizCore *paCore = (PAWizCore*)get_xf_core_handler(trGetN);
		DataPlot dp;
		if( paCore )
			///Sophy 7/22/2009 v8.1073 NANOSIZER_NEED_TO_GET_ORIGINAL_INPUTDATA
			//change_indep_data_type_combo_on_source_page_type(trGetN, paCore->GetSourceDataPlot(dp));
			change_indep_data_type_combo_on_source_page_type(trGetN, trGetN.trAdv.InputData, paCore->GetSourceDataPlot(dp));
			///end NANOSIZER_NEED_TO_GET_ORIGINAL_INPUTDATA
		check_set_xdatatype_value(trGetN);
		///end CHECK_SET_XDATATYPE_VALUE_ON_APPLY_THEME
	}
	
	///Kyle 09/26/08 HANDLE_ERROR_ON_BEFORE_EXECUTE
	trGetN.GetAttribute(_ERROR_CODE_ATTRIB, nErr);	///Jasmine 04/23/08 WIZZARD_XF_CANNOT_ABORT_UNTIL_nGetNDialog_IS_MINUS_2
	if(nGetNDialog < 0 && CER_NO_ERROR == nErr)
	{
		
		//check_get_progress(trGetN, STR_EXE_ATTRIB, true);
		
		PeakFitHelper* pFitHelper = _check_get_peak_fit_helper( trGetN );
	
		if( NULL != pFitHelper )
		{
			bool 	bShowResidual = trGetN.residual.nVal,
					bShow2ndDervi = trGetN.derivative.nVal;
			pFitHelper->UpdatePreview( FITPREVIEW_REMOVE_FITS, & bShowResidual, & bShowResidual );
		}
	
		_access_params_dlg(pFitHelper, OMSG_CLOSE);
		
		nErr = _check_source_data(trGetN);
		
		//------ Folger 10/17/08 NEED_TO_UPDATE_PARAMS_TREE_INTO_PA_FIT_GETNTREE_WHEN_PEAK_FIT_DIALOG_CLOSE
		//if( NULL != pFitHelper )
			//pFitHelper->UpdateSettingOnChange(trGetN);
		//------ End NEED_TO_UPDATE_PARAMS_TREE_INTO_PA_FIT_GETNTREE_WHEN_PEAK_FIT_DIALOG_CLOSE
	}
	
	if(CER_NO_ERROR != nErr && nGetNDialog < 0)		///Jasmine 04/23/08 WIZZARD_XF_CANNOT_ABORT_UNTIL_nGetNDialog_IS_MINUS_2
	{
		trGetN.GetAttribute(_ERROR_CODE_ATTRIB2, strErrMsg);
		if( strErrMsg.IsEmpty() )
			warning_msg_box(nErr, false, 'E');
		else
			warning_msg_box(nErr, strErrMsg, false, 'E');
		nRet = XFEVT_ABORT;
	}
	///End HANDLE_ERROR_ON_BEFORE_EXECUTE
	
}
//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int pa_fit_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
