#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	method_linear,
	method_spline,
	method_bspline,
};
#include <GetNBox.h> 
#include <event_utils.h>
#include <..\originlab\XFunctionEx.h>
#include <o8dlg.h>
static bool s_bInit = false;
static string s_strErrMsg = "";
/***************************************************************************************
/// Modification Log :
/// Folger 07/23/08 BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS
/// Folger 12/26/08 QA80-12856 v8.0991 IMRPOVE_ocmath_xy_remove_duplicates
/// Folger 03/12/09 QA80-13261 AUTO_SUPPORT_FOR_NUMBER_OF_POINTS_IN_INTERPOLATE_TOOLS
/// Sandy 03/13/09  QA80-13260 ADD_PREVIEW
/// Kyle 03/13/2009 QA80-13260-S1 ADD_OPTION_TO_COPY_FORMAT_FROM_SOURCE_LAYER
/// Kyle 07/28/2009 QA80-14026 FIX_WRONG_LEGEND_FOR_PREVIEW
/// Kyle 08/19/2009 QA80-14023 FIX_OUTPUT_SAMPLING_INTERVAL_IS_LOST_WHEN_INPUT_IS_LOOSE_DATASET
/// Kyle 09/22/2009 QA80-14023 FIX_SAMPLING_IS_NOT_RESET_IF_SET_INPUT_AS_OUTPUT
/// YuI 09/30/09 QA70-14399 UNNECESARY_AUTOUPDATE_IN_CASE_OF_INPUT_NEW
/// Iris 10/13/09 QA70-14403 PREVIEW_GRAPH_SHOULD_NEVER_RESCALE_ON_CHANGE
///	Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
***************************************************************************************/

//put your own support static functions here
//#define Y_INDEX_IN_XYRANGE 1

#define MIN_BSPLINE_PTS 4
#define MIN_SPLINE_PTS 2
#define MIN_LINEAR_PTS 2
///Cheney 2007-8-15 FIX_SOME_BU_OF_INTERP
//#define MIN_OUTPUT_INTERPOLATION_POINTS 1
#define MIN_OUTPUT_INTERPOLATION_POINTS 2
///end FIX_SOME_BU_OF_INTERP
#define MIN_SMOOTHING_FACTOR 0

#define STR_NODE_XYRANGE "iy"
#define STR_NODE_METHOD "method"

#define STR_ERR_THROW1 "Minimum interpolation ponits"
#define STR_ERR_THROW2 "Smoothing Factor"

//#define STR_INTER_RESULT1 "Interpolation Result"
//#define STR_INTER_RESULT2 "Interpolation of "

/// Cloud 9/24/07 NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
//static void _update_method_show(TreeNode& trGetN)
//{
	//switch(trGetN.method.nVal)
	//{
	//case INTERP_TYPE_LINEAR:
		//trGetN.sf.Show = false;
		//break;
	//case INTERP_TYPE_SPLINE:
		//trGetN.sf.Show = false;
		//break;
	//case INTERP_TYPE_BSPLINE:
		//trGetN.sf.Show = true;
		//break;
	//default:
	//}
//}
/// End NOT_SMOOTH_FOR_NON_MONOTONIC_DATA

static void _init_tree_show(TreeNode& trGetN, bool bIsChangingData = false)
{
	GraphLayer gl = Project.ActiveLayer();
	if(!gl.IsValid())
		trGetN.color.Show = false;

	/// Cloud 9/24/07 NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
	//_update_method_show(trGetN);
	/// End NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
}

static string _get_interp_method_name(int nMethod)
{
	string strInterpName;
	switch(nMethod)
	{
	case INTERP_TYPE_LINEAR:
		strInterpName = "Linear";
		break;
	case INTERP_TYPE_SPLINE:
		strInterpName = "Spline";
		break;
	case INTERP_TYPE_BSPLINE:
		strInterpName = "B-Spline";
		break;
	default:
	}	
	return strInterpName;
}

static int _get_min_pts(int nMethod)
{
	int nMinPts;
	switch(nMethod)
	{
	case INTERP_TYPE_LINEAR:
		nMinPts = MIN_LINEAR_PTS;
		break;
	case INTERP_TYPE_SPLINE:
		nMinPts = MIN_SPLINE_PTS;
		break;
	case INTERP_TYPE_BSPLINE:
		nMinPts = MIN_BSPLINE_PTS;
		break;
	default:
	}	
	return nMinPts;
}

