#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	plottype_line,
	plottype_scatter,
	plottype_linesymb,
	plottype_column,
	plottype_template,
	plottype_custom,
};
enum{
	portrait_landscape,
	portrait_portrait,
};
enum{
	dir_vertical,
	dir_horizontal,
};
enum{
	order_top,
	order_bottom,
};
enum{
	legend_none,
	legend_seperate,
	legend_combine,
};
enum{
	xlink_none,
	xlink_straight,
};
enum{
	unit_page,
	unit_inch,
	unit_cm,
	unit_mm,
	unit_pixel,
	unit_point,
	unit_link,
};

#include <event_utils.h>
#include <..\Originlab\graph_utils.h>

// modification log
//CPY 5/14/07 BETTER_X_AXIS_HIDE_SHOW_BASED_ON_LAYER_GAP_AND_POSITION
//Jasmine 05/15/07 QA80-9754 MORE_OPTIONS
//Jasmine 05/17/07 MOVE_OUT_PORTRAIT_OPTION
/// Hong 08/08/07 QA80-10064 FIX_LEGEND_COMBINE_FAIL_KEEP_ORIGIN_ORDER
//Jasmine 02/11/09 SHOULD_CHECK_ERROR_ON_EVERY_EVENT
//CPY 5/6/09 QA70-13568 STATCK_PLOT_FAILED_FOR_X_COL_OF_ALL_TEXT
//Kyle 06/25/2009 ADD_PREVIEW
//Kenny 07/23/2009 QA80-13992 NEW_XF_FOR_GENERAL_MULTI_AXES_PLOTTING
//Kenny 08/25/2009 QA81-14203 RESET_PAGE_NAME_IF_CREATED_FROM_OC
//Jasmine 09/14/09 MAKE_SAME_COLOR_AS_COLUMN_TEMPLATE
//Jasmine 09/17/09 QA81-14321 SAVE_SPACING_SETTING_FOR_ARRANGEMENT
//Jasmine 11/12/09 QA80-14619 USER_WANT_ARRANGE_STACK_HORIZONTAL
//Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
//Jasmine 11/19/09 QA80-14619-P3 CHECK_USE_EXISTING_LAYERS_IN_PAGE
//Jasmine 11/23/09 QA80-14619-P9 SET_TEMPLATE_BROWSER_DEFAULT_TO_UFF_PATH
//Jasmine 11/23/09 QA80-14619-P10 FIX_NO_TICKLABEL_IN_BOTTOM_LAYER
//Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
//Jasmine 09/15/2010 ORG-172-P7 RESET_NOCLICK_BIT_FOR_RESULT_GRAPH


///Jasmine 11/12/09 QA80-14619 USER_WANT_ARRANGE_STACK_HORIZONTAL
#define order_left		order_top
#define order_right		order_bottom

static void	_update_gui_on_dir_change(TreeNode& trGetN, bool bVertical)
{	
	string strOrder = bVertical? _L("Top to Bottom|Bottom to Top") : _L("Left to Right|Right to Left");
	trGetN.order.SetAttribute(STR_COMBO_ATTRIB, strOrder);
			
	string strGap = bVertical? _L("Vertical Gap") : _L("Horizontal Gap");
	trGetN.gapy.SetAttribute(STR_LABEL_ATTRIB, strGap);
}
///End USER_WANT_ARRANGE_STACK_HORIZONTAL

///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
static	void	_update_custom_plottypes_show(TreeNode& trGetN)
{
	trGetN.custom.Show = trGetN.hint_custom.Show = plottype_custom == trGetN.plottype.nVal;
}

static	void	_update_max_layer_numbers(TreeNode& trGetN)
{
	TreeNode	trLayer = trGetN.layer;
	if ( 1 == octree_get_auto_support(&trLayer) )
	{
		XYRange	xy;
		if ( xy_range_from_GetN_data_node(trGetN.iy, xy) )
		{
			DataPlotsArrangeHelper		clHelper(NULL, trGetN.number.strVal);
			trGetN.layer.nVal = clHelper.GetTotalLayers(xy.GetNumData(DRR_GET_DEPENDENT));
		}
	}
}

//---Jasmine 11/25/09 show "n plots in total." in hint_plots label
/*static	string&	_layer_number_hint()
{
	static	string	l_str;
	return l_str;
}*/

static	string&	_plots_in_layer_hint()
{
	static	string	l_str;
	return l_str;
}

/*static	void	_update_hint_plots_number(TreeNode& trGetN)
{
	XYRange	xy;
	if ( xy_range_from_GetN_data_node(trGetN.iy, xy) )
	{
		string		str;
		str.Format(_L("%d plots in total."), xy.GetNumData(DRR_GET_DEPENDENT));
		trGetN.hint_number.SetAttribute(STR_LABEL_ATTRIB, str + " " + _layer_number_hint());
	}
}*/

