#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
//put additional include files here
#include <..\originlab\grobj_utils.h>
#include <..\originlab\GraphObjTools.h> ///---Sim 01-08-2010 QA81-14930 CLEAN_GRAPH_OBJ_TOOLS
#include <ocmsp.h>
#include <o8dlg.h>
/*------------------------------------------------------------------------------*
 * Modification Log:															*
 *	Folger 09/24/08 SHOULD_NOT_OUTPUT_UNNECESSARY_RESULTS						*
 *	YuI 10/09/08 QA70-12265-P3 CURVE_STATS_QUICK_TOOL_MUST_BE_SMARTER			*
 *	CPY 11/02/08 QA70-12504 BETTER_DATAPLOT_NAME_DISPLAY						*
 *	Sophy 8/5/2009 MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS				*
 *	Sophy 8/12/2009 ADD_LOCAL_EXTREME_METHOD_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING_TOOLS
 *	Sophy 8/12/2009 IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT			*
 *	Sophy 8/13/2009 IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE	*
 *	Sophy 8/14/2009 ADD_FLEXIBLE_PARAM_FOR_MORE_USER_OPTIONS					*
 *	Sophy 8/19/2009 UPDATE_MARKERS_FORMAT_TREE_IN_SINGLE_TRANSACTION			*
 *	Sophy 8/19/2009 OUTPUT_RESULT_TO_SCRIPT_WINDOW_SHOULD_BE_BETTER_DISPLAYED	*
 *	Sophy 8/20/2009 RISETTIME_TOOL_INDICATOR_USE_MARKER_GRAPHOBJECT				*
 *	Sophy 8/21/2009 RISETIME_RISERANGE_LINE_NOT_SHOW_WHEN_RUN_RISETIME_FOR_THE_FIRST_TIME
 *	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 9/1/2009 BETTER_DISPLAY_TOP_LABEL_LIKE_CURE_INTEG_TOOL_DOES			*
 *	Sophy 9/1/2009 GIVE_BETTER_LABELS_FOR_RESULT_TREE							*
 *	Sophy 9/11/2009 CLEAR_CUSTOMER_INPUT_WHEN_AUTO_LOW_HIGH_VOLT				*
 *	Sophy 10/9/2009 USER_DEFINED_VOLT_LEVEL_BOUND_NOT_APPLICABLE_WHEN_USE_LOCAL_EXTREME_METHOD
 *	Sophy 11/6/2009 QA80-14598-P1 FORCE_XF_COMPILE_WHEN_CLICK_ATTACH_GROBJ_AFTER_LOAD_GRAPPH
 *	Sophy 11/11/2009 OUTPUT_BOOK_NAME_CHANGED_WHEN_REOPEN_DLG_TO_CHANGE_SETTINGS*
 *	Sophy 11/25/2009 QA80-14719 PROPER_LOW_HIGN_LEVEL_FINDING					*
 *	Sophy 11/26/2009 EVT_HANDLER_IN_TREENODE_INVALID_WHEN_RESTART_ORIGIN		*
 *	Sophy 12/3/2009 QA80-14686 CENTRALIZE_CODE_FOR_UPDATE_RESULT_ON_RESCALE_GRAPH
 *	Sophy 12/14/2009 QA80-14686-P2 DATAPLOT_GET_DATAPOINTS_NEED_TO_SKIP_MASKED_DATA
 *	Sophy 12/17/2009 QA80-14598-P4 RISE_TIME_TOOL_NEED_CREATE_LONGNAME_IN_RESULT_COLUMN
 *	Sophy 12/30/2009 QA80-14904-S1 SUPPORT_FLEXIBLE_ATTACHED_GROBJ_FOR_ROI_TOOLS
 *	Sim 01-08-2010 QA81-14930 CLEAN_GRAPH_OBJ_TOOLS								*
 *	Sophy 10/15/2010 ORG-1263-P1 UPDATE_INDICATOR_SETTINGS_FOR_RISETIME_TOOL	*
 *------------------------------------------------------------------------------*/
//put your own support static functions here

#define XF_NAME		"addtool_rise_time"
#define	TOOLNAME	_L("Gadget Rise Time")
#define	TOOL_PREFERENCES_TITLE	_L("Rise Time")

#define _MARKER_SIZE 10

///Sophy 6/12/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
//indicate whether valid risetime found
#define	STR_RISETIME_STATUS	"RiseTimeStatus"
enum {
	GET_SUCCESS = 0,
	GET_NO_DATA = 1,
	GET_NO_RISETIME = 2
};
///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING

///Sophy 6/17/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
#define	STR_RESULT_WKS_RISETIME	"[QkRiseTime]Result"
#define	STR_RESULT_WKS_FALLTIME	"QkFallTime"

#define	STR_RISETIME	_L("RiseTime")
#define	STR_FALLTIME	_L("FallTime")
#define	STR_RISE_RANGE	_L("Rise Range")
#define	STR_FALL_RANGE	_L("Fall Range")
#define	STR_RISE_TIME	_L("Rise Time")
#define	STR_FALL_TIME	_L("Fall Time")

#define	STR_RISE_RANGE_QT	_L("Rise Range(dVref)")
#define	STR_FALL_RANGE_QT	_L("Fall Range(dVref)")
#define	STR_RISE_TIME_QT	_L("Rise Time(dT)")
#define	STR_FALL_TIME_QT	_L("Fall Time(dT)")
///Sophy 11/5/2009 QA80-14598-S4 OUTPUT_MORE_RESULT
#define	STR_RISE_VELOCITY	_L("Rise Velocity(Velocity)")
#define	STR_FALL_VELOCITY	_L("Fall Velocity(Velocity)")
#define	STR_MAX_RISE_VELO	_L("Maximum Rise Velocity(MaxVelocity)")
#define	STR_MAX_FALL_VELO	_L("Maximum Fall Velocity(MaxVelocity)")
///end OUTPUT_MORE_RESULT
///Sophy 8/12/2009 IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT
#define	STR_SMOOTH_PTS_ON_RISE	_L("Smooth Points on Rising Area")
#define	STR_SMOOTH_PTS_ON_FALL	_L("Smooth Points on Falling Area")
///end IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT
#define	STR_RISETIME_FALLTIME_TOOLS	_L("Rise Time|Fall Time")
///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING

///Sophy 9/1/2009 GIVE_BETTER_LABELS_FOR_RESULT_TREE
#define	STR_RESULTS_RISE_TIME	_L("Results of Rise Time")
#define	STR_RESULTS_FALL_TIME	_L("Results of Fall Time")
///end GIVE_BETTER_LABELS_FOR_RESULT_TREE

///Sophy 6/26/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
///Sophy 8/12/2009 ADD_LOCAL_EXTREME_METHOD_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING_TOOLS
//#define	STR_LINEAR_HISTOGRAM_METOHDS	"Linear Search|Histogram"
#define	STR_LINEAR_HISTOGRAM_METOHDS	_L("Linear Search|Histogram|Largest Triangle")
///end ADD_LOCAL_EXTREME_METHOD_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING_TOOLS

static int METOHDS[] = 
{
	RTIME_LINEAR_SEARCH,
	RTIME_HISTOGRAM, 
	///Sophy 8/12/2009 ADD_LOCAL_EXTREME_METHOD_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING_TOOLS
	RTIME_LOCAL_EXTREME
	///end ADD_LOCAL_EXTREME_METHOD_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING_TOOLS
};
///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING

///Sophy 11/25/2009 QA80-14719 PROPER_LOW_HIGN_LEVEL_FINDING
#define	LN_SEARCH_OPTION_LIST			_L("Average|Maximal Mean")
static int LN_SEARCH_OPTIONS[] = 
{
	MINMAX_AVERAGE,
	MINMAX_MAXIMAL_MEAN
};
///end PROPER_LOW_HIGN_LEVEL_FINDING
///Sophy 8/5/2009 MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS
#define	STR_OPTIONS_ON_RESCALE			_L("Update Results|Invalidate Results")
#define	STR_OPTIONS_NOISE_LEVEL_UNITS	_L("Absolute Value|Relative to Step Size")
///end MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS
enum{
	_QT_RISETIME_POS_ID_POINT_T1,
	_QT_RISETIME_POS_ID_POINT_T2,
	
	_QT_RISETIME_POS_ID_H_VOLT,
	_QT_RISETIME_POS_ID_L_VOLT,
	
	//_QT_RISETIME_POS_ID_RISE_TRACE,
};

///Sophy 12/2/2009 RISETIME_TOOL_FAIL_TO_USE_OLD_THEME
//from now on, when we add new Nodes to GUI, should not enum ID with (nUserID++) when make tree, better use separate IDs
#define	NEW_ID_BEGIN	(GET_USER_DATAID(0) + 200)
enum TOOL_NEW_NODE_ID{
	TOOL_VELOCITY_ID 		= NEW_ID_BEGIN,
	TOOL_MAX_VELOCITY_ID,
	TOOL_MINMAX_FIND_METHOD_ID,
	///Sophy 1/19/2010 SHOW_TOOLNAME_FOR_ROI_TOOLS
	TOOL_TOOLNAME_ID,
	///end SHOW_TOOLNAME_FOR_ROI_TOOLS
};
///end RISETIME_TOOL_FAIL_TO_USE_OLD_THEME

////XF_NAME_events
void addtool_rise_time_events(string strGrName, int nEvent, int nMsg = 0)
{
	///---Sim 01-08-2010 QA81-14930 CLEAN_GRAPH_OBJ_TOOLS
	//RiseTimeTool sTool(strGrName);
	////sTool.OnEvent(nEvent, nMsg);
	//graphobjtool_events(sTool, nEvent, nMsg);
	RiseTimeTool sTool;
	graphobjtool_events(sTool, strGrName, nEvent, nMsg);
	///---END QA81-14930 CLEAN_GRAPH_OBJ_TOOLS
}

void rise_time_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
		//RiseTimeTool itool(go.GetName());
		//
		//if(!itool.IsValidLayer())
		//{
			//error_report("invalid layer!");
			//return;
		//}
		//
		//itool.DoOutput();
		addtool_rise_time_events(go.GetName(), OE_BUTTONCLICK, GOT_BTN_OUTPUT);
		///end SUPPORT_FLEXIBLE_ATTACHED_GROBJ_FOR_ROI_TOOLS
	}
}

