#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	plottype_line,
	plottype_scatter,
	plottype_linesymb,
	plottype_column,
};

//put additional include files here
#include <event_utils.h>
#include <..\Originlab\WksColLabels.h>
#include <..\Originlab\graph_utils.h>

/*------------------------------------------------------------------------------*
 * Modification Log:															*
 *	Jasmine 10/15/09 QA81-14321 SAVE_SPACING_SETTING_FOR_ARRANGEMENT			*
 *	Folger 11/06/09 SHARE_CODE_WITH_NEW_CLASS_MultipleXYRangesWksCommonLabelHelper
 *	Kenny 12/10/2009 QA81-14182-P1 PLOT_BY_LABEL_NEED_IMPROVE_ERROR_CHECKING_RUN_FROM_SCRIPT*
 *	Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL	*
*-------------------------------------------------------------------------------*/

//put your own global variables here
static string	s_strErrMsg		= "";

//put your own support static functions here

#define	STR_TEMPLATE_PLOT_BY_LABEL	"mgroups"
#define STR_ATTRIB_GROUPS_COUNT		"GroupsCount"
#define STR_ATTRIB_LABEL_TYPES		"LabelTypes"
#define	ITEM_SEPARATOR				'|'
#define	STR_ITEM_SEPARATOR			"|"
#define	STR_EMPTY_COMBO				(" " STR_ITEM_SEPARATOR)
///Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
//#define	PREVIEW_GRAPH_NOCLICKS		(NOCLICK_WINDOW | NOCLICK_LABEL | NOCLICK_DATA_PLOT | NOCLICK_TICKLABEL | NOCLICK_LAYER | NOCLICK_LAYERICON | NOCLICK_AXES | NOCLICK_BUTTONS)
#define	PREVIEW_GRAPH_NOCLICKS		(OC_PREVIEW_NOCLICK_NOZOOMPAN | NOCLICK_WINDOW | NOCLICK_LABEL | NOCLICK_BUTTONS)
///End CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL

#define IS_USER_DEFINED_LABEL(_type)	(_type >= RCLT_UDL)

/*----------------------------------------------------------------------------*/
/* class PlotByLabelHelper
/*----------------------------------------------------------------------------*/

class PlotByLabelHelper
{
public:
	XYRange			m_XYRange;
	GraphPage		m_gp;
	int				m_nLayerRows;
	int				m_nLayerCols;
	string			m_strLabelName;
	int				m_nLabelType;
	
