#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	method_linear,
	method_spline,
	method_bspline,
};
enum{
	boundary_natural,
	boundary_notaknot,
};
#include <GetNBox.h> 
#include <event_utils.h>
#include <../OriginLab/graph_utils.h>		///Kyle 03/17/2009 CHECK_MIN_MAX_BASE_ON_GRAPH_SCALE_TYPE_IF_APPARENT_CHECKED
//#include <control.h>
//#include <XFbase.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
/// Kyle 11/25/2008 QA80-12051 GET_XYRANGE_DATA_BASE_ON_RULES
/// Folger 03/12/09 QA80-13261 AUTO_SUPPORT_FOR_NUMBER_OF_POINTS_IN_INTERPOLATE_TOOLS
/// Sandy 03/12/09  QA80-13260 ADD_PREVIEW
/// Folger 03/13/09 QA80-13262 CONVERT_OBJECT_VARIABLE_OPTIOANL_TO_NEW_IN_XF_DIALOG
/// Kyle 03/13/2009 QA80-13260-S1 ADD_OPTION_TO_COPY_FORMAT_FROM_SOURCE_LAYER
/// Kyle 03/17/2009 CHECK_MIN_MAX_BASE_ON_GRAPH_SCALE_TYPE_IF_APPARENT_CHECKED
/// Folger 04/10/09 QA80-13262-P2 OPTIONAL_SHOWN_INSTEAD_OF_NEW_AFTER_RESET_THEME
/// Folger 04/14/09 QA80-12786-P3 PREVIEW_GETN_FAILS_TO_SHOW_DATA_TIME_FORMAT_AFTER_CHANGED
/// Folger 04/14/09 QA80-13260-P5 FAILS_TO_UPDATE_DYNACTRL_SHOWN_STATUS_AFTER_CHANGE_THEME
/// Kyle 05/27/2009 QA80-13330-P4 RESCALE_PREVIEW_GRAPH_AFTER_UPDATE_DATA
/// Kyle 07/28/2009 QA80-14026 FIX_WRONG_LEGEND_FOR_PREVIEW
///	Folger 09/25/09 OLD_DYNAUSECHECK_STATUS_SHOULD_BE_RESET_WHEN_THEME_CHANGE
/// CPY 9/30/09 QA70-14403 PREVIEW_GRAPH_SHOULD_NEVER_RESCALE_ON_CHANGE undo Kyle 05/27/2009 QA80-13330-P4 RESCALE_PREVIEW_GRAPH_AFTER_UPDATE_DATA
/// Folger 10/20/09 QA81-14500 XF_SHOULD_CLEAR_OUTPUT_DATA_BY_DEFAULT_WHEN_TOTALLY_INTERSECTED_WITH_INPUT
/// Sophy 4/13/2010 QA81-15308 GET_GRAPHLAYER_OF_INPUTDATA_IN_XF_BODY
/// Kyle 04/16/2010 CLEAR_DATA_TO_FIX_WRONG_PREVIEW
///	Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
***************************************************************************************/

//#define Y_INDEX_IN_XYRANGE 1
#define MIN_BSPLINE_PTS 4
#define MIN_SPLINE_PTS 2
#define MIN_LINEAR_PTS 2
#define MIN_OUTPUT_INTERPOLATION_POINTS 1
#define MIN_SMOOTHING_FACTOR 0

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

#define STR_ATTRIB_OLD_CHK	"oldDynaCheck"///Cheney 2007-8-15 FIX_SOME_BU_OF_INTERP

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

#define STR_ERR_THROW1 _L("Minimum interpolation ponits")
#define STR_ERR_THROW2 _L("Smoothing Factor")

static void _update_method_show(TreeNode& trGetN)
{
	switch(trGetN.method.nVal)
	{
	case INTERP_TYPE_LINEAR:
		trGetN.boundary.Show=false;	/// Max 4/24/08 QA70-11435 v8.0849 ADD_BOUNDARY_CONDITION_TO_MATCH_SPLINE_CONNECTION_PLOTTING
		trGetN.sf.Show = false;
		trGetN.coef.Show = false;
		break;
	case INTERP_TYPE_SPLINE:
		trGetN.boundary.Show=true;	/// Max 4/24/08 QA70-11435 v8.0849 ADD_BOUNDARY_CONDITION_TO_MATCH_SPLINE_CONNECTION_PLOTTING
		trGetN.sf.Show = false;
		trGetN.coef.Show = true;
		break;
	case INTERP_TYPE_BSPLINE:
		trGetN.boundary.Show=false;	/// Max 4/24/08 QA70-11435 v8.0849 ADD_BOUNDARY_CONDITION_TO_MATCH_SPLINE_CONNECTION_PLOTTING
		trGetN.sf.Show = true;
		trGetN.coef.Show = true;
		break;
	default:
		break;
	}
}