///Sophy 6/12/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
void	rise_time_edit_btn_click(string strName) ///Sophy 1/4/2010 leave this function for backward compatibility
{
	GraphObject go = get_master_gr(Project.ActiveLayer().GraphObjects(strName));
	///Sophy 12/30/2009 QA80-14904-S1 SUPPORT_FLEXIBLE_ATTACHED_GROBJ_FOR_ROI_TOOLS
	if ( go )
		go = get_master_gr(go); //'...' is now attach to '+', should get rect from '+'
	///end SUPPORT_FLEXIBLE_ATTACHED_GROBJ_FOR_ROI_TOOLS
	if ( go )
	{
		///Sophy 1/4/2010 QA80-14904-S1 SUPPORT_FLEXIBLE_ATTACHED_GROBJ_FOR_ROI_TOOLS
		//RiseTimeTool itool(go.GetName());
		//if ( !itool.IsValidLayer() )
		//{
			//error_report("Invalid layer!!!");
			//return;
		//}
		//itool.DoEdit();
		addtool_rise_time_events(go.GetName(), OE_BUTTONCLICK, GOT_BTN_EDIT);
		///end SUPPORT_FLEXIBLE_ATTACHED_GROBJ_FOR_ROI_TOOLS
	}
}
///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING

///Sophy 6/17/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
bool update_GUI_on_tool_type_change(TreeNode& tr, int nRow, int nCtrlType, Dialog& GetNDlg)
{
	TreeNode trGUI = tr.trGUI;
	if ( !trGUI )
		 trGUI = tr; //one click Edit button, tr is trGUI.
	
	int nToolType = trGUI.tool.nVal;
	
	trGUI.input.SetAttribute(STR_LABEL_ATTRIB, ((nToolType == 0) ? STR_RISE_RANGE : STR_FALL_RANGE));
	trGUI.output.dT.SetAttribute(STR_LABEL_ATTRIB, ((nToolType == 0) ? STR_RISE_TIME_QT : STR_FALL_TIME_QT));
	trGUI.output.dVref.SetAttribute(STR_LABEL_ATTRIB, ((nToolType == 0) ? STR_RISE_RANGE_QT : STR_FALL_RANGE_QT));
	///Sophy 11/11/2009 OUTPUT_BOOK_NAME_CHANGED_WHEN_REOPEN_DLG_TO_CHANGE_SETTINGS
	//trGUI.output_to.wbkName.strVal = ((nToolType == 0) ? STR_RESULT_WKS_RISETIME : STR_RESULT_WKS_FALLTIME);
	///end OUTPUT_BOOK_NAME_CHANGED_WHEN_REOPEN_DLG_TO_CHANGE_SETTINGS
	///Sophy 11/5/2009 QA80-14598-S4 OUTPUT_MORE_RESULT
	trGUI.output.Velocity.SetAttribute(STR_LABEL_ATTRIB, (nToolType == 0) ? STR_RISE_VELOCITY : STR_FALL_VELOCITY);
	trGUI.output.MaxVelocity.SetAttribute(STR_LABEL_ATTRIB, (nToolType ==0) ? STR_MAX_RISE_VELO : STR_MAX_FALL_VELO);
	///end OUTPUT_MORE_RESULT

	///Sophy 8/12/2009 IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT
	trGUI.adv.pts2.SetAttribute(STR_LABEL_ATTRIB, ((nToolType == 0) ? STR_SMOOTH_PTS_ON_RISE : STR_SMOOTH_PTS_ON_FALL));
	trGUI.display.risetime.SetAttribute(STR_LABEL_ATTRIB, ((nToolType == 0) ? STR_RISE_TIME : STR_FALL_TIME));
	trGUI.display.riserange.SetAttribute(STR_LABEL_ATTRIB, ((nToolType == 0) ? STR_RISE_RANGE : STR_FALL_RANGE));
	///end IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT
	return true;
}

bool hide_show_output_wkb_name(TreeNode& tr, int nRow, int nCtrlType, Dialog& GetNDlg)
{
	TreeNode trGUI = tr.trGUI;
	if ( !trGUI )
		 trGUI = tr; //one click Edit button, tr is trGUI.
	
	int	nAppendWks = trGUI.output_to.appendwks.nVal;
	trGUI.output_to.wbkName.Show = nAppendWks;
	return true;
}
///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
///Sophy 6/26/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
bool update_GUI_on_method_change(TreeNode& tr, int nRow, int nCtrlType, Dialog& GetNDlg)
{
	TreeNode trGUI = tr.trGUI;
	if ( !trGUI )
		 trGUI = tr; //one click Edit button, tr is trGUI.
	
	int nMethod = trGUI.method.nVal;
	trGUI.adv.pts.Show = (nMethod == 0); //linear
	trGUI.adv.bins.Show = (nMethod == 1); //histogram
	
	///Sophy 8/12/2009 ADD_LOCAL_EXTREME_METHOD_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING_TOOLS
	trGUI.adv.tol.Show = (nMethod != 2); //hide when is largest triangle
	///end ADD_LOCAL_EXTREME_METHOD_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING_TOOLS
	///Sophy 10/9/2009 USER_DEFINED_VOLT_LEVEL_BOUND_NOT_APPLICABLE_WHEN_USE_LOCAL_EXTREME_METHOD
	trGUI.input.highVolt.Show = (nMethod != 2);
	trGUI.input.lowVolt.Show = (nMethod != 2);
	///end USER_DEFINED_VOLT_LEVEL_BOUND_NOT_AVAIBLE_WHEN_USE_LOCAL_EXTREME_METHOD
	///Sophy 11/25/2009 QA80-14719 PROPER_LOW_HIGN_LEVEL_FINDING
	trGUI.adv.lnsearch.Show = (nMethod == 0);
	///end PROPER_LOW_HIGN_LEVEL_FINDING
	return true;
}
///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING

///Sophy 5/4/2010 QA82-15353 MORE_WORK_ON_RISETIME_AUTO_INIT_HIGH_LOW_STATE_LEVEL
#define	STR_OLDVOLT_VALUE	"OldVoltValue"
static	bool	_init_high_low_state_value(TreeNode& trGUI)
{
	
	GraphLayer gl = Project.ActiveLayer();
	DataPlot dpSrc;
	if ( gl && (dpSrc = gl.DataPlots()) )
	{
		vector vX, vY;
		///Sophy 6/8/2010 ORG-238 PROPER_INIT_VALUES_FOR_HIGH_LOW_STATE_LEVEL
		//dpSrc.GetDataPoints(0, -1, vX, vY);
		vector vAllX, vAllY;
		int nSize = dpSrc.GetDataPoints(0, -1, vAllX, vAllY);
		vAllX.GetSubVector(vX, nSize * 0.3, nSize * 0.7);
		vAllY.GetSubVector(vY, nSize * 0.3, nSize * 0.7);
		///end PROPER_INIT_VALUES_FOR_HIGH_LOW_STATE_LEVEL
		
		///end PROPER_INIT_VALUES_FOR_HIGH_LOW_STATE_LEVEL
		RiseTimeResult result;
		return ( OE_NOERROR == _find_rise_or_fall_time(trGUI, vX, vY, result) );
	}
	return false;
}

static	int	_find_rise_or_fall_time(const TreeNode& trGUI, vector& vX, vector& vY, RiseTimeResult& result)
{
	if ( !trGUI )
		return false;
	
	int nToolType = trGUI.tool.nVal;
	double dFrom = trGUI.input.from.dVal/100;
	double dTo = trGUI.input.to.dVal/100;
	double dTol = trGUI.adv.tol.dVal;
	int nPts = trGUI.adv.pts.nVal;
	int nPtsEx = trGUI.adv.pts2.nVal;
	int nBins = trGUI.adv.bins.nVal;
	int nMethod = METOHDS[trGUI.method.nVal];
	int nLNOption = LN_SEARCH_OPTIONS[trGUI.adv.lnsearch.nVal];
	
	RiseTimeParams params;
	params.dLowLevelRefer = dFrom;
	params.dHighLevelRefer = dTo;
	params.nMethod = nMethod;
	params.dTolerance = dTol;
	params.nSmoothPoints = nPts;
	params.nSmoothPointsEx = nPtsEx;
	params.nBins = nBins;
	params.bAveVal = TRUE;
	params.nMinMaxFindingMethod = nLNOption;
	BOOL bForward = (nToolType == 0) ? TRUE : FALSE;

	TreeNode trHighVolt = trGUI.input.highVolt;
	params.dHighLevelVolt = trHighVolt.dVal;
	int nAuto = octree_get_auto_support(&trHighVolt);
	if ( 1 != nAuto )
		params.dwCtrl |= CTRL_FIX_HIGHLEVEL;
	
	TreeNode trLowVolt = trGUI.input.lowVolt;
	params.dLowLevelVolt = trLowVolt.dVal;
	nAuto = octree_get_auto_support(&trLowVolt);
	if ( 1 != nAuto )
		params.dwCtrl |= CTRL_FIX_LOWLEVEL;

	vector<int> vnIndices(vX.GetSize());
	int nNewSize = ocmath_1d_remove_missingvalue(vX, vY, vX.GetSize(), get_missing_value(), vnIndices);
	vX.SetSize(nNewSize);
	vY.SetSize(nNewSize);
	
	int nRet = ocmsp_find_fall_or_fall_time(vX.GetSize(), vX, vY, &result, &params, bForward); 
	if ( OE_NOERROR == nRet )
	{
		trLowVolt.SetAttribute(STR_OLDVOLT_VALUE, result.y1);
		trHighVolt.SetAttribute(STR_OLDVOLT_VALUE, result.y2);

		//update index, according to data before remove missing values.
		result.it1 = vnIndices[result.it1];
		result.it2 = vnIndices[result.it2];
		result.i1y1 = vnIndices[result.i1y1];
		result.i1y2 = vnIndices[result.i1y2];
		result.i2y1 = vnIndices[result.i2y1];
		result.i2y2 = vnIndices[result.i2y2];
	}
	///Sophy 6/8/2010 ORG-238 PROPER_INIT_VALUES_FOR_HIGH_LOW_STATE_LEVEL
	else
	{
		vector vPer(2);
		vPer[0] = params.dLowLevelRefer * 100;
		vPer[1] = params.dHighLevelRefer * 100;
		vector vPerValue(vPer.GetSize());
		ocmath_percentiles(vY, vY.GetSize(), vPer, vPer.GetSize(), vPerValue);
		
		trLowVolt.SetAttribute(STR_OLDVOLT_VALUE, vPerValue[0]);
		trHighVolt.SetAttribute(STR_OLDVOLT_VALUE, vPerValue[1]);
	}
	///end PROPER_INIT_VALUES_FOR_HIGH_LOW_STATE_LEVEL

	return nRet;
}
///end MORE_WORK_ON_RISETIME_AUTO_INIT_HIGH_LOW_STATE_LEVEL
///Sophy 8/27/2009 SUPPORT_CUSTOMER_SPECIFIED_LOW_HIGHT_STATE_LEVEL
bool update_method_on_auto_check(TreeNode& tr, int nRow, int nCtrlType, Dialog& GetNDlg)
{
	TreeNode trGUI = tr.trGUI;
	if ( !trGUI )
		trGUI = tr;
	
	TreeNode trHighLevel = trGUI.input.highVolt;
	TreeNode trLowLevel = trGUI.input.lowVolt;
	TreeNode trMethod = trGUI.method;
	
	///Sophy 9/11/2009 CLEAR_CUSTOMER_INPUT_WHEN_AUTO_LOW_HIGH_VOLT
	int nAutoLow = octree_get_auto_support(&trLowLevel);
	///Sophy 5/4/2010 QA82-15353 MORE_WORK_ON_RISETIME_AUTO_INIT_HIGH_LOW_STATE_LEVEL
	//if ( nAutoLow == 1 )
		//trLowLevel.dVal = NANUM;
	///Sophy 6/8/2010 ORG-238 PROPER_INIT_VALUES_FOR_HIGH_LOW_STATE_LEVEL
	//double dLow = NANUM;
	double dLow = trLowLevel.dVal;
	///end PROPER_INIT_VALUES_FOR_HIGH_LOW_STATE_LEVEL
	if ( nAutoLow == 1 )
		trLowLevel.GetAttribute(STR_OLDVOLT_VALUE, dLow);
	trLowLevel.dVal = dLow;
	///end MORE_WORK_ON_RISETIME_AUTO_INIT_HIGH_LOW_STATE_LEVEL
	int nAutoHigh = octree_get_auto_support(&trHighLevel);
	///Sophy 5/4/2010 QA82-15353 MORE_WORK_ON_RISETIME_AUTO_INIT_HIGH_LOW_STATE_LEVEL
	//if ( nAutoHigh == 1 )
		//trHighLevel.dVal = NANUM;
	///Sophy 6/8/2010 ORG-238 PROPER_INIT_VALUES_FOR_HIGH_LOW_STATE_LEVEL
	//double dHigh = NANUM;
	double dHigh = trHighLevel.dVal;
	///end PROPER_INIT_VALUES_FOR_HIGH_LOW_STATE_LEVEL
	if ( nAutoHigh == 1 )
		trHighLevel.GetAttribute(STR_OLDVOLT_VALUE, dHigh);
	trHighLevel.dVal = dHigh;
	///end MORE_WORK_ON_RISETIME_AUTO_INIT_HIGH_LOW_STATE_LEVEL
	///end CLEAR_CUSTOMER_INPUT_WHEN_AUTO_LOW_HIGH_VOLT
	if ( nAutoLow != 1 && nAutoHigh != 1 )
	{
		trMethod.Enable = false;
	}
	else
		trMethod.Enable = true;
	
	return true;
}
///end SUPPORT_CUSTOMER_SPECIFIED_LOW_HIGHT_STATE_LEVEL