static	void	_update_hint_plots_in_layer(TreeNode& trGetN)
{
	XYRange	xy;
	if ( xy_range_from_GetN_data_node(trGetN.iy, xy) )
	{
		DataPlotsArrangeHelper		clHelper(NULL, trGetN.number.strVal, NULL, NULL, NULL, trGetN.layer.nVal);
		//trGetN.hint_plots.SetAttribute(STR_LABEL_ATTRIB, _plots_in_layer_hint() + clHelper.MakeActualNumPlotsInLayerString(xy.GetNumData(DRR_GET_DEPENDENT)));
		int nTotalPlots = xy.GetNumData(DRR_GET_DEPENDENT);
		string strLabel;
		strLabel.Format("%d plots in total. %s%s", nTotalPlots, _plots_in_layer_hint(), clHelper.MakeActualNumPlotsInLayerString(nTotalPlots) );
		trGetN.hint_plots.SetAttribute(STR_LABEL_ATTRIB, strLabel);
	}
}
//---Jasmine 11/25/09 end
///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS

///Kenny 07/23/2009 QA80-13992 NEW_XF_FOR_GENERAL_MULTI_AXES_PLOTTING
//static int _convert_gui_plot_type(const int nPlot)
//{
	//vector<int> vnPlots = {IDM_PLOT_LINE, IDM_PLOT_SCATTER, IDM_PLOT_LINESYMB, IDM_PLOT_COLUMN};///Jasmine 05/15/07 QA80-9754 MORE_OPTIONS
	//if(0 <= nPlot && nPlot < vnPlots.GetSize())
		//return vnPlots[nPlot];
	//return IDM_PLOT_LINE;
//}
///End QA80-13992 NEW_XF_FOR_GENERAL_MULTI_AXES_PLOTTING

//------- CPY 5/14/07 BETTER_X_AXIS_HIDE_SHOW_BASED_ON_LAYER_GAP_AND_POSITION
///Jasmine 05/15/07 QA80-9754 MORE_OPTIONS
static void _set_show_X_axes(GraphLayer& gl, bool bTop, bool bBottom, int nGapPercent, bool bShow)
{
	if(bTop)
		axis_set_show(gl, AXIS_TOP, true);
	if(bBottom)
		axis_set_show(gl, AXIS_BOTTOM, true);
	
	if(nGapPercent > 0)// when gap is there, we should leave things as is
		return;
	// no gap, we need to make sure in between layers do not show top as it will overwise overlap with bottom of next
	///Jasmine 11/23/09 QA80-14619-P10 FIX_NO_TICKLABEL_IN_BOTTOM_LAYER
	//if(bTop)
	//{
		//axis_set_show(gl, AXIS_BOTTOM, true, bShow, bShow);
		//return;
	//}
	//axis_set_show(gl, AXIS_TOP, false);
	//if(bBottom)
		//return;
	//// for all inbetween layers, bottom axis should not show tick labels nor title, as tick labels will take un space for plotting on another layer
	//axis_set_show(gl, AXIS_BOTTOM, true, bShow, bShow);
	if(!bBottom)
		axis_set_show(gl, AXIS_BOTTOM, true, bShow, bShow);
	if(!bTop)
		axis_set_show(gl, AXIS_TOP, false);
	///End FIX_NO_TICKLABEL_IN_BOTTOM_LAYER
}
///End MORE_OPTIONS
//-------

///Kyle 06/25/2009 ADD_PREVIEW

static bool s_bInit = false;
static string s_strErrMsg = "";

