#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	labels_direct_4,
	labels_direct_8,
	labels_direct_16,
};
enum{
	ystepby_inc,
	ystepby_int,
};
enum{
	orientation_from,
	orientation_to,
};
enum{
	stats_count,
	stats_freq,
};
//put additional include files here
#include <event_utils.h>
#include <report_utils.h>
#include <ReportTree.h>
#include <..\originlab\graph_utils.h> ///---Sim 09-11-2009 ADD_WIND_INFO_TEXT_OBJ
#include <..\originlab\grobj_utils.h> ///---Sim 09-11-2009 ADD_WIND_INFO_TEXT_OBJ
#include <o8dlg.h>		///------ Folger 10/29/09 XF_HELP_MAPPING_TO_ORIGIN_CHM

/// Iris 7/9/2009 CHANGE_PLOT_WINDROSE_XF_TO_PX_WAY
/// Iris 7/23/2009 REMOVE_YBIN_CONTROL_FROM_PLOT_WINDROSE
/// Iris 7/23/2009 ADD_CONTROL_TO_SPECIFY_DIRECTION_LABELS
/// Iris 7/24/2009 KEEP_SAME_AS_WRPLOT_TOOL
/// Iris 7/30/2009 SUPPORT_PREVIEW
/// Iris 7/30/2009 NO_NEED_SUPPORT_PERIODICAL_FOR_SPEED
//---- Iris 8/04/2009 NEED_AUTO_CHOOSE_X_WHEN_SEL_Y
/// iris 9/09/2009 ADD_WIND_INFO_TEXT_OBJ
/// Sim 09-11-2009 ADD_WIND_INFO_TEXT_OBJ
/// Sim 09-11-2009 QA81-14287 WIND_ROSE_NEED_INCLUDE_SEPARATE_BIN_FOR_MIN
/// Iris 9/16/2009 IMPROVE_WINDINFO_TEXT_OBJ_POSITION
/// Folger 10/29/09 XF_HELP_MAPPING_TO_ORIGIN_CHM
/// Kyle 06/30/2010 ORG-209 EXPAND_2D_BINNING_TO_SUPPORT_ADDITIONAL_Y_COLUMN
///	Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
/// Jasmine 10/29/2010 ORG-1367-P1 SET_NOCLICK_BIT_FOR_PREVIEW

//put your own support static functions here
enum
{
	RANGE_X = 0,
	RANGE_Y
};
/// Iris 7/23/2009 REMOVE_YBIN_CONTROL_FROM_PLOT_WINDROSE
enum
{
	BIN_CENTER = 0,
	BIN_END
};
///end REMOVE_YBIN_CONTROL_FROM_PLOT_WINDROSE

/// Iris 7/23/2009 ADD_CONTROL_TO_SPECIFY_DIRECTION_LABELS
#define STR_4_DIRECTIONS_LABELS 	"N \"\" \"\" \"\" E \"\" \"\" \"\" S \"\" \"\" \"\" W"
#define STR_8_DIRECTIONS_LABELS 	"N \"\" NE \"\" E \"\" SE \"\" S \"\" SW \"\" W \"\" NW"
#define STR_16_DIRECTIONS_LABELS 	"N NNE NE ENE E ESE SE SSE S SSW SW WSW W WNW NW NNW"
///end ADD_CONTROL_TO_SPECIFY_DIRECTION_LABELS

/// Iris 7/9/2009 CHANGE_PLOT_WINDROSE_XF_TO_PX_WAY, no need for new way plotting
//#define WINDROSE_PLOT_ID 			100 
//#define STR_WINDROSE_TAMPLATE		"WindRose"
///end CHANGE_PLOT_WINDROSE_XF_TO_PX_WAY

#define DIRECTION_PERIOD			360

/// Iris 7/30/2009 SUPPORT_PREVIEW
#define STR_TEMPLATE_WINDROSE_BIN_DATA		"WindRose"
#define STR_TEMPLATE_WINDROSE_RAW_DATA		"WindRoseRaw"
///end SUPPORT_PREVIEW

