#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	win_rect,
	win_welch,
	win_tri,
	win_bartlett,
	win_hanning,
	win_hamming,
	win_blackman,
	win_gauss,
	win_kaiser,
};
enum{
	option_complex,
	option_amp,
	option_ampdb,
};
#include <event_utils.h>
#include <getnbox.h> // temp solution
#include <fft_utils.h>
#include <fftEx_utils.h>
#include <o8dlg.h>
//enum {
	//ERR_FAIL_TO_GETDATA = XF_LOCAL_ERR_BEGIN,	
	//INVALID_VARIABLE_VALUE,
	//FAILD_IN_GET_STFT_WINDOW,
	//INVALID_MISSING_DATA_IN_WINDOW_DATA,
	//INVALID_MISSING_DATA,
//};

/***************************************************************************************
/// Modification Log :
/// Max 8/27/08 v8.0931b TEMP_COMMENT_SANDY_CHANGE_WHICH_WILL_POP_UP_DLG_ONCE_ERR_APPEAR
/// Kyle 03/12/2009 SET_PREVIEW_GRAPH_NO_CLICK
***************************************************************************************/


#define _WINDOW_LENGTH_MIN 2
#define _NONE_OVERLAP_MIN 1


static void _update_gl_axes_labels(GraphLayer& glay, bool bSwapXY)
{
	GraphObject goX = glay.GraphObjects("XB");
	GraphObject goY = glay.GraphObjects("YL");	
	
	if(bSwapXY)
	{
		goX.Text = "Frequency";
		goY.Text = "Time";
	}	
	else
	{
		goX.Text = "Time";
		goY.Text = "Frequency";
	}
	
	glay.Rescale();
	return;
}
static int _get_x_size(TreeNode& trData)
{
	vector<complex> vx;
	if(!trData)
		return 0;
	
	
	okxf_resolve_tree_get_data_into_vector(&trData, &vx);
	
	return vx.GetSize();
	
}
static void _update_grid_hide_show(TreeNode& trGetN, bool bIsWinLenNode = false, bool bIsOptionNode = false)
{
	trGetN.alpha.Show = (trGetN.win.nVal == Gaussian_Win);
	trGetN.beta.Show = (trGetN.win.nVal == Kaiser_Win);	
	
	if((trGetN.option.nVal == option_ampdb || trGetN.option.nVal == option_amp))
	{
		//trGetN.plot.Show = true;
		trGetN.plot.Enable = true;  //Sandy 2008-10-12 for couturier's suggestion on beta forum
		if(bIsOptionNode)
		  	trGetN.plot.nVal = 1;
	}
	else
	{
		//trGetN.plot.Show = false;//Sandy 2008-10-12 for couturier's suggestion on beta forum
		trGetN.plot.Enable = false;
		trGetN.plot.nVal = 0;
	}
	
	///justin 2007-04-26 IMPROVE_STFT_AS_BETAT_TESTER_SUGGESTION
	/*
	//sandy change to use slider to control winlen, fftlen, and overlap
	int nSize = _get_x_size(trGetN.ix);
	if(nSize > 2)
	{	
	
		String str;
		///Sandy 2006-11-22 for prevent large matrix create and not support
		int win_min = ((nSize / STFT_MAX_OUTPUT_MATRIX_COLS)<1? 1:((nSize / STFT_MAX_OUTPUT_MATRIX_COLS)+1));
		//str.Format("Slider:%d|%d|%d",1,trGetN.fftlen.nVal,trGetN.fftlen.nVal);	
	    str.Format("%d|%d|%d",win_min,trGetN.fftlen.nVal,(trGetN.fftlen.nVal - win_min));
	    ///end 	
	    
		trGetN.winlen.SetAttribute(STR_COMBO_ATTRIB,str);
		if(trGetN.fftlen.nVal<trGetN.winlen.nVal)
			trGetN.winlen.nVal = trGetN.fftlen.nVal;
		
		///Sandy 2006-11-22 for prevent large matrix create and not support
		//int ol_max = max(0,(trGetN.winlen.nVal-1));
		int ol_max = max(0,(trGetN.winlen.nVal-win_min));
		///end 	
		
		if(ol_max != 0)
		{
			trGetN.overlap.Show = true;
			str.Format("%d|%d|%d",0,ol_max,ol_max);
			trGetN.overlap.SetAttribute(STR_COMBO_ATTRIB,str);
			if(ol_max < trGetN.overlap.nVal || bIsWinLenNode)
				trGetN.overlap.nVal = ol_max/2;
		}
		else
		{
			trGetN.overlap.Show = false;
			trGetN.overlap.nVal = 0;
		}

	}
	*/
	///END IMPROVE_STFT_AS_BETAT_TESTER_SUGGESTION

}

