/*------------------------------------------------------------------------------*
 * File Name:NLFitPreviewCtrl.h													*
 * Creation: Cheney 09/08/07													*
 * Purpose: OriginC Header file for general vsFlexGrid control					*
 * Copyright (c) Originlab Corp. 2003, 2004, 2005, 2006, 						*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	Hong 09/05/08 v8.093cc FITNL_USING_NEW_NLFSESSION							*
 *	Kyle 09/28/08 CHECK_IF_NEED_TO_CLEAN_LAYERS									*
 *	Kyle 10/08/08 GET_Y_DATA_COLUMN_INDEX_FOR_RESIDUAL							*
 *	Kyle 10/21/08 CHANGE_FUNCTION_NAME_HASBASELINEPEAK_TO_GETBASELINEFITMODE	*
 *	Hong 10/17/08 QA80-10624 NLFIT_SUPPORT_FIT_SWAPPED_POLAR_PLOT				*
 *	Sophy 10/24/2008 SUPPORT_MUILTI_INDEP_AND_DEP_PREVIEW_FOR_NLFIT_81			*
 *	Sophy 10/24/2008 SHOULD_REARRANGE_LAYERS_WHEN_SWITCH_BETWEEN_SINGLE_INDEP_N_DEP_AND_MULTI_IDEP_N_DEP
 *	Sophy 10/24/2008 v8.960b FIX_ERROR_SOURCE_PLOT_PREVIEW_ON_MUILTI_DEP_AND_INDEP_FIT
 *	Hong 10/28/08 v8.0962 MORE_ERROR_CHECKING									*
 *	Sophy 10/28/2008 SHOULD_REARRANGE_LAYERS_WHEN_SWITCH_BETWEEN_SINGLE_INDEP_N_DEP_AND_MULTI_IDEP_N_DEP
 *	Sophy 10/31/2008 GROUP_CUMULATIVE_CURVE_WITH_FITTED_CURVES					*
 *	Sophy 11/1/2008 v8.0964c FIX_NLEND_FAIL_CREATE_FIT_CURVE_IN_SRC_GRAPH		*
 *	Sophy 11/1/2008 IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE			*
 *	Sophy 11/4/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
 *	Sophy 11/5/2008 SOURCE_CURVES_FITTED_CURVES_AND_RESIDUAL_SHOULD_GIVE_GROUPED_COLOR_ON_MULTI_DATASET
 *	Sophy 11/6/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
 *	Sophy 11/10/2008 CENTRALIZE_CODE_PEAK_LABEL_TYPE_FROM_NLFPREVIEW_AND_PAWIZCORE
 *	Folger 11/10/08 QA80-12509 v8.0968 ONLY_SET_PLOT_LABEL_TYPE_IN_PEAK_FIT_DIALOG_EXCLUDE_ROTATION
 *	Sophy 11/11/2008 v8.968 QA80-10599-P1 NLFIT_PREVIEW_UPDATE_CLEANUP			*
 *	Sophy 11/13/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
 *	Sophy 11/18/2008 FIX_FAIL_TO_SET_LABEL_YOFFSET_WHEN_PREVIEW_ON_DLG			*
 *	Sophy 11/20/2008 QA80-10599-P6 FIX_FITCURVE_GRAPH_AXES_RESCALE_PROBLEM		*
 *	Sophy 11/24/2008 v8.978c QA80-12643 SHOULD_NOT_ALWAYS_RESCALE_SCALE_IN_NLFIT_BY_FITTED_CURVES_RANGE
 *	Sophy 11/25/2008 v8.979 ONLY_PLOT_PEAKCENTER_LABAL_FOR_NLFIT_REPLICA		*
 *	Hong 12/03/08 v8.0982 SPEED_UP_NLFIT_OPEN_DLG								*
 *  Sandy 2008-12-17 ADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW
 *	Sophy 12/23/2008 v8.0990 QA80-12832 SUPPORT_MULTI_DATASET_FOR_MULTI_INDEPS_AND_DEPS_FITTING
 *	Sophy 1/16/2009 v8.0957 FITCURVE_PREVIEW_GRAPH_LAYERS_SHOULD_USE_SAME_TEMPLATE
 *	Folger 01/04/09 QA80-12962 MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
 *	Kyle 01/19/2009 QA80-12976 JUST_UPDATE_SOURCE_LAYER_IF_FROM_GRAPHLAYER		*
 *	Folger 02/01/09 PEAK_FITTING_RESIDUAL_PLOT_PREVIEW_BROKEN					*
 *	Sophy 2/1/2009 v8.0968b FIX_RESIDUAL_PLOTS_FAIL_TO_GROUP_CORRECTLY_WITH_MUILTI_DATASETS
 *	Folger 02/03/09 PA_FITTING_WITH_BASELINE_FAILS_TO_GET_CORRECT_RESIDUAL_DATA	*
 *	Kyle 02/10/2009 QA80-12976 NOT_DO_FORMAT_COPY_IF_THE_CURRENT_PAGE_IS_THE_SOURCE
 *	Folger 02/10/09 PA_FITTING_FAILS_TO_PREPARE_RESIDUAL_DATA_FOR_SINGLE_PEAK_CASE
 *	Sophy 2/11/2009 v8.0976c QA80-13020-P4 SHOW_COLORSCALE_ON_RESIDUAL_TAB_ON_CHANGE_PARAMS_AND_APPLY_LAST_USED_THEME
 *	Sophy 2/16/2009 v8.0979b QA80-13121 CUSTOM_LEGEND_NEED_SIMPLER_LINE_SUPPORT	*
 *	Sophy 4/27/2009 v8.0987 QA80-13178 UPDATE_FITCURVE_RESIDUAL_PLOTS_SETTINGS_FOR_UPDATE_3D_RESIDUAL_PREVIEW
 *	Folger 10/31/09 QA81-14560 NLBEGIN_GIVES_WRONG_PREVIEW_WHEN_MULTIPLE_DATASETS_WITH_DIFFERENT_X
 *	Kenny 12/24/2009 QA81-14875-P2 PROGRESS_BAR_IN_BUILTIN_TOOL_SHOULD_NOT_KEEP_TOPMOST*
 *	Folger 08/12/10 ORG-733-P3 NLFIT_PREVIEW_FAILED_TO_UPDATE_IF_FIRST_FUNCTION_INVALID_AFTER_OPEN
 *	Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL	*
 *------------------------------------------------------------------------------*/
 
#ifndef _NLF_PREVIEWCTRL_H_    
#define _NLF_PREVIEWCTRL_H_

///--- MACRO for debug
#define	SHOW_PREVIEW_FITTING_GRAPH
//#define IS_PREVIEW_DEBUG_MODE
//#define	_DEBUG_FIT
///----

//------ Folger 11/08/07 CATEGORY_NEEDED_WHEN_LOCALIZE
#define STR_CAT_STATS "Statistics"
//------ End CATEGORY_NEEDED_WHEN_LOCALIZE

///Sophy 11/4/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
#define	STR_REPLICA_PEAKS_CENTER_WKS_NAME	"ReplicaCenters"
enum{
	NLFIT_REPLICA_PK_CENTER_XCOL = 0,
	NLFIT_REPLICA_PK_CENTER_YCOL = 1,
};
///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
///Sophy 11/10/2008 CENTRALIZE_CODE_PEAK_LABEL_TYPE_FROM_NLFPREVIEW_AND_PAWIZCORE
//#define PEAK_LABEL_ROW_NUM_GUI	2	///Sophy 11/7/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH better 
///end CENTRALIZE_CODE_PEAK_LABEL_TYPE_FROM_NLFPREVIEW_AND_PAWIZCORE
enum //HIDDEN_TEMP_DATASHEET_TYPE
{
	WKS_FIT_CURVES,
	WKS_RESIDUAL,
	MAT_FIT_CURVES, //for 3D fitting
	MAT_RESIDUAL_CURVES, //just for matrix fitting
};

/// Iris NLF_81, add the following to easily understand
/*
1. prepare wks
2. setup wks col number & type
3. calc fit data and put to wks
4. prepare graph
5. plot
6. setup plot

FITPREVIEW_INIT: 1,2,3,4,5,6
FITPREVIEW_REINIT: 2,3,5,6
FITPREVIEW_UPDATE: 3
*/
///end NLF_81

enum {
	FITPREVIEW_UPDATE, // no contents change, just need to update the plots, will not even check if data outside axes scales
	//FITPREVIEW_REPLOT_FITS, // no change in source data, only fit curves changed ///Arvin 11/06/07 QA70-10599 PREVIEW_CORRUPTTED_WHEN_REPLICA_CHANGES
	FITPREVIEW_INIT, 	// complete reload of page from template and prepare all plots and legends
	FITPREVIEW_REINIT,  // use existing page and layers but recreate all the plots and legends
	///Arvin 11/06/07 QA70-10599 PREVIEW_CORRUPTTED_WHEN_REPLICA_CHANGES
	FITPREVIEW_REMOVE_FITS 		= 0x0004, ///Arvin 10/31/07 PFM_NEED_REMOVE_FIT_CURVE_PLOTS_FROM_PREVIEW
	FITPREVIEW_REPLOT			= 0x0008, // no change in source data, only fit curves changed
	FITPREVIEW_REPLICA_UPDATE	= 0x0010, // only number of replica change, //need to prepare wks
	FITPREVIEW_CLEAN_LAYER 		= 0x1000, ///Kyle 09/28/08 CHECK_IF_NEED_TO_CLEAN_LAYERS
	///END PREVIEW_CORRUPTTED_WHEN_REPLICA_CHANGES
};

///Sophy 2/11/2009 v8.0976c QA80-13020-P4 SHOW_COLORSCALE_ON_RESIDUAL_TAB_ON_CHANGE_PARAMS_AND_APPLY_LAST_USED_THEME
#define	UPDATE_TEMPLATE_PREVIEW_PAGE_FITCURVE		0x0001
#define	UPDATE_TEMPLATE_PREVIEW_PAGE_RESIDUAL		0x0002
///end SHOW_COLORSCALE_ON_RESIDUAL_TAB_ON_CHANGE_PARAMS_AND_APPLY_LAST_USED_THEME
#define NUM_INVALID_PLOT_INDEX						-2	///Sophy 11/1/2008 IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
#define NUM_DATASET_PER_FITTED_CURVE				2
#define ROW_NUM										50
#define COL_NUM										50

typedef struct tagPreviewCtrlInfo
{
	//bool									bNoPreview; /// Iris NLF_81, introduce pucbic method SetNonePreview to replace this one
	bool									bComputeCumulativeCurve;
	bool									bPlotIndividualPeak;
	bool									bPlotCumulativeCurve;
	/// Iris NLF_81, the following are no need, template and fitoptions moved to NLFCurvesBase class to control
	//bool									bSimplexFit;
	//int 									nPrevType;
	//string									strFitTemplate;
	//string									strResidualTemplate;	
	//FitResultCurveDataOptions 				fitOptionsX;
	//FitResultCurveDataOptions 				fitOptionsY; ///Arvin 11/22/07 NEED_RESCALE_FOR_3D_FITTINGS
	///end NLF_81
} PreviewCtrlInfo;


//-------------------------------------- NLFitPreviewCtrlBase class begin (virtual class)---------------------------------------
class NLFitPreviewCtrlBase
{
public:	
	~NLFitPreviewCtrlBase()
	{
		///Sophy 9/27/2008 MOVE_PREVIEW_ONDESTROY_CODE_TO_DESTRUCTOR
		///Sophy 11/1/2008 v8.0964c FIX_NLEND_FAIL_CREATE_FIT_CURVE_IN_SRC_GRAPH
		//removeFitCurves(); ///Sophy 9/27/2008 FIX_NLFIT_PREVIEW_FAIL_TO_REMOVE_FIT_CURVE_ON_CLICK_CANCEL
		RemoveFitCurves();
		///end FIX_NLEND_FAIL_CREATE_FIT_CURVE_IN_SRC_GRAPH
		m_vnSrcPlotIndex.SetSize(0);
		m_vnFitPlotIndex.SetSize(0);
		if ( m_graph )
		{
			GraphLayer gl = m_graph.Layers(0);
			GraphObject go = gl.GraphObjects(GO_LEGEND_NAME);			
			if( go )
				go.Text = m_strSourceLegend;
		}
		///end MOVE_PREVIEW_ONDESTROY_CODE_TO_DESTRUCTOR
		if(m_pNLFCurves)
		{
			delete m_pNLFCurves;
			m_pNLFCurves = NULL;
		}
	}
	
	///virtual void OnDestroy();	///Sophy 9/27/2008 MOVE_PREVIEW_ONDESTROY_CODE_TO_DESTRUCTOR
	
	// set fit curve options like x points, from, to...will set into NLFCurvesBase class
	void	SetFitCurveOptions(TreeNode& trCurveOptions);

	// to set if real time update preview or not
	bool 	SetEnableUpdate(bool bAuto);
	
	// set is none preivew or not. If data is not ready or met GUI settings error, will show None Preview graph
	void	SetNonePreview(bool bIsNone = true) { m_bIsNonePreview = bIsNone; }	
	///------ Folger 08/12/10 ORG-733-P3 NLFIT_PREVIEW_FAILED_TO_UPDATE_IF_FIRST_FUNCTION_INVALID_AFTER_OPEN
	BOOL	IsNonePreview(bool bIsNone = true) { return m_bIsNonePreview; }
	///------ End NLFIT_PREVIEW_FAILED_TO_UPDATE_IF_FIRST_FUNCTION_INVALID_AFTER_OPEN

	// set preview graph page
	virtual bool 	SetPreviewGraph(GraphPage& gp, int nType, int nLayer = 0);	
	
	// update preview
	///Sophy 9/9/2008 UPDATE_REPLICA_PREVIEW_FOR_NLF_81
	//bool 	UpdatePreviewGraph(DWORD dwUpdateBits = FITPREVIEW_INIT, bool* pUpdateLegend = NULL);	
	virtual	bool 	UpdatePreviewGraph(DWORD dwUpdateBits = FITPREVIEW_INIT, PreviewCtrlInfo* pPreviewCtrlInfo = NULL, bool* pUpdateLegend = NULL);	
	///end UPDATE_REPLICA_PREVIEW_FOR_NLF_81
	
	virtual string GetTemplate(bool bIsResidual) { ASSERT(false); return "";}
	
	virtual bool UpdateResidualContourLevels(GraphLayer& gl = NULL) {return false;}	
	
	virtual	bool SetResidualLimits(const double& dIRL, const double& dORL){ASSERT(FALSE); return false;}///Sophy 4/27/2009 v8.0987 QA80-13178 UPDATE_FITCURVE_RESIDUAL_PLOTS_SETTINGS_FOR_UPDATE_3D_RESIDUAL_PREVIEW
	
protected:
	virtual NLFCurvesBase* GetNLFCurvesObject() { ASSERT(false); return NULL; } /// Iris NLF_81 need to override, should not enter here any way. 
	
	virtual bool	IsResetWksCols(DWORD dwUpdateBits) { return false; }
	
	void 	CleanFitCurveGraphLayer(int nLayer);
	virtual bool GetFitCurveGraphLayer(GraphLayer& gl, int nLayer = 0);
	
	bool	SetSourcePlotUID(DWORD dwPlotUID);
	bool	GetSourcePlotUID(int index, DWORD* pdwPlotUID = NULL);
	bool	ResetSourcePlotUIDs();	
	
	/// Iris NLF_81, moved rescale codes to NLFCurves
	/*
	/// Hong 07/05/08 QA80-11206 MORE_FIX_SURFACE_FIT_CONTOUR_LEVEL_CHANGED_BY_RESCALE	
	//virtual bool RescaleFitCurvesGraph(GraphLayer& gl, const NLFitSession& nlfitSessionBase, const FitResultCurveDataOptions& fitOptionsX, DataRange& drSrc, const FitResultCurveDataOptions& fitOptionsY = NULL);
	virtual bool RescaleFitCurvesGraph(GraphLayer& gl, const NLFitSession& nlfitSessionBase, const FitResultCurveDataOptions& fitOptionsX, DataRange& drSrc, const FitResultCurveDataOptions& fitOptionsY = NULL, DWORD dwRescaleCtrl = 0);
	/// end MORE_FIX_SURFACE_FIT_CONTOUR_LEVEL_CHANGED_BY_RESCALE
	*/
	///end NLF_81
	
	bool	SetSourcePlotInfo(int nPlotIndex, int nDataset, int nNumDataset = 1, int nLayer = 0);

	
	/// Iris NLF_81, to do, need move to NLFCurves.h
	//bool 	SetPlotFormatfromSrcPlot(const DataPlot& dpSrc, int nPlot, GraphLayer& gl);
	///end NLF_81
	
	///------ Folger 01/04/09 QA80-12962 MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
	//int  GetXDataColIndex(int nDataset = 0, int nPeaks = 1) 
	virtual	int  GetXDataColIndex(int nDataset = 0, int nPeaks = 1, int nPeak = -1) 
	///------ End MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
	{ 
		return (nPeaks + 1) * nDataset + nDataset;
	}

	virtual int  GetYDataColIndex(int nDataset = 0, int nPeak = 0, int nPeaks = 1)
	{
		int 	nn = GetXDataColIndex(nDataset, nPeaks) + nPeak + 1;
		
		bool	bHasCumulativeCurve = true; // always has cumulative data column in normal xy fit, so columns are X, Cumulative, FitCurveY1, FitCurveY2, FitCurveY3...
		if(bHasCumulativeCurve)
			nn ++;
		
		return nn;
	}	
	