///---Sim 09-11-2009 QA81-14287 WIND_ROSE_NEED_INCLUDE_SEPARATE_BIN_FOR_MIN
#define OUT_Y_MIN 1
#define INC_Y_MIN 1
#define HAS_CALM ( OUT_Y_MIN && INC_Y_MIN )
///---END QA81-14287 WIND_ROSE_NEED_INCLUDE_SEPARATE_BIN_FOR_MIN

#define		STR_DIRECT_WIND			_L("Direction Wind")
#define		STR_FLOW_VECTOR_WIND	_L("Flow Vector Wind")
#define		STR_CALMS				_L("Calms")

/// Iris 7/9/2009 CHANGE_PLOT_WINDROSE_XF_TO_PX_WAY
BOOL	plot_windrose_CreatePlots(GraphLayer& gl, DataRange& dr, TreeNode& trGetN, BOOL bFromAutoUpdate)
{
	return _plot_windrose_CreatePlots(STR_TEMPLATE_WINDROSE_RAW_DATA, gl, dr, trGetN, bFromAutoUpdate, true, false);
}

static BOOL _plot_windrose_CreatePlots(	LPCSTR lpcszTemplate, GraphLayer& gl, DataRange& dr, TreeNode& trGetN, 
										BOOL bFromAutoUpdate, BOOL bKeepFormat,
										BOOL bPreview)///Jasmine 10/29/2010 ORG-1367-P1 SET_NOCLICK_BIT_FOR_PREVIEW
{	
	if( !gl )
		return FALSE;
	
	Tree trFormat;
	if( bFromAutoUpdate )
	{
		if( bKeepFormat ) //Iris, introduce this argument to temp fix after apply original format, colormap list moved up, and this is very obvious in preview.
			trFormat = gl.GetFormat(FPB_ALL, FOB_ALL, TRUE, TRUE); // remember the settings(include color map) for each plotting and apply after remove all and replot.
		
		GraphPage gp = gl.GetPage();
		///Jasmine 10/29/2010 ORG-1367-P1 SET_NOCLICK_BIT_FOR_PREVIEW, it also runs in here to do preview plotting so I add bPreview
		if(bPreview)
			page_load(gp, lpcszTemplate, OC_PREVIEW_NOCLICK_NOZOOMPAN);
		else
			gp.LoadTemplate(lpcszTemplate);
		///End SET_NOCLICK_BIT_FOR_PREVIEW
		if( !gl ) // gl will be invalid after load template
			gl = gp.Layers();
	}

	Worksheet	wks;
	int			c1, c2;
	dr.GetRange(wks, c1, c2, 1);
	if ( !wks )
	{
		ASSERT(false);
		return FALSE;
	}
	
	int nLastCol = wks.GetNumCols() - 1;
	int nXColIndex = 0;
	int nYColFrom = 1;
	int nYColTo = trGetN.subcount.nVal? nLastCol - 2 : nLastCol;
	///---Sim 09-11-2009 QA81-14287 WIND_ROSE_NEED_INCLUDE_SEPARATE_BIN_FOR_MIN
	if ( HAS_CALM )
		nYColTo--;
	///---END QA81-14287 WIND_ROSE_NEED_INCLUDE_SEPARATE_BIN_FOR_MIN
	
	if( nYColFrom >= wks.GetNumCols() || nYColTo >= wks.GetNumCols() ) 
		return false;
	
	DataRange 	drPlot;
	drPlot.Add(wks, nXColIndex, "X");
	drPlot.Add(wks, nYColFrom, "Y", nYColTo);
	
	int nPlot = gl.AddPlot(drPlot, IDM_PLOT_COLUMN_STACK);
	
	// after plotting
	if( nPlot >= 0 )
	{	
		if( bFromAutoUpdate )
		{
			if( bKeepFormat )
			{
				bool bRet = gl.ApplyFormat(trFormat, true, true);
				ASSERT( bRet );
			}
		}
		
		gl.Rescale();	
		_set_plot_axis_label(gl, trGetN.labels.nVal);  /// Iris 7/23/2009 ADD_CONTROL_TO_SPECIFY_DIRECTION_LABELS		
		///---Sim 09-11-2009 QA81-14287 ADD_WIND_INFO_TEXT_OBJ
		//_update_wind_info_text(gl, trGetN); /// Iris 9/09/2009 ADD_WIND_INFO_TEXT_OBJ
		if ( HAS_CALM )
		{
			string strCalmValue;
			strCalmValue.Format("%%(%s, %s, 1, *)", wks_get_book_sheet_name(wks), _L("Calm"));
			_update_wind_info_text(gl, trGetN, strCalmValue); /// Iris 9/09/2009 ADD_WIND_INFO_TEXT_OBJ
		}
		///---END QA81-14287 ADD_WIND_INFO_TEXT_OBJ
	}
		
	return TRUE;
}
///end CHANGE_PLOT_WINDROSE_XF_TO_PX_WAY

