#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	win_rect,
	win_welch,
	win_tri,
	win_bartlett,
	win_hanning,
	win_hamming,
	win_blackman,
};
enum{
	factor_ee,
	factor_science,
};
enum{
	st_auto,
	st_oneside,
	st_twoside,
};
enum{
	norm_msa,
	norm_ssa,
	norm_tisa,
};
enum{
	pre_none,
	pre_ap,
	pre_pp,
	pre_amp,
	pre_img,
	pre_mag,
	pre_phase,
	pre_power,
	pre_real,
	pre_ri,
	pre_db,
	pre_ndb,
	pre_rms,
	pre_sqamp,
	pre_sqmag,
};
#include <getnbox.h> // temp solution
#include <fft_utils.h>
#include <event_utils.h> ///justin 10/30/2006 JUST_RECACULATE_WHEN_NECESSARY
#include <ReportTree.h> 
#include <o8dlg.h>
///////////////////////////////////////////////////
// Modification log
//
// CPY 9/21/06 added EMBEDGRAPH_KEEP_ASPECT_RATIO
//	CPY 10/20/06 BETTER_GRAPHS_IF_FEWE, I also change the template for ReportTree to Graphs from Graph
//		Graph.OTW is for showing graphs only and cells will resize, but Graphs.OTW will not resize the cells when window resize
// CPY 10/26/06 QA70-9063 DYNAMIC_ERR_MSG_IN_GETN_DIALOGS, show sample interval on init and data change
/// ML 11/9/2006 REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT
// CPY 11/21/06 GRAPH_NODE_USE_CHECKBOX_TO_ALLOW_NO_GRAPHS
// Justin 2006-06-11 ADD_ENUM_FOR_COMBO_LIST not add code mark for every change
///Jasmine 08/08/07 QA80-10193 APPLY_SYSTEM_THEME
///Jasmine 08/14/07 QA80-10207 REPORT_SHEET_CHECK_CONFLICT
/// Max 3/8/08 ONLY_RESET_PLOT_SHEET_NODE_WHEN_IT_IS_NOT_MANUALLY_MODIFIED
/// Max 4/7/08 v8.0838 MUST_CHECK_VALID_INPUT
/// Max 8/27/08 v8.0931b TEMP_COMMENT_SANDY_CHANGE_WHICH_WILL_POP_UP_DLG_ONCE_ERR_APPEAR
/// Fisher 2008/10/21 QA80-12436 CLEANUP_FFT_TOOL
/// Fisher 2008/10/21 QA80-12420 OUTPUT_HALF_DATASET_FOR_ONE_SIDE_SPECTRUM  		
/// Fisher 2/9/2009 FIX_INCORRECT_POWER_NORMALIZATION_FACTOR
/// Fisher 2/17/2009 FIX_INCORRECT_NORMALIZAION_AND_SIDED_RESULT
/// Fisher 2/17/2009	REMOVE_COMPENSATE_OPTION
/// Kyle 03/12/2009 SET_PREVIEW_GRAPH_NO_CLICK
/// Folger 04/14/09 QA80-13436 IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
/// Kenny 08/25/2009 QA81-14203 RESET_PAGE_NAME_IF_CREATED_FROM_OC
/// Jasmine 08/24/09 QA81-14165 DISPLAY_BUT_DISABLE_PRO_OPTION_IN_REG_VERSION
/// Iris 9/4/2009 QA80-14165 SCRIPT_MODE_NEED_THROW_ERROR_FOR_PRO_OPTION_IN_REGULAR_BUILD
/// Iris 2/02/2010 QA81-14165 ALSO_SHOW_PRO_IN_PRO_VERSION
///	Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
/// Jacky 08/27/10 ORG-920-P3 ONE_SAMPLE_TTEST_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
/// Folger 09/27/2010 ORG-1151-P1 SAVE_AS_ANALYSIS_TEMPLATE_FAILED_TO_CLEAN_GRAPHS_EMEBEDED_IN_WKS
///	Kit 10/26/2010 ORG-1227-P3 SUPPORT_OTHER_FFT_TOOL_SHOW_UNITS_ON_REPORT_TABLE
///////////////////////////////////////////////////


//#define STR_WARN_BAG_TIME_INTERVAL "Warning : Time sequences should be monotonic increase!"
//#define STR_ERR_SOURCE_DATA        "Error: Invalid input data!"

#define STR_PREVIEW_FOR_PRO        _L("None|Amplitude/Phase|Power/Phase|Amplitude|Imaginary|Magnitude|Phase|Power|Real|Real/Imaginary|dB|Normalized dB|RMS Amplitude|Square Amplitude|Square Magnitude")
#define STR_PREVIEW_FOR_REGULAR    _L("None|Amplitude/Phase|Power/Phase|Amplitude|Imaginary|Magnitude|Phase|Power|Real|Real/Imaginary")
/// Max 4/8/08 v8.0839 move to event_utils.h
//#define STR_DEFAULT_VALUE_FOR_PLOT_SHEET_NODE	"[<input>]<new template:=graph>"	/// Max 3/8/08 ONLY_RESET_PLOT_SHEET_NODE_WHEN_IT_IS_NOT_MANUALLY_MODIFIED

/// Justin 2006-06-11 ADD_ENUM_FOR_COMBO_LIST
//enum{
	//FFT_SPC_AUTO,
	//FFT_SPC_ONE_SIDE,
	//FFT_SPC_TWO_SIDE,
//};
///End ADD_ENUM_FOR_COMBO_LIST

/// ML 11/9/2006 REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT
//#define	_FFT_RDID_GRAPH	1 ///CPY, 8/25/06, this index of rt should be a small value, 
/// end REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT

///------ Folger 04/14/09 QA80-13436 IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
IMPLEMENT_SHOULD_WARNING_MSG_SHOW_IN_XF_BODY
IMPLEMENT_XF_GET_WARNING_MSG_ID
///------ End IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY


static bool _check_update_graph(TreeNode& trNode)
{
	if(trNode.IsValid() && (trNode.tagName == "AutoUpdate" ||trNode.tagName == "rd" || trNode.tagName == "rt" || trNode.tagName == "re" || trNode.tagName == "im" || trNode.tagName =="ap" || trNode.tagName == "phase" || trNode.tagName == "pp" || trNode.tagName == "ri" || trNode.tagName == "mag" || trNode.tagName == "amp" || trNode.tagName == "psd" || trNode.tagName == "db" || trNode.tagName == "ndb" || trNode.tagName == "rms" || trNode.tagName == "sqr_amp" || trNode.tagName == "sqr_mag") )
	{
		return false;
	}
	return true;
}
static bool _prepare_tree_for_preview(TreeNode& trGetN, Tree& trPre)
{
	if(trGetN ) //&& trPre)
	{
		trPre = trGetN;

		trPre.ap.nVal = 0;
		trPre.re.nVal = 0;
		trPre.im.nVal = 0;
		trPre.pp.nVal = 0;
		trPre.ri.nVal = 0;
		trPre.mag.nVal = 0;
		trPre.amp.nVal = 0;
		trPre.phase.nVal = 0;
		trPre.psd.nVal = 0;
		trPre.db.nVal = 0;
		trPre.ndb.nVal = 0;
		trPre.rms.nVal = 0;
		trPre.sqr_amp.nVal = 0;
		trPre.sqr_mag.nVal = 0; 
		
		switch( trPre.pre.nVal )
		{
		case pre_ap:
			trPre.ap.nVal = 1;
			return true;
		case pre_pp:
			trPre.pp.nVal = 1;
			return true;
		case pre_amp:
			trPre.amp.nVal = 1;
			return true;
		case pre_phase:
			trPre.phase.nVal = 1;
			return true;
		case pre_power:   
			trPre.psd.nVal = 1;
			return true;
		case pre_db:
			trPre.db.nVal = 1;
			return true;
		case pre_ri:
			trPre.ri.nVal = 1;
			return true;
		case pre_real:
			trPre.re.nVal = 1;
			return true;
		case pre_img:
			trPre.im.nVal = 1;
			return true;
		case pre_ndb:
			trPre.ndb.nVal = 1;
			return true;
		case pre_mag:
			trPre.mag.nVal = 1;
			return true;
		case pre_rms:
			trPre.rms.nVal = 1;
			return true;
		case pre_sqamp:
			trPre.sqr_amp.nVal = 1;
			return true;
		case pre_sqmag:
			trPre.sqr_mag.nVal = 1;
			return true;
		default:			
		}
		return true;
	}
	return false;
	
}

//---CPY 5/29/06 FFT_PLOT_OPTIONS
// nPlotType can be one of the followings
enum {
	//jutin 08/01/2006 MORE_OPTIONAL_PLOT
	//FFTPLOT_NONE, FFTPLOT_AMP, FFTPLOT_POWER
	FFTPLOT_NONE, 
	FFTPLOT_AMP_AND_PHASE, 
	FFTPLOT_POWER_AND_PHASE,	
	FFTPLOT_AMP, 
	FFTPLOT_IMAG, 
	FFTPLOT_MAG,
	FFTPLOT_PHASE, 
	FFTPLOT_POWER,
	FFTPLOT_REAL, 
	FFTPLOT_REAL_AND_IMAG,	
	FFTPLOT_DB,
	FFTPLOT_NORM_DB,
	FFTPLOT_RMS,
	FFTPLOT_SQR_AMP,
	FFTPLOT_SQR_MAG,
	//FFTPLOT_TISA,
	//FFTPLOT_MSA,
	//FFTPLOT_SSA,
	//FFTPLOT_VARIACNCE
	//end
};

/// ML 11/9/2006 REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT
#define	_FFT_RDID_GRAPH_PREVIEW		FFTPLOT_NONE 
/// end REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT


//---
static bool _prepare_plot_tree(Tree& trPlot, int re, int im, int ap, int pp, int ri, int mag, int  amp, int phase, int psd, int db, int ndb, int rms,  int sqr_amp, int sqr_mag)
{
	if(!trPlot ) 
		return false;
	trPlot.AddNumericNode(ap, "ap", FFTPLOT_AMP_AND_PHASE);
	trPlot.AddNumericNode(re, "re", FFTPLOT_REAL);
	trPlot.AddNumericNode(im, "im", FFTPLOT_IMAG);
	trPlot.AddNumericNode(pp, "pp", FFTPLOT_POWER_AND_PHASE);
	trPlot.AddNumericNode(ri, "ri", FFTPLOT_REAL_AND_IMAG);
	trPlot.AddNumericNode(mag, "mag", FFTPLOT_MAG);
	trPlot.AddNumericNode(amp, "amp", FFTPLOT_AMP);
	trPlot.AddNumericNode(phase, "phase", FFTPLOT_PHASE);
	trPlot.AddNumericNode(psd, "psd", FFTPLOT_POWER);
	trPlot.AddNumericNode(db, "db",   FFTPLOT_DB);
	trPlot.AddNumericNode(ndb, "ndb", FFTPLOT_NORM_DB );
	trPlot.AddNumericNode(rms, "rms", FFTPLOT_RMS);
	trPlot.AddNumericNode(sqr_amp, "sqr_amp", FFTPLOT_SQR_AMP);
	trPlot.AddNumericNode(sqr_mag, "sqr_mag", FFTPLOT_SQR_MAG);
	return true;
}
static void _plot_preview(int nPre, GraphPage& gpTemp,  ReportData& rd, int nRow1, int nRow2)
{
	if(gpTemp && gpTemp.IsValid())
	{
		string strTemplate;
		string strLab = "Preview";
		int nY1ID, nY2ID;
		_prpare_plot_info(nPre, strTemplate, nY1ID, nY2ID);
		//gpTemp.LoadTemplate(strTemplate);   //jusitn 11/13/2006 //temp solution
		page_load(gpTemp, strTemplate);	///Jasmine 08/08/07 QA80-10193 APPLY_SYSTEM_THEME
		_fft_rd_plotting(rd, gpTemp, strLab, strTemplate, nY1ID, nY2ID, nRow1, nRow2, nPre); //_fft_rd_plotting(rd, gpTemp, strLab, strTemplate, nY1ID, nY2ID, nRow1, nRow2); ///justin 11/20/2006
	}

}

