#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
//put additional include files here
#include <..\originlab\grobj_utils.h>
#include <..\originlab\GraphObjTools.h>
#include <o8dlg.h>
/*------------------------------------------------------------------------------*
 * Modification Log:															*
 *	Folger 09/24/08 IMPROVE_GUI_AND_RESULT_TREE_GENERATION						*
 *	CPY 9/24/08 ADD_EDIT_BUTTON_TO_PEAK_INTEG_TOOL								*
 *	Fisher 2008-9-26 ON_ASSERT_FALSE											* 
 *	Folger 04/07/09 CHANGE_BASELINE_METHOD_FAILS_TO_UPDATE_GETN					*
 *	Sophy 8/21/2009 QA80-14175 CREATE_ALL_NODES_IN_ONE_TREE_TO_GET_RID_OF_OPTIONS_BRANCH
 *	Sophy 8/26/2009 QA80-14169 MAKE_GRAPHOBJECT_FOR_PROGRAMMING_CONTROL_PRINTABLE
 *	Sophy 11/6/2009 QA80-14598-P1 FORCE_XF_COMPILE_WHEN_CLICK_ATTACH_GROBJ_AFTER_LOAD_GRAPPH
 *	Sophy 12/3/2009 QA80-14686 CENTRALIZE_CODE_FOR_UPDATE_RESULT_ON_RESCALE_GRAPH
 *	Sophy 12/30/2009 QA80-14904-S1 SUPPORT_FLEXIBLE_ATTACHED_GROBJ_FOR_ROI_TOOLS*
 *	Sophy 2/11/2010 FIX_BASELINE_FROM_TO_OUT_OF_RECT_WHEN_EXCHANGE_XY_AXES		*
 *	Sophy 3/26/2010 QA80-15244 SHOW_AREA_FOR_ROI_INTEG_TOOL						*
 *	Sophy 4/8/2010 UPDATE_COL_DESIGNATION_ON_REPORT								*
 *	Folger 04/09/10 GADGET_INTEGRATE_SHOULD_USE_MATHEMATIC_AREA					*
 *	Sophy 4/14/2010 BACKWORD_COMPATIBILITY_SUPPORT_FOR_GADGET_ATTACHMENTS		*
 *	Sophy 4/15/2010 QA81-15287 IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE			*
 *	CPY 4/16/10 SHOW_INTEG_AREA_SHOULD_BE_ON_BY_DEFAULT							*
 *	Folger 04/19/10 QA81-15324 GADGET_INTEGRATE_BETTER_BASELINE_TO_FIT_RECTANGLE*
 *	Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA	*
 *	Folger 04/30/10 QA81-15287-P1 GADGET_INTEGRATE_SHOUND_NOT_REMEMBER_BASELINE_DATASET
 *	Kyle 09/17/2010 ORG-1082-P1 RENAME_OUTPUT_TABEL_LABELS						*
 *	Kyle 09/17/2010 ORG-1083-P1 ADD_AREA_TYPE_FOR_ROI_INTEG_TOOL				*
 *	Sophy 9/17/2010 ORG-1089-P1 EFFECTIVE_WAY_FOR_REMOVE_AND_RESTORE_MISSING_VALUES*
 *------------------------------------------------------------------------------*/

//put your own support static functions here
#define XFNAME		"addtool_curve_integ"
#define	TOOLNAME	_L("Gadget Integration")
#define	TOOL_PREFERENCES_TITLE	_L("Integration")


#define _STR_OUTPUT_BRANCH_TAG_NAME "quantities"// Don't localize

enum{
	BSM_NONE,
	BSM_CONSTANTY,
	BSM_LINEARINP,
	BSM_DATASET,//sandy 2008-12-8 add dataset baseline
};

enum{
	LBS_FIX_X_TO_DATA,
	LBS_FIX_X_TO_INTEGRAL,
	LBS_FIX_X_TO_DISPLAY,
};

enum{
	INTG_CURVE_NO,
	INTG_CURVE_RECT,
	INTG_CURVE_FACTOR
};

#define _GETN_METHOD_OPTION_EVENT(tr, _PFN)	{PEVENT_FUNC __dfn = _PFN;DWORD _dw_fn = (DWORD)__dfn;\
if(_dw_fn) {string _strTemp = _dw_fn;tr.SetAttribute(STR_ATTRIB_HANDLER, _strTemp);}}	

	
///Sophy 1/13/2010 CLEAN_ROI_TOOLS
enum {
	ITT_OBJ_FIRST = GOT_OBJ_TOTAL,
	ITT_OBJ_BASECURVE,
	ITT_OBJ_INTEGCURVE,
	ITT_OBJ_DIFFCURVE,
	ITT_OBJ_INTEGAREA,	///Sophy 3/26/2010 QA80-15244 SHOW_AREA_FOR_ROI_INTEG_TOOL
};
///end CLEAN_ROI_TOOLS

///Sophy 1/19/2010 SHOW_TOOLNAME_FOR_ROI_TOOLS
#define	NEW_ID_BEGIN	(GET_USER_DATAID(0) + 800)
enum INTEG_NEW_NODE_ID{
	INTEG_TOOLNAME_ID	= NEW_ID_BEGIN,
	INTEG_SHOWAREA_ID,	///Sophy 3/26/2010 QA80-15244 SHOW_AREA_FOR_ROI_INTEG_TOOL
	INTEG_AREA_TYPE_ID,		///Kyle 09/17/2010 ORG-1083-P1 ADD_AREA_TYPE_FOR_ROI_INTEG_TOOL
};
///end SHOW_TOOLNAME_FOR_ROI_TOOLS

///Sophy 1/22/2010 CENTRALIZE_OPEN_PREFERENCE_DIALOG_TO_BASE_CLASS
static	int*	_get_xf_treenode_evt_handle_state()
{
	static int nUpdated = 0;
	return &nUpdated;
}
///end CENTRALIZE_OPEN_PREFERENCE_DIALOG_TO_BASE_CLASS

///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
class IntegrateMissingValueHelper
{
public:
	IntegrateMissingValueHelper(vector& vx, vector& vy, BOOL bNeedRestore)
	{
		m_pvx = &vx;
		m_pvy = &vy;
		ASSERT(m_pvx->GetSize() == m_pvy->GetSize());
		///Sophy 9/17/2010 ORG-1089-P1 EFFECTIVE_WAY_FOR_REMOVE_AND_RESTORE_MISSING_VALUES
		//m_nOldSize = m_pvx->GetSize();
		//m_vnIndicesNonNANUM.SetSize(m_nOldSize);
		//int		nSize = ocmath_1d_remove_missingvalue(*m_pvx, *m_pvy, m_nOldSize, NANUM, m_vnIndicesNonNANUM);
		//if ( nSize >= 0 && nSize < m_nOldSize )
		//{
			//m_pvx->SetSize(nSize);		
			//m_pvy->SetSize(nSize);
			//m_vnIndicesNonNANUM.SetSize(nSize);
		//}
		int nOldSize = vx.GetSize();
		int nSize = ocmath_1d_remove_missingvalue(vx, vy, nOldSize);
		if ( nSize >= 0 && nSize < nOldSize )
		{
			vx.SetSize(nSize);
			vy.SetSize(nSize);
			m_bNeedRestore = bNeedRestore;
			if ( m_bNeedRestore )
			{
				m_vBackupX = vx;
				m_vBackupY = vy;
			}
		}
		else
			m_bNeedRestore = false;
		///end EFFECTIVE_WAY_FOR_REMOVE_AND_RESTORE_MISSING_VALUES
	}
	~IntegrateMissingValueHelper()
	{
		if ( m_bNeedRestore )
		{
			///Sophy 9/17/2010 ORG-1089-P1 EFFECTIVE_WAY_FOR_REMOVE_AND_RESTORE_MISSING_VALUES
			//InsertMissingValue(*m_pvx);
			//InsertMissingValue(*m_pvy);
			*m_pvx = m_vBackupX;
			*m_pvy = m_vBackupY;
			///end EFFECTIVE_WAY_FOR_REMOVE_AND_RESTORE_MISSING_VALUES
		}
	}
	
	int		GetSize()
	{
		return m_pvx->GetSize();
	}
	
private:
	///Sophy 9/17/2010 ORG-1089-P1 EFFECTIVE_WAY_FOR_REMOVE_AND_RESTORE_MISSING_VALUES not used any more, so comment out
	//void	InsertMissingValue(vector& vv)
	//{
		//if ( vv.GetSize() < m_nOldSize )
		//{
			//for ( int ii=0; ii<m_nOldSize; ++ii )
			//{
				//vector<uint>	vn;
				//if ( m_vnIndicesNonNANUM.Find(vn, ii) > 0 )
					//continue;
				//
				//vv.InsertAt(ii, NANUM);
			//}
		//}
	//}
	///end EFFECTIVE_WAY_FOR_REMOVE_AND_RESTORE_MISSING_VALUES
private:
	vector*			m_pvx;
	vector*			m_pvy;
	BOOL			m_bNeedRestore;
	///Sophy 9/17/2010 ORG-1089-P1 EFFECTIVE_WAY_FOR_REMOVE_AND_RESTORE_MISSING_VALUES
	//int				m_nOldSize;
	//vector<int>		m_vnIndicesNonNANUM;
	vector			m_vBackupX;
	vector			m_vBackupY;
	///end EFFECTIVE_WAY_FOR_REMOVE_AND_RESTORE_MISSING_VALUES
};
///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA

class CurvePeakIntegTool : public GraphObjCurveTool
{
public:
	CurvePeakIntegTool(LPCSTR lpcszMainObjName = NULL) : GraphObjCurveTool(lpcszMainObjName)
	{
		m_vnObjIDs.Add(ITT_OBJ_BASECURVE);
		m_vsObjNames.Add("Baseline");
		
		m_vnObjIDs.Add(ITT_OBJ_INTEGCURVE);
		m_vsObjNames.Add("IntegCurve");
		
		m_vnObjIDs.Add(ITT_OBJ_DIFFCURVE);
		m_vsObjNames.Add("DiffCurve");
		
		///Sophy 3/26/2010 QA80-15244 SHOW_AREA_FOR_ROI_INTEG_TOOL
		m_vnObjIDs.Add(ITT_OBJ_INTEGAREA);
		m_vsObjNames.Add("IntegArea");
		///end SHOW_AREA_FOR_ROI_INTEG_TOOL
	}
	
	//virtaul
	string GetSignature()
	{
		return "xf_" XFNAME;
	}
	
protected:
	
	//virtual 
	BOOL OnMove()
	{
		if ( !OnPreMove() )
			return false;
		
		///---Sandy 2008-12-5 add the borderlines of left and right side which may not be the data points.
		///Sophy 2/11/2010 FIX_BASELINE_FROM_TO_OUT_OF_RECT_WHEN_EXCHANGE_XY_AXES
		//FRECT frect;
		//m_go.GetTempBoundingBox(&frect);
		//double x1 = m_gl.X.From;
		//double x2 = m_gl.X.To;
		//m_s1 = x1 + frect.left * (x2-x1); 
		//m_s2 = x1 + frect.right * (x2-x1);
		GetRectCoordinate(m_s1, m_s2);
		///end FIX_BASELINE_FROM_TO_OUT_OF_RECT_WHEN_EXCHANGE_XY_AXES
		//--end
		
		///Sophy 4/15/2010 QA81-15287 IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
		//if( updateBaselineData() && curvePeakInteg() )		
		//{
			//drawLineObjs();
			//showInfoOnEndOfMove();
		//}
		bool bHasData = m_bShowBaseline = getData();
		if ( m_bShowBaseline )
			updateBaselineData();
		
		if ( bHasData )
		{
			curvePeakInteg();
			showInfoOnEndOfMove();
		}
		drawLineObjs();
		///end IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
		///Sophy 3/26/2010 QA80-15244 SHOW_AREA_FOR_ROI_INTEG_TOOL
		if ( isShowIntegArea() )
			updateIntegArea();
		///end SHOW_AREA_FOR_ROI_INTEG_TOOL
		
		return GraphObjCurveTool::OnMove();		
		//if(GraphObjCurveTool::OnMove())
		//{
			//if(updateBaseline() && curvePeakInteg() )		
			//{
				//showInfoOnEndOfMove();
				//return true;
			//}
		//}		
		//return false;
	}
	//virtual
	int		CreateAttachments()
	{
		int nRet = GraphObjCurveTool::CreateAttachments();
		if ( 0 != nRet )
			return nRet;

		///Sophy 2/12/2010 MORE_CLEAN_CODE_TO_RESET_LABEL_POSITION	
		//roi_tool_option_access(ROI_OPTION_RESET_LABEL_POS, ROI_OP_SET);
		//UpdateTopLabel("Area=0\ndx=0"); //2 lines in label
		///end MORE_CLEAN_CODE_TO_RESET_LABEL_POSITION
		
		GraphObject go;
		nRet = CreateAttachment(go, ITT_OBJ_BASECURVE, CTP_FREE_1, GROBJ_TN_POLYLINE);
		if ( 0 != nRet )
			return nRet;
		set_go_color(go, SYSCOLOR_RED);
		set_go_selectable(go, false);
		
		nRet = CreateAttachment(go, ITT_OBJ_INTEGCURVE, CTP_FREE_2, GROBJ_TN_POLYLINE);
		if ( 0 != nRet )
			return nRet;
		set_go_color(go, SYSCOLOR_BLUE);
		set_go_selectable(go, false);
		
		nRet = CreateAttachment(go, ITT_OBJ_DIFFCURVE, CTP_FREE_3, GROBJ_TN_POLYLINE);
		if ( 0 != nRet )
			return nRet;
		set_go_color(go, SYSCOLOR_GREEN);
		set_go_selectable(go, false);
		
		///Sophy 3/26/2010 QA80-15244 SHOW_AREA_FOR_ROI_INTEG_TOOL
		nRet = CreateAttachment(m_goIntegArea, ITT_OBJ_INTEGAREA, CTP_FREE_4, GROBJ_TN_POLYGON);
		if ( 0 != nRet )
			return nRet;
		set_go_selectable(m_goIntegArea, false);
		set_go_behind_data(m_goIntegArea);
		updateAreaSettings();
		///end SHOW_AREA_FOR_ROI_INTEG_TOOL
		
		return nRet;
	}
	