	///Kyle 10/08/08 GET_Y_DATA_COLUMN_INDEX_FOR_RESIDUAL
	virtual		///------ Folger 02/10/09 PA_FITTING_FAILS_TO_PREPARE_RESIDUAL_DATA_FOR_SINGLE_PEAK_CASE
	int GetResidualYDataColIndex(int nDataset = 0, int nPeak = 0, int nPeaks = 1)
	{
		int nYCol;
		if( nPeaks == 1)
		{
			nYCol = GetYDataColIndex(nDataset, 0, nPeaks);
		}
		else
		{
			int nXCol = GetXDataColIndex(nDataset, nPeaks);
			nYCol = nXCol + 1;
		}
		return nYCol;
	}
	///End GET_Y_DATA_COLUMN_INDEX_FOR_RESIDUAL
	
	/// Iris NLF_81, to do, this method should be removed later
	virtual bool GetPreviewCumulativeData(vector& vCumuData, int nNumPeaks, int nDataIndex = 0) {return false;}
	virtual void SubtractBaseline(const vector vx, vector& vy) {}
	///end NLF_81
	
	bool	RemoveFitCurves(); ///Sophy 11/1/2008 v8.0964c FIX_NLEND_FAIL_CREATE_FIT_CURVE_IN_SRC_GRAPH
	virtual	bool	RemovePeakLabels(){ return false;}	///Sophy 11/6/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
	
private:
	/// Hong 04/23/08 QA80-11357-P2 FIX_NLBEGIN_FAIL_PREVIEW_FROM_SRC_GRAPH
	//NLFitPreviewCtrlBase(){} 
	// default should init to do preview, should not depend on compiler's initial value of class member
	NLFitPreviewCtrlBase()
	{ 
		m_bAutoUpdate = true;
		m_PreviewCtrlInfo.bPlotIndividualPeak = true;
		m_PreviewCtrlInfo.bComputeCumulativeCurve = true;
	} 
	/// end FIX_NLBEGIN_FAIL_PREVIEW_FROM_SRC_GRAPH	
	
	bool 	isAutoUpdate() { return m_bAutoUpdate; }
	virtual bool 	updatePreviewData(DWORD dwUpdateBits) { ASSERT(false); return false; }
	
	virtual bool 	plotSourceCurves() { return false; }
	///Sophy 11/1/2008 IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
	//virtual int 	plotFitCurvesAndResidual() {return 0;}
	virtual int 	plotFitCurvesAndResidual( DWORD dwUpdateBits = FITPREVIEW_REPLOT ) {return 0;}//default:plot both
	///end IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
	
	bool	cleanGraphLayer(GraphPage& pg, bool bCleanFirstLayer = false);

	//bool    removeFitCurves();	///Sophy 11/1/2008 v8.0964c FIX_NLEND_FAIL_CREATE_FIT_CURVE_IN_SRC_GRAPH moved to protected

	///------ Folger 08/13/10 ORG-733-P3 NLFIT_PREVIEW_FAILED_TO_UPDATE_IF_FIRST_FUNCTION_INVALID_AFTER_OPEN
	//bool	isReloadPreviewTemplate();
	bool	isReloadPreviewTemplate(LPDWORD pdwUpdateBits = NULL);
	///------ End NLFIT_PREVIEW_FAILED_TO_UPDATE_IF_FIRST_FUNCTION_INVALID_AFTER_OPEN
	bool	isShowPreviewGraph( bool bResidual );	///Sophy 7/11/2008 CONTROL_WHETHER_TO_SHOW_PREVIEW
	///Sophy 2/11/2009 v8.0976c QA80-13020-P4 SHOW_COLORSCALE_ON_RESIDUAL_TAB_ON_CHANGE_PARAMS_AND_APPLY_LAST_USED_THEME
	//bool	reloadPreviewTemplate();
	bool	reloadPreviewTemplate(DWORD dwUpdateBits = 0x0003); //default, reload both fitcurve and residual
	///end SHOW_COLORSCALE_ON_RESIDUAL_TAB_ON_CHANGE_PARAMS_AND_APPLY_LAST_USED_THEME
	bool	cleanPlots(GraphPage& pg, int nStartPlotIndex = 0, int nEndPlotIndex = -1);

	bool	setSourcePlotIndex(int nPlotIndex, int nPos);
	
	///Arvin 12/10/07 PFW_SHOULD_NOT_RESCALE_DERIVATIVE_LAYER
	virtual int getNeedRescaleLayerNum(const GraphPage& pg) { return pg.Layers.Count();}
	///end PFW_SHOULD_NOT_RESCALE_DERIVATIVE_LAYER		

	bool	setFitCurvePreviewGraph(GraphPage& gp, int nLayer);
	bool	setResidualPreviewGraph(GraphPage& gp, int nLayer);
	///Sophy 11/11/2008 v8.968 QA80-10599-P1 NLFIT_PREVIEW_UPDATE_CLEANUP
	//void 	updateLegendAndRescale(GraphPage& gp, bool bUpdateLegend, bool bRescale, bool bCopyForamtFromSource);
	void 	updateLegendAndRescale(GraphPage& gp, bool bUpdateLegend, bool bRescale, bool bCopyForamtFromSource, bool bFitCurveGraph );
	///end NLFIT_PREVIEW_UPDATE_CLEANUP
	
	///Kyle 01/19/2009 QA80-12976 JUST_UPDATE_SOURCE_LAYER_IF_FROM_GRAPHLAYER
	void 	updateLegendAndRescale(GraphLayer& gl, bool bUpdateLegend, bool bRescale, bool bCopyForamtFromSource, bool bFitCurveGraph );
	///End JUST_UPDATE_SOURCE_LAYER_IF_FROM_GRAPHLAYER

protected:
	int							m_nFitCurveLayer;	///Jasmine 03/21/08 QA80-10198 SPECIFY_PREVIEW_LAYER_IN_MULTILAYER_GRAPH_FOR_SINGLE_DEPS_INDEPS
	GraphPage 					m_graph; 
	
	int							m_nResidualLayer;	///Jasmine 03/21/08 QA80-10198 SPECIFY_PREVIEW_LAYER_IN_MULTILAYER_GRAPH_FOR_SINGLE_DEPS_INDEPS
	GraphPage 					m_gpResidual;
	
	bool						m_bExternalPreview;	//----- CPY 10/30/07 JASMINE_FOUND_PFM_NEED_SEPARATE_PREVIEW
	
	vector<int> 				m_vnSrcPlotIndex;
	vector<int>					m_vnFitPlotIndex;	
	
	bool						m_bAutoUpdate;///Arvin 04/01/08 QA70-11322 ADD_AUTO_UPDATE_PREVIEW_CHECKBOX	
	
	string						m_strSourceLegend;/// Hong 04/02/08 QA80-11360 FIX_LEGEND_UPDATED_EVEN_UNCHECK_UPDATE_SRC_LEGEND
	
	/// Iris NLF_81
	NLFitSession*					m_pNLFSession; 
	NLFCurvesBase*				m_pNLFCurves;
	bool						m_bIsNonePreview;
	vector<int>					m_vnSourcePlotUIDs;
	///end NLF_81
	PreviewCtrlInfo 			m_PreviewCtrlInfo;///Sophy 9/9/2008 UPDATE_REPLICA_PREVIEW_FOR_NLF_81
};
//------------------------------------------ NLFitPreviewCtrlBase class end ---------------------------------------


//------------------------------------- NLFitPreviewCtrl class begin (General XY Fitting Preview ctrl class)---------------------------------------	
class NLFitPreviewCtrl : public NLFitPreviewCtrlBase
{
public:
	NLFitPreviewCtrl(NLFitSession* pNLFSession)
	{
		ASSERT(pNLFSession);
		m_pNLFSession = pNLFSession;
		m_bShowResidual = true;			//Kyle 
		///------ Folger 10/31/09 QA81-14560 NLBEGIN_GIVES_WRONG_PREVIEW_WHEN_MULTIPLE_DATASETS_WITH_DIFFERENT_X
		if ( m_pNLFSession )
		{
			m_PreviewCtrlInfo.bComputeCumulativeCurve = m_pNLFSession->GetNumberMultiplicity() > 1;
		}
		///------ End NLBEGIN_GIVES_WRONG_PREVIEW_WHEN_MULTIPLE_DATASETS_WITH_DIFFERENT_X
	}
	///Sophy 9/27/2008 MOVE_PREVIEW_ONDESTROY_CODE_TO_DESTRUCTOR
	~NLFitPreviewCtrl()
	{
		RemoveFitCurves();///Sophy 11/1/2008 v8.0964c FIX_NLEND_FAIL_CREATE_FIT_CURVE_IN_SRC_GRAPH
		///Sophy 11/6/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
		removePeakLabel();
		///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
		#ifndef IS_PREVIEW_DEBUG_MODE
			destroyPeakCenterWks();///Sophy 11/6/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
			if(m_FitCurvesWks)
				m_FitCurvesWks.Destroy();
			if(m_wksResidual)
				m_wksResidual.Destroy();
		#endif //IS_PREVIEW_DEBUG_MODE
	}
	///end MOVE_PREVIEW_ONDESTROY_CODE_TO_DESTRUCTOR
	//virtual
	//void 	OnDestroy();	///Sophy 9/27/2008 MOVE_PREVIEW_ONDESTROY_CODE_TO_DESTRUCTOR
	
	//virtual 
	string GetTemplate(bool bIsResidual);
	
	bool SetFitGraphAxesTypeWithSrcGraphLayer(bool& bLogScale );///Sophy 9/16/2008 CLEAN_NLFSPLITTER_FOR_81
protected:
	//virtual 
	NLFCurvesBase* GetNLFCurvesObject() 
	{  
		if(NULL == m_pNLFCurves)
		{
			ASSERT(m_pNLFSession);
			m_pNLFCurves = new NLFCurves(m_pNLFSession);
		}
		return m_pNLFCurves;
	} 	
	
	Worksheet*	GetTempWks(int nWksType);
	bool 		PrepareWks(int nWksType, DWORD dwUpdateBits = FITPREVIEW_INIT);	
	
	/// Iris NLF_81, will override in SurfaceFitPrevireCtrl
	// ask if need reset column number, type and format
	//virtual 
	bool	IsResetWksCols(DWORD dwUpdateBits);
	
	virtual void SubtractBaseline(const vector vx, vector& vy);
	///Sophy 11/6/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
	///virtual
	bool	RemovePeakLabels(){ return removePeakLabel(); }
	///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
private:
	//virtual 
	bool 	updatePreviewData(DWORD dwUpdateBits);
	
	virtual	int		getNumIndividualFitCurveCol(int nWksType = WKS_FIT_CURVES);		///------ Folger 01/04/09 QA80-12962 MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA

	//virtual 
	bool 	plotSourceCurves();
	///Sophy 11/5/2008 SOURCE_CURVES_FITTED_CURVES_AND_RESIDUAL_SHOULD_GIVE_GROUPED_COLOR_ON_MULTI_DATASET
	bool	groupDataPlots( GraphLayer& gl, const int nStartIndex, const int nEndIndex, int nStartColor = SYSCOLOR_BLACK );
	//bool	setupSourcePlots( GraphLayer& glSource, const int nStartIndex, const int nEndIndex, int nStartColor = SYSCOLOR_BLACK );//Sophy, commented out 11/7/2008, if gived proper template, no need this special code
	///end SOURCE_CURVES_FITTED_CURVES_AND_RESIDUAL_SHOULD_GIVE_GROUPED_COLOR_ON_MULTI_DATASET
	//virtual
	///Sophy 11/1/2008 IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
	//int 	plotFitCurvesAndResidual();	
	int 	plotFitCurvesAndResidual( DWORD dwUpdateBits = FITPREVIEW_REPLOT );	//plot both defaultly
	///end IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
	
	virtual void 	setWksColTypeAndFormat(Worksheet& wks, int nColumns, int nXNumCols = 1);
	
	bool 	plotSourceCurvesEachDataset(int nIndex);

	/// Iris NLF_81, to do, will do plot setup in NLFCurvesBase
	//virtual bool setupPlotStyles(GraphLayer& gl, int nPlot1Index, int nPlotLastIndex = -1, bool bGroup = true, int nLayer = 0, int nColor = SYSCOLOR_BLACK, int* pnCumulateIndex = NULL, int* pnBaseline = NULL);	///Jasmine 11/28/07 SET_FIT_CURVES_A_SAME_COLOR
	///end NLF_81	

	/// Iris NLF_81 ///Sophy, in getFitDataRange() : if nPeak == -1 and bIncPeakCurve == true, get all peaks; if bIncCumulativeCurve == true, get Cumulative range
	///------ Folger 01/04/09 QA80-12962 MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
	//bool	getFitDataRange(DataRange& drFit, int nDatasetIndex, int nPeak, int nPeaks, bool bIncCumulativeCurve = false, bool bIncPeakCurve = true );
	virtual	bool	getFitDataRange(DataRange& drFit, int nDatasetIndex, int nPeak, int nPeaks, bool bIncCumulativeCurve = false, bool bIncPeakCurve = true );
	///------ End MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
	bool	getResidualDataRange(DataRange& drResidual, int nDatasetIndex, int nPeak, int nPeaks, bool bPeakFit = false);
	///end NLF_81

	// plot fit curve and residual
	int  	plotFitCurEachDataset(DataRange& drFit, int nDatasetIndex, GraphLayer& glFit);
	int  	plotResidualEachDataset(DataRange& drResidual, int nDatasetIndex, GraphLayer& glResidual);
	
	///Sophy 11/1/2008 IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
	//bool	plotFitAndResidualForSingileDepsIndeps();
	bool	plotFitAndResidualForSingileDepsIndeps( DWORD dwUpdateBits = FITPREVIEW_REPLOT );
	///end IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
	bool 	plotFitCurvesForMultiDepsMultiIndeps();
	bool 	plotResidualForMultiDepsMultiIndeps();
	
	// update fit curve and residual data
	void 	setFitColumnLongName(Column& col, LPCSTR lpcszName, int index, int nNumDataset, int nPeak = 0, int nMultiplicity = 1, bool bResidual = false, int nOffset = 1);	
	bool 	updateFitAndResidulDataForSingleDepsIndeps(int nDatasetIndex);
	///Sophy 10/24/2008 SUPPORT_MUILTI_INDEP_AND_DEP_PREVIEW_FOR_NLFIT_81
	//bool 	updateFitCurveDataForMultiDepsIndeps();	
	//bool 	updateResidualDataForMultiDepsIndeps();
	bool 	updateFitCurveDataForMultiDepsIndeps( const int& nIndeps, const int& nDeps, const int& nDataIndex );	
	bool 	updateResidualDataForMultiDepsIndeps( const int& nIndeps, const int& nDeps, const int& nDataIndex );
	///end SUPPORT_MUILTI_INDEP_AND_DEP_PREVIEW_FOR_NLFIT_81

	bool	checkGetReplicaPeakCenterWks( Worksheet& wks );
	bool	getReplicaPeakCenterRange( XYRange& xyRange );
	bool	plotReplicaPeakCenterLabel( GraphLayer& glPreview );
	bool	updatePeakLabel();
	///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
	///Sophy 11/6/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
	bool	removePeakLabel();
	void	destroyPeakCenterWks();
	///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH

protected:
	Worksheet					m_FitCurvesWks;// all numeric cols
	Worksheet					m_wksResidual;
	
	bool 						m_bShowResidual;		//Kyle 
	
	///Sophy 11/4/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
private:
	XYRange						m_xyReplicaPKCenter;
	///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
//private:
	//Worksheet					m_wksResidual;
};
//------------------------------------------ NLFitPreviewCtrl class end ---------------------------------------


/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////NLFitPreviewCtrlBase Implement//////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
///Sophy 9/27/2008 MOVE_PREVIEW_ONDESTROY_CODE_TO_DESTRUCTOR
/*
//virtual 
void 	NLFitPreviewCtrlBase::OnDestroy()
{
	m_vnSrcPlotIndex.SetSize(0);
	m_vnFitPlotIndex.SetSize(0);
	
	if ( m_graph )
	{
		GraphLayer gl = m_graph.Layers(0);
		GraphObject go = gl.GraphObjects(GO_LEGEND_NAME);			
		/// Hong 07/05/08 v8.0857b FIX_CONCATENATE_FIT_FAIL_WORK_AS_DATA_PREPARED_IN_PREVIEW_OBJ
		//if( go )
		/// Iris NLF_81
		//if( go && m_bRestoreLegend )
		if( go )
		///end NLF_81
		/// end FIX_CONCATENATE_FIT_FAIL_WORK_AS_DATA_PREPARED_IN_PREVIEW_OBJ
			go.Text = m_strSourceLegend;
	}
}
*/
///end MOVE_PREVIEW_ONDESTROY_CODE_TO_DESTRUCTOR	
	
void	NLFitPreviewCtrlBase::SetFitCurveOptions(TreeNode& trCurveOptions)
{
	GetNLFCurvesObject()->SetFitCurveOptions(trCurveOptions);
}

bool 	NLFitPreviewCtrlBase::SetEnableUpdate(bool bAuto)
{
	bool bOldVal = m_bAutoUpdate;
	m_bAutoUpdate = bAuto;
	return bOldVal;
}

/// Iris NLF_81, to do, need move to NLFCurves.h
/*
bool	NLFitPreviewCtrlBase::SetPlotFormatfromSrcPlot(const DataPlot& dpSrc, int nPlot, GraphLayer& gl)	
{
	DataPlot dp = gl.DataPlots(nPlot);
	if(!dp)
		return false;
	
	BASIC_PLOT_SETTINGS stps;
	int nType = dpSrc.GetPlotType(NULL, &stps);
	if(nType >= IDM_PLOT_LINE && nType <= IDM_PLOT_LINESYMB)
	{
		int nColor = nType == IDM_PLOT_SCATTER? stps.nEdgeColor : stps.nLineColor;
		dp.SetColor(nColor, true, false);
	}
	
	return true;
}
*/
///end NLF_81