//justin 11/21/2006 
//static void	_run_stft_on_current_data(TreeNode& trGetN, PageBase& pgTemp, MatrixLayer& ml)
static int	_run_stft_on_current_data(TreeNode& trGetN, PageBase& pgTemp, MatrixLayer& ml)
///end 
{
	//--- CPY 5/20/06 CHANGE_GETN_PREVIEW_TO_DATASHEET_FROM_WKSHEET

	GraphPage gp = pgTemp;
	//MatrixObject moDB = ml.MatrixObjects(0);
	MatrixObject om = ml.MatrixObjects(0);
	
	Tree trTemp;
	trTemp = trGetN;
	
	///Sandy 2007-7-23 move out to check in on_change
	/////Justin 2007-03-23 CHECK_INTERVAL_IS_VALID
	////auto_compute_sampling_interval_from_InputData(trTemp.ix, trTemp.interval, false); //justin 11/21/2006 SET_TEMP_INTERVAL
	//auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.interval); 
	//int nErr = check_interval(trGetN.interval);
	//if(nErr)
	//{
		//return nErr;
	//}
	/////END CHECK_INTERVAL_IS_VALID
	//end
	
	TreeNode trnInput = trTemp.ix;
	vector<complex> vx;
	if(trnInput)
	{
		
		okxf_resolve_tree_get_data_into_vector(&trnInput, &vx);
		
		if(vx.GetSize()>2)
		{
			double dv = trTemp.interval.dVal;
			int wl = trTemp.winlen.nVal;
			int ol = trTemp.overlap.nVal;
			int fl = trTemp.fftlen.nVal;
			int win = trTemp.win.nVal;
			int swapxy = trTemp.swapxy.nVal; ///justin 2007-04-26 IMPROVE_STFT_AS_BETAT_TESTER_SUGGESTION
			
			double aa = 0, bb = 0;
			if(trTemp.alpha.Show)
			{
				aa = trTemp.alpha.dVal;
			}
		
			if(trTemp.beta.Show)
			{
				bb = trTemp.beta.dVal;
			}
			
			///justin 11/21/2006 CATCH_ERROR
			//if(trTemp.option.nVal == option_ampdb)
				//stft(vx, dv, fl, wl, ol,  win, aa, bb, option_ampdb, om, 0);	
			//else
				//stft(vx, dv, fl, wl, ol,  win, aa, bb, option_amp, om, 0);
			try{
				int iOutput = (trTemp.option.nVal == option_ampdb)? option_ampdb : option_amp ;
				stft(vx, dv, fl, wl, ol,  win, aa, bb, iOutput, swapxy, om, 0);
			}
			catch(int nErr)
			{
				return nErr;
			}
			///end CATCH_ERROR
		}

	}
}
///justin 2007-04-26 IMPROVE_STFT_AS_BETAT_TESTER_SUGGESTION
/*
static bool _init_GetN_by_signal_size(TreeNode& trGetN)
{
	if(!trGetN.ix || !trGetN.fftlen || !trGetN.winlen || !trGetN.overlap)
		return false;
	int nSize = _get_x_size(trGetN.ix);
	trGetN.fftlen.nVal = min(256, nSize);
	trGetN.winlen.nVal = trGetN.fftlen.nVal;
	trGetN.overlap.nVal = trGetN.winlen.nVal/2;
	
	return true;
}
*/
static bool _auto_set_winlen(TreeNode& trGetN)
{
	int nFFT = trGetN.fftlen.nVal;
	if(0 >= nFFT)
		return false;
	TreeNode trWin = trGetN.winlen;
	if(1 == octree_get_auto_support(&trWin) )
		trWin.nVal = nFFT;
	return true;
}
static bool _auto_set_overlap(TreeNode& trGetN, int nDataSize)
{
	int nWin = trGetN.winlen.nVal;
	if(1 >= nWin)
		return false;

	TreeNode trOverLap = trGetN.overlap;
	if(1 == octree_get_auto_support(&trOverLap) )
		trOverLap.nVal = min(nWin/2, nWin - nDataSize/STFT_MAX_OUTPUT_MATRIX_COLS -1);
	return true;	
}
static int _check_fft_win_overlap_size(int nDataSize, int nFFTLength, int nWinLength, int nOverLap)
{
	int win_min = ((nDataSize / STFT_MAX_OUTPUT_MATRIX_COLS)<2? _WINDOW_LENGTH_MIN:((nDataSize / STFT_MAX_OUTPUT_MATRIX_COLS)+1));
	int win_max = STFT_MAX_OUTPUT_MATRIX_COLS;   //int win_max = min(nDataSize, STFT_MAX_OUTPUT_MATRIX_COLS);  ///Justin 2007-05-25 PERMIT_FFT_LENGTH_LARGT_THAN_DATA_SIZE

	if(nFFTLength > win_max)
		return STFT_ERR_FFT_LENGTH_TOO_LARGE;
	if(nFFTLength < win_min)
		return STFT_ERR_FFT_LENGTH_TOO_SMALL;

	if(nWinLength > nFFTLength)
		return STFT_ERR_WIN_LENGTH_TOO_LARGE;
	if(nWinLength < win_min)
		return STFT_ERR_WIN_LENGTH_TOO_SMALL;
	
	if( (nWinLength - nOverLap) < _NONE_OVERLAP_MIN || nDataSize > (nWinLength - nOverLap) * STFT_MAX_OUTPUT_MATRIX_COLS)
		return STFT_ERR_OVERLAP_TOO_LARGE;
	if( nOverLap < 0 )
		return STFT_ERR_OVERLAP_TOO_SAMLL;
	return 0;
}
///END IMPROVE_STFT_AS_BETAT_TESTER_SUGGESTION