	//virtual
	int		GetAttachments()
	{
		int nRet = GraphObjCurveTool::GetAttachments();
		if ( 0 != nRet )
			return nRet;
		
		nRet = GetAttachment(m_goBaseline, ITT_OBJ_BASECURVE);
		if ( 0 != nRet )
			return nRet;
		
		nRet = GetAttachment(m_goIntegCurve, ITT_OBJ_INTEGCURVE);
		if ( 0 != nRet )
			return nRet;
		
		nRet = GetAttachment(m_goDiffCurve, ITT_OBJ_DIFFCURVE);
		if ( 0 != nRet )
			return nRet;
		
		///Sophy 3/26/2010 QA80-15244 SHOW_AREA_FOR_ROI_INTEG_TOOL
		nRet = GetAttachment(m_goIntegArea, ITT_OBJ_INTEGAREA);
		if ( 0 != nRet )
			return nRet;
		///end SHOW_AREA_FOR_ROI_INTEG_TOOL
		
		return nRet;
	}
	///end CLEAN_ROI_TOOLS
	
	///Sophy 4/14/2010 BACKWORD_COMPATIBILITY_SUPPORT_FOR_GADGET_ATTACHMENTS
	//virtual
	int		CheckCreateAttachments()
	{
		int nRet = GraphObjCurveTool::CheckCreateAttachments();
		if ( 0 != nRet )
			return nRet;
		
		nRet = GetAttachment(m_goIntegArea, ITT_OBJ_INTEGAREA);
		if ( 0 != nRet ) //if not exist, create it
		{
			nRet = CreateAttachment(m_goIntegArea, ITT_OBJ_INTEGAREA, CTP_FREE_4, GROBJ_TN_POLYGON);
			if ( 0 != nRet )
				return nRet;
			set_go_selectable(m_goIntegArea, false);
			set_go_behind_data(m_goIntegArea);
			updateAreaSettings();
		}
		return nRet;
	}
	///end BACKWORD_COMPATIBILITY_SUPPORT_FOR_GADGET_ATTACHMENTS
	
	//---- CPY 9/24/08 ADD_EDIT_BUTTON_TO_PEAK_INTEG_TOOL
	///Sophy 1/22/2010 CENTRALIZE_OPEN_PREFERENCE_DIALOG_TO_BASE_CLASS
	/*
	bool	DoEdit()
	{
		Tree trGUI;
		if(!GetGUITree(trGUI))
			return false;
		
		GETN_TREE(tr)
		tr.Replace(trGUI.Clone(), true,true,false);
		// for now do not allow changing configuration
		//tr.showtop.Show = 0;
		tr.showtop.Show = 1;//Sandy 2008-12-11 snow suggest it can change when click button to open dlg
		//tr.showbottom.Show = 0;
		//tr.baseline.Show = 0;
		tr.baseline.Show = 1;//Sandy 2008-10-28
		
		_GETN_METHOD_OPTION_EVENT(tr.baseline.method, _edit_baseline_method_event);
		//_GETN_METHOD_OPTION_EVENT(tr.curves.restrict, _edit_integcurve_scale_event);
		_GETN_METHOD_OPTION_EVENT(tr.curves.integcurve, _edit_integcurve_scale_event);//Sandy 2008-12-9 add control to unshow integ curve
		_GETN_METHOD_OPTION_EVENT(tr.output.appendwks, _edit_appendwks_event);

		tr.SetAttribute(STR_CLASS_OPTION_NAME_ATTRIB, "addtool_curve_integ");	///Sophy 11/5/2009 QA80-14598-S2 SUPPORT_HELP_WHEN_CHANGE_OPTION

		if(GetNBox(tr, NULL, _L("Quick Integ Tool"), _L("Tool Settings")))
		{
			UpdateMainRect(tr);///Sophy 8/21/2009 QA80-14175 CREATE_ALL_NODES_IN_ONE_TREE_TO_GET_RID_OF_OPTIONS_BRANCH
			SetGUITree(tr);
			SetResultsTree(NULL); // since we need to dup again to get the settings on quantities
			OnMove();// to update the results again
		}
		
		return true;
	}
	*/
	///end CENTRALIZE_OPEN_PREFERENCE_DIALOG_TO_BASE_CLASS
	//----
	
	///Sophy 1/26/2010 ADD_GO_TO_REPORT_TABLE_MENU_IN_CONTEXT
	//virtual
	BOOL	GetReportWorksheet(Worksheet& wksReport)
	{
		Tree trGUI;
		if ( !GetGUITree(trGUI) || trGUI.output.appendwks.nVal != 1 )
			return FALSE;
		string strWorksheet = getReslutPageName(trGUI);
		wksReport.Attach(strWorksheet);
		return wksReport.IsValid();
	}
	///end ADD_GO_TO_REPORT_TABLE_MENU_IN_CONTEXT
	
	/// Iris 2/20/2010 MOVE_REPLACE_LAST_OUTPUT_TO_CONTEXT_MENU
	//bool 	DoOutput()
	bool 	DoOutput(bool bUpdateLastOutput)
	///End MOVE_REPLACE_LAST_OUTPUT_TO_CONTEXT_MENU
	{
		///Sandy 2008-12-22 add if not increasing,  warning message for invalid index info exists in result
		vector vx, vy;
		///Sophy 4/15/2010 QA81-15287 IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
		//if(!getDataRange(vx, vy))
			//return false;		
		if ( !getData() )
			return false;
		
		vx = m_vX; vy = m_vY;
		///end IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
		
		int nSize = vx.GetSize();
	    if(ocmath_is_monotonic(vx, nSize, true)!=MONO_INCREASE)
		{
		 	 warning_msg_box(XFWARN_NONE_MONO_INCREASE, false,'W');//XFWARN_NONE_MONO_INCREASE
		}
		
		//
		if(m_bHasReduced)
			warning_msg_box(XFWAR_REDUCE_X_TO_INTEG, false,'W');//XFWARN_NONE_MONO_INCREASE
		
		Tree trGUI;
		//------ Folger 09/24/08 IMPROVE_GUI_AND_RESULT_TREE_GENERATION
		//if(!GetTree(trGUI) || !trGUI.output || !trGUI.output.script || !trGUI.output.reslog || !trGUI.output.appendwks)
		if(!GetGUITree(trGUI) || !trGUI.output || !trGUI.output.script || !trGUI.output.reslog || !trGUI.output.appendwks)
		//------
		{
			ASSERT(false);
			return false;
		}	
		bool bToScript, bToResLog, bAppendWks;
		bToScript = trGUI.output.script.nVal;
		bToResLog = trGUI.output.reslog.nVal;
		bAppendWks = trGUI.output.appendwks.nVal;
		
		//------ Folger 09/24/08 IMPROVE_GUI_AND_RESULT_TREE_GENERATION
		Tree trResults;
		//GetResultsTree(trResults)//Sandy 2009-2-24 FOUND_DUPLICATE_WITH_BASECLASS_AND_CLEAN_UP
		GetResultsTree(trResults, _STR_OUTPUT_BRANCH_TAG_NAME);
		//------
		
		
		///Sandy CENTRALIZE_TO_BASE_CLASS_GROBJ_UTILS
		/*
		//---- CPY 9/23/08 CURVE_INTEG_TOOL_OUTPUT_TO_WKS_USING_STANDARD_RERPOT_TREE 
		if(bAppendWks)
		{
			string strWksPageName = getReslutPageName(trGUI);
			WorksheetPage wp(strWksPageName);
			Worksheet resWks;
			if(!wp)
			{
				wp.Create("Origin", CREATE_NACTIVE);
				resWks = wp.Layers(0);
				resWks.SetSize(-1, 0);
				wp.Rename(strWksPageName);
			}
			else
				resWks = wp.Layers(0);
			
			//------ Folger 09/24/08 IMPROVE_GUI_AND_RESULT_TREE_GENERATION
			//out_tree_to_wks(trGUI.results, resWks);			
			out_tree_to_wks(trResults, resWks);
			//------
		}
		if(bToScript || bToResLog)
		{
			Tree trTemp;
			//------ Folger 09/24/08 IMPROVE_GUI_AND_RESULT_TREE_GENERATION
			//trTemp = trGUI.results;
			trTemp = trResults;
			//------
			trTemp.Show = 1;
			string strOut;
			vector<int> vnTableDisplayFormat = { DISPLAY_CENTER, DISPLAY_RIGHT, DISPLAY_RIGHT};
			DWORD dw = 0; 
			if(trGUI.output.useLongName.nVal) 
				dw |= TREE2STR_CHECK_USER_LABEL;
			tree_to_str(trTemp, strOut, vnTableDisplayFormat, TREE2STR_SKIP_HIDDEN | TREE2STR_SIMPLE_TYPE_ONLY | dw);
			if(bToScript)
			{
				LT_execute("type -a");
				out_str(strOut);
			}
			if(bToResLog)
			{
				if(m_gp) // should really have this
				{
					Project.OutStringToResultsLog("", false, m_gp.GetName());
				}
				strOut.WriteLine(WRITE_OUTPUT_LOG);
			}
		}
		*/
		DWORD dwCtrl = 0; 
		if(trGUI.output.useLongName.nVal) 
			dwCtrl |= TREE2STR_CHECK_USER_LABEL;
		string strWksPageName = getReslutPageName(trGUI);
		OutputResultTree(bToScript, bToResLog, bAppendWks, strWksPageName, dwCtrl);
		///end  CENTRALIZE_TO_BASE_CLASS_GROBJ_UTILS
		
		return true;
	}
	//virtual

	///Sandy 2009-2-24 FOUND_DUPLICATE_WITH_BASECLASS_AND_CLEAN_UP
	/*
	bool	GetResultsTree(TreeNode& trResults)
	{
		Tree tr;
		if ( GetTree(tr) )
		{
			if ( !tr.Results )
			{
				ASSERT(tr.GUI);
				//tr.results.DataID = tr.GUI.quantities.DataID + 1;
				tr.Results.Replace(tr.GUI.quantities.Clone(), true, true, true);
				tree_remove_attribute(tr.results, STR_ID_ATTRIB); // GETN_CHECK etc things no longer needed and better clean it
				tree_remove_attribute(tr.results, STR_LABEL_ATTRIB); // to avoid double storage, they will be transfered over later anyway
				SetTree(tr);
			}
			trResults = tr.Results;
		}
		
		return trResults.IsValid();
	}
	*/
	//end FOUND_DUPLICATE_WITH_BASECLASS_AND_CLEAN_UP
	//------ End IMPROVE_GUI_AND_RESULT_TREE_GENERATION
	
///Sophy 8/26/2009 QA80-14169 MAKE_GRAPHOBJECT_FOR_PROGRAMMING_CONTROL_PRINTABLE
protected:
	
	//virtual
	double	GetVersion()
	{
		return 8.103;
	}
	
	//virtual
	bool	MakePrintable(GraphObject& go) { return set_go_printable(go); }
///end MAKE_GRAPHOBJECT_FOR_PROGRAMMING_CONTROL_PRINTABLE

	///Sophy 12/3/2009 QA80-14686 CENTRALIZE_CODE_FOR_UPDATE_RESULT_ON_RESCALE_GRAPH
	BOOL	InvalidateResults()
	{
		return OnMove();
	}
	///end CENTRALIZE_CODE_FOR_UPDATE_RESULT_ON_RESCALE_GRAPH
	
	//virtual
	string	GetXFName(){ return XFNAME; }
	
	///Sophy 1/22/2010 CENTRALIZE_OPEN_PREFERENCE_DIALOG_TO_BASE_CLASS
	//virtual
	int*	GetXFEventHandlersState() { return _get_xf_treenode_evt_handle_state(); }
	//virtual
	string	GetToolName(){ return TOOLNAME; }
	//virtual
	string	GetPreferenceTitle(){ return TOOL_PREFERENCES_TITLE; }
	///end CENTRALIZE_OPEN_PREFERENCE_DIALOG_TO_BASE_CLASS
	
	//virtual
	bool	UpdateROIGUI()
	{
		updateAreaSettings();
		return GraphObjCurveTool::UpdateROIGUI();
	}

private:
	///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
	//#define		INSERT_REF_DATA(_index1, _index2)		vX.InsertAt(_index1, vxRef[vnIndicesEx[_index2]]), 	vY.InsertAt(_index1, vyRef[vnIndicesEx[_index2]])	
	bool	removeMissingValuesAndSort(vector& vX, vector& vY, DWORD dwSortOptions, vector& vxRef = NULL, vector& vyRef = NULL)
	{
		ASSERT(vX.GetSize() == vY.GetSize());
		if ( vX.GetSize() != vY.GetSize() || vX.GetSize() == 0 )
			return false;
		
		//int				nOldSize = vX.GetSize();
		//vector<int>		vnIndicesEx(nOldSize);
		//int				nSize = ocmath_1d_remove_missingvalue(vX, vY, nOldSize, NANUM, vnIndicesEx);
		//if ( nSize >= 0 )
		//{
			//vX.SetSize(nSize);
			//vY.SetSize(nSize);
		//}
		//if ( nSize > 2 && nSize < nOldSize && vxRef != NULL && vyRef != NULL )
		//{
			//ASSERT(vxRef.GetSize() == nOldSize);
			//ASSERT(vyRef.GetSize() == nOldSize);
			//
			//for ( int ii=nSize-1; ii>0; --ii )
			//{
				//if ( vnIndicesEx[ii - 1] + 1 != vnIndicesEx[ii] )
				//{
					//if ( vxRef[vnIndicesEx[ii - 1]] <= m_s1 || vxRef[vnIndicesEx[ii]] >= m_s2 )
						//continue;
					//
					//INSERT_REF_DATA(ii, ii);
					//INSERT_REF_DATA(ii, ii - 1);
				//}
			//}
		//}
		IntegrateMissingValueHelper		clHelper(vX, vY, FALSE);
		
		vector<uint> vnIndices;
		vX.Sort(dwSortOptions, TRUE, vnIndices);
		vY.Reorder(vnIndices);
		return true;
	}
	///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
	