//---- CPY 11/21/06 GRAPH_NODE_USE_CHECKBOX_TO_ALLOW_NO_GRAPHS
/*
static void _uadate_graph_sheet(TreeNode& trGetN, bool bChange = false)
{
	if(trGetN.re.nVal || trGetN.im.nVal || trGetN.ap.nVal || trGetN.pp.nVal || trGetN.ri.nVal || trGetN.mag.nVal || trGetN.amp.nVal || trGetN. phase.nVal || trGetN.psd.nVal || trGetN.db.nVal || trGetN.ndb.nVal || trGetN.rms.nVal || trGetN.sqr_amp.nVal || trGetN.sqr_mag.nVal)
	{
		trGetN.rt.Enable = true;
		return;
	}
	else 
	{
		trGetN.rt.Enable = false;
		if(bChange)
		{
			trGetN.rt.strVal = "<optional>";		
		}
	}
}
*/
static void _uadate_graph_node_from_LT_execution(TreeNode& trGetN)
{
	if(trGetN.re.nVal || trGetN.im.nVal || trGetN.ap.nVal || trGetN.pp.nVal || trGetN.ri.nVal || trGetN.mag.nVal || trGetN.amp.nVal || trGetN. phase.nVal || trGetN.psd.nVal || trGetN.db.nVal || trGetN.ndb.nVal || trGetN.rms.nVal || trGetN.sqr_amp.nVal || trGetN.sqr_mag.nVal)
	{
		//trGetN.rt.Enable = true;
		return;
	}
	else 
	{
		//trGetN.rt.Enable = false;
		//if(bUpdateGraphNodeValue)
		//{
		trGetN.rt.strVal = "<optional>";		
		//}
	}
}
//---- CPY 11/21/06 GRAPH_NODE_USE_CHECKBOX_TO_ALLOW_NO_GRAPHS
// return false when rt update is not needed
static bool _check_update_grid_nodes(TreeNode& trGetN, bool bChangedByGraph, LPCSTR lpcszNodeName)
{
	if(lstrcmp(lpcszNodeName, "rt")==0)
	{
		int nUseCheck = -1;
		if(trGetN.rt.GetAttribute(STR_ATTRIB_DYNACONTROL_USE_CHECK, nUseCheck))
			trGetN.re.Show = nUseCheck;
		return false;
	}
	// check others, will add
	// I think now we have the check box on the rt node, it is no longer needed to disable/enable from checkboxes on plot list
	//_uadate_graph_output(trGetN);
	return true;
}
//----

///---justin 08/14/2006 DISABLE_SOME_UTILITIES_IN_REGULAR_VERSION
///justin 10/24/2006 
//static bool _update_interface(TreeNode& trGetN)
/// Iris 9/4/2009 QA80-14165 SCRIPT_MODE_NEED_THROW_ERROR_FOR_PRO_OPTION_IN_REGULAR_BUILD
//static bool _disable_utilities_for_regular_version(TreeNode& trGetN)
static bool _disable_utilities_for_regular_version(TreeNode& trGetN, bool bInit, bool bScriptMode, string& strProOption)
///end SCRIPT_MODE_NEED_THROW_ERROR_FOR_PRO_OPTION_IN_REGULAR_BUILD
//end
{
	if(!trGetN) return false;
	
	/// Iris 2/02/2010 QA81-14165 ALSO_SHOW_PRO_IN_PRO_VERSION
	/*
	if( is_pro_version() )
		return true;
	*/
	///End ALSO_SHOW_PRO_IN_PRO_VERSION
	
	///Jasmine 08/24/09 QA81-14165 DISPLAY_BUT_DISABLE_PRO_OPTION_IN_REG_VERSION
	/*
	trGetN.norm.Show = false;
	trGetN.norm.nVal = 0;
	
	...similar cides are deleted for compaction
	*/
	
	strProOption.Empty();
	
	//vector<string> vsProOptions = {"norm", "st", "reserve", "db", "ndb", "rms", "sqr_amp", "sqr_mag"};
	vector<string> vsProOptions = {"norm", "reserve", "db", "ndb", "rms", "sqr_amp", "sqr_mag"};
	for(int ii = vsProOptions.GetSize()-1; ii >= 0; ii--)
	{
		TreeNode trNode = trGetN.GetNode( vsProOptions[ii] );
		if( !is_pro_version() ) /// Iris 2/02/2010 QA81-14165 ALSO_SHOW_PRO_IN_PRO_VERSION
		{
			/// Iris 9/4/2009 QA80-14165 SCRIPT_MODE_NEED_THROW_ERROR_FOR_PRO_OPTION_IN_REGULAR_BUILD
			if( 1 == trNode.nVal )
			{
				if( strProOption.IsEmpty() )
					trNode.GetAttribute(STR_LABEL_ATTRIB, strProOption);
				
				if( bScriptMode)
					return false;
			}
			///end SCRIPT_MODE_NEED_THROW_ERROR_FOR_PRO_OPTION_IN_REGULAR_BUILD
			trNode.Enable = false;
			trNode.nVal = 0;
		}
		
		if( bInit )
		{
			string  strLabel;
			trNode.GetAttribute(STR_LABEL_ATTRIB, strLabel);
			trNode.SetAttribute(STR_LABEL_ATTRIB, strLabel + " " + STR_PRO_POSTFIX);
		}
	}
	
	//trGetN.pre.SetAttribute("Combo", STR_PREVIEW_FOR_REGULAR); 
	if( bInit )
	{
		string strCombo;
		trGetN.pre.GetAttribute(STR_COMBO_ATTRIB, strCombo); 
		vector<string> vsPre;
		int nCount = strCombo.GetTokens(vsPre, '|');
		for(ii = FFTPLOT_DB; ii < nCount; ii++)
			vsPre[ii] = vsPre[ii] + " " + STR_PRO_POSTFIX;
		strCombo.SetTokens(vsPre, '|');
		trGetN.pre.SetAttribute(STR_COMBO_ATTRIB, strCombo); 
	}
	
	/// Iris 2/02/2010 QA81-14165 ALSO_SHOW_PRO_IN_PRO_VERSION
	//if( FFTPLOT_REAL_AND_IMAG < trGetN.pre.nVal )
	if( !is_pro_version() && FFTPLOT_REAL_AND_IMAG < trGetN.pre.nVal )
	///End ALSO_SHOW_PRO_IN_PRO_VERSION
	{
		if( strProOption.IsEmpty() )
			strProOption = get_selected_string_from_combolist(trGetN.pre);
		
		if( bScriptMode)
			return false;
			
		trGetN.pre.nVal = FFTPLOT_NONE;//trGetN.plot.nVal = FFTPLOT_NONE;
	}
	///End DISPLAY_BUT_DISABLE_PRO_OPTION_IN_REG_VERSION

	return true;

}
///end DISABLE_SOME_UTILITIES_IN_REGULAR_VERSION


//---- CPY 8/24/06 MOVE_FFT_GRAPH_TO_RESULT_SHEET 
static string _get_plot_name(int plot)
{
	string strCombo = STR_PREVIEW_FOR_PRO; //"None|Amplitude/Phase|Power/Phase|Amplitude|Amp in dB|Normalized Amp in dB|Imaginary|Magnitude|Phase|Power|Real|Real/Imaginary|RMS Amplitude|Square Amplitude|Square Magnitude";
	vector<string> vs;
	strCombo.GetTokens(vs, '|');
	if(plot < 0 || plot >= vs.GetSize())
		return "Invalid Plot";
	
	return vs[plot];
}
//----
//
static bool _prpare_plot_info(int plot, string& strTemplate, int& nY1ID, int& nY2ID)
{
	nY1ID = -1;  //-1 means no plot
	nY2ID = -1;  //-1 means no y2
	strTemplate = "FFTPlot1L1";

	switch( plot )
	{
	case FFTPLOT_AMP_AND_PHASE:
		strTemplate = "FFTPlot2L1";
		nY1ID = _FFT_RDID_AMP;
		nY2ID = _FFT_RDID_PHASE;
		break;
	case FFTPLOT_POWER_AND_PHASE:
		strTemplate = "FFTPlot2L3";
		nY1ID = _FFT_RDID_POWER;
		nY2ID = _FFT_RDID_PHASE;
		break;
	case FFTPLOT_REAL_AND_IMAG:
		strTemplate = "FFTPlot2L2";
		nY1ID = _FFT_RDID_REAL;
		nY2ID = _FFT_RDID_IMAG;
		//no need
		break;
	case FFTPLOT_REAL:
		nY1ID = _FFT_RDID_REAL;
		break;
	case FFTPLOT_IMAG:
		nY1ID = _FFT_RDID_IMAG;
		break;
	case FFTPLOT_AMP:
		nY1ID = _FFT_RDID_AMP;
		break;
	case FFTPLOT_PHASE:
		nY1ID = _FFT_RDID_PHASE;
		break;
	case FFTPLOT_POWER:   
		nY1ID = _FFT_RDID_POWER;
		strTemplate = "FFTPlot1L2";
		break;
	case FFTPLOT_DB:
		nY1ID = _FFT_RDID_DB;
		break;
	case FFTPLOT_NORM_DB:
		nY1ID = _FFT_RDID_NORM_DB;
		break;
	case FFTPLOT_MAG:
		nY1ID = _FFT_RDID_MAG;
		break;
	case FFTPLOT_RMS:
		nY1ID = _FFT_RDID_RMS;
		break;
	case FFTPLOT_SQR_AMP:
		nY1ID = _FFT_RDID_SQR_AMP;
		strTemplate = "FFTPlot1L2";
		break;
	case FFTPLOT_SQR_MAG:
		nY1ID = _FFT_RDID_SQR_MAG;
		strTemplate = "FFTPlot1L2";
		break;
	//case FFTPLOT_TISA:
		//nY1ID = _FFT_RDID_TISA;
		//strTemplate = "FFTPlot1L2";
		//break;
	//case FFTPLOT_MSA:
		//nY1ID = _FFT_RDID_MSA;
		//strTemplate = "FFTPlot1L2";
		//break;
	//case FFTPLOT_SSA:
		//nY1ID = _FFT_RDID_SSA;
		//strTemplate = "FFTPlot1L2";
		//break; 
	default:
		return false; // not supported
	}
	return true;
}