static bool _init_tree_show(TreeNode& trGetN)
{
	//GraphLayer gl = Project.ActiveLayer();
	//if(!gl.IsValid())
		//trGetN.color.Show = false;
	
	_update_method_show(trGetN);
	
	return update_xminmax_show(trGetN);
}

static int _check_pts_enough(const TreeNode& trGetN, int nSize)
{
	switch(trGetN.method.nVal)
	{
	case INTERP_TYPE_LINEAR:
		if(nSize < MIN_LINEAR_PTS)
			return MIN_LINEAR_PTS;
		break;
	case INTERP_TYPE_SPLINE:
		if(nSize < MIN_SPLINE_PTS)
			return MIN_SPLINE_PTS;
		break;
	case INTERP_TYPE_BSPLINE:
		if(nSize < MIN_BSPLINE_PTS)
			return MIN_BSPLINE_PTS;
		break;
	default:
		break;
	}
	return OE_NOERROR;
}
/*
static bool _check_reset_to_data_x_range(double& x1, double& x2, const vector& vxIn, bool bCheckIfMissing = true)
{
	if(bCheckIfMissing && !is_missing_value(x1) && !is_missing_value(x2))
		return false;
	double dx1, dx2;
	vxIn.GetMinMax(dx1, dx2);
	if(!bCheckIfMissing || is_missing_value(x1)) x1 = dx1;
	if(!bCheckIfMissing || is_missing_value(x2)) x2 = dx2;
	//x1 = dx1;
	//x2 = dx2;
	return true;
}

static bool _check_reset_to_data_x_range(TreeNode& trGetN, const XYRange& iy, bool bCheckIfMissing)
{
	if(!iy.IsValid())
		return false;
	
	vector vx, vy;
	if(!iy.GetData(vy, vx,NULL, 0, 0))
		return false;
	double x1 = trGetN.x1.dVal;
	double x2 = trGetN.x2.dVal;
	if(_check_reset_to_data_x_range(x1, x2, vx, bCheckIfMissing))
	{
		trGetN.x1.dVal = x1;
		trGetN.x2.dVal = x2;
		return true;
	}
	return false;
}
*/

///Cheney 2007-8-15 FIX_SOME_BU_OF_INTERP
bool _check_min_max(int nPts, double dMin, double dMax)
{
	if(nPts == 1)
		return dMin > dMax? false : true;
	
	return check_min_max(dMin, dMax);
}
///end FIX_SOME_BU_OF_INTERP

///Kyle 03/17/2009 CHECK_MIN_MAX_BASE_ON_GRAPH_SCALE_TYPE_IF_APPARENT_CHECKED
bool _check_min_max_on_scale_type(TreeNode& trGetN)
{
	if(trGetN.apparent.nVal == 0)
		return true;
	
	int nXScale;
	GraphLayer gl = Project.ActiveLayer();
	axis_get_scale_type(gl, &nXScale);
	
	if(	is_missing_value(real_space(trGetN.xmin.dVal, nXScale)) ||
		trGetN.npts.nVal > 1 && is_missing_value(real_space(trGetN.xmax.dVal, nXScale))	)
	{
		return false;
	}
	return true;
}
///End CHECK_MIN_MAX_BASE_ON_GRAPH_SCALE_TYPE_IF_APPARENT_CHECKED