	bool curvePeakInteg()
	{
		vector vx, vy;
		///Sophy 4/15/2010 QA81-15287 IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
		//if(!getDataRange(vx, vy))
			//return false;
		vx = m_vX; vy = m_vY;
		///end IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
		///move upper and use
		Tree trGUI;
		//------ Folger 09/24/08 IMPROVE_GUI_AND_RESULT_TREE_GENERATION
		//if(!GetTree(trGUI))
		if(!GetGUITree(trGUI))
		//------
		{
			ASSERT(false);
		}
		//------ Folger 09/24/08 IMPROVE_GUI_AND_RESULT_TREE_GENERATION
		
		//DWORD dwPlotID;
		//vector vx, vy;
		//
		//if(m_dr.GetData(DRR_GET_MISSING |  DRR_GET_DEPENDENT | DRR_NO_FACTORS, 0, &dwPlotID, NULL, &vy, &vx) < 0)
			//return false;
		
		///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA		
		//int nSize = vx.GetSize();
		
		//vector vby(nSize);
		IntegrateMissingValueHelper			clHelper(vx, vy, FALSE);
		int		nSize = clHelper.GetSize();
		///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
		
		//Sandy 2008-12-5 Jack said that the size of cumulative integral vector you want,  should be larger than inputDataSize by at least  by 2 !!!!
		//vector vIntgCurve(nSize); //Sandy 2008-12-2 add integral curve
		vector vIntgCurve;
		
		//---Sandy 2008-12-24 Joe suggestion split "rectangle" to with extrapolate or not
		//bool bLimitToRect = (QT_INTEG_FIT_LIMITS_RECT == _is_fit_integal_limit_to_rectange(trGUI));
		bool bNeedExtrapolate;
		bool bLimitToRect = _is_fit_integal_limit_to_rectange(trGUI, bNeedExtrapolate);
		//---end 
		//if(bLimitToRect)
			//vIntgCurve.SetSize(nSize + 2); 
		//else
			vIntgCurve.SetSize(nSize);
	
		///------Sophy Folger 04/19/10 QA81-15324 GADGET_INTEGRATE_BETTER_BASELINE_TO_FIT_RECTANGLE
		//ASSERT(m_vby.GetSize() == nSize);//CPY
		///------End GADGET_INTEGRATE_BETTER_BASELINE_TO_FIT_RECTANGLE
		
		IntegrationResult pInteg;
		///--------- Fisher 2008-9-24 size should not be greater than 1 and the 4th parameter should be nSize-1
		//int nRet = ocmath_integrate( vx, vy, 0, nSize, &pInteg, NULL, ABSOLUTE_AREA, m_vby);
		if( nSize > 1) 
		{
			///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
			{
				IntegrateMissingValueHelper			clHelperBase(m_vbx, m_vby, TRUE);
			///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
				///------Sophy Folger 04/19/10 QA81-15324 GADGET_INTEGRATE_BETTER_BASELINE_TO_FIT_RECTANGLE
				vector	vby;
				vby = m_vby;
				int		nvbxSize = m_vbx.GetSize();
				if ( nvbxSize > nSize )
				{
					ASSERT(nvbxSize - nSize <= 2);
					if ( m_vbx[0] < vx[0] )
						vby.RemoveAt(0);
					if ( m_vbx[nvbxSize - 1] > vx[nSize - 1] )
						vby.RemoveAt(vby.GetSize() - 1);
				}
				///------End GADGET_INTEGRATE_BETTER_BASELINE_TO_FIT_RECTANGLE
		
				///-----Sandy 2008-12-5 USE_NEW_BOUNDS_INTEGRAL
				//---Sandy 2008-12-2 add integral curve
				//int nRet = ocmath_integrate( vx, vy, 0, nSize-1, &pInteg, vIntgCurve, ABSOLUTE_AREA, m_vby);//Sandy 2008-12-2 add integral curve
				//int nRet = ocmath_integrate( vx, vy, 0, nSize-1, &pInteg, vIntgCurve, ABSOLUTE_AREA, m_vby, true);//-Sandy 2008-12-22 use sorted data to integral
				//int nRet = ocmath_integrate( vx, vy, 0, nSize-1, &pInteg, vIntgCurve, ABSOLUTE_AREA, m_vby, true, SEARCH_FROM_PEAK);///Sandy 2009-1-25 QA80-12999&13019 OCMATH_INTEGRATE_COMPUTED_WRONG_VALUE_FOR_FWHM_WITH_MULTIPLE_PEAKS_DATA
				///------ Folger 04/09/10 GADGET_INTEGRATE_SHOULD_USE_MATHEMATIC_AREA
				//int nRet = ocmath_integrate( vx, vy, 0, nSize-1, &pInteg, vIntgCurve, ABSOLUTE_AREA, m_vby, true); // YuI 01/26/09 reverting back per CP's request
				///Kyle 09/17/2010 ORG-1083-P1 ADD_AREA_TYPE_FOR_ROI_INTEG_TOOL
				//int nRet = ocmath_integrate( vx, vy, 0, nSize-1, &pInteg, vIntgCurve, MATHEMATICAL_AREA, vby, true); // YuI 01/26/09 reverting back per CP's request
				int nAreaType = MATHEMATICAL_AREA;
				if( trGUI.areatype )
					nAreaType = trGUI.areatype.nVal;
				int nRet = ocmath_integrate( vx, vy, 0, nSize-1, &pInteg, vIntgCurve, nAreaType, vby, true);
				///End ADD_AREA_TYPE_FOR_ROI_INTEG_TOOL
				///------ End GADGET_INTEGRATE_SHOULD_USE_MATHEMATIC_AREA
				if(nRet != OE_NOERROR)
				{
					error_report("error return in ocmath_integrate");
				}
				
				if(bLimitToRect)
				{
					///Sandy 2008-12-10 with bounds integral should input all source data points to interpolate.
					//int nDataPtsIntegrated = vIntgCurve.GetSize() + 2;
					
					///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
					IntegrateMissingValueHelper			clHelperEx(m_vxEx, m_vyEx, TRUE);
					
					int		nSizeEx = clHelperEx.GetSize();
					int nDataPtsIntegrated = nSizeEx + 2;
					///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
					vIntgCurve.SetSize(nDataPtsIntegrated);
					
					IntegrationResult pIntegJunk;
					vector vobx(nDataPtsIntegrated);
					vector voby(nDataPtsIntegrated);
					///Sandy 2008-12-10 with bounds integral should input all source data points to interpolate.
					//nRet = ocmath_integrate_with_bounds(m_s1,m_s2, nSize, vx, vy, &pIntegJunk, m_vby,  ABSOLUTE_AREA, &nDataPtsIntegrated, vIntgCurve, vobx, voby);			
					vector vbxEx, vbyEx;
					vbxEx = m_vxEx;
					vbyEx.SetSize(vbxEx.GetSize());
					
					////---Sandy 2008-12-26 REDUCE_BASELINE_X 
					//vector vxBaseNoRepeat, vyBaseNoRepeat;
					//vxBaseNoRepeat = m_vbx;
					//vyBaseNoRepeat = m_vby;
					//int nNoRepeatSize  = vxBaseNoRepeat.GetSize();
					//nNoRepeatSize = ocmath_xy_remove_duplicates(vxBaseNoRepeat, vyBaseNoRepeat, nNoRepeatSize);
					//if(0 > nNoRepeatSize)
					//{
						//error_report("fail to remove duplicates.");
						//return false;
					//}
					//vxBaseNoRepeat.SetSize(nNoRepeatSize);
					//vyBaseNoRepeat.SetSize(nNoRepeatSize);
					/////end REDUCE_BASELINE_X
	
					int nRet = ocmath_interpolate(vbxEx, vbyEx, vbxEx.GetSize(), m_vbx, m_vby, m_vbx.GetSize());
					//nRet = ocmath_interpolate(vbxEx, vbyEx, vbxEx.GetSize(), vxBaseNoRepeat, vyBaseNoRepeat, nNoRepeatSize);
					//---end  REDUCE_BASELINE_X
					
					if(0 != nRet)
					{
						error_report("fail to interpolate baseline curvePeakInteg.");
						return false;
					}	
					
					DWORD dwOption = OCMATH_INTEGRATE_WITH_BOUNDS_SORT;
					if(bNeedExtrapolate)
						dwOption |=  OCMATH_INTEGRATE_WITH_BOUNDS_EXTRAPOLATE;;
					//---Sandy 2008-12-24 Joe suggestion split "rectangle" to with extrapolate or not
					//nRet = ocmath_integrate_with_bounds(m_s1,m_s2, m_vxEx.GetSize(), m_vxEx, m_vyEx, &pIntegJunk, vbyEx,  ABSOLUTE_AREA, &nDataPtsIntegrated, vIntgCurve, vobx, voby);			
					//nRet = ocmath_integrate_with_bounds(m_s1,m_s2, m_vxEx.GetSize(), m_vxEx, m_vyEx, &pIntegJunk, vbyEx,  ABSOLUTE_AREA, &nDataPtsIntegrated, vIntgCurve, vobx, voby, true, bNeedExtrapolate);			
					//nRet = ocmath_integrate_with_bounds(m_s1,m_s2, m_vxEx.GetSize(), m_vxEx, m_vyEx, &pIntegJunk, vbyEx,  ABSOLUTE_AREA, &nDataPtsIntegrated, vIntgCurve, vobx, voby, dwOption);			
					///------ Folger 04/09/10 GADGET_INTEGRATE_SHOULD_USE_MATHEMATIC_AREA
					//nRet = ocmath_integrate_with_bounds(m_s1,m_s2, m_vxEx.GetSize(), m_vxEx, m_vyEx, &pIntegJunk, vbyEx,  ABSOLUTE_AREA, &nDataPtsIntegrated, vIntgCurve, vobx, voby, dwOption, SEARCH_FROM_PEAK);	//Sandy 2009-1-25 QA80-12999&13019 OCMATH_INTEGRATE_COMPUTED_WRONG_VALUE_FOR_FWHM_WITH_MULTIPLE_PEAKS_DATA		
					///Kyle 09/17/2010 ORG-1083-P1 ADD_AREA_TYPE_FOR_ROI_INTEG_TOOL
					//nRet = ocmath_integrate_with_bounds(m_s1,m_s2, nSizeEx, m_vxEx, m_vyEx, &pIntegJunk, vbyEx,  MATHEMATICAL_AREA, &nDataPtsIntegrated, vIntgCurve, vobx, voby, dwOption, SEARCH_FROM_PEAK);	//Sandy 2009-1-25 QA80-12999&13019 OCMATH_INTEGRATE_COMPUTED_WRONG_VALUE_FOR_FWHM_WITH_MULTIPLE_PEAKS_DATA		
					nRet = ocmath_integrate_with_bounds(m_s1,m_s2, nSizeEx, m_vxEx, m_vyEx, &pIntegJunk, vbyEx,  nAreaType, &nDataPtsIntegrated, vIntgCurve, vobx, voby, dwOption, SEARCH_FROM_PEAK);
					///End ADD_AREA_TYPE_FOR_ROI_INTEG_TOOL
					///------ End GADGET_INTEGRATE_SHOULD_USE_MATHEMATIC_AREA
					//---end
					if(nRet != OE_NOERROR)
					{
						error_report("error return in ocmath_integrate_with_bounds");
					}
					ASSERT(nRet == 0);
					vIntgCurve.SetSize(nDataPtsIntegrated);
					vobx.SetSize(nDataPtsIntegrated);
					voby.SetSize(nDataPtsIntegrated);
					pInteg.Area = pIntegJunk.Area;
					
					///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
					//m_vbx = vobx;
					//m_vby = voby;
					vx = vobx;
					///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
				}
				//--------end of USE_NEW_BOUNDS_INTEGRAL
			///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
			}
			///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
			
			//GraphObject go;
			//if(CreateAttachedFreeLine(&go, 1, GROBJ_TN_POLYLINE) > 0)
			//{
				//if(_update_integral_curve(go,  trGUI, vIntgCurve))
				//{
					//m_goIntegCurve = go;
					//if(bLimitToRect)
						//m_goIntegCurve.SetPoints(m_vbx, vIntgCurve);
					//else
						//m_goIntegCurve.SetPoints(vx, vIntgCurve);
					//m_gp.Refresh();
				//}
			//}
			
			updateIntegralCurve(trGUI, vx, vIntgCurve);
			updateDiffCurve(trGUI);
			//if(_update_integral_curve(m_gl,  trGUI, vIntgCurve))
			//{
				//if(bLimitToRect)
				//{
					//m_vxint = m_vbx;
					//m_vyint = vIntgCurve;
				//}
				//else
				//{
					//m_vxint = vx;
					//m_vyint = vIntgCurve;
				//}
			//}
			///---end of add integral curve

		}
		else
		{
			pInteg.x1 = pInteg.x2 = vx[0];
		}
		///---------	


		//---- CPY 9/23/08 NO_IEAD_WHY_SANDY_SUBTRACT_ONE_HERE, I saw runtime error if two few points like size = 1
		//double dPeakHeightFromBaseline = pInteg.yPeak - m_vby[pInteg.iPeak - 1];
		
		///Sandy 2008-12-30 use result to compute peak height from base.
		//double dPeakHeightFromBaseline = pInteg.yPeak - m_vby[pInteg.iPeak];
		double dPeakHeightFromBaseline =   pInteg.yPeak;// - pInteg.yPeakBase;//sandy 2009-2-26  Baseline has been subtracted internally, so no need subtract base again here
	
		//----
		double dxCentroid = (pInteg.xCentroid<pInteg.x1 || pInteg.xCentroid > pInteg.x2)?NANUM:pInteg.xCentroid;
		double dLeftFromCenter, dRightFromCenter;
		if(pInteg.xLeft != NANUM)
		   dLeftFromCenter = pInteg.xPeak - pInteg.xLeft;
		else
			dLeftFromCenter = NANUM;
		
		if(pInteg.xRight != NANUM)
			dRightFromCenter = pInteg.xRight - pInteg.xPeak;
		else
			dRightFromCenter = NANUM;
		
		//Tree trGUI;
		////------ Folger 09/24/08 IMPROVE_GUI_AND_RESULT_TREE_GENERATION
		////if(!GetTree(trGUI))
		//if(!GetGUITree(trGUI))
		////------
		//{
			//ASSERT(false);
		//}
		////------ Folger 09/24/08 IMPROVE_GUI_AND_RESULT_TREE_GENERATION
		Tree trResults;
		//if(!GetResultsTree(trResults))//Sandy 2009-2-24 FOUND_DUPLICATE_WITH_BASECLASS_AND_CLEAN_UP
		if(!GetResultsTree(trResults, _STR_OUTPUT_BRANCH_TAG_NAME))
		{
			ASSERT(false);
			return false;
		}
		//------ End IMPROVE_GUI_AND_RESULT_TREE_GENERATION
		
		m_x1 = pInteg.x1;
		m_x2 = pInteg.x2;

		
		//TreeNode 		trResults = trGUI.results;		//------ Folger 09/24/08 IMPROVE_GUI_AND_RESULT_TREE_GENERATION
		tree_remove_attribute(trResults, ATTR_CTRL_ID);// I have no idea where this came from but we sure don't need it here 
		///Sophy 4/8/2010 UPDATE_COL_DESIGNATION_ON_REPORT
#define	TYPE(_SubNode, _Type)	trResults._SubNode.SetAttribute(STR_COL_DESIGNATION_ATTRIB, _Type)
		///end UPDATE_COL_DESIGNATION_ON_REPORT
		///Sophy 11/5/2009 QA80-14598-S1 OUTPUT_RESULT_SHOULD_USE_NEW_DATAPLOT_NAME_CONVENTION
		//trResults.name.strVal = m_dp.GetName();
		string strPlotRngStr;
		m_dp.GetRangeString(strPlotRngStr, NTYPE_BOOKSHEET_XY_RANGE);
		trResults.name.strVal = strPlotRngStr;
		///end OUTPUT_RESULT_SHOULD_USE_NEW_DATAPLOT_NAME_CONVENTION
		trResults.name.TypeID = TNVAL_TYPE_CSTRING;	TYPE(name, OKDATAOBJ_DESIGNATION_X);
		///Sandy 2008-10-30 split range string to separated col text
		/*
		string strTemp; strTemp.Format("%d - %d", m_i1+1, m_i2+1);	// Fisher Index should begins with 1
		trResults.rows.strVal = strTemp;
		strTemp.Format("%s - %s", ftoa(m_x1, "*5"), ftoa(m_x2, "*5"));
		trResults.xrange.strVal = strTemp;
		// somehow .strVal does not set these, so I have to hardcode them again
		trResults.name.TypeID = TNVAL_TYPE_CSTRING;
		trResults.rows.TypeID = TNVAL_TYPE_CSTRING;
		trResults.xrange.TypeID = TNVAL_TYPE_CSTRING;
		*/	
		string strTemp; 
		strTemp.Format("%d", m_i1+1);
		trResults.begin_row.strVal = strTemp;
		strTemp.Format("%d", m_i2+1);
		trResults.end_row.strVal = strTemp;
		
		///---Sandy 2008-12-5 USE_NEW_BOUNDS_INTEGRAL
		//strTemp.Format("%s", ftoa(m_x1, "*5"));
		if(bLimitToRect)
			strTemp.Format("%s", ftoa(m_s1, "*5"));
		else
			strTemp.Format("%s", ftoa(m_x1, "*5"));
		///---end USE_NEW_BOUNDS_INTEGRAL 
		trResults.begin_x.strVal = strTemp;
		
		
		///---Sandy 2008-12-5 USE_NEW_BOUNDS_INTEGRAL
		//strTemp.Format("%s", ftoa(m_x2, "*5"));
		if(bLimitToRect)
			strTemp.Format("%s", ftoa(m_s2, "*5"));
		else
			strTemp.Format("%s", ftoa(m_x2, "*5"));
		///---end USE_NEW_BOUNDS_INTEGRAL 
		trResults.end_x.strVal = strTemp;
		
		
		trResults.begin_row.TypeID = TNVAL_TYPE_CSTRING;	TYPE(begin_row, OKDATAOBJ_DESIGNATION_Y);
		trResults.end_row.TypeID = TNVAL_TYPE_CSTRING;		TYPE(end_row, OKDATAOBJ_DESIGNATION_Y);
		trResults.begin_x.TypeID = TNVAL_TYPE_CSTRING;		TYPE(begin_x, OKDATAOBJ_DESIGNATION_Y);
		trResults.end_x.TypeID = TNVAL_TYPE_CSTRING;		TYPE(end_x, OKDATAOBJ_DESIGNATION_Y);
		
		//end

		trResults.ph.dVal = dPeakHeightFromBaseline;	TYPE(ph, OKDATAOBJ_DESIGNATION_Y);
		trResults.pc.dVal = pInteg.xPeak;	TYPE(pc, OKDATAOBJ_DESIGNATION_Y);
		trResults.pa.dVal = pInteg.Area;	TYPE(pa, OKDATAOBJ_DESIGNATION_Y);
		trResults.pcd.dVal = dxCentroid;	TYPE(pcd, OKDATAOBJ_DESIGNATION_Y);//CPY why was this commented out?  
		trResults.pfwhm.dVal = pInteg.dxPeak;	TYPE(pfwhm, OKDATAOBJ_DESIGNATION_Y);
		trResults.plhw.dVal = dLeftFromCenter;	TYPE(plhw, OKDATAOBJ_DESIGNATION_Y);
		trResults.prhw.dVal = dRightFromCenter;	TYPE(prhw, OKDATAOBJ_DESIGNATION_Y);
		trResults.pymax.dVal = vy[pInteg.iPeak]; TYPE(pymax, OKDATAOBJ_DESIGNATION_Y);//pInteg.yPeak;  //Sandy 2009-2-27 should be the y value of source curve
		trResults.pxofymax.dVal = m_i1 + pInteg.iPeak+1; TYPE(pxofymax, OKDATAOBJ_DESIGNATION_Y); // Fisher Index should begins with 1
		//sandy 2008-10-28 QA80-12350-s1 ADD_BASELINE_RESULT
		trResults.base.strVal = m_strBaseline;
		trResults.base.TypeID = TNVAL_TYPE_CSTRING;
		//end		

		//--- hide all those that are unchecked
		tree_copy_values_to_attributes(trGUI.quantities, trResults, STR_LABEL_ATTRIB);

		//---- save for showing on gr at end of move
		m_Area = pInteg.Area; 
		//------ CPY 10/1/08 MOVE_DATA_DISPLAY_CODE_TO_BASE_CLASS
		//m_strIndexAndX.Format("i=%s x=%s", trResults.rows.strVal, trResults.xrange.strVal);
		//------
		//----
		
		//------ Folger 09/24/08 IMPROVE_GUI_AND_RESULT_TREE_GENERATION
		//if(!SetTree(trGUI))
		//{
			//ASSERT(false);
			//return false;
		//}
		if(!SetResultsTree(trResults))
		{
			ASSERT(false);
			return false;
		}
		//------ End IMPROVE_GUI_AND_RESULT_TREE_GENERATION
		return true;
	}
	