bool	NLFitPreviewCtrlBase::setSourcePlotIndex(int nPlotIndex, int nPos)
{
	if( m_vnSrcPlotIndex.GetSize() <= nPos )
		return false;
		
	m_vnSrcPlotIndex[nPos] = nPlotIndex;
	return true;
}

bool	NLFitPreviewCtrlBase::SetSourcePlotInfo(int nPlotIndex, int nDataset, int nNumDataset, int nLayer)
{
	int nPos = 0;
	
	if(nDataset == 0) //1st data plot
		if(!setSourcePlotIndex(nPlotIndex, nLayer * 2))
			return false;
	
	if(nDataset == nNumDataset - 1)
		if(!setSourcePlotIndex(nPlotIndex, nLayer * 2 + 1))
			return false;
	
	return true;
}

/// Iris NLF_81, moved to NLFCurves.h
/*
void 	NLFitPreviewCtrlBase::setFitCurvePreviewLegendMode()
{
	GraphLayer 	glSource;
	GetSourceGraphLayer(glSource);
	if(!glSource)
		return;
	
	GraphPage gpSource = glSource.GetPage();
	
	string		strCustomFormat;
	int	nLegendMode = get_page_legend_mode(gpSource, strCustomFormat);
	
	if( set_page_legend_mode(m_graph, nLegendMode, strCustomFormat) )
		m_graph.Refresh(true);
}
*/
///end NLF_81

/// Iris NLF_81, no need
/*
bool    NLFitPreviewCtrlBase::GetSourceGraphLayer(GraphLayer& gl, int index)
{
	// should call m_pNLFSession->GetSourcePlotUID, not NLFitPreviewCtrlBase::GetSourcePlotUID since want to get real source graph here, 
	// NLFitPreviewCtrlBase::GetSourcePlotUID will return source plot uid plotted on preview graph, not real source graph.
	return get_graph_layer_by_plot_uid(gl, m_pNLFSession->GetSourcePlotUID(index));
}
*/
///end NLF_81

/// Iris NLF_81
//bool	NLFitPreviewCtrlBase::SetSourcePlotUID(int nDatasetIndex, DWORD dwPlotUID)
bool	NLFitPreviewCtrlBase::SetSourcePlotUID(DWORD dwPlotUID)
///end 
{
	/// Iris NLF_81
	//if( nDatasetIndex >= m_vnSourcePlotUIDs.GetSize() )
		//return error_report("Out index of m_vnSourcePlotUIDs in setSourcePlotUID");
	//
	//m_vnSourcePlotUIDs[nDatasetIndex] = dwPlotUID;
	m_vnSourcePlotUIDs.Add(dwPlotUID);
	///end NLF_81
	return true;
}

bool	NLFitPreviewCtrlBase::ResetSourcePlotUIDs()
{
	/// Iris NLF_81
	//int nDeps, nIndeps;
	//if(!m_pNLFSession->GetNumVars(&nDeps, &nIndeps))
		//return false;
	//
	//m_vnSourcePlotUIDs.SetSize(nDeps * nIndeps * m_pNLFSession->GetNumDataset());	
	//m_vnSourcePlotUIDs = 0;
	m_vnSourcePlotUIDs.SetSize(0);
	///end NLF_81
	return true;
}

bool	NLFitPreviewCtrlBase::GetSourcePlotUID(int index, DWORD* pdwPlotUID)
{
	///*
	if( index >= m_vnSourcePlotUIDs.GetSize() )
		return false;
		
	DWORD dwPlotUID = m_vnSourcePlotUIDs[index];
	
	if(pdwPlotUID)
		*pdwPlotUID = dwPlotUID;
	
	return 0 != dwPlotUID; // returns true if has plotted source data, else false
	//*/
	//DWORD	dwPlotUID = m_pNLFSession->GetSourcePlotUID(index);
	//if( pdwPlotUID )
		//*pdwPlotUID = dwPlotUID;
	//return 0 != dwPlotUID;
}


bool	NLFitPreviewCtrlBase::GetFitCurveGraphLayer(GraphLayer& gl, int nLayer)
{
	if(!m_graph)
		return false;
	
	gl = m_graph.Layers(nLayer);
	if(!gl)
	{
		///Sophy 1/16/2009 v8.0957 FITCURVE_PREVIEW_GRAPH_LAYERS_SHOULD_USE_SAME_TEMPLATE
		//nLayer = m_graph.AddLayer();
		nLayer = m_graph.AddLayer(NULL, 0, GetNLFCurvesObject()->GetTemplate(false));
		///end FITCURVE_PREVIEW_GRAPH_LAYERS_SHOULD_USE_SAME_TEMPLATE
		gl = m_graph.Layers(nLayer);
	}
	
	return true;
}

void 	NLFitPreviewCtrlBase::CleanFitCurveGraphLayer(int nLayer)
{
	GraphLayer gl;
	if( GetFitCurveGraphLayer(gl, nLayer) )
	{
		while(gl.RemovePlot(0));
	}	
}

bool	NLFitPreviewCtrlBase::cleanPlots(GraphPage& pg, int nStartPlotIndex, int nEndPlotIndex)
{
	if(!pg)
		return false;
	
	if(nStartPlotIndex < 0 || (nEndPlotIndex > -1 && nStartPlotIndex > nEndPlotIndex) )
		return false;
	
	int nLayers = pg.Layers.Count();
	for(int ii = 0; ii < nLayers; ii++)
	{
		GraphLayer gl = pg.Layers(ii);
		
		if(nEndPlotIndex == -1)
			nEndPlotIndex = gl.DataPlots.Count();
			
		for(int ii = nStartPlotIndex; ii <= nEndPlotIndex; ii++)
			gl.RemovePlot(nStartPlotIndex);
	}
	return true;
}	

///------ Folger 08/13/10 ORG-733-P3 NLFIT_PREVIEW_FAILED_TO_UPDATE_IF_FIRST_FUNCTION_INVALID_AFTER_OPEN
/*
bool	NLFitPreviewCtrlBase::isReloadPreviewTemplate()
{
	if( m_bExternalPreview )
		return false;
	
	bool bCurrentNoPreview = is_nonepreview_template(m_graph, true);
	return bCurrentNoPreview != m_bIsNonePreview;		
}
*/
bool	NLFitPreviewCtrlBase::isReloadPreviewTemplate(LPDWORD pdwUpdateBits/* = NULL*/)
{
	DWORD	dwUpdateBits = 0;
	O_SET_BIT(dwUpdateBits, UPDATE_TEMPLATE_PREVIEW_PAGE_FITCURVE, !m_bExternalPreview && m_bIsNonePreview != is_nonepreview_template(m_graph, true));
	O_SET_BIT(dwUpdateBits, UPDATE_TEMPLATE_PREVIEW_PAGE_RESIDUAL, m_bIsNonePreview != is_nonepreview_template(m_gpResidual, true));
	
	if ( pdwUpdateBits )
		*pdwUpdateBits = dwUpdateBits;
	return dwUpdateBits != 0;
}

///------ End NLFIT_PREVIEW_FAILED_TO_UPDATE_IF_FIRST_FUNCTION_INVALID_AFTER_OPEN

///Sophy 7/11/2008 CONTROL_WHETHER_TO_SHOW_PREVIEW
bool	NLFitPreviewCtrlBase::isShowPreviewGraph( bool	bResidual )
{
	if( bResidual )
		return m_gpResidual.IsValid();
	else
		return m_graph.IsValid();
	
	return false;
}
///end CONTROL_WHETHER_TO_SHOW_PREVIEW
//----- CPY 10/22/2007 QA70-10569 ALLOW_LEGEND_TO_BE_MOVED_IN_NLFIT_PREVIEW
// seems there is no need to add new bit, can add later if really needed, but for NLFit, the preview is generated from our code
// so there are no other text labels that we need to worry about except axis titles but those are ok to move as well
//------- CPY 3/4/08 QA-11206 XYZ_PREVIEW_NOT_SHOWING
#ifdef _DEBUG_FIT
	#define NLFIT_PREVIEW_NOCLICK_BITS 	 0
#else
	///Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
	//#define NLFIT_PREVIEW_NOCLICK_BITS 	(NOCLICK_DATA_PLOT | NOCLICK_TICKLABEL | NOCLICK_LAYER | NOCLICK_LAYERICON)
	#define NLFIT_PREVIEW_NOCLICK_BITS 	(OC_TOOL_NOCLICK | NOCLICK_ZOOMPAN)
	//End CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
#endif
//-------
//#define NLFIT_PREVIEW_NOCLICK_BITS 	 (NOCLICK_DATA_PLOT | NOCLICK_LAYER | NOCLICK_LAYERICON)  //CPY 10/28/07, Easwar said should allow double-click tick labels
//----- end ALLOW_LEGEND_TO_BE_MOVED_IN_NLFIT_PREVIEW

///Sophy 2/11/2009 v8.0976c QA80-13020-P4 SHOW_COLORSCALE_ON_RESIDUAL_TAB_ON_CHANGE_PARAMS_AND_APPLY_LAST_USED_THEME
//bool	NLFitPreviewCtrlBase::reloadPreviewTemplate()
bool	NLFitPreviewCtrlBase::reloadPreviewTemplate(DWORD dwUpdateBits)
///end SHOW_COLORSCALE_ON_RESIDUAL_TAB_ON_CHANGE_PARAMS_AND_APPLY_LAST_USED_THEME
{
	//----- CPY 10/22/2007 QA70-10569 ALLOW_LEGEND_TO_BE_MOVED_IN_NLFIT_PREVIEW
	//DWORD 	dwNoClicks = NOCLICK_DATA_PLOT | NOCLICK_LABEL | NOCLICK_TICKLABEL | NOCLICK_LAYER | NOCLICK_LAYERICON;
	DWORD 	dwNoClicks = NLFIT_PREVIEW_NOCLICK_BITS;
	//----- end ALLOW_LEGEND_TO_BE_MOVED_IN_NLFIT_PREVIEW
	
	///Sophy 2/11/2009 v8.0976c QA80-13020-P4 SHOW_COLORSCALE_ON_RESIDUAL_TAB_ON_CHANGE_PARAMS_AND_APPLY_LAST_USED_THEME
	//string strTemplate = m_bIsNonePreview? NLSF_NO_PREVIEW_TEMPLATE : GetNLFCurvesObject()->GetTemplate(false);
	//page_load(m_graph, strTemplate, dwNoClicks);
	//
	//strTemplate = m_bIsNonePreview? NLSF_NO_PREVIEW_TEMPLATE : GetNLFCurvesObject()->GetTemplate(true);
	//page_load(m_gpResidual, strTemplate, dwNoClicks);
	
	string strTemplate;
	if ( dwUpdateBits & UPDATE_TEMPLATE_PREVIEW_PAGE_FITCURVE )
	{
		strTemplate = m_bIsNonePreview? NLSF_NO_PREVIEW_TEMPLATE : GetNLFCurvesObject()->GetTemplate(false);
		page_load(m_graph, strTemplate, dwNoClicks);
	}
    
	if ( dwUpdateBits & UPDATE_TEMPLATE_PREVIEW_PAGE_RESIDUAL )
	{
		strTemplate = m_bIsNonePreview? NLSF_NO_PREVIEW_TEMPLATE : GetNLFCurvesObject()->GetTemplate(true);
		page_load(m_gpResidual, strTemplate, dwNoClicks);
	}
	return true;
}

bool	NLFitPreviewCtrlBase::cleanGraphLayer(GraphPage& pg, bool bCleanFirstLayer)
{
	if(!pg)
		return false;
	
	int nLayers = pg.Layers.Count();
	while(nLayers > 1)
	{
		pg.Layers().Destroy();
		nLayers--;
	}
	
	if(bCleanFirstLayer)
		while(pg.Layers().RemovePlot(0));
	///Sophy 10/28/2008 SHOULD_REARRANGE_LAYERS_WHEN_SWITCH_BETWEEN_SINGLE_INDEP_N_DEP_AND_MULTI_IDEP_N_DEP
	//if(nLayers > 1)//Original layers number > 1.
	//{
		//int nRow = 1;
		//int nCol = 1;
		//page_arrange_layers(pg, nRow, nCol);
	//}
	ASSERT( pg.Layers.Count() == 1 );
	page_arrange_layers( pg, 1, 1 );
	///end SHOULD_REARRANGE_LAYERS_WHEN_SWITCH_BETWEEN_SINGLE_INDEP_N_DEP_AND_MULTI_IDEP_N_DEP
	
	return true;
}


bool	NLFitPreviewCtrlBase::setFitCurvePreviewGraph(GraphPage& gp, int nLayer)
{
	if( !gp )
		return false;	
	GraphLayer 	glPreview = gp.Layers(nLayer);
	
	/// Hong 04/02/08 QA80-11360 FIX_LEGEND_UPDATED_EVEN_UNCHECK_UPDATE_SRC_LEGEND
	if ( m_graph.IsValid() )
	{
		GraphLayer gl = m_graph.Layers(m_nFitCurveLayer);
		GraphObject go = gl.GraphObjects(GO_LEGEND_NAME);
		if ( go )
		{
			go.Text = m_strSourceLegend;
		}
	}
	/// end FIX_LEGEND_UPDATED_EVEN_UNCHECK_UPDATE_SRC_LEGEND
	
	m_graph = gp;
	m_nFitCurveLayer = nLayer;	///Jasmine 03/21/08 QA80-10198 SPECIFY_PREVIEW_LAYER_IN_MULTILAYER_GRAPH_FOR_SINGLE_DEPS_INDEPS	
	
	GraphObject go = glPreview.GraphObjects(GO_LEGEND_NAME);
	if ( go.IsValid() )
	{
		m_strSourceLegend = go.Text;
	}	
	else
		m_strSourceLegend = "";
	return true;
}

bool	NLFitPreviewCtrlBase::setResidualPreviewGraph(GraphPage& gp, int nLayer)
{
	GraphLayer  gl = gp.Layers(nLayer);
	if( !gl )
		return false;
	
	m_gpResidual = gp;
	m_nResidualLayer = nLayer;	///Jasmine 03/21/08 QA80-10198 SPECIFY_PREVIEW_LAYER_IN_MULTILAYER_GRAPH_FOR_SINGLE_DEPS_INDEPS
	
	//hide SPECTRUM1 object in 3D residual graph for init time
	GraphObject go = gl.GraphObjects("SPECTRUM1");
	if(go)
		go.Show(false);
	return true;
}

bool 	NLFitPreviewCtrlBase::SetPreviewGraph(GraphPage& gp, int nType, int nLayer)
{
	if( !gp )
		return false;	
	
	bool bSuccess = false;	///Sophy 2/11/2009 v8.0976c QA80-13020-P4 SHOW_COLORSCALE_ON_RESIDUAL_TAB_ON_CHANGE_PARAMS_AND_APPLY_LAST_USED_THEME
	if(nType == PREVIEW_RESIDUAL)
	{
		///Sophy 2/11/2009 v8.0976c QA80-13020-P4 SHOW_COLORSCALE_ON_RESIDUAL_TAB_ON_CHANGE_PARAMS_AND_APPLY_LAST_USED_THEME
		//return setResidualPreviewGraph(gp, nLayer);
		bSuccess  = setResidualPreviewGraph(gp, nLayer);
		if ( bSuccess && !m_bExternalPreview ) //PFM needn't to change template
			reloadPreviewTemplate(UPDATE_TEMPLATE_PREVIEW_PAGE_RESIDUAL);
		return bSuccess;
		///end SHOW_COLORSCALE_ON_RESIDUAL_TAB_ON_CHANGE_PARAMS_AND_APPLY_LAST_USED_THEME
	}
	else
	{
		m_bExternalPreview = PREVIEW_EXTERNAL_DATA_FIT == nType? true:false;	//----- CPY 10/30/07 JASMINE_FOUND_PFM_NEED_SEPARATE_PREVIEW
		///Sophy 2/11/2009 v8.0976c QA80-13020-P4 SHOW_COLORSCALE_ON_RESIDUAL_TAB_ON_CHANGE_PARAMS_AND_APPLY_LAST_USED_THEME
		//return setFitCurvePreviewGraph(gp, nLayer);
		bSuccess = setFitCurvePreviewGraph(gp, nLayer);
		if ( bSuccess && !m_bExternalPreview ) //PFM needn't to change template
			reloadPreviewTemplate(UPDATE_TEMPLATE_PREVIEW_PAGE_FITCURVE);
		return bSuccess;
		///end SHOW_COLORSCALE_ON_RESIDUAL_TAB_ON_CHANGE_PARAMS_AND_APPLY_LAST_USED_THEME
	}
	return false;	
}
///Sophy 11/1/2008 v8.0964c FIX_NLEND_FAIL_CREATE_FIT_CURVE_IN_SRC_GRAPH
//bool	NLFitPreviewCtrlBase::removeFitCurves()
bool	NLFitPreviewCtrlBase::RemoveFitCurves()
///end FIX_NLEND_FAIL_CREATE_FIT_CURVE_IN_SRC_GRAPH
{
	if(m_vnFitPlotIndex.GetSize() <= 0)
		return false;
	
	GraphLayer glPrev;
	if(!GetFitCurveGraphLayer(glPrev, m_nFitCurveLayer))
		return false;
	
	/// Iris NLF_81
	//bool bPlotIndividualPeak = pPreviewCtrlInfo->bPlotIndividualPeak;
	//bool bPlotCumulativeCurve = pPreviewCtrlInfo->bPlotCumulativeCurve;
	///Sophy 9/18/2008 FIX_PA_UNDO_PREVIEW_GRAPH_NOT_UPDATED
	//bool 	bPlotIndividualPeak = false;
	//bool 	bPlotCumulativeCurve = false;
	bool 	bPlotIndividualPeak = m_PreviewCtrlInfo.bPlotIndividualPeak;
	bool 	bPlotCumulativeCurve = m_PreviewCtrlInfo.bPlotCumulativeCurve;
	///end FIX_PA_UNDO_PREVIEW_GRAPH_NOT_UPDATED
	///end NLF_81
	
	int 	nPeaks = m_pNLFSession->GetNumPeaks();
	
	/// Hong 03/25/08 QA80-10969 FIX_MULTI_CURVES_FAIL_CLEAN_CLAERLY
	m_vnFitPlotIndex.Sort(SORT_DESCENDING);
	/// end FIX_MULTI_CURVES_FAIL_CLEAN_CLAERLY
	
	for(int ii = 0; ii < m_vnFitPlotIndex.GetSize(); ii++)
	{
		/////Jasmine 05/30/08 QA80-11633 UNWANTED_ZERO_IN_m_vnFitPlotIndex
		//if(0 == m_pNLFSession->GetPlotUID(ii))
			//continue;
		/////End UNWANTED_ZERO_IN_m_vnFitPlotIndex
			
		int nPlotStart	= m_vnFitPlotIndex[ii];
		int nPlotEnd 	= m_vnFitPlotIndex[ii];		
		
		//------ Folger 03/31/08 QA80-10969 FIX_LEGNED_NOT_CORRECT_UPDATE_WHEN_CHANGE_REPLICA_FIT_PLOT_SELECTION
		//if(nMultiplicity > 1 && bPlotIndividualPeak)
			//nPlotEnd = bPlotCumulativeCurve? nPlotStart+nMultiplicity : nPlotStart+nMultiplicity-1;
		/// Hong 06/02/08 v8.0875b FIX_CUMULATIVE_FIT_FAIL_REMOVE_IF_PLOT_INDIVIAL_PEAK
		//if( nMultiplicity > 1 )
		//	nPlotEnd = !bPlotCumulativeCurve || !bPlotIndividualPeak ? nPlotStart+nMultiplicity : nPlotStart+nMultiplicity-1;		
		if( nPeaks > 1 )
		{
			if ( bPlotIndividualPeak )
			{
				nPlotEnd = nPlotStart+nPeaks-1;
				if ( bPlotCumulativeCurve )
					nPlotEnd += 1;				
			}
			else if ( bPlotCumulativeCurve )
			{
				nPlotEnd = nPlotStart;
			}
			else
			{
				ASSERT(FALSE); // GUI have restrainted this case, do NOT know how u come here
			}
		}		
		/// end FIX_CUMULATIVE_FIT_FAIL_REMOVE_IF_PLOT_INDIVIAL_PEAK
		//------

		for(int iPlot = nPlotEnd; iPlot >= nPlotStart; iPlot--)
			glPrev.RemovePlot(iPlot);	
	}
	
	m_vnFitPlotIndex.SetSize(0);///Sophy 11/1/2008 v8.0964c FIX_NLEND_FAIL_CREATE_FIT_CURVE_IN_SRC_GRAPH if called in derived, can avoid duplicated invoked
	
	legend_check_remove_invalid_plot(glPrev.GraphObjects(GO_LEGEND_NAME));
	return true;
}
///end PFM_NEED_REMOVE_FIT_CURVE_PLOTS_FROM_PREVIEW