/// Iris 7/30/2009 NO_NEED_SUPPORT_PERIODICAL_FOR_SPEED
//static double _get_preiod(double dMin, double dMax)
//{
	//return dMin < dMax? dMax - dMin : NANUM;
//}
///end NO_NEED_SUPPORT_PERIODICAL_FOR_SPEED

static void _check_input(TreeNode& trGetN, string& strErrMsg, DWORD& dwEnables)
{
	bool bOKEnable = dwEnables & GETNGEVT_OK_ENABLE;
	if( !strErrMsg.IsEmpty() || !bOKEnable )
		return;
	
	//---- Iris 8/04/2009 NEED_AUTO_CHOOSE_X_WHEN_SEL_Y
	/*
	if( trGetN.iy.IsEmpty() )
		return XFERR_INVALID_RANGE;
	
	DataRange dr;
	dr.Add("Range1", trGetN.iy.strVal);
	if( dr.GetNumRanges() != 2 )
		return XFERR_INVALID_RANGE;
	*/
	XYRange xy;
	xy.Create(trGetN.iy.Range1);
	vector vx, vy;
	if( 1 != xy.GetNumData(DRR_GET_DEPENDENT) || !xy.GetData(vy, vx) || 0 == vy.GetSize() )
	{
		strErrMsg = XFERR_INVALID_RANGE;
		bOKEnable = false;
	}
	//----
	
	if( strErrMsg.IsEmpty() && vx.GetSize() > 0 && vy.GetSize() > 0 )
	{
		vx.Sort();
		vy.Sort();
		if( vx[0] < 0 || vy[0] < 0 )
		{
			strErrMsg = XFERR_INPUT_CANNOT_INCLUDE_NEGATIVE;
			bOKEnable = false;
		}
	}
	
	if( bOKEnable )
		dwEnables |= GETNGEVT_OK_ENABLE;
	else
		dwEnables &= ~GETNGEVT_OK_ENABLE;
	
	/// Iris 7/30/2009 NO_NEED_SUPPORT_PERIODICAL_FOR_SPEED
	//if( !_check_min_max(trGetN.ymin.dVal, trGetN.ymax.dVal, _get_preiod(trGetN.ymin.dVal, trGetN.ymax.dVal)) )
		//return XFERR_BINNING_CROSS_PERIOD_BOUNDARY;
	///end NO_NEED_SUPPORT_PERIODICAL_FOR_SPEED	
}

static bool _check_min_max(double dMin, double dMax, double dPreiod)
{
	if(dMin >= dMax)
		return false;
	
	if((dMax-dMin) > dPreiod)
		return false;
	return true;
}

static void _init_GetN(TreeNode& trGetN)
{
	init_two_binning_tree_show(trGetN);
	if( trGetN.ymin.dVal < 0 )
		trGetN.ymin.dVal = 0;
	
	/// Iris 8/05/2009 FIX_MISS_ONE_BIN_IN_TWODBINNING	
	// should dynamicly set xinc and xmax depend on xintervals
	//trGetN.xinc.dVal = ( trGetN.xmax.dVal - trGetN.xmin.dVal ) / (trGetN.xintervals.nVal - 1);	
	trGetN.xmin.dVal = 0;
	trGetN.xinc.dVal = 360 / (double)trGetN.xintervals.nVal;
	trGetN.xmax.dVal = trGetN.xinc.dVal * (double)(trGetN.xintervals.nVal - 1);
	///end FIX_MISS_ONE_BIN_IN_TWODBINNING
}