	bool updateDiffCurve(TreeNode& trGUI)
	{
		TreeNode trCurves = trGUI.curves;
		TreeNode trDiff = trCurves.diffcurve;
		if(!trCurves ||!trDiff)
		{
			error_report("Invalid object in _update_integral_curve() ");
			return false;
		}
		
		m_bShowDiffCurve = trDiff.nVal && trDiff.Enable;
		if(m_bShowDiffCurve)
		{
			m_vxdiff = m_vbx;
			m_vydiff = m_vby;
			///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
			IntegrateMissingValueHelper		clhelper(m_vxEx, m_vyEx, TRUE);
			///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
			int nRet = ocmath_interpolate(m_vxdiff, m_vydiff, m_vxdiff.GetSize(), m_vxEx, m_vyEx, m_vyEx.GetSize());
			if(0 != nRet)
			{
				error_report("fail to interpolate in updateDiffCurve.");
				return false;
			}	
			
			m_vydiff = m_vydiff - m_vby;
			///Sophy 3/31/2010 TRIM_MISSING_VALUES_IN_DIFF_CURVE_DATA
			removeMissingValuesAndSort(m_vxdiff, m_vydiff, SORT_ASCENDING);
			///end TRIM_MISSING_VALUES_IN_DIFF_CURVE_DATA
		}

		
		return true;
	}
	
	bool updateIntegralCurve(TreeNode& trGUI, vector& vx, vector& vIntgCurve)
	{
		TreeNode trcurves = trGUI.curves;
		TreeNode trDisplay = trcurves.integcurve;
		TreeNode trMultiply = trcurves.multiply;
		
		if(!trcurves ||!trDisplay ||!trMultiply)
		{
			error_report("Invalid object in _update_integral_curve() ");
			return false;
		}
	
		double dMultiply = trMultiply.dVal;
		int nIntegCurDisplay = trDisplay.nVal;
	
		m_bShowIntegCurve = true;
		if(nIntegCurDisplay == INTG_CURVE_RECT)
		{
			if(m_gl)
			{
				Scale yaxis(m_gl.Y);
				double dFrom = yaxis.From;
				double dTo = yaxis.To;
				double dMax, dMin;
				vIntgCurve.GetMinMax(dMin, dMax);
				ASSERT(dMin != dMax);
				if ( dMin != dMax )
				{
					vIntgCurve = ( (vIntgCurve-dMin)/(dMax-dMin) ) * (dTo - dFrom) + dFrom;
				}
			}
			else
			{
				error_report("Invalid Layer in updateIntegralCurve");
				return false;
			}
		}
		else if(nIntegCurDisplay == INTG_CURVE_FACTOR)
		{
			vIntgCurve = vIntgCurve*dMultiply;
		}
		else
			m_bShowIntegCurve = false;

		//---Sandy 2008-12-24 Joe suggestion split "rectangle" to with extrapolate or not
		//bool bLimitToRect = (QT_INTEG_FIT_LIMITS_RECT == _is_fit_integal_limit_to_rectange(trGUI));
		bool bNeedExtrapolate;
		bool bLimitToRect = _is_fit_integal_limit_to_rectange(trGUI, bNeedExtrapolate);
		//---end
		
		///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
		//if(bLimitToRect)
		//{
			//m_vxint = m_vbx;
			//m_vyint = vIntgCurve;
		//}
		//else
		//{
			//m_vxint = vx;
			//m_vyint = vIntgCurve;
		//}
		m_vxint = vx;
		m_vyint = vIntgCurve;
		///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
		
		m_vxint.SetSize(m_vyint.GetSize());// if y data is empty, x should be the same
		
		return true;
	}