///Sophy 9/9/2008 UPDATE_REPLICA_PREVIEW_FOR_NLF_81
//bool	NLFitPreviewCtrlBase::UpdatePreviewGraph(DWORD dwUpdateBits, bool* pbUpdateLegend)
bool	NLFitPreviewCtrlBase::UpdatePreviewGraph(DWORD dwUpdateBits, PreviewCtrlInfo* pPreviewCtrlInfo, bool* pbUpdateLegend)
///end UPDATE_REPLICA_PREVIEW_FOR_NLF_81
{
	///Sophy 9/9/2008 UPDATE_REPLICA_PREVIEW_FOR_NLF_81
	if( NULL != pPreviewCtrlInfo )
		m_PreviewCtrlInfo = *pPreviewCtrlInfo;
	///end UPDATE_REPLICA_PREVIEW_FOR_NLF_81
	///Arvin 04/01/08 QA70-11322 ADD_AUTO_UPDATE_PREVIEW_CHECKBOX
	if(!isAutoUpdate())
		return false;
	///end ADD_AUTO_UPDATE_PREVIEW_CHECKBOX
	
	///------ Folger 08/13/10 ORG-733-P3 NLFIT_PREVIEW_FAILED_TO_UPDATE_IF_FIRST_FUNCTION_INVALID_AFTER_OPEN
	//if(isReloadPreviewTemplate())
	//{
		//reloadPreviewTemplate(); 
	//}
	DWORD	dwPrevUpate = UPDATE_TEMPLATE_PREVIEW_PAGE_FITCURVE | UPDATE_TEMPLATE_PREVIEW_PAGE_RESIDUAL;
	if ( isReloadPreviewTemplate(&dwPrevUpate) )
	{
		reloadPreviewTemplate(dwPrevUpate);
	}
	///------ End NLFIT_PREVIEW_FAILED_TO_UPDATE_IF_FIRST_FUNCTION_INVALID_AFTER_OPEN
	if(m_bIsNonePreview)
	{
		load_text_for_nonepreview_graphpage(m_graph, TEMPLATE_NONE_PREVIEW_CONTENT, TEMPLATE_NONE_PREVIEW_NLFIT_HINTS);
		load_text_for_nonepreview_graphpage(m_gpResidual, TEMPLATE_NONE_PREVIEW_CONTENT, TEMPLATE_NONE_PREVIEW_NLFIT_HINTS);
		return true;
	}
	
	///Arvin 10/31/07 PFM_NEED_REMOVE_FIT_CURVE_PLOTS_FROM_PREVIEW
	//if(nExecCtxt >=FITPREVIEW_INIT)
	///Arvin 11/06/07 QA70-10599 PREVIEW_CORRUPTTED_WHEN_REPLICA_CHANGES
	//if(nExecCtxt >=FITPREVIEW_INIT && nExecCtxt < FITPREVIEW_REMOVE_FITS)
	///Kyle 09/28/08 CHECK_IF_NEED_TO_CLEAN_LAYERS
	bool bCleanLayer = FITPREVIEW_CLEAN_LAYER & dwUpdateBits;
	dwUpdateBits &= ~FITPREVIEW_CLEAN_LAYER;
	///End CHECK_IF_NEED_TO_CLEAN_LAYERS
	///Sophy 10/28/2008 SHOULD_REARRANGE_LAYERS_WHEN_SWITCH_BETWEEN_SINGLE_INDEP_N_DEP_AND_MULTI_IDEP_N_DEP
	//bool bInitOrRe = (dwUpdateBits == FITPREVIEW_INIT || dwUpdateBits == FITPREVIEW_REINIT);
	bool bInitOrRe = (dwUpdateBits & FITPREVIEW_INIT || dwUpdateBits & FITPREVIEW_REINIT);
	///end SHOULD_REARRANGE_LAYERS_WHEN_SWITCH_BETWEEN_SINGLE_INDEP_N_DEP_AND_MULTI_IDEP_N_DEP
	if(bInitOrRe)
	///end PREVIEW_CORRUPTTED_WHEN_REPLICA_CHANGES
	///end 	PFM_NEED_REMOVE_FIT_CURVE_PLOTS_FROM_PREVIEW
	{
		if(bCleanLayer)					///Kyle 09/28/08 CHECK_IF_NEED_TO_CLEAN_LAYERS
			cleanGraphLayer(m_gpResidual, true);
		if(!m_bExternalPreview)
		{
			cleanGraphLayer(m_graph, true);
			
			/// Iris NLF_81, will do ResetSourcePlotUIDs in plotSourceCurves()
			/*
			//If all source data from graph should not reset plot UID
			/// Hong 05/30/08 QA80-11629 FIX_FAIL_GET_SOURCE_PLOT_WHEN_GENERATE_REPORT_WHEN_CONVERGE
			//if( !nlfitSessionBase.IsAllSrcDataFromGraph() )
			bool	bMultipleDimensionFit = NLFIT_XYZ_FITTING == m_pNLFSession->GetFitType() || NLFIT_MATRIX_FITTING == m_pNLFSession->GetFitType();
			if( !m_pNLFSession->IsAllSrcDataFromGraph() && !bMultipleDimensionFit )
			/// end FIX_FAIL_GET_SOURCE_PLOT_WHEN_GENERATE_REPORT_WHEN_CONVERGE
				m_pNLFSession->ResetPlotUID(); ///Cheney 2007-10-30 IF_FUNC_CHANGE_NO_SOURCE_CURVE
			*/
			///end NLF_81
			
			/// Iris NLF_81
			//PlotSourceCurves(dr, drSrc, pPreviewCtrlInfo, nlfitSessionBase);			
			plotSourceCurves();
			///end NLF_81
		}
		///Sophy 9/12/2008 FIX_PA_PREVIEW_FAIL_TO_PLOT_FIT_CURVE
		else // Sophy, if source is from graph( say, PA fit preview ), though needn't plot source, should keep its UID for later use
		{
			int			nNumDataset = m_pNLFSession->GetNumDataset();
			DWORD		dwPlotUID;
			ResetSourcePlotUIDs();
			for( int iDataset = 0; iDataset < nNumDataset; iDataset++ )
				SetSourcePlotUID( m_pNLFSession->GetSourcePlotUID( iDataset ) );
		}
		///end FIX_PA_PREVIEW_FAIL_TO_PLOT_FIT_CURVE
	}

	///Arvin 11/06/07 QA70-10599 PREVIEW_CORRUPTTED_WHEN_REPLICA_CHANGES
	///Sophy 11/24/2008 v8.978c QA80-12643 SHOULD_NOT_ALWAYS_RESCALE_SCALE_IN_NLFIT_BY_FITTED_CURVES_RANGE
	//bool bRemoveFits = (dwUpdateBits & FITPREVIEW_REMOVE_FITS) && (m_vnFitPlotIndex.GetSize() > 0);
	bool bRemoveFits = (dwUpdateBits & FITPREVIEW_REMOVE_FITS || dwUpdateBits & FITPREVIEW_REPLICA_UPDATE) && (m_vnFitPlotIndex.GetSize() > 0);
	///end SHOULD_NOT_ALWAYS_RESCALE_SCALE_IN_NLFIT_BY_FITTED_CURVES_RANGE
	///Sophy 9/18/2008 FIX_PA_UNDO_PREVIEW_GRAPH_NOT_UPDATED
	//if(bRemoveFits && !m_bExternalPreview)
	//{
		//if(!m_bExternalPreview)
		//{
			////we need clean previous fit plots 
			//cleanPlots(m_graph, m_vnFitPlotIndex[0]);
		//}
		////cleanPlots(m_gpResidual);///Sophy KEEP_OLD_LOGIC moved out of if_statement
		//else //bRemoveFits && m_bExternalPreview
			//removeFitCurves();
	//}
	if( bRemoveFits && !m_bExternalPreview )
	{
		cleanPlots(m_graph, m_vnFitPlotIndex[0]);
		m_vnFitPlotIndex.SetSize(0);	///Sophy 11/1/2008 IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
	}
	else if( bRemoveFits )
		///Sophy 11/1/2008 v8.0964c FIX_NLEND_FAIL_CREATE_FIT_CURVE_IN_SRC_GRAPH
		//removeFitCurves();
		///Sophy 11/6/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
		//RemoveFitCurves();
	{
		RemoveFitCurves();
		RemovePeakLabels();
	}
		///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
		///end FIX_NLEND_FAIL_CREATE_FIT_CURVE_IN_SRC_GRAPH
	///end FIX_PA_UNDO_PREVIEW_GRAPH_NOT_UPDATED
	if( bRemoveFits )
		cleanPlots( m_gpResidual );///Sophy KEEP_OLD_LOGIC
	
	///Sophy 11/24/2008 v8.978c QA80-12643 SHOULD_NOT_ALWAYS_RESCALE_SCALE_IN_NLFIT_BY_FITTED_CURVES_RANGE
	//bool bPlotFits = (bInitOrRe || dwUpdateBits & FITPREVIEW_REPLOT);
	bool bPlotFits = (bInitOrRe || dwUpdateBits & FITPREVIEW_REPLOT || dwUpdateBits & FITPREVIEW_REPLICA_UPDATE);
	///end SHOULD_NOT_ALWAYS_RESCALE_SCALE_IN_NLFIT_BY_FITTED_CURVES_RANGE
	if(bPlotFits)
	{
		updatePreviewData(dwUpdateBits);
		///Sophy 11/1/2008 IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
		//plotFitCurvesAndResidual();
		plotFitCurvesAndResidual( dwUpdateBits );
		///end IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
	}
	
	/// Hong 01/22/08 QA80-10969 ONLY_RESCALE_WHEN_INIT_REINIT_DIALOG_PREVIEW_PAGE
	bool bUpdateLegend = false, bRescale = false; 
	if ( bInitOrRe && !m_bExternalPreview ) // rescale NLFit dialog preview page when init or reinit
		bRescale = true;
	/// end ONLY_RESCALE_WHEN_INIT_REINIT_DIALOG_PREVIEW_PAGE
	
	if(bPlotFits)
		bUpdateLegend = true;
	
	///Jasmine 03/20/08 REMOVE_LEGEND_IN_PA_GRAPH
	if( pbUpdateLegend )
		bUpdateLegend = *pbUpdateLegend;
	///End REMOVE_LEGEND_IN_PA_GRAPH	

	///Sophy 2/16/2009 v8.0979b QA80-13121 CUSTOM_LEGEND_NEED_SIMPLER_LINE_SUPPORT
	if ( m_pNLFSession->GetFitType() != NLFIT_GENERAL_XY_FITTING )
		bUpdateLegend = false;
	///end CUSTOM_LEGEND_NEED_SIMPLER_LINE_SUPPORT
	///Sophy 7/11/2008 CONTROL_WHETHER_TO_SHOW_PREVIEW
	/*
	updateLegendAndRescale(m_graph, bUpdateLegend, bRescale, true);
	updateLegendAndRescale(m_gpResidual, bUpdateLegend, bRescale, false);	
	*/
	if(isShowPreviewGraph(false)) //fit curve
		///Sophy 11/11/2008 v8.968 QA80-10599-P1 NLFIT_PREVIEW_UPDATE_CLEANUP
		//updateLegendAndRescale(m_graph, bUpdateLegend, bRescale, true);
		updateLegendAndRescale(m_graph, bUpdateLegend, bRescale, true, true );
		///end NLFIT_PREVIEW_UPDATE_CLEANUP
	if(isShowPreviewGraph(true)) //residual
		///Sophy 11/11/2008 v8.968 QA80-10599-P1 NLFIT_PREVIEW_UPDATE_CLEANUP
		//updateLegendAndRescale(m_gpResidual, bUpdateLegend, bRescale, false);
		updateLegendAndRescale(m_gpResidual, bUpdateLegend, bRescale, false, false );
		///end NLFIT_PREVIEW_UPDATE_CLEANUP
	///end CONTROL_WHETHER_TO_SHOW_PREVIEW
	return true;
}

///Kyle 01/19/2009 QA80-12976 JUST_UPDATE_SOURCE_LAYER_IF_FROM_GRAPHLAYER
void 	NLFitPreviewCtrlBase::updateLegendAndRescale(GraphLayer& gl, bool bUpdateLegend, bool bRescale, bool bCopyForamtFromSource, bool bFitCurveGraph )
{
	if(!gl)
		return;

	if( bCopyForamtFromSource )
		GetNLFCurvesObject()->CopyFormatFromSourceGraph( gl );
	
	if( bUpdateLegend )
		GetNLFCurvesObject()->UpdateLegend( gl );
	
	if( bRescale )
		GetNLFCurvesObject()->Rescale( gl, bFitCurveGraph );
}
///End JUST_UPDATE_SOURCE_LAYER_IF_FROM_GRAPHLAYER

///Sophy 11/11/2008 v8.968 QA80-10599-P1 NLFIT_PREVIEW_UPDATE_CLEANUP
//void 	NLFitPreviewCtrlBase::updateLegendAndRescale(GraphPage& gp, bool bUpdateLegend, bool bRescale, bool bCopyForamtFromSource)
void 	NLFitPreviewCtrlBase::updateLegendAndRescale(GraphPage& gp, bool bUpdateLegend, bool bRescale, bool bCopyForamtFromSource, bool bFitCurveGraph )
///end 
{
	///Kyle 01/19/2009 QA80-12976 JUST_UPDATE_SOURCE_LAYER_IF_FROM_GRAPHLAYER
	GraphPage gpSrc = m_pNLFSession->GetSrcGraphPage();
	if(gp == gpSrc)
	{
		int nDataset = m_pNLFSession->GetNumDataset();
		for(int nDataIndex = 0; nDataIndex < nDataset; nDataIndex ++ )
		{
			GraphLayer gl;
			m_pNLFSession->GetSourceGraphLayer(gl, nDataIndex);
			if(!gl)
				return;
			///Kyle 02/10/2009 QA80-12976 NOT_DO_FORMAT_COPY_IF_THE_CURRENT_PAGE_IS_THE_SOURCE
			//updateLegendAndRescale(gl, bUpdateLegend, bRescale, bCopyForamtFromSource, bFitCurveGraph);
			updateLegendAndRescale(gl, bUpdateLegend, bRescale, false, bFitCurveGraph);
			///End NOT_DO_FORMAT_COPY_IF_THE_CURRENT_PAGE_IS_THE_SOURCE
		}
		return;
	}
	///End JUST_UPDATE_SOURCE_LAYER_IF_FROM_GRAPHLAYER
	for( int nLayer = 0; nLayer < getNeedRescaleLayerNum(gp); nLayer++ )
	{
		GraphLayer gl = gp.Layers(nLayer);
		if( !gl )
			return;
		///Kyle 01/19/2009 QA80-12976 JUST_UPDATE_SOURCE_LAYER_IF_FROM_GRAPHLAYER
		//if( bCopyForamtFromSource )
			//GetNLFCurvesObject()->CopyFormatFromSourceGraph( gl );
		//
		//if( bUpdateLegend )
			//GetNLFCurvesObject()->UpdateLegend( gl );
		//
		//if( bRescale )
			/////Sophy 11/11/2008 v8.968 QA80-10599-P1 NLFIT_PREVIEW_UPDATE_CLEANUP
			////GetNLFCurvesObject()->Rescale( gl );
			//GetNLFCurvesObject()->Rescale( gl, bFitCurveGraph );
			/////end NLFIT_PREVIEW_UPDATE_CLEANUP
		updateLegendAndRescale(gl, bUpdateLegend, bRescale, bCopyForamtFromSource, bFitCurveGraph);
		///End JUST_UPDATE_SOURCE_LAYER_IF_FROM_GRAPHLAYER
	}
}