static int _check_pts_enough(const TreeNode& trGetN, int nSize)
{
	int nMinPts = _get_min_pts(trGetN.method.nVal);

	if(nSize < nMinPts)
		return nMinPts;

	return OE_NOERROR;
}

static void _remove_duplicates(vector& vxIn, vector& vyIn)
{
	int nSize = vxIn.GetSize();
	int nMethod = Replace_With_Mean;
	double dPrecision = 1.0e-8;
	///------ Folger 12/26/08 QA80-12856 v8.0991 IMRPOVE_ocmath_xy_remove_duplicates
	//ocmath_xy_remove_duplicates(&nSize, vxIn, vyIn, nMethod, dPrecision, false);
	if ( (nSize = ocmath_xy_remove_duplicates(vxIn, vyIn, nSize, nMethod, dPrecision, false)) >= OE_NOERROR )
	{
	///------ End IMRPOVE_ocmath_xy_remove_duplicates
	vxIn.SetSize(nSize);
	vyIn.SetSize(nSize);
	}		///------ Folger 12/26/08 QA80-12856 v8.0991 IMRPOVE_ocmath_xy_remove_duplicates
}

/// Cloud 9/24/07 NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
//static bool _interpolate_by_parameter(vector& vxIn, vector& vyIn, vector& vxOut, vector& vyOut, double dSmoothFac, int nMethod)
static bool _interpolate_by_parameter(vector& vxIn, vector& vyIn, vector& vxOut, vector& vyOut, int nMethod)
/// End NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
{
	_remove_duplicates(vxIn, vyIn);
	
	_remove_duplicates(vyIn, vxIn); // Jack 06/20/08 QA80-11757  REMOVE_SEQUENCE_WITH_DUPLICATE_Y
	// Functionally, the first remove_duplicate is intended to remove sequences with duplicate x but different y
	// The second remove_duplicate is intended to remove sequences with different x but duplicate y
	// both kinds of duplication will lead to problem in the following parametric interpolation
	
	int nSize = vxIn.GetSize();
	if(nSize < _get_min_pts(nMethod))
	{
		XF_THROW(XFERR_UNDUPLICATED_DATA_TOO_FEW);
		return false;
	}
	matrix mIn(2, nSize);
	mIn.SetRow(vxIn, 0);
	mIn.SetRow(vyIn, 1);
	
	//get curve's cumulate curve length
	vector vCumLen(nSize); 
	ocmath_cumulative_curve_length(nSize, vCumLen, vxIn, vyIn);
	
	double dCurveLen = vCumLen[nSize - 1];
	
	//generate data for interp
	int nOutSize = vyOut.GetSize();
	vector vEvalCumLen;
	vEvalCumLen.Data(0, dCurveLen, (dCurveLen-0)/(nOutSize-1.0));
	
	
	matrix mOut(2, nOutSize);
	// Call internal function for performing cubic b-spline interpolation
	/// Cloud 9/24/07 NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
	//if(OE_NOERROR != ocmath_parametric_interpolate_eval(vEvalCumLen, mOut, nOutSize, vCumLen, mIn, nSize, 2, nMethod, dSmoothFac))
	if(OE_NOERROR != ocmath_parametric_interpolate_eval(vEvalCumLen, mOut, nOutSize, vCumLen, mIn, nSize, 2, nMethod, 0))
	/// End NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
	{
		XF_THROW(XFERR_BSPLINE_INTERP_FAILED);
		return false;
	}
	mOut.GetRow(vxOut, 0);
	mOut.GetRow(vyOut, 1);
	return true;
}

///Cheney 2007-6-7 ADD_AN_ERR_CHECK_FUNC
static int _check_err_condition(TreeNode& trGetN, int nSize)
{
	int nErr = CER_NO_ERROR;
	
	if(get_input_xyrange_num(trGetN.iy) != 1)
		nErr = CER_NOT_ONE_XYRANGE;
	
	else if(0>= get_input_xyrange_data_size(trGetN.iy))
		nErr = CER_NO_DATA;
	
	else if(_check_pts_enough(trGetN, nSize) != OE_NOERROR)
		nErr = CER_DATA_TOO_FEW;
	
	else if(trGetN.npts.dVal < MIN_OUTPUT_INTERPOLATION_POINTS)
		nErr = CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE;

	/// Cloud 9/24/07 NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
	//else if(trGetN.sf.dVal < 0)
		//nErr = CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE;
	/// End NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
	
	return nErr;
}
///end ADD_AN_ERR_CHECK_FUNC