/// Max 12/19/07 ADD_STRERRMSG_OUTPUT_ON_ERR_CHECKING
///Cheney 2007-6-7 ADD_AN_ERR_CHECK_FUNC
//static int _check_err_condition(TreeNode& trGetN, int nSize)
static int _check_err_condition(TreeNode& trGetN, int nSize, string* pstrErrMsg = NULL)
{
	string strErrMsg;
	int nErr = CER_NO_ERROR;
	int npts = _check_pts_enough(trGetN, nSize);
	
	if(get_input_xyrange_num(trGetN.iy) != 1)
	{	
		nErr = CER_NOT_ONE_XYRANGE;
		strErrMsg = nErr;
	
	}	
	else if(0>= get_input_xyrange_data_size(trGetN.iy))
	{	
		nErr = CER_NO_DATA;
		strErrMsg = nErr;
	
	}
	else if( npts != OE_NOERROR)
	{
		nErr = CER_DATA_TOO_FEW;
		strErrMsg = nErr;
		strErrMsg += ":";
		strErrMsg += npts;
	}
	///Cheney 2007-8-15 FIX_SOME_BU_OF_INTERP
	//else if(!check_min_max(trGetN.xmin.dVal, trGetN.xmax.dVal))
	//	nErr = CER_MIN_MAX;
	///end FIX_SOME_BU_OF_INTERP
	
	else if(trGetN.npts.dVal < MIN_OUTPUT_INTERPOLATION_POINTS)
	{
		nErr = CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE;
		strErrMsg = nErr;
		strErrMsg += ":";
		strErrMsg += STR_ERR_THROW1;
		strErrMsg += "|";
		strErrMsg += MIN_OUTPUT_INTERPOLATION_POINTS;
	}
	///Cheney 2007-8-15 FIX_SOME_BU_OF_INTERP
	else if(!_check_min_max(trGetN.npts.dVal, trGetN.xmin.dVal, trGetN.xmax.dVal))
	{
		nErr = CER_MIN_MAX;
		strErrMsg = nErr;
	}
	///end FIX_SOME_BU_OF_INTERP
	
	///Kyle 03/17/2009 CHECK_MIN_MAX_BASE_ON_GRAPH_SCALE_TYPE_IF_APPARENT_CHECKED
	else if(!_check_min_max_on_scale_type(trGetN))
	{
		nErr = XFERR_RANGE_VIOLATE_SCALE_TYPE;
		strErrMsg = nErr;
	}
	///End CHECK_MIN_MAX_BASE_ON_GRAPH_SCALE_TYPE_IF_APPARENT_CHECKED
	
	/// Max 12/19/07 CALCULATE_SMOOTH_FACTOR_ONLY_FOR_BSPLINE
	//else if(trGetN.sf.dVal < 0)
	else if((trGetN.method.nVal == INTERP_TYPE_BSPLINE) && (trGetN.sf.dVal < 0))
	/// END CALCULATE_SMOOTH_FACTOR_ONLY_FOR_BSPLINE
	{
		nErr = CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE;
		strErrMsg = nErr;
		strErrMsg += ":";
		strErrMsg += STR_ERR_THROW2;
		strErrMsg += "|";
		strErrMsg += MIN_SMOOTHING_FACTOR;
	}
	if(pstrErrMsg != NULL)
		*pstrErrMsg = strErrMsg;
	return nErr;
}
///end ADD_AN_ERR_CHECK_FUNC
/// END ADD_STRERRMSG_OUTPUT_ON_ERR_CHECKING

///Cheney 2007-8-15 FIX_SOME_BU_OF_INTERP
static void _set_coef_disable_if_linear(TreeNode& trGetN)
{
	if(trGetN.method.nVal == INTERP_TYPE_LINEAR)
		trGetN.coef.SetAttribute( STR_ATTRIB_DYNACONTROL_USE_CHECK, false );
}

static void _update_coef_attrib(TreeNode& trGetN, LPCSTR lpcszAttrib1, LPCSTR lpcszAttrib2)
{
	TreeNode trCoef = trGetN.coef;
	int nVal = 0;
	trCoef.GetAttribute( lpcszAttrib1, nVal );
	trCoef.SetAttribute( lpcszAttrib2, nVal );
}

static void _update_coef_enable(TreeNode& trGetN)
{
	if(trGetN.method.nVal != INTERP_TYPE_LINEAR)
	{
		_update_coef_attrib(trGetN, STR_ATTRIB_OLD_CHK, STR_ATTRIB_DYNACONTROL_USE_CHECK);
		_update_coef_attrib(trGetN, STR_ATTRIB_DYNACONTROL_USE_CHECK, STR_ATTRIB_OLD_CHK);
	}
	else 
		trGetN.coef.SetAttribute( STR_ATTRIB_DYNACONTROL_USE_CHECK, false );
}
///end FIX_SOME_BU_OF_INTERP

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