///end 
static void	_run_fft_on_current_data(TreeNode& trGetN, PageBase& pgTemp, Worksheet& wksTemp)
{
	//------ CPY 7/11/06 KEEP_AUTO_IN_GUI
	//TreeNode& trTemp = trGetN.ix;
	Tree trTemp;
	_prepare_tree_for_preview(trGetN, trTemp); //trTemp = trGetN;  ///jusitin 10/30/2006 JUST_RECACULATE_WHEN_NECESSARY
	//if(! _update_sampling_interval_from_InputData(trTemp))
	///justin 10/31/2006
	//if(auto_compute_sampling_interval_from_InputData(trTemp) == -1)
		//return; // may need err handling
	///justin 01/11/2007 APPLY_EDIT_BOX_WITH_AUTO_CHECKE_BOX
	//auto_compute_sampling_interval_from_InputData(trTemp.ix, trTemp.interval, false); //auto_compute_sampling_interval_from_InputData(trTemp.ix, trTemp.interval, true); //jusitn 11/21/2006
	//end APPLY_EDIT_BOX_WITH_AUTO_CHECKE_BOX
	//end
	//-------
	//justin 10/30/2006 JUST_RECACULATE_WHEN_NECESSARY
	/*
	vector<complex> vx;
	TreeNode trnInput = trTemp.ix;
	if(trnInput)
	{
		okxf_resolve_tree_get_data_into_vector(&trnInput, &vx);
		if(vx.GetSize()<=0)
		{
			return;
		}
	}
	*/
	//end JUST_RECACULATE_WHEN_NECESSARY
	Tree trReport;
	ReportData rdTemp(trReport);
	//rdTemp.SetWorksheet(wksTemp);
	/// ML 7/13/2006 FFT_REWORK_REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
	if(wksTemp)
		wksTemp.SetSize(-1, 0);  
	rdTemp.SetWorksheet(wksTemp);
	GraphPage	gp = pgTemp;
	//int			nGraphType = trTemp.plot.nVal; ///justin 08/02/2006 MORE_OPTIONAL_PLOT
	/// ML 7/17/2006 GETTING_INPUT_DATA_DESCRIPTION_FROM_WITHIN_XFUNCTION_EXECUTION
	//rdTemp.SetGraph(gp, nGraphType);
	//XFPushPopGetNTree	pushpopGetN(trGetN);
	XFPushPopGetNTree	pushpopGetN(trGetN);
	XFExeContext	*pxfexectxt = Project.GetCurrentXFExeCtxt();
	/// ML 11/9/2006 REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT
	//pxfexectxt->SetGraph(gp, _FFT_RDID_GRAPH); //pxfexectxt->SetGraph(gp, nGraphType); ///justin 08/02/2006 MORE_OPTIONAL_PLOT
	pxfexectxt->SetGraph(gp, _FFT_RDID_GRAPH_PREVIEW);
	/// end REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT
	/// end GETTING_INPUT_DATA_DESCRIPTION_FROM_WITHIN_XFUNCTION_EXECUTION
	/// end FFT_REWORK_REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
    
	//justin 10/30/2006 JUST_RECACULATE_WHEN_NECESSARY
	vector<complex> vx;
	
	//if(check_input_complex_vector(trTemp.ix, 1, false, vx) || trTemp.pre.nVal == FFTPLOT_NONE) ///justin 
	if(check_input_complex_vector(trTemp.ix, 1, false, vx) || trTemp.pre.nVal == pre_none || check_interval(trTemp.interval)) 
	{
		if(pgTemp)
		{
			page_load(gp, "NonePreview");  //page_load(gp, "FFTPlot1L1");  ///justin 
			load_text_for_nonepreview_graphpage(gp, TEMPLATE_NONE_PREVIEW_CONTENT, TEMPLATE_NONE_PREVIEW_HINTS);
		}
		return;			
	}
	//end JUST_RECACULATE_WHEN_NECESSARY
	try {
		///justin 08/07/2006 OUTPUT_DATA_ACCORDING_TO_PLOT
		/////justin 07/31/2006 MORE_OPTIONAL_OUTPUT
		////fft(vx, trTemp.interval.dVal, trTemp.plot.nVal, trTemp.win.nVal, trTemp.norm_amp.nVal,
			////trTemp.shift.nVal, trTemp.unwrap_phase.nVal, trTemp.factor.nVal, rdTemp);
		//fft(vx, trTemp.interval.dVal, trTemp.win.nVal, trTemp.shift.nVal, trTemp.unwrap_phase.nVal,  trTemp.factor.nVal, 
			 //trTemp.amplitude.nVal, trTemp.phase.nVal, 
			 //trTemp.power.nVal, trTemp.db.nVal, trTemp.norm_db.nVal, trTemp.magnitude.nVal, trTemp.rms_amp.nVal,
			//trTemp.sqr_amp.nVal,  trTemp.sqr_mag.nVal, trTemp.tisa.nVal, trTemp.msa.nVal, trTemp.ssa.nVal, 
			//trTemp.plot.nVal, rdTemp);
		/////end MORE_OPTIONAL_OUTPUT
		///justin 10/13/2006 OUTPUT_MULTI_PLOT
		/*
		fft(vx, trTemp.interval.dVal, trTemp.win.nVal, trTemp.shift.nVal, trTemp.unwrap.nVal, trTemp.factor.nVal, 
			trTemp.st.nVal, trTemp.norm.nVal, trTemp.plot.nVal, trTemp.mag.nVal,
			trTemp.amp.nVal, trTemp.phase.nVal, trTemp.psd.nVal, trTemp.db.nVal, trTemp.ndb.nVal,  
			trTemp.rms.nVal, trTemp.sqr_amp.nVal, trTemp.sqr_mag.nVal, rdTemp, NULL);
		*/
		fft1(vx, trTemp.interval.dVal, trTemp.win.nVal, trTemp.reserve.nVal, trTemp.norma.nVal, trTemp.shift.nVal, trTemp.unwrap.nVal, trTemp.factor.nVal, 
			trTemp.st.nVal, trTemp.norm.nVal, trTemp.pre.nVal, trTemp.re.nVal, trTemp.im.nVal, trTemp.ap.nVal, trTemp.phase.nVal,
			trTemp.pp.nVal, trTemp.ri.nVal, trTemp.mag.nVal, trTemp.amp.nVal,  trTemp.psd.nVal, trTemp.db.nVal, trTemp.ndb.nVal,  
			trTemp.rms.nVal, trTemp.sqr_amp.nVal, trTemp.sqr_mag.nVal, rdTemp, NULL);
		//end OUTPUT_MULTI_PLOT
		///end OUTPUT_DATA_ACCORDING_TO_PLOT
	}
	catch(int nErr)
	{
		/// ML 7/17/2006 GETTING_INPUT_DATA_DESCRIPTION_FROM_WITHIN_XFUNCTION_EXECUTION
		//return;
		;
		/// end GETTING_INPUT_DATA_DESCRIPTION_FROM_WITHIN_XFUNCTION_EXECUTION
	}
	// no err, generate results data
	/// ML 7/13/2006 FFT_REWORK_REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
	//rdTemp.GenerateReport(wksTemp, false, true);	
	/// end FFT_REWORK_REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
	/// ML 7/17/2006 GETTING_INPUT_DATA_DESCRIPTION_FROM_WITHIN_XFUNCTION_EXECUTION
	//worksheet pgTmp = wksTemp.Clone(); //test
	return;
	/// end GETTING_INPUT_DATA_DESCRIPTION_FROM_WITHIN_XFUNCTION_EXECUTION
}

/// ML 7/13/2006 FFT_REWORK_REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
enum _FFT_RDID {
	_FFT_RDID_TABLE		= 100,
	_FFT_RDID_FREQ		= IDST_FIT_X, 
	
	_FFT_RDID_REAL		= IDST_FIT_Y, 
	_FFT_RDID_IMAG, 
	_FFT_RDID_AMP, 
	_FFT_RDID_PHASE, 
	_FFT_RDID_POWER, 
	///justin 07/31/2006 MORE_OPTIONAL_OUTPUT
	_FFT_RDID_DB,
	_FFT_RDID_NORM_DB,
	_FFT_RDID_MAG, 
	_FFT_RDID_RMS,
	_FFT_RDID_SQR_AMP,
	_FFT_RDID_SQR_MAG,
	_FFT_RDID_COMPLEX,   //Justin 10/23/2006	
	//_FFT_RDID_TISA,
	//_FFT_RDID_MSA,
	//_FFT_RDID_SSA,
	//_FFT_RDID_VARIACNCE,
	///end MORE_OPTIONAL_OUTPUT
};
///justin 10/16/2006 OUTPUT_MULTI_PLOT
/*
static void _calculate_result(ReportTable& rtFFT, int nY1ID, int nY2ID, 
	const vector& vFreq, double interval, const vector<complex>& vOut, int shift, int unwrap, int st, int norm,	
	int amp, int phase, int power, int db, int ndb, int mag, int rms, int sqr_amp, int sqr_mag) //, int tisa, int msa, int ssa) 
{
	vector vReal, vImag, vPhase, vAmp, vTemp,vSqrAmp;
	int nSize = vOut.GetSize();
	
	vOut.GetReal(vReal);
	vOut.GetImaginary(vImag);
	vOut.GetAmplitude(vAmp);
	vOut.GetPhase(vPhase);
	
	vector vAmp2;
	vAmp2 = vAmp / nSize;   
	vSqrAmp = vAmp * vAmp /nSize;
	if (1 == st)
	{
		//vSqrAmp *=2;
		//vSqrAmp[ shift? (nSize-1)/2 : 0 ] /= 2;   //DC component
		int nS = nSize + ( shift? ( nSize%2 -2) : 0 );
		for(int ii = (shift?0:1); ii < (nSize-1)/2 + (shift?0:1); ii++ )
		{
			vSqrAmp[nS-ii] = vSqrAmp [ii] = vSqrAmp[ii] + vSqrAmp [nS-ii];
			vAmp2[nS-ii] = vAmp2[ii] = vAmp2[ii] + vAmp2[nS-ii]; 
		}
	}
	
	double dPsdFactor = ((2==norm)?interval:1.0 ) * ( (0 == norm)? 1.0/nSize : 1.0 ); 
	string strPsd = (norm == 0)? "MSA" :((norm == 1)? "SSA": "TISA");
	
	vPhase *= 180.0/PI;
	if(unwrap)
	{
		fft_unwrap_phase(vPhase);
	}
	
	rtFFT.AddColumn(vFreq, "Freq", _FFT_RDID_FREQ, "Frequency", OKDATAOBJ_DESIGNATION_X);
	rtFFT.AddColumn(vReal, "Real", _FFT_RDID_REAL, "Real");
	rtFFT.AddColumn(vImag, "Imag", _FFT_RDID_IMAG, "Imaginary");

	if(mag || _FFT_RDID_MAG == nY1ID ||   _FFT_RDID_MAG == nY2ID )
	{
		rtFFT.AddColumn(vAmp, "Mag", _FFT_RDID_MAG, "Magnitude");
	}
	if(amp || _FFT_RDID_AMP == nY1ID ||   _FFT_RDID_AMP == nY2ID )
	{
		rtFFT.AddColumn(vAmp2, "Amp", _FFT_RDID_AMP, "Amplitude"); 
	}
	if(phase || _FFT_RDID_PHASE == nY1ID ||   _FFT_RDID_PHASE == nY2ID )
	{
		rtFFT.AddColumn(vPhase, "Phase", _FFT_RDID_PHASE, "Phase"); 
	}
	if(power || _FFT_RDID_POWER == nY1ID ||   _FFT_RDID_POWER == nY2ID )
	{
		vTemp = vSqrAmp * dPsdFactor;
		rtFFT.AddColumn(vTemp, "Power", _FFT_RDID_POWER, "Power as " + strPsd); 
	}
	if(db || _FFT_RDID_DB == nY1ID ||   _FFT_RDID_DB == nY2ID )
	{
		vTemp = 20*log10( vAmp2/1.0 ); //vTemp = 20*log10( vAmp/nSize/1.0 );  // reference = 1.0 
		rtFFT.AddColumn(vTemp, "dB", _FFT_RDID_DB, "dB in amplitude"); 
	}
	if(ndb || _FFT_RDID_NORM_DB == nY1ID ||   _FFT_RDID_NORM_DB == nY2ID )
	{
		vTemp = 20*log10( vAmp2 );
		vTemp -= max(vTemp);
		rtFFT.AddColumn(vTemp, "NormdB", _FFT_RDID_NORM_DB, "dB Normalized");
	}
	if(rms || _FFT_RDID_RMS == nY1ID ||   _FFT_RDID_RMS == nY2ID )
	{
		rtFFT.AddColumn(vAmp/( sqrt(2.0) * nSize), "RMS", _FFT_RDID_RMS, "RMS Amplitude"); 
	}
	if(sqr_amp || _FFT_RDID_SQR_AMP == nY1ID ||   _FFT_RDID_SQR_AMP == nY2ID )
	{
		vTemp = vAmp2^2;
		rtFFT.AddColumn(vTemp, "SqrAmp", _FFT_RDID_SQR_AMP, "Square Amplitude"); 
	}
	if(sqr_mag || _FFT_RDID_SQR_MAG == nY1ID ||   _FFT_RDID_SQR_MAG == nY2ID )
	{
		rtFFT.AddColumn(vAmp*vAmp, "SqrMag", _FFT_RDID_SQR_MAG, "Square Magnitude"); 
	}
	//if(tisa || _FFT_RDID_TISA == nY1ID ||   _FFT_RDID_TISA == nY2ID )
	//{
		//vTemp = interval * vAmp * vAmp / ( 2.0 * nSize);
		//rtFFT.AddColumn(vTemp, "TISA", _FFT_RDID_TISA, "TISA"); 
	//}
	//if(msa || _FFT_RDID_MSA == nY1ID ||   _FFT_RDID_MSA == nY2ID )
	//{
		//vTemp = vAmp*vAmp/(2.0 * nSize * nSize);
		//rtFFT.AddColumn(vTemp, "MSA", _FFT_RDID_MSA, "MSA"); 
	//}
	//if(ssa || _FFT_RDID_SSA == nY1ID ||   _FFT_RDID_SSA == nY2ID )
	//{
		//vTemp = vAmp * vAmp / (2.0 * nSize);
		//rtFFT.AddColumn(vTemp, "SSA", _FFT_RDID_SSA, "SSA");
	//}
}
*/

#define CUTOFF(_n_)	((_n_)/2+1)