//------ Folger 07/23/08 BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS
static	void	_set_output_range_comments(XYRange &oy, const XYRange& iy, int nMethod)
{
	vector<string>		vsMethods = {"Linear", "Spline", "B-Spline"};
	string	strComments;
	strComments.Format("%s trace interp of %s", vsMethods[nMethod], get_input_data_range_string(iy));
	oy.SetOutputComment(strComments);
}
//------ End BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS

static bool _get_err_condition(TreeNode trGetN, int nSize, string& strErrMsg)
{
	strErrMsg = "";
	int nErr = CER_NO_ERROR;
	nErr = _check_err_condition(trGetN, nSize);
	if(nErr != CER_NO_ERROR)
	{
		
		strErrMsg = nErr;
		
		if(trGetN.npts.dVal < MIN_OUTPUT_INTERPOLATION_POINTS)
		{
			strErrMsg += ":";
			strErrMsg += _get_interp_method_name(trGetN.method.nVal) + " " + STR_ERR_THROW1;
			strErrMsg += "|";
			strErrMsg += MIN_OUTPUT_INTERPOLATION_POINTS;
		}
		return false;
	}
	
	return true;
}

static void	 _run_interp1trace_on_current_data(TreeNode& trGetN, PageBase& pgTemp, Worksheet& wksTemp)
{
	XYRange xy, xySim;	
	if(!init_preview_graph(trGetN.iy, pgTemp, wksTemp, NULL, &xy, &xySim))
		return;
	int method = trGetN.method.nVal;
	int npts = trGetN.npts.nVal;
	wksTemp.SetSize(0, -1);///Kyle 09/04/2009 CLEAR_DATA
	try {
		interp1trace(xy, method, npts,  xySim);
	}
	catch(int nErr)
	{
	}
	/// Iris 10/13/09 QA70-14403 PREVIEW_GRAPH_SHOULD_NEVER_RESCALE_ON_CHANGE
	/*
	// Kyle 09/22/2009 rescale preview
	GraphPage gp = pgTemp;
	GraphLayer gl = gp.Layers(0);
	if(gl)
		gl.Rescale();
	*/
	///end PREVIEW_GRAPH_SHOULD_NEVER_RESCALE_ON_CHANGE
}