	bool			m_bIsPreviewing;
protected:
	int				m_nPlotType;
private:
	vector<string>	m_vsGroupsLabels;
public:
	PlotByLabelHelper(
		bool bIsPreviewing = false,
		const XYRange& iy = NULL, 
		int nGUIPlotType = 0, 
		PageBase& pgTemp = NULL
		)
	{
		m_bIsPreviewing = bIsPreviewing;
		m_gp = pgTemp;
		m_XYRange = iy;
		SetPlotType(nGUIPlotType);
		m_nLayerRows = 1;
		m_nLayerCols = 1;
		///Kenny 12/10/2009 QA81-14182-P1 PLOT_BY_LABEL_NEED_IMPROVE_ERROR_CHECKING_RUN_FROM_SCRIPT
		//m_nLabelType = -1;
		m_nLabelType = RCLT_INVALID;
		///End QA81-14182-P1 PLOT_BY_LABEL_NEED_IMPROVE_ERROR_CHECKING_RUN_FROM_SCRIPT
	}
public:
	BOOL Perform()
	{
		// Init
		if ( !Init() )
		{
			ASSERT(FALSE);
			return FALSE;
		}

		int nRangeNum = 0;
		if ( !m_XYRange || (nRangeNum = m_XYRange.GetNumData(DRR_GET_DEPENDENT)) <= 0 )
		{
			XF_THROW(CER_INVALID_RANGE);
			return FALSE;
		}
		// Do the plotting.
		for(int ii = 0; ii < nRangeNum; ii++)
		{
			DataRange dr;
			m_XYRange.GetSubRange(dr, DRR_GET_DEPENDENT | DRR_NO_FACTORS, ii);
			
			int nLayerIndex = GetNextLayerIndex(ii);
			BOOL bRet = DoNextPlot(dr, nLayerIndex);
		}
		
		foreach(GraphLayer gl in m_gp.Layers)
		{
			UpdateYAxisTitle(gl);
			legend_update(gl, ALM_COMMENT, true, true);
			// Group all the plots
			const int nPlotCount = gl.DataPlots.Count();
			if ( 1 == nPlotCount )
			{
				if ( IDM_PLOT_COLUMN == m_nPlotType )
				{
					// Column type plot should be updated to use Red Fill color by default 
					// when there is only one plot in one layer
					DataPlot dp = gl.DataPlots(0);
					Tree trFormat;
					trFormat.Root.Pattern.Fill.FillColor.nVal = SYSCOLOR_RED;
					int nErr = dp.UpdateThemeIDs(trFormat.Root);
					if(0 == nErr)
						dp.ApplyFormat(trFormat, TRUE, TRUE);
				}
			}
			else
			{
				gl.GroupPlots(0, -1);
			}
		}
		
		// Arrange the layers
		stLayersGridFormat stFormat;
		stFormat.nXGap		= 5;
		stFormat.nYGap		= 5;
		stFormat.nLeftMg	= 12;
		stFormat.nRightMg	= 10;
		stFormat.nTopMg		= 10;
		stFormat.nBottomMg	= 12;
		page_arrange_layers(m_gp, m_nLayerRows, m_nLayerCols, &stFormat);

		///Jasmine 10/15/09 QA81-14321 SAVE_SPACING_SETTING_FOR_ARRANGEMENT
		bool bOK = save_arrange_spacing_settings(m_gp, m_nLayerCols, m_nLayerRows, 
												stFormat.nXGap, stFormat.nYGap, 
												stFormat.nLeftMg, stFormat.nRightMg, stFormat.nTopMg, stFormat.nBottomMg);
		ASSERT(bOK);
		///End SAVE_SPACING_SETTING_FOR_ARRANGEMENT
		return TRUE;
	}
	void SetPlotType(int nGUIPlotType)
	{
		m_nPlotType = convert_gui_plot_type(nGUIPlotType);
	}
protected:
	BOOL Init()
	{
		if ( !m_gp )
		{
			if (m_bIsPreviewing)
				m_gp.Create(STR_TEMPLATE_PLOT_BY_LABEL);
			else
				m_gp.Create(STR_TEMPLATE_PLOT_BY_LABEL, CREATE_DEFAULT_OPTIONS | CREATE_ENUM_EXIST_PAGE);
		}
		if ( !m_gp.IsValid() )
		{
			XF_THROW(CER_UNKNOWN_ERROR);
			return FALSE;
		}
		if (m_bIsPreviewing)
		{
			page_load(m_gp, STR_TEMPLATE_PLOT_BY_LABEL, PREVIEW_GRAPH_NOCLICKS);
		}
		return TRUE;
	}
	int GetNextLayerIndex(int nDataIndex)
	{
		Column colY;
		int nLayerIndex = -1;
		if( m_XYRange.GetYColumn(colY, nDataIndex) && colY.IsValid() )
		{
			Worksheet wks;
			colY.GetParent(wks);
			if ( wks.IsValid() )
			{
				// If the label is user-defined, we have to retrieve the type index since
				// they can be different index value in different worksheet
				///Kenny 12/10/2009 QA81-14182-P1 PLOT_BY_LABEL_NEED_IMPROVE_ERROR_CHECKING_RUN_FROM_SCRIPT
				//if ( -1 == m_nLabelType || IS_USER_DEFINED_LABEL(m_nLabelType) )
					//m_nLabelType = get_label_type_by_name(wks, m_strLabelName);
				if ( RCLT_INVALID == m_nLabelType || IS_USER_DEFINED_LABEL(m_nLabelType) )
				{
					m_nLabelType = get_label_type_by_name_or_indentifier(wks, m_strLabelName);
					if ( RCLT_INVALID == m_nLabelType )
					{
						XF_THROW(CER_INVALID_LABEL_TYPE);
					}
				}
				///End QA81-14182-P1 PLOT_BY_LABEL_NEED_IMPROVE_ERROR_CHECKING_RUN_FROM_SCRIPT
				string strLabelValue;
				if ( colY.GetExtendedLabel(strLabelValue, m_nLabelType) )
				{
					strLabelValue.TrimLeft();
					strLabelValue.TrimRight();
					// Use the index of the label value as the layer index
					nLayerIndex = m_vsGroupsLabels.Find(strLabelValue);
					if ( nLayerIndex < 0 )
					{
						nLayerIndex = m_vsGroupsLabels.Add(strLabelValue);
					}
				}
			}
		}
		return nLayerIndex;
	}
	BOOL DoNextPlot(DataRange& dr, const int nLayerIndex)
	{
		if( !dr || !dr.GetNumData() )
			return FALSE;
		ASSERT(nLayerIndex >= 0);
		GraphLayer gl;
		int nLayerCount = m_gp.Layers.Count();
		if( nLayerIndex < nLayerCount )
		{
			gl = m_gp.Layers(nLayerIndex);
		}
		else
		{
			int nIndex = m_gp.AddLayer();
			if (nIndex >= 0)
				gl = m_gp.Layers(nIndex);
		}
		if(gl.IsValid())
		{
			int nPlotIndex = gl.AddPlot(dr, m_nPlotType);
			if ( nPlotIndex >= 0 )
			{
				gl.Rescale();
				return TRUE;
			}
			return TRUE;
		}
		return FALSE;
	}
	void UpdateYAxisTitle(GraphLayer& gl)
	{
		int nLayerIndex = gl.GetIndex();
		if ( nLayerIndex < m_vsGroupsLabels.GetSize() )
		{
			string strLabel = m_vsGroupsLabels[nLayerIndex];
			AxisObject ao = get_axis_object(gl, AXIS_LEFT);
			GraphObject go = ao.GetTitleObject();
			if ( go && go.Show )
			{
				go.Text = strLabel;
			}
		}
		else
		{
			ASSERT(0);
		}
	}
private:
};