/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////NLFitPreviewCtrl Implement//////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////

string 	NLFitPreviewCtrl::GetTemplate(bool bIsResidual)
{
	return GetNLFCurvesObject()->GetTemplate(bIsResidual);
	
}	
///Sophy 9/16/2008 CLEAN_NLFSPLITTER_FOR_81
bool	NLFitPreviewCtrl::SetFitGraphAxesTypeWithSrcGraphLayer(bool& bLogScale )
{
	GraphLayer glSrc;
	///Arvin 11/22/07 NEED_RESCALE_FOR_3D_FITTINGS
	//getSourceGraphLayer(glSrc, nlfitSessionBase);
	m_pNLFSession->GetSourceGraphLayer(glSrc);
	///end NEED_RESCALE_FOR_3D_FITTINGS
	if(!glSrc)
		return false;
	
	TreeNode trSrcSetting = glSrc.GetFormat(FPB_SCALE, FOB_SCALE, true, true);
		
	bool bLogScaletemp = true;
	int nLayers = m_graph.Layers.Count();
	for(int ii = 0; ii < nLayers; ii++)
	{
		GraphLayer gl = m_graph.Layers(ii);
		TreeNode tr = gl.GetFormat(FPB_SCALE, FOB_SCALE, true, true);
		bool bSetAxesType = false;
		if(tr.Root.Axes.X.Scale.Type.nVal != trSrcSetting.Root.Axes.X.Scale.Type.nVal)
		{
			tr.Root.Axes.X.Scale.Type.nVal = trSrcSetting.Root.Axes.X.Scale.Type.nVal;
			bSetAxesType = true;
		}
		if(tr.Root.Axes.Y.Scale.Type.nVal != trSrcSetting.Root.Axes.Y.Scale.Type.nVal)
		{
			tr.Root.Axes.Y.Scale.Type.nVal = trSrcSetting.Root.Axes.Y.Scale.Type.nVal;
			bSetAxesType = true;
		}
		
		if(bSetAxesType)
			gl.ApplyFormat(tr, FALSE, TRUE);
		if(tr.Root.Axes.X.Scale.Type.nVal != FIT_CURVE_UNIFORM_LOG)
			bLogScaletemp = false;
	}
	
	if(bLogScale != NULL)
		bLogScale = bLogScaletemp;
	return true;
}
///end CLEAN_NLFSPLITTER_FOR_81
//virtual
bool	NLFitPreviewCtrl::plotSourceCurves()
{
	/// Iris NLF_81
	//GraphLayer gl;	
	//if( !GetPreviewGraphLayer(gl, 0, false, m_nFitCurveLayer) || !gl) /// Iris NLF_81, temp codes, need to rewrite
	//	return false;	
	CleanFitCurveGraphLayer(m_nFitCurveLayer);
	ResetSourcePlotUIDs();
	///end NLF_81

	for (int ii = 0; ii < m_pNLFSession->GetNumDataset(); ii++)
		plotSourceCurvesEachDataset(ii);
	///Sophy 11/5/2008 SOURCE_CURVES_FITTED_CURVES_AND_RESIDUAL_SHOULD_GIVE_GROUPED_COLOR_ON_MULTI_DATASET
	GraphLayer gl;
	DWORD dwPlotUID;
	if( GetFitCurveGraphLayer(gl, m_nFitCurveLayer) ) //Sophy, source plot & fitted curves on same layer
	{
		DataPlot dp;
		GetSourcePlotUID( 0, &dwPlotUID );
		dp = (DataPlot)Project.GetObject( dwPlotUID );
		if( !dp )
			return false;
		if( !m_pNLFSession->GetDataObject()->IsAllSrcDataFromGraph() )
			groupDataPlots( gl, dp.GetIndex(), dp.GetIndex() + m_pNLFSession->GetNumDataset()-1, SYSCOLOR_BLACK );
	}

	///end SOURCE_CURVES_FITTED_CURVES_AND_RESIDUAL_SHOULD_GIVE_GROUPED_COLOR_ON_MULTI_DATASET
	return true;
}
///Sophy 11/5/2008 SOURCE_CURVES_FITTED_CURVES_AND_RESIDUAL_SHOULD_GIVE_GROUPED_COLOR_ON_MULTI_DATASET
bool	NLFitPreviewCtrl::groupDataPlots( GraphLayer& gl, const int nStartIndex, const int nEndIndex, int nStartColor )
{
	if( !gl )
		return false;
	
	gl.UngroupPlots( nStartIndex );
	gl.GroupPlots( nStartIndex, nEndIndex );
	DataPlot dp = gl.DataPlots( nStartIndex );
	if( dp )
		dp.SetColor( nStartColor );
	
	return true;
}
//Sophy, GraphLayer::GroupPlots fail to correctly set the increment of color after plot source curves, maybe due to template problem.
//This is a temperary solution, need support on VC level later. ///Sophy 11/7/2008 commented out, just need a proper template and this code should be discarded
//bool	NLFitPreviewCtrl::setupSourcePlots( GraphLayer& glSource, const int nStartIndex, const int nEndIndex, int nStartColor )//= SYSCOLOR_BLACK
//{
	//if( !glSource )
		//return false;
	//for( int ii = nStartIndex; ii <= nEndIndex; ii++ )
	//{
		//DataPlot dp = glSource.DataPlots(ii);
		//if( dp )
			//dp.SetColor( nStartColor + ii );
	//}
	//return true;
//}

///end SOURCE_CURVES_FITTED_CURVES_AND_RESIDUAL_SHOULD_GIVE_GROUPED_COLOR_ON_MULTI_DATASET

// to do 
/// virtual		///------ Folger 01/04/09 QA80-12962 MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
bool	NLFitPreviewCtrl::getFitDataRange(DataRange& drFit, int nDatasetIndex, int nPeak, int nPeaks, bool bIncCumulativeCurve, bool bIncPeakCurve )
{
	if(!m_FitCurvesWks.IsValid())
	{
		error_report("Found invalid m_FitCurvesWks in getFitDataRange");
		return false;
	}
	///Sophy 9/9/2008 UPDATE_REPLICA_PREVIEW_FOR_NLF_81
	/*
	int nXCol = GetXDataColIndex(nDatasetIndex, nPeaks);
	int nYCol = GetYDataColIndex(nDatasetIndex, nPeak, nPeaks);
	
	Dataset dsTempX,  dsTempY;
	dsTempX.Attach(m_FitCurvesWks, nXCol); 
	dsTempY.Attach(m_FitCurvesWks, nYCol); 

	drFit.Add("X", m_FitCurvesWks, 0, nXCol , -1, nXCol);
	drFit.Add("Y", m_FitCurvesWks, 0, nYCol , -1, nYCol);
	*/
	Dataset dsTempX,  dsTempY;
	int nXCol;
	int nYCol;
	
	nXCol = GetXDataColIndex(nDatasetIndex, nPeaks);
	dsTempX.Attach(m_FitCurvesWks, nXCol);
	
	if( !dsTempX )
	{
		error_report("Found invalid X-Range in getFitDataRange");
		return false;
	}
	drFit.Add("X", m_FitCurvesWks, 0, nXCol , -1, nXCol);
	///Sophy 10/31/2008 GROUP_CUMULATIVE_CURVE_WITH_FITTED_CURVES if to add, add it at the end of fittedcurves
	//if(bIncCumulativeCurve)
	//{
		//nYCol = nXCol + 1;
		//dsTempY.Attach(m_FitCurvesWks, nYCol);
		//if( !dsTempY )
			//return false;
		//drFit.Add("Y", m_FitCurvesWks, 0, nYCol , -1, nYCol);
	//}
	///end GROUP_CUMULATIVE_CURVE_WITH_FITTED_CURVES
	if( nPeaks > 0 && bIncPeakCurve)
	{
		if( nPeak < 0 ) //get all peaks' range
		{
			int nPeakIndex = 0;
			for( nPeakIndex = 0; nPeakIndex < nPeaks; nPeakIndex++ )
			{
				nYCol = GetYDataColIndex(nDatasetIndex, nPeakIndex, nPeaks );
				dsTempY.Attach(m_FitCurvesWks, nYCol);
				if( !dsTempY )
					return false;
				drFit.Add("Y", m_FitCurvesWks, 0, nYCol , -1, nYCol);
			}
		}
		else //get one peak
		{
			nYCol = GetYDataColIndex(nDatasetIndex, nPeak, nPeaks);
			dsTempY.Attach(m_FitCurvesWks, nYCol);
			if( !dsTempY )
				return false;
			drFit.Add("Y", m_FitCurvesWks, 0, nYCol , -1, nYCol);
		}
	}
	///end UPDATE_REPLICA_PREVIEW_FOR_NLF_81
	///Sophy 10/31/2008 GROUP_CUMULATIVE_CURVE_WITH_FITTED_CURVES
	if(bIncCumulativeCurve)
	{
		nYCol = nXCol + 1;
		dsTempY.Attach(m_FitCurvesWks, nYCol);
		if( !dsTempY )
			return false;
		drFit.Add("Y", m_FitCurvesWks, 0, nYCol , -1, nYCol);
	}
	///end GROUP_CUMULATIVE_CURVE_WITH_FITTED_CURVES
	drFit.Add("S", NULL);
	return true;
}

bool	NLFitPreviewCtrl::getResidualDataRange(DataRange& drResidual, int nDatasetIndex, int nPeak, int nPeaks, bool bPeakFit)
{
	if(!m_wksResidual.IsValid())
	{
		error_report("Found invalid m_wksResidual in getResidualDataRange");
		return false;
	}
	
	int nXCol = GetXDataColIndex(nDatasetIndex, nPeaks);
	///Kyle 10/08/08 GET_Y_DATA_COLUMN_INDEX_FOR_RESIDUAL
	//int nYCol;
	//if( nPeaks == 1)
		//nYCol = GetYDataColIndex(nDatasetIndex, 0, nPeaks);
	//else
		//nYCol = nXCol + 1;
	int nYCol = GetResidualYDataColIndex(nDatasetIndex, 0, nPeaks);
	///End GET_Y_DATA_COLUMN_INDEX_FOR_RESIDUAL
	
	Dataset dsTempX,  dsTempY;
	dsTempX.Attach(m_wksResidual, nXCol);
	dsTempY.Attach(m_wksResidual, nYCol);
	
	if(dsTempX && dsTempY)
	{
		drResidual.Add("X", m_wksResidual, 0, nXCol , -1, nXCol);
		drResidual.Add("Y", m_wksResidual, 0, nYCol , -1, nYCol);
		drResidual.Add("S", NULL); 
	}
	else
		return false;
	
	return true;	
}
///end NLF_81

//virtual
///Sophy 11/1/2008 IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
//int	NLFitPreviewCtrl::plotFitCurvesAndResidual()
int	NLFitPreviewCtrl::plotFitCurvesAndResidual( DWORD dwUpdateBits )
///end IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
{	
	int nRet = 0;
	///Sophy 11/1/2008 IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
	//m_vnFitPlotIndex.SetSize(m_pNLFSession->GetNumDataset()); 
	int nOldSize = m_vnFitPlotIndex.GetSize();
	m_vnFitPlotIndex.SetSize(m_pNLFSession->GetNumDataset()); 
	int nNewSize = m_vnFitPlotIndex.GetSize();
	for( int ii = nOldSize; ii < nNewSize; ii++ )
		m_vnFitPlotIndex[ii] = NUM_INVALID_PLOT_INDEX; //-2 stands for invalid plot index
	///end IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE

	int 	nDeps, nIndeps;
	if(!m_pNLFSession->GetNumVars(&nDeps, &nIndeps))
		return nRet;
	if( nDeps > 1 || nIndeps > 1 )
	{
		if( plotFitCurvesForMultiDepsMultiIndeps() )
			nRet++;//return false;
		if( plotResidualForMultiDepsMultiIndeps() )
			nRet++;
		return nRet;
	}
	///Sophy 11/1/2008 IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
	//if(plotFitAndResidualForSingileDepsIndeps())
	if(plotFitAndResidualForSingileDepsIndeps(dwUpdateBits))
	///end IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
		nRet = 2;//fit and residual
	
	return nRet;
}

/// Iris NLF_81, will do plot setup in NLFCurvesBase
/*
bool	NLFitPreviewCtrl::setupPlotStyles(GraphLayer& gl, int nPlot1Index, int nPlotLastIndex, bool bGroup, int nLayer, int nColor, int* pnCumulateIndex, int* pnBaseline)
{
	if(!gl)
		return false;

	if(bGroup)
	{
		gl.UngroupPlots(nPlot1Index);
		gl.GroupPlots(nPlot1Index, nPlotLastIndex);
	}
		
	DataPlot dp = gl.DataPlots(nPlot1Index);
	if(dp)
		dp.SetColor(nColor);
	return true;
}
*/
///end NLF_81


bool	NLFitPreviewCtrl::plotSourceCurvesEachDataset(int nDatasetIndex)
{
	/// Iris NLF_81, from logic, should be source plot uid from source graph in case input got from graph, or from preview graph in case input got from worksheet
	//DWORD dwPlotUID = m_pNLFSession->GetSourcePlotUID(nDatasetIndex);	
	///end NLF_81
	
	//when multi x and multi y fitting, will has more than 1 layer for preview
	//will add duplicate data plot
	/// Iris NLF_81
	//if(dwPlotUID != 0)
	///Sophy 12/23/2008 v8.0990 QA80-12832 SUPPORT_MULTI_DATASET_FOR_MULTI_INDEPS_AND_DEPS_FITTING
	int nDeps, nIndeps;
	if(!m_pNLFSession->GetNumVars(&nDeps, &nIndeps))
		return false;
	///end SUPPORT_MULTI_DATASET_FOR_MULTI_INDEPS_AND_DEPS_FITTING
	
	DWORD 	dwPlotUID;
	///Sophy 12/23/2008 v8.0990 QA80-12832 SUPPORT_MULTI_DATASET_FOR_MULTI_INDEPS_AND_DEPS_FITTING
	//if( GetSourcePlotUID(nDatasetIndex, &dwPlotUID) )
	if( GetSourcePlotUID(nDatasetIndex * (nDeps * nIndeps) + nDatasetIndex, &dwPlotUID) )
	///end SUPPORT_MULTI_DATASET_FOR_MULTI_INDEPS_AND_DEPS_FITTING
	///end NLF_81	
	{
		GraphLayer 	gl;
		/// Iris NLF_81
		//if(!GetPreviewGraphLayer(gl, nIndex, false, m_nFitCurveLayer))
		if(!GetFitCurveGraphLayer(gl, m_nFitCurveLayer))
		///end NLF_81
			return error_report("In NLFitPreviewCtrl::plotSourceCurvesEachDataset, fail to get fit curve preivew layer");
	
		DataPlot dp;
		dp = Project.GetObject(dwPlotUID);
		
		if(!dp.IsValid())
			return true;
		
		int 	nPlotType = dp.GetPlotType(); 		
		int 	nPlot = gl.AddPlot(dp, ADDPLTPFROMPLT_ADD_EVEN_IF_DATASET_PRESENT | ADDPLTPFROMPLT_ERRORBAR);
		SetSourcePlotInfo(nPlot, nDatasetIndex, m_pNLFSession->GetNumDataset());
		/// Iris NLF_81, to do 
		//if(m_pNLFSession->IsAllSrcDataFromGraph())
		//	SetPlotFormatfromSrcPlot(dp, nPlot, gl);
		///end NLF_81
		
		return true;
	}	
	///end NLF_81
	
	///Sophy 12/23/2008 v8.0990 QA80-12832 SUPPORT_MULTI_DATASET_FOR_MULTI_INDEPS_AND_DEPS_FITTING
	//int nDeps, nIndeps; //Sophy, move to the beginning of this function
	//if(!m_pNLFSession->GetNumVars(&nDeps, &nIndeps))
		//return false;
	///end SUPPORT_MULTI_DATASET_FOR_MULTI_INDEPS_AND_DEPS_FITTING
	
	///Sophy 12/23/2008 v8.0990 QA80-12832 SUPPORT_MULTI_DATASET_FOR_MULTI_INDEPS_AND_DEPS_FITTING
	//int 		nLayer = 0;
	int 		nLayer;
	if ( 1 < nDeps || 1 < nIndeps )
		nLayer = nDatasetIndex * nDeps * nIndeps; //plot different dataset of multi deps&indeps in different layer.
	else
		nLayer = 0;
	///end SUPPORT_MULTI_DATASET_FOR_MULTI_INDEPS_AND_DEPS_FITTING
	for(int ny = 0; ny < nDeps; ny++)
	{
		for(int nx = 0; nx < nIndeps; nx++)	
		{
			GraphLayer	gl;
			if( GetFitCurveGraphLayer(gl, nLayer++) )						
			{
				///Sophy 10/24/2008 v8.960b FIX_ERROR_SOURCE_PLOT_PREVIEW_ON_MUILTI_DEP_AND_INDEP_FIT
				//int		nPlot = GetNLFCurvesObject()->PlotSourceCurve(gl, nDatasetIndex, &dwPlotUID, nx, ny);
				int		nPlot = GetNLFCurvesObject()->PlotSourceCurve(gl, nDatasetIndex, &dwPlotUID, ny, nx);
				///end FIX_ERROR_SOURCE_PLOT_PREVIEW_ON_MUILTI_DEP_AND_INDEP_FIT
				if( nPlot < 0)
					error_report("NLFCurvesBase::PlotSourceCurve fail to plot source curve");
				
				//dwPlotUID = dwPlotUID == 0? dwPlotUID+1 : dwPlotUID;/// Iris NLF_81, i do not know why if dwPlotUID == 0 then dwPlotUID+1? The logic is not correct, so commented out.
				
				SetSourcePlotInfo(nPlot, nDatasetIndex, m_pNLFSession->GetNumDataset(), nLayer);
				SetSourcePlotUID(dwPlotUID);					
			}
		}
	}	
		
	return true;
}