/// Iris 9/09/2009 ADD_WIND_INFO_TEXT_OBJ
///---Sim 09-11-2009 QA81-14287 ADD_WIND_INFO_TEXT_OBJ
//static void _update_wind_info_text(GraphLayer& gl, TreeNode& trGetN)
static void _update_wind_info_text(GraphLayer& gl, TreeNode& trGetN, LPCSTR lpcszCalmValue)
///---END QA81-14287 ADD_WIND_INFO_TEXT_OBJ
{
	const string strName = "WindInfo";
	GraphObject goText = gl.GraphObjects(strName);
	if( !goText )
	{
		/// Iris 9/16/2009 IMPROVE_WINDINFO_TEXT_OBJ_POSITION, has added WindInfo text object to template with good position.
		//goText = gl.CreateGraphObject(GROT_TEXT, strName);
		return;
		///end IMPROVE_WINDINFO_TEXT_OBJ_POSITION
	}	

	///---Sim 09-11-2009 ADD_WIND_INFO_TEXT_OBJ
	goText.Attach = 0; // to layer
	///---END ADD_WIND_INFO_TEXT_OBJ
	
	string strText;		
	///---Sim 09-11-2009 QA81-14287 ADD_WIND_INFO_TEXT_OBJ
	//strText += "Calms:" + " 0%";
	strText += STR_CALMS + ": " + lpcszCalmValue;
	///---END QA81-14287 ADD_WIND_INFO_TEXT_OBJ
	
	string strDirection = orientation_from == trGetN.orientation.nVal? STR_DIRECT_WIND : STR_FLOW_VECTOR_WIND;
	strText += "\r\n" + strDirection;
	
	goText.Text = strText;	
	set_text_link_LT_var(goText, true); ///---Sim 09-11-2009 ADD_WIND_INFO_TEXT_OBJ
	
	/// Iris 9/16/2009 IMPROVE_WINDINFO_TEXT_OBJ_POSITION, has added WindInfo text object to template with good position.
	/////---Sim 09-11-2009 ADD_WIND_INFO_TEXT_OBJ
	///*
	//// adjust position according to legend
	//GraphObject goLegend = gl.GraphObjects("Legend");
	//ASSERT(goLegend);
	//if( goLegend )
	//{
		//goText.Left = goLegend.Left;
		//int nEdge = goText.Height;
		//goText.Top = goLegend.Top + goLegend.Height + nEdge;
	//}
	//*/
	//double arrPos[TOTAL_POS];
	//int nUnit = gl.GetPosition(arrPos);
	//gl.UnitsConvert(M_INCH, arrPos, nUnit);
	//double dLayerRight = arrPos[LEFT_POS] + arrPos[WIDTH_POS];
	//double dLayerBottom = arrPos[TOP_POS] + arrPos[HEIGHT_POS];
	//
	////double dTextLeft, dTextTop, dTextRight, dTextBottom;
	////rect_get_position(goText, dTextLeft, dTextTop, dTextRight, dTextBottom, UNITS_INCH);
	//
	//double dEdge = 0.5;
	////rect_move(goText, dLayerRight + nEdge, dLayerBottom - (dTextBottom - dTextTop), UNITS_INCH);
	//rect_move(goText, dLayerRight + dEdge, dLayerBottom, UNITS_INCH);
	/////---END ADD_WIND_INFO_TEXT_OBJ
	///end IMPROVE_WINDINFO_TEXT_OBJ_POSITION
		
}
///end ADD_WIND_INFO_TEXT_OBJ