static void _run_plotbylabel_on_current_data(TreeNode& trGetN, PageBase& pgTemp)
{
	XYRange iy;
	xy_range_from_GetN_data_node(trGetN.iy, iy);

	PlotByLabelHelper plothelper;

	plothelper.m_XYRange			= iy;
	plothelper.m_gp					= pgTemp;
	plothelper.m_nLayerRows			= trGetN.rows.nVal;
	plothelper.m_nLayerCols			= trGetN.cols.nVal;
	plothelper.m_strLabelName		= trGetN.group.strVal;
	plothelper.SetPlotType(trGetN.plottype.nVal);

	plothelper.m_bIsPreviewing		= true;

	plothelper.SetPlotType(trGetN.plottype.nVal);

	try
	{
		plothelper.Perform();
	}
	catch(int nErr)
	{
	}
}

static bool _update_wks_shown_labels_from_range(TreeNode& trGetN, XYRange& xy)
{
	///------ Folger 11/06/09 SHARE_CODE_WITH_NEW_CLASS_MultipleXYRangesWksCommonLabelHelper
	//bool bRet = xy.IsValid();
	//WksCommonColLabelHelper helper;
	//if ( bRet )
	//{
		//int nNumData = xy.GetNumData(DRR_GET_DEPENDENT);
		//for( int ii = 0; ii < nNumData; ii++ )
		//{
			//Column colX, colY;
			//Worksheet wks;
			//if( xy.GetYColumn(colY, ii) && colY.IsValid() )
			//{
				//colY.GetParent(wks);
			//}
			//else if( xy.GetXColumn(colX, ii) && colX.IsValid() )
			//{
				//colX.GetParent(wks);
			//}
			//if ( wks )
			//{
				//int nRet = helper.UpdateCommonColLabelInfo( wks );
				//switch(nRet)
				//{
				//case GET_COMMON_LABEL_OK:
					//break;
				//case GET_COMMON_LABEL_ERROR:
					//ASSERT(0);
					//// No break here! Update the header if any error was met
				//case GET_COMMON_LABEL_NO_COMMON:
					//goto UpdateHeader;
					//break;
				//default:
					//ASSERT(0);
					//break;
				//}
			//}
		//}
	//}
//UpdateHeader:
	//{
		//ASSERT( trGetN.IsValid() );
		//TreeNode trHeader = trGetN.group;
		//string strLabelNamesCombo, strLabelTypes;
		//vector<string>	vsLabelNames;
		//vector<int>		vnLabelTypes;
		//helper.GetLabelNames(vsLabelNames);
		//helper.GetLabelTypes(vnLabelTypes);
		//vector<string> vsLabelTypes;
		//
		//vector<int>		vnTypesToSkip = {
			//RCLT_SAMPLE_RATE
			//, RCLT_SPARKLINE
		//};
		//for ( int nn = vnTypesToSkip.GetSize()-1; nn >= 0; --nn)
		//{
			//vector<uint>	vnIndices;
			//if (  vnLabelTypes.Find(vnIndices, vnTypesToSkip[nn]) > 0 )
			//{
				//ASSERT(vnIndices.GetSize() > 0);
				//int nIndex = vnIndices[0];
				//vnLabelTypes.RemoveAt(nIndex);
				//vsLabelNames.RemoveAt(nIndex);
				//continue;
			//}
		//}
	if ( !xy )
		return false;
	
	MultipleXYRangesWksCommonLabelHelper	clHelper(xy);
	vector<string>	vsLabelNames;
	vector<int>		vnLabelTypes;
	vsLabelNames = GET_LABEL_NAMES(clHelper);
	vnLabelTypes = GET_LABEL_TYPES(clHelper);
	
	string strLabelNamesCombo, strLabelTypes;
	vector<string> vsLabelTypes;
	bool	bRet = true;
	{
	///------ End SHARE_CODE_WITH_NEW_CLASS_MultipleXYRangesWksCommonLabelHelper
		
		convert_int_vector_to_string_vector(vnLabelTypes, vsLabelTypes);

		trGetN.group.Enable = vsLabelNames.GetSize() > 0;

		strLabelNamesCombo.SetTokens( vsLabelNames, ITEM_SEPARATOR );
		strLabelTypes.SetTokens( vsLabelTypes, ITEM_SEPARATOR );

		if ( strLabelNamesCombo.IsEmpty() )
		{
			strLabelNamesCombo = STR_EMPTY_COMBO;
			bRet = false;
		}
		
		string	strSel = trGetN.group.strVal;
		///Kenny 12/10/2009 QA81-14182-P1 PLOT_BY_LABEL_NEED_IMPROVE_ERROR_CHECKING_RUN_FROM_SCRIPT
		//if ( strSel.IsEmpty() || vsLabelNames.Find(strSel) < 0 )
		if ( strSel.IsEmpty() )
		///End QA81-14182-P1 PLOT_BY_LABEL_NEED_IMPROVE_ERROR_CHECKING_RUN_FROM_SCRIPT
			strSel = strLabelNamesCombo.GetToken(0, ITEM_SEPARATOR);
		trGetN.group.SetAttribute(STR_COMBO_ATTRIB, strLabelNamesCombo);
		trGetN.group.SetAttribute(STR_ATTRIB_LABEL_TYPES, strLabelTypes);
		trGetN.group.strVal = strSel;
	}
	return bRet;
}