///Sophy 11/26/2009 EVT_HANDLER_IN_TREENODE_INVALID_WHEN_RESTART_ORIGIN
static	int*	_get_xf_treenode_evt_handle_state()
{
	static int nUpdated = 0;
	return &nUpdated;
}
///end EVT_HANDLER_IN_TREENODE_INVALID_WHEN_RESTART_ORIGIN

///---Sim 01-08-2010 QA81-14930 CLEAN_GRAPH_OBJ_TOOLS
enum {
	RTT_OBJ_FIRST = GOT_OBJ_TOTAL,
	RTT_OBJ_HIGH_VOLT,
	RTT_OBJ_LOW_VOLT,
	RTT_OBJ_T1,
	RTT_OBJ_T2,
	RTT_OBJ_HIGH_REFER,
	RTT_OBJ_LOW_REFER,
	RTT_OBJ_REFER_START,
	RTT_OBJ_REFER_END,
};
///---END QA81-14930 CLEAN_GRAPH_OBJ_TOOLS

class RiseTimeTool : public GraphObjCurveTool
{
public:
	///---Sim 01-08-2010 QA81-14930 CLEAN_GRAPH_OBJ_TOOLS
	//RiseTimeTool(LPCSTR lpcszMainObjName=NULL):GraphObjCurveTool(lpcszMainObjName) {}
	RiseTimeTool(LPCSTR lpcszMainObjName=NULL):
		GraphObjCurveTool(lpcszMainObjName)
	{
		m_vnObjIDs.Add(RTT_OBJ_HIGH_VOLT);
		m_vsObjNames.Add("HighVolt");
		
		m_vnObjIDs.Add(RTT_OBJ_LOW_VOLT);
		m_vsObjNames.Add("LowVolt");
		
		m_vnObjIDs.Add(RTT_OBJ_T1);
		m_vsObjNames.Add("T1");
		
		m_vnObjIDs.Add(RTT_OBJ_T2);
		m_vsObjNames.Add("T2");
		
		m_vnObjIDs.Add(RTT_OBJ_HIGH_REFER);
		m_vsObjNames.Add("HighRefer");
		
		m_vnObjIDs.Add(RTT_OBJ_LOW_REFER);
		m_vsObjNames.Add("LowRefer");
		
		m_vnObjIDs.Add(RTT_OBJ_REFER_START);
		m_vsObjNames.Add("ReferStart");
		
		m_vnObjIDs.Add(RTT_OBJ_REFER_END);
		m_vsObjNames.Add("ReferEnd");
	}
	///---END QA81-14930 CLEAN_GRAPH_OBJ_TOOLS
	
protected:
	
	//virtaul
	string GetSignature()
	{
		return "xf_addtool_rise_time";
	}
	