/// Iris 7/23/2009 ADD_CONTROL_TO_SPECIFY_DIRECTION_LABELS
static bool _set_plot_axis_label(GraphLayer& gl, int nLabelOption)
{
	if( !gl )
		return false;
	
	string strLabels = _get_direction_labels(nLabelOption);
	if( strLabels.IsEmpty() )
		return false;
	
	Tree trFormat;
	trFormat = gl.GetFormat(FPB_ALL, FOB_AXIS_LABELS, true, true);
	
	TreeNode trLabels = trFormat.Root.Axes.X.Labels.TopLabels.String;
	if( trLabels )
	{
		trLabels.strVal = strLabels;
		return gl.ApplyFormat(trFormat, true, true);	
	}	
	return false;
}

string _get_direction_labels(int nLabels)
{
	string strLabels;
	
	switch(nLabels)
	{
	case labels_direct_4:
		strLabels = STR_4_DIRECTIONS_LABELS;
		break;
	case labels_direct_8:
		strLabels = STR_8_DIRECTIONS_LABELS;
		break;
	case labels_direct_16:
		strLabels = STR_16_DIRECTIONS_LABELS;
		break;
	default:
		ASSERT(0);
		break;
	}
	return strLabels;	
}
///end ADD_CONTROL_TO_SPECIFY_DIRECTION_LABELS

/// Iris 7/30/2009 SUPPORT_PREVIEW
static bool _update_preview(PageBase& pgTemp, Datasheet& datasheet, TreeNode& trGetN, bool bInit)
{	
	Worksheet wksBin(datasheet);	
	GraphPage gp(pgTemp);
	if( !wksBin || !gp )
	{
		ASSERT(0);
		return false;	
	}
	
	// ralculate and update bin result to template worksheet
	Tree tr;
	ReportData rd;
	rd = tr.AddNode("BinData");
	
	//---- Iris 8/04/2009 NEED_AUTO_CHOOSE_X_WHEN_SEL_Y
	//DataRange drIn;
	//TreeNode triy = trGetN.iy;
	//okxf_resolve_tree_construct_range(&triy, &drIn);
	XYRange drIn;
	drIn.Create(trGetN.iy.Range1);
	vector vx, vy;
	if( !drIn.GetData(vy, vx, NULL) || 0 == vx.GetSize() || 0 == vy.GetSize() )
	{
		return false;
	}
	//----
	
	double dxInc = ( trGetN.xmax.dVal - trGetN.xmin.dVal ) / (trGetN.xintervals.nVal - 1);
	_report_data_add_bin_data(drIn, rd, trGetN.stats.nVal, trGetN.xmin.dVal, trGetN.xmax.dVal, dxInc, trGetN.xintervals.nVal, 
							trGetN.ymin.dVal, trGetN.ymax.dVal, trGetN.yinc.dVal, trGetN.ystepby.nVal, trGetN.yintervals.nVal, 
							trGetN.subcount.nVal, trGetN.orientation.nVal);
	
	wksBin.SetSize(-1, 0);
	foreach(TreeNode trCol in rd.FirstNode.Children)
	{
		Column col(wksBin, wksBin.AddCol());
		
		int nColType;
		if( trCol.GetAttribute(STR_COL_DESIGNATION_ATTRIB, nColType) )
			col.SetType( nColType );
		
		string strComment;
		if( trCol.GetAttribute(STR_COMMENT_ATTRIB, strComment) )
			col.SetComments( strComment );
		
		vector& vv = col.GetDataObject();
		vv = trCol.dVals;		
	}
	
	// update graph
	DataRange drBin;
	drBin.Add(); // add an emtpy range since in plot_windrose_CreatePlots always pick the second range to plot windrose
	drBin.Add(wksBin, 0, "Range1", -1);
	
	if( bInit )
	{
		///Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
		//gp.LoadTemplate(STR_TEMPLATE_WINDROSE_BIN_DATA);
		page_load(gp, STR_TEMPLATE_WINDROSE_BIN_DATA, OC_PREVIEW_NOCLICK_NOZOOMPAN);
		///End CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
	}
		
	GraphLayer gl = gp.Layers();
	
	return _plot_windrose_CreatePlots(STR_TEMPLATE_WINDROSE_BIN_DATA, gl, drBin, trGetN, !bInit, false, true);	
}