static int _get_wks_all_col_header_labels_group_num(XYRange& xy, string strLabelName)
{
	int nCount = 0;
	if ( xy.IsValid() && !strLabelName.IsEmpty() )
	{
		int nNumData = xy.GetNumData(DRR_GET_DEPENDENT);
		vector<UINT>	vnColUIDs;
		vector<string>	vsGroups;
		for( int ii = 0; ii < nNumData; ii++ )
		{
			Column colY;
			if( xy.GetYColumn(colY, ii) && colY.IsValid() )
			{
				UINT nColUID = colY.GetUID(TRUE);
				vector<uint> vIndex;
				if ( vnColUIDs.Find(MATREPL_TEST_EQUAL, nColUID, vIndex) <= 0 )
				{
					Worksheet wks;
					colY.GetParent(wks);
					if ( wks.IsValid() )
					{
						///Kenny 12/10/2009 QA81-14182-P1 PLOT_BY_LABEL_NEED_IMPROVE_ERROR_CHECKING_RUN_FROM_SCRIPT
						//const int nLabelType = get_label_type_by_name(wks, strLabelName);
						const int nLabelType = get_label_type_by_name_or_indentifier(wks, strLabelName);
						///End QA81-14182-P1 PLOT_BY_LABEL_NEED_IMPROVE_ERROR_CHECKING_RUN_FROM_SCRIPT
						string strLabelValue;
						if ( colY.GetExtendedLabel(strLabelValue, nLabelType) )
						{
							strLabelValue.TrimLeft();
							strLabelValue.TrimRight();
							vnColUIDs.Add(nColUID);
							if ( vsGroups.Find(strLabelValue) < 0 )
							{
								vsGroups.Add(strLabelValue);
								++nCount;
							}
						}
					}
				}
			}
		}
	}
	return nCount;
}