	//virtual 
	BOOL OnMove()
	{
		if(!OnPreMove()) 
			return false;

		///Sophy 6/12/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
		//bool bValidRise = false;
		int nResult = GET_NO_DATA;
		///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
		
		Tree trGUI;
		if(!GetGUITree(trGUI))
		{
			error_report("Invalid GUI Tree! OnMove()");
			return false;
		}
		
		// to do
		//if(!checkCreateAttachmentObjs())
		//{
			//error_report("Invalid Attachments! OnMove()");
			//return false;
		//}
		
		Tree trResults;
		if(!GetResultsTree(trResults, "output"))
		{
			error_report("Invalid result tree! OnMove()");
			return false;
		}
		
		int nToolType = trGUI.tool.nVal;
		///Sophy 12/14/2009 QA80-14686-P2 DATAPLOT_GET_DATAPOINTS_NEED_TO_SKIP_MASKED_DATA
		//if(GetData(m_vx, m_vy))
		///Sophy 5/4/2010 QA82-15364-P2 ROI_TOOLS_OPTION_FOR_SKIP_ALL_MASKED_DATAPOINTS
		//if(GetData(m_vx, m_vy, GDPS_AFTER_MASK))
		if ( GetData() ) //after confirm with Max, we should get data by left-right range when ROI rectangle span full Y range
		///end ROI_TOOLS_OPTION_FOR_SKIP_ALL_MASKED_DATAPOINTS
		///end DATAPLOT_GET_DATAPOINTS_NEED_TO_SKIP_MASKED_DATA
		{
			RiseTimeResult result;
			nResult = GET_NO_RISETIME;	///Sophy 6/12/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
			
			///Sophy 5/4/2010 QA82-15353 MORE_WORK_ON_RISETIME_AUTO_INIT_HIGH_LOW_STATE_LEVEL
			/*
			double dFrom = trGUI.input.from.dVal/100;
			double dTo = trGUI.input.to.dVal/100;
			double dTol = trGUI.adv.tol.dVal;
			int nPts = trGUI.adv.pts.nVal;
			int nPtsEx = trGUI.adv.pts2.nVal;
			int nBins = trGUI.adv.bins.nVal;
			int nMethod = METOHDS[trGUI.method.nVal];
			int nLNOption = LN_SEARCH_OPTIONS[trGUI.adv.lnsearch.nVal];
			int nRet;
			
			///Sophy 8/14/2009 ADD_FLEXIBLE_PARAM_FOR_MORE_USER_OPTIONS
			//nRet = ocmsp_find_fall_or_fall_time(m_vx.GetSize(), m_vx, m_vy, &result, dFrom, dTo, nMethod, dTol, nPts, nPtsEx, nBins, nToolType == 0); 
			RiseTimeParams params;
			params.dLowLevelRefer = dFrom;
			params.dHighLevelRefer = dTo;
			params.nMethod = nMethod;
			params.dTolerance = dTol;
			params.nSmoothPoints = nPts;
			params.nSmoothPointsEx = nPtsEx;
			params.nBins = nBins;
			params.bAveVal = TRUE;
			params.nMinMaxFindingMethod = nLNOption;
			BOOL bForward = (nToolType == 0) ? TRUE : FALSE;
			///Sophy 8/27/2009 SUPPORT_CUSTOMER_SPECIFIED_LOW_HIGHT_STATE_LEVEL
			TreeNode trHighVolt = trGUI.input.highVolt;
			params.dHighLevelVolt = trHighVolt.dVal;
			int nAuto = octree_get_auto_support(&trHighVolt);
			if ( 1 != nAuto )
				params.dwCtrl |= CTRL_FIX_HIGHLEVEL;
			
			TreeNode trLowVolt = trGUI.input.lowVolt;
			params.dLowLevelVolt = trLowVolt.dVal;
			nAuto = octree_get_auto_support(&trLowVolt);
			if ( 1 != nAuto )
				params.dwCtrl |= CTRL_FIX_LOWLEVEL;
			///end SUPPORT_CUSTOMER_SPECIFIED_LOW_HIGHT_STATE_LEVEL	
			///Sophy 12/14/2009 QA80-14686-P2 DATAPLOT_GET_DATAPOINTS_NEED_TO_SKIP_MASKED_DATA
			//nRet = ocmsp_find_fall_or_fall_time(m_vx.GetSize(), m_vx, m_vy, &result, &params, bForward); 
			{
				vector<int> vnIndices(m_vX.GetSize());
				int nNewSize = ocmath_1d_remove_missingvalue(m_vX, m_vY, m_vX.GetSize(), get_missing_value(), vnIndices);
				m_vX.SetSize(nNewSize);
				m_vY.SetSize(nNewSize);
				nRet = ocmsp_find_fall_or_fall_time(m_vX.GetSize(), m_vX, m_vY, &result, &params, bForward); 
				
				//update index, according to data before remove missing values.
				result.it1 = vnIndices[result.it1];
				result.it2 = vnIndices[result.it2];
				result.i1y1 = vnIndices[result.i1y1];
				result.i1y2 = vnIndices[result.i1y2];
				result.i2y1 = vnIndices[result.i2y1];
				result.i2y2 = vnIndices[result.i2y2];
			}
			*/
			int nRet = _find_rise_or_fall_time(trGUI, m_vX, m_vY, result);
			///end MORE_WORK_ON_RISETIME_AUTO_INIT_HIGH_LOW_STATE_LEVEL
			///end DATAPLOT_GET_DATAPOINTS_NEED_TO_SKIP_MASKED_DATA
			///end ADD_FLEXIBLE_PARAM_FOR_MORE_USER_OPTIONS
				
			if(nRet == OE_NOERROR)
			{
				ASSERT(result.y2 > result.y1);///Sophy 8/5/2009 MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS
				///Sophy 6/12/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
				//bValidRise = true;
				nResult = GET_SUCCESS;
				///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
				
				///Sophy 5/4/2010 QA82-15353 MORE_WORK_ON_RISETIME_AUTO_INIT_HIGH_LOW_STATE_LEVEL
				SetGUITree(trGUI); //need to save tree, since auto detecting high/low value might changes.
				///end MORE_WORK_ON_RISETIME_AUTO_INIT_HIGH_LOW_STATE_LEVEL
				
				///Sophy 8/14/2009 IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
				//drawHighLowVoltLines(result.y1, result.y2);
				if ( trGUI.display.statelevel.nVal == 1 )
					drawHighLowVoltLines(result.y1, result.y2);
				else
					hideLines();
				///end IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
				//m_goRise.Show(true);
				//drawRiseLine(result.i1y1, result.i2y1, result.i1y2, result.i2y2);
				///Sophy 8/12/2009 IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT update markders after update data
				//updateMarkers(result.it1, result.it2);
				///end IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT
				
				///Sophy 11/5/2009 QA80-14598-S1 OUTPUT_RESULT_SHOULD_USE_NEW_DATAPLOT_NAME_CONVENTION
				//trResults.name.strVal = m_dp.GetName();
				string strRngStr;
				m_dp.GetRangeString(strRngStr, NTYPE_BOOKSHEET_XY_RANGE);
				trResults.name.strVal = strRngStr;
				///end OUTPUT_RESULT_SHOULD_USE_NEW_DATAPLOT_NAME_CONVENTION
				trResults.name.TypeID = TNVAL_TYPE_CSTRING;
				trResults.dT.dVal = result.dRiseTime;
				trResults.VMin.dVal = result.y1;
				trResults.VMax.dVal = result.y2;
				trResults.dV.dVal = result.y2 - result.y1;
				///Sophy 8/12/2009 IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT
				//trResults.t1.dVal = (result.it1>0 && result.it1<m_vx.GetSize()) ? m_vx[result.it1] : NANUM;
				//trResults.t2.dVal = (result.it2>0 && result.it2<m_vx.GetSize()) ? m_vx[result.it2] : NANUM;
				//trResults.v1.dVal = (result.it1>0 && result.it1<m_vy.GetSize()) ? m_vy[result.it1] : NANUM;
				//trResults.v2.dVal = (result.it2>0 && result.it2<m_vy.GetSize()) ? m_vy[result.it2] : NANUM;
				trResults.T1.dVal = result.t1;
				trResults.T2.dVal = result.t2;
				trResults.VrefMin.dVal = result.y1 + (result.y2 - result.y1) * (trGUI.input.from.dVal) / 100.0;
				trResults.VrefMax.dVal = result.y1 + (result.y2 - result.y1) * (trGUI.input.to.dVal) / 100.0;
				trResults.dVref.dVal = trResults.VrefMax.dVal - trResults.VrefMin.dVal;
				if ( nToolType == 1 ) 
				{
					double dTemp = trResults.T1.dVal;
					trResults.T1.dVal = trResults.T2.dVal;
					trResults.T2.dVal = dTemp;
				}
				///end IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT
				///Sophy 11/5/2009-S4 QA80-14598-S4 OUTPUT_MORE_RESULT
				trResults.Velocity.dVal = result.velocity;
				trResults.MaxVelocity.dVal = result.max_velocity;
				///end OUTPUT_MORE_RESULT
				trResults.e1.dVal = result.b1;
				trResults.e2.dVal = result.b2;
				
				///Sophy 8/12/2009 MOVE_CHECK_ON_OSCILLOSCOPE_SIGNAL_PROCESS_RESULT for debugging
				double dLowStateLevel = trResults.VMin.dVal;
				double dHighStateLevel = trResults.VMax.dVal;
				double dLowReferLevel = trResults.VrefMin.dVal;
				double dHighReferLevel = trResults.VrefMax.dVal;
				ASSERT( (dLowStateLevel < dLowReferLevel ) && (dHighReferLevel < dHighStateLevel) );
				///end MOVE_CHECK_ON_OSCILLOSCOPE_SIGNAL_PROCESS_RESULT
				
				///Sophy 8/12/2009 IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT update markders after update data
				updateMarkers(trResults.T1.dVal, trResults.VrefMin.dVal, trResults.T2.dVal, trResults.VrefMax.dVal);
				///end IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT

				///Sophy 8/14/2009 IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
				bool bShowTime = trGUI.display.risetime.nVal == 1;
				bool bShowRange = trGUI.display.riserange.nVal == 1;
				double dVrefT1, dVrefT2, dT1, dT2;
				
				dT1 = trResults.T1.dVal;
				dT2 = trResults.T2.dVal;
				
				if ( nToolType == 0 ) //rise time
				{
					dVrefT1 = trResults.VrefMax.dVal;
					dVrefT2 = trResults.VrefMin.dVal;
				}
				else //fall time
				{
					dVrefT1 = trResults.VrefMin.dVal;
					dVrefT2 = trResults.VrefMax.dVal;
				}
				updateRiseFallRange(dT1, dVrefT1, dT2, dVrefT2, bShowTime, bShowRange);
				
				updateLabels(result, dHighReferLevel - dLowReferLevel, NULL, trGUI.tool.nVal);
				///end IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
				///Sophy 8/5/2009 MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS
				int nNoiseUnit = trGUI.adv.noiseUnit.nVal;
				if ( nNoiseUnit == 1 ) //relative to step size
				{
					//percentage, no need to output full precision
					trResults.e1.dVal = prec(trResults.e1.dVal / (trResults.VMax.dVal - trResults.VMin.dVal) * 100, 4);
					trResults.e2.dVal = prec(trResults.e2.dVal / (trResults.VMax.dVal - trResults.VMin.dVal) * 100, 4);
				}
				///end MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS

			}
		}
		///Sophy 6/12/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
		//if(!bValidRise)
		if( GET_SUCCESS != nResult )
		///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
		{
			///Sophy 8/5/2009 MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS
			/* centralize code
			//m_goRise.Show(false);
			///Sophy 6/12/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
			//intercrossLines();
			if ( GET_NO_DATA == nResult )
				intercrossLines();
			///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
			//error_report("Invalid RiseTime!");
			updateMarkers(-1, -1);
			///Sophy 6/12/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
			//updateLabels(NULL);
			if ( GET_NO_DATA == nResult )
				updateLabels(NULL, _L("No Data Selected"));
			else if ( GET_NO_RISETIME == nResult )
			{
				if ( nToolType == 0 )
					updateLabels(NULL, _L("No RiseTime"));
				else
					updateLabels(NULL, _L("No FallTime"));
				hideLines(); ///Sophy 6/17/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
			}
			///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
			
			trResults.rt.dVal = NANUM;
			trResults.y1.dVal = NANUM;
			trResults.y2.dVal = NANUM;
			trResults.t1.dVal = NANUM;
			trResults.t2.dVal = NANUM;
			trResults.v1.dVal = NANUM;
			trResults.v2.dVal = NANUM;
			trResults.e1.dVal = NANUM;
			trResults.e2.dVal = NANUM;	
			*/
			makeResultsInvalid(trResults, nResult, nToolType);
		}
		

		//--- hide all those that are unchecked
		///Sophy 9/1/2009 GIVE_BETTER_LABELS_FOR_RESULT_TREE
		//tree_copy_values_to_attributes(trGUI.output, trResults, STR_LABEL_ATTRIB);
		///Sophy 12/17/2009 QA80-14598-P4 RISE_TIME_TOOL_NEED_CREATE_LONGNAME_IN_RESULT_COLUMN
		//tree_copy_values_to_attributes(trGUI.output, trResults);
		tree_copy_values_to_attributes(trGUI.output, trResults, STR_LABEL_ATTRIB);
		///end RISE_TIME_TOOL_NEED_CREATE_LONGNAME_IN_RESULT_COLUMN
		trResults.SetAttribute(STR_LABEL_ATTRIB, (nToolType == 0 ? STR_RESULTS_RISE_TIME : STR_RESULTS_FALL_TIME));
		///end GIVE_BETTER_LABELS_FOR_RESULT_TREE
		
		trResults.SetAttribute(STR_RISETIME_STATUS, nResult);	///Sophy 6/12/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING

		if(!SetResultsTree(trResults))
		{
			ASSERT(false);
			return false;
		}
		
		m_gp.Refresh(); ///Sophy, need to refresh the graph after moving objects, maybe this should be done in base class

		return GraphObjCurveTool::OnMove();
	}
	///---Sim 01-08-2010 QA81-14930 CLEAN_GRAPH_OBJ_TOOLS
	/*
	//virtual
	BOOL Init()
	{
		if(!GraphObjCurveTool::Init())
			return false;
			
		///Sophy 9/1/2009 BETTER_DISPLAY_TOP_LABEL_LIKE_CURE_INTEG_TOOL_DOES
		//return checkCreateAttachmentObjs();
		BOOL bRet = checkCreateAttachmentObjs();
		m_goLabel.Top -= m_goLabel.Height / 2; //we call checkCreateAttachmentObjs in OnMove, so in order to avoid moving further and further the label, I have to do that here.
		return bRet;
		///end BETTER_DISPLAY_TOP_LABEL_LIKE_CURE_INTEG_TOOL_DOES
	}
	*/
	///---END QA81-14930 CLEAN_GRAPH_OBJ_TOOLS