	//Sandy 2008-12-2 QA80-12263-S2 REPOSITION_LABEL_FOR_MORE_CLEARER
	//bool getShowOptions(bool& bShowTop, bool& bShowBottom, int& nBaselineMethod)
	//bool getShowOptions(bool& bShowTop, bool& bShowBottom)
	bool getShowOptions()
	{
		
		Tree trGUI;
		//------ Folger 09/24/08 IMPROVE_GUI_AND_RESULT_TREE_GENERATION
		//if(!GetTree(trGUI) || !trGUI.showtop || !trGUI.showbottom || !trGUI.baseline)
		//if(!GetGUITree(trGUI) || !trGUI.showtop || !trGUI.showbottom || !trGUI.baseline)
		if(!GetGUITree(trGUI) || !trGUI.showtop )//Sandy 2008-12-2 QA80-12263-S2 REPOSITION_LABEL_FOR_MORE_CLEARER
		//------
		{
			ASSERT(false);
			return false;
		}	
		bool bShowTop = trGUI.showtop.nVal;
		
		
		//bShowBottom = trGUI.showbottom.nVal;//Sandy 2008-12-2 QA80-12263-S2 REPOSITION_LABEL_FOR_MORE_CLEARER
		//bShowBottom = false;
		
		/////Sandy 2008-10-10 add baseline options
		////nBaseline = trGUI.baseline.nVal;  
		//nBaselineMethod = trGUI.baseline.method.nVal;
		return bShowTop;
	}	
	string getReslutPageName(const TreeNode& trGUI)
	{
		return trGUI.output.wbkName.strVal;
	}
	void showInfoOnEndOfMove()
	{
	
		//Sandy 2008-12-2 QA80-12263-S2 REPOSITION_LABEL_FOR_MORE_CLEARER
		//bool bShowTop, bShowBottom; 
		//int nbaseline;
		//getShowOptions(bShowTop, bShowBottom, nbaseline);
		bool bShowTop = getShowOptions();
		
		int nRet;
		
		//---Sandy 2008-12-2 QA80-12263-S2 REPOSITION_LABEL_FOR_MORE_CLEARER
		//string strTemp;
		//if(bShowTop && (nRet = GetAttachment(CTP_TOP, m_goTop)) > 0)
		//{
			//strTemp.Format("Area=%s", ftoa(m_Area, "*4"));
			//m_goTop.Text = strTemp;	
		//}
		//
		//if(bShowBottom && (nRet = GetAttachment(CTP_BOTTOM, m_goBottom)) > 0)
		//{
			//strTemp.Format("dx=%s", ftoa(m_x2-m_x1, "*4"));
			//m_goBottom.Text = strTemp;
		//}
		////------ CPY 10/1/08 MOVE_DATA_DISPLAY_CODE_TO_BASE_CLASS
		////SetDataDisplayText(m_strIndexAndX);
		////-----
		string strTemp;
		//if(bShowTop && (nRet = GetAttachment(CTP_TOP, m_goTop)) > 0)
		if(bShowTop)
		{
			Tree trGUI;
			if(!GetGUITree(trGUI))
			{
				ASSERT(false);
			}
			
			///Sandy 2008-12-8 show true dx if limit to rectangle
			//strTemp.Format("Area=%s\ndx=%s", ftoa(m_Area, "*4"), ftoa(m_x2-m_x1, "*4"));
			
			//---Sandy 2008-12-24 Joe suggestion split "rectangle" to with extrapolate or not
			//bool bLimitToRect = (QT_INTEG_FIT_LIMITS_RECT == _is_fit_integal_limit_to_rectange(trGUI));
			bool bNeedExtrapolate;
			bool bLimitToRect = _is_fit_integal_limit_to_rectange(trGUI, bNeedExtrapolate);
			//---end
			
			double dx;
			if(bLimitToRect)
				dx = m_s2 - m_s1;
			else
				dx = m_x2 - m_x1;
			strTemp.Format("Area=%s\ndx=%s", ftoa(m_Area, "*4"), ftoa(dx, "*4"));
				
			///Sophy 2/12/2010 MORE_CLEAN_CODE_TO_RESET_LABEL_POSITION
			//m_goLabel.Text = strTemp;	
			UpdateTopLabel(strTemp);
			//end MORE_CLEAN_CODE_TO_RESET_LABEL_POSITION
		}
		m_goLabel.Show(bShowTop);
		//------end of QA80-12263-S2 REPOSITION_LABEL_FOR_MORE_CLEARER

	}		
	bool updateBaselineData()
	{
		/////Sandy 2008-12-8 improve baseline to polyline
		////if(CreateAttachedFreeLine(&m_goBaseline < 0)
		//if(CreateAttachedFreeLine(&m_goBaseline, _QT_INTEG_POS_ID_BASELINE, GROBJ_TN_POLYLINE) < 0)
			//return false;
		
		vector vx, vy;
		///Sophy 4/15/2010 QA81-15287 IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
		//if(!getDataRange(vx, vy))
			//return false;
		vx = m_vX; vy = m_vY;
		///end IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
		Tree trInfo;
		if(!GetTree(trInfo))
		{
			ASSERT(false);
			return false;
		}
		//bool bShowTop, bShowBottom;
		//int nBaselineMethod;
		//getShowOptions(bShowTop, bShowBottom, nBaselineMethod);
		
		//DWORD dwPlotID;
		//vector vx, vy, vi;
		//if(m_dr.GetData(DRR_GET_MISSING |  DRR_GET_DEPENDENT | DRR_NO_FACTORS, 0, &dwPlotID, NULL, &vy, &vx) < 0)
			//return false;
		
		int nSize = vx.GetSize();
		int nSizeEx = m_vxEx.GetSize();
		
		m_vbx.SetSize(nSize);
		m_vby.SetSize(nSize);
		///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
		//m_vbx = vx;
		m_vbx = vy - vy + vx;
		///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA

		double dMinEx, dMaxEx;
		int iminEx, imaxEx;
		m_vxEx.GetMinMax(dMinEx, dMaxEx,  &iminEx, &imaxEx);
		
		double dMin, dMax;
		int imin, imax;
		m_vbx.GetMinMax(dMin, dMax, &imin, &imax);	
		
		vector vxTemp(2), vyTemp(2);
		TreeNode& trBaseline = trInfo.GetNode("GUI").GetNode("baseline");
		ASSERT(trBaseline);
		int nfixxto = trInfo.GUI.baseline.fixxto.nVal;
		switch(nfixxto)
		{
		case LBS_FIX_X_TO_DATA:
			vxTemp[0] = dMinEx;
			vxTemp[1] = dMaxEx;
			vyTemp[0] = m_vyEx[iminEx];
			vyTemp[1] = m_vyEx[imaxEx];
			break;
		case LBS_FIX_X_TO_INTEGRAL:
			vxTemp[0] = dMin;
			vxTemp[1] = dMax;
			vyTemp[0] = vy[imin];
			vyTemp[1] = vy[imax];
			break;
		case LBS_FIX_X_TO_DISPLAY:
			GraphLayer gl = Project.ActiveLayer();
			if(!gl)
			{
				error_report("invalid graph layer!");
				return false;
			}
			Scale scX(gl.X);
			vxTemp[0] = scX.From;
			vxTemp[1] = scX.To;
			vyTemp[0] = 0;
			vyTemp[1] = 0;	
			break;
		default:
			break;
		}
		
		///------Sophy Folger 04/19/10 QA81-15324 GADGET_INTEGRATE_BETTER_BASELINE_TO_FIT_RECTANGLE
		bool bNeedExtrap = false;
		if ( _is_fit_integal_limit_to_rectange(trInfo.GUI, bNeedExtrap) )
		{
			double dY1 = NANUM, dY2 = NANUM;
			interploateRectBounds(m_vbx, m_vby, dY1, dY2, bNeedExtrap);
			if ( LBS_FIX_X_TO_INTEGRAL == nfixxto )
			{
				if ( !is_missing_value(dY1) )
				{
					vxTemp[0] = m_vbx[0];
					vyTemp[0] = dY1;
				}
				if ( !is_missing_value(dY2) )
				{
					vxTemp[1] = m_vbx[m_vbx.GetSize() - 1];
					vyTemp[1] = dY2;
				}
			}
		}
		///------ End GADGET_INTEGRATE_BETTER_BASELINE_TO_FIT_RECTANGLE
		
		int nBaselineMethod =  trInfo.GUI.baseline.method.nVal;	
		m_bShowBaseline  = (nBaselineMethod != BSM_NONE);
		switch(nBaselineMethod)
		{
			case BSM_NONE: // no basline
			{
				//m_goBaseline.Show(false);
				m_vby = 0;
				m_strBaseline = "None";
				return true;
			}
			
			case BSM_CONSTANTY:
			{
				ASSERT(trBaseline.yvalue);
				double dY = trBaseline.yvalue.dVal;
				//m_goBaseline.Show();
				vxTemp[0] = dMin;
				vxTemp[1] = dMax;
				vyTemp[0] = dY;
				vyTemp[1] = dY;
				m_strBaseline.Format("Constant Y(%f)", dY);
				break;	
			}
			case BSM_LINEARINP:
			{
				ASSERT(trBaseline.yoffsetleft && trBaseline.yoffsetright);
				double dY1 = trBaseline.yoffsetleft.dVal;
				double dY2 = trBaseline.yoffsetright.dVal;
				//m_goBaseline.Show();
				vyTemp[0] += dY1;
				vyTemp[1] += dY2;
				m_strBaseline.Format("Linear (%f, %f), (%f, %f)", vxTemp[0], vyTemp[0], vxTemp[1], vyTemp[1]);
				break;
			}
			
			//sandy 2008-12-8 add baseline dataset
			case BSM_DATASET:
			{
				XYRange xyBaseline;
				TreeNode trBaselineRange = trInfo.GUI.baseline.xyrbase;
				if(!trBaselineRange || !okxf_resolve_tree_construct_range(&trBaselineRange, &xyBaseline) )
				{
					error_report("There isn't baseline dataset!");
					m_bShowBaseline = false;
					m_strBaseline = "Invalid Dataset";
				} 
				else
				{
					xyBaseline.GetData(vyTemp, vxTemp);
					m_strBaseline = xyBaseline.GetDescription(GETLC_NO_DESIGNATIONS | GETLC_NO_ROWS);
				}

				break;
			}
			
		default:
			break;
		}
		
		///Sandy 2008-12-8 improve baseline to polyline
		int nRet = ocmath_interpolate(m_vbx, m_vby, m_vbx.GetSize(), vxTemp, vyTemp, vxTemp.GetSize());
		if(0 != nRet)
		{
			error_report("fail to interpolate linear baseline.");
			return false;
		}	
		
		//if(!move_line(m_goBaseline, vxTemp[0], vxTemp[1], vyTemp[0], vyTemp[1]))
		//{
			//error_report("fail to move linear baseline.");
			//return false;
		//}
		return true;
	}	
	
	///Sandy 2008-12-8 improve baseline to polyline
	void drawLineObjs()
	{
		
		//if(CreateAttachedFreeLine(&m_goBaseline, _QT_INTEG_POS_ID_BASELINE, GROBJ_TN_POLYLINE) > 0)
		//{
			if(m_bShowBaseline)
			{
				if(1 < m_vbx.GetSize())
				{
					///Sophy 4/15/2010 QA81-15287 IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
					//int nSize = m_goBaseline.SetPoints(m_vbx, m_vby);
					Tree trFmt;
					trFmt = m_goIntegArea.GetFormat(FPB_DATA, FOB_ALL, true, true);
					///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
					IntegrateMissingValueHelper		clHelper(m_vbx, m_vby, TRUE);
					///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
					trFmt.Root.Data.X.dVals = m_vbx;
					trFmt.Root.Data.Y.dVals = m_vby;
					m_goBaseline.ApplyFormat(trFmt, true, true);
					///end IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
					m_goBaseline.Show();
				}
				else
					error_report("Create free line fail in drawLineObjs");
			}
			else
				m_goBaseline.Show(false);
		//}

			
		

		//if(CreateAttachedFreeLine(&m_goIntegCurve,_QT_INTEG_POS_ID_INTEG_CURVE, GROBJ_TN_POLYLINE) > 0)
		//{
			if(m_bShowIntegCurve)
			{
				if(1 < m_vxint.GetSize())
				{
					///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
					IntegrateMissingValueHelper		clHelper(m_vxint, m_vyint, TRUE);
					///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
					m_goIntegCurve.SetPoints(m_vxint, m_vyint);
					m_goIntegCurve.Show();
				}
				else
					error_report("Create free line fail in drawLineObjs");
			}
			else
				m_goIntegCurve.Show(false);
		//}


		//if(CreateAttachedFreeLine(&m_goDiffCurve, _QT_INTEG_POS_ID_DIFF_CURVE, GROBJ_TN_POLYLINE) > 0)
		//{
			if(m_bShowDiffCurve)
			{
				if(1 < m_vxdiff.GetSize())
				{
					m_goDiffCurve.SetPoints(m_vxdiff, m_vydiff);
					m_goDiffCurve.Show();
				}
				else
					error_report("Create free line fail in drawLineObjs");	
			}
			else
				m_goDiffCurve.Show(false);
		//}
		
		
		
		m_gp.Refresh();
		return;
	}
	
	///Sophy 3/26/2010 QA80-15244 SHOW_AREA_FOR_ROI_INTEG_TOOL
	bool isShowIntegArea()
	{
		bool bShow = false;
		Tree trGUI;
		if ( GetGUITree(trGUI) )
		{
			bShow = trGUI.integlimit.ShowIntegArea.nVal == 1
		}
		return bShow;
	}
	bool updateAreaSettings()
	{
		if ( m_goIntegArea )
		{
			Tree trFmt;
			trFmt.Root.Border.Width.nVal = 0; //no border
			//trFmt.Root.Fill.Pattern.Style.nVal = 15; //sparse
			trFmt.Root.Fill.Pattern.Style.nVal = 0; //none
			trFmt.Root.Fiil.Pattern.PatternColor.nVal = 0; //black
			trFmt.Root.Fill.Pattern.UseBorderColor.nVal = 0;
			trFmt.Root.Fill.Pattern.Width.nVal = 1;
			//trFmt.Root.Fill.Color.nVal = -4; //None
			trFmt.Root.Fill.Color.nVal = 18; //light gray
			m_goIntegArea.UpdateThemeIDs(trFmt.Root);
			m_goIntegArea.ApplyFormat(trFmt, true, true);
			
			m_goIntegArea.Show(isShowIntegArea());
		}
		return false;
	}
	