static void _run_plotstack_on_current_data(TreeNode& trGetN, PageBase& pgTemp)
{
	XYRange iy;
	xy_range_from_GetN_data_node(trGetN.iy, iy);	
	int plottype = trGetN.plottype.nVal;
	string template = trGetN.template.strVal;
	int portrait = trGetN.portrait.nVal;
	int dir = trGetN.dir.nVal;
	int order = trGetN.order.nVal;
	int legend = trGetN.legend.nVal;
	int link = trGetN.link.nVal;
	int xlink = trGetN.xlink.nVal;
	int unit = trGetN.unit.nVal;
	int gapy = trGetN.gapy.nVal;
	int leftmg = trGetN.leftmg.nVal;
	int rightmg = trGetN.rightmg.nVal;
	int topmg = trGetN.topmg.nVal;
	int bottommg = trGetN.bottommg.nVal;
	try {
		///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
		//_run_plotstack(iy, plottype, template, portrait, dir, order, legend, link, xlink, unit, gapy, leftmg, rightmg, topmg, bottommg, pgTemp);
		_run_plotstack(iy, plottype, template, portrait, dir, order, legend, link, xlink, unit, gapy, leftmg, rightmg, topmg, bottommg, pgTemp, trGetN.custom.strVal, trGetN.number.strVal, trGetN.layer.nVal);
		///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	}
	catch(int nErr)
	{
	}
}

///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
static	BOOL	_check_custom_plottype(TreeNode& trGetN, string* pstrErrMsg = NULL)
{
	if ( plottype_custom == trGetN.plottype.nVal )
	{
		if ( trGetN.custom.strVal.IsEmpty() )
		{
			if ( pstrErrMsg )
				pstrErrMsg->Format("%d:%s", XFERR_SPEICIFIED_STRING_EMPTY, _L("plot types"));
			return FALSE;
		}
	}
	
	return TRUE;
}
static	BOOL	_check_num_plots_in_layer(TreeNode& trGetN, string* pstrErrMsg = NULL)
{
	if ( trGetN.number.IsEmpty() )
	{
		if ( pstrErrMsg )
			pstrErrMsg->Format("%d:%s", XFERR_SPEICIFIED_STRING_EMPTY, _L("number of plots"));
		return FALSE;
	}
	
	return TRUE;
}

static	BOOL	_check_total_number_of_layers(TreeNode& trGetN, string* pstrErrMsg = NULL)
{
	if ( trGetN.layer.nVal == 0 )
	{
		if ( pstrErrMsg )
			*pstrErrMsg = XFERR_NUMBER_OF_LAYERS_IS_ZERO;
		return FALSE;
	}
	
	return TRUE;
}

static	BOOL	_error_checkings(TreeNode& trGetN, string* pstrErrMsg = NULL)
{
	return ( _check_custom_plottype(trGetN, pstrErrMsg)
			&& _check_num_plots_in_layer(trGetN, pstrErrMsg)
			&& _check_total_number_of_layers(trGetN, pstrErrMsg)
			);
}
///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS

static bool _check_input(TreeNode& trGetN, string& strErrMsg)
{
	strErrMsg = "";
	trGetN.xlink.Show = trGetN.unit.Show = trGetN.link.nVal;
	
	///Jasmine 02/11/09 SHOULD_CHECK_ERROR_ON_EVERY_EVENT
	//if(GETNE_ON_INIT == nEventID || GETNE_ON_OK == nEventID || (nEventID > 0 && !lstrcmpi(lpcszNodeName, "iy")))
	///End SHOULD_CHECK_ERROR_ON_EVERY_EVENT
	{
		int nSize;
		XYRange xy;
		//---- CPY 5/6/09 QA70-13568 STATCK_PLOT_FAILED_FOR_X_COL_OF_ALL_TEXT
		//get_error_for_input_xyrange(trGetN.iy, strErrMsg, nSize, xy);
		get_error_for_input_xyrange(trGetN.iy, strErrMsg, nSize, xy, true);
		//----
		if(strErrMsg.IsEmpty())
		{
			nSize = xy.GetNumData(DRR_GET_DEPENDENT);
			trGetN.iy.SetAttribute("Size", nSize);
		}
	}
	if(!strErrMsg.IsEmpty())
	{
		return false;
	}
	///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	if ( strErrMsg.IsEmpty() )
	{
		if ( !_error_checkings(trGetN, &strErrMsg) )
			return false;
	}
	///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	///Jasmine 02/11/09 SHOULD_CHECK_ERROR_ON_EVERY_EVENT
	//if( GETNE_ON_INIT == nEventID || GETNE_ON_OK == nEventID || (nEventID > 0 && (!lstrcmpi(lpcszNodeName, "iy") || !lstrcmpi(lpcszNodeName, "gapy") || !lstrcmpi(lpcszNodeName, "leftmg") || !lstrcmpi(lpcszNodeName, "rightmg") || !lstrcmpi(lpcszNodeName, "topmg") || !lstrcmpi(lpcszNodeName, "bottommg"))))
	///End SHOULD_CHECK_ERROR_ON_EVERY_EVENT
	{
		int nSize, nErr;
		trGetN.iy.GetAttribute("Size", nSize);
		stLayersGridFormat 	stFormat;	
		//stFormat.nXGap = 5;		
		stFormat.nYGap 		= trGetN.gapy.nVal;		
		stFormat.nLeftMg 	= trGetN.leftmg.nVal;
		stFormat.nRightMg 	= trGetN.rightmg.nVal;		
		stFormat.nTopMg 	= trGetN.topmg.nVal;
		stFormat.nBottomMg 	= trGetN.bottommg.nVal;
		///Jasmine 11/19/09 QA80-14619 LAYER_SIZE_IS_SPECIFIED
		nSize = trGetN.layer.nVal;
		//arrange_layer_check_spacing(nSize, 1, stFormat, nErr);
		if(dir_vertical == trGetN.dir.nVal)
			arrange_layer_check_spacing(nSize, 1, stFormat, nErr);
		else
			arrange_layer_check_spacing(1, nSize, stFormat, nErr);
		///End LAYER_SIZE_IS_SPECIFIED
		if(nErr != CER_NO_ERROR)
			strErrMsg = nErr;
		if(nErr == CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE)
		{
			strErrMsg += ":";
			strErrMsg += _L("Spacing");
			strErrMsg += "|";
			strErrMsg += 0;
		}
		if(nErr == CER_LAYER_TOO_SMALL)
		{
			strErrMsg += ":";
			int nInfo;
			if(stFormat.nYGap || stFormat.nLeftMg || stFormat.nRightMg || stFormat.nTopMg || stFormat.nBottomMg)
			{
				nInfo = CER_ARRANGE_LAYERS_RESET_SPACING;
			}
			else
			{
				nInfo = CER_ARRANGE_LAYERS_RESET_ROW_COLUMN;
			}
			string strErrMsg2;
			ocu_load_msg_str(nInfo, &strErrMsg2);
			strErrMsg += strErrMsg2;
		}
	}
	
	///Jasmine 02/11/09 SHOULD_CHECK_ERROR_ON_EVERY_EVENT
	//if(!strErrMsg.IsEmpty())
		//bOKEnable = -1 < strErrMsg.Find((string)CER_LAYER_TOO_SMALL);
	if(!strErrMsg.IsEmpty())
	{
		return false;
	}
	///End SHOULD_CHECK_ERROR_ON_EVERY_EVENT

	return true;
}
///Jasmine 09/14/09 MAKE_SAME_COLOR_AS_COLUMN_TEMPLATE
static void _set_column_plot_color(DataPlot& dp)
{
	if(!dp)
	{
		ASSERT(0);
		return;
	}
	
	Tree trFmt;
	trFmt = dp.GetFormat(FPB_ALL, FOB_ALL, TRUE, TRUE);
	trFmt.Root.Pattern.Border.Width.dVal = 1;
	trFmt.Root.Pattern.Fill.FillColor.nVal = SYSCOLOR_RED;
	int iRet = dp.UpdateThemeIDs(trFmt.Root, "Error", "Unknown tag");
	ASSERT(iRet == 0);
	BOOL bRet = dp.ApplyFormat(trFmt, TRUE, TRUE, TRUE);
	ASSERT(bRet);
}
///End MAKE_SAME_COLOR_AS_COLUMN_TEMPLATE
///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
//static void _run_plotstack(const XYRange& iy, const int& plottype, const string& template, const int& portrait, const int& dir, const int& order, const int& legend, const int& link, const int& axeslink, const int& unit, const int& gap, const int& leftmg, const int& rightmg, const int& topmg, const int& bottommg, PageBase& pgTemp)
static void _run_plotstack(const XYRange& iy, const int& plottype, const string& template, const int& portrait, const int& dir, const int& order, const int& legend, const int& link, const int& axeslink, const int& unit, const int& gap, const int& leftmg, const int& rightmg, const int& topmg, const int& bottommg, PageBase& pgTemp, const string& custom, const string& number, const int& layer)
///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
{
	int nRange = iy.GetNumData(DRR_GET_DEPENDENT);
	if(!iy || !nRange)
		XF_THROW(CER_INVALID_RANGE);
	///Kenny 07/23/2009 QA80-13992 NEW_XF_FOR_GENERAL_MULTI_AXES_PLOTTING
	//int nPlot = _convert_gui_plot_type(plottype);
	int nPlot = convert_gui_plot_type(plottype);
	///End QA80-13992 NEW_XF_FOR_GENERAL_MULTI_AXES_PLOTTING
	///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	//int nCount;
	///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	GraphPage gp;
	if(pgTemp)
	{
		gp = pgTemp;
		gp.LoadTemplate(template);
	}
	else
	{
		/// Kenny 08/25/2009 QA81-14203 RESET_PAGE_NAME_IF_CREATED_FROM_OC
		//gp.Create(template); 
		gp.Create(template, CREATE_DEFAULT_OPTIONS | CREATE_ENUM_EXIST_PAGE); 
		/// End QA81-14203 RESET_PAGE_NAME_IF_CREATED_FROM_OC
		pgTemp = gp;
	}
	set_gp_noclick(gp, OC_PREVIEW_NOCLICK_NOZOOMPAN);	///Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
	
	///Jasmine 11/19/09 QA80-14619-P3 CHECK_USE_EXISTING_LAYERS_IN_PAGE
	string strLabtalk;
	foreach(GraphLayer lay in gp.Layers)
	{
		if(lay.GetIndex() == 0)
			continue;
		strLabtalk.Format("%s!layer%d.link=0", gp.GetName(), lay.GetIndex()+1);
		LT_execute(strLabtalk);
	}
	///End CHECK_USE_EXISTING_LAYERS_IN_PAGE
	
	///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	vector<int>		vnPlotTypes = {IDM_PLOT_LINE
			, IDM_PLOT_SCATTER
			, IDM_PLOT_LINESYMB
			, IDM_PLOT_COLUMN
		};
	DataPlotsArrangeHelper		clHelper(gp, number, custom, vnPlotTypes, template, layer);
	///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	///Jasmine 11/19/09 QA80-14619-P3 CHECK_USE_EXISTING_LAYERS_IN_PAGE
	//make sure layer count <= layer
	clHelper.CheckLayerCount();	
	///End CHECK_USE_EXISTING_LAYERS_IN_PAGE
	
	for(int ii = 0; ii < nRange; ii++)
	{
		DataRange dr;
		iy.GetSubRange(dr, DRR_GET_DEPENDENT | DRR_NO_FACTORS, ii);
		if(!dr || !dr.GetNumData())
			continue;
		///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
		//GraphLayer gl;
		//if(!nCount++)
			//gl = gp.Layers();
		//else
		//{
			//int nn = gp.AddLayer(NULL, 0, template);
			//gl = gp.Layers(nn);
		//}
		
		GraphLayer	gl = clHelper.GetLayerAdvanced();
		///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
		if(gl.IsValid())
		{
			///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
			//int nAddPlot = gl.AddPlot(dr, nPlot);
			switch ( plottype )
			{
			case plottype_custom:
				nPlot = plottype_custom;
				break;
				
			case plottype_template:
				nPlot = IDM_PLOT_UNKNOWN;
				break;
				
			default:
				break;
			}
			if ( plottype == plottype_custom )
				nPlot = clHelper.GetPlotType();
			int nAddPlot = gl.AddPlot(dr, nPlot);
			///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
			///Jasmine 09/14/09 MAKE_SAME_COLOR_AS_COLUMN_TEMPLATE
			if(nAddPlot >= 0 && nPlot == IDM_PLOT_COLUMN)				
			{
				DataPlot dp = gl.DataPlots(nAddPlot);
				_set_column_plot_color(dp);
			}
			///End MAKE_SAME_COLOR_AS_COLUMN_TEMPLATE
			
			gl.Rescale(ANL_CHK_DATA_OUTSIDE);	
		}
	}
	
	///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	clHelper.CheckLayerCount();//clHelper.CheckAppendLayers();	///Jasmine 11/19/09 QA80-14619-P3 CHECK_USE_EXISTING_LAYERS_IN_PAGE
	///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	
	stLayersGridFormat 	stFormat;	
	///Jasmine 11/12/09 QA80-14619 USER_WANT_ARRANGE_STACK_HORIZONTAL
	if(dir_vertical == dir)
		stFormat.nYGap = gap;		
	else
		stFormat.nXGap = gap;		
	///End USER_WANT_ARRANGE_STACK_HORIZONTAL
	stFormat.nLeftMg 	= leftmg;
	stFormat.nRightMg 	= rightmg;		
	stFormat.nTopMg 	= topmg;
	stFormat.nBottomMg 	= bottommg;
	int nErr;
	///Jasmine 11/12/09 QA80-14619 USER_WANT_ARRANGE_STACK_HORIZONTAL
	if(dir_vertical == dir)
		arrange_layer_check_spacing(gp.Layers.Count(), 1, stFormat, nErr);
	else
		arrange_layer_check_spacing(1, gp.Layers.Count(), stFormat, nErr);
	///End USER_WANT_ARRANGE_STACK_HORIZONTAL
	if(nErr != CER_NO_ERROR)
	{
		if(nErr == CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE)
			XF_THROW_EX2(nErr, _L("Spacing"), 0);
		if(nErr == CER_LAYER_TOO_SMALL)
		{
			string strInfo;
			ocu_load_msg_str(XFERR_INVALID_OPERATION, &strInfo);
			XF_THROW_EX(nErr, strInfo);
		}
		XF_THROW(nErr);
	}
	bool bPortrait = portrait;
	///Jasmine 05/17/07 MOVE_OUT_PORTRAIT_OPTION
	///Jasmine 11/12/09 QA80-14619 USER_WANT_ARRANGE_STACK_HORIZONTAL
	if(dir_vertical == dir)
		page_arrange_layers(gp, gp.Layers.Count(), 1, &stFormat, order);
	else
		page_arrange_layers(gp, 1, gp.Layers.Count(), &stFormat, order);
	///End USER_WANT_ARRANGE_STACK_HORIZONTAL
	string strLT;
	strLT.Format("page -o %s",bPortrait?"p":"l");
	gp.LT_execute(strLT);	
	//End MOVE_OUT_PORTRAIT_OPTION

	foreach(GraphLayer gl in gp.Layers) 
	{
		///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
		legend_update(gl);
		if ( !(plottype_template == plottype || plottype_custom == plottype && !clHelper.IsDataPlotsGroupAllowed()) )
			gl.GroupPlots(0);
		///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
		int nIndex = gl.GetIndex();
		//------- CPY 5/14/07 BETTER_X_AXIS_HIDE_SHOW_BASED_ON_LAYER_GAP_AND_POSITION
		/*
		if(!gapy)
		{	//hide all horizontal axes, except the topmost and bottommost
			if(nIndex != gp.Layers.Count() - 1)
				axis_set_show(gl, order? AXIS_TOP:AXIS_BOTTOM, false);
			if(nIndex)
				axis_set_show(gl, order? AXIS_BOTTOM:AXIS_TOP, false);
		}
		*/
		bool bLastLayer = nIndex == gp.Layers.Count() - 1?true:false;
		bool bFirstLayer = nIndex>0?false:true;
		bool bShow = !link || !axeslink;
		///Jasmine 11/12/09 QA80-14619 USER_WANT_ARRANGE_STACK_HORIZONTAL		
		if(dir_vertical == dir)
			_set_show_X_axes(gl, order_bottom==order? bLastLayer:bFirstLayer, order_bottom==order?bFirstLayer:bLastLayer, gap, bShow);
		else
			_set_show_X_axes(gl, order_right==order? bFirstLayer:bLastLayer, order_right==order?bLastLayer:bFirstLayer, gap, bShow);
		
		string strLT;
		strLT.Format("%s!layer%d.exchangexy=%d", gp.GetName(), gl.GetIndex()+1, dir_vertical == dir? 0 : 1);
		LT_execute(strLT);
		///End USER_WANT_ARRANGE_STACK_HORIZONTAL
		//-------
		
		///Jasmine 05/15/07 QA80-9754 MORE_OPTIONS
		//legend_update(gl, -1, true);
		switch(legend)
		{
		case legend_none:
			gl.RemoveGraphObject(GO_LEGEND_NAME);
			break;
		case legend_combine:	///not ready
			if(nIndex>0)
				break;
		case legend_seperate:
			GraphObject goLegend = gl.GraphObjects(GO_LEGEND_NAME);	
			if(goLegend)
			{
				legend_position(goLegend, true, LEGEND_POS_LEFT);
				legend_position(goLegend, false, LEGEND_POS_TOP);
			}
			break;
		}
		///End MORE_OPTIONS
		if(!nIndex)
			continue;
		if(link)
		{
			int nUnit = unit;
			layer_set_link(gl, 0, axeslink, 0, &nUnit);
		}
	}
	
	if(link)
		gp.LT_execute("layer -all ma");	//gp.Layers(0).Rescale();	///Jasmine 11/19/09 QA80-14619-P2 RESCALE_ALL_LINKED_LAYERS

	//---Jasmine 11/17/09 GroupPlots need legend_update, so legend_combine should after that
	///Jasmine 05/15/07 QA80-9754 MORE_OPTIONS
	/// Hong 08/08/07 QA80-10064 FIX_LEGEND_COMBINE_FAIL_KEEP_ORIGIN_ORDER
	//if(legend)
	//{
	//	//LT_execute("sec -p 0.02");//temp  /// Iris 05/14/2007 v8.0619 CORRECTED_LEGEND_POSITION
	//	legend_update_text_property(gp, legend_combine == legend);
	if ( legend_combine == legend )
	{
		//legend_combine(gp);
		legend_combine(gp, 0, !order); /// Hong 08/14/07 v8.0681 MORE_BETTER_INITIAL_ORDER
	/// end /// Hong 08/08/07 QA80-10064 FIX_LEGEND_COMBINE_FAIL_KEEP_ORIGIN_ORDER
	}
	///End MORE_OPTIONS
	//---End
}