	/// Fisher 7/20/09 QA80-13975 	HANDLE_RESCALE_EVENT_FOR_GRAPH_OBJ_TOOL
	// virtual
	///Sophy 12/3/2009 QA80-14686 CENTRALIZE_CODE_FOR_UPDATE_RESULT_ON_RESCALE_GRAPH
	//BOOL OnRescale()
	BOOL InvalidateResults()
	///end CENTRALIZE_CODE_FOR_UPDATE_RESULT_ON_RESCALE_GRAPH
	{
		///Sophy 8/5/2009 MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS
		//return OnMove();
		Tree trGUI;
		if ( !GetGUITree(trGUI) )
			return FALSE;
		
		int nToolType = trGUI.tool.nVal;
		int nInvalidateRes = trGUI.adv.onrescale.nVal;
		if ( nInvalidateRes == 1 )
		{
			Tree trResult;
			if ( !GetResultsTree(trResult, "output") )
				return FALSE;
			
			// to do
			//checkCreateAttachmentObjs(); //check create objects before move, or will runtime
			makeResultsInvalid(trResult, GET_NO_DATA, nToolType);

			SetResultsTree(trResult);
			
			m_gp.Refresh();
			
			return TRUE;
		}
		
		if ( !OnMove() )
			return FALSE;
		///end MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS
	}
	/// End HANDLE_RESCALE_EVENT_FOR_GRAPH_OBJ_TOOL	
	
	/// 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
	{
		Tree trGUI;		
		if(!GetGUITree(trGUI) || !trGUI.output || !trGUI.output_to.script || !trGUI.output_to.reslog || !trGUI.output_to.appendwks)
		{
			ASSERT(false);
			return false;
		}	
		
		bool bToScript, bToResLog, bAppendWks;
		bToScript = trGUI.output_to.script.nVal;
		bToResLog = trGUI.output_to.reslog.nVal;
		bAppendWks = trGUI.output_to.appendwks.nVal;
		string strWksPageName = trGUI.output_to.wbkName.strVal;
		
		Tree trResults;
		if(!GetResultsTree(trResults, "output"))
		{
			ASSERT(false);
			return false;
		}	
		
		///Sophy 6/12/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
		int nResult;
		if ( trResults.GetAttribute(STR_RISETIME_STATUS, nResult) && GET_SUCCESS != nResult )
		{
			LT_execute("type -a");
			if ( nResult == GET_NO_RISETIME )
			{
				if( 1 == trGUI.tool.nVal )
					out_str("Fail to Find Fall Time!!!");
				else
					out_str("Fail to Find Rise Time!!!");
			}
			else if ( nResult == GET_NO_DATA )
				out_str("No Data Selected!!!");
			return false;
		}
		///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
		///Sophy 8/19/2009 OUTPUT_RESULT_TO_SCRIPT_WINDOW_SHOULD_BE_BETTER_DISPLAYED
		//OutputResultTree(bToScript, bToResLog, bAppendWks, strWksPageName, TREE2STR_CHECK_USER_LABEL);
		///Sophy 9/1/2009 GIVE_BETTER_LABELS_FOR_RESULT_TREE
		//OutputResultTree(bToScript, bToResLog, bAppendWks, strWksPageName, 0);
		OutputResultTree(bToScript, bToResLog, bAppendWks, strWksPageName, OUTTREE_USE_TAGNAME_IN_SCRIPT_WIN | TREE2STR_CHECK_USER_LABEL); //////Sophy 12/17/2009 QA80-14598-P4 RISE_TIME_TOOL_NEED_CREATE_LONGNAME_IN_RESULT_COLUMN add OUTTREE_USE_TAGNAME_IN_SCRIPT_WIN option.
		///end GIVE_BETTER_LABELS_FOR_RESULT_TREE
		///end OUTPUT_RESULT_TO_SCRIPT_WINDOW_SHOULD_BE_BETTER_DISPLAYED
		return true;
	}	
	
	///Sophy 6/12/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
	///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, true, true, false); //Sophy, hide Theme saving menu.
		
		tr.SetAttribute(STR_CLASS_OPTION_NAME_ATTRIB, "addtool_rise_time");	///Sophy 11/5/2009 QA80-14598-S2 SUPPORT_HELP_WHEN_CHANGE_OPTION
		