static void _calculate_result(ReportTable& rtFFT, 
	const vector& vFreq, double interval, vector<complex>& vOut, int shift, int unwrap, int st, int norm,	
	int real, int imag,
	int amp, int phase, int power, int db, int ndb, int ri, int mag, int rms, int sqr_amp, int sqr_mag, const int nWin, int norma) //, int tisa, int msa, int ssa) 
{
	/// Fisher 2008/10/21 QA80-12436 CLEANUP_FFT_TOOL
	// Avoid redundant calaulation if some option uncheck
	/*
	//vector vReal, vImag, vPhase, vAmp, vTemp,vSqrAmp;	

	vOut.GetReal(vReal);
	vOut.GetImaginary(vImag);
	vOut.GetAmplitude(vAmp);
	vOut.GetPhase(vPhase);
	*/
	/// End CLEANUP_FFT_TOOL
	
	/// Fisher 2008/10/21 QA80-12420 OUTPUT_HALF_DATASET_FOR_ONE_SIDE_SPECTRUM  	
	/*
	///jusitn 11/20/2006 IMPROVE_SPEED
	//vector vAmp2;
	//double dTmp = 1.0 / nSize;
	//vAmp2 = vAmp / nSize;   
	//vSqrAmp = vAmp * vAmp /nSize;
	//if (1 == st)
	//{
		////vSqrAmp *=2;
		////vSqrAmp[ shift? (nSize-1)/2 : 0 ] /= 2;   //DC component
		//int nS = nSize + ( shift? ( nSize%2 -2) : 0 );
		//for(int ii = (shift?0:1); ii < (nSize-1)/2 + (shift?0:1); ii++ )
		//{
			//vSqrAmp[nS-ii] = vSqrAmp [ii] = vSqrAmp[ii] + vSqrAmp [nS-ii];
			//vAmp2[nS-ii] = vAmp2[ii] = vAmp2[ii] + vAmp2[nS-ii]; 
		//}
	//}
	
	vector vAmp2;
	double dTmp = 1.0 / nSize;
	vAmp2 = vAmp * dTmp ;   
	vSqrAmp = vAmp * vAmp2 ;
	if (st_oneside == st)
	{
		fft_one_side_spectrum(vAmp2.GetSize(), vAmp2, shift);
		fft_one_side_spectrum(vSqrAmp.GetSize(), vSqrAmp, shift);
	}	
	///END IMPROVE_SPEED
	*/
	vector<complex> vFFT;
	vector vAmp, vAmp2, vTemp;
	int nSize = vOut.GetSize();	
	BOOL	bOneSided = st_oneside == st;
	
	vFFT = vOut;

	int nSizeOriginal = nSize;		
	if(bOneSided)
	{
		nSize = CUTOFF(nSizeOriginal);
		if(0 == shift)
		{
			vFreq.SetSize(nSize);
			vOut.SetSize(nSize);
		}
		else if ( nSizeOriginal > nSize ) //if nSizeOriginal <= nSize, may cause runtime error when call RemoveAt.
		{
			vFreq.RemoveAt(0, nSizeOriginal-nSize);
			vOut.RemoveAt(0, nSizeOriginal-nSize);
		}
	}


	vOut.GetAmplitude(vAmp2);
	vAmp2 *= (2.0/nSizeOriginal);
	
	/// Fisher 11/4/08 FIX_INCORRECT_DC_AMPLITUDE_FACTOR
	if(bOneSided)
	{
		vAmp2[0] *= 0.5;
		vAmp2[nSize-1] *= 0.5;
	}
	else
	{
		vAmp2 *= 0.5;
	}
	/// End FIX_INCORRECT_DC_AMPLITUDE_FACTOR	
	
	/// End OUTPUT_HALF_DATASET_FOR_ONE_SIDE_SPECTRUM

	
	/// Fisher 2/17/2009 FIX_INCORRECT_NORMALIZAION_AND_SIDED_RESULT
	/// http://wiki.originlab.com/~originla/wiki2/index.php?title=X-Function:Fft1
	if(norma)
	{
		vOut *= (double)(1.0/nSizeOriginal);
	}
	vOut.GetAmplitude(vAmp);	
	/// End FIX_INCORRECT_NORMALIZAION_AND_SIDED_RESULT	

	
	/// Fisher 2008/10/21 QA80-12436 CLEANUP_FFT_TOOL
	// Avoid redundant calaulation if some option uncheck	
	/*	
	double dPsdFactor = ((2==norm)?interval:1.0 ) * ( (0 == norm)? 1.0/nSize : 1.0 ); 
	string strPsd = (norm == 0)? "MSA" :((norm == 1)? "SSA": "TISA");

	vPhase *= 180.0/PI;
	if(unwrap)
	{
		fft_unwrap_phase(vPhase);
	}
	*/
	/// End CLEANUP_FFT_TOOL
	
	rtFFT.AddColumn(vFreq, "Freq", _FFT_RDID_FREQ, _L("Frequency"), OKDATAOBJ_DESIGNATION_X);
	if(ri)
	{
		rtFFT.AddColumn(vOut, "FFT", _FFT_RDID_COMPLEX, _L("Complex")); 
	}
	if(real)
	{
		/// Fisher 2008/10/21 QA80-12436 CLEANUP_FFT_TOOL
		// Avoid redundant calaulation if real uncheck			
		vector vReal;
		vOut.GetReal(vReal);
		/// End CLEANUP_FFT_TOOL

		rtFFT.AddColumn(vReal, "Real", _FFT_RDID_REAL, _L("Real"));
	}
	if(imag)
	{
		/// Fisher 2008/10/21 QA80-12436 CLEANUP_FFT_TOOL
		// Avoid redundant calaulation if imag uncheck		
		vector vImag;
		vOut.GetImaginary(vImag);
		/// End CLEANUP_FFT_TOOL

		rtFFT.AddColumn(vImag, "Imag", _FFT_RDID_IMAG, _L("Imaginary"));
	}
	if(mag)
	{
		rtFFT.AddColumn(vAmp, "Mag", _FFT_RDID_MAG, _L("Magnitude"));
	}
	if(amp)
	{
		rtFFT.AddColumn(vAmp2, "Amp", _FFT_RDID_AMP, _L("Amplitude")); 
	}
	if(phase )
	{
		/// Fisher 2008/10/21 QA80-12436 CLEANUP_FFT_TOOL
		// Avoid redundant calaulation if phase uncheck
		vector vPhase;
		vOut.GetPhase(vPhase);
		vPhase *= 180.0/PI;
		if(unwrap)
		{
			fft_unwrap_phase(vPhase);
		}
		/// End CLEANUP_FFT_TOOL
		
		rtFFT.AddColumn(vPhase, "Phase", _FFT_RDID_PHASE, _L("Phase")); 
	}
	if(power)
	{
		/// Fisher 2008/10/21 QA80-12436 CLEANUP_FFT_TOOL
		double dPsdFactor = ((2==norm)?interval:1.0 ) * ( (0 == norm)? 1.0/nSizeOriginal : 1.0 ); 
		string strPsd = (norm == 0)? "MSA" :((norm == 1)? "SSA": "TISA");
		/// End CLEANUP_FFT_TOOL
		
		/// Fisher 2008/10/30 QA80-12420 OUTPUT_HALF_DATASET_FOR_ONE_SIDE_SPECTRUM  
		/*
		vector vWin, vTmp;

		get_window_data(nWin, nSize, vWin, 0, 0);

		vector	vSqrAmp;
		vSqrAmp = vAmp2^2;
		
		/// Fisher 2008/10/21 QA80-12436 CLEANUP_FFT_TOOL
		// Since C language evaluate the expression from left to right
		// old codes will have 2 vector *, so we should group scaler math together
		// so that we will have just one vector multiplication.	
		//vTemp = vSqrAmp * dPsdFactor * (nSize/dTmp);

		/// End CLEANUP_FFT_TOOL
		*/
		vector vTmp, vPsd, vWin;
		double dTmp;
		get_window_data(nWin, nSizeOriginal, vWin, 0, 0);
		vTmp = vWin*vWin;
		vTmp.Sum(dTmp);
		vFFT.GetAmplitude(vTmp);
		/// Fisher 2/9/2009 FIX_INCORRECT_POWER_NORMALIZATION_FACTOR
		//vPsd = (vTmp*vTmp) * (dPsdFactor / (nSizeOriginal*dTmp));
		//
		// The problem was that power after the change CLEANUP_FFT_TOOL or OUTPUT_HALF_DATASET_FOR_ONE_SIDE_SPECTRUM above
		// got divided by the number of points, which made it different from SR4 (much smaller).
		// So, this restores SR$ behavior as far as the scaling with the number of points is concerned.
		vPsd = (vTmp*vTmp) * (dPsdFactor / dTmp);
		/// End FIX_INCORRECT_POWER_NORMALIZATION_FACTOR
		
		if(bOneSided)
		{
			fft_one_side_spectrum(vPsd.GetSize(), vPsd, shift);
			if(0 == shift)
				vPsd.SetSize(nSize);
			else if ( nSizeOriginal > nSize )
				vPsd.RemoveAt(0, nSizeOriginal-nSize);
			vPsd[nSize-1] *= 2;// correct the last element			
		}
		/// End OUTPUT_HALF_DATASET_FOR_ONE_SIDE_SPECTRUM  		
		
		if(power)
			rtFFT.AddColumn(vPsd, "Power", _FFT_RDID_POWER, _L("Power as") + " " + strPsd);  
	}
	if(db)
	{
		vTemp = 20*log10( vAmp2/1.0 ); //vTemp = 20*log10( vAmp/nSize/1.0 );  // reference = 1.0 
		rtFFT.AddColumn(vTemp, "dB", _FFT_RDID_DB, "dB"); 
	}
	if(ndb)
	{
		vTemp = 20*log10( vAmp2 );
		vTemp -= max(vTemp);
		rtFFT.AddColumn(vTemp, "NormdB", _FFT_RDID_NORM_DB, _L("Normalized Amp in dB"));
	}
	if(rms )
	{
		/// Fisher 2008/10/30 QA80-12420 OUTPUT_HALF_DATASET_FOR_ONE_SIDE_SPECTRUM  	
		//rtFFT.AddColumn(vAmp/( sqrt(2.0) * nSize), "RMS", _FFT_RDID_RMS, _L("RMS Amplitude")); 
		rtFFT.AddColumn(vAmp2 * (1/sqrt(2.0)), "RMS", _FFT_RDID_RMS, _L("RMS Amplitude")); 
		/// End OUTPUT_HALF_DATASET_FOR_ONE_SIDE_SPECTRUM  	
	}
	if(sqr_amp)
	{
		vTemp = vAmp2^2;
		rtFFT.AddColumn(vTemp, "SqrAmp", _FFT_RDID_SQR_AMP, _L("Square Amplitude")); 
	}
	if(sqr_mag)
	{
		rtFFT.AddColumn(vAmp*vAmp, "SqrMag", _FFT_RDID_SQR_MAG, _L("Square Magnitude")); 	
	}
	
}
//end OUTPUT_MULTI_PLOT