static bool _update_gui_group_number_hint(TreeNode& trGetN, int nNumGroups)
{
	string strHint;
	strHint.Format(_L("%d groups in total"), nNumGroups);
	trGetN.hint_groups.SetAttribute(STR_LABEL_ATTRIB, strHint);
	trGetN.hint_groups.Enable = ENABLE_READ_ONLY;
	trGetN.hint_groups.SetAttribute(STR_ATTRIB_DISPFMT, DISPLAY_EDITOR_USE_LABEL);
	trGetN.hint_groups.SetAttribute(STR_ATTRIB_GROUPS_COUNT, nNumGroups);
	
	return true;
}

static void _get_gui_layer_row_col_auto_status(TreeNode& trGetN, int& nAutoRow, int& nAutoCol)
{
	TreeNode tnRow = trGetN.rows;
	TreeNode tnCol = trGetN.cols;
	nAutoRow = octree_get_auto_support( &tnRow );
	nAutoCol = octree_get_auto_support( &tnCol );
}

static void _update_gui_layer_row_col_val(TreeNode& trGetN, int nNumGroups)
{
	ASSERT( nNumGroups > 0 );
	int nAutoRow, nAutoCol;
	_get_gui_layer_row_col_auto_status(trGetN, nAutoRow, nAutoCol);
	
	int nAutoNum = (1 == nAutoRow ? 1 : 0) + (1 == nAutoCol ? 1 : 0);
	
	if ( 0 == nAutoNum )
		return;
	
	int nRow = trGetN.rows.nVal;
	int nCol = trGetN.cols.nVal;
	
	if ( 1 == nAutoNum )
	{
		if ( 1 == nAutoRow )
		{
			if ( nCol > 0 )
			{
				nRow = ceil((double)nNumGroups / nCol);
			}
		}
		else if ( nRow > 0 )
		{
			nCol = ceil((double)nNumGroups / nRow);
		}
	}
	else if ( 2 == nAutoNum )
	{
		double	dSquareRoot = sqrt( nNumGroups );

		nRow = ceil( dSquareRoot );
		nCol = floor( dSquareRoot );
		
		int		nTotal = nRow * nCol;
		if ( nTotal < nNumGroups )
		{
			nCol = nRow;
		}
	}
	
	ASSERT( nRow * nCol >= nNumGroups );
	
	trGetN.rows.nVal = nRow;
	trGetN.cols.nVal = nCol;
}

static bool _check_correct_gui_layer_row_col(TreeNode& trGetN, int nNumGroups)
{
	string strRow = trGetN.rows.strVal;
	string strCol = trGetN.cols.strVal;
	strRow.Remove('.');
	strCol.Remove('.');
	if ( !is_str_numeric_integer(strRow) )
	{
		trGetN.rows.nVal = nNumGroups > 0 ? 1 : 0;
	}
	if ( !is_str_numeric_integer(strCol) )
	{
		trGetN.cols.nVal = nNumGroups;
	}
	int nRow = trGetN.rows.nVal;
	int nCol = trGetN.cols.nVal;
	return nRow * nCol > 0;
}