///End ADD_PREVIEW


void plotstack(const XYRange& iy, const int& plottype, const string& custom, const string& hint_custom, const string& template, const int& portrait, const int& dir, const int& order, const int& legend, const int& link, const int& xlink, const int& unit, const int& layer, const string& number, const string& hint_number, const string& hint_plots, const int& gapy, const int& leftmg, const int& rightmg, const int& topmg, const int& bottommg)
{
	///Kyle 06/25/2009 ADD_PREVIEW
	//int nRange = iy.GetNumData(DRR_GET_DEPENDENT);
	//if(!iy || !nRange)
		//XF_THROW(CER_INVALID_RANGE);
	//int nPlot = _convert_gui_plot_type(plottype);
	//int nCount;
	//GraphPage gp;
	//gp.Create(template); 
	//for(int ii = 0; ii < nRange; ii++)
	//{
		//DataRange dr;
		//iy.GetSubRange(dr, DRR_GET_DEPENDENT | DRR_NO_FACTORS, ii);
		//if(!dr || !dr.GetNumData())
			//continue;
		//GraphLayer gl;
		//if(!nCount++)
			//gl = gp.Layers();
		//else
		//{
			//int nn = gp.AddLayer(NULL, 0, template);
			//gl = gp.Layers(nn);
		//}
		//if(gl.IsValid())
		//{
			//gl.AddPlot(dr, nPlot);
			//gl.Rescale();	
		//}
	//}	
	//stLayersGridFormat 	stFormat;	
	////stFormat.nXGap = 5;		
	//stFormat.nYGap 		= gapy;		
	//stFormat.nLeftMg 	= leftmg;
	//stFormat.nRightMg 	= rightmg;		
	//stFormat.nTopMg 	= topmg;
	//stFormat.nBottomMg 	= bottommg;
	//int nErr;
	//arrange_layer_check_spacing(gp.Layers.Count(), 1, stFormat, nErr);
	//if(nErr != CER_NO_ERROR)
	//{
		//if(nErr == CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE)
			//XF_THROW_EX2(nErr, _L("Spacing"), 0);
		//if(nErr == CER_LAYER_TOO_SMALL)
		//{
			//string strInfo;
			//ocu_load_msg_str(XFERR_INVALID_OPERATION, &strInfo);
			//XF_THROW_EX(nErr, strInfo);
		//}
		//XF_THROW(nErr);
	//}
	//bool bPortrait = portrait;
	/////Jasmine 05/17/07 MOVE_OUT_PORTRAIT_OPTION
	//page_arrange_layers(gp, gp.Layers.Count(), 1, &stFormat, order);	
	//string strLT;
	//strLT.Format("page -o %s",bPortrait?"p":"l");
	//gp.LT_execute(strLT);	
	////End MOVE_OUT_PORTRAIT_OPTION
	/////Jasmine 05/15/07 QA80-9754 MORE_OPTIONS
	///// Hong 08/08/07 QA80-10064 FIX_LEGEND_COMBINE_FAIL_KEEP_ORIGIN_ORDER
	////if(legend)
	////{
	////	//LT_execute("sec -p 0.02");//temp  /// Iris 05/14/2007 v8.0619 CORRECTED_LEGEND_POSITION
	////	legend_update_text_property(gp, legend_combine == legend);
	//if ( legend_combine == legend )
	//{
		////legend_combine(gp);
		//legend_combine(gp, 0, !order); /// Hong 08/14/07 v8.0681 MORE_BETTER_INITIAL_ORDER
	///// end /// Hong 08/08/07 QA80-10064 FIX_LEGEND_COMBINE_FAIL_KEEP_ORIGIN_ORDER
	//}
	/////End MORE_OPTIONS
	//foreach(GraphLayer gl in gp.Layers)
	//{
		//int nIndex = gl.GetIndex();
		////------- CPY 5/14/07 BETTER_X_AXIS_HIDE_SHOW_BASED_ON_LAYER_GAP_AND_POSITION
		///*
		//if(!gapy)
		//{	//hide all horizontal axes, except the topmost and bottommost
			//if(nIndex != gp.Layers.Count() - 1)
				//axis_set_show(gl, order? AXIS_TOP:AXIS_BOTTOM, false);
			//if(nIndex)
				//axis_set_show(gl, order? AXIS_BOTTOM:AXIS_TOP, false);
		//}
		//*/
		//bool bLastLayer = nIndex == gp.Layers.Count() - 1?true:false;
		//bool bFirstLayer = nIndex>0?false:true;
		//bool bShow = !link || !xlink;
		//_set_show_X_axes(gl, order? bLastLayer:bFirstLayer, order?bFirstLayer:bLastLayer, gapy, bShow);
		////-------
		/////Jasmine 05/15/07 QA80-9754 MORE_OPTIONS
		////legend_update(gl, -1, true);
		//switch(legend)
		//{
		//case legend_none:
			//gl.RemoveGraphObject(GO_LEGEND_NAME);
			//break;
		//case legend_combine:	///not ready
			//if(nIndex>0)
				//break;
		//case legend_seperate:
			//GraphObject goLegend = gl.GraphObjects(GO_LEGEND_NAME);	
			//if(goLegend)
			//{
				//legend_position(goLegend, true, LEGEND_POS_LEFT);
				//legend_position(goLegend, false, LEGEND_POS_TOP);
			//}
			//break;
		//}
		/////End MORE_OPTIONS
		//if(!nIndex)
			//continue;
		//if(link)
		//{
			//int nUnit = unit;
			//layer_set_link(gl, 0, xlink, 0, &nUnit);
		//}
	//}
	//if(link)
		//gp.Layers(0).Rescale();
	GraphPage gp;
	///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	//_run_plotstack(iy, plottype, template, portrait, dir, order, legend, link, xlink, unit, gapy, leftmg, rightmg, topmg, bottommg, gp);
	_run_plotstack(iy, plottype, template, portrait, dir, order, legend, link, xlink, unit, gapy, leftmg, rightmg, topmg, bottommg, gp, custom, number, layer);
	///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	///End ADD_PREVIEW
	
	///Jasmine 09/17/09 QA81-14321 SAVE_SPACING_SETTING_FOR_ARRANGEMENT
	if(!gp)
		ASSERT(0);
	set_gp_noclick(gp, 0);	///Jasmine 09/15/2010 ORG-172-P7 RESET_NOCLICK_BIT_FOR_RESULT_GRAPH
	
	///Jasmine 11/12/09 QA80-14619 USER_WANT_ARRANGE_STACK_HORIZONTAL
	bool bRet;
	if(dir_vertical == dir)
		bRet = save_arrange_spacing_settings(gp, 1, gp.Layers.Count(), 0, gapy, leftmg, rightmg, topmg, bottommg);
	else
		bRet = save_arrange_spacing_settings(gp, gp.Layers.Count(), 1, 0, gapy, leftmg, rightmg, topmg, bottommg);
	ASSERT(bRet);
	///End USER_WANT_ARRANGE_STACK_HORIZONTAL
	///End SAVE_SPACING_SETTING_FOR_ARRANGEMENT
}

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

}