	#define		CHECK_HIDE_INTEG_AREA_AND_RETURN \
				if ( vY.GetSize() == 0 ) \
				{ \
					m_goIntegArea.Show(false); \
					return false; \
				}
	bool updateIntegArea()
	{		
		if ( !m_goIntegArea )
			return false;
		
		vector vX, vY;
		vX = m_vX; vY = m_vY;
		CHECK_HIDE_INTEG_AREA_AND_RETURN;
		
		///Sophy 4/15/2010 QA81-15287 IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE do linear interpolate/extrapolate at ROI bounds
		Tree trGUI;
		bool bNeedExtrap = false;
		///------ Folger 04/19/10 QA81-15324 GADGET_INTEGRATE_BETTER_BASELINE_TO_FIT_RECTANGLE
		//bool bLeftBound = false, bRightBound = false;
		//if ( GetGUITree(trGUI) && _is_fit_integal_limit_to_rectange(trGUI, bNeedExtrap) )
		//{
			//vector vPlotX;
			//if ( m_dp.GetDataRange(m_dr, 0, -1) && m_dr && m_dr.GetData(&vPlotX, 0) )
			//{
				//if ( vPlotX[0] > m_s1 )
					//bLeftBound = true;
				//if ( vPlotX[vPlotX.GetSize() - 1] < m_s2 )
					//bRightBound = true;
			//}
			//
			//double dY = NANUM;
			//if ( m_vX[0] > m_s1 && (bNeedExtrap || !bLeftBound) )
			//{
				//ocmath_interpolate(&m_s1, &dY, 1, m_vxEx, m_vyEx, m_vxEx.GetSize());
				//vX.Add(m_s1);
				//vY.Add(dY);
			//}
			//if ( m_vX[m_i2 - m_i1] < m_s2 && (bNeedExtrap || !bRightBound) )
			//{
				//ocmath_interpolate(&m_s2, &dY, 1, m_vxEx, m_vyEx, m_vxEx.GetSize());
				//vX.Add(m_s2);
				//vY.Add(dY);
			//}
		//}
		if ( GetGUITree(trGUI) && _is_fit_integal_limit_to_rectange(trGUI, bNeedExtrap) )
		{
			double	dY1 = NANUM;
			double	dY2 = NANUM;
			interploateRectBounds(vX, vY, dY1, dY2, bNeedExtrap);
		}
		///------ End GADGET_INTEGRATE_BETTER_BASELINE_TO_FIT_RECTANGLE
		///end IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
		///Sophy 3/30/2010 QA81-15244-P1 REMOVE_MISSING_VALUE_WHEN_CONTRUCT_SHADE_AREA
		removeMissingValuesAndSort(vX, vY, SORT_ASCENDING, m_vbx, m_vby);
		///end REMOVE_MISSING_VALUE_WHEN_CONTRUCT_SHADE_AREA
		
		CHECK_HIDE_INTEG_AREA_AND_RETURN;
		
		///Sophy 3/30/2010 QA81-15244-P2 BETTER_SHADE_AREA_FOR_LOG_SCALE_TYPE
		int nScale = m_gl.Y.Type;
		vector<uint> vnIndices;
		if ( nScale == SCALE_TYPE_LOG10 || nScale == SCALE_TYPE_LN || nScale == SCALE_TYPE_LOG2 )
		{
			m_vby.Find(MATREPL_TEST_LESSTHAN | MATREPL_TEST_EQUAL, m_gl.Y.From, vnIndices);
			m_vby.Replace(vnIndices, m_gl.Y.From);
		}
		vnIndices.SetSize(0);
		m_vby.Find(MATREPL_TEST_EQUAL, NANUM, vnIndices);
		m_vby.Replace(vnIndices, m_gl.Y.From);
		///Sophy 4/15/2010 QA81-15287 IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
		vnIndices.SetSize(0);
		m_vbx.Find(MATREPL_TEST_LESSTHAN, vX[0], vnIndices);
		m_vbx.Replace(vnIndices, NANUM);
		vnIndices.SetSize(0);
		m_vbx.Find(MATREPL_TEST_GREATER, vX[vX.GetSize() - 1], vnIndices);
		m_vbx.Replace(vnIndices, NANUM);
		///end IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
		removeMissingValuesAndSort(m_vbx, m_vby, SORT_DESCENDING);
		///end BETTER_SHADE_AREA_FOR_LOG_SCALE_TYPE
		vX.Append(m_vbx);
		vY.Append(m_vby);

		Tree trFmt;
		trFmt = m_goIntegArea.GetFormat(FPB_DATA, FOB_ALL, true, true);
		trFmt.Root.Data.X.dVals = vX;
		trFmt.Root.Data.Y.dVals = vY;
		m_goIntegArea.ApplyFormat(trFmt, true, true);

		m_goIntegArea.Show(true && isShowIntegArea());
		
		return true;
	}
	///end SHOW_AREA_FOR_ROI_INTEG_TOOL
	
	///------Sophy Folger 04/19/10 QA81-15324 GADGET_INTEGRATE_BETTER_BASELINE_TO_FIT_RECTANGLE
	void	interploateRectBounds(vector& vX, vector& vY, double& dY1, double& dY2, bool bNeedExtrap)
	{
		bool	bLeftBound = false, bRightBound = false;
		vector	vPlotX, vPlotY;
		///Sophy 4/26/2010 QA81-15324 GADGET_INTEGRATE_BETTER_BASELINE_TO_FIT_RECTANGLE
		//if ( m_dp.GetDataRange(m_dr, 0, -1) && m_dr && m_dr.GetData(&vPlotX, 0) )
		XYRange xyData;
		if ( m_dp.GetDataRange(xyData, 0, -1) && xyData && xyData.GetData(vPlotY, vPlotX) )
		///end GADGET_INTEGRATE_BETTER_BASELINE_TO_FIT_RECTANGLE
		{
			double dMin, dMax;
			vPlotX.GetMinMax(dMin, dMax);
			if ( m_s1 > m_s2 )
			{
				double dTemp = m_s1;
				m_s1 = m_s2;
				m_s2 = dTemp;
			}
			if ( dMin > m_s1 )
				bLeftBound = true;
			if ( dMax < m_s2 )
				bRightBound = true;
		}
		
		dY1 = dY2 = NANUM;
		///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
		IntegrateMissingValueHelper		clhelper(m_vxEx, m_vyEx, TRUE);
		///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
		if ( m_vX[0] > m_s1 && (bNeedExtrap || !bLeftBound) )
		{
			ocmath_interpolate(&m_s1, &dY1, 1, m_vxEx, m_vyEx, m_vxEx.GetSize());
			vX.InsertAt(0, m_s1);
			vY.InsertAt(0, dY1)
		}
		///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
		//if ( m_vX[m_i2 - m_i1] < m_s2 && (bNeedExtrap || !bRightBound) )
		if ( m_vX[m_vX.GetSize() -1] < m_s2 && (bNeedExtrap || !bRightBound) )
		///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
		{
			ocmath_interpolate(&m_s2, &dY2, 1, m_vxEx, m_vyEx, m_vxEx.GetSize());
			vX.Add(m_s2);
			vY.Add(dY2);
		}
	}
	///------ End GADGET_INTEGRATE_BETTER_BASELINE_TO_FIT_RECTANGLE
	
	//bool getDataRange()
	///Sophy 4/15/2010 QA81-15287 IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
	//bool getDataRange(vector& vx = NULL, vector &vy = NULL)
	//{
		//if(!GetData())
		//{
			//error_report("GetData() form Grobj error!");
			//return false;
		//}
		//
		////return m_dp.GetDataRange(m_dr, m_i1, m_i2);		
		//if(!m_dp.GetDataRange(m_dr, m_i1, m_i2))
		//{
			//error_report("GetDataRange from dataplot error!");
			//return false;
		//}
		////----Sandy 2008-12-15 Trim missing is Needed
		////if(0 > m_dp.GetDataPoints(0, -1, m_vxEx, m_vyEx))
			////return false;
			//
		/////Sandy 2008-12-23 fix no x col bug
		////Worksheet wksSource;
		////int r1, r2, c1, c2;
		////m_dr.GetRange(0, r1, c1, r2, c1, wksSource);
		//////m_dr.GetRange(1, r1, c2, r2, c2, wksSource);
		////XYRange xyIn(m_dr);
		//
		//if(vx != NULL && vy != NULL)
		//{
			/////Sophy 2/2/2010 FAIL_TO_GET_DATA_WHEN_SRC_X_IS_NOT_NUMERIC
			////DWORD dwPlotID;		
			////if(m_dr.GetData(DRR_GET_MISSING |  DRR_GET_DEPENDENT | DRR_NO_FACTORS, 0, &dwPlotID, NULL, &vy, &vx) < 0)
			//////if(!xyIn.GetData(vy, vx))
			////{
				////error_report("GetData from datarange error!");
				////return false;
			////}
			//if ( m_dp.GetDataPoints(m_i1, m_i2, vx, vy) <= 0 )
			//{
				//error_report("GetDataPoints from DataPlot Error!");
				//return false;
			//}
			/////end FAIL_TO_GET_DATA_WHEN_SRC_X_IS_NOT_NUMERIC
			//
			////Sandy 2008-12-30 REDUCE_INPUT_X
			//m_bHasReduced = _reduce_data(vx, vy);
			////end
		//}
		//
		///*
		//XYRange xyEx;
		//Column colY, colX;
		//
		//if(xyIn.GetXColumn(colX))
			//xyEx.Add(wksSource,  colX.GetIndex(), "X");	
			//
		//if(!xyIn.GetYColumn(colY))
		//{
			//error_report("Invalid col Y of xyrange");
			//return false;
		//}
		//else
			//xyEx.Add(wksSource,  colY.GetIndex(), "Y");	
		//*/
		//
		//
		/////Sandy 2008-12-31 Folger add a new functio to create the full range 
		////XYRange xyIn(m_dr);
  	   ////_get_full_range_data_without_missing(xyIn, m_vyEx, m_vxEx);
  	   /////Sophy 2/2/2010 FAIL_TO_GET_DATA_WHEN_SRC_X_IS_NOT_NUMERIC
		////XYRange xyIn(m_dr);
		////XYRange xyEx;
		////xyIn.MakeFullRowRange(xyEx);        
////
		////if(0 > xyEx.GetData(DRR_GET_DEPENDENT |DRR_NO_FACTORS, 0, NULL, NULL, &m_vyEx, &m_vxEx))
		////{
			////error_report("Get full range data error!");
			////return false;
		////}
		//if ( m_dp.GetDataPoints(0, -1, m_vxEx, m_vyEx) <= 0 )
		//{
			//error_report("Get All Points Error!!!");
			//return false;
		//}
		/////end FAIL_TO_GET_DATA_WHEN_SRC_X_IS_NOT_NUMERIC
		////----end of Trim missing is Needed
//
//
		////Sandy 2008-12-30 REDUCE_INPUT_X
		//bool bHasReduced = _reduce_data(  m_vxEx, m_vyEx);
		////end
			//
		//return true;
	//}
	bool	getData()
	{
		if(!GetData())
		{
			error_report("GetData() form Grobj error!");
			return false;
		}
		///Sophy 5/4/2010 QA82-15364-P2 ROI_TOOLS_OPTION_FOR_SKIP_ALL_MASKED_DATAPOINTS check in base class
		//if ( m_dp.GetDataPoints(m_i1, m_i2, m_vX, m_vY) <= 0 )
		//{
			//error_report("GetDataPoints from DataPlot Error!");
			//return false;
		//}
		///end ROI_TOOLS_OPTION_FOR_SKIP_ALL_MASKED_DATAPOINTS

		///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA		
		//m_bHasReduced = _reduce_data(m_vX, m_vY);
		///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
	
		if ( m_dp.GetDataPoints(0, -1, m_vxEx, m_vyEx) <= 0 )
		{
			error_report("Get All Points Error!!!");
			return false;
		}

		///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
		//_reduce_data(  m_vxEx, m_vyEx);
		///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA

		return true;
	}
	///end IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE

private:
	GraphObject m_goBottom;
	//GraphObject m_goBaseline;
	PolylineGraphObject m_goBaseline;//Sandy 2008-12-8 improve baseline to polyline
	PolylineGraphObject m_goIntegCurve;//sandy 2008-12-2 add integal curve
	PolylineGraphObject m_goDiffCurve;//sandy 2008-12-9 add diff curve
	GraphObject	m_goIntegArea;	///Sophy 3/26/2010 QA80-15244 SHOW_AREA_FOR_ROI_INTEG_TOOL
	//DataRange   m_dr;
	vector      m_vbx;
	vector      m_vby;
	vector      m_vxint;  //Sandy add 2008-12-8 add integral curve
	vector      m_vyint;  //Sandy add 2008-12-8 add integral curve
	double		m_Area;//for quick showing on gr
	//---- CPY 10/1/08 MOVE_DATA_DISPLAY_CODE_TO_BASE_CLASS
//	string		m_strIndexAndX;
//	DataPlot    m_dp;
//	int 		m_i1, m_i2;
//	double 		m_x1, m_x2;
	//----
	///Sophy 4/15/2010 QA81-15287 IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
	///Sophy 5/4/2010 QA82-15364-P2 ROI_TOOLS_OPTION_FOR_SKIP_ALL_MASKED_DATAPOINTS move to base class
	//vector		m_vX;
	//vector		m_vY;
	///end ROI_TOOLS_OPTION_FOR_SKIP_ALL_MASKED_DATAPOINTS
	///end IMPROVE_CODE_OF_GET_DATA_FOR_RECALCULATE
	vector 		m_vxEx;
	vector		m_vyEx;//Sandy 2008-10-28 add for save the full datarange of input data
	
	
	string m_strBaseline;//sandy 2008-10-28 QA80-12350-s1 ADD_BASELINE_RESULT
	
	//----Sandy 2008-12-5 add the borderlines of left and right side which may not be the data points.
	double      m_s1; 
	double      m_s2;
	///---end
	
	//---Sandy 2008-12-9 add difference curve
	vector      m_vxdiff;
	vector      m_vydiff;
	//---end
	
	bool 		m_bShowBaseline;
	bool 		m_bShowDiffCurve;
	int         m_bShowIntegCurve;
	
	bool		m_bHasReduced; //Sandy 2008-12-30 add for report data if need reduce
};

enum{
	QT_INTEG_FIT_LIMITS_RECT = 0,
	QT_INTEG_FIT_LIMITS_RECT_WITH_EXTRAPOLATE,
	QT_INTEG_FIT_LIMITS_DATA,
};

enum{
	_QT_INTEG_POS_ID_BASELINE,
	_QT_INTEG_POS_ID_INTEG_CURVE,
	_QT_INTEG_POS_ID_DIFF_CURVE
};