void stft(const vector<complex>& ix, const double& interval, const int& fftlen, const int& winlen, const int& overlap, const int& win, const double& alpha, const double& beta, const int& option, const int& swapxy, MatrixObject& om, const int& plot)
{
	
	waitCursor junk;
	int nRet;
	vector vReal, vImag;
	
	int nSize = ix.GetSize();
	
	ix.GetImaginary(vImag);
	ix.GetReal(vReal);
	
	//check missing value
	//if (ocmath_count(NANUM, vReal.GetSize(), vReal)||ocmath_count(NANUM, vImag.GetSize(), vImag))
	//{
		//XF_THROW(INVALID_MISSING_DATA);
	//}
	
	//check variable 
	if( fftlen <= 1 || winlen > fftlen || overlap >= winlen || overlap < 0)
		XF_THROW(XFERR_INVALID_ARG);
	
	if(fftlen >= STFT_MAX_OUTPUT_MATRIX_COLS)
		XF_THROW(CWAR_MATRUX_SIZE_NOT_SUPPORT);
	
	//get window data
	vector vWin(winlen);
	nRet = get_window_data( win, winlen, vWin, alpha, beta ) ;
	if ( 0 !=  nRet)
	{	
		XF_THROW(nRet);
	}	
	//if ( ocmath_count(NANUM, vWin.GetSize(), vWin) ) 
	//{
		//XF_THROW(INVALID_MISSING_DATA_IN_WINDOW_DATA);
	//}	
	//
	
	
	double	dScaleFreq, dScaleTime;	
	double dSampFreq = 1.0/interval;
	if(nSize == ocmath_count(0., vImag.GetSize(), vImag) && (option == option_amp || option == option_ampdb))
	{
		om.SetInternalData(FSI_DOUBLE);///Sandy 2008-4-28 make sure the right data type is set when Change Parameters.
		matrix& mat = om.GetDataObject();
		nRet = stft_real(vReal, vWin , dSampFreq, overlap, fftlen, mat, dScaleTime, dScaleFreq );
	
		
		///Sandy 2006-8-25 pad half of window to the start and the end of the data
		//vector vPadded;
		//vPadded.SetSize(winlen + nSize);
		//vPadded.SetSubVector(vReal, winlen/2);
		//nRet = stft_real(vPadded, vWin , dSampFreq, overlap, fftlen, mat, dScaleTime, dScaleFreq );
		
	}
	else if(option == option_amp || option == option_ampdb)
	{
		om.SetInternalData(FSI_DOUBLE);///Sandy 2008-4-28 make sure the right data type is set when Change Parameters.
		matrix& matA = om.GetDataObject();
		matrix<complex> matC;
		nRet = stft_complex(ix, vWin , dSampFreq, overlap, fftlen, matC, matA, dScaleTime, dScaleFreq);
		
		///Sandy 2006-8-25 pad half of window to the start and the end of the data
		//vector<complex> vPadded;
		//vPadded.SetSize(winlen + nSize);		
		//vPadded.SetSubVector(ix, winlen/2);
		//nRet = stft_complex(vPadded, vWin , dSampFreq, overlap, fftlen, matC, matA, dScaleTime, dScaleFreq);
		
	}
	else
	{
		om.SetInternalData(FSI_COMPLEX);
		matrix<complex>& mat = om.GetDataObject();
		nRet = stft_complex(ix, vWin , dSampFreq, overlap, fftlen, mat, NULL, dScaleTime, dScaleFreq);
		
		///Sandy 2006-8-25 pad half of window to the start and the end of the data
		//vector<complex> vPadded;
		//vPadded.SetSize(winlen + nSize);	
		//vPadded.SetSubVector(ix, winlen/2);
		//nRet = stft_complex(vPadded, vWin , dSampFreq, overlap, fftlen, mat, NULL, dScaleTime, dScaleFreq, false);
	
	}
	
	
	if( 0 !=  nRet )
	{
		//XF_THROW_EX("Failed in stft, Error Code = %d", nRet);
		XF_THROW_EX(CER_UNKNOWN_ERROR_EX, nRet);
	}
	
	///Sandy Modify the coordinate to start from zero
	//om.SetXY(1, 1, dScaleTime, dScaleFreq);
	om.SetXY(0, 0, dScaleTime, dScaleFreq);
	if(swapxy)
	{
		if(option == option_complex)
		{
			matrix<complex>& mat = om.GetDataObject();
			mat.Transpose();
			om.SetXY(0, 0, dScaleFreq, dScaleTime);			
		}
		else
		{
			matrix& mat = om.GetDataObject();
			mat.Transpose();
			om.SetXY(0, 0, dScaleFreq, dScaleTime);
		}
	}
		
	//if(((option == option_amp ) || (option == option_ampdb)))
	//{
		//Matrix& Mat = om.GetDataObject();
		//Mat.SetXMin(0);
		//Mat.SetYMin(0);
		//Mat.SetXMax(dScaleTime);
		//Mat.SetYMax(dScaleFreq);
		
		if(option == option_ampdb)
		{
			Matrix& Mat = om.GetDataObject();
			vector vMat;
			Mat.GetAsVector(vMat);
			vMat = 20*log10(vMat);
			Mat.SetByVector(vMat);
		}
	
	//}
	
	//if(option == option_complex)
	//{
		//Matrix<complex>& Mat = om.GetDataObject();
		//Mat.SetXMin(0);
		//Mat.SetYMin(0);
		//Mat.SetXMax(dScaleTime);
		//Mat.SetYMax(dScaleFreq);		
	//}
	//
	if(plot)
	{
		/* ------Sandy 2008-10-22 use Folger's utils function to create graph, avoid create duplicate
		GraphPage gp;
		gp.Create("STFTSpectrogram");
		gp.SetLongName("STFT_Plot1");
		gp.Rename("STFT_Plot1");
		
		///Sandy 2007-5-8 NO_NEED_USING_2ND_opt
	//	page_load(gp, "STFTSpectrogram"); 
		///jsutin1
		//string strTemplate = "STFTSpectrogram";
		//if(swapxy)
		//{		
			//strTemplate = "STFTSpectrogram2";
		//}
		//page_load(gp, strTemplate); 		
		///jsutin2
		//---
		GraphLayer glay = gp.Layers();
		
		int nPlot = glay.AddPlot(om, IDM_PLOT_MATRIX_IMAGE );
		glay.Rescale();
		*/ 
		//---end of 2008-10-22
		
		GraphLayer glay;
		if(!xf_check_plot_output_matrix_in_graph(om, glay, 0, NULL, IDM_PLOT_MATRIX_IMAGE, "STFTSpectrogram") || !glay)
			error_report("Error happen when check image plot!");
		
		
		///Sandy 2007-5-8 ADD
		_update_gl_axes_labels(glay, swapxy);
		//---
		
	
	}
	
	
}