/// Iris NLF_81, to do 
//virtual
bool	NLFitPreviewCtrl::IsResetWksCols(DWORD dwUpdateBits)
{
	///Sophy 11/24/2008 v8.978c QA80-12643 SHOULD_NOT_ALWAYS_RESCALE_SCALE_IN_NLFIT_BY_FITTED_CURVES_RANGE	
	//if(FITPREVIEW_INIT & dwUpdateBits || FITPREVIEW_REINIT & dwUpdateBits)
	if(FITPREVIEW_INIT & dwUpdateBits || FITPREVIEW_REINIT & dwUpdateBits || FITPREVIEW_REPLICA_UPDATE & dwUpdateBits)
	///end SHOULD_NOT_ALWAYS_RESCALE_SCALE_IN_NLFIT_BY_FITTED_CURVES_RANGE
		return true;
	
	return false;
}
///end NLF_81

Worksheet*	NLFitPreviewCtrl::GetTempWks(int nWksType)
{
	Worksheet* pwks = NULL;
	switch(nWksType)
	{
	case WKS_FIT_CURVES:
		pwks = &m_FitCurvesWks;
		break;
	case WKS_RESIDUAL:
		pwks = &m_wksResidual;
		break;		
	default:
		break;		
	}

	return pwks;
}

bool 	NLFitPreviewCtrl::PrepareWks(int nWksType, DWORD dwUpdateBits)
{
	Worksheet* pwks = GetTempWks(nWksType);
	if( NULL == pwks )
		return error_report("Found NULL pwks pointer");
	
	if(!pwks->IsValid())
	{	
#ifdef IS_PREVIEW_DEBUG_MODE
		pwks->Create(NULL, CREATE_HIDDEN);
#else
		pwks->Create(NULL, CREATE_HIDDEN  | CREATE_SET_MISSING_IN_MANAGER);
#endif
		
		/// Iris NLF_81, "Temp..." worksheet name only used to indicate wks is template when not introduce CREATE_SET_MISSING_IN_MANAGER
		/*
		string strPageName;
		switch(nWksType)
		{
		case WKS_FIT_CURVES:
			strPageName = "TempNLFitCuv1";
			break;
		case WKS_RESIDUAL:
			strPageName = "TempNLFitResidual1";
			break;
		}	
		if( !strPageName.IsEmpty() )
			wks.GetPage().Rename(strPageName);
		*/
		///end NLF_81
	}
	
	if( !IsResetWksCols(dwUpdateBits) )
		return true;	
	pwks->SetSize(-1, 0); 

		
	for(int index = 0; index < m_pNLFSession->GetNumDataset(); index++)
	{
		int nColumns = NUM_DATASET_PER_FITTED_CURVE;		
		
		int		nDeps, Indeps;
		m_pNLFSession->GetNumVars(&nDeps, &Indeps);
		if(nDeps > 1 || Indeps > 1)
		{			
			nColumns = nDeps + Indeps;			
		}
		else
		{
			Indeps = 1;
			///------ Folger 01/04/09 QA80-12962 MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
			//int nPeaks = m_pNLFSession->GetNumPeaks();		
			//nColumns += nPeaks; /// Iris NLF_81, this is old logic, but + nPeaks - 1 here better I think.
			nColumns += getNumIndividualFitCurveCol(nWksType);		///------ Folger 02/01/09 PEAK_FITTING_RESIDUAL_PLOT_PREVIEW_BROKEN
			///------ End MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
		}
		
		setWksColTypeAndFormat(*pwks, nColumns, Indeps);
	}	
	return true;
}

//must reset column number and type if data number changed, function changed, replica number changed	
void    NLFitPreviewCtrl::setWksColTypeAndFormat(Worksheet& wks, int nColumns, int nXNumCols)
{
	if(nXNumCols > nColumns)
	{
		error_report("The number of X columns is large than the number of all columns");
		return;
	}
	/// Hong 12/03/08 v8.0982 SPEED_UP_NLFIT_OPEN_DLG
	int			nOldNumCols = wks.GetNumCols();
	if ( nColumns > 0 )
		wks.SetSize(-1, nColumns + nOldNumCols);
	/// end SPEED_UP_NLFIT_OPEN_DLG
	for(int ii = 0; ii < nColumns; ii++)
	{
		/// Hong 12/03/08 v8.0982 SPEED_UP_NLFIT_OPEN_DLG
		//int nCol = wks.AddCol();
		//Column 	col(wks, nCol);		
		Column 	col(wks, nOldNumCols + ii);
		ASSERT(col);
		/// end SPEED_UP_NLFIT_OPEN_DLG
		col.SetFormat(OKCOLTYPE_NUMERIC);
		
		if(ii < nXNumCols)
			col.SetType(OKDATAOBJ_DESIGNATION_X); //for default of col type is Y, so only set X type
		
		DatasetObject dobj(col);
		dobj.Info.SYSTEM.PARAMETERS.TAG$ = STR_DATASETOBJ_FITCURVE;
	}
}


/// Iris NLF_81, plotting fit curves for multiple deps / multiple indeps is diff in preview and operation, so keep this logic in preview, not in NLFCurvesBase
bool	NLFitPreviewCtrl::plotFitCurvesForMultiDepsMultiIndeps()
{
	string	strTemplate = GetNLFCurvesObject()->GetTemplate(false);
	if( 1 <= plot_combinated_xy(m_FitCurvesWks, m_graph, IDM_PLOT_LINE, SYSCOLOR_RED, true, true, strTemplate))
		return true;
	return false;
}

bool    NLFitPreviewCtrl::plotResidualForMultiDepsMultiIndeps()
{
	string	strTemplate = GetNLFCurvesObject()->GetTemplate(true);
	if( 1 <= plot_combinated_xy(m_wksResidual, m_gpResidual, IDM_PLOT_SCATTER, SYSCOLOR_RED, true, true, strTemplate))
		return true;
	return false;
}
///end NLF_81

/// Iris NLF_81
/*
void	NLFitPreviewCtrl::getFitCurve(DataRange& drFit, int nDataset, int nPeak, int nPeaks, bool bCumulativeCurve)
{
	if(!m_FitCurvesWks.IsValid())
	{
		error_report("Found invalid m_FitCurvesWks in getFitCurve ");
		return;
	}
	
	int nXCol = GetXDataColIndex(nDataset, nPeaks);
	int nYCol = GetYDataColIndex(nDataset, nPeak, nPeaks);
	
	Dataset dsTempX,  dsTempY;
	dsTempX.Attach(m_FitCurvesWks, nXCol); 
	dsTempY.Attach(m_FitCurvesWks, nYCol); 

	drFit.Add("X", m_FitCurvesWks, 0, nXCol , -1, nXCol);
	drFit.Add("Y", 
	, 0, nYCol , -1, nYCol);
	drFit.Add("S", NULL); 
}

void	NLFitPreviewCtrl::getResidual(DataRange& drResidual, int nDataset, int nPeak, int nPeaks, bool bPeakFit)
{
	int nXCol = GetXDataColIndex(nDataset, nPeaks);
	int nYCol = GetYDataColIndex(nDataset, nPeak, nPeaks);	
	
	Dataset dsTempX,  dsTempY;
	dsTempX.Attach(m_wksResidual, nXCol);
	dsTempY.Attach(m_wksResidual, nYCol);
	
	if(dsTempX && dsTempY)
	{
		drResidual.Add("X", m_wksResidual, 0, nXCol , -1, nXCol);
		drResidual.Add("Y", m_wksResidual, 0, nYCol , -1, nYCol);
		drResidual.Add("S", NULL); 
	}
}
*/
///end NLF_81

int 	NLFitPreviewCtrl::plotFitCurEachDataset(DataRange& drFit, int nDataset, GraphLayer& glFit)
{
	//if have multiple layers in current source page, need to plot fit curve to the source layer
	/// Iris NLF_81
	//if( !GetPreviewGraphLayer(glFit, nDataset, false, m_nFitCurveLayer) )
	if( !GetFitCurveGraphLayer(glFit, m_nFitCurveLayer) )
		return -1;
	///end NLF_81
	
	/// Iris NLF_81
	//int nIndex = glFit.AddPlot(drFit, IDM_PLOT_LINE);	
	/// Hong 10/17/08 QA80-10624 NLFIT_SUPPORT_FIT_SWAPPED_POLAR_PLOT
	//int nIndex = GetNLFCurvesObject()->PlotFitCurve(glFit, drFit);
	///Sophy 10/31/2008 GROUP_CUMULATIVE_CURVE_WITH_FITTED_CURVES
	//int nIndex = GetNLFCurvesObject()->PlotFitCurve(glFit, drFit, m_pNLFSession->GetDataObject());
	int nCumulativeIndex =  m_PreviewCtrlInfo.bPlotCumulativeCurve ? drFit.GetNumData(DRR_GET_DEPENDENT) - 1 : -1;
	int nIndex = GetNLFCurvesObject()->PlotFitCurve(glFit, drFit, m_pNLFSession->GetDataObject(), false, NULL, NULL, nCumulativeIndex);
	///end GROUP_CUMULATIVE_CURVE_WITH_FITTED_CURVES
	/// end NLFIT_SUPPORT_FIT_SWAPPED_POLAR_PLOT
	///end NLF_81
	return nIndex;
}

int 	NLFitPreviewCtrl::plotResidualEachDataset(DataRange& drResidual, int nDatasetIndex, GraphLayer& glResidual)
{
	///Jasmine 03/21/08 QA80-10198 SPECIFY_PREVIEW_LAYER_IN_MULTILAYER_GRAPH_FOR_SINGLE_DEPS_INDEPS
	//glResidual = m_gpResidual.Layers(0);
	if(!m_bShowResidual)			///Kyle 
		return -1;
	glResidual = m_gpResidual.Layers( m_nResidualLayer );
	///End SPECIFY_PREVIEW_LAYER_IN_MULTILAYER_GRAPH_FOR_SINGLE_DEPS_INDEPS
	if(!glResidual)
		return -1;
	
	/// Iris NLF_81
	//int nPlot = glResidual.AddPlot(drResidual, IDM_PLOT_SCATTER);
	int	nPlot = GetNLFCurvesObject()->PlotResidual(glResidual, drResidual);
	///end NLF_81
	
	return nPlot;
}
///Sophy 11/1/2008 IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
//bool	NLFitPreviewCtrl::plotFitAndResidualForSingileDepsIndeps()
bool	NLFitPreviewCtrl::plotFitAndResidualForSingileDepsIndeps( DWORD dwUpdateBits )
///end IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
{
	int 	nPeaks = m_pNLFSession->GetNumPeaks();	
	///Sophy 9/9/2008 UPDATE_REPLICA_PREVIEW_FOR_NLF_81
	/*
	/// Iris NLF_81, hard code, to do 
	//bool 	bPeakFit = pPreviewCtrlInfo->bComputeCumulativeCurve && nPeaks > 1;
	bool	bPeakFit = false;
	///end NLF_81
	*/	
	bool	bPeakFit = m_PreviewCtrlInfo.bComputeCumulativeCurve && (nPeaks > 1);
	///end UPDATE_REPLICA_PREVIEW_FOR_NLF_81
	
	//assume is not peak fit
	bool bPlotFitCurve = true;
	bool bPlotIndividualPeak = false;
	bool bPlotCumulativeCurve = false;
	int nCumPlot = -1;
	if(bPeakFit) // if peak fit
	{
		bPlotFitCurve = false;
		///Sophy 9/9/2008 UPDATE_REPLICA_PREVIEW_FOR_NLF_81
		/// Iris NLF_81,to do
		//bPlotIndividualPeak = pPreviewCtrlInfo->bPlotIndividualPeak;
		//bPlotCumulativeCurve = pPreviewCtrlInfo->bPlotCumulativeCurve;
		///end NLF_81
		bPlotIndividualPeak = m_PreviewCtrlInfo.bPlotIndividualPeak;
		bPlotCumulativeCurve = m_PreviewCtrlInfo.bPlotCumulativeCurve;
		///end UPDATE_REPLICA_PREVIEW_FOR_NLF_81
	}
	///Sophy 11/1/2008 IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE if no need to plot fitcurve should reset these booleans
	bool bInitOrReInit = (dwUpdateBits & FITPREVIEW_INIT || dwUpdateBits & FITPREVIEW_REINIT);
	bool bHasFitCurve = true;
	vector<uint> vnIndices;
	if ( m_vnFitPlotIndex.Find( vnIndices,  NUM_INVALID_PLOT_INDEX ) == m_vnFitPlotIndex.GetSize() )//all are invalid plots
		bHasFitCurve = false;
	if( bHasFitCurve )
	{
		bPlotFitCurve &=  ( !( dwUpdateBits & FITPREVIEW_REPLOT ) || bInitOrReInit );
		bPeakFit &= ( !( dwUpdateBits & FITPREVIEW_REPLOT ) || bInitOrReInit );
		bPlotIndividualPeak &= ( !( dwUpdateBits & FITPREVIEW_REPLOT ) || bInitOrReInit );
		bPlotCumulativeCurve &= ( !( dwUpdateBits & FITPREVIEW_REPLOT ) || bInitOrReInit );
	}
	///end IMPROVE_CODE_SKIP_PLOT_FITCURVE_ON_RESIDUAL_CHANGE
	int 		nResidualPlotStart = -1, nResidualPlotEnd = -1; 	
	GraphLayer 	glFit, glResidual; 
	///Sophy 2/1/2009 v8.0968b FIX_RESIDUAL_PLOTS_FAIL_TO_GROUP_CORRECTLY_WITH_MUILTI_DATASETS
	if ( m_bShowResidual )
		glResidual = m_gpResidual.Layers( m_nResidualLayer );
	if ( glResidual )
	{
		glResidual.UngroupPlots(); //Sophy, in VC level, if the plot existing plot that has been grouped, it will return the index of the first plot in the group
	}
	///end FIX_RESIDUAL_PLOTS_FAIL_TO_GROUP_CORRECTLY_WITH_MUILTI_DATASETS
	for(int nDataset = 0; nDataset < m_pNLFSession->GetNumDataset(); nDataset++)
	{
		/// Iris NLF_81
		////if(0 != m_pNLFSession->GetPlotUID(nDataset))
		if( GetSourcePlotUID(nDataset) )// !=0 means already plot source data or plot fit curve on source graph
		///end NLF_81
		{
			int 	nPlotStart = -1;				
			if( (bPeakFit && bPlotIndividualPeak) || (!bPeakFit && bPlotFitCurve) )
			{
				///Sophy 9/9/2008 UPDATE_REPLICA_PREVIEW_FOR_NLF_81
				/*
				for(int nPeak = 0; nPeak < nPeaks; nPeak++) 
				{
					DataRange drFit;		
					/// Iris NLF_81
					//getFitCurve(drFit, nDataset, nPeak, nPeaks, false);
					getFitDataRange(drFit, nDataset, nPeak, nPeaks, false);
					///end NLF_81
					
					int 	nPlot = plotFitCurEachDataset(drFit, nDataset, glFit);
					if(nPeak == 0) //get the first plot index
						m_vnFitPlotIndex[nDataset] = nPlot;
					
					if(nPlot < 0)
						return false;
					
					if(nPlotStart < 0)
						nPlotStart = nPlot;
				}
				*/
				DataRange drFit;
				///Sophy 10/31/2008 GROUP_CUMULATIVE_CURVE_WITH_FITTED_CURVES
				//if( getFitDataRange( drFit, nDataset, -1, nPeaks, false ) )
				if(  bPlotCumulativeCurve ? getFitDataRange( drFit, nDataset, -1, nPeaks, true ) : getFitDataRange( drFit, nDataset, -1, nPeaks, false ) )
				///end GROUP_CUMULATIVE_CURVE_WITH_FITTED_CURVES
				{
					nPlotStart = plotFitCurEachDataset( drFit, nDataset, glFit );
					m_vnFitPlotIndex[nDataset] = nPlotStart;
					///Sophy 10/31/2008 GROUP_CUMULATIVE_CURVE_WITH_FITTED_CURVES
					if( bPlotCumulativeCurve )
						bPlotCumulativeCurve = false; //already ploted above, no need to plot again in following code
					///end GROUP_CUMULATIVE_CURVE_WITH_FITTED_CURVES
				}
				else
					ASSERT( FALSE );
				///end UPDATE_REPLICA_PREVIEW_FOR_NLF_81
			}
			
			//consistent with report graph, plot cumulative at last
			if(bPlotCumulativeCurve) // add cumulative curve to datarange
			{
				DataRange 	drFit;
				getFitDataRange(drFit, nDataset, 0, nPeaks, true, false ); //just get cumulative, but not peakcurve
				
				nCumPlot = plotFitCurEachDataset(drFit, nDataset, glFit);
				if(!bPlotIndividualPeak)
					m_vnFitPlotIndex[nDataset] = nCumPlot;
			}
			
			DataRange drResidual;
			if( getResidualDataRange(drResidual, nDataset, 0, nPeaks, bPeakFit) )
				nResidualPlotEnd = plotResidualEachDataset(drResidual, nDataset, glResidual);
			
			if(nResidualPlotStart < 0)
				nResidualPlotStart = nResidualPlotEnd;		
			
			/// Iris NLF_81, this logic moved to NLFCurves::setupFitPlot and NLFCurves::setupResidualPlot
			/*			
			if(nPeaks > 1) 
			{
				if(bPlotIndividualPeak)
					setupPlotStyles(glFit, nPlotStart, bPlotCumulativeCurve? nPlotStart+nPeaks : nPlotStart+nPeaks-1, true, 0, SYSCOLOR_RED, bPlotCumulativeCurve? &nCumPlot : NULL, m_pNLFSession->HasBaselinePeak()? &nPlotStart : NULL);	///Jasmine 11/28/07 SET_FIT_CURVES_A_SAME_COLOR
				else
					setupPlotStyles(glFit, m_vnFitPlotIndex[nDataset], m_vnFitPlotIndex[nDataset], false, 0, SYSCOLOR_RED);
			}
			*/
			///end NLF_81
			///Sophy 11/4/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
			///Sophy 11/25/2008 v8.979 ONLY_PLOT_PEAKCENTER_LABAL_FOR_NLFIT_REPLICA
			//if( bPeakFit )
			if( bPeakFit && m_pNLFSession->GetNumberMultiplicity() > 1)
			///end ONLY_PLOT_PEAKCENTER_LABAL_FOR_NLFIT_REPLICA
				plotReplicaPeakCenterLabel( glFit );
			///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
			///Sophy 11/6/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
			else if( m_vnFitPlotIndex.GetSize() < 1 )
				removePeakLabel();
			///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
		}		
	}
	///Sophy 10/28/2008 SHOULD_REARRANGE_LAYERS_WHEN_SWITCH_BETWEEN_SINGLE_INDEP_N_DEP_AND_MULTI_IDEP_N_DEP
	//Sophy, comment out, not need to arrange preview pages here, but in cleanGraphLayer();
	///Sophy 10/24/2008 SHOULD_REARRANGE_LAYERS_WHEN_SWITCH_BETWEEN_SINGLE_INDEP_N_DEP_AND_MULTI_IDEP_N_DEP
	//if( glFit )
	//{
		//int nFitLayers = glFit.GetPage().Layers.Count();
		//if( nFitLayers < 2 )
			//page_arrange_layers( (GraphPage)glFit.GetPage(), 1, 1 );
	//}
	//if( glResidual ) ///Sophy, for pa may not have residual preview
	//{
		//int nResidualLayers = glResidual.GetPage().Layers.Count();
		//if( nResidualLayers <=2 )
			//page_arrange_layers( (GraphPage)glResidual.GetPage(), 1, 1 );
	//}
	///end SHOULD_REARRANGE_LAYERS_WHEN_SWITCH_BETWEEN_SINGLE_INDEP_N_DEP_AND_MULTI_IDEP_N_DEP
	///Sophy 11/5/2008 SOURCE_CURVES_FITTED_CURVES_AND_RESIDUAL_SHOULD_GIVE_GROUPED_COLOR_ON_MULTI_DATASET
	if( bPlotFitCurve && glFit && m_vnFitPlotIndex.GetSize() > 0 ) // group all fit curve if no peak fit
	{
		groupDataPlots( glFit, m_vnFitPlotIndex[0], m_vnFitPlotIndex[m_vnFitPlotIndex.GetSize() - 1], SYSCOLOR_RED );
	}
	groupDataPlots(glResidual, nResidualPlotStart, nResidualPlotEnd, SYSCOLOR_RED );
	///end SOURCE_CURVES_FITTED_CURVES_AND_RESIDUAL_SHOULD_GIVE_GROUPED_COLOR_ON_MULTI_DATASET
	/// Iris NLF_81, this logic moved to NLFCurves::setupFitPlot and NLFCurves::setupResidualPlot
	/*
	if(bPlotFitCurve && glFit && m_vnFitPlotIndex.GetSize() > 0 ) //guoup plot all fit curve if not peak fit
	{
		int nPos = m_vnFitPlotIndex.GetSize()-1;
		setupPlotStyles(glFit, m_vnFitPlotIndex[0], m_vnFitPlotIndex[nPos], true, 0, SYSCOLOR_RED);
	}

	setupPlotStyles(glResidual, nResidualPlotStart, nResidualPlotEnd, true, 0, SYSCOLOR_RED);
	*/
	///end NLF_81
	return true;
}