//---- CPY 8/24/06 MOVE_FFT_GRAPH_TO_RESULT_SHEET
// I changed _fft_rd_plotting to pass in gpFFT
//static BOOL _fft_rd_plotting(ReportData& rd, const string& strTemplate, int nYID1stLayer, int nYID2ndLayer, bool bFreqFrom0) //static BOOL _fft_rd_plotting(ReportData &rd, int nGraphType, bool bFreqFrom0) //justin 08/07/2006 
///justin 11/20/2006 SET_NAME_FOR_GRAPH
//static BOOL _fft_rd_plotting(ReportData& rd, GraphPage& gpFFT, const string& strLabel, const string& strTemplate, int nYID1stLayer, int nYID2ndLayer, int nR1, int nR2) //test
static BOOL _fft_rd_plotting(ReportData& rd, GraphPage& gpFFT, const string& strLabel, const string& strTemplate, int nYID1stLayer, int nYID2ndLayer, int nR1, int nR2, string strPlotName) //test
///END SET_NAME_FOR_GRAPH
{
	XFExeContext	*pxfexectxt = Project.GetCurrentXFExeCtxt();
	//prepare graphpage
	if( -1 == nYID1stLayer)  // none plot
	{
		if(gpFFT)
			page_load(gpFFT, strTemplate);  
		return true;
	}
	
	if ( !gpFFT )
	{
		/// Kenny 08/25/2009 QA81-14203 RESET_PAGE_NAME_IF_CREATED_FROM_OC
		//gpFFT.Create(strTemplate, CREATE_HIDDEN); //---- CPY 8/24/06 MOVE_FFT_GRAPH_TO_RESULT_SHEET, change to create as hidden
		gpFFT.Create(strTemplate, CREATE_HIDDEN | CREATE_ENUM_EXIST_PAGE); //---- CPY 8/24/06 MOVE_FFT_GRAPH_TO_RESULT_SHEET, change to create as hidden
		/// End QA81-14203 RESET_PAGE_NAME_IF_CREATED_FROM_OC
		
		//string			strInputDesc;
		if(!strLabel.IsEmpty())
		{
			gpFFT.SetLongName("FFT" + " " + strPlotName); //gpFFT.SetLongName("FFT of "+strInputDesc, false); ///justin 11/20/2006
			//gpFFT.SetName(strShortName);
			gpFFT.TitleShow = WIN_TITLE_SHOW_BOTH;
		}		
	}
	///justin 11/13/2006   REPLOT_ALWAYS_WHEN_RERUNNIN 
	//temp solution
	//assume that a valid graphpage has a correct template
	
	//else if ( pxfexectxt->IsAddPlots() )
	//{
		//page_load(gpFFT, strTemplate);
	//}
	//else
	//{
		//gpFFT.Refresh(TRUE);		// just refresh
		//return TRUE;
	//}
	///end 
	
	//plot
	DataRange		drPlot;
	GraphLayer		gl;	
	if(-1 != nYID2ndLayer )  
	{
		gl = gpFFT.Layers(1);
		
		///justin 11/13/2006 UPDATE_PLOT  //tempsolution		
		for(int ii = gl.DataPlots.Count(); ii > 0; ii--)
			gl.RemovePlot(0);
		///end  UPDATE_PLOT
		
		if(!gl)
			return error_report("_fft_graph found invalid template, 2nd layer is missing!");
		if (1 != rd.GetDataRange(drPlot, _FFT_RDID_TABLE, _FFT_RDID_FREQ, &nYID2ndLayer) )
			return error_report("_fft_graph found invalid worksheet!");

		Worksheet wksTemp;
		int r1, c1, r2, c2;
		drPlot.GetRange(0, r1, c1, r2, c2, wksTemp);	
		drPlot.SetRange(0, wksTemp, nR1, c1, nR2, c2);
		drPlot.GetRange(1, r1, c1, r2, c2, wksTemp);	
		drPlot.SetRange(1, wksTemp, nR1, c1, nR2, c2);
		
		///------ Folger 09/27/2010 ORG-1151-P1 SAVE_AS_ANALYSIS_TEMPLATE_FAILED_TO_CLEAN_GRAPHS_EMEBEDED_IN_WKS
		check_make_full_row_range(drPlot);
		///------ End SAVE_AS_ANALYSIS_TEMPLATE_FAILED_TO_CLEAN_GRAPHS_EMEBEDED_IN_WKS
		if ( 0 != gl.AddPlot(drPlot, IDM_PLOT_LINE) )
			return error_report("_fft_graph failed to create plot!");
		gl.Rescale();
		//gl.LT_execute("label -y Phase (degree);");
	}
	
	// Thr first layer:
	gl = gpFFT.Layers(0);
	
	///justin 11/13/2006 UPDATE_PLOT 
	for(int ii = gl.DataPlots.Count(); ii > 0; ii--)
		gl.RemovePlot(0);
	///end  UPDATE_PLOT
	
	if (1 != rd.GetDataRange(drPlot, _FFT_RDID_TABLE, _FFT_RDID_FREQ, &nYID1stLayer) )
		return error_report("_fft_graph found invalid worksheet!");

	Worksheet wksTemp;
	int r1, c1, r2, c2;
	drPlot.GetRange(0, r1, c1, r2, c2, wksTemp);	
	drPlot.SetRange(0, wksTemp, nR1, c1, nR2, c2);
	drPlot.GetRange(1, r1, c1, r2, c2, wksTemp);	
	drPlot.SetRange(1, wksTemp, nR1, c1, nR2, c2);
	///------ Folger 09/27/2010 ORG-1151-P1 SAVE_AS_ANALYSIS_TEMPLATE_FAILED_TO_CLEAN_GRAPHS_EMEBEDED_IN_WKS
	check_make_full_row_range(drPlot);
	///------ End SAVE_AS_ANALYSIS_TEMPLATE_FAILED_TO_CLEAN_GRAPHS_EMEBEDED_IN_WKS
	if ( 0 != gl.AddPlot(drPlot, IDM_PLOT_LINE) )
		return error_report("_fft_graph failed to create plot!");
	gl.Rescale();
	
	//if( bFreqFrom0 )
		//gl.LT_execute("x1=0");// to show freq only the positive part
	//---- CPY 8/24/06 MOVE_FFT_GRAPH_TO_RESULT_SHEET
	//pxfexectxt->SetGraph(gpFFT, _FFT_RDID_GRAPH); ///justin 10/30/2006 JUST_RECACULATE_WHEN_NECESSARY 
	//---
	return true;
}
	//end MORE_OPTIONAL_PLOT
	
	/// end FFT_REWORK_REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
/*	
	///---justin 08/07/2006 OUTPUT_DATA_ACCORDING_TO_PLOT
	/////justin 07/31/2006 MORE_OPTIONAL_OUTPUT
	////static void _update_result_data(ReportData& outData, vector& vFreq, vector& vReal, vector& vImag, vector& vAmp, vector& vPhase, vector& vPower)
	//static void _update_result_data(ReportData& outData, vector& vFreq, vector& vReal, vector& vImag, TreeNode trOtherOut)
	/////end MORE_OPTIONAL_OUTPUT
static ReportTable _prepare_table(ReportData& outData)
{
	int nIndex = 1;
	
	ReportTable rtFFT;
	string strTableName;
	strTableName.Format("FFT%d", nIndex);
	
	rtFFT = outData.CreateTable(strTableName, "FFT Results", _FFT_RDID_TABLE);
	outData.ID = IDST_RESULT_CURVES;

	return rtFFT;
}
*/

///Sandy 2007-10-15 add checking if no plot, no graph sheet output
static bool _check_if_need_plots_in_result_sheet(TreeNode trGetN)
{
	if(trGetN.re.nVal == 0 
		&& trGetN.im.nVal == 0 
		&& trGetN.ap.nVal == 0 
		&& trGetN.phase.nVal == 0
		&& trGetN.pp.nVal == 0 
		&& trGetN.ri.nVal == 0 
		&& trGetN.mag.nVal == 0 
		&& trGetN.amp.nVal == 0 
		&& trGetN.psd.nVal == 0 
		&& trGetN.db.nVal == 0 
		&& trGetN.ndb.nVal == 0 
		&& trGetN.rms.nVal == 0 
		&& trGetN.sqr_amp.nVal == 0 
		&& trGetN.sqr_mag.nVal == 0)
	/// Max 3/8/08 ONLY_RESET_PLOT_SHEET_NODE_WHEN_IT_IS_NOT_MANUALLY_MODIFIED
	/*	
	{
		trGetN.rt.Enable = false;
		//trGetN.rt.strVal = "<optional>";
		trGetN.rt.strVal = STR_OPTIONAL;
		return false;
	}
	else
	{
		trGetN.rt.Enable = true;
		//trGetN.rt.strVal = "[<input>]<new template:=graph>";	/// Max 12/5/07 should not set value in code
		return true;
	}
	*/
		return false;
	else
		return true;
	/// END ONLY_RESET_PLOT_SHEET_NODE_WHEN_IT_IS_NOT_MANUALLY_MODIFIED
} 

///-----Kit 10/26/2010 REFACTOR_THE_CODE, and move to ShowUnitsHelperBase class in fft_utils.h and fft_utils.c
/////-----Kit 10/11/2010 ORG-1227 ADD_UNITS_FOR_FFT_REPORT
//static bool _get_worksheet_and_col_index( const DataRange &dr, Worksheet &wks, int &nColIndex )
//{
	//if( !dr.IsValid() || (dr.GetNumRanges() == 0) )
		//return false;
	//
	//int nColStart, nColEnd;
	//if( !dr.GetRange( wks, nColStart, nColEnd, 0 ) )
	//{
		//return false;
	//}
	//
	//nColIndex = nColStart;
	//return true;
//
//}
//
//// if strUnit include operator, add parentheses to strUnit and return true, otherwise return false
//static bool _check_unit_is_compoiste( string &strUnit )
//{
	//vector<string> vsOperator = { "+", "-", "*", "*/", "^", "%" };
	//
	//for( int ii=0; ii<vsOperator.GetSize(); ++ii )
	//{
		//if( -1 != strUnit.Find( vsOperator[ii] ) )
		//{
			//string strTmp = "(";
			//strTmp += strUnit;
			//strTmp += ")";
			//
			//strUnit = strTmp;
			//
			//return true;
		//}
	//}
	//
	//return false;
//}
//
//static bool _get_unit_str( const DataRange &dr, string &strXUnit, string &strYUnit )
//{
	//Worksheet inputWks;
	//int nColIndex;
	//if( !_get_worksheet_and_col_index( dr, inputWks, nColIndex ) )
	//{
		//ASSERT( false );
		//return false;
	//}
	//
	//Column colY = inputWks.Columns( nColIndex );
	//
	//int nNewColIndex = inputWks.FindColIndex( colY.GetIndex(), OKDATAOBJ_DESIGNATION_X );
	//
	//if( nNewColIndex < 0 )
		//return false;
	//
	//Column colX = inputWks.Columns( nNewColIndex );
	//
	//strXUnit = colX.GetUnits();
	//strYUnit = colY.GetUnits();
	//if( strXUnit.IsEmpty() || strYUnit.IsEmpty() )
		//return false;
	//
	//_check_unit_is_compoiste( strXUnit );
	//_check_unit_is_compoiste( strYUnit );
	//
	//return true;
//}
//
//static bool _create_fft_report_unit_str( int nRDID, LPCTSTR lpcstrXUnit, LPCTSTR lpcstrYUnit, string &strUnit )
//{
	//bool bRet = true;
	//switch( nRDID )
	//{
		//case _FFT_RDID_FREQ:
			//if( compare_string_localization( lpcstrXUnit, "sec", true )
				//|| compare_string_localization( lpcstrXUnit, "s", true ) 
				//|| compare_string_localization( lpcstrXUnit, "second", true ) )
			//{
				//strUnit = _L( "Hz" );
			//}
			//else if( compare_string_localization( lpcstrXUnit, "ms", true ) )
			//{
				//strUnit = _L( "kHz" );
			//}
			//else
			//{
				//strUnit.Format( _L("1/%s"), lpcstrXUnit );
			//}
			//break;
		//case _FFT_RDID_AMP:
		//case _FFT_RDID_MAG:
			//strUnit = lpcstrYUnit;
			//break;
		//case _FFT_RDID_POWER:
			//strUnit.Format( _L("%s^2*%s"), lpcstrYUnit, lpcstrXUnit );
			//break;
		//case _FFT_RDID_NORM_DB:
		//case _FFT_RDID_DB:
			//strUnit = _L("dB");
			//break;
		//case _FFT_RDID_SQR_AMP:
		//case _FFT_RDID_SQR_MAG:
			//strUnit.Format( _L("%s^2"), lpcstrYUnit );
			//break;
		//default:
			//bRet = false;
			//break;
	//}
	//
	//return bRet;
//}
//
//static bool _show_units_row( const DataRange &dr, Worksheet &wksFFT, const ReportTable &rtFFT )
//{
	//string strXUnit, strYUnit;
	//if( !_get_unit_str( dr, strXUnit, strYUnit ) )
		//return false;
	//
	//wksFFT.CheckAddLabelByType( RCLT_UNIT );
		//
	//if( wksFFT.Columns.Count() != rtFFT.Children.Count() )
	//{
		//ASSERT( false );
		//return false;
	//}
	//
	//int iColIndex = 0;
	//foreach( TreeNode tr in rtFFT.Children )
	//{	
		//string strUnit;
		//if( _create_fft_report_unit_str( tr.ID, strXUnit, strYUnit, strUnit ) )
		//{
			//Column col = wksFFT.Columns( iColIndex );
			//col.SetUnits( strUnit );
		//}
		//
		//iColIndex++;
	//}
	//
	//return true;
//}
/////-----End ADD_UNITS_FOR_FFT_REPORT