//---- Iris 8/04/2009 NEED_AUTO_CHOOSE_X_WHEN_SEL_Y
//static void _report_data_add_bin_data(DataRange& iy, ReportData& rd, int stats, 
static void _report_data_add_bin_data(XYRange& dr, ReportData& rd, int stats, 
//----
double xmin, double xmax, double xinc, double xintervals, double ymin, double ymax, double yinc, double ystepby, double yintervals,
int subcount, int orientation)
{
	// check and get input data
	//---- Iris 8/04/2009 NEED_AUTO_CHOOSE_X_WHEN_SEL_Y
	/*
	XYRange dr(iy);
	if(!dr.IsValid())
	{
		XF_THROW(XFERR_FAILED_GET_RANGE);
	}	
	*/
	//---- 
	
	int nStats = -1;
	switch(stats)
	{
	case stats_count:
		nStats = two_d_stats_count;
		break;
	case stats_freq:
		nStats = two_d_stats_freq;
		break;
	default:
		ASSERT(0);
		return;
	}
	
	// calcuate and report data
	/// Iris 7/24/2009 KEEP_SAME_AS_WRPLOT_TOOL
	//int		xbin = BIN_END;
	int		xbin = BIN_CENTER;
	///end KEEP_SAME_AS_WRPLOT_TOOL
	int		ybin = BIN_END; /// Iris 7/23/2009 REMOVE_YBIN_CONTROL_FROM_PLOT_WINDROSE	
	int 	xstepby = 1;
	/// Iris 7/30/2009 NO_NEED_SUPPORT_PERIODICAL_FOR_SPEED
	//int 	xperiodical = 1, yperiodical = 1;
	//double 	xperiod = DIRECTION_PERIOD, yperiod = _get_preiod(ymin, ymax);
	int 	xperiodical = 1, yperiodical = 0;
	double 	xperiod = DIRECTION_PERIOD, yperiod = -1;
	///end NO_NEED_SUPPORT_PERIODICAL_FOR_SPEED
	///---Sim 09-11-2009 QA81-14287 WIND_ROSE_NEED_INCLUDE_SEPARATE_BIN_FOR_MIN
	//int 	xoutleft = 0, xoutright = 0, youtleft = 0, youtright = 1;
	int 	xoutleft = 0, xoutright = 0, youtleft = OUT_Y_MIN, youtright = 1;
	int 	xincludemin = 0, xincludemax = 0, yincludemin = INC_Y_MIN, yincludemax = 0;
	///---END QA81-14287 WIND_ROSE_NEED_INCLUDE_SEPARATE_BIN_FOR_MIN
	int 	xorder = 0, yorder = 0;
	
	///Kyle 06/30/2010 ORG-209 EXPAND_2D_BINNING_TO_SUPPORT_ADDITIONAL_Y_COLUMN
	//report_2d_binning(rd, dr, 
	//					xbin, xmin, xmax, xstepby, xinc, xintervals, xperiodical, xperiod, xoutleft, xoutright, xorder,
	//					ybin, ymin, ymax, ystepby, yinc, yintervals, yperiodical, yperiod, youtleft, youtright, yorder, 
	//					///---Sim 09-11-2009 QA81-14287 WIND_ROSE_NEED_INCLUDE_SEPARATE_BIN_FOR_MIN
	//					//nStats, subcount, NULL, orientation);	
	//					nStats, subcount, NULL, orientation, xincludemin, xincludemax, yincludemin, yincludemax);	
	//					///---END QA81-14287 WIND_ROSE_NEED_INCLUDE_SEPARATE_BIN_FOR_MIN
	report_2d_binning(rd, dr, NULL,
						xbin, xmin, xmax, xstepby, xinc, xintervals, xperiodical, xperiod, xoutleft, xoutright, xorder,
						ybin, ymin, ymax, ystepby, yinc, yintervals, yperiodical, yperiod, youtleft, youtright, yorder, 
						nStats, subcount, NULL, orientation, xincludemin, xincludemax, yincludemin, yincludemax);
	///End EXPAND_2D_BINNING_TO_SUPPORT_ADDITIONAL_Y_COLUMN
}