///Sophy 9/27/2008 MOVE_PREVIEW_ONDESTROY_CODE_TO_DESTRUCTOR
/*
void	NLFitPreviewCtrl::OnDestroy()
{
	/// Hong 03/31/08 QA80-10969 v8.0834c FIX_LEGEND_NOT_UPDATE_WHEN_END_NLFIT_DIALOG
	//NLFitPreviewCtrlBase::OnDestroy();
	/// end FIX_LEGEND_NOT_UPDATE_WHEN_END_NLFIT_DIALOG
#ifndef IS_PREVIEW_DEBUG_MODE
	if(m_FitCurvesWks)
		m_FitCurvesWks.Destroy();
	if(m_wksResidual)
		m_wksResidual.Destroy();
#endif //IS_PREVIEW_DEBUG_MODE
		
	/// Hong 03/31/08 QA80-10969 v8.0834c FIX_LEGEND_NOT_UPDATE_WHEN_END_NLFIT_DIALOG
	NLFitPreviewCtrlBase::OnDestroy();
	/// end FIX_LEGEND_NOT_UPDATE_WHEN_END_NLFIT_DIALOG
}
*/
///end MOVE_PREVIEW_ONDESTROY_CODE_TO_DESTRUCTOR

///------ Folger 01/04/09 QA80-12962 MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
///virtual
int		NLFitPreviewCtrl::getNumIndividualFitCurveCol(int nWksType/* = WKS_FIT_CURVES*/)
{
	return m_pNLFSession->GetNumPeaks();
}
///------ End MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA

//virtual
bool 	NLFitPreviewCtrl::updatePreviewData(DWORD dwUpdateBits)
{
	PrepareWks(WKS_FIT_CURVES, dwUpdateBits);		
	PrepareWks(WKS_RESIDUAL, dwUpdateBits);
	
	///Sophy 11/20/2008 QA80-10599-P6 FIX_FITCURVE_GRAPH_AXES_RESCALE_PROBLEM
	GetNLFCurvesObject()->ResetFitCurvesScaleRange();
	///end FIX_FITCURVE_GRAPH_AXES_RESCALE_PROBLEM
	int 	nDeps, nIndeps;
	if(!m_pNLFSession->GetNumVars(&nDeps, &nIndeps))
		return false;	

	for(int nDatasetIndex = 0; nDatasetIndex < m_pNLFSession->GetNumDataset(); nDatasetIndex++)
	{
		GraphLayer glSource;
		if( m_pNLFSession->GetSourceGraphLayer(glSource, nDatasetIndex) )
		{
			GetNLFCurvesObject()->SetSrcFromAndTo(glSource, nDatasetIndex);
		}
		
		if(nDeps > 1 || nIndeps > 1)
		{
			if(!updateFitCurveDataForMultiDepsIndeps( nIndeps, nDeps, nDatasetIndex ))
				return false;
			
			updateResidualDataForMultiDepsIndeps( nIndeps, nDeps, nDatasetIndex );
		}
		else
			updateFitAndResidulDataForSingleDepsIndeps(nDatasetIndex);
	}
	
	return true;
}
///Sophy 10/24/2008 SUPPORT_MUILTI_INDEP_AND_DEP_PREVIEW_FOR_NLFIT_81 clean code, as NLFCurves' code is ready now.
bool	NLFitPreviewCtrl::updateFitCurveDataForMultiDepsIndeps( const int& nIndeps, const int& nDeps, const int& nDataIndex )
{

	matrix mFitXs, mFitYs;
	
	if( !GetNLFCurvesObject()->GetFitX( mFitXs, m_pNLFSession->GetDataObject(), nDataIndex, nIndeps ) )
		return false;	
	
	if( !GetNLFCurvesObject()->GetFitY( mFitXs, mFitYs, m_pNLFSession->GetNLParamsMngr(), nDataIndex, nDeps ) )
		return false;
	
	int nCol = nDataIndex * (mFitXs.GetNumCols() + mFitYs.GetNumCols());
	for(int nx = 0; nx < mFitXs.GetNumCols(); nx++)
	{		
		vector	vec;
		mFitXs.GetColumn(vec, nx);
		
		Dataset ds(m_FitCurvesWks, nCol++);
		if( ds )
			ds = vec;
		else
			return error_report("Get error when put fit X data into m_FitCurvesWks");
		
		/// Iris NLF_81, ///Sophy, range rescale now done in NLFCurves.
		//SetRescaleRange(vec, m_vFitXMin, m_vFitXMax); 
		///end NLF_81
		///Sophy 11/20/2008 QA80-10599-P6 FIX_FITCURVE_GRAPH_AXES_RESCALE_PROBLEM
		GetNLFCurvesObject()->SetFitCurveScaleRange(vec, false); //set x scale minmax
		///end FIX_FITCURVE_GRAPH_AXES_RESCALE_PROBLEM
	}
	
	for(int ny = 0; ny < mFitYs.GetNumCols(); ny++)
	{		
		vector	vec;
		mFitYs.GetColumn(vec, ny);
		
		Dataset ds(m_FitCurvesWks, nCol++);
		if( ds )
			ds = vec;
		else
			return error_report("Get error when put fit Y data into m_FitCurvesWks");
		
		/// Iris NLF_81, ///Sophy, range rescale now done in NLFCurves.
		//SetRescaleRange(vec, m_vFitYMin, m_vFitYMax);
		///end NLF_81
		///Sophy 11/20/2008 QA80-10599-P6 FIX_FITCURVE_GRAPH_AXES_RESCALE_PROBLEM
		GetNLFCurvesObject()->SetFitCurveScaleRange(vec, true); //set y scale minmax
		///end FIX_FITCURVE_GRAPH_AXES_RESCALE_PROBLEM
	}
	return true;
}

bool		NLFitPreviewCtrl::updateResidualDataForMultiDepsIndeps( const int& nIndeps, const int& nDeps, const int& nDataIndex )
{
	matrix mFitXs, mFitYs;
	
	if( !GetNLFCurvesObject()->GetFitX( mFitXs, m_pNLFSession->GetDataObject(), nDataIndex, nIndeps, false ) )
		return false;	
	
	if( !GetNLFCurvesObject()->GetFitY( mFitXs, mFitYs, m_pNLFSession->GetNLParamsMngr(), nDataIndex, nDeps ))
		return false;
	
	int nYBegin = nDataIndex * (nIndeps + nDeps) + nIndeps;
	int nYEnd 	= nYBegin + nDeps - 1;
	
	matrix mInputYs;
	for(int ii = nYBegin, jj = 0; ii <= nYEnd; ii++, jj++)
	{
		vector vData;
		m_pNLFSession->GetInputData(vData, true, nDataIndex, jj );		
		if(vData.GetSize() <= 0)
			return false;
		
		
		if(ii == nYBegin)
			mInputYs.SetSize(vData.GetSize(), nYEnd - nYBegin + 1);
		
		mInputYs.SetColumn(vData, jj);
	}	
	mInputYs -= mFitYs;
	
	int nRows = mInputYs.GetNumRows();
	int nCols = nIndeps + nDeps;
	matrix mResidul(nRows, nCols);
	
	mResidul.SetSubMatrix(mFitXs);
	mResidul.SetSubMatrix(mInputYs, mFitXs.GetNumCols());
	
	int nColBegin 	= nDataIndex * (nIndeps + nDeps);
	int nColEnd 	= nYEnd;
	for(ii = nColBegin, jj = 0; ii <= nColEnd; ii++, jj++)
	{
		if(ii == nColBegin)
		{
			Column col(m_wksResidual, ii);	
			setFitColumnLongName(col, "", nDataIndex + 1, m_pNLFSession->GetNumDataset());
		}
		
		vector vec;
		mResidul.GetColumn(vec, jj);
		Dataset ds(m_wksResidual, ii);
		if( ds )
			ds = vec;
		else
			return error_report("Get error when put residual data into m_wksResidual");

	}
	
	return true;
}
///end SUPPORT_MUILTI_INDEP_AND_DEP_PREVIEW_FOR_NLFIT_81
bool	NLFitPreviewCtrl::updateFitAndResidulDataForSingleDepsIndeps(int nDatasetIndex)