void interp1trace(const XYRange& iy, const int& method, const int& npts, XYRange& oy)
{
	vector vxIn, vyIn, vxOut, vyOut;
	
	if(!iy.IsValid() || iy.GetNumData(DRR_GET_DEPENDENT) != 1 || !iy.GetData(vyIn, vxIn))
		XF_THROW(CER_NOT_ONE_XYRANGE)
	
	if(0>= vyIn.GetSize())
		XF_THROW(CER_NO_DATA);
		
	if (npts < MIN_OUTPUT_INTERPOLATION_POINTS)
		XF_THROW_EX2(CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE, STR_ERR_THROW1, MIN_OUTPUT_INTERPOLATION_POINTS);
	/// Cloud 9/24/07 NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
	//if(sf < 0)
		//XF_THROW_EX2(CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE, STR_ERR_THROW2, MIN_SMOOTHING_FACTOR);
	/// End NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
	
	vyOut.SetSize(npts);
	/// Cloud 9/24/07 NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
	//if(!_interpolate_by_parameter(vxIn, vyIn, vxOut, vyOut, sf, method))
	if(!_interpolate_by_parameter(vxIn, vyIn, vxOut, vyOut, method))
	/// End NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
		return;
	
	///Kyle 08/19/2009 QA80-14023 FIX_OUTPUT_SAMPLING_INTERVAL_IS_LOST_WHEN_INPUT_IS_LOOSE_DATASET
	//if(oy.SetData(&vyOut, &vxOut,  0, NULL, DRS_SET_COL_DESIGNATIONS))
	///Kyle 09/22/2009 QA80-14023 FIX_SAMPLING_IS_NOT_RESET_IF_SET_INPUT_AS_OUTPUT
	//if(set_xyrange_data_ex(oy, &vyOut, &vxOut,  0, iy))
	/// YuI 09/30/09 QA70-14399 UNNECESARY_AUTOUPDATE_IN_CASE_OF_INPUT_NEW
	//	if( oy.SetData(&vyOut, &vxOut,  0, NULL, DRS_SET_COL_DESIGNATIONS) && update_output_xyrange_even_sampling(oy, &vxOut) )
	
	// reverting Kyle's change
	// fixed in update_output_xyrange_even_sampling which is called from set_xyrange_data_ex
	/// YuI 10/13/09 QA70-14023 OPTION_TO_FORCE_SAMPLING_INTERVAL_RECALCULATION
	if( set_xyrange_data_ex(oy, &vyOut, &vxOut,  0, iy, NULL, SXYDC_RECALCULATE_SAMPLING_INTERVAL) )
	/// end OPTION_TO_FORCE_SAMPLING_INTERVAL_RECALCULATION
	/// end UNNECESARY_AUTOUPDATE_IN_CASE_OF_INPUT_NEW
	///End FIX_SAMPLING_IS_NOT_RESET_IF_SET_INPUT_AS_OUTPUT
	///End FIX_OUTPUT_SAMPLING_INTERVAL_IS_LOST_WHEN_INPUT_IS_LOOSE_DATASET
	{
		/// Max 5/17/07 NEW_NAME_CREATION
		/*
		Worksheet wks;
		int r1, r2, c1, c2;
		int yIndex = get_first_y_col_index(iy);
		string strName = range_get_col_name(iy, yIndex);
	
		if(strName == NULL)
			strName = STR_INTER_RESULT1;
		else
			strName = STR_INTER_RESULT2 + strName;
		
		oy.GetRange(Y_INDEX_IN_XYRANGE, r1, c1, r2, c2, wks);
		wks.Columns(c1).SetLongName(strName);
		*/
		/// END NEW_NAME_CREATION
		
		// If user started from a graph, add the interpolation results to the graph
		///Arvin 08/16/07 QA70-10073 KEEP_OUTPUT_CURVE_CUSTOMIZATION_AFTER_RECALCULATE_FOR_XF
		//DataPlot dp = oy.MakePlot(iy);
		//if(dp)
		//{
		//	dp.SetColor(color);
		//	/*
		//	GraphLayer gl;
		//	dp.GetParent(gl);
		//	if(gl)
		//	{	
		//		legend_update(gl);
		//		gl.Rescale();
		//	}
		//	*/
		//}	
		xf_check_plot_output_rng_in_source_rng_graph(iy, oy);
		///end KEEP_OUTPUT_CURVE_CUSTOMIZATION_AFTER_RECALCULATE_FOR_XF
	}
	else
	{
		XF_THROW(XFERR_FAIL_IN_SET_XYRANGE_DATA);
	}
	
	//------ Folger 07/23/08 BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS
	_set_output_range_comments(oy, iy, method)
	//------
	
}