class FFTShowUnitsHelper : public ShowUnitsHelperBase
{
public:
	FFTShowUnitsHelper(const DataRange &dr, int nNorma);
protected:
	//virtual
	bool	CreateReportUnitStr(int nRDID, string &strUnit);
private:
	int m_nNorma;
};

FFTShowUnitsHelper::FFTShowUnitsHelper(const DataRange &dr, int nNorma) : ShowUnitsHelperBase(dr)
{
	m_nNorma = nNorma;
}

bool	FFTShowUnitsHelper::CreateReportUnitStr(int nRDID, string &strUnit)
{
	bool bRet = true;
	strUnit.Empty();
	string strX = m_strUnitX;
	string strReal = m_strUnitReal;
	
	if( CheckUnitIsCompoiste(strX) )
		AddParenthesis(strX);
	if( CheckUnitIsCompoiste(strReal) )
		AddParenthesis(strReal);
	
	switch( nRDID )
	{
		case _FFT_RDID_FREQ:
			if( compare_string_localization( m_strUnitX, "sec", true )
				|| compare_string_localization( m_strUnitX, "s", true ) 
				|| compare_string_localization( m_strUnitX, "second", true ) )
			{
				strUnit = "Hz";
			}
			else if( compare_string_localization( m_strUnitX, "ms", true ) )
			{
				strUnit = "kHz";
			}
			else
			{
				if( !HandleReciprocalCase(strUnit) )
					strUnit = "1/" + strX;
			}
			break;
		case _FFT_RDID_AMP:
			if( m_nNorma == 0 )
			{
				strUnit = strReal;
			}
			break;
		case _FFT_RDID_MAG:
		case _FFT_RDID_RMS:
			strUnit = strReal;
			break;
		case _FFT_RDID_POWER:
			strUnit.Format( "%s^2*%s", strReal, strX );
			break;
		case _FFT_RDID_NORM_DB:
		case _FFT_RDID_DB:
			strUnit = "dB";
			break;
		case _FFT_RDID_SQR_AMP:
		case _FFT_RDID_SQR_MAG:
			strUnit.Format( "%s^2", strReal );
			break;
		case _FFT_RDID_PHASE:
			strUnit = "Deg";
			break;
		default:
			bRet = false;
			break;
	}
	
	return bRet;
}
///-----End REFACTOR_THE_CODE


void fft1(const vector<complex>& ix, const double& interval, const int& win, const int& reserve, const int& norma, const int& shift, const int& unwrap, const int& factor, const int& st, const int& norm, const int& pre, const int& re, const int& im, const int& ap, const int& phase, const int& pp, const int& ri, const int& mag, const int& amp, const int& psd, const int& db, const int& ndb, const int& rms, const int& sqr_amp, const int& sqr_mag, ReportData& rd, ReportTree& rt)
{
	
	/// Justin 01/10/2007
	if(NULL == rd &&  interval)
		XF_THROW(XFERR_INVALID_ARG);
	///end 
	
	waitCursor junk;
	
	int	nRet; 
	///---justin 07/31/2006 MORE_OPTIONAL_OUTPUT
	//vector				vFreq, vImag, vReal, vAmp, vPhase, vPower;	
	vector				vFreq, vImag, vReal;	//vector vFreq, vImag, vReal, vMagnitude, vPhase, vTemp; 	///---justin 08/07/2006 OUTPUT_DATA_ACCORDING_TO_PLOT
	///end MORE_OPTIONAL_OUTPUT
	//double dComp = 1.0;   /// Fisher 2/17/2009	REMOVE_COMPENSATE_OPTION
	
	vector<complex> vOut;
	
	vOut = ix;
	int nSize = vOut.GetSize();
	vOut.GetImaginary(vImag);
	vOut.GetReal(vReal);
	
	bool bRealInput = nSize == ocmath_count(0., vImag.GetSize(), vImag);
	
	nRet = get_frequence_from_interval(nSize, vFreq, interval);
	if (0 != nRet)
	{
		XF_THROW(nRet);
	}
	
	if (nSize == ocmath_count(0., vImag.GetSize(), vImag))
	{
		/// Fisher 2/17/2009	REMOVE_COMPENSATE_OPTION
		//apply_window_data(vReal, win, comp?&dComp:NULL);
		apply_window_data(vReal, win, NULL);		
		/// End REMOVE_COMPENSATE_OPTION
			
		nRet = fft_real(nSize, vReal, FFT_FORWARD);
		if(0 != nRet )
		{
			XF_THROW(nRet);
		}			
			
		fft_hermitian_to_complex(nSize, vReal, vOut);
	}
	else
	{
		/// Fisher 2/17/2009	REMOVE_COMPENSATE_OPTION
		//apply_window_data(vReal, win, comp?&dComp:NULL);
		apply_window_data(vReal, win, NULL);		
		/// End REMOVE_COMPENSATE_OPTION		
	  	apply_window_data(vImag, win);
	  	
		vOut.MakeComplex(vReal, vImag);
		nRet = fft_complex(nSize, vOut, FFT_FORWARD);
		if (0 != nRet )
		{
			XF_THROW(nRet);
		}
	}
	
	///---justin 07/31/2006 MORE_OPTIONAL_OUTPUT
	//if (norm_amp)
	//{
		//fft_norm_amp(vOut);
	//}
	///end MORE_OPTIONAL_OUTPUT
	
	if(factor) 
	{
		fft_factor(vOut);
	}
	
	if (shift)
	{
		fft_shift(vOut, vFreq);
	}
	
	/// Fisher 2/17/2009	REMOVE_COMPENSATE_OPTION
	// We will remove the codes and do not use this option anymore, reserve this option.
	//if (comp)
	//{
	//	vOut /= sqrt(dComp);  //Compensate tapering caused by applying window
	//}	
	//End REMOVE_COMPENSATE_OPTION
	
	/// Fisher 2/17/2009 FIX_INCORRECT_NORMALIZAION_AND_SIDED_RESULT
	/// norma Only affect ri, Re, Im, Magnitude and Square Magnitude
	//if (norma)
	//{
	//	vOut *= 2.0/nSize;
	//}
	/// End FIX_INCORRECT_NORMALIZAION_AND_SIDED_RESULT
	
	int nDefType = st;
	if( st_auto == st)
	{
		nDefType = bRealInput? st_oneside : st_twoside;
	}
	
	string strTemplate;
	int nY1ID, nY2ID;
	
	/// Fisher 2008/10/21 QA80-12420 OUTPUT_HALF_DATASET_FOR_ONE_SIDE_SPECTRUM	
	//int nRow1 = (nDefType == 1 && shift == 1)? (nSize - 1)/2 : 0; 
	//int nRow2 = nRow1 + ( (nDefType == 1)? nSize/2 : nSize -1 );
	int nRow1 = 0;
	int nRow2 = nDefType == 1 ? CUTOFF(nSize)-1 : nSize-1;
	/// End OUTPUT_HALF_DATASET_FOR_ONE_SIDE_SPECTRUM	
	
	//---- CPY 8/24/06 MOVE_FFT_GRAPH_TO_RESULT_SHEET
	XFExeContext	*pxfexectxt = Project.GetCurrentXFExeCtxt();
	GraphPage	gpFFT;
	/// ML 11/9/2006 REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT
	//gpFFT = pxfexectxt->GetGraph( _FFT_RDID_GRAPH );
	gpFFT = pxfexectxt->GetGraph(_FFT_RDID_GRAPH_PREVIEW);
	/// end REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT
	string strLabel, strInputDesc;
	pxfexectxt->GetArgDescription(strInputDesc, "ix");
	strLabel = "FFT of" + " " + strInputDesc;
	//----	
	
	//_prpare_plot_info(plot, strTemplate, nY1ID, nY2ID);
	
	//rd.ID = IDST_RESULT_CURVES; CPY 8/26/06 DEFAULT_ID_TO_AVOID_SETTING_ID_TO_12345_IN_XF, not needed anymore
	ReportTable rtFFT = rd.CreateTable("FFT", strLabel, _FFT_RDID_TABLE);
	
	//justin 10/13/2006 OUTPUT_MULTI_PLOT
	/*
	_calculate_result(rtFFT, nY1ID, nY2ID, vFreq, interval, vOut, shift, unwrap, nDefType, norm, amp, phase, psd, db, ndb, mag, rms, sqr_amp, sqr_mag );
	//---- CPY 8/24/06 MOVE_FFT_GRAPH_TO_RESULT_SHEET
	//_fft_rd_plotting(rd, strTemplate, nY1ID, nY2ID, nRow1, nRow2);//_fft_rd_plotting(rd, strTemplate, nY1ID, nY2ID, shift == 0);	//test
	if(_fft_rd_plotting(rd, gpFFT, strLabel, strTemplate, nY1ID, nY2ID, nRow1, nRow2) && gpFFT)
	{
		if(rt)
		{
			ReportTable rt = rt.CreateTable("Graphs", strLabel, IDST_RESULT_GRAPHS, 0, 1);
			rt.SetCell(0, 0, gpFFT, EMBEDGRAPH_KEEP_ASPECT_RATIO);//CPY 9/21/06 added EMBEDGRAPH_KEEP_ASPECT_RATIO
			rt.SetCell(-1, 0, _get_plot_name(plot));
		}
	}
	*/
	
	//----Sandy 2008-8-26 QA80-12094 Real/Imaginary preview in FFT did not show any plot  
	//	_calculate_result(rtFFT, vFreq, interval, vOut, shift, unwrap, nDefType, norm, re, im, amp || ap,  phase || ap || pp, psd || pp, db, ndb, ri, mag, rms, sqr_amp, sqr_mag, win );
	_calculate_result(rtFFT, vFreq, interval, vOut, shift, unwrap, nDefType, norm, re || ri, im || ri, amp || ap,  phase || ap || pp, psd || pp, db, ndb, ri , mag, rms, sqr_amp, sqr_mag, win, norma );
	
	if(!rt)          ///justin 11/13/2006  //temp solution
	{
		_plot_preview(pre, gpFFT, rd, nRow1, nRow2);
	}
	
	if(rt)
	{
		Tree trPlot;
		_prepare_plot_tree(trPlot, re, im, ap, pp, ri, mag, amp, phase, psd, db, ndb, rms, sqr_amp, sqr_mag);
		ReportTable rt = rt.CreateTable("Graphs", strLabel, IDST_RESULT_GRAPHS, 0, 1);
		int iCol = 0;
		int iRow = 0;
		//------ CPY 10/20/06 BETTER_GRAPHS_IF_FEWER
		int nGraphsPerCol = 1;
		int nNumGraphs = 0;
		foreach(TreeNode trC in trPlot.Children)
		{
			if(trC.nVal)
				nNumGraphs++;
		}
		if(nNumGraphs > 1)
			nGraphsPerCol += sqrt(nNumGraphs - 1); //nGraphsPerCol = 0.5+ sqrt(nNumGraphs);  //justin 10/23/2006 
		//-------
				
			
		foreach(TreeNode trTmp in trPlot.Children)
		{
			if(trTmp.nVal)
			{
				/// ML 11/9/2006 REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT
				GraphPage gpTemp;
				// See if it already exists:
				gpTemp = pxfexectxt->GetGraph(trTmp.ID);
				/// end REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT
				_prpare_plot_info(trTmp.ID, strTemplate, nY1ID, nY2ID);
				_fft_rd_plotting(rd, gpTemp, strLabel, strTemplate, nY1ID, nY2ID, nRow1, nRow2, _get_plot_name(trTmp.ID)); //_fft_rd_plotting(rd, gpTemp, strLabel, strTemplate, nY1ID, nY2ID, nRow1, nRow2);///justin 11/20/2006
				/// ML 11/9/2006 REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT
				pxfexectxt->SetGraph(gpTemp, trTmp.ID);		// remember the rt for the future
				/// end REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT
				///Justin 2007-04-02 AUTO_RESIZE_GRAPH_CELL
				//rt.SetCell(iRow, iCol, _get_plot_name(trTmp.ID));			
				//rt.SetCell(iRow+1, iCol, gpTemp, EMBEDGRAPH_KEEP_ASPECT_RATIO);
				//if(++ iCol >= nGraphsPerCol)
				//{
					//iRow += 2;
					//iCol = 0;
				//}
				rt.SetCell(iRow, iCol, gpTemp, EMBEDGRAPH_KEEP_ASPECT_RATIO | EMBEDGRAPH_MOVE_IF_ALREADY_EMBEDDED);
				if(++ iCol >= nGraphsPerCol)
				{
					iRow ++;
					iCol = 0;
				}				
				///end 
				
				
			}			
			/// ML 11/9/2006 REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT
			else
				pxfexectxt->RemoveGraph(trTmp.ID);		// remove from the context in case it was there
			/// end REMEMBERING_GRAPHS_IN_EXECUTION_CONTEXT
		}
		
		///-----Kit 10/12/2010 ORG-1227-P1 FAIL_TO_EXECUTE_FFT1_BY_SCRIPT
		if( rd.IsValid() )
		{
			///-----Kit 10/26/2010 REFACTOR_THE_CODE
			
			/////-----Kit 10/20/2010 ORG-1227-P2 WRONG_RANGE_TO_GET_UNITS_STR
			//DataRange	dr;
			//dr = ix.GetSourceDataRange();
			/////-----End WRONG_RANGE_TO_GET_UNITS_STR
			//Worksheet wksFFT;
			//rd.GetWorksheet( wksFFT );  
			//if( wksFFT.IsValid() )
				/////-----Kit 10/20/2010 ORG-1227-P2 WRONG_RANGE_TO_GET_UNITS_STR
				////_show_units_row( strInputDesc, wksFFT, rtFFT );
				//_show_units_row( dr, wksFFT, rtFFT );
				/////-----End WRONG_RANGE_TO_GET_UNITS_STR
			//else  
				//ASSERT( false );
			DataRange dr;
			dr = ix.GetSourceDataRange();
			Worksheet wksFFT;
			rd.GetWorksheet(wksFFT);
			if( wksFFT.IsValid() )
			{
				FFTShowUnitsHelper showUnitHelper(dr, norma);
				showUnitHelper.ShowUnitsRowOnReportTable(wksFFT, rtFFT);
			}
			else
			{
				ASSERT(false);
			}
			///-----End REFACTOR_THE_CODE
		}
		///-----End FAIL_TO_EXECUTE_FFT1_BY_SCRIPT
	}
	//end OUTPUT_MULTI_PLOT
	//----	
	///end 
	//end OUTPUT_DATA_ACCORDING_TO_PLOT
	
	///-----Kit 10/12/2010 ORG-1227-P1 FAIL_TO_EXECUTE_FFT1_BY_SCRIPT
	/////-----Kit 10/11/2010 ORG-1227 ADD_UNITS_FOR_FFT_REPORT
	//Worksheet wksFFT;
	//rd.GetWorksheet( wksFFT );
	//ASSERT( wksFFT );
	//_show_units_row( strInputDesc, wksFFT );
	/////-----End ADD_UNITS_FOR_FFT_REPORT
	///-----End FAIL_TO_EXECUTE_FFT1_BY_SCRIPT
	
	///------ Folger 04/14/09 QA80-13436 IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
	CHECK_SHOW_WARNING_MESSAGE_IN_XF_BODY
	///------ End IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
	
}