static void	_run_interp1xy_on_current_data(TreeNode& trGetN, PageBase& pgTemp, Worksheet& wksTemp)
{
	XYRange xy, xySim;	
	if(!init_preview_graph(trGetN.iy, pgTemp, wksTemp, NULL, &xy, &xySim))
		return;
	wksTemp.SetSize(0, -1);				///Kyle 04/16/2010 CLEAR_DATA_TO_FIX_WRONG_PREVIEW
	int method = trGetN.method.nVal;
	int npts = trGetN.npts.nVal;
	
	double xmin = trGetN.xmin.dVal;
	double xmax = trGetN.xmax.dVal;

	int boundary = trGetN.boundary.nVal;

	double sf = trGetN.sf.dVal;
	int apparent = trGetN.apparent.nVal;

	try {
		interp1xy(xy, method, npts,  xmin,  xmax, boundary, sf, apparent, xySim, NULL);
	}
	catch(int nErr)
	{
	}
	//---- CPY 9/30/09 QA70-14403 PREVIEW_GRAPH_SHOULD_NEVER_RESCALE_ON_CHANGE
	/*
	GraphPage gp = pgTemp;
	///Kyle 05/27/2009 QA80-13330-P4 RESCALE_PREVIEW_GRAPH_AFTER_UPDATE_DATA
	GraphLayer gl = gp.Layers(0);
	if(gl)
		gl.Rescale();
	///End RESCALE_PREVIEW_GRAPH_AFTER_UPDATE_DATA
	*/
	//----
	
}