//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 interp1trace_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return interp1trace_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	/// Sandy 03/13/09  QA80-13260 ADD_PREVIEW
	/*
	bOKEnable = true;
	
	update_interp_number_points(trGetN.npts, trGetN.iy);		///------ Folger 03/12/09 QA80-13261 AUTO_SUPPORT_FOR_NUMBER_OF_POINTS_IN_INTERPOLATE_TOOLS
	
	if(GETNE_ON_INIT == nEventID)
		_init_tree_show(trGetN);
		
	bool bIsChangingData1 = lstrcmpi(lpcszNodeName,STR_NODE_XYRANGE) == 0? true:false;
	/// Cloud 9/24/07 NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
	//bool bIsChangingData2 = lstrcmpi(lpcszNodeName,STR_NODE_METHOD) == 0? true:false;
	
	//if(bIsChangingData2)
		//_update_method_show(trGetN);
	
	/// Cloud 07/23/07 GET_SMOOTH_FACTOR_AUTOMATICALLY
	//bool bChangeSF = lstrcmpi(lpcszNodeName, "sf")==0 ? true : false;
	//if (GETNE_ON_INIT==nEventID || GETNE_ON_THEME==nEventID || bChangeSF || lstrcmpi(lpcszNodeName, "method")==0 || lstrcmpi(lpcszNodeName, "iy")==0)
	//{
		//TreeNode trsf = trGetN.sf;
		//if (1==octree_get_auto_support(&trsf))
		//{
			//get_smooth_factor(trGetN);
		//}
	//}
	/// End GET_SMOOTH_FACTOR_AUTOMATICALLY
	/// End NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
	
	int nSize = get_input_xyrange_data_size(trGetN.iy);
	
	int nErr = CER_NO_ERROR;
	
	///Cheney 2007-6-7 ADD_AN_ERR_CHECK_FUNC
	//if(get_input_xyrange_num(trGetN.iy) != 1)
		//nErr = CER_NOT_ONE_XYRANGE;
	//
	//else if(0>= get_input_xyrange_data_size(trGetN.iy))
		//nErr = CER_NO_DATA;
	//
	//else if(_check_pts_enough(trGetN, nSize) != OE_NOERROR)
		//nErr = CER_DATA_TOO_FEW;
	//
	//else if(trGetN.npts.dVal < MIN_OUTPUT_INTERPOLATION_POINTS)
		//nErr = CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE;
	//
	//else if(trGetN.sf.dVal < 0)
		//nErr = CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE;
	nErr = _check_err_condition(trGetN, nSize);
	///end ADD_AN_ERR_CHECK_FUNC
	
	
	if(nErr != CER_NO_ERROR)
	{
		bOKEnable = false;
		strErrMsg = nErr;
		
		if(trGetN.npts.dVal < MIN_OUTPUT_INTERPOLATION_POINTS)
		{
			strErrMsg += ":";
			strErrMsg += _get_interp_method_name(trGetN.method.nVal) + " " + STR_ERR_THROW1;
			strErrMsg += "|";
			strErrMsg += MIN_OUTPUT_INTERPOLATION_POINTS;
		}
	
		/// Cloud 9/24/07 NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
		//if(trGetN.sf.dVal < 0)
		//{
			//strErrMsg += ":";
			//strErrMsg += _get_interp_method_name(trGetN.method.nVal) + " " + STR_ERR_THROW2;
			//strErrMsg += "|";
			//strErrMsg += MIN_SMOOTHING_FACTOR;
		//}
		/// End NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
	}
	
	return bOKEnable;
	*/
	
	return false;

}

int interp1trace_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	return false;
}
//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 interp1trace_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	
	
	//------ fisher 11/16/07 ADD_MAP_ID_TO_CHM
	if(is_use_origin_chm())
		trGetN.SetAttribute(STR_HELPID_ATTRIB, IDD_XF_interp1trace);
	
	if(0 == nGetNDialog || -1 == nGetNDialog)
		update_xminmax_show(trGetN);
	
	update_interp_number_points(trGetN.npts, trGetN.iy);		///------ Folger 03/12/09 QA80-13261 AUTO_SUPPORT_FOR_NUMBER_OF_POINTS_IN_INTERPOLATE_TOOLS
	
	/// Cloud 9/24/07 NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
	/// Cloud 07/23/07 GET_SMOOTH_FACTOR_AUTOMATICALLY
	//TreeNode trsf = trGetN.sf;
	//if (1==octree_get_auto_support(&trsf))
	//{
		//get_smooth_factor(trGetN);
	//}
	/// End GET_SMOOTH_FACTOR_AUTOMATICALLY
	/// End NOT_SMOOTH_FOR_NON_MONOTONIC_DATA
	
	///Cheney 2007-6-7 ADD_AN_ERR_CHECK_FUNC
	//if(0 == nGetNDialog && (dwCntrl&LTXF_THEME_USED) )	/// Max 6/8/07 PROCEED_WITH_DLG_SHOULD_DETECT_MENU_AND_THEME
	//if((dwCntrl&LTXF_FROM_GUI_MENU) && (dwCntrl&LTXF_THEME_USED) ) //CPY 6/8/2007
	if((dwCntrl & LTXF_FROM_GUI_MENU) && (dwCntrl & LTXF_THEME_USED) && 0 == nGetNDialog)
	{
		int nSize = get_input_xyrange_data_size(trGetN.iy);
		if(_check_err_condition(trGetN, nSize) != CER_NO_ERROR)
			nRet = XFEVT_PROCEED_WITH_DLG;	
	}
	///end ADD_AN_ERR_CHECK_FUNC
}
//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 interp1trace_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}