//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 fft1_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return fft1_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	///justin 10/30/2006 CLEAN
	/*
	//--------- CPY 7/3/06 QA70-8798 DYNABOX_BETTER_EVENTS
	printf("nRow=%d, nEventID=%d\n", nRow, nEventID);
	
	if(GETNE_ON_INIT == nEventID || is_data_selection_control_id(nEventID))
	{
		///justin 08/18/2006 KEEP_AUTO_OF_INTERVAL
		//int nRet = auto_compute_sampling_interval_from_InputData(trGetN);
		Tree trTemp;
		trTemp = trGetN;
		int nRet = auto_compute_sampling_interval_from_InputData(trTemp);
		//end KEEP_AUTO_OF_INTERVAL
		if(nRet != -1 && nRet != 0)
		{
			XF_TRACE("Warning : Time sequences should be monotonic increase!");
		}	
		bOKEnable = (nRet == -1) ? false : true;	
		return true;
	}
	
	if(TRGP_ENUM_LIST == nEventID)
		return true;
	*/
	return false;
	//--------
	//end CLEAN
	

}

int fft1_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 fft1_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_fft1);
	//---CPY 8/16/06, temp, will remove later
	//out_int("before execute, nGetNDialog= ", nGetNDialog);
	//---
	/// Iris 9/4/2009 QA80-14165 SCRIPT_MODE_NEED_THROW_ERROR_FOR_PRO_OPTION_IN_REGULAR_BUILD
	//_disable_utilities_for_regular_version(trGetN);	
	string 	strProOption;
	bool 	bScriptMode = nGetNDialog == 0;
	bool 	bProErr = !_disable_utilities_for_regular_version(trGetN, true, bScriptMode, strProOption);
	///end SCRIPT_MODE_NEED_THROW_ERROR_FOR_PRO_OPTION_IN_REGULAR_BUILD
	//---- CPY 11/21/06 GRAPH_NODE_USE_CHECKBOX_TO_ALLOW_NO_GRAPHS
	//_uadate_graph_sheet(trGetN, nGetNDialog == 0);
	if(nGetNDialog == 0 && (dwCntrl & LTXF_FROM_GUI_PROMPT))
		_uadate_graph_node_from_LT_execution(trGetN);
	//----
	
	/// Max 3/8/08 ONLY_RESET_PLOT_SHEET_NODE_WHEN_IT_IS_NOT_MANUALLY_MODIFIED
	// (nGetNDialog > 0) case is handled in GetNGraphPreview_OnChange()
	///Sandy 2007-10-15 add checking if no plot, no graph sheet output
	/*
	if(nGetNDialog > 0)
		_check_if_need_plots_in_result_sheet(trGetN);
	*/
	/// END ONLY_RESET_PLOT_SHEET_NODE_WHEN_IT_IS_NOT_MANUALLY_MODIFIED
	/// Max 4/8/08 v8.0839 NEED_TO_CHECK_THEME_CHANGE_CASE
	ASSERT (trGetN.rt);
	if(nGetNDialog > 0 && !_check_if_need_plots_in_result_sheet(trGetN))
		trGetN.rt.Enable = false;
	/// END NEED_TO_CHECK_THEME_CHANGE_CASE
	
	if(nGetNDialog == 0 || nGetNDialog == -1) //if(nGetNDialog == 0 ) // when running from LT without openning any dialog, or on OK button before running ///justin 08/17/2006 HANDLE_AUTO_WHEN_CLICK_OK
	{
		///justin 08/18/2006 SAME_NAME_OF_TWO_VARIABLES
		//int nRet = auto_compute_sampling_interval_from_InputData(trGetN);
		//if(nRet != 0 && nRet != -1)
			//XF_TRACE("Warning : Time sequences should be monotonic increase!");
		///justin 11/21/2006 
		//int nStat = auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.Interval, false); //int nStat = auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.Interval, true); //int nStat = auto_compute_sampling_interval_from_InputData(trGetN);
		//if(nStat != 0 && nStat != -1)
			//XF_TRACE("Warning : Time sequences should be monotonic increase!");
		/////end SAME_NAME_OF_TWO_VARIABLES
		//double dInterval = trGetN.interval.dVal;
		//if(is_missing_value(dInterval))
			//nRet = XFEVT_ABORT;
			
		///Justin
		//int nErr = auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.Interval, false); //int nStat = auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.Interval, true); //int nStat = auto_compute_sampling_interval_from_InputData(trGetN);
		//if(nErr)
			//XF_WARN(nErr);
			
		int nErr = CER_NO_ERROR;
		/// Max 8/27/08 v8.0931b TEMP_COMMENT_SANDY_CHANGE_WHICH_WILL_POP_UP_DLG_ONCE_ERR_APPEAR
		
		///Sandy add 2008-8-12 for check input 
		string strErrMsg;
		if(!get_error_for_input_complex_vector(trGetN.ix, strErrMsg) )
		{
			nErr = XFERR_INVALID_RANGE;	
		}
		
		/// END TEMP_COMMENT_SANDY_CHANGE_WHICH_WILL_POP_UP_DLG_ONCE_ERR_APPEAR
	
		//auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.Interval);  ///Justin 2007-03-27 AUTO_FOR_NO_DIALOG
		//int nErr = check_interval(trGetN.interval);
		///------ Folger 04/14/09 QA80-13436 IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
		//if(CER_NO_ERROR == nErr)
		//{
			//auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.Interval);  ///Justin 2007-03-27 AUTO_FOR_NO_DIALOG
			//nErr = check_interval(trGetN.interval);
			//strErrMsg = nErr;			
		//}
		///------ End IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
		
		///Jasmine 08/14/07 QA80-10207 REPORT_SHEET_CHECK_CONFLICT
		if(CER_NO_ERROR == nErr && is_same_sheet(trGetN.rd, trGetN.rt))
		{
			nErr = XFERR_REPORT_SHEET_CONFLICT;
			strErrMsg = nErr;
		}
		
		if(CER_NO_ERROR != nErr)
		{
			///Sandy 2008-8-29 XF called from LT should not pop up dialog as Max's attention
			/*
			//XF_WARN(nErr);
			//warning_msg_box(nErr, false, 'E');
			//nRet = XFEVT_ABORT;
			/// Max 8/27/08 v8.0931b TEMP_COMMENT_SANDY_CHANGE_WHICH_WILL_POP_UP_DLG_ONCE_ERR_APPEAR
			//nRet = XFEVT_PROCEED_WITH_DLG;//Sandy 2008-8-21 Dialog should prompt although there is invalid input.
			warning_msg_box(nErr, false, 'E');
			nRet = XFEVT_ABORT;
			// END TEMP_COMMENT_SANDY_CHANGE_WHICH_WILL_POP_UP_DLG_ONCE_ERR_APPEAR
			*/
			if( (dwCntrl&LTXF_THEME_USED) && (dwCntrl&LTXF_FROM_GUI_MENU))
			{
				nRet = XFEVT_PROCEED_WITH_DLG;
			}
			else
			{
				//warning_msg_box(nErr, false, 'E');
				xf_warning_msg_box(strErrMsg, false, 'E');
				nRet = XFEVT_ABORT;				
			}
		}
		
		/// Iris 9/4/2009 QA80-14165 SCRIPT_MODE_NEED_THROW_ERROR_FOR_PRO_OPTION_IN_REGULAR_BUILD
		if( CER_NO_ERROR == nErr && bScriptMode && bProErr )
		{
			warning_msg_box(XFERR_PRO_OPTION_WARNNING_MSG, strProOption, false, 'E');
			nRet = XFEVT_ABORT;
		}
		///end SCRIPT_MODE_NEED_THROW_ERROR_FOR_PRO_OPTION_IN_REGULAR_BUILD
		
		///End REPORT_SHEET_CHECK_CONFLICT
		///end 
		///end  
		///justin 10/16/2006 OUTPUT_MULTI_PLOT
		/*
		///justin 09/28/2006 NO_PLOT_NO_GRAPH
		if(FFTPLOT_NONE == trGetN.plot.nVal)
		{
			trGetN.rt.strVal = "<optional>";
		}
		//end NO_PLOT_NO_GRAPH
		*/
		//end OUTPUT_MULTI_PLOT
	}
	//_update_interface(trGetN); ///justin 08/14/2006 DISABLE_SOME_UTILITIES_IN_REGULAR_VERSION ///justin 10/16/2006
	
	///------ Folger 04/14/09 QA80-13436 IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
	if ( is_xf_startup(nGetNDialog, dwCntrl) )
	{
		SET_WARNING_MSG_SHOW_IN_XF_BODY(IS_ERR_MSG_OK_TO_SHOW_IN_BODY);
		int		nErr = auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.Interval);
		if ( CER_NO_ERROR == nErr )
			nErr = check_interval(trGetN.interval);
		XF_SET_WARNING_MSG_ID(nErr);
	}
	///------ End IMPROVE_MECHANISM_ABOUT_XF_ERR_MSG_SHOWN_IN_BODY
}
//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 fft1_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;
	

}

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

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

	//Worksheet wks = wksTemp;
	/////justin 10/30/2006 JUST_RECACULATE_WHEN_NECESSARY
	///*
	////bOKEnable = _update_sampling_interval_from_InputData(trGetN, false); //--------- CPY 7/3/06 QA70-8798 DYNABOX_BETTER_EVENTS
	/////justin 08/18/2006 KEEP_AUTO_OF_INTERVAL
	////int nRet = auto_compute_sampling_interval_from_InputData(trGetN);
	//Tree trTemp;
	//trTemp = trGetN;
	//int nRet = auto_compute_sampling_interval_from_InputData(trTemp);
	////end KEEP_AUTO_OF_INTERVAL
	//if(nRet != -1 && nRet != 0)
	//{
		////---- CPY 10/26/06 QA70-9063 DYNAMIC_ERR_MSG_IN_GETN_DIALOGS
		////XF_TRACE("Warning : Time sequences should be monotonic increase!");
		//strErrMsg = STR_WARN_BAG_TIME_INTERVAL;
		////----
	//}
	//else
		////---- CPY 10/26/06 QA70-9063 DYNAMIC_ERR_MSG_IN_GETN_DIALOGS
		//strErrMsg.Format("Sample Interval: %g", trTemp.interval.dVal);
		////----
		//
	//bOKEnable = (nRet == -1) ? false : true;	
	//*/