		if ( GetNBox(tr, NULL, _L("Quick RiseTime 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);
			OnMove();
			return true;
		}
		return false;
	}
	*/
	///end CENTRALIZE_OPEN_PREFERENCE_DIALOG_TO_BASE_CLASS
	///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
	
	///Sophy 1/26/2010 ADD_GO_TO_REPORT_TABLE_MENU_IN_CONTEXT
	//virtual
	BOOL	GetReportWorksheet(Worksheet& wksReport)
	{
		Tree trGUI;
		if ( !GetGUITree(trGUI) || trGUI.output_to.appendwks.nVal != 1 )
			return FALSE;
		string strWorksheet = trGUI.output_to.wbkName.strVal;
		wksReport.Attach(strWorksheet);
		return wksReport.IsValid();
	}
	///end ADD_GO_TO_REPORT_TABLE_MENU_IN_CONTEXT

	///Sophy 10/15/2010 ORG-1263-P1 UPDATE_INDICATOR_SETTINGS_FOR_RISETIME_TOOL
	//virtual
	bool	UpdateAttachments()
	{
		return (applyMarkerFormat(m_goT1) && applyMarkerFormat(m_goT2));
	}
	///end UPDATE_INDICATOR_SETTINGS_FOR_RISETIME_TOOL

///Sophy 8/26/2009 QA80-14169 MAKE_GRAPHOBJECT_FOR_PROGRAMMING_CONTROL_PRINTABLE
protected:
	//virtual
	bool	MakePrintable(GraphObject& go) { return set_go_printable(go); }
///end MAKE_GRAPHOBJECT_FOR_PROGRAMMING_CONTROL_PRINTABLE

	///Sophy 11/26/2009 EVT_HANDLER_IN_TREENODE_INVALID_WHEN_RESTART_ORIGIN
	//virtual
	string	GetXFName(){ return XF_NAME; }
	//virtual
	int*	GetXFEventHandlersState() { return _get_xf_treenode_evt_handle_state(); }
	///EVT_HANDLER_IN_TREENODE_INVALID_WHEN_RESTART_ORIGIN
	///Sophy 1/22/2010 CENTRALIZE_OPEN_PREFERENCE_DIALOG_TO_BASE_CLASS
	string	GetToolName(){ return TOOLNAME; }
	//virtual
	string	GetPreferenceTitle(){ return TOOL_PREFERENCES_TITLE; }
	///end CENTRALIZE_OPEN_PREFERENCE_DIALOG_TO_BASE_CLASS


private:
	///Sophy 8/12/2009 IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT
	//void updateMarkers(int nMarker1, int nMarker2)
	//{
		//if( nMarker1<0 || nMarker1>=m_vx.GetSize() || nMarker2<0 || nMarker2>=m_vx.GetSize() )
		//{
			//m_goT1.Show(false);
			//m_goT2.Show(false);
		//}
		//else
		//{
			//double dx1 = m_vx[nMarker1];
			//double dx2 = m_vx[nMarker2];
			//double dy1 = m_vy[nMarker1];
			//double dy2 = m_vy[nMarker2];
			//
			//if(!ellipse_move(m_goT1, dx1,  dy1, UNITS_SCALE))
				//error_report("Fail in update marker_1 position!");
			//
			//if(!ellipse_move(m_goT2, dx2,  dy2,  UNITS_SCALE))
				//error_report("Fail in update marker_2 position!");
			//
			//m_goT1.Show();
			//m_goT2.Show();
		//}
	//}
	void updateMarkers(double dx1, double dy1, double dx2, double dy2, bool bShow = true)
	{
		if ( !bShow )
		{
			m_goT1.Show(false);
			m_goT2.Show(false);
		}
		else
		{
			///Sophy 8/20/2009 RISETTIME_TOOL_INDICATOR_USE_MARKER_GRAPHOBJECT
			//if ( !ellipse_move(m_goT1, dx1, dy1, UNITS_SCALE) )
				//error_report("Fail in update marker_1 position!");
			//if ( !ellipse_move(m_goT2, dx2, dy2, UNITS_SCALE) )
				//error_report("Fail in update marker_2 position!");
			vector vX(1), vY(1);
			vX[0] = dx1;
			vY[0] = dy1;
			m_goT1.SetPoints(vX, vY);
			
			vX[0] = dx2;
			vY[0] = dy2;
			m_goT2.SetPoints(vX, vY);
			///end RISETTIME_TOOL_INDICATOR_USE_MARKER_GRAPHOBJECT			
			m_goT1.Show();
			m_goT2.Show();
		}
	}
	///end IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT
	//i1 = index of the beginning of the linear region on the low voltage, typically 0, but if the data has some big noise we will skip that so might be > 0 ;
	//i2 = Index of the end of linear region on the low voltage;
	//i3 = Index of the beginning of the high voltage baseline region;
	//i4 = index of the end of the high voltage baseline, typically the last data point;
	//void drawRiseLine(int i1, int i2, int i3, int i4)
	//{
		//vector vxRise, vyRise;
		//m_vx.GetSubVector(vxRise, i2, i3);
		//m_vy.GetSubVector(vyRise, i2, i3);
		//if(1 < vxRise.GetSize())
		//{
			//int nSize = m_goRise.SetPoints(vxRise, vyRise);
			//m_goRise.Show();
		//}
		//else
			//error_report("Draw Rise Line fail!");
	//}
	
	void updateLabels(RiseTimeResult& result, double dRiseRange, LPCSTR lpcszMsg = NULL, int nToolType = 0)
	{
		string strTemp(lpcszMsg);
		if(result != NULL)
		{
			//strTemp.Format(" RiseTime=%s\n t1=%s\n t2=%s\n LowVolt=%s\n HighVolt=%s\n", 
							//ftoa(result.dRiseTime, "*4"), ftoa(result.t1, "*4"), ftoa(result.t2, "*4"),
							//ftoa(result.y1, "*4"),ftoa(result.y2, "*4"));
			///Sophy 6/17/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
			//strTemp.Format("RiseTime=%s",	ftoa(result.dRiseTime, "*4"));
			string strTool = (nToolType == 0) ? STR_RISE_TIME : STR_FALL_TIME;
			string strRange = (nToolType == 0) ? STR_RISE_RANGE : STR_FALL_RANGE;
			strTemp.Format("%s=%s\r\n%s=%s",	strTool, ftoa(result.dRiseTime, "*4"), strRange, ftoa(dRiseRange, "*4"));
			///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
		}
		///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
	}
	
	///Sophy 8/14/2009 IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
	//void updateRangeLabel(double& dRiseRange, LPCSTR lpcszMsg = NULL, int nToolType = 0)
	//{
		//string strTemp = lpcszMsg;
		//if(dRiseRange != NULL)
		//{
			//string strTool = (nToolType == 0) ? STR_RISE_RANGE : STR_FALL_RANGE;
			//strTemp.Format("%s=%s",	strTool, ftoa(dRiseRange, "*4"));
		//}
					//
		//m_goRangeLabel.Text = strTemp;			
	//}
	///end IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
	void drawHighLowVoltLines(double dLow, double dHight)
	{
		double dLeft, dRight;
		GetRectCoordinate(dLeft, dRight);
		
		m_goHighVolt.Show(true);
		if(!move_line(m_goHighVolt, dLeft, dRight, dHight, dHight))
		{
			error_report("fail to move HighVolt Line.");
		}
		m_goLowVolt.Show(true);
		if(!move_line(m_goLowVolt, dLeft, dRight, dLow, dLow))
		{
			error_report("fail to move LowVolt Line.");
		}		
	}
	
	void intercrossLines()
	{
		if(m_gl)
		{
			double dLeft, dRight, dTop, dBottom;
			GetRectCoordinate(dLeft, dRight, dTop, dBottom);
			
			if(!move_line(m_goHighVolt, dLeft, dRight, dTop, dBottom))
			{
				error_report("fail to move HighVolt Line.");
			}
			
			if(!move_line(m_goLowVolt, dLeft, dRight, dBottom, dTop))
			{
				error_report("fail to move LowVolt Line.");
			}
		}
		else
		{
			error_report("Invalid Layer and No Rise Time Found");
		}	

	}
	
	///Sophy 6/17/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
	void hideLines()
	{
		if ( m_gl )
		{
			m_goHighVolt.Show(false);
			m_goLowVolt.Show(false);
		}
		else
			error_report("Invalid Layer and No Rise Time Found.");
	}
	///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
	///Sophy 8/13/2009 IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
	void updateRiseFallRange(double dLeft, double dTop, double dRight, double dBottom, bool bShowTime = true, bool bShowRange = true)
	{
		if ( bShowTime )
		{
			move_line(m_goReferStart, dLeft, dLeft, m_gl.Y.From, m_gl.Y.To);
			move_line(m_goReferEnd, dRight, dRight, m_gl.Y.From, m_gl.Y.To);
		}
		if ( bShowRange )
		{
			move_line(m_goHighRefer, m_gl.X.From, m_gl.X.To, dTop, dTop);
			move_line(m_goLowRefer, m_gl.X.From, m_gl.X.To, dBottom, dBottom);
		}
		
		m_goHighRefer.Show(bShowRange);
		m_goLowRefer.Show(bShowRange);
		
		m_goReferStart.Show(bShowTime);
		m_goReferEnd.Show(bShowTime);
	}
	///end IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
	
	///---Sim 01-08-2010 QA81-14930 CLEAN_GRAPH_OBJ_TOOLS
	/*
	bool checkCreateAttachmentObjs()
	{
		///Sophy 9/1/2009 BETTER_DISPLAY_TOP_LABEL_LIKE_CURE_INTEG_TOOL_DOES
		//if ( 0 > CreateAttachment(GROBJ_TN_TEXT, CTP_TOP, &m_goLabel, _L("No Data Selected")) )
			//return false;
		if ( 0 > CreateAttachment(GROBJ_TN_TEXT, CTP_TOP, &m_goLabel, _L("Rise Time = 0.0000\nRise Range = 0.0000")) )
			return false;
		///end BETTER_DISPLAY_TOP_LABEL_LIKE_CURE_INTEG_TOOL_DOES
		
		if ( 0 > CreateAttachedFreeLine(&m_goHighVolt, _QT_RISETIME_POS_ID_H_VOLT,GROT_LINE,/# GROBJ_TN_LINE2,#/ SYSCOLOR_BLUE) )
			return false;
		
		if ( 0 > CreateAttachedFreeLine(&m_goLowVolt, _QT_RISETIME_POS_ID_L_VOLT, GROT_LINE,/# GROBJ_TN_LINE2,#/ SYSCOLOR_BLUE) )
			return false;
		
		//if(CreateAttachedFreeLine(&m_goRise, _QT_RISETIME_POS_ID_RISE_TRACE,  GROBJ_TN_POLYLINE, SYSCOLOR_RED) < 0)
			//return false;
			
		///Sophy 8/20/2009 RISETTIME_TOOL_INDICATOR_USE_MARKER_GRAPHOBJECT
		//if(CreateAttachment(GROBJ_TN_ELLIPSE, _QT_RISETIME_POS_ID_POINT_T1, &m_goT1, "t1") <0 )
			//return false;
		//
		//if(CreateAttachment(GROBJ_TN_ELLIPSE, _QT_RISETIME_POS_ID_POINT_T2, &m_goT2, "t2") <0 )
			//return false;
		if ( 0 > CreateAttachment(GROBJ_TN_MARKER, _QT_RISETIME_POS_ID_POINT_T1, &m_goT1, "t1") )
			return false;
		
		if ( 0 > CreateAttachment(GROBJ_TN_MARKER, _QT_RISETIME_POS_ID_POINT_T2, &m_goT2, "t2") )
			return false;
		///end RISETTIME_TOOL_INDICATOR_USE_MARKER_GRAPHOBJECT
		
		if ( !applyMarkerFormat(m_goT1) || !applyMarkerFormat(m_goT2) )
			error_report("applyMarkerFormat return Fail!");		
		
		if ( !applyVoltLineFormat(m_goHighVolt) || !applyVoltLineFormat(m_goLowVolt) )
			error_report("ApplyVoltLineFormat return Fail!");
		
		///Sophy 8/14/2009 IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE		
		if ( 0 > CreateAttachment(GROT_LINE, CTP_FREE_6, &m_goHighRefer, "HighRefer") )
			return false;
		applyRiseFallRangeFormat(m_goHighRefer);
		
		if ( 0 > CreateAttachment(GROT_LINE, CTP_FREE_7, &m_goLowRefer, "LowRefer") )
			return false;
		applyRiseFallRangeFormat(m_goLowRefer);
		
		if ( 0 > CreateAttachment(GROT_LINE, CTP_FREE_8, &m_goReferStart, "ReferStart") )
			return false;
		applyRiseFallRangeFormat(m_goReferStart);
		
		if ( 0 > CreateAttachment(GROT_LINE, CTP_FREE_9, &m_goReferEnd, "ReferEnd") )
			return false;
		applyRiseFallRangeFormat(m_goReferEnd);
		///end IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
		return true;
	}
	*/
	virtual int		CreateAttachments()
	{
		int nRet;
		nRet = GraphObjCurveTool::CreateAttachments();
		if ( 0 != nRet )
			return nRet;
		
		m_goLabel.Top = m_go.Top - m_goLabel.Height * 2; //2 lines in label
		
		GraphObject go;

		//if ( 0 > CreateAttachedFreeLine(&goHighVolt, _QT_RISETIME_POS_ID_H_VOLT,GROT_LINE,/* GROBJ_TN_LINE2,*/ SYSCOLOR_BLUE) )
		if ( 0 > CreateAttachment(m_goHighVolt, RTT_OBJ_HIGH_VOLT, CTP_FREE_1, GROT_LINE) )
			return -1;
		
		//if ( 0 > CreateAttachedFreeLine(&goLowVolt, _QT_RISETIME_POS_ID_L_VOLT, GROT_LINE,/* GROBJ_TN_LINE2,*/ SYSCOLOR_BLUE) )
		if ( 0 > CreateAttachment(m_goLowVolt, RTT_OBJ_LOW_VOLT, CTP_FREE_2, GROT_LINE) )
			return -1;
		
		if ( !applyVoltLineFormat(m_goHighVolt) || !applyVoltLineFormat(m_goLowVolt) )
			error_report("ApplyVoltLineFormat return Fail!");
		
		//if(CreateAttachedFreeLine(&m_goRise, _QT_RISETIME_POS_ID_RISE_TRACE,  GROBJ_TN_POLYLINE, SYSCOLOR_RED) < 0)
			//return false;
			
		///Sophy 8/20/2009 RISETTIME_TOOL_INDICATOR_USE_MARKER_GRAPHOBJECT
		//if(CreateAttachment(GROBJ_TN_ELLIPSE, _QT_RISETIME_POS_ID_POINT_T1, &m_goT1, "t1") <0 )
			//return false;
		//
		//if(CreateAttachment(GROBJ_TN_ELLIPSE, _QT_RISETIME_POS_ID_POINT_T2, &m_goT2, "t2") <0 )
			//return false;
		MarkerGraphObject goT1, goT2;
		if ( 0 > CreateAttachment(goT1, RTT_OBJ_T1, CTP_LEFT_BOTTOM, GROBJ_TN_MARKER, "t1") )
			return -1;
		
		if ( 0 > CreateAttachment(goT2, RTT_OBJ_T2, CTP_LEFT, GROBJ_TN_MARKER, "t2") )
			return -1;
		///end RISETTIME_TOOL_INDICATOR_USE_MARKER_GRAPHOBJECT
		
		if ( !applyMarkerFormat(goT1) || !applyMarkerFormat(goT2) )
			error_report("applyMarkerFormat return Fail!");		
		
		///Sophy 8/14/2009 IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE		
		if ( 0 > CreateAttachment(go, RTT_OBJ_HIGH_REFER, CTP_FREE_6, GROT_LINE, "HighRefer") )
			return -1;
		applyRiseFallRangeFormat(go);
		
		if ( 0 > CreateAttachment(go, RTT_OBJ_LOW_REFER, CTP_FREE_7, GROT_LINE, "LowRefer") )
			return -1;
		applyRiseFallRangeFormat(go);
		
		if ( 0 > CreateAttachment(go, RTT_OBJ_REFER_START, CTP_FREE_8, GROT_LINE, "ReferStart") )
			return -1;
		applyRiseFallRangeFormat(go);
		
		if ( 0 > CreateAttachment(go, RTT_OBJ_REFER_END, CTP_FREE_9, GROT_LINE, "ReferEnd") )
			return -1;
		applyRiseFallRangeFormat(go);
		///end IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
		return 0;
	}
	virtual int		GetAttachments()
	{
		int nRet;
		if ( (nRet = GraphObjCurveTool::GetAttachments()) != 0 )
			return nRet;
		
		nRet = GetAttachment(m_goHighVolt, RTT_OBJ_HIGH_VOLT);
		if ( 0 != nRet )
			return nRet;
		
		nRet = GetAttachment(m_goLowVolt, RTT_OBJ_LOW_VOLT);
		if ( 0 != nRet )
			return nRet;
		
		nRet = GetAttachment(m_goT1, RTT_OBJ_T1);
		if ( 0 != nRet )
			return nRet;
		
		nRet = GetAttachment(m_goT2, RTT_OBJ_T2);
		if ( 0 != nRet )
			return nRet;
		
		nRet = GetAttachment(m_goHighRefer, RTT_OBJ_HIGH_REFER);
		if ( 0 != nRet )
			return nRet;
		
		nRet = GetAttachment(m_goLowRefer, RTT_OBJ_LOW_REFER);
		if ( 0 != nRet )
			return nRet;
		
		nRet = GetAttachment(m_goReferStart, RTT_OBJ_REFER_START);
		if ( 0 != nRet )
			return nRet;
		
		nRet = GetAttachment(m_goReferEnd, RTT_OBJ_REFER_END);
		if ( 0 != nRet )
			return nRet;
		
		return 0;
	}	
	///---END QA81-14930 CLEAN_GRAPH_OBJ_TOOLS
	
	bool    applyMarkerFormat(MarkerGraphObject& go)
	{
		///Sophy 8/20/2009 RISETTIME_TOOL_INDICATOR_USE_MARKER_GRAPHOBJECT
		/*
		///Sophy 6/12/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING 
		//if( fill_rect_with_color(go,  SYSCOLOR_RED) && rect_resize(go, _MARKER_SIZE, _MARKER_SIZE, UNITS_PIXEL) && set_go_selectable(go, false))
			//return true;
		//else
			//return false;
		///Sophy 8/19/2009 UPDATE_MARKERS_FORMAT_TREE_IN_SINGLE_TRANSACTION
		//set_unit(go, UNITS_PIXEL); //Sophy, set unit will fail when Attachment is not updated
		///end UPDATE_MARKERS_FORMAT_TREE_IN_SINGLE_TRANSACTION

		///Sophy 8/5/2009 MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS
		//go.Height = _MARKER_SIZE;
		//go.Width = _MARKER_SIZE;
		int nRectWidth = m_go.Width;
		Tree trGUI;
		GetGUITree(trGUI);
		///Sophy 8/19/2009 UPDATE_MARKERS_FORMAT_TREE_IN_SINGLE_TRANSACTION
		//update units fail if Attachment attribute not updated in format tree, so can not simply call set_unit() to update the format
		//go.Height = nRectWidth * trGUI.display.indicatorsize.nVal / 100.0;
		//go.Width = nRectWidth * trGUI.display.indicatorsize.nVal / 100.0;		
		Tree trFormat;
		trFormat = go.GetFormat(FPB_ALL, FOB_ALL, true, true);
		trFormat.Root.Dimension.Units.nVal = UNITS_PIXEL;
		trFormat.Root.Dimension.Width.dVal = nRectWidth * trGUI.display.indicatorsize.nVal / 100.0;
		trFormat.Root.Dimension.Height.dVal = nRectWidth * trGUI.display.indicatorsize.nVal / 100.0;
		trFormat.Root.Dimension.Attachment.nVal = 2;
		go.ApplyFormat(trFormat, true, true);
		///end UPDATE_MARKERS_FORMAT_TREE_IN_SINGLE_TRANSACTION
		///end MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS
		if( fill_rect_with_color(go,  SYSCOLOR_RED) && set_go_selectable(go, false))
			return true;
		else
			return false;
		///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
		*/
		Tree trGUI;
		GetGUITree(trGUI);
		
		const int nSymbolsPerLine = 11;
		const int nSymbolsLines = 10;
		int nSymbolIndex = trGUI.display.indicator.shape.nVal; //need to convert from value by GETN_SYMBOL to Shape and Interior in format tree
		
		Tree trFormat;
		trFormat = go.GetFormat(FPB_ALL, FOB_ALL, true, true);
		trFormat.Root.Dimension.Units.nVal = UNITS_SCALE;
		
		int nShape = 1;
		int nInterior = 0;
		if ( nSymbolIndex > nSymbolsPerLine * nSymbolsLines )
		{
			nShape = (nSymbolIndex / nSymbolsPerLine + 1) + (nSymbolIndex % nSymbolsPerLine);
			nInterior = 0;
		}
		else
		{
			nShape = nSymbolIndex / nSymbolsPerLine + 1;
			nInterior =  nSymbolIndex % nSymbolsPerLine + 1;
		}
		trFormat.Root.Symbol.Shape.nVal = nShape;
		trFormat.Root.Symbol.Interior.nVal = nInterior;
		trFormat.Root.Symbol.Size.nVal = trGUI.display.indicator.size.nVal;
		trFormat.Root.Symbol.EdgeColor.nVal = trGUI.display.indicator.edgecolor.nVal;
		trFormat.Root.Symbol.FillColor.nVal = trGUI.display.indicator.fillcolor.nVal;
		trFormat.Root.States.nVal = GOC_NO_SELECT; //not selectable from GUI
		go.ApplyFormat(trFormat, true, true);
		return true;
		///end RISETTIME_TOOL_INDICATOR_USE_MARKER_GRAPHOBJECT
	}
	
	///Sophy 8/13/2009 IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
	bool	applyRiseFallRangeFormat(GraphObject& go)
	{
		Tree trFormat;
		trFormat = go.GetFormat(FPB_ALL, FOB_ALL, true, true);
		trFormat.Root.Style.nVal = 0; //solid
		trFormat.Root.Color.nVal = 3; //blue
		///Sophy 8/21/2009 RISETIME_RISERANGE_LINE_NOT_SHOW_WHEN_RUN_RISETIME_FOR_THE_FIRST_TIME
		//when launch Origin and run addtool_rise_time for the first time, these lines are not in correct position and not visible
		trFormat.Root.Dimension.Units.nVal = UNITS_SCALE;
		trFormat.Root.Dimension.Attachment.nVal = 2;
		///end RISETIME_RISERANGE_LINE_NOT_SHOW_WHEN_RUN_RISETIME_FOR_THE_FIRST_TIME
		go.ApplyFormat(trFormat, true, true);
		
		///Sophy 8/18/2009 MAKE_AUXILIARY_LINES_UNSELECTABLE
		set_go_selectable(go, false);
		///end MAKE_AUXILIARY_LINES_UNSELECTABLE
		return true;
	}
	///end IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
	///Sandy This function doesn't take effect, I don't know why?
	bool	applyVoltLineFormat(GraphObject& go)
	{
		///Sophy 6/17/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING fix fail to update line object
		/*
		Tree tr;
		tr = go.GetFormat(FPB_DATA, FOB_ALL, true, true);

		tr.Root.Global.LineStyle.nVal = 2;// Dash Line
		tr.Root.Global.LineWidth.dVal = 2.5;
		tr.Root.Global.Color.dVal = 1;
		
		int nErr = go.UpdateThemeIDs(tr.Root);
		if(nErr == 0)
		{
			go.ApplyFormat(tr, true, true);
			return true;
		}
		out_int("err = ", nErr);
		return false;
		*/
		set_go_selectable(go, false);
		Tree trFormat;
		trFormat = go.GetFormat(FPB_ALL, FOB_ALL, true, true);
		///Sophy 8/12/2009 IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT
		//trFormat.Root.Style.nVal = 2; //Dash Line
		//trFormat.Root.Width.dVal = 2.5;
		trFormat.Root.Style.nVal = 0; //Solid Line
		trFormat.Root.Width.dVal = 0.5;
		///end IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT
		trFormat.Root.Color.nVal = 1;
		
		int nErr = go.UpdateThemeIDs(trFormat.Root);
		if ( nErr == 0 )
		{
			go.ApplyFormat(trFormat, true, true);
			go.Show(true);
			return true;
		}
		out_int("Error = ", nErr);
		return true;
		///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
	}
	///Sophy 8/5/2009 MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS
	bool	makeResultsInvalid(TreeNode& trResults, int nResult, int nToolType)
	{
		if ( !trResults )
			return false;
		
		if ( GET_NO_DATA == nResult )
			intercrossLines();
		
		///Sophy 8/12/2009 IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT
		//updateMarkers(-1, -1);
		updateMarkers(0, 0, 0, 0, false);
		///end IMPROVE_RISETIME_TOOL_FOR_BETTER_DISPLAYING_RESULT
		
		if ( GET_NO_RISETIME == nResult )
		{
			if ( nToolType == 0 )
			{
				updateLabels(NULL, NANUM, _L("No Rise Time") + "\r\n" + _L("No Rise Range"));
			}
			else
			{
				updateLabels(NULL, NANUM, _L("No Fall Time") + "\r\n" + _L("No Fall Range"));
			}
			hideLines(); ///Sophy 6/17/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
		}
		
		updateRiseFallRange(-1, -1, -1, -1, false, false); ///Sophy 8/13/2009 IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE hide it
		trResults.dT.dVal = NANUM;
		trResults.T1.dVal = NANUM;
		trResults.T2.dVal = NANUM;
		trResults.VMin.dVal = NANUM;
		trResults.VMax.dVal = NANUM;
		trResults.dV.dVal = NANUM;
		trResults.VrefMin.dVal = NANUM;
		trResults.VrefMax.dVal = NANUM;
		trResults.dVref.dVal = NANUM;
		trResults.e1.dVal = NANUM;
		trResults.e2.dVal = NANUM;
		trResults.SetAttribute(STR_RISETIME_STATUS, nResult);
		
		return false;
	}
	///end MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS

	

private:	

	GraphObject			m_goHighVolt;
	GraphObject 		m_goLowVolt;
	//PolylineGraphObject m_goRise;
	///Sophy 8/20/2009 RISETTIME_TOOL_INDICATOR_USE_MARKER_GRAPHOBJECT
	//GraphObject			m_goT1;
	//GraphObject			m_goT2;
	MarkerGraphObject	m_goT1;
	MarkerGraphObject	m_goT2;
	///end RISETTIME_TOOL_INDICATOR_USE_MARKER_GRAPHOBJECT
	///Sophy 8/13/2009 IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE to mark rise/fall time and range
	//GraphObject			m_goRangeLabel;
	GraphObject			m_goHighRefer;		
	GraphObject			m_goLowRefer;
	GraphObject			m_goReferStart;
	GraphObject			m_goReferEnd;
	///end IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
	double      		m_dHightVolt;
	double      		m_dLowVolt;
	///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

};




void addtool_rise_time(const TreeNode& trGUI)
{
	
	RiseTimeTool sTool();
	///Sophy 8/21/2009 QA80-14175 CREATE_ALL_NODES_IN_ONE_TREE_TO_GET_RID_OF_OPTIONS_BRANCH
	//int nErr = sTool.Create(XF_NAME, color,  LN_VERTICAL, trGUI);
	int nErr = sTool.Create(XF_NAME, LN_VERTICAL, 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 != 0)
		error_report("addtool_rise_time failed");
	
}

//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_rise_time_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_rise_time_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	///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_to.wbkName.strVal;
		if ( !check_update_worksheet_name(strBookSheetName) )
		{
			trGetN.trGUI.output_to.wbkName.strVal = strBookSheetName; //update report book sheet name
			strErrMsg = CER_SHEET_NAME_ILLEGAL_CHAR;
		}
		///Sophy 5/4/2010 QA82-15353 MORE_WORK_ON_RISETIME_AUTO_INIT_HIGH_LOW_STATE_LEVEL
		if ( GETNE_ON_INIT == nEventID )
		{
			_init_high_low_state_value(trGetN.trGUI);
		}
		///end MORE_WORK_ON_RISETIME_AUTO_INIT_HIGH_LOW_STATE_LEVEL
	}
	///end CHECK_UPDATE_REPORT_WORKSHEET_NAME_FOR_ROI_TOOLS	return false;
	return false;

}