{
	int 	nPeaks = m_pNLFSession->GetNumPeaks();
	int		nXCol = GetXDataColIndex(nDatasetIndex, nPeaks);
	
	if(!m_FitCurvesWks || m_FitCurvesWks.GetNumCols() <= nXCol + 1)
		return error_report("updateFitAndResidulDataForSingleDepsIndeps found m_FitCurvesWks not prepared");
	
	m_FitCurvesWks.Columns(nXCol + 1).SetLongName(_L("Cumulative Peak Fit"));
	m_wksResidual.Columns(nXCol + 1).SetLongName(_L("Cumulative Residual"));
	
	Dataset dsX(m_FitCurvesWks, nXCol);
	Dataset dsCumulativeFit(m_FitCurvesWks, nXCol + 1);
	vector	vFitYbyInput, vFitY; 
	/// Hong 10/28/08 v8.0962 MORE_ERROR_CHECKING
	if ( !dsX )		
		return error_report("Fit curve data is not ready");
	/// end MORE_ERROR_CHECKING

	
	vector vInX, vInY;
	m_pNLFSession->GetInputData(vInX, vInY, NULL, nDatasetIndex);
	
	if( 0 == vInX.GetSize() ||  0 == vInY.GetSize())
		return false;
	
	int nResidualYCol = nXCol + 1;
	///Sophy 9/9/2008 UPDATE_REPLICA_PREVIEW_FOR_NLF_81
	/*
	//bool bComputeCumuFitCurve = pPreviewCtrlInfo->bComputeCumulativeCurve;
	//bool bHasBaselinePeak = nlfitSessionBase.HasBaselinePeak();///Jasmine 11/14/07 FIT_BASELINE_AS_WELL_AS_OTHER_PEAKS
	*/
	bool bComputeCumuFitCurve = m_PreviewCtrlInfo.bComputeCumulativeCurve;
	///Kyle 10/21/08 CHANGE_FUNCTION_NAME_HASBASELINEPEAK_TO_GETBASELINEFITMODE
	//bool	bHasBaselinePeak = m_pNLFSession->HasBaselinePeak();
	bool	bHasBaselinePeak = m_pNLFSession->GetBaselineFitMode();
	///End CHANGE_FUNCTION_NAME_HASBASELINEPEAK_TO_GETBASELINEFITMODE
	///end UPDATE_REPLICA_PREVIEW_FOR_NLF_81
	
	//--Sandy 2008-12-17 ADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW
	//bool bHideProgressBox = (nPeaks < NLFIT_NUM_PEAKS_THRESHOLD_TO_SHOW_PROGRESSBOX && vInX.GetSize()< NLFIT_DATA_POINTS_THRESHOLD_TO_SHOW_PROGRESSBOX);
	bool bHideProgressBox = (nPeaks <= 1 || (nPeaks < NLFIT_NUM_PEAKS_THRESHOLD_TO_SHOW_PROGRESSBOX && vInX.GetSize()< NLFIT_DATA_POINTS_THRESHOLD_TO_SHOW_PROGRESSBOX));///Sandy 2009-1-23 If only one peak, no need to show progress box
	string strTitle = _L("Preparing Preview Data.....");
	string strTips;
	/// Kenny 12/24/2009 QA81-14875-P2 PROGRESS_BAR_IN_BUILTIN_TOOL_SHOULD_NOT_KEEP_TOPMOST
	//progressBox pb("", PBOX_TOPMOST, bHideProgressBox);
	progressBox pb("", PBOX_DEFAULT_STYLE, bHideProgressBox);
	/// End QA81-14875-P2 PROGRESS_BAR_IN_BUILTIN_TOOL_SHOULD_NOT_KEEP_TOPMOST
	pb.SetText(strTitle, PBOXT_TITLE);
	pb.SetRange(0,nPeaks);
	string str;
	//--end ADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW
	
	int nPeakOffset = bHasBaselinePeak? 0 : 1;
	for(int nPeak = 0; nPeak < nPeaks; nPeak++)
	{			
	
		//--Sandy 2008-12-17 ADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW
        strTips.Format(_L("Preparing preview data, current peak = %d......"), nPeak);
        if(pb.Set(nPeak))
        {
            pb.SetText(strTips, PBOXT_MIDCENTER);
        }
        else
        {
            //out_str("User abort!");
            //break;
            return error_report("User abort!");
        }
        //--end ADD_PROGRESSBOX_AND_GIVE_USER_FEEDBACK_AND_CANCEL_WHEN_THE_PROGRESS_SLOW
        
		if( m_pNLFSession->GetNumDataset()>1 && nPeaks>1 )
			return error_report("Not support Mutliple dataset and multiple peaks just now");
		
		nXCol = GetXDataColIndex(nDatasetIndex, nPeaks, nPeak);		///------ Folger 01/04/09 QA80-12962 MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
		int nYCol = GetYDataColIndex(nDatasetIndex, nPeak, nPeaks);
		
		// setup column long name according to data
		string strColName;
		//strColName = nMultiplicity > 1 ? _L("FitPeak") : _L("Fit Curve")+ " " + ftoa(nDatasetIndex+1);
		if(nPeaks > 1)
			strColName = (bHasBaselinePeak && 0 == nPeak)? _L("Baseline") : _L("Fit Peak");///Jasmine 11/14/07 FIT_BASELINE_AS_WELL_AS_OTHER_PEAKS
		else
			strColName = _L("Fit Curve")+ " " + ftoa(nDatasetIndex+1);
		
		if(0 == nPeak)
		{
			int nYFrom = nYCol;
			Column colY(m_FitCurvesWks, nYFrom);
			setFitColumnLongName(colY, strColName, nDatasetIndex, m_pNLFSession->GetNumDataset(), nPeak, bHasBaselinePeak? 0 : nPeaks, false, nPeakOffset);
		}
		else
		{
			Column colY(m_FitCurvesWks, nYCol);	
			setFitColumnLongName(colY, strColName, nDatasetIndex, m_pNLFSession->GetNumDataset(), nPeak, nPeaks, false, nPeakOffset);	
		}
		
		// calc Fit X and Fit Y
		dsX.Attach(m_FitCurvesWks, nXCol);		///------ Folger 01/04/09 QA80-12962 MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
		Dataset dsY(m_FitCurvesWks, nYCol);
		/// Hong 10/28/08 v8.0962 MORE_ERROR_CHECKING
		if ( !dsY )		
			return error_report("Fit curve data is not ready");
		/// end MORE_ERROR_CHECKING
		
		///------ Folger 01/04/09 QA80-12962 MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
		/*
		/// Iris NLF_81
		//m_pNLFSession->GetFit(dsX, dsY, nDatasetIndex, nPeak); 
		//GetNLFCurvesObject()->GetFitX(dsX, m_pNLFSession->GetDataObject(), nDatasetIndex);
		//GetNLFCurvesObject()->GetFitY(dsX, dsY, m_pNLFSession->GetNLParamsMngr(), nDatasetIndex, nPeak);
		GetNLFCurvesObject()->GetFit( dsX, dsY, nDatasetIndex, nPeak );
		///end NLF_81
		*/
		SmartXOnPeakShapeOption		stSmartXOpt;
		bool						bSmartX = GetNLFCurvesObject()->CheckGetSmartXOnPeakShapeOption(stSmartXOpt, nPeak);
		GetNLFCurvesObject()->GetFit( dsX, dsY, nDatasetIndex, nPeak, bSmartX ? &stSmartXOpt : NULL);
		///------ End MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
		
		vector vYTemp;
		/// Iris NLF_81
		//m_pNLFSession->GetFitY(vInX, vYTemp, nDatasetIndex, nPeak);
		GetNLFCurvesObject()->GetFitY(vInX, vYTemp, m_pNLFSession->GetNLParamsMngr(), nDatasetIndex, nPeak);
		///end NLF_81
		
		if(vFitYbyInput.GetSize() != vYTemp.GetSize())
			vFitYbyInput.SetSize(vYTemp.GetSize());
		///------ Folger 02/10/09 PA_FITTING_FAILS_TO_PREPARE_RESIDUAL_DATA_FOR_SINGLE_PEAK_CASE
		//if(nPeaks == 1) //not peak fit
			//nResidualYCol = nYCol;
		///------ End PA_FITTING_FAILS_TO_PREPARE_RESIDUAL_DATA_FOR_SINGLE_PEAK_CASE
		
		if(0 == nPeak)
		{
			vFitYbyInput = vYTemp;
		}
		else
		{
			vFitYbyInput += vYTemp;
			SubtractBaseline(vInX, vFitYbyInput);
		}
		///Sophy 11/20/2008 QA80-10599-P6 FIX_FITCURVE_GRAPH_AXES_RESCALE_PROBLEM
		GetNLFCurvesObject()->SetFitCurveScaleRange(dsX, false);
		GetNLFCurvesObject()->SetFitCurveScaleRange(dsY, true);		
		///end FIX_FITCURVE_GRAPH_AXES_RESCALE_PROBLEM
	}
	///Sophy 9/19/2008 FIX_FAIL_TO_GET_CUMULATIVE_DATA_RANGE
	/*		
	if(!m_pNLFSession->GetCumulativeData(vFitY, nDatasetIndex))	///Jasmine 11/05/07 SUBTRACT_BASELINE_BEFORE_PFM_FIT
		return error_report("nlfitSessionBase.GetCumulativeData failed"); //---CPY 4/4/08
	
	if(bComputeCumuFitCurve) //if multipeak, get cumulative fit curve
	{
		if(dsCumulativeFit.GetSize() != vFitY.GetSize())
			dsCumulativeFit.SetSize(vFitY.GetSize());		
		dsCumulativeFit = vFitY;
		
		SetRescaleRange(dsCumulativeFit, m_vFitYMin, m_vFitYMax); 
	}
	*/
	
	///Sophy 10/13/2008 GET_CUMULATIVE_DATA_WHITH_BASELINE_MODE
	//if(!GetNLFCurvesObject()->GetCumulativeData(vFitY, m_pNLFSession->GetNLParamsMngr(), nDatasetIndex, nPeaks ))	///Jasmine 11/05/07 SUBTRACT_BASELINE_BEFORE_PFM_FIT
	///Kyle 10/21/08 CHANGE_FUNCTION_NAME_HASBASELINEPEAK_TO_GETBASELINEFITMODE
	//if(!GetNLFCurvesObject()->GetCumulativeData(vFitY, m_pNLFSession->GetNLParamsMngr(), nDatasetIndex, nPeaks, m_pNLFSession->HasBaselinePeak() ))	///Jasmine 11/05/07 SUBTRACT_BASELINE_BEFORE_PFM_FIT
	///------ Folger 01/04/09 QA80-12962 MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
	//if(!GetNLFCurvesObject()->GetCumulativeData(vFitY, m_pNLFSession->GetNLParamsMngr(), nDatasetIndex, nPeaks, m_pNLFSession->GetBaselineFitMode() ))	///Jasmine 11/05/07 SUBTRACT_BASELINE_BEFORE_PFM_FIT
	vector		vXCumulative;
	if(!GetNLFCurvesObject()->GetCumulativeData(vFitY, m_pNLFSession->GetNLParamsMngr(), nDatasetIndex, nPeaks, m_pNLFSession->GetBaselineFitMode(), &vXCumulative ))	///Jasmine 11/05/07 SUBTRACT_BASELINE_BEFORE_PFM_FIT
	///------ End MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
	///End CHANGE_FUNCTION_NAME_HASBASELINEPEAK_TO_GETBASELINEFITMODE
	///end GET_CUMULATIVE_DATA_WHITH_BASELINE_MODE
		return error_report("nlfitSessionBase.GetCumulativeData failed"); //---CPY 4/4/08
	
	if(bComputeCumuFitCurve) //if multipeak, get cumulative fit curve
	{
		/// Hong 10/28/08 v8.0962 MORE_ERROR_CHECKING
		if ( !dsCumulativeFit )
			return error_report("Cumulative fit curve data is not ready");
		/// end MORE_ERROR_CHECKING
		if(dsCumulativeFit.GetSize() != vFitY.GetSize())
			dsCumulativeFit.SetSize(vFitY.GetSize());
		///------ Folger 01/04/09 QA80-12962 MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
		dsX.Attach(m_FitCurvesWks, 0);
		dsX = vXCumulative;
		///------ End MORE_WORK_ON_GENERATE_INDIVIDUAL_FIT_CURVE_USING_INDEPENDENT_X_IN_PA
		dsCumulativeFit = vFitY;
		///Sophy 11/20/2008 QA80-10599-P6 FIX_FITCURVE_GRAPH_AXES_RESCALE_PROBLEM
		GetNLFCurvesObject()->SetFitCurveScaleRange(dsCumulativeFit, true);
		///end FIX_FITCURVE_GRAPH_AXES_RESCALE_PROBLEM
		
		//SetRescaleRange(dsCumulativeFit, m_vFitYMin, m_vFitYMax); 
	}
	///end FIX_FAIL_TO_GET_CUMULATIVE_DATA_RANGE
	
	// calc residual data and setup residual worksheet column long name
	///------ Folger 02/01/09 PEAK_FITTING_RESIDUAL_PLOT_PREVIEW_BROKEN
	//Dataset dsResisualX(m_wksResidual, nXCol);
	int		nResidualXCol = GetXDataColIndex(nDatasetIndex, nPeaks);
	Dataset dsResisualX(m_wksResidual, nResidualXCol);
	///------ End PEAK_FITTING_RESIDUAL_PLOT_PREVIEW_BROKEN
	nResidualYCol = GetResidualYDataColIndex(nDatasetIndex, 0, nPeaks);		///------ Folger 02/10/09 PA_FITTING_FAILS_TO_PREPARE_RESIDUAL_DATA_FOR_SINGLE_PEAK_CASE
	Dataset dsResisualY(m_wksResidual, nResidualYCol);
	if(dsResisualX && dsResisualY)
	{
		dsResisualX.SetSize(vInY.GetSize());
		dsResisualY.SetSize(vInY.GetSize());
		
		///------ Folger 02/03/09 PA_FITTING_WITH_BASELINE_FAILS_TO_GET_CORRECT_RESIDUAL_DATA
		if ( m_pNLFSession->HasBaseline() && !m_pNLFSession->GetBaselineFitMode() )		/// PA
		{
			SubtractBaseline(vInX, vFitYbyInput);
		}
		///------ End PA_FITTING_WITH_BASELINE_FAILS_TO_GET_CORRECT_RESIDUAL_DATA

		dsResisualX 	= vInX;
		dsResisualY 	= vInY - vFitYbyInput;
		
		//------ Folger 11/08/07 CATEGORY_NEEDED_WHEN_LOCALIZE
		//string strColName =  nMultiplicity > 1 ? _L("Cumulative Residual") : _L("Regular Residual");
		string strColName =  nPeaks > 1 ? _L("Cumulative Residual") : _LC("Regular Residual", STR_CAT_STATS);
		//------ 
		
		Column colResidual(m_wksResidual, nResidualYCol);
		setFitColumnLongName(colResidual, strColName, nDatasetIndex, m_pNLFSession->GetNumDataset(), nPeak, nPeaks, true);
	}
	
	updatePeakLabel();///Sophy 11/4/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
	return true;
}

///Sophy 11/4/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
bool	NLFitPreviewCtrl::checkGetReplicaPeakCenterWks( Worksheet& wks )
{
	if( !m_FitCurvesWks )
		return false;
	Page wp = m_FitCurvesWks.GetPage();
	if( !wp )
		return false;
	wks = wp.Layers( STR_REPLICA_PEAKS_CENTER_WKS_NAME );
	if( !wks )
	{
		int nLayerIndex = wp.AddLayer( STR_REPLICA_PEAKS_CENTER_WKS_NAME );
		wks = wp.Layers( nLayerIndex );

	}
	if( !wks )
		return false;
	
	return true;
}
bool	NLFitPreviewCtrl::getReplicaPeakCenterRange( XYRange& xyRange )
{
	if( !m_xyReplicaPKCenter )
	{
		Worksheet wks;
		if( !checkGetReplicaPeakCenterWks( wks ) )
			return false;
		Column colX( wks, NLFIT_REPLICA_PK_CENTER_XCOL );
		Column colY (wks, NLFIT_REPLICA_PK_CENTER_YCOL );
		if( !colX || !colY )
			return false;
		colX.SetLongName("Peak Center X");
		colY.SetLongName("Peak Center");
		m_xyReplicaPKCenter.Add("X", wks, 0, NLFIT_REPLICA_PK_CENTER_XCOL, -1, NLFIT_REPLICA_PK_CENTER_XCOL);
		m_xyReplicaPKCenter.Add("Y", wks, 0, NLFIT_REPLICA_PK_CENTER_YCOL, -1, NLFIT_REPLICA_PK_CENTER_YCOL);
	}
	xyRange = m_xyReplicaPKCenter;
	return true;
}

bool	NLFitPreviewCtrl::plotReplicaPeakCenterLabel( GraphLayer& glPreview )
{
	if( !glPreview )
		return false;

	XYRange xyCenter;
	if( !getReplicaPeakCenterRange( xyCenter ) )
		return false;
	///Sophy 11/6/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH better not update legend
	removePeakLabel(); //Sophy, if already plotted, should removed it first as to keep legend hidden.
	string strLegend;
	GraphObject go = glPreview.GraphObjects(GO_LEGEND_NAME);
	if( go )
		strLegend = go.Text;
	///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
	int nPlot = glPreview.AddPlot( xyCenter, IDM_PLOT_TEXT, GAP_USE_TEMPLATE );
	///Sophy 11/6/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH better not update legend
	if( go )
		go.Text = strLegend;
	///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
	if( nPlot < 0 )
		return false;
	DataPlot dp = glPreview.DataPlots(nPlot);
	if( dp )
	{
		dp.SetColor( SYSCOLOR_RED );
		///Sophy 11/7/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
		///Sophy 11/10/2008 CENTRALIZE_CODE_PEAK_LABEL_TYPE_FROM_NLFPREVIEW_AND_PAWIZCORE
		//int	nLabelType = PEAK_LABEL_ROW_NUM_GUI;
		int	nLabelType = LABEL_ROW_NUM_GUI;
		///end CENTRALIZE_CODE_PEAK_LABEL_TYPE_FROM_NLFPREVIEW_AND_PAWIZCORE
		//------ Folger 11/10/08 QA80-12509 v8.0968 ONLY_SET_PLOT_LABEL_TYPE_IN_PEAK_FIT_DIALOG_EXCLUDE_ROTATION
		//dp.LabTalk("tts", &nLabelType, true); 
		dp.LabTalk(STR_PLOT_DATA_LABEL_TYPE, &nLabelType, true); 
		//------
		///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
		///Sophy 11/13/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH to make labels more visible, as Max suggested
		Tree trFormat;
		///Sophy 11/18/2008 FIX_FAIL_TO_SET_LABEL_YOFFSET_WHEN_PREVIEW_ON_DLG apply relative format
		//trFormat = dp.GetFormat();
		//trFormat.Root.Page.Layers.All.DataLabels.All.YOffset.nVal = 30;
		//dp.ApplyFormat( trFormat );
		trFormat = dp.GetFormat(FPB_ALL, FOB_ALL, true, true);
		trFormat.Root.YOffset.nVal = 30;
		dp.ApplyFormat(trFormat, true, true);
		///end FIX_FAIL_TO_SET_LABEL_YOFFSET_WHEN_PREVIEW_ON_DLG
		return true;
		///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
	}
	
	return true;
}

bool	NLFitPreviewCtrl::updatePeakLabel()
{
	vector vXCenter, vYCenter;
	XYRange xyPeakCenter;
	if( !getReplicaPeakCenterRange( xyPeakCenter ) )
		return false;
	m_pNLFSession->GetPeakCenterX( vXCenter );
	m_pNLFSession->GetPeakCenterY( vYCenter );
	ASSERT( vXCenter.GetSize() == vYCenter.GetSize() );

	xyPeakCenter.SetData( &vYCenter, &vXCenter, 0, NULL, DRS_SET_COL_DESIGNATIONS );
	
	return true;
}
///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
///Sophy 11/6/2008 QA80-12510 ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH
bool	NLFitPreviewCtrl::removePeakLabel()
{
	vector<int>	vnPlotIndices;
	GraphLayer glPreview;
	GetFitCurveGraphLayer(glPreview, m_nFitCurveLayer);
	
	if( !glPreview )
		return false;
	if( check_has_plotted_in_graph( m_xyReplicaPKCenter, glPreview, vnPlotIndices ) > 0 )
	{
		int nSize = vnPlotIndices.GetSize();
		if( nSize < 1 )
			return false;
		for( int ii = 0; ii < nSize; ii++ )
		{
			DataPlot dp = glPreview.DataPlots( vnPlotIndices[ii] );
			if( dp && IDM_PLOT_TEXT == dp.GetPlotType() )
				dp.Destroy();
		}
	}
   legend_check_remove_invalid_plot( glPreview.GraphObjects(GO_LEGEND_NAME) );
   return true;
}

void	NLFitPreviewCtrl::destroyPeakCenterWks()
{
	Worksheet wks;
	checkGetReplicaPeakCenterWks( wks );
	if( wks )
		wks.Destroy();
}
///end ADD_LABEL_OBJECT_FOR_NLFIT_REPLICA_PEAK_ON_NLFIT_PREVIEW_GRAPH

///Jasmine 11/07/07 MOVE_MULFUNC_FITSESSION_TO_SEPARATE_FILE
void NLFitPreviewCtrl::SubtractBaseline(const vector vx, vector& vy)
{
	vector vParamValues;
	/// Hong 09/05/08 v8.093cc FITNL_USING_NEW_NLFSESSION
	//m_pNLFSession->GetParamsSettingDoubleVector(vParamValues, NLPARAMGRIDCOLTYPE_VALUE);
	m_pNLFSession->GetParamNumericValues(vParamValues, NLPARAMGRIDCOLTYPE_VALUE);
	/// end FITNL_USING_NEW_NLFSESSION
	
	double dY0 = vParamValues[0];   
	vy -= dY0;
}
///End MOVE_MULFUNC_FITSESSION_TO_SEPARATE_FILE

void	NLFitPreviewCtrl::setFitColumnLongName(Column& col, LPCSTR lpcszName, int index, int nNumDataset, int nPeak, int nMultiplicity, bool bResidual, int nOffset)//1
{
	string 	str(lpcszName);
	if(str.IsEmpty() || !col)
		return;
	
	if(!bResidual)	
	{
		str += nMultiplicity > 1 ? " " + (nPeak+nOffset) : "";
	}
	
	col.SetLongName(str);
}

#endif _NLF_PREVIEWCTRL_H_