static void _grid_event(TreeNode& trGetN, string& strErrMsg, DWORD& dwEnables)
{
	_init_GetN(trGetN);
	
	/// Iris 8/10/2009 UPDATE_INPUT_RANGE_TREE_LABEL
	_grid_set_input_range_labels(trGetN);
	///end UPDATE_INPUT_RANGE_TREE_LABEL

	trGetN.xintervals.Enable = 1;		
	trGetN.yintervals.Enable = ENABLE_READ_ONLY;	
	
	_check_input(trGetN, strErrMsg, dwEnables);
}
///END SUPPORT_PREVIEW

/// Iris 8/10/2009 UPDATE_INPUT_RANGE_TREE_LABEL
static void _grid_set_input_range_labels(TreeNode& trGetN)
{
	TreeNode trRange;
	if( trGetN.iy.Range1 )
		trRange = trGetN.iy.Range1;
	else
		trRange = trGetN.iy;	
	trRange.SetAttribute(STR_LABEL_ATTRIB, "Wind");
	trRange.X.SetAttribute(STR_LABEL_ATTRIB, "Wind Direction");
	trRange.Y.SetAttribute(STR_LABEL_ATTRIB, "Wind Speed");
}
/// end UPDATE_INPUT_RANGE_TREE_LABEL


void plot_windrose(const XYRange& iy, const double& xmin, const double& xmax, const double& xinc, const int& xintervals, const int& labels, const double& ymin, const double& ymax, const int& ystepby, const double& yinc, const int& yintervals, const int& orientation, const int& stats, const int& subcount, ReportData& rd)
{
	
	/// Iris 7/30/2009 SUPPORT_PREVIEW
	/*
	// check and get input data
	XYRange dr(iy);
	if(!dr.IsValid())
	{
		XF_THROW(XFERR_FAILED_GET_RANGE);
	}	
	
	int nStats = -1;
	switch(stats)
	{
	case stats_count:
		nStats = two_d_stats_count;
		break;
	case stats_freq:
		nStats = two_d_stats_freq;
		break;
	default:
		ASSERT(0);
		return;
	}
	
	// calcuate and report data
	/// Iris 7/24/2009 KEEP_SAME_AS_WRPLOT_TOOL
	//int		xbin = BIN_END;
	int		xbin = BIN_CENTER;
	///end KEEP_SAME_AS_WRPLOT_TOOL
	int		ybin = BIN_END; /// Iris 7/23/2009 REMOVE_YBIN_CONTROL_FROM_PLOT_WINDROSE	
	int 	xstepby = 1;
	int 	xperiodical = 1, yperiodical = 0;
	double 	xperiod = DIRECTION_PERIOD, yperiod = _get_preiod(ymin, ymax);
	int 	xoutleft = 0, xoutright = 0, youtleft = 0, youtright = 1;
	int 	xorder = 0, yorder = 0;
	
	report_2d_binning(rd, dr, 
						xbin, xmin, xmax, xstepby, xinc, xintervals, xperiodical, xperiod, xoutleft, xoutright, xorder,
						ybin, ymin, ymax, ystepby, yinc, yintervals, yperiodical, yperiod, youtleft, youtright, yorder, 
						nStats, subcount, NULL, orientation);
	*/
	_report_data_add_bin_data(iy, rd, stats, xmin, xmax, xinc, xintervals, ymin, ymax, yinc, ystepby, yintervals, subcount, orientation);
	///END SUPPORT_PREVIEW
	
	
	/// Iris 7/9/2009 CHANGE_PLOT_WINDROSE_XF_TO_PX_WAY
	/*
	// plotting
	XFExeContext* pxfexectxt = Project.GetCurrentXFExeCtxt();
	if(!pxfexectxt)
		XF_THROW(CER_UNKNOWN_ERROR);
	
	GraphPage gp;
	gp = pxfexectxt->GetGraph(WINDROSE_PLOT_ID);	
	if( !gp )
	{
		gp.Create(STR_WINDROSE_TAMPLATE);
	}
	else
	{
		GraphLayer gl = gp.Layers();
		while( gl.RemovePlot(0) );
		
	}
	
	Worksheet wksOut;
	if( rd.GetWorksheet(wksOut) )
	{		
		vector<int> vnIDYs;
		vnIDYs.Data(TWO_D_BINNING_Y_BEGIN, TWO_D_BINNING_Y_BEGIN + yintervals, 1);
		
		DataRange 	drPlot;
		if( rd.GetDataRange(drPlot, TWO_D_BINNING_REPORT_TABLE, TWO_D_BINNING_X, vnIDYs, vnIDYs.GetSize()) )
		{
			GraphLayer gl = gp.Layers();
			int nPlot = gl.AddPlot(drPlot, IDM_PLOT_COLUMN_STACK);
			if( nPlot >= 0 )
				gl.Rescale();
		}
	
	}
	pxfexectxt->SetGraph(gp, WINDROSE_PLOT_ID);
	*/
	///end CHANGE_PLOT_WINDROSE_XF_TO_PX_WAY
	
	
}