int plotstack_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 plotstack_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	if ( is_xf_startup(nGetNDialog, dwCntrl) )
	{
		//trGetN.hint_number.GetAttribute(STR_LABEL_ATTRIB, _layer_number_hint());
		trGetN.hint_plots.GetAttribute(STR_LABEL_ATTRIB, _plots_in_layer_hint());
		_update_max_layer_numbers(trGetN);
		if ( 0 == nGetNDialog )
		{
			string	strErrMsg;
			if ( !_check_input(trGetN, strErrMsg) )
			{
				nRet = XFEVT_PROCEED_WITH_DLG;
				return;
			}
		}
	}
	///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
}
//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 plotstack_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

	///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	_update_custom_plottypes_show(trGetN);
	//_update_hint_plots_number(trGetN);
	_update_hint_plots_in_layer(trGetN);
	///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	
	bOKEnable = _check_input(trGetN, strErrMsg);

	tree_set_file_browse_combo_more_attrib(trGetN.template, GetAppPath(), NULL);	///Jasmine 11/23/09 QA80-14619-P9 SET_TEMPLATE_BROWSER_DEFAULT_TO_UFF_PATH
	
	///Jasmine 11/12/09 QA80-14619 USER_WANT_ARRANGE_STACK_HORIZONTAL
	_update_gui_on_dir_change(trGetN, dir_vertical == trGetN.dir.nVal);
	///End USER_WANT_ARRANGE_STACK_HORIZONTAL
	
	// wksTemp is not used
	Worksheet wks = wksTemp;
	wks.SetSize(-1, 0);

	s_bInit = false;
	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;
	///Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
	//GraphPage gp = pgTemp;
	//page_load(gp, "NonePreview");
	//load_text_for_nonepreview_graphpage(gp, TEMPLATE_NONE_PREVIEW_CONTENT, TEMPLATE_NONE_PREVIEW_HINTS);
	xf_load_nopreview(pgTemp);
	///End CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL

}

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

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

	if(!s_bInit)
	{
		GraphPage gp = pgTemp;
		gp.Refresh(true);
		s_bInit = true;
	}
	_run_plotstack_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
	
	///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	if ( !trNode )		/// on theme change
	{
		_update_custom_plottypes_show(trGetN);
		_update_max_layer_numbers(trGetN);
		//_update_hint_plots_number(trGetN);
		_update_hint_plots_in_layer(trGetN);
		_update_gui_on_dir_change(trGetN, dir_vertical == trGetN.dir.nVal);
	}
	else
	{
		if ( trNode.tagName.Compare("plottype") ==  0 )
		{
			_update_custom_plottypes_show(trGetN);
		}
		else if ( trNode.tagName.Compare("layer") == 0 )
		{
			_update_max_layer_numbers(trGetN);
			_update_hint_plots_in_layer(trGetN);
		}
		else if ( trNode.tagName.Compare("number") == 0 )
		{
			_update_max_layer_numbers(trGetN);
			_update_hint_plots_in_layer(trGetN);
		}
		else if ( trNode.tagName.Compare("iy") == 0 )
		{
			s_bInit = false;
			_update_max_layer_numbers(trGetN);
			//_update_hint_plots_number(trGetN);
			_update_hint_plots_in_layer(trGetN);
		}
		else if ( trNode.tagName.Compare("dir") == 0 )
		{
			_update_gui_on_dir_change(trGetN, dir_vertical == trGetN.dir.nVal);
		}
	}
	///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	
	bOKEnable = _check_input(trGetN, strErrMsg);
	bUpdateGrid = true;

	///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	//if (trNode && (trNode.tagName =="iy"))
	//{
		//s_bInit = false;
	//}
//
	/////Jasmine 11/12/09 QA80-14619 USER_WANT_ARRANGE_STACK_HORIZONTAL
	//if (trNode && (trNode.tagName =="dir"))
	//{
		//_update_gui_on_dir_change(trGetN, dir_vertical == trGetN.dir.nVal);
	//}
	/////End USER_WANT_ARRANGE_STACK_HORIZONTAL
	///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
	
	if(!bOKEnable)
		dwUpdateGraph = UPDATE_GRAPH_INVALID; //nUpdateGraph = UPDATE_GRAPH_ERROR;
	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_plotstack(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

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