//Sandy 2008-12-24 Joe suggestion split "rectangle" to with extrapolate or not
//static int _is_fit_integal_limit_to_rectange(TreeNode& trGUI)
static bool _is_fit_integal_limit_to_rectange(TreeNode& trGUI, bool& bNeedExtrapolate)
{
	TreeNode& trIntegralLimit = trGUI.integlimit.fitlimit;
	int nFitLimit = trIntegralLimit.nVal;
	
	//return nFitLimit;
	bool bLimitRect;
	switch(nFitLimit)
	{
	case QT_INTEG_FIT_LIMITS_RECT:
		bLimitRect = true;
		bNeedExtrapolate = false;
		break;
		
	case QT_INTEG_FIT_LIMITS_RECT_WITH_EXTRAPOLATE:
		bLimitRect = true;
		bNeedExtrapolate = true;
		break;
	case QT_INTEG_FIT_LIMITS_DATA:
		bLimitRect = false;
		bNeedExtrapolate = false;
		break;
	default:
		error_report("Invalid argument! in _is_fit_integal_limit_to_rectange");
		break;
	}
	
	return bLimitRect
}

static bool _reduce_data(vector& vx, vector& vy)
{
	int nSize  = vx.GetSize();
	int nNoRepeatSize = ocmath_xy_remove_duplicates(vx, vy, nSize,  Replace_With_Mean, 1.0e-20);
	if(0 > nNoRepeatSize)
	{
		error_report("error return from ocmath_xy_remove_duplicates");
		return false;
	}
	if(nSize != nNoRepeatSize)
	{
		vx.SetSize(nNoRepeatSize);
		vy.SetSize(nNoRepeatSize);
		return true;
	}
	else
		return false;
}

///------ Folger 04/27/10 QA81-15364 GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA
/*
///Sophy 3/30/2010 QA81-15244-P1 REMOVE_MISSING_VALUE_WHEN_CONTRUCT_SHADE_AREA
static	bool	_remove_missing_values_and_sort(vector& vX, vector& vY, DWORD dwSortOptions, vector& vxRef = NULL, vector& vyRef = NULL)
{
	ASSERT(vX.GetSize() == vY.GetSize());
	if ( vX.GetSize() != vY.GetSize() || vX.GetSize() == 0 )
		return false;
	
	vector<uint> vnXMissing, vnYMissing;
	if ( vX.Find(MATREPL_TEST_EQUAL, NANUM, vnXMissing) > 0
		|| vY.Find(MATREPL_TEST_EQUAL, NANUM, vnYMissing) > 0 )
	{
		vector<int> vnMissing;
		vnMissing = vnXMissing;
		vnMissing.Append(vnYMissing);
		vX.RemoveAt(vnMissing);
		vY.RemoveAt(vnMissing);
	}	

	vector<uint> vnIndices;
	vX.Sort(dwSortOptions, TRUE, vnIndices);
	vY.Reorder(vnIndices);
	return true;
}
///end REMOVE_MISSING_VALUE_WHEN_CONTRUCT_SHADE_AREA
*/
///------ End GADGET_INTEGRATE_RUNTIME_ERROR_ON_MASKED_DATA

/*
//static bool	_update_integral_curve(GraphObject go, TreeNode& trGUI, vector& vIntgCurve)
static bool	_update_integral_curve(GraphLayer gl, TreeNode& trGUI, vector& vIntgCurve)
{
	TreeNode trIntegCurve = trGUI.integcurve;
	//TreeNode trRestrict = trIntegCurve.restrict;
	TreeNode trDisplay = trIntegCurve.integcurve;
	TreeNode trMultiply = trIntegCurve.multiply;
	
	//GraphObject go = *pgo;
	
	if(!trIntegCurve ||!trRestrict ||!trMultiply)
	{
		
		error_report("Invalid object in _update_integral_curve() ");
		return false;
	}

	double dMultiply = trMultiply.dVal;
	//bool bRestrict = trRestrict.nVal;
	int nIntegCurDisplay = trDisplay.nVal;
	
	//if(bRestrict)
	if(nIntegCurDisplay == INTG_CURVE_RECT)
	{
		//GraphLayer gl;
		//go.GetParent(gl);
		if(gl)
		{
			Scale yaxis(gl.Y);
			double dFrom = yaxis.From;
			double dTo = yaxis.To;
			double dMax, dMin;
			vIntgCurve.GetMinMax(dMin, dMax);
			vIntgCurve = ( (vIntgCurve-dMin)/(dMax-dMin) ) * (dTo - dFrom) + dFrom;
		}
		else
			return false;
	}
	else if(nIntegCurDisplay == INTG_CURVE_FACTOR)
	{
		vIntgCurve = vIntgCurve*dMultiply;
	}
	else// unshow integral curve
	{
		vIntgCurve.SetSize(0);
		return false;
	}
	
	return true;
}
*/
///Sandy 2008-10-28  QA80-12350-s2 ADD_BASELINE_WHEN_EDIT
static bool _edit_baseline_method_event(TreeNode& tr, int nRow, int nType, Dialog& Dlg)
{
	TreeNode trGUI = tr.trGUI;
	if ( !trGUI )
		trGUI = tr;
	_update_gui_baseline_method(trGUI);
	return true;
}


static bool _edit_integcurve_scale_event(TreeNode& tr, int nRow, int nType, Dialog& Dlg)
{
	TreeNode trGUI = tr.trGUI;
	if ( !trGUI )
		trGUI = tr;
	_update_gui_integcurve_scale(trGUI);
	return true;	
}

static bool _edit_appendwks_event(TreeNode& tr, int nRow, int nType, Dialog& Dlg)
{
	TreeNode trGUI = tr.trGUI;
	if ( !trGUI )
		trGUI = tr;
	_update_gui_appendwks(trGUI);
	return true;
}

static void _update_gui_appendwks(TreeNode& trGUI)
{
	if(trGUI)
	{
		trGUI.output.wbkName.Show = (trGUI.output.appendwks.nVal == 1 ? true:false);
	}	
}

static void _update_gui_integcurve_scale(TreeNode& trGUI)
{
	if(trGUI)
	{
		
		TreeNode& trcurves = trGUI.GetNode("curves");
		if(trcurves)
		{
			//TreeNode& trRestrict = trcurves.GetNode("restrict");
			TreeNode& trDisplay = trcurves.GetNode("integcurve");
			TreeNode& trMultiply = trcurves.GetNode("multiply");
			//if(trRestrict && trMultiply)
			if(trDisplay && trMultiply)
			{
				//bool bRestrict = trRestrict.nVal;
				int nDisplayType = trDisplay.nVal;
				//trMultiply.Show = !bRestrict;
				trMultiply.Show = (nDisplayType == INTG_CURVE_FACTOR);
			}
		}
	}	
}
static void _update_gui_baseline_method(TreeNode& trGUI)
{
	if(trGUI)
	{
		
		TreeNode& trBaseline = trGUI.GetNode("baseline");
		if(trBaseline)
		{
			TreeNode& trMethod = trBaseline.GetNode("method");
			if(trMethod)
			{
				int nMethod = trMethod.nVal;
				trBaseline.yvalue.Show = (nMethod == BSM_CONSTANTY ? true:false);
				trBaseline.fixxto.Show = (nMethod == BSM_LINEARINP ? true:false);
				trBaseline.yoffsetleft.Show = (nMethod == BSM_LINEARINP ? true:false);
				trBaseline.yoffsetright.Show = (nMethod == BSM_LINEARINP ? true:false);
				trBaseline.xyrbase.Show = (nMethod == BSM_DATASET ? true:false);
				///Sophy 4/14/2010 QA81-15287 MORE_WORK_ON_INTEGRATION_GADGET
				trGUI.curves.diffcurve.Enable = !(nMethod == BSM_NONE || (nMethod == BSM_CONSTANTY && (trBaseline.yvalue.dVal == 0)));
				///end MORE_WORK_ON_INTEGRATION_GADGET
			}
		}
	}
}
///Sandy end  QA80-12350-s2 ADD_BASELINE_WHEN_EDIT

void peak_integ_output_btn_click(string strGrName) ///Sophy 1/4/2010 leave this function for backward compatibility
{
	
	GraphObject go = get_master_gr(Project.ActiveLayer().GraphObjects(strGrName));
	ASSERT(go);
	
	if(go)
	{
		///Sophy 1/4/2010 QA80-14904-S1 SUPPORT_FLEXIBLE_ATTACHED_GROBJ_FOR_ROI_TOOLS
		//CurvePeakIntegTool itool(go.GetName());
		//
		//if(!itool.IsValidLayer())
		//{
			//error_report("invalid layer!");
			//return;
		//}
		//
		//itool.doOutput();
		addtool_curve_integ_events(go.GetName(), OE_BUTTONCLICK, GOT_BTN_OUTPUT);
		///end SUPPORT_FLEXIBLE_ATTACHED_GROBJ_FOR_ROI_TOOLS
	}

}	
	
//---- CPY 9/24/08 ADD_EDIT_BUTTON_TO_PEAK_INTEG_TOOL
void curve_peak_integ_edit_btn_click(string strGrName) ///Sophy 1/4/2010 leave this function for backward compatibility
{
	GraphObject go = get_master_gr(Project.ActiveLayer().GraphObjects(strGrName));
	///Sophy 12/30/2009 QA80-14904-S1 SUPPORT_FLEXIBLE_ATTACHED_GROBJ_FOR_ROI_TOOLS
	if ( go )
		go = get_master_gr(go); //now "..." is not attach to main rectangle object, so need to get it.
	///end SUPPORT_FLEXIBLE_ATTACHED_GROBJ_FOR_ROI_TOOLS
	if(go)
	{
		///Sophy 1/4/2010 QA80-14904-S1 SUPPORT_FLEXIBLE_ATTACHED_GROBJ_FOR_ROI_TOOLS
		//CurvePeakIntegTool itool(go.GetName());
		//itool.doEdit();
		addtool_curve_integ_events(go.GetName(), OE_BUTTONCLICK, GOT_BTN_EDIT);
		///end SUPPORT_FLEXIBLE_ATTACHED_GROBJ_FOR_ROI_TOOLS
	}
}
//----

//must be in the form of XFNAME_events
void addtool_curve_integ_events(string strGrName, int nEvent, int nMsg = 0)
{
	CurvePeakIntegTool itool;
	//itool.OnEvent(nEvent, nMsg);
	graphobjtool_events(itool, strGrName, nEvent, nMsg);
}


//static   void   _get_full_range_data_without_missing(XYRange xy, vector& vY, vector& vX)
//{
//
	//string strY, strX, strYErr;
	//xy.GetDatasetNames(strY, strX, strYErr);
	//{
		//Dataset dsY(strY);
		//if ( dsY )
			//vY = dsY;
		//
		//if ( vX )
		//{
			//Dataset dsX(strX);
			//if ( dsX )
				//vX = dsX;
		//}
	//}
	//
	///* --- bad solution
	////int nIndex = 0;
    ////vector vErr;
	////xyIn.GetData(vY, vX, &vErr, nIndex,  DRR_GET_MISSING);
	//*/
	//
//
	/////Trim missing
	//vX.SetSize(vY.GetSize());
	//vector vTemp;
	//vTemp = vY*vX;
	//vTemp.Replace(NANUM, 1, MATREPL_TEST_LESSTHAN|MATREPL_TEST_GREATER);
	//vY *= vTemp;
	//vX *= vTemp;
	//vY.Trim();
	//vX.Trim();
	//*/
//}

//bool pointsOnGraphEvent(TreeNode& trGUI, int nRow, int nCol, TreeNode& trNode, DWORD dwCntrl, int nType, WndContainer& theDlg)
//{
	//if(!(dwCntrl & GETNEVENT_ON_INIT))
	//{
		//if(trNode.tagName == "gpointedit")
		//{
			/////doing
		//}
		//return true;
	//}
	//return false;
//}

void addtool_curve_integ(const TreeNode& trGUI)
{
	
	CurvePeakIntegTool itool;
	///Sophy 8/21/2009 QA80-14175 CREATE_ALL_NODES_IN_ONE_TREE_TO_GET_RID_OF_OPTIONS_BRANCH
	//int nErr = itool.Create(XFNAME, color, 0, trGUI);
	int nErr = itool.Create(XFNAME, 0, trGUI);
	///end CREATE_ALL_NODES_IN_ONE_TREE_TO_GET_RID_OF_OPTIONS_BRANCH
	if(nErr < 0)
	{
		XF_THROW(XFERR_INVALID_GRAPH_LAYER);
		return;
	}
	if(nErr)
		error_report("addtool_curve_integ failed Init");
	
}

//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int addtool_curve_integ_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return addtool_curve_integ_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	///Sophy 1/22/2010 CENTRALIZE_OPEN_PREFERENCE_DIALOG_TO_BASE_CLASS
	/*
	TreeNode& trGUI = trGetN.GetNode("trGUI");
	if(trGUI)
	{
		_update_gui_baseline_method(trGUI);
		_update_gui_appendwks(trGUI);
		_update_gui_integcurve_scale(trGUI);
		return true;		///------ Folger 04/07/09 CHANGE_BASELINE_METHOD_FAILS_TO_UPDATE_GETN
	}
	*/
	///end CENTRALIZE_OPEN_PREFERENCE_DIALOG_TO_BASE_CLASS
	
	///Sophy 1/29/2010 QA80-14995-P2 CHECK_UPDATE_REPORT_WORKSHEET_NAME_FOR_ROI_TOOLS
	if ( GETNE_ON_INIT == nEventID || GETNE_ON_THEME == nEventID || 0 == lstrcmpi(lpcszNodeName, "wbkName") )
	{
		string strBookSheetName = trGetN.trGUI.output.wbkName.strVal;
		if ( !check_update_worksheet_name(strBookSheetName) )
		{
			trGetN.trGUI.output.wbkName.strVal = strBookSheetName; //update report book sheet name
			strErrMsg = CER_SHEET_NAME_ILLEGAL_CHAR;
		}
	}
	///end CHECK_UPDATE_REPORT_WORKSHEET_NAME_FOR_ROI_TOOLS	
	return false;

}