//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 stft_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return stft_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	///Justin 2007-04-26 COMMENT_THIS_FOR_EVENT1_IS_NOT_USED_FRO_PREVIEW_DIALOG
	/*
	if(nEventID > 0)
	{
		return false;
	
	}
	
	_update_grid_hide_show(trGetN);
	///justin 11/21/2006 REWRITE_AUTO_SAMPLING
	//int nRet = auto_compute_sampling_interval_from_InputData(trGetN);
	//if(nRet != -1 && nRet != 0)
	//{
		//XF_TRACE("Warning : Time sequences should be monotonic increase!");
	//}	
	//bOKEnable = (nRet == -1) ? false : true;	
	//auto_compute_params_value(trGetN, "fftlen", "winlen", "overlapp");
	strErrMsg = auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.interval);
	//END REWRITE_AUTO_SAMPLING
	*/
	///END COMMENT_THIS_FOR_EVENT1_IS_NOT_USED_FRO_PREVIEW_DIALOG
	return true;
	
	

}

int stft_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 stft_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_stft);
	
	if(-1 == nGetNDialog || 0 == nGetNDialog)//if(0 == nGetNDialog) //justin 11/21/2006 //temp solution
	{
		
		//string strInterval = trGetN.interval.strVal;
		//if(okutil_cvt_str_to_predefined_type(strInterval) == PDS_UNASSIGNED)
			//_update_sampling_interval_from_InputData(trGetN);
		
		///justin 11/21/2006 REWRITE_AUTO_SAMPLEING	
		//int nRet = auto_compute_sampling_interval_from_InputData(trGetN);
		//if(nRet != 0 && nRet != -1)
			//warning_msg_box(XFWAR_TIME_SEQ_INVALID, false);
		//double dInterval = trGetN.interval.dVal;
		//if(is_missing_value(dInterval))
			//nRet = XFEVT_ABORT;
		//auto_compute_params_value(trGetN, "fftlen", "winlen", "overlapp");
		///Justin 2007-03-23 CHECK_INTERVAL_IS_VALID
		//int nErr = auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.interval, false);
		
		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-21 for check input 
		string strErrMsg;
		if(!get_error_for_input_complex_vector(trGetN.ix, strErrMsg) )
		{
			nErr = XFERR_INVALID_RANGE;
		}
		//end
	
		/// END TEMP_COMMENT_SANDY_CHANGE_WHICH_WILL_POP_UP_DLG_ONCE_ERR_APPEAR
		
		if(CER_NO_ERROR == nErr)
		{
			auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.interval); 
			nErr = check_interval(trGetN.interval);
			strErrMsg = nErr;
		}
		//if(nErr)
		//{
			//XF_WARN(nErr);
			//nRet = XFEVT_ABORT;
		//}
		if(CER_NO_ERROR != nErr)
		{
			///Sandy 2008-8-29 XF called from LT should not pop up dialog as Max's attention
			/*
			//warning_msg_box(nErr, false, 'E');
			/// 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;				
			}			
		}
		///END CHECK_INTERVAL_IS_VALID
		
		///Sandy 2008-1-15 set auto value when run from script
		int nDataSize = _get_x_size(trGetN.ix);
		_auto_set_winlen(trGetN);
		_auto_set_overlap(trGetN, nDataSize);
	
		///end REWRITE_AUTO_SAMPLEING
	}
	
	///----Sandy 2008-10-20 always plot! talking with Max
	///Sandy 2007-8-20 disable plot when change param or autoupdate
	//if ((dwCntrl&LTXF_CHANGE_PARAM) || (dwCntrl&LTXF_FROM_AUTO_UPDATE))
	//{	
		//trGetN.plot.nVal = 0;	
	//}	
}
//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 stft_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

	

	//auto_compute_params_value(trGetN, "fftlen", "winlen", "overlapp");
	//_init_GetN_by_signal_size(trGetN); ///justin 2007-04-26 IMPROVE_STFT_AS_BETAT_TESTER_SUGGESTION
	_update_grid_hide_show(trGetN);
	//trGetN.option.nVal = option_ampdb;
	//int nSize = _get_x_size(trGetN.ix);
	//trGetN.fftlen.nVal = min(256, nSize);
	//trGetN.winlen.nVal = trGetN.fftlen.nVal;
	//trGetN.overlap.nVal = trGetN.winlen.nVal/2;
	
	bUpdateGrid = true;

	///justin 2007-04-26 IMPROVE_STFT_AS_BETAT_TESTER_SUGGESTION
	//int nDataSize = _get_x_size(trGetN.ix);
	//_auto_set_winlen(trGetN);
	//_auto_set_overlap(trGetN, nDataSize);
	
	///Justin 2007-05-25 MOVE_INITIAL_ERROR_INTO_ONINITGRAPH
	//int nErr = _check_fft_win_overlap_size(nDataSize, trGetN.fftlen.nVal, trGetN.winlen.nVal, trGetN.overlap.nVal);
	//if(nErr)
	//{
		//strErrMsg = nErr;	
		//bOKEnable = false;
		//return;
	//}
	////END MOVE_INITIAL_ERROR_INTO_ONINITGRAPH
	///END IMPROVE_STFT_AS_BETAT_TESTER_SUGGESTION
	
	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

	/////Sandy 2006-12-19 move from the bottom of this function for init graph whether the input is right
	//GraphPage gp = pgTemp;
	//
	/////Sandy 2007-5-8 NO_NEED_USING_2ND_opt
	//page_load(gp, "STFTSpectrogram"); 
	/////jsutin1
	////string strTemplate = "STFTSpectrogram";
	////if(trGetN.swapxy.nVal)
		////strTemplate = "STFTSpectrogram2";
	////DWORD 	dwClicks = 	NOCLICK_AXES|NOCLICK_DATA_PLOT|NOCLICK_LABEL|NOCLICK_BUTTONS|NOCLICK_LAYER|	NOCLICK_TICKLABEL|NOCLICK_LAYERICON|NOCLICK_WINDOW;	
	////page_load(gp, strTemplate, dwClicks); 		
	/////jsutin2
	////---
	//
	//if(! (bOKEnable = get_error_for_input_complex_vector(trGetN.ix, strErrMsg) ) )
		//return;
	//strErrMsg = auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.interval);
	//
	/////Justin 2007-05-25 MOVE_INITIAL_ERROR_INTO_ONINITGRAPH
	//int nDataSize = _get_x_size(trGetN.ix);
	//int nErr = _check_fft_win_overlap_size(nDataSize, trGetN.fftlen.nVal, trGetN.winlen.nVal, trGetN.overlap.nVal);
	//if(nErr)
	//{
		//strErrMsg = nErr;	
		//bOKEnable = false;
		//return;
	//}
	//////END MOVE_INITIAL_ERROR_INTO_ONINITGRAPH
	//
	////------------------ CPY 5/20/06 CHANGE_GETN_PREVIEW_TO_DATASHEET_FROM_WKSHEET
	//MatrixLayer ml = wksTemp;
	//
	/////justin 11/21/2006 REWRITE_AUTO_SAMPLING
	////int nRet = auto_compute_sampling_interval_from_InputData(trGetN);
	////if(nRet != -1 && nRet != 0)
	////{
		////strErrMsg = XFWAR_TIME_SEQ_INVALID;
	////}	
	////bOKEnable = (nRet == -1) ? false : true;	
	/////end REWRITE_AUTO_SAMPLING
	////auto_compute_params_value(trGetN, "fftlen", "winlen", "overlapp");
	//
	//int nRet = _run_stft_on_current_data(trGetN, pgTemp, ml);
	//if(nRet != CER_NO_ERROR )
	//{
		//strErrMsg = nRet;
		//bOKEnable = false;
		//return;
	//}
	//bUpdateGrid = true;
	//
	//MatrixObject om = ml.MatrixObjects(0);
	//
//
	//GraphLayer gl = gp.Layers(0);
	//gl.AddPlot(om, IDM_PLOT_MATRIX_IMAGE);
	//gl.Rescale();
	////------------------

	///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);
	///End CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL

	if(! (bOKEnable = get_error_for_input_complex_vector(trGetN.ix, strErrMsg) ) )
		return;

	///Sandy 2009-4-10 add sampleing interval checking when init dlg
	strErrMsg = auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.interval); 
	int nErr = check_interval(trGetN.interval);
	if(nErr)
	{
		strErrMsg = nErr;
		bOKEnable = false;
		return;
	}
	
}

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

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

	GraphPage gp = pgTemp;
	page_load(gp, "STFTSpectrogram"); 
	
	MatrixLayer ml = wksTemp;
	
	//int nRet =_run_stft_on_current_data(trGetN, pgTemp, ml);
	//if(nRet != CER_NO_ERROR )
	//{
		//return;
	//}
	
	//GraphPage gp = pgTemp;
	//GraphLayer gl = gp.Layers(0);
	MatrixObject om = ml.MatrixObjects(0);
	//GraphPage gp = pgTemp;
	
	///Sandy 2007-5-8 NO_NEED_USING_2ND_opt
	//page_load(gp, "STFTSpectrogram"); 
	///jsutin1
	//string strTemplate = "STFTSpectrogram";
	//if(trGetN.swapxy.nVal)
		//strTemplate = "STFTSpectrogram2";
	//DWORD 	dwClicks = 	NOCLICK_AXES|NOCLICK_DATA_PLOT|NOCLICK_LABEL|NOCLICK_BUTTONS|NOCLICK_LAYER|	NOCLICK_TICKLABEL|NOCLICK_LAYERICON|NOCLICK_WINDOW;	
	//page_load(gp, strTemplate, dwClicks); 		
	///jsutin2
	//------
	
	///Sandy 2007-7-23 move the compute part code to updateGraph
	int nRet =_run_stft_on_current_data(trGetN, pgTemp, ml);
	if(nRet != CER_NO_ERROR )
	{
		warning_msg_box(nRet, true);
//temp, waitting for error msg box
		return;
	}
	//end
	
	GraphLayer gl = gp.Layers(0);
	_update_gl_axes_labels(gl, trGetN.swapxy.nVal);
	
	if(0 < gl.AddPlot(om, IDM_PLOT_MATRIX_IMAGE))
		gl.Rescale();
	
	
	///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

	if(! (bOKEnable = get_error_for_input_complex_vector(trGetN.ix, strErrMsg) ) )
		return;

	///justin 2007-04-26 IMPROVE_STFT_AS_BETAT_TESTER_SUGGESTION
	/*
	if(!trNode.IsValid() || trNode.tagName == "ix")
	{
		//Sandy 2006-8-25 for initialize parameters of stft
		//int nSize = _get_x_size(trGetN.ix);
		//trGetN.fftlen.nVal = min(256, nSize);
		//trGetN.winlen.nVal = trGetN.fftlen.nVal;
		//trGetN.overlap.nVal = trGetN.winlen.nVal/2;
		
		_init_GetN_by_signal_size(trGetN);
		//auto_compute_params_value(trGetN, "fftlen", "winlen", "overlapp");
	}
	*/
	///END IMPROVE_STFT_AS_BETAT_TESTER_SUGGESTION
	
	///justin 11/21/2006 REWRITE_AUTO_SAMPLING
	//int nRet = auto_compute_sampling_interval_from_InputData(trGetN);
	//if(nRet != -1 && nRet != 0)
	//{
		//strErrMsg = XFWAR_TIME_SEQ_INVALID;
	//}	
	//bOKEnable = (nRet == -1) ? false : true;
	strErrMsg = auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.interval);
	///END REWRITE_AUTO_SAMPLING
	
	
	///Sandy 2007-8-20 remove this line since update is also needed when change theme.
	//if(trNode.IsValid() && trNode.tagName == "option")
	bool bIsOptionChange = (trNode.IsValid() && trNode.tagName == "option");
	_update_grid_hide_show(trGetN, false, bIsOptionChange);
	
	///justin 2007-04-26 IMPROVE_STFT_AS_BETAT_TESTER_SUGGESTION
	//else if(trNode.IsValid() && trNode.tagName == "winlen")
		//_update_grid_hide_show(trGetN, true);
	//else
		//_update_grid_hide_show(trGetN);	
	int nDataSize = _get_x_size(trGetN.ix);
		
	_auto_set_winlen(trGetN);
	_auto_set_overlap(trGetN, nDataSize);
	
	int nErr = _check_fft_win_overlap_size(nDataSize, trGetN.fftlen.nVal, trGetN.winlen.nVal, trGetN.overlap.nVal);
	if(nErr)
	{
		strErrMsg = nErr;	
		bOKEnable = false;
		return;
	}
	///END IMPROVE_STFT_AS_BETAT_TESTER_SUGGESTION
	
	///Sandy 2007-7-23 move out from _run_stft_on_current_data, since it should be check in on_change
	auto_compute_sampling_interval_from_InputData(trGetN.ix, trGetN.interval); 
	nErr = check_interval(trGetN.interval);
	if(nErr)
	{
		strErrMsg = nErr;
		bOKEnable = false;
		return;
	}
	

	bUpdateGraph = true;
	bUpdateGrid = true;
	
	///Sandy 2007-7-23 move the compute part code to updateGraph
	//MatrixLayer ml = wksTemp;
	//int nRet =_run_stft_on_current_data(trGetN, pgTemp, ml);
	//if(nRet != CER_NO_ERROR )
	//{
		//strErrMsg = nRet;
		//bUpdateGraph = false;
		//bOKEnable = false;
		//return;
	//}
	
	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)
{

	dwOptions = XFGSETUP_IMAGEGRAPH_CNTRL;//CPY 5/20/06 use image graph 
	
}

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

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