int addtool_rise_time_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)
				GETN_STR(toolname, STR_TOOLNAME, TOOLNAME)	GETN_ID(TOOL_TOOLNAME_ID)	GETN_CONTROL_OPTION_BOX(0)	///Sophy 1/19/2010 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
				
				GETN_LIST(tool, _L("Tool"), 0, STR_RISETIME_FALLTIME_TOOLS) GETN_ID(nUserID++)	GETN_OPTION_EVENT(update_GUI_on_tool_type_change);
				GETN_LIST(method, _L("Method"), 0, STR_LINEAR_HISTOGRAM_METOHDS)	GETN_ID(nUserID++)	GETN_OPTION_EVENT(update_GUI_on_method_change);
				GETN_BEGIN_BRANCH(input, STR_RISE_RANGE);  GETN_OPTION_BRANCH(GETNBRANCH_OPEN)	GETN_ID(nBranchID++)
					///Sophy 8/27/2009 SUPPORT_CUSTOMER_SPECIFIED_LOW_HIGHT_STATE_LEVEL
					GETN_NUM(highVolt, _L("High State Level"), NANUM)				GETN_ID(nUserID++)	GETN_ADD_AUTO(true) GETN_OPTION_EVENT(update_method_on_auto_check);
					GETN_NUM(lowVolt, _L("Low State Level"), NANUM)					GETN_ID(nUserID++)	GETN_ADD_AUTO(true) GETN_OPTION_EVENT(update_method_on_auto_check);
					///end SUPPORT_CUSTOMER_SPECIFIED_LOW_HIGHT_STATE_LEVEL
					GETN_NUM(from, _L("From (%) of Step Height"), 10)				GETN_ID(nUserID++)
					GETN_NUM(to,   _L("To (%) of Step Height"), 90)					GETN_ID(nUserID++)
				GETN_END_BRANCH(input);
				
				
				GETN_BEGIN_BRANCH(output, _L("Quantities"))	GETN_ID(nBranchID++) GETN_OPTION_BRANCH(GETNBRANCH_CHECK_CONTROL)
					GETN_CHECK(name, _L("Dataset Name(name)"), 1)						GETN_ID(nUserID++)
					GETN_CHECK(VMin, _L("Low State Level(VMin)"), true)				GETN_ID(nUserID++)
					GETN_CHECK(VMax, _L("High State Level(VMax)"), true)				GETN_ID(nUserID++)
					GETN_CHECK(dV, _L("Step Height(dV)"), false)								GETN_ID(nUserID++)
					GETN_CHECK(VrefMin, _L("Low Reference Level(VrefMin)"), true)				GETN_ID(nUserID++)
					GETN_CHECK(VrefMax, _L("High Reference Level(VrefMax)"), true)				GETN_ID(nUserID++)	
					GETN_CHECK(dVref, STR_RISE_RANGE_QT, false)								GETN_ID(nUserID++)
					GETN_CHECK(T1, _L("Time at Low Reference Level(T1)"), true)						GETN_ID(nUserID++)
					GETN_CHECK(T2, _L("Time at High Reference Level(T2)"), true)					GETN_ID(nUserID++)				
					GETN_CHECK(dT, STR_RISE_TIME_QT, true)											GETN_ID(nUserID++)
					///Sophy 11/5/2009 QA80-14598-S4 OUTPUT_MORE_RESULT
					GETN_CHECK(Velocity, STR_RISE_VELOCITY, false)									GETN_ID(TOOL_VELOCITY_ID)
					GETN_CHECK(MaxVelocity, STR_MAX_RISE_VELO, false);								GETN_ID(TOOL_MAX_VELOCITY_ID);
					///end OUTPUT_MORE_RESULT
					GETN_CHECK(e1, _L("Noise Level Low(e1)"), false)							GETN_ID(nUserID++)
					GETN_CHECK(e2, _L("Noise Level High(e2)"), false)							GETN_ID(nUserID++)
				GETN_END_BRANCH(output);
				
				GETN_BEGIN_BRANCH(output_to, _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(appendwks, _L("Append to Worksheet"), 0)							GETN_ID(nUserID++) GETN_OPTION_EVENT(hide_show_output_wkb_name)
				GETN_STR(wbkName, _L("Result Workbook Name"), STR_RESULT_WKS_RISETIME) 		GETN_ID(nUserID++)				
			GETN_END_BRANCH(output)
			
			///Sophy 8/14/2009 IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
			GETN_BEGIN_BRANCH(display, _L("Display on Graph"))	GETN_ID_BRANCH(nBranchID++)
				
				///Sophy 8/20/2009 RISETTIME_TOOL_INDICATOR_USE_MARKER_GRAPHOBJECT
				GETN_BEGIN_BRANCH(indicator, _L("Indicator"))	GETN_ID_BRANCH(nBranchID++)
					GETN_COMBO(size, _L("Size"), 10, "1|2|3|4|5|6|7|8|9|10|15|20")	GETN_ID(nUserID++)
					GETN_SYMBOL(shape, _L("Symbol"), 0)						GETN_ID(nUserID++)
					GETN_COLOR(edgecolor, _L("Edge Color"), 0)	GETN_COLOR_CHOICE_OPTIONS(COLORLIST_CUSTOM | COLORLIST_SINGLE) GETN_ID(nUserID++)
					GETN_COLOR(fillcolor, _L("Fill Color"), 1)	GETN_COLOR_CHOICE_OPTIONS(COLORLIST_CUSTOM | COLORLIST_SINGLE) GETN_ID(nUserID++)
				GETN_END_BRANCH(indicator)
				///end RISETTIME_TOOL_INDICATOR_USE_MARKER_GRAPHOBJECT
				GETN_CHECK(statelevel, _L("State Level"), 1)								GETN_ID(nUserID++)
				GETN_CHECK(risetime, _L("Rise Time"), 0)									GETN_ID(nUserID++)
				GETN_CHECK(riserange, _L("Rise Range"), 0)									GETN_ID(nUserID++)
			GETN_END_BRANCH(display)
			///end IMPROVE_RISETIME_TOOL_TO_INDICATE_RISETIME_FALLTIME_RANGE
	
			GETN_BEGIN_BRANCH(adv, _L("Advanced")) GETN_ID(nBranchID++)
				///Sophy 11/25/2009 QA80-14719 PROPER_LOW_HIGN_LEVEL_FINDING
				GETN_LIST(lnsearch, _L("Low/High Level Determine"), 0, LN_SEARCH_OPTION_LIST) GETN_ID(TOOL_MINMAX_FIND_METHOD_ID)
				///end PROPER_LOW_HIGN_LEVEL_FINDING
				///Sophy 6/26/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
				//GETN_NUM(pts, "Smooth Points", 100)						GETN_ID(nUserID++)
				//GETN_NUM(pts2,   "Smooth Points of Rising Area", 10)	GETN_ID(nUserID++)
				GETN_SLIDER(pts, _L("Smooth Points"), 50, "1|200|199")					GETN_ID(nUserID++)
				GETN_SLIDER(pts2, _L( "Smooth Points on Rising Area"), 1, "1|50|49")	GETN_ID(nUserID++)
				///end IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
				GETN_NUM(tol,   _L("Tolerance(Percentage)"), 0.03)						GETN_ID(nUserID++)
				GETN_NUM(bins, _L("Number of Bins"), 256)					GETN_ID(nUserID++) ///Sophy 6/26/2009 IMPROVE_RISETIME_TOOL_FOR_OSCILLOSCOPE_SIGNAL_PROCESSING
				///Sophy 8/5/2009 MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS
				GETN_SEPARATOR_LINE
				GETN_LIST(onrescale, _L("When Graph Scale Changes"), 0, STR_OPTIONS_ON_RESCALE)	GETN_ID(nUserID++)
				GETN_LIST(noiseUnit, _L("Noise Level Unit"), 0, STR_OPTIONS_NOISE_LEVEL_UNITS) GETN_ID(nUserID++)
				///end MORE_OPTIONS_TO_CONTROL_RISETIME_FALLTIME_TOOLS
			GETN_END_BRANCH(adv);			
		}
	}
	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_rise_time_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_rise_time);
	}
	
	///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_to.wbkName.strVal;
			if ( !check_update_worksheet_name(strBookSheetName) )
			{
				trGetN.trGUI.output_to.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_rise_time_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