//
	////end JUST_RECACULATE_WHEN_NECESSARY
//
	////_run_fft_on_current_data(trGetN, pgTemp, wks); //Justin 2007-06-13 SHOULD_AUTO_INTERVAL_BEFORE_PLOT
	//
	//
	///// ML 7/13/2006 FFT_REWORK_REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
	////if(!_plot_fft_results(trGetN, pgTemp, wks))
	////	return;
	///// end FFT_REWORK_REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
	//// there is some problem that we need to force a dialog page to refresh
	//GraphPage gp = pgTemp;
	//gp.Refresh(true);
	//
	/////justin 11/03/2006 UPDATE_ERROR_MESSAGE
	////int nRet = get_fft_input_vector(trGetN.ix);
	////if(nRet)
	////{
		////strErrMsg = nRet;
		////bOKEnable = false; 
		////return;
	////}
	//if(! (bOKEnable = get_error_for_input_complex_vector(trGetN.ix, strErrMsg) ) )
		//return;
	/////end UPDATE_ERROR_MESSAGE
	//strErrMsg = auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.interval);
	//
	//_run_fft_on_current_data(trGetN, pgTemp, wks); //Justin 2007-06-13 SHOULD_AUTO_INTERVAL_BEFORE_PLOT
	//
	/////--justin 
	//int nErr =  check_interval(trGetN.interval);
	//if(nErr)
	//{
		//bOKEnable = false;
		//strErrMsg = nErr;
	//}
	/////end 
	
	///Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
	/////Sandy 2007-8-28 Clean initial code to speed up open dlg
	//GraphPage gp = pgTemp;
	//page_load(gp, "NonePreview"); 
	//load_text_for_nonepreview_graphpage(gp, TEMPLATE_NONE_PREVIEW_CONTENT, TEMPLATE_NONE_PREVIEW_HINTS);
	//
	/////Kyle 03/12/2009 SET_PREVIEW_GRAPH_NO_CLICK
	//GraphPage gpPreview(pgTemp);
	//if(gpPreview)
		//set_gp_noclick(gpPreview, NOCLICK_DATA_PLOT | NOCLICK_TICKLABEL | NOCLICK_LAYER | NOCLICK_LAYERICON | NOCLICK_AXES | NOCLICK_LABEL);
	/////End SET_PREVIEW_GRAPH_NO_CLICK
	xf_load_nopreview(pgTemp, OC_PREVIEW_NOCLICK_NOZOOMPAN);
	///End CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
	
	///Sandy add 2007-12-27 for check input when initialize, should move to initGrid actually
	if(!(bOKEnable = get_error_for_input_complex_vector(trGetN.ix, strErrMsg) ) )
	{
		return;
	}
	
	strErrMsg = auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.interval);

	int nErr =  check_interval(trGetN.interval);
	if(nErr)
	{
		strErrMsg = nErr;
		bOKEnable = false;
	}	
	///end

	
}

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

static void GetNGraphPreview_OnUpdateGraph(TreeNode& trGetN, PageBase& pgTemp, Datasheet& wksTemp, PictureControl& pict)
{

	Worksheet wks = wksTemp;
	_run_fft_on_current_data(trGetN, pgTemp, wks);	
	/// ML 7/13/2006 FFT_REWORK_REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
	//_plot_fft_results(trGetN, pgTemp, wks);
	/// end FFT_REWORK_REPORT_DATA_WITH_XF_WORKSHEET_GRAPHS_HANDLING
	
	///Kyle 03/12/2009 SET_PREVIEW_GRAPH_NO_CLICK
	GraphPage gpPreview(pgTemp);
	if(gpPreview)
		///Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
		//set_gp_noclick(gpPreview, NOCLICK_DATA_PLOT | NOCLICK_TICKLABEL | NOCLICK_LAYER | NOCLICK_LAYERICON | NOCLICK_AXES | NOCLICK_LABEL);
		set_gp_noclick(gpPreview, OC_PREVIEW_NOCLICK_NOZOOMPAN | NOCLICK_LABEL);
		///End CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
	///End SET_PREVIEW_GRAPH_NO_CLICK


}

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

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

	string strProOption;
	_disable_utilities_for_regular_version(trGetN, false, false, strProOption); /// Iris 9/04/2009 QA80-14165-P1 FIX_RESET_THEME_db_CONTROL_IS_CHECKED

	///justin 10/30/2006 JUST_RECACULATE_WHEN_NECESSARY
	/*
	if(trNode.IsValid() && trNode.tagName == "ix") 
	{
		//bOKEnable = _update_sampling_interval_from_InputData(trGetN, false);//--------- CPY 7/3/06 QA70-8798 DYNABOX_BETTER_EVENTS			
		///justin 08/18/2006 KEEP_AUTO_OF_INTERVAL
		//int nRet = auto_compute_sampling_interval_from_InputData(trGetN);
		Tree trTemp;
		trTemp = trGetN;
		int nRet = auto_compute_sampling_interval_from_InputData(trTemp);
		//end KEEP_AUTO_OF_INTERVAL
		if(nRet != -1 && nRet != 0)
		{
			XF_TRACE("Warning : Time sequences should be monotonic increase!");
		}	
		bOKEnable = (nRet == -1) ? false : true; 	
	}
	///---justin 08/07/2006 OUTPUT_DATA_ACCORDING_TO_PLOT
	/////--justin 08/01/2006 MORE_OPTIONAL_PLOT
	//string strPlotList;
	//_get_plot_type_and_create_plot_list(strPlotList, trGetN.plot.nVal, trGetN.amplitude.nVal,  
			//trGetN.phase.nVal, trGetN.power.nVal, trGetN.db.nVal, trGetN.norm_db.nVal, trGetN.magnitude.nVal, 
			//trGetN.rms_amp.nVal, trGetN.sqr_amp.nVal, trGetN.sqr_mag.nVal, trGetN.tisa.nVal, trGetN.msa.nVal, 
			//trGetN.ssa.nVal);
	//trGetN.plot.SetAttribute("Combo", strPlotList);
	//Worksheet wks = wksTemp;
	//_run_fft_on_current_data(trGetN, pgTemp, wks);	
	////end MORE_OPTIONAL_PLOT
	//Worksheet wks = wksTemp;
	//_run_fft_on_current_data(trGetN, pgTemp, wks);	
	///--end OUTPUT_DATA_ACCORDING_TO_PLOT
	*/
	//bUpdateGrid = true;
	
	//---- CPY 11/21/06 GRAPH_NODE_USE_CHECKBOX_TO_ALLOW_NO_GRAPHS
	//bUpdateGraph = true;
	//_uadate_graph_output(trGetN);
	//bUpdateGraph = _check_update_grid_nodes(trGetN, bChangedByGraph, trNode.tagName);  ///justin 11/22/2006 temp solution
	//---- end GRAPH_NODE_USE_CHECKBOX_TO_ALLOW_NO_GRAPHS
	
	///justin 11/03/2006 IMPROVE_CODE
	//if(trNode.IsValid())
	//{
		//if((trNode.tagName == "AutoUpdate" || trNode.tagName == "re" || trNode.tagName == "im" || trNode.tagName =="ap" || trNode.tagName == "phase" || trNode.tagName == "pp" || trNode.tagName == "ri" || trNode.tagName == "mag" || trNode.tagName == "amp" || trNode.tagName == "psd" || trNode.tagName == "db" || trNode.tagName == "ndb" || trNode.tagName == "rms" || trNode.tagName == "sqr_amp" || trNode.tagName == "sqr_mag"))
		//{
			//bUpdateGraph = false;
		//}
	//}
	bUpdateGraph = _check_update_graph(trNode);
	///end IMPROVE_CODE

	///justin 11/03/2006 UPDATE_ERROR_MESSAGE
	//int nRet = get_fft_input_vector(trGetN.ix);
	//if(nRet)
	//{
		//strErrMsg = nRet;
		//bOKEnable = false;
		//return;
	//}
	if((bOKEnable = get_error_for_input_complex_vector(trGetN.ix, strErrMsg) ) )
	{
		strErrMsg = auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.interval);
		//justin 2007-3-22
		int nErr =  check_interval(trGetN.interval);
		if(nErr)
		{
			strErrMsg = nErr;
			bOKEnable = false;
		}
		bUpdateGrid = true;  //Justin 2007-04-04 FORCE_TO_DISPLAY_INTERVAL_AFTER_CHANGE_THEME 		
	}
	///end UPDATE_ERROR_MESSAGE


	//end JUST_RECACULATE_WHEN_NECESSARY
	///Jasmine 08/14/07 QA80-10207 REPORT_SHEET_CHECK_CONFLICT
	if(bOKEnable && is_same_sheet(trGetN.rd, trGetN.rt))
	{
		int nErr = XFERR_REPORT_SHEET_CONFLICT;
		strErrMsg = nErr;
		bOKEnable = false;
	}
	///End REPORT_SHEET_CHECK_CONFLICT
	
	///Jasmine 08/24/09 QA81-14165 DISPLAY_BUT_DISABLE_PRO_OPTION_IN_REG_VERSION
	if(bOKEnable && !is_pro_version() && !strProOption.IsEmpty() )
	{
		strErrMsg = XFERR_PRO_OPTION_WARNNING_MSG;
		strErrMsg += ":" + strProOption;
	}
	///End DISPLAY_BUT_DISABLE_PRO_OPTION_IN_REG_VERSION
	
	/// Max 3/8/08 ONLY_RESET_PLOT_SHEET_NODE_WHEN_IT_IS_NOT_MANUALLY_MODIFIED
	///Sandy 2007-10-15 add checking if no plot, no graph sheet output
	//_check_if_need_plots_in_result_sheet(trGetN);
	//--- Jacky 08/27/10 ORG-920-P3 ONE_SAMPLE_TTEST_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
	//string strRTvalue = STR_DEFAULT_VALUE_FOR_PLOT_SHEET_NODE;
    //okutil_convert_localized_PDS(&strRTvalue);
	//--- end ONE_SAMPLE_TTEST_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
	bool bplot = _check_if_need_plots_in_result_sheet(trGetN);
	/// Max 4/8/08 v8.0839 NEED_TO_CHECK_THEME_CHANGE_CASE
	///// Max 4/7/08 v8.0838 MUST_CHECK_VALID_INPUT
	//ASSERT(trNode == NULL);
	//if (trNode)
	///// END MUST_CHECK_VALID_INPUT
		//tr_set_optional(true, trNode.tagName, trGetN.rt, bplot, strRTvalue);
	
	// theme change will also invoke GetNGraphPreview_OnChange() and trNode will be ivalid when theme changes
	LPCSTR lpcszNode;
	if(trNode)
		lpcszNode = trNode.tagName;
	//--- Jacky 08/27/10 ORG-920-P3 ONE_SAMPLE_TTEST_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
	//tr_set_optional(true, lpcszNode, trGetN.rt, bplot, strRTvalue);
	tr_set_optional_ex(true, lpcszNode, trGetN.rt, xf_event_is_change_param(trGetN), bplot);
	//--- end ONE_SAMPLE_TTEST_BETTER_HANDLING_OF_OUTPUT_PLOT_AND_REPORT_DATA
	/// END NEED_TO_CHECK_THEME_CHANGE_CASE
		
	/// END ONLY_RESET_PLOT_SHEET_NODE_WHEN_IT_IS_NOT_MANUALLY_MODIFIED
	
	if(!bOKEnable)
		dwUpdateGraph = UPDATE_GRAPH_INVALID; //nUpdateGraph = UPDATE_GRAPH_ERROR;

}

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

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