void interp1xy(const XYRange& iy, const int& method, const int& npts, const double& xmin, const double& xmax, const int& boundary, const double& sf, const int& apparent, XYRange& oy, vector& coef)
{
		
	if(!iy.IsValid() || iy.GetNumData(DRR_GET_DEPENDENT) != 1)
		XF_THROW(CER_NOT_ONE_XYRANGE)
	///Cheney 2007-8-15 FIX_SOME_BU_OF_INTERP
	//if (!check_min_max(xmin, xmax))
	if (!_check_min_max(npts, xmin, xmax))
	///end FIX_SOME_BU_OF_INTERP
		XF_THROW(CER_MIN_MAX)
	if (npts < MIN_OUTPUT_INTERPOLATION_POINTS)
		XF_THROW_EX2(CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE, STR_ERR_THROW1, MIN_OUTPUT_INTERPOLATION_POINTS);
	//if (sf<0)//Sandy 2009-3-17 only method is bspline need check sf<0
	if(method == INTERP_TYPE_BSPLINE && sf<0)	
		XF_THROW_EX2(CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE, STR_ERR_THROW2, MIN_SMOOTHING_FACTOR);
	
	/// Cloud 04/19/2007 USE_OCMATH_FUNCTION_TO_DO_INTERPOLATION
	vector vxIn, vyIn, vxOut, vyOut, vcof;
	///Cheney 2007-8-15 FIX_SOME_BU_OF_INTERP
	//vxOut.Data(xmin, xmax, (xmax-xmin)/(npts-1));
	if(npts == 1)
		vxOut.Add(xmin); //as max suggestion
	else
		vxOut.Data(xmin, xmax, (xmax-xmin)/(npts-1));
	///end FIX_SOME_BU_OF_INTERP
	///Kyle 11/25/2008 QA80-12051 GET_XYRANGE_DATA_BASE_ON_RULES
	//int nSize = interpolation_preprocess(vxOut, iy, vxIn, vyIn, npts, vyOut, method, vcof);
	DWORD dwRules = DRR_BAD_WEIGHT_TREATMENT;
	int nXScale = LINEAR_SPACE;
	int nYScale = LINEAR_SPACE;
	if(apparent)
	{
		dwRules = DRR_APPARENT;
		///Sophy 4/13/2010 QA81-15308 GET_GRAPHLAYER_OF_INPUTDATA_IN_XF_BODY
		//GraphLayer gl = Project.ActiveLayer();
		GraphLayer gl; //in XF body, when the XF create new book, input graphlayer might NOT be active any more...
		get_graphlayer_from_input(iy, gl);
		///end GET_GRAPHLAYER_OF_INPUTDATA_IN_XF_BODY
		if ( gl )
		{
			///Kyle 03/17/2009 CHECK_MIN_MAX_BASE_ON_GRAPH_SCALE_TYPE_IF_APPARENT_CHECKED
			//Tree tr;
			//tr = gl.GetFormat(FPB_SCALE, FOB_SCALE, true, true);
			//TreeNode trXAxis = tr.Root.Axes.GetNode("X");
			//if(trXAxis)
				//nXScale = trXAxis.Scale.Type? trXAxis.Scale.Type.nVal : 0;
			//TreeNode trYAxis = tr.Root.Axes.GetNode("Y");
			//if(trYAxis)
				//nYScale = trYAxis.Scale.Type? trYAxis.Scale.Type.nVal : 0;
			axis_get_scale_type(gl, &nXScale, &nYScale);
			///End CHECK_MIN_MAX_BASE_ON_GRAPH_SCALE_TYPE_IF_APPARENT_CHECKED
		}
		///Kyle 03/17/2009 CHECK_MIN_MAX_BASE_ON_GRAPH_SCALE_TYPE_IF_APPARENT_CHECKED
		if(	is_missing_value(real_space(xmin, nXScale)) ||
			npts > 1 && is_missing_value(real_space(xmax, nXScale))	)
		{
			XF_THROW(XFERR_RANGE_VIOLATE_SCALE_TYPE);
		}
		///End CHECK_MIN_MAX_BASE_ON_GRAPH_SCALE_TYPE_IF_APPARENT_CHECKED
		vxOut = real_space(vxOut, nXScale);
	}
	int nSize = interpolation_preprocess(vxOut, iy, vxIn, vyIn, npts, vyOut, method, vcof, dwRules);
	///End GET_XYRANGE_DATA_BASE_ON_RULES
	
	/// Max 4/24/08 QA70-11435 v8.0849 ADD_BOUNDARY_CONDITION_TO_MATCH_SPLINE_CONNECTION_PLOTTING
	//int nRet = ocmath_interpolate(vxOut, vyOut, npts, vxIn, vyIn, nSize, method, sf, NULL, vcof);
	DWORD dwCntrl = OCMATH_SRCDATA_X_MONOTONIC;	// interpolation_preprocess() sorts the input
	int nRet = ocmath_interpolate(vxOut, vyOut, npts, vxIn, vyIn, nSize, method, sf, NULL, vcof, dwCntrl, boundary);
	/// END ADD_BOUNDARY_CONDITION_TO_MATCH_SPLINE_CONNECTION_PLOTTING
	
	if(nRet != OE_NOERROR)
		switch (method)
		{
		case 0:
			XF_THROW(XFERR_LINEAR_INTERP_FAILED);
			break;
		case 1:
			XF_THROW(XFERR_SPLINE_INTERP_FAILED);
			break;
		case 2:
			XF_THROW(XFERR_BSPLINE_INTERP_FAILED);
			break;
		}
	///Kyle 11/25/2008 QA80-12051 GET_XYRANGE_DATA_BASE_ON_RULES
	if(apparent)
	{
		vxOut = real_inv_space(vxOut, nXScale);
		vyOut = real_inv_space(vyOut, nYScale);
	}
	///End GET_XYRANGE_DATA_BASE_ON_RULES
	///Cheney 2007-8-15 FIX_SOME_BU_OF_INTERP
	//if(coef)
	if(coef && method > INTERP_TYPE_LINEAR)
	///end FIX_SOME_BU_OF_INTERP
		coef = vcof;
	
	//if(oy.SetData(&vyOut, &vxOut))
	///------ Folger 10/20/09 QA81-14500 XF_SHOULD_CLEAR_OUTPUT_DATA_BY_DEFAULT_WHEN_TOTALLY_INTERSECTED_WITH_INPUT
	//if(oy.SetData(&vyOut, &vxOut,  0, NULL, DRS_SET_COL_DESIGNATIONS))
	if( set_xyrange_data_ex(oy, &vyOut, &vxOut,  0, iy, NULL, SXYDC_RECALCULATE_SAMPLING_INTERVAL) )
	///------ End XF_SHOULD_CLEAR_OUTPUT_DATA_BY_DEFAULT_WHEN_TOTALLY_INTERSECTED_WITH_INPUT
	{
		/// Max 5/16/07 QA70-9715 NEW_NMAE_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_NMAE_CREATION
		///Arvin 08/16/07 QA70-10073 KEEP_OUTPUT_CURVE_CUSTOMIZATION_AFTER_RECALCULATE_FOR_XF
		//DataPlot dp = oy.MakePlot(iy);
		//if(dp)
		//	dp.SetColor(color);
		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);
	
	//switch(method)
	//{
		//case INTERP_TYPE_LINEAR:
			//string		strXFNameInner = "interp1q";
			//XFBase		xf(strXFNameInner);
			//if ( !xf )
				//XF_THROW(XFERR_FAIL_LOAD_XF);
	
			//if ( !xf.SetArgs(iy, npts, xmin, xmax, oy, color) )
				//XF_THROW(XFERR_FAIL_SET_ARG);
	
			///// Max 11/17/06 USE_EXECUTELABTALK
			///*
			//if ( !xf.Evaluate() )
				//XF_THROW(XFERR_LINEAR_INTERP_FAILED);
			//*/
			//DWORD dwCntrl = 0;
			//int nErr;
			//if(xf.ExecuteLabTalk(NULL, NULL, NULL, 0, &nErr, dwCntrl) != 0)
				//XF_THROW(XFERR_SPLINE_INTERP_FAILED);
			///// END USE_EXECUTELABTALK
			//break;
		//case INTERP_TYPE_SPLINE:
			//string		strXFuncName = "spline";
			///*
			//XFBase		xf(strXFNameInner);
			//if ( !xf )
				//XF_THROW(XFERR_FAIL_LOAD_XF);
			//*/
			//XFunction xf;
			//TreeNode trXF;
			//bool bDialog = false;
	
			//bool bSkipHelpNodes = bDialog? false:true;
			//if(!xf.Load(&trXF, strXFuncName, 0, true, bSkipHelpNodes, true))
				//XF_THROW(XFERR_FAIL_LOAD_XF);
	
			//if(!xf.SetArg("iy", iy) || !xf.SetArg("npts", npts) || !xf.SetArg("xmin", xmin) || !xf.SetArg("xmax", xmax) || !xf.SetArg("oy", oy) || !xf.SetArg("color", color))
				//XF_THROW(XFERR_FAIL_SET_ARG);
			//
			//if(coef)
			//{
				//if(!xf.SetArg("coef", coef))
					//XF_THROW(XFERR_FAIL_SET_ARG);
			//}
			///*
			//if ( !xf.SetArgs(iy, npts, x1, x2, oy, coef, color) )
				//XF_THROW(XFERR_FAIL_SET_ARG);
			//*/
			//DWORD dwCntrl = 0;
			//int nErr;
			//if(xf.ExecuteLabTalk(NULL, NULL, NULL, 0, &nErr, dwCntrl) != 0)
				//XF_THROW(XFERR_SPLINE_INTERP_FAILED);
			///*
			//if ( !xf.Evaluate() )
				//XF_THROW(XFERR_SPLINE_INTERP_FAILED);
			//*/
			//break;
		//case INTERP_TYPE_BSPLINE:
			//string		strXFuncName = "bspline";
			///*
			//XFBase		xf(strXFNameInner);
			//if ( !xf )
				//XF_THROW(XFERR_FAIL_LOAD_XF);
	
			//if ( !xf.SetArgs(iy, npts, x1, x2, sf, oy, coef, color) )
				//XF_THROW(XFERR_FAIL_SET_ARG);
	
			//if ( !xf.Evaluate() )
				//XF_THROW(XFERR_BSPLINE_INTERP_FAILED);
			//*/
			//XFunction xf;
			//TreeNode trXF;
			//bool bDialog = false;
	
			//bool bSkipHelpNodes = bDialog? false:true;
			//if(!xf.Load(&trXF, strXFuncName, 0, true, bSkipHelpNodes, true))
				//XF_THROW(XFERR_FAIL_LOAD_XF);
	
			//if(!xf.SetArg("iy", iy) || !xf.SetArg("npts", npts) || !xf.SetArg("xmin", xmin) || !xf.SetArg("xmax", xmax) || !xf.SetArg("sf", sf) || !xf.SetArg("oy", oy) || !xf.SetArg("color", color))
				//XF_THROW(XFERR_FAIL_SET_ARG);
			//
			//if(coef)
			//{
				//if(!xf.SetArg("coef", coef))
					//XF_THROW(XFERR_FAIL_SET_ARG);
			//}
			//
			//DWORD dwCntrl = 0;
			//int nErr;
			//if(xf.ExecuteLabTalk(NULL, NULL, NULL, 0, &nErr, dwCntrl) != 0)
				//XF_THROW(XFERR_SPLINE_INTERP_FAILED);
			//
			//break;
	//}
	
	//------ Folger 07/23/08 BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS
	_set_output_range_comments(oy, iy, method, coef);
	//------
	
}