int addtool_curve_integ_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	if(tr.IsValid())
	{
		int nBranchID = 1;
		int nUserID = GET_USER_DATAID(0);
		string strVarName = lpcszVarName;
		if(strVarName == "trGUI")
		{
			GETN_USE(tr)
			GETN_OPTION_BRANCH(GETNBRANCH_OPEN)
			///Sophy 1/19/2010 SHOW_TOOLNAME_FOR_ROI_TOOLS
			GETN_STR(toolname, STR_TOOLNAME, TOOLNAME)	GETN_ID(INTEG_TOOLNAME_ID)	GETN_CONTROL_OPTION_BOX(0)
			///end SHOW_TOOLNAME_FOR_ROI_TOOLS
			///Sophy 8/21/2009 QA80-14175 CREATE_ALL_NODES_IN_ONE_TREE_TO_GET_RID_OF_OPTIONS_BRANCH
			GETN_COLOR(rectcolor, STR_FILL_COLOR, 20)	GETN_COLOR_CHOICE_OPTIONS(COLORLIST_CUSTOM | COLORLIST_SINGLE) GETN_ID(nUserID++)
			///end CREATE_ALL_NODES_IN_ONE_TREE_TO_GET_RID_OF_OPTIONS_BRANCH
			//---Sandy 2008-12-2 QA80-12263-S2 REPOSITION_LABEL_FOR_MORE_CLEARER
			//GETN_CHECK(showtop, _L("Show Area on Center-Top"), 1)	GETN_ID(nUserID++)
			//GETN_CHECK(showbottom, _L("Show X Range on Center-Bottom"), 1)	GETN_ID(nUserID++)
			GETN_CHECK(showtop, _L("Show Area/X Range on Center-Top"), 1)	GETN_ID(nUserID++)
			//---end QA80-12263-S2 REPOSITION_LABEL_FOR_MORE_CLEARER
			
			//GETN_CHECK(baseline, _L("Simple Straight Line Baseline"), 1) GETN_ID(nUserID++)	
			///Kyle 09/17/2010 ORG-1083-P1 ADD_AREA_TYPE_FOR_ROI_INTEG_TOOL
			GETN_LIST(areatype, _L("Area Type"), 0, _L("Mathematical Area|Absolute Area"))		GETN_ID(INTEG_AREA_TYPE_ID)
			///End ADD_AREA_TYPE_FOR_ROI_INTEG_TOOL
		
			///Sandy 2008-12-2 add integral limit
			nUserID = GET_USER_DATAID(0) + 100; 
			GETN_BEGIN_BRANCH(integlimit, _L("Integration Limits"))								GETN_ID_BRANCH(nBranchID++)  GETN_OPTION_BRANCH(GETNBRANCH_OPEN) 
				//Sandy 2008-12-24 Joe suggestion split "rectangle" to with extrapolate or not
				//GETN_LIST(fitlimit, _L("Fit Limits To"), 0,  _L("Rectangle|Data Points"))			GETN_ID(nUserID++)	
				GETN_LIST(fitlimit, _L("Fit Limits To"), 0,  _L("Interpolate to Rectangle Edge|Interpolate/Extrapolate to Rectangle Edge|Data Points"))			GETN_ID(nUserID++)
				//---- CPY 4/16/10 SHOW_INTEG_AREA_SHOULD_BE_ON_BY_DEFAULT
				//GETN_CHECK(showIntegArea, _L("Show Integrated Area"), 0)							GETN_ID(INTEG_SHOWAREA_ID)	///Sophy 3/26/2010 QA80-15244 SHOW_AREA_FOR_ROI_INTEG_TOOL
				GETN_CHECK(showIntegArea, _L("Show Integrated Area"), 1)							GETN_ID(INTEG_SHOWAREA_ID)	///Sophy 3/26/2010 QA80-15244 SHOW_AREA_FOR_ROI_INTEG_TOOL
				//----
			GETN_END_BRANCH(integlimit)
			///end
			
			////sandy 2008-10-10 add baseline options
			nUserID = GET_USER_DATAID(0) + 200; 
			GETN_BEGIN_BRANCH(baseline, _L("Baseline"))								GETN_ID_BRANCH(nBranchID++)	//GETN_OPTION_BRANCH(GETNBRANCH_OPEN) 
				//GETN_LIST(method, _L("Method"), 0, _L("None|Constant Y|Straight Line"))	GETN_ID(nUserID++)
				GETN_LIST(method, _L("Method"), 0, _L("None|Constant Y|Straight Line|Dataset"))	GETN_OPTION_EVENT(_edit_baseline_method_event)	GETN_ID(nUserID++)///Sandy 2008-12-8 add dataset baseline
				GETN_NUM(yvalue, _L("Y = "), 0)													GETN_OPTION_EVENT(_edit_baseline_method_event)	GETN_ID(nUserID++)
				///Sandy 2008-12-2 QA80-12263 CHANGE_DEFAULT_SETTING_FOR_EASWAR_SUGGESTION
				//GETN_LIS-T(fixxto, _L("Fix x to "), 0, _L("Entire Data|Rectangle|Data Range"))		   			GETN_ID(nUserID++)
				GETN_LIST(fixxto, _L("Fix x to "), 1, _L("Entire Data|Rectangle|Scale"))		   			GETN_ID(nUserID++)
				GETN_NUM(yoffsetleft, _L("Y offset of left"), 0)									GETN_ID(nUserID++)
				GETN_NUM(yoffsetright, _L("Y offset of right"), 0)									GETN_ID(nUserID++)
				GETN_XYRANGE(xyrbase, _L("Baseline Dataset"), 1, "")                                GETN_ID(nUserID++) ///Sandy 2008-12-8 add dataset baseline 
				///------ Folger 04/30/10 QA81-15287-P1 GADGET_INTEGRATE_SHOUND_NOT_REMEMBER_BASELINE_DATASET
				GETN_OPTION_THEME_APPLICAPABILITY(XVTA_DO_NOT_APPLY_VALUE | XVTA_DO_NOT_APPLY_ATTRIBUTES)
				///------ End GADGET_INTEGRATE_SHOUND_NOT_REMEMBER_BASELINE_DATASET
							
				//GETN_BUTTON_GROUP(gpointedit, _L("Points"), 0, "Add|Modify/Del|Clean All")  			GETN_OPTION_EVENT_EX(pointsOnGraphEvent)
	            //GETN_XYRANGE(xybase, _L("Data"), 1, PDS_UNASSIGNED)									GETN_ID(nUserID++)	
			GETN_END_BRANCH(baseline)
			//add end			
			
			///Sandy 2008-12-2 add integral curve only for display
			nUserID = GET_USER_DATAID(0) + 300; 
			GETN_BEGIN_BRANCH(curves, _L("Curves"))								GETN_ID_BRANCH(nBranchID++)  //GETN_OPTION_BRANCH(GETNBRANCH_OPEN) 
				GETN_CHECK(diffcurve, _L("Difference Curve"), 0)									GETN_ID(nUserID++)
				//----Sandy 2008-12-9 add control of unshow integral curve
			    GETN_LIST(integcurve, _L("Integral Curve"), 0,  _L("None|Restrict to Rectangle|True Value"))			GETN_ID(nUserID++)	GETN_OPTION_EVENT(_edit_integcurve_scale_event)
				//GETN_CHECK(restrict, _L("Restrict to Rectangle"), 1)						GETN_ID(nUserID++)	
				GETN_NUM(multiply, _L("Multiply by"), 1)									GETN_ID(nUserID++)
				//----end
			GETN_END_BRANCH(curves)
			///end
			
			nUserID = GET_USER_DATAID(0) + 400; //CPY 9/24/08, reset to ensure unique for each branch regardless of insert
			GETN_BEGIN_BRANCH(output, _L("Output To"))	GETN_ID_BRANCH(nBranchID++)  //GETN_OPTION_BRANCH(GETNBRANCH_OPEN) 
				GETN_CHECK(script, _L("Script Window"), 1)									GETN_ID(nUserID++)
				GETN_CHECK(reslog, _L("Results Log"), 0)									GETN_ID(nUserID++)
				GETN_CHECK(useLongName, _L("Long Name in Results Log/Script Window"), 1) 	GETN_ID(nUserID++)
				GETN_CHECK(appendwks, _L("Append to Worksheet"), 0)							GETN_ID(nUserID++)	GETN_OPTION_EVENT(_edit_appendwks_event)
				GETN_STR(wbkName, _L("Result Workbook Name"), "[QkInteg]Result") 					GETN_ID(nUserID++)				
			GETN_END_BRANCH(output)
			
			
			nUserID = GET_USER_DATAID(0) + 500; //CPY 9/24/08, reset to ensure unique for each branch regardless of insert
			GETN_BEGIN_BRANCH(quantities, _L("Quantities"))								GETN_ID_BRANCH(nBranchID++)  GETN_OPTION_BRANCH(GETNBRANCH_OPEN)
				GETN_CHECK(name, _L("Dataset Name"), 1)								GETN_ID(nUserID++)
				GETN_CHECK(begin_row, _L("Beginning Row Index"), 1) 							GETN_ID(nUserID++)
				GETN_CHECK(end_row, _L("Ending Row Index"), 1) 							GETN_ID(nUserID++)
				GETN_CHECK(begin_x, _L("Beginning X"), 1)								GETN_ID(nUserID++)
				GETN_CHECK(end_x, _L("Ending X"), 1)								GETN_ID(nUserID++)
				///Kyle 09/17/2010 ORG-1082-P1 RENAME_OUTPUT_TABEL_LABELS
				/*
				GETN_CHECK(ph, _L("Peak Height"), 0)								GETN_ID(nUserID++)
				GETN_CHECK(pc, _L("Peak Center"), 1)								GETN_ID(nUserID++)
				GETN_CHECK(pa, _L("Peak Area"), 1)									GETN_ID(nUserID++)
				GETN_CHECK(pcd, _L("Peak Centroid"), 0)								GETN_ID(nUserID++)
				*/
				GETN_CHECK(ph, _L("Max Height"), 0)								GETN_ID(nUserID++)
				GETN_CHECK(pc, _L("X at YMax"), 1)								GETN_ID(nUserID++)
				GETN_CHECK(pa, _L("Area"), 1)									GETN_ID(nUserID++)
				GETN_CHECK(pcd, _L("Centroid"), 0)								GETN_ID(nUserID++)
				///End RENAME_OUTPUT_TABEL_LABELS
				GETN_CHECK(pfwhm, _L("FWHM"), 0)									GETN_ID(nUserID++)
				GETN_CHECK(plhw, _L("Left Half Width"), 0)							GETN_ID(nUserID++)
				GETN_CHECK(prhw, _L("Right Half Width"), 0)							GETN_ID(nUserID++)
				GETN_CHECK(pymax, _L("Y Max"), 0)									GETN_ID(nUserID++)
				///Kyle 09/17/2010 ORG-1082-P1 RENAME_OUTPUT_TABEL_LABELS
				//GETN_CHECK(pxofymax, _L("X Index of Peak Center"), 0)				GETN_ID(nUserID++)		
				GETN_CHECK(pxofymax, _L("Index of X at YMax"), 0)				GETN_ID(nUserID++)		
				///End RENAME_OUTPUT_TABEL_LABELS
				GETN_CHECK(base, _L("Baseline"), 1)									GETN_ID(nUserID++)//sandy 2008-10-28 QA80-12350-s1 ADD_BASELINE_RESULT
			GETN_END_BRANCH(quantities)
			tr.quantities.SetAttribute(STR_ATTRIB_BRANCH, GETNBRANCH_CHECK_CONTROL);
		}
	}
	
	return 0;
}
//nGetNDialog = 0,1,2, corresponding to the XF GetN dropdown, 0 = dialog is not used
//you can change nRet to be one of XFEVT_PROCEED (defualt), XFEVT_ABORT, XFEVT_PROCEED_NO_DLG or XFEVT_PROCEED_WITH_DLG(when nGetNDialog = 0)
//nGetNDialog = -1 when Ok on GetN dialog to allow handler to preocess <auto> etc variables
//dwCntrl is combination of bits
//LTXF_FROM_GUI_MENU, LTXF_FROM_GUI_PROMPT, LTXF_FROM_AUTO_UPDATE, LTXF_FROM_FUNCTION, LTXF_THEME_USED, LTXF_CHANGE_PARAM
void addtool_curve_integ_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	if ( is_xf_startup(nGetNDialog, dwCntrl) )
	{
		if(is_use_origin_chm())
			trGetN.SetAttribute(STR_HELPID_ATTRIB, IDD_XF_addtool_curve_integ);
	}
	
	///Sophy 1/29/2010 QA80-14995-P2 CHECK_UPDATE_REPORT_WORKSHEET_NAME_FOR_ROI_TOOLS
	if ( 0 == nGetNDialog || -1 == nGetNDialog )
	{
		if ( !O_QUERY_BOOL(dwCntrl, LTXF_SHOW_DIALOG) )
		{
			string strBookSheetName = trGetN.trGUI.output.wbkName.strVal;
			if ( !check_update_worksheet_name(strBookSheetName) )
			{
				trGetN.trGUI.output.wbkName.strVal = strBookSheetName; //update report book sheet name
				dwCntrl |= LTXF_SHOW_DIALOG;
			}			
		}
	}
	///end CHECK_UPDATE_REPORT_WORKSHEET_NAME_FOR_ROI_TOOLS
	
}
//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int addtool_curve_integ_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