// put your grid initialization here
// you may also initialize wksTemp here
static void GetNGraphPreview_OnInitGrid(TreeNode& trGetN, PageBase& pgTemp, Datasheet& wksTemp,
PictureControl& pict, // optional tab for showing an image or EMF, as requested in OnDialogSetup 
DWORD& dwUpdateGraph,  // default to 0, UPDATE_GRAPH_CHANGED to cause graphs to be updated, UPDATE_GRAPH_INVALID to disable preview button
DWORD& dwUpdateGrid, // default to 0, set to UPDATE_GRID_SIMPLE to update the DynaControl grid, UPDATE_GRID_RESET to reset DynaControl grid
DWORD& dwEnables,// bOKEnable, bBTN1Enable, bBTN2Enable and bBTN3Enable :default to true, can set to false to disable buttons
string& strErrMsg) // optional err msg to be shown on dialog
{
	DECLARE_BUTTON_ENABLES
	DECLARE_UPDATE_GRAPH
	DECLARE_UPDATE_GRID
	bUpdateGraph = true;
	
	///update gui
	_init_tree_show(trGetN);

	
	//check input
	int nSize = get_input_xyrange_data_size(trGetN.iy);

	bOKEnable = _get_err_condition(trGetN, nSize, strErrMsg);
	
	//if ok, set data to temp worksheet
	///Kyle 07/28/2009 QA80-14026 FIX_WRONG_LEGEND_FOR_PREVIEW, always init the temp worksheet
	//if(bOKEnable)
	bUpdateGraph = bOKEnable;
	///End FIX_WRONG_LEGEND_FOR_PREVIEW
	{
		Worksheet wks = wksTemp;
		wks.SetSize(-1, 2, WSS_CLEAR_DATA);
		wks.SetColDesignations("XY");
		wks.Columns(1).SetLongName("Interp1trace");
	}

	s_bInit = false;
	s_strErrMsg = strErrMsg; //keep the err message for OnInitGraph;
}

///////////////////////////////////////////////////////

// pgTemp is the graph for preview or control
// wksTemp is the the temp wks created to hold data to plot into pgTemp
static void GetNGraphPreview_OnInitGraph(TreeNode& trGetN, PageBase& pgTemp, Datasheet& wksTemp,
PictureControl& pict, // optional tab for showing an image or EMF, as requested in OnDialogSetup  
DWORD& dwUpdateGrid, // default to 0, set to UPDATE_GRID_SIMPLE to update the DynaControl grid, UPDATE_GRID_RESET to reset DynaControl grid
DWORD& dwEnables,// bOKEnable, bBTN1Enable, bBTN2Enable and bBTN3Enable :default to true, can set to false to disable buttons
string& strErrMsg) // optional err msg to be shown on dialog
{
	DECLARE_BUTTON_ENABLES
	DECLARE_UPDATE_GRID
	strErrMsg = s_strErrMsg; 
	///Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
	//GraphPage gp = pgTemp;
	//page_load(gp, "NonePreview"); 	
	//
	//load_text_for_nonepreview_graphpage(gp, TEMPLATE_NONE_PREVIEW_CONTENT, TEMPLATE_NONE_PREVIEW_HINTS);
	xf_load_nopreview(pgTemp);
	///End CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
}

///////////////////////////////////////////////////////

static void GetNGraphPreview_OnUpdateGraph(TreeNode& trGetN, PageBase& pgTemp, Datasheet& wksTemp, PictureControl& pict)
{
	Worksheet wks = wksTemp;
	if(!s_bInit)
	{
		Worksheet wks = wksTemp;
		wks.SetSize(0,-1, true);

		///Kyle 03/13/2009 QA80-13260-S1 ADD_OPTION_TO_COPY_FORMAT_FROM_SOURCE_LAYER
		//init_preview_graph(trGetN.iy, pgTemp, wks, "CurvePreview");
		init_preview_graph(trGetN.iy, pgTemp, wks, "CurvePreview", NULL, NULL, 0, 0, 1, PREVIEW_LAYER_FORMAT_SCALE_TYPE);
		///End ADD_OPTION_TO_COPY_FORMAT_FROM_SOURCE_LAYER

		GraphPage gp = pgTemp;
		gp.Refresh(true);
		s_bInit = true;
	}

	_run_interp1trace_on_current_data(trGetN, pgTemp, wks);
}

///////////////////////////////////////////////////////