//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 interp1xy_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return interp1xy_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	return false;
	

}

int interp1xy_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 interp1xy_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_interp1xy);	
		
	/*
	if(nGetNDialog >= XF_GETN_SIMPLE) // before dialog is open
	{
		XYRange xyTemp;
		if(xy_range_from_GetN_data_node(trGetN.iy, xyTemp))
			_check_reset_to_data_x_range(trGetN, xyTemp, true);
	}
	*/
	/// Cloud 07/23/07 GET_SMOOTH_FACTOR_AUTOMATICALLY
	TreeNode trsf = trGetN.sf;
	/// Max 3/19/08 REWRITE_AND_RENAME_GET_SMOOTH_FACTOR
	//if (1==octree_get_auto_support(&trsf))
	if (trsf.IsValid() && 1==octree_get_auto_support(&trsf))
	{
		//get_smooth_factor(trGetN);
		trsf.dVal = get_smooth_factor_for_bspline(trGetN.iy);
	/// END REWRITE_AND_RENAME_GET_SMOOTH_FACTOR
	}
	/// End GET_SMOOTH_FACTOR_AUTOMATICALLY
	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
	
	///------ Folger 03/13/09 QA80-13262 CONVERT_OBJECT_VARIABLE_OPTIOANL_TO_NEW_IN_XF_DIALOG
	if ( nGetNDialog > 0 )		/// open dialog
		check_convert_optional_outputs_to_new(trGetN);
	///------ End CONVERT_OBJECT_VARIABLE_OPTIOANL_TO_NEW_IN_XF_DIALOG
	
	///Cheney 2007-6-7 ADD_AN_ERR_CHECK_FUNC
	///Cheney 2007-6-14 PROCEED_WITH_DLG_SHOULD_IF_ERR
	//if(0 == nGetNDialog && (dwCntrl&LTXF_THEME_USED) )
	if(0 == nGetNDialog && (dwCntrl&LTXF_THEME_USED) && (dwCntrl&LTXF_FROM_GUI_MENU) )
	///end PROCEED_WITH_DLG_SHOULD_IF_ERR
	{
		int nSize = get_input_xyrange_data_size(trGetN.iy);
		if(_check_err_condition(trGetN, nSize) != CER_NO_ERROR)
			nRet = XFEVT_PROCEED_WITH_DLG;
		_set_coef_disable_if_linear(trGetN); ///Cheney 2007-8-15 FIX_SOME_BU_OF_INTERP
	}
	///end ADD_AN_ERR_CHECK_FUNC
	
	///Kyle 11/25/2008 QA80-12051 GET_XYRANGE_DATA_BASE_ON_RULES
	if(is_xf_startup(nGetNDialog, dwCntrl))
	{
		GraphLayer gl = Project.ActiveLayer();
		if(gl)
		{
			trGetN.apparent.Enable = true;
		}
		else
		{
			trGetN.apparent.nVal = 0;
			trGetN.apparent.Enable = false;
		}
	}
	///End GET_XYRANGE_DATA_BASE_ON_RULES
}
//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 interp1xy_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
	bOKEnable = _init_tree_show(trGetN);
	_update_coef_attrib(trGetN, STR_ATTRIB_DYNACONTROL_USE_CHECK, STR_ATTRIB_OLD_CHK);
	_set_coef_disable_if_linear(trGetN);
	
	//check input
	int nSize = get_input_xyrange_data_size(trGetN.iy);
	if(CER_NO_ERROR != _check_err_condition(trGetN, nSize, strErrMsg))
		bOKEnable = false;
	
	TreeNode trsf = trGetN.sf;
	if ((trGetN.method.nVal == INTERP_TYPE_BSPLINE) && trsf.IsValid() && (1==octree_get_auto_support(&trsf)))
	{
		trsf.dVal = get_smooth_factor_for_bspline(trGetN.iy);
	}		
	
	//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("Interp");
	}

	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_interp1xy_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

	///------ Folger 04/10/09 QA80-13262-P2 OPTIONAL_SHOWN_INSTEAD_OF_NEW_AFTER_RESET_THEME
    if ( !trNode )		/// assume coms from theme changed, ugly, needs improve...
    {
		check_convert_optional_outputs_to_new(trGetN);
		_update_method_show(trGetN);		///------ Folger 04/14/09 QA80-13260-P5 FAILS_TO_UPDATE_DYNACTRL_SHOWN_STATUS_AFTER_CHANGE_THEME
		///------ Folger 09/25/09 OLD_DYNAUSECHECK_STATUS_SHOULD_BE_RESET_WHEN_THEME_CHANGE
		trGetN.coef.RemoveAttribute(STR_ATTRIB_OLD_CHK);
		///------ End OLD_DYNAUSECHECK_STATUS_SHOULD_BE_RESET_WHEN_THEME_CHANGE
    }
    ///------ End OPTIONAL_SHOWN_INSTEAD_OF_NEW_AFTER_RESET_THEME
    
    ///------ Folger 04/14/09 QA80-12786-P3 PREVIEW_GETN_FAILS_TO_SHOW_DATA_TIME_FORMAT_AFTER_CHANGED
    PreviewGetNTreeChangesHelper		clHelper(trGetN);
    ///------ End PREVIEW_GETN_FAILS_TO_SHOW_DATA_TIME_FORMAT_AFTER_CHANGED
    
    bOKEnable = 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
	if(update_interp_number_points(trGetN.npts, trGetN.iy)) ///Sandy 2009-3-17 need update grid
		bUpdateGrid = true;
	
	if(trNode)
	{
		if(trNode.tagName == STR_NODE_METHOD)
			_update_method_show(trGetN);
		
		
		bool bChangeSF =  (trNode.tagName == "sf");
		if ( bChangeSF ||  (trNode.tagName == "method") ||  (trNode.tagName == "iy"))
		{
			TreeNode trsf = trGetN.sf;
			if ((trGetN.method.nVal == INTERP_TYPE_BSPLINE) && trsf.IsValid() && (1==octree_get_auto_support(&trsf)))
			{
				trsf.dVal = get_smooth_factor_for_bspline(trGetN.iy);
				bUpdateGrid = true;///Sandy 2009-3-17 need update grid
			}
			
			if (trNode.tagName =="iy")
			{
				s_bInit = false;
			}
		}
		
		if((trNode.tagName == "method") )
			_update_coef_enable(trGetN);
		
		if((trNode.tagName == "coef") )
		{
			_update_coef_attrib(trGetN, STR_ATTRIB_DYNACONTROL_USE_CHECK, STR_ATTRIB_OLD_CHK);
		}
	}
	
	//check input
	int nSize = get_input_xyrange_data_size(trGetN.iy);
	if(CER_NO_ERROR != _check_err_condition(trGetN, nSize, strErrMsg))
		bOKEnable = false;	
	

	if(!bOKEnable)
		dwUpdateGraph = UPDATE_GRAPH_INVALID; //nUpdateGraph = UPDATE_GRAPH_ERROR;
	else
		bUpdateGraph = bOKEnable;
	
	///------ Folger 04/14/09 QA80-12786-P3 PREVIEW_GETN_FAILS_TO_SHOW_DATA_TIME_FORMAT_AFTER_CHANGED
	if ( clHelper.IsGUINeedReset(trGetN) )
		dwUpdateGrid |= UPDATE_GRID_RESET;
	///------ End PREVIEW_GETN_FAILS_TO_SHOW_DATA_TIME_FORMAT_AFTER_CHANGED
}

// 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_interp1xy(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

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