//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 plot_windrose_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return plot_windrose_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	/// Iris 7/30/2009 SUPPORT_PREVIEW
	/*
	_init_GetN(trGetN);
	
	trGetN.xintervals.Enable = 1;		
	trGetN.yintervals.Enable = ENABLE_READ_ONLY;	
	
	int nErr = _check_input(trGetN);
	if( nErr != CER_NO_ERROR)
	{
		strErrMsg = nErr;
		bOKEnable = false;
	}
	*/
	///end SUPPORT_PREVIEW
	return false;

}

int plot_windrose_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 plot_windrose_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	
	///------ Folger 10/29/09 XF_HELP_MAPPING_TO_ORIGIN_CHM
	if ( is_xf_startup(nGetNDialog, dwCntrl) )
	{
		trGetN.SetAttribute(STR_HELPID_ATTRIB, IDD_XF_plot_windrose);
	}
	///------ End XF_HELP_MAPPING_TO_ORIGIN_CHM
	
	if(0 == nGetNDialog || -1 == nGetNDialog)
	{
		_init_GetN(trGetN); 
	}	
	
}
//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 plot_windrose_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
	
	/// Iris 7/30/2009 SUPPORT_PREVIEW
	_grid_event(trGetN, strErrMsg, dwEnables); 
	///end SUPPORT_PREVIEW
	
	dwUpdateGrid = UPDATE_GRID_RESET; // changed label in _grid_event	
	bUpdateGraph = strErrMsg.IsEmpty(); 	/// Iris 8/10/2009 ADD_AUTO_PREVIEW_CHECKBOX
	
}

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

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

	/// Iris 7/30/2009 SUPPORT_PREVIEW
	_check_input(trGetN, strErrMsg, dwEnables);
	
	/// Iris 8/10/2009 ADD_AUTO_PREVIEW_CHECKBOX
	/*
	if( !strErrMsg.IsEmpty() )		
		return;	
	_update_preview(pgTemp, wksTemp, trGetN, true);
	*/
	///Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
	//GraphPage gp = pgTemp;
	//page_load(gp, "NonePreview");
	//load_text_for_nonepreview_graphpage(gp, TEMPLATE_NONE_PREVIEW_CONTENT, TEMPLATE_NONE_PREVIEW_HINTS);
	xf_load_nopreview(pgTemp);
	///End CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
	///end ADD_AUTO_PREVIEW_CHECKBOX
	///END SUPPORT_PREVIEW
	
}

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

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

	/// Iris 7/30/2009 SUPPORT_PREVIEW
	_update_preview(pgTemp, wksTemp, trGetN, false);
	///END SUPPORT_PREVIEW

	
}

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

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

	/// Iris 7/30/2009 SUPPORT_PREVIEW
	_grid_event(trGetN, strErrMsg, dwEnables); 
	dwUpdateGrid = UPDATE_GRID_RESET; // changed label in _grid_event	
	
	if( trNode && 0 == strcmp(trNode.tagName, "subcount") )
	{
		// no need update preview
	}
	else
	{
		dwUpdateGraph = UPDATE_GRAPH_CHANGED;
	}
	///end SUPPORT_PREVIEW
	
}

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

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