static bool _check_input(TreeNode& trGetN, string& strErrMsg, TreeNode& trNode = NULL, bool bInit = false)
{
	strErrMsg = "";

	// Check the input range
	int nSize;
	XYRange xy;
	get_error_for_input_xyrange(trGetN.iy, strErrMsg, nSize, xy, true);
	
	bool bRet = strErrMsg.IsEmpty();
	
	if ( !trNode.IsValid() || "group" != trNode.tagName )
	{
		bRet &= _update_wks_shown_labels_from_range(trGetN, xy);
	}
	
	if ( bInit )
	{
		_select_first_user_defined_param_label_type(trGetN);
	}
	
	int nNumGroups = _get_wks_all_col_header_labels_group_num(xy, trGetN.group.strVal);
	bRet &= _update_gui_group_number_hint(trGetN, nNumGroups);
	
	bRet &= _check_correct_gui_layer_row_col(trGetN, nNumGroups);
	
	if ( nNumGroups > 0 )
	{
		_update_gui_layer_row_col_val(trGetN, nNumGroups);
	}

	return bRet;
}

static void _select_first_user_defined_param_label_type(TreeNode& trGetN)
{
	string strLabelTypes;
	vector<string> vsLabelTypes;
	vector<int> vnLabelTypes;
	trGetN.group.GetAttribute(STR_ATTRIB_LABEL_TYPES, strLabelTypes);
	if ( !strLabelTypes.IsEmpty() )
	{
		strLabelTypes.GetTokens(vsLabelTypes, ITEM_SEPARATOR);
		convert_string_vector_to_int_vector(vsLabelTypes, vnLabelTypes);
		
		for (int ii = 0; ii < vnLabelTypes.GetSize(); ++ii)
		{
			if ( IS_USER_DEFINED_LABEL( vnLabelTypes[ii] ) )
			{
				string strLabelNames;
				vector<string> vsLabelNames;
				trGetN.group.GetAttribute(STR_COMBO_ATTRIB, strLabelNames);
				strLabelNames.GetTokens(vsLabelNames, ITEM_SEPARATOR);
				ASSERT(ii < vsLabelNames.GetSize());
				trGetN.group.strVal = vsLabelNames[ii];
				break;
			}
		}
	}
}


void plotbylabel(const XYRange& iy, const string& group, const int& plottype, const int& rows, const int& cols, const string& hint_groups)
{
	PlotByLabelHelper plothelper;
	
	plothelper.m_XYRange			= iy;
	plothelper.m_nLayerRows			= rows;
	plothelper.m_nLayerCols			= cols;
	plothelper.m_strLabelName		= group;
	plothelper.SetPlotType(plottype);
	
	plothelper.Perform();
}

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

}

int plotbylabel_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 plotbylabel_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	///Kenny 12/10/2009 QA81-14182-P1 PLOT_BY_LABEL_NEED_IMPROVE_ERROR_CHECKING_RUN_FROM_SCRIPT
	string strErrMsg;
	BOOL bRet = _check_input(trGetN, strErrMsg, NULL, true);
	///End QA81-14182-P1 PLOT_BY_LABEL_NEED_IMPROVE_ERROR_CHECKING_RUN_FROM_SCRIPT
}
//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 plotbylabel_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
	
	bOKEnable = _check_input(trGetN, strErrMsg, NULL, true);

	s_strErrMsg = strErrMsg;
	bUpdateGraph = bOKEnable;
	bUpdateGrid = 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
	strErrMsg = s_strErrMsg;
	GraphPage gp = pgTemp;
	page_load(gp, "NonePreview", PREVIEW_GRAPH_NOCLICKS);
	load_text_for_nonepreview_graphpage(gp, TEMPLATE_NONE_PREVIEW_CONTENT, TEMPLATE_NONE_PREVIEW_HINTS);
}

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

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

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

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

	if(!bOKEnable)
		dwUpdateGraph = UPDATE_GRAPH_INVALID;
	else
		bUpdateGraph = bOKEnable;
}

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

}

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

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

}
//


///////////////////////////////////////////////////////
	
int GetNGraphBox_plotbylabel(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

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