static void GetNGraphPreview_OnChange(TreeNode& trGetN, TreeNode& trNode, PageBase& pgTemp, Datasheet& wksTemp,
PictureControl& pict, // optional tab for showing an image or EMF that might be present, as requested in OnDialogSetup  
bool bChangedByGraph, // called when graph has been modified by user, like dragging a vertical line
DWORD& dwUpdateGraph,  // default to 0, UPDATE_GRAPH_CHANGED to cause graphs to be updated, UPDATE_GRAPH_INVALID to disable preview button
DWORD& dwUpdateGrid,  // default to 0, set to UPDATE_GRID_SIMPLE to update the DynaControl grid, UPDATE_GRID_RESET to reset DynaControl grid
DWORD& dwEnables,	// bOKEnable, bBTN1Enable, bBTN2Enable and bBTN3Enable :default to true, can set to false to disable buttons
string& strErrMsg) // optional err msg to be shown on dialog
{
	DECLARE_BUTTON_ENABLES
	DECLARE_UPDATE_GRAPH
	DECLARE_UPDATE_GRID
	bOKEnable = true;
	update_interp_number_points(trGetN.npts, trGetN.iy);		///------ Folger 03/12/09 QA80-13261 AUTO_SUPPORT_FOR_NUMBER_OF_POINTS_IN_INTERPOLATE_TOOLS
	
	int nSize = get_input_xyrange_data_size(trGetN.iy);
	bOKEnable = _get_err_condition(trGetN, nSize, strErrMsg);
	
	if (trNode && trNode.tagName =="iy")
	{
		s_bInit = false;
	}
	
	if(!bOKEnable)
		dwUpdateGraph = UPDATE_GRAPH_INVALID; //nUpdateGraph = UPDATE_GRAPH_ERROR;
	else
		bUpdateGraph = bOKEnable;
}

// called from OnInitDialog to allow options on setting up of dialog
// dwOptions = 0 (default) will create a line graph with data in a temp worksheet
// dwOptions = XFGSETUP_IMAGEGRAPH_CNTRL to create an image graph with data in a temp matrix book
// dwOptions = XFGSETUP_MATRIX_CNTRL to have a MatrixControl with data in a temp matrix book
// dwOptions = XFGSETUP_2_TABS | XFGSETUP_EMF_1ST to have a PictureControl on 1st tab and a GraphControl on 2nd tab
// vsTabTitles is empty on entering the event, but you can put tab title strings in this array.
static void GetNGraphPreview_OnDialogSetup(TreeNode& trGetN, WndContainer& theDlg, DWORD& dwOptions, vector<string>& vsTabTitles)
{

}

// called when dialog is being destroyed, either as OK button or as Cancel button being pressed
static void GetNGraphPreview_OnDestroy(TreeNode& trGetN, PageBase& pgTemp, Datasheet& wksTemp, PictureControl& pict)
{

}
//------------
//
static void GetNGraphPreview_OnCustomButton(TreeNode& trGetN, int nButton, PageBase& pgTemp, Datasheet& wksTemp,
PictureControl& pict, // optional tab for showing an image or EMF that might be present, as requested in OnDialogSetup  
bool bChangedByGraph, // called when graph has been modified by user, like dragging a vertical line
DWORD& dwUpdateGraph,  // default to 0, UPDATE_GRAPH_CHANGED to cause graphs to be updated, UPDATE_GRAPH_INVALID to disable preview button
DWORD& dwUpdateGrid,  // default to 0, set to UPDATE_GRID_SIMPLE to update the DynaControl grid, UPDATE_GRID_RESET to reset DynaControl grid
DWORD& dwEnables,	// bOKEnable, bBTN1Enable, bBTN2Enable and bBTN3Enable :default to true, can set to false to disable buttons
string& strErrMsg) // optional err msg to be shown on dialog
{
	DECLARE_BUTTON_ENABLES
	DECLARE_UPDATE_GRAPH
	DECLARE_UPDATE_GRID

}
//


///////////////////////////////////////////////////////
	
int GetNGraphBox_interp1trace(TreeNode& trGetN, int nRow, int nCol, TreeNode& trNode, DWORD dwCntrl, int nType, WndContainer& theDlg, PageBase& pgTemp, Datasheet& wksTemp, PictureControl& pict)
{
	return xf_GetNPreviewDlg_event_handler(trGetN, nRow, nCol, trNode, dwCntrl, nType, theDlg, pgTemp, wksTemp, pict,
	GetNGraphPreview_OnInitGrid, GetNGraphPreview_OnInitGraph,
	GetNGraphPreview_OnChange, GetNGraphPreview_OnUpdateGraph, GetNGraphPreview_OnDialogSetup, GetNGraphPreview_OnDestroy,
	GetNGraphPreview_OnCustomButton);	
}


//This file is the template for GetNEvent4

///////////////////////////////////////////////////////

