#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	option_page,
	option_folder,
	option_recursive,
	option_open,
	option_embed,
	option_project,
	option_specified,
};
enum{
	portrait_landscape,
	portrait_portrait,
};
enum{
	unit_inch,
	unit_cm,
	unit_mm,
	unit_pixel,
	unit_point,
};
enum{
	scalemode_source,
	scalemode_frame,
	scalemode_fixed,
};

//#include <getnbox.h>					///Jasmine 05/17/07 CLEAN_UP_CODES, no need
//#include <..\Originlab\DialogEx.h>
#include <..\System\okocUtils.h>
#include <..\Originlab\okThemeID.h>
#include <..\Originlab\graph_utils.h>
#include <o8dlg.h>

// modification log
///Jasmine 05/17/07 CLEAN_UP_CODES
///Jasmine 08/06/07 GET_AND_APPLY_FIRST_PAGE_LENGEND_MODE
///Jasmine QA80-10204 THEME_ACCESS_TO_PAGE_AUTO_LEGEND_AXIS_ITEMS
///Jasmine 05/08/08 DO_NOTHING_BUT_ENABLE_GRAPHS_IF_CHANGE_OPTION_TO_SPECIFY
///Jasmine 01/15/09 QA80-12966-P1
/// Iris 01/22/2009 ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
///Jasmine 01/22/09 ARRANGE_CHILD_IS_NEWLY_ADDED_IN_VARIABLE_LIST
///Jasmine 03/06/09 QA80-13231 KEEP_ROW_COL_NUMBER_IF_ONLY_GRAPH_ORDER_CHANGE
///Kenny 7/16/2009 QA80-13966-P1 IMPROVE_ERROR_CHECKING_FOR_MERGE_GRAPH_INPUT_NAMES
///Kenny 08/25/2009 QA81-14203 RESET_PAGE_NAME_IF_CREATED_FROM_OC
///Jasmine 09/11/09 SMART_SHOW_TICK_AS_LAYMANAGE
///Jasmine 09/17/09 QA81-14321 SAVE_SPACING_SETTING_FOR_ARRANGEMENT
///Jasmine 01/25/10 QA80-14963 KEEP_LAYER_AXES_TITLE_POSITION
///Jasmine 02/26/10 QA81-15144 UPDATE_PAGE_SIZE_ON_UNIT_CHANGE
///Jasmine 03/26/10 #14963-P3 TEMP_WORK_AROUND_TO_UPDATE_LAYER_INTERNAL_VALUE

enum //Dialog Settings
{
	DLG_OPTION = 1,
	DLG_GRAPHS_NAMES,
	
	DLG_KEEP_SOURCE,
	
	DLG_ARRANGE,
	
	DLG_ROW_NUM,
	DLG_COL_NUM,
	DLG_NEW_LAYERS,
	DLG_KEEP_RATIO,
	
	/// Iris 01/22/2009 ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
	DLG_LINK_ARRANGE,
	DLG_SMART_ARRANGE,
	///end ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
	
	DLG_SCALE_MODE, 
	DLG_FIXED_FACTOR,
	
	DLG_PORTRAIT,
	DLG_WIDTH,
	DLG_HEIGHT,
	DLG_UNIT,
	
	DLG_X_GAP,
	DLG_Y_GAP,
	DLG_LEFT_MARGIN,
	DLG_RIGHT_MARGIN,
	DLG_TOP_MARGIN,
	DLG_BOTTOM_MARGIN,

	DLG_LAST_ITEM		
};

/// Iris 12/18/2006 v8.0527 COMBO_TO_SEL_ALL_PAGES_IN_FOLDER_FOR_EXPORT_PAGE
/*
enum //merge option
{
	OPTION_ALL,
	OPTION_ALL_RECURSIVE,
	OPTION_ALL_OPEN,
	OPTION_ALL_EMBEDDED,
	OPTION_SPECIFIED	
};
*/
// the options of Unit node on dialog
/*
enum
{
	PAGE_UNIT_INCH = 0,
	PAGE_UNIT_CM,
	PAGE_UNIT_MM,
	PAGE_UNIT_PIXEL,
	PAGE_UNIT_POINT,
	//PAGE_UNIT_RATIO
	PAGE_UNIT_LAST_ITEM
};
*/
///Jasmine 05/17/07 CLEAN_UP_CODES, no need
/*
#define DEFAULT_LANDSCAPE_WIDTH		11.3
#define DEFAULT_LANDSCAPE_HEIGHT	7.93
#define DEFAULT_PORTRAIT_WIDTH		7.79
#define DEFAULT_PORTRAIT_HEIGHT		11.4
*/
///End CLEAN_UP_CODES
//#define STR_WARNING					_L("Resulting layers are too small!\nPlease specify smaller margins or gaps.")
#define	STR_PAGE_LIST_SEPARATOR 	'\n'
#define	PAGE_OPTION_OFFSET 			0	///Jasmine 05/17/07 CLEAN_UP_CODES, replace s_nPageOptionOffset
#define	MERGE_GRAPH_TEMPLATE		"MergeGraph"	///Jasmine 12/05/08 v8.0982d Max said each tool should have its own template
#define MY_OLD_VALUE				"MyOldValue"	///Jasmine 03/06/09 QA80-13231 KEEP_ROW_COL_NUMBER_IF_ONLY_GRAPH_ORDER_CHANGE
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
/////////********Parameters of merge setting********////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
///Jasmine 05/17/07 CLEAN_UP_CODES
//reduce unnecessay static variables
//static vector<string>		s_vsPages;
static vector				s_vdScFixFactor, s_vdRatios;	
static vector<int>			s_vnNewLayers;
//static double 				s_dFactor;			
//static int					s_nRow, s_nCol, s_nMode;
//static bool					s_bNewlayer;
//static stLayersGridFormat	s_stFormat;
//static string				s_strTempGP;

//---- Iris 01/04/2007 v8.0536 ADD_ACTIVE_PAGE_INTO_PAGE_OPTION
//static int s_nPageOptionOffset = 0; //In order to skip the first option Acitve Page here	///Jasmine 03/24/07 GET_GRAPH_IN_WKBOOK	
///End CLEAN_UP_CODES
//---- 
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
/////////////********Internal Functions********/////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////

///Jasmine 05/16/07 ALLOW_MERGE_WITHOUT_ARRANGE
void _enable_arrange_setting_node(TreeNode& trGetN, bool bEnable)
{
	//trGetN.row.Show = trGetN.xgap.Show = bEnable;
	vector<int> vnArrangeNodeIDs = {DLG_ROW_NUM, DLG_COL_NUM, DLG_NEW_LAYERS, DLG_KEEP_RATIO,
									DLG_X_GAP, DLG_Y_GAP, DLG_LEFT_MARGIN, DLG_RIGHT_MARGIN, 
									DLG_TOP_MARGIN, DLG_BOTTOM_MARGIN,
									/// Iris 01/22/2009 ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
									DLG_LINK_ARRANGE,
									DLG_SMART_ARRANGE
									///end ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
	};
	for(int ii = vnArrangeNodeIDs.GetSize() - 1; ii > -1; ii--)
	{
		TreeNode tr = trGetN.FindNodeByAttribute(STR_DATA_ATTRIB, vnArrangeNodeIDs[ii]);
		if(tr)
			tr.Enable = bEnable;
	}
}
///End ALLOW_MERGE_WITHOUT_ARRANGE
///Jasmine 03/29/07 ADD_SCALE_ELEMENT
void _get_scale_elements(const vector<string> vsGraphs, vector<double> &vdFixFactor)
{
	vdFixFactor.SetSize(0);
	for(int ii = 0; ii < vsGraphs.GetSize(); ii++)
	{
		GraphPage gp(vsGraphs[ii]);
		if(!gp)
			continue;
		foreach(GraphLayer gl in gp.Layers)
		{
			int nScaleMode;
			double dFactor;
			layer_get_scale_elements(gl, nScaleMode, &dFactor);
			if(!nScaleMode)
				dFactor = NANUM;//dFixFactor = NANUM means nMode should be 0
			vdFixFactor.Add(dFactor);
		}
	}
}
void _set_layer_scale_elements(GraphPage& gp, vector<double> vdFixFactor, int nMode, double dFactor)
{
	if(!gp)
		return;
	int ii, nSize = vdFixFactor.GetSize();
	foreach(GraphLayer gl in gp.Layers)
	{
		int nScaleMode = nMode - 1;//convert gui value
		double dFixFactor = dFactor;
		if(!nMode)
		{
			nScaleMode = 0;
			if(ii < nSize)
			{
				dFixFactor = vdFixFactor[ii++];
				nScaleMode = !is_missing_value(dFixFactor);//dFixFactor = NANUM means nMode should be 0
			}				
		}
		layer_set_scale_elements(gl, nScaleMode, dFixFactor); 
	}
}
///End ADD_SCALE_ELEMENT
void _get_layer_ratios(const GraphPage gp, vector& vdRatios)
{
	vdRatios.SetSize(0);
	foreach(GraphLayer gl in gp.Layers)
		vdRatios.Add(layer_get_ratio(gl));
}
void _set_layer_ratios(GraphPage& gp, const vector vdRatios)
{
	GraphLayer gl;
	for(int nSize = vdRatios.GetSize(), ii = 0; ii < nSize; ii++)
	{
		gl = gp.Layers(ii);
		if(!gl.IsValid())
			break;
		layer_set_ratio(gl, vdRatios[ii]);
	}
}

static void _update_size_setting(GraphPage gp, double dIWidth, double dIHeight, int nIUnit, bool bPortrait, double& dOWidth, double& dOHeight, int& nOUnit)
{
	if(!gp)
		return;
	_get_graph_size(gp, dOWidth, dOHeight, &nOUnit);
	if(dIWidth <= 0 && dIHeight <= 0 && bPortrait)
	{
		double dd = dOWidth;
		dOWidth = dOHeight;
		dOHeight = dd;
	}
	if(dIWidth > 0)
		dOWidth = dIWidth;
	if(dIHeight > 0)
		dOHeight = dIHeight;
	if(-1 != nIUnit && unit_inch <= nIUnit && unit_point >= nIUnit)
		nOUnit = nIUnit;
}
void _set_graph_size(GraphPage gp, double dWidth, double dHeight, int nUnit)
{
	Tree 	tr;
	tr.Root.Page.Dimension.Units.nVal = nUnit;
	tr.Root.Page.Dimension.Width.dVal = dWidth;
	tr.Root.Page.Dimension.Height.dVal = dHeight;
	gp.UpdateThemeIDs(tr.Root.Page);
	//temp, after UpdateThemeIDs(tr.Root), some node will be removed
	tr.Root.SetAttribute(STR_ID_ATTRIB, OTID_ROOT);
	tr.Root.Page.SetAttribute(STR_ID_ATTRIB, OTID_PAGE);
	//
	int nRet = gp.ApplyFormat(tr);
}
void _get_graph_size(GraphPage gp, double& dWidth, double& dHeight, int* pnUnit = NULL)
{
	Tree 	tr;
	tr = gp.GetFormat(FPB_DIMENSION, FOB_DIMENSION);
	dWidth = tr.Root.Page.Dimension.Width.dVal;
	dHeight = tr.Root.Page.Dimension.Height.dVal;
	if(pnUnit)
		*pnUnit = tr.Root.Page.Dimension.Units.nVal;
}
void _set_graph_unit(GraphPage& gp, int nUnit)
{
	Tree 	tr;
	tr.Root.Page.Dimension.Units.nVal = nUnit;
	gp.UpdateThemeIDs(tr.Root.Page);
	//temp, after UpdateThemeIDs(tr.Root), some node will be removed
	tr.Root.SetAttribute(STR_ID_ATTRIB, OTID_ROOT);
	tr.Root.Page.SetAttribute(STR_ID_ATTRIB, OTID_PAGE);
	//
	int nRet = gp.ApplyFormat(tr);
}

static void _get_default_row_col_number(int nLayerNum, int& nRow, int& nCol, bool bIsLandscape = false)
{
	nRow = nCol = 1;
	if(nLayerNum <= 1)
		return;
	
	bool bb = bIsLandscape;
	while(nRow * nCol < nLayerNum)
	{
		if(bb)
			nCol++;
		else 
			nRow++;
		bb = !bb;
	}
}
/// Iris 12/18/2006 v8.0527 COMBO_TO_SEL_ALL_PAGES_IN_FOLDER_FOR_EXPORT_PAGE
/*
static int _get_merge_graphs(vector<string>& vsGraphs, int nOption, LPCSTR lpcszGraphs = NULL, LPCSTR lpcszRemove = NULL)
{
	Folder fld = Project.ActiveFolder();
	int nPageShowState = PAGE_OPEN;
	bool bRecursive = false, bSpecified = false;
	switch(nOption)
	{
	case OPTION_ALL_EMBEDDED:
		get_folder_embedded_graphs(fld, vsGraphs);
	case OPTION_ALL:
		nPageShowState = -1;
		break;
	case OPTION_ALL_RECURSIVE:
		nPageShowState = -1;
		bRecursive = true;
		break;		
	case OPTION_ALL_OPEN:
		break;
	case OPTION_SPECIFIED:
		bSpecified = true;
		string strNames(lpcszGraphs);
		if(strNames.Find("|")>0)
			strNames.GetTokens(vsGraphs, '|');
		else
			strNames.GetTokens(vsGraphs, STR_PAGE_LIST_SEPARATOR);//'|');
		break;
	}
	if(!bSpecified)
		get_folder_pages_name(fld, vsGraphs, EXIST_PLOT, bRecursive, nPageShowState);
	
	string strExclude(lpcszRemove);
	int nIndex = vsGraphs.Find(strExclude);
	if(nIndex > -1)
		vsGraphs.RemoveAt(nIndex);
	return vsGraphs.GetSize(); 
}
*/
///end COMBO_TO_SEL_ALL_PAGES_IN_FOLDER_FOR_EXPORT_PAGE

static bool _tree_set_data_id(TreeNode& trParent, LPCSTR lpcszNodeName, int nID)
{
	if(!trParent.IsValid())
		return false;
	TreeNode tr = trParent.GetNode(lpcszNodeName, false);
	if(tr.IsValid())
	{
		//tr.DataID = nID;
		tr.SetAttribute(STR_DATA_ATTRIB, nID);
		return true;
	}
	return false;
}
static bool _beyond_layer_max_num(GraphPage& gp)//beyondLayerMaxNum
{
	int nLayers = gp.Layers.Count();
	if(nLayers >= 255 )
	{
		MessageBox(NULL, "Unable to add any more layers to this Graph.", "Attention!", MB_ICONSTOP | MB_OK);
		return true;
	}
	
	return false;
}
static int _add_layers(GraphPage& gp, int nLayers, vector<int>& vnNewPages)
{
	int nLayerNum = page_get_layer_count(gp), nNewNum = 0;
	if(nLayerNum<nLayers)//not enough
	{
		nNewNum = nLayers - nLayerNum;
		for(int index=0; index<nNewNum && !_beyond_layer_max_num(gp); index++) 
		///Jasmine 10/31/07 SET_NAME_TO_NEWLY_CREATED_LAYER, same as page_add_to_one_graph
		{
			int nIndex = gp.AddLayer(NULL, CREATE_VISIBLE, MERGE_GRAPH_TEMPLATE);
			vnNewPages.Add( nIndex );
			//gp.Layers(nIndex).SetName("Layer" + (string)(nIndex + 1));	///Jasmine 12/17/08 v8.0987d QA80-12271 CP_MAKE_ADDLAYERS_KEEP_NAME
		}
		///End SET_NAME_TO_NEWLY_CREATED_LAYER
	}
	return nNewNum;
}
static void _update_graph(GraphPage& gpNew, int nRow, int nCol, bool bCreateNew)
{	
	if(!bCreateNew)//remove the additive layers
	{
		//for(int ii=0; ii<s_vnNewLayers.GetSize(); ii++)
		for(int ii = s_vnNewLayers.GetSize() - 1; ii >= 0; ii--)
		{
			GraphLayer gl = gpNew.Layers(s_vnNewLayers[ii]);
			if(gl)
				gl.Destroy();
		}
		s_vnNewLayers.RemoveAll();
		return;
	}
					
	if(_add_layers(gpNew, nRow*nCol, s_vnNewLayers))
		return;
	
	while(s_vnNewLayers.GetSize() > 0 && nRow*nCol < page_get_layer_count(gpNew))
	{
		int ii = s_vnNewLayers.GetSize()-1;
		GraphLayer gl = gpNew.Layers(s_vnNewLayers[ii]);
		if(gl)
			gl.Destroy();
		s_vnNewLayers.RemoveAt(ii);
	}	
}

///Jasmine 01/25/10 QA80-14963 KEEP_LAYER_AXES_TITLE_POSITION
static void _copy_layer_axes_format(GraphPage& gp, const vector<string>& vsPages)
{
	LT_execute("sec -p 0.02");	///Jasmine 03/26/10 #14963-P3 TEMP_WORK_AROUND_TO_UPDATE_LAYER_INTERNAL_VALUE
	int nLayer = 0;
	for(int nPage = 0; nPage < vsPages.GetSize(); nPage++)
	{
		GraphPage gpSource( vsPages[nPage] );
		if(!gpSource)
			continue;
		
		foreach(GraphLayer glSource in gpSource.Layers)
		{
			GraphLayer glTarget = gp.Layers(nLayer++);
			if(glTarget)
				_copy_axes_title_dimension(glSource, glTarget);
		}
	}
}	
///Jasmine 03/24/10 QA80-14963-P2 APPLY_ALL_AXES_FORMAT_BLOCK_SHOW_AXES_FRAME_CHECKBOX
//static void _copy_axes_fmt(const GraphLayer& glSource, GraphLayer& glTarget)	
//{
	//Tree trFmt;
	//trFmt = glSource.GetFormat(FPB_ALL, FOB_ALL, true, true);
	//foreach(TreeNode trNode in trFmt.Root.Children)
	//{
		//if(trNode.tagName.CompareNoCase("Axes") == 0)
			//continue;
		//trNode.Remove();
	//}
	//
	//int nMax = 100;
	//for(int ii = 0; ii < nMax; ii++)
	//{
		//TreeNode trShow = tree_get_node_by_tagname(trFmt, "Show", true);
//
		//if(!trShow)
			//break;
		//trShow.Remove();
	//}
	//
	//glTarget.ApplyFormat(trFmt, TRUE, TRUE);
//}
static void _copy_axes_title_dimension(const GraphLayer& glSource, GraphLayer& glTarget)
{
	vector<string> vsTitles = {"XB", "XT", "YL", "YR"};
	for(int ii = 0; ii < vsTitles.GetSize(); ii++)
	{
		GraphObject goSource = glSource.GraphObjects(vsTitles[ii]);
		GraphObject goTarget = glTarget.GraphObjects(vsTitles[ii]);
		if(!goSource || !goTarget)
			continue;
		Tree trFmt;
		trFmt = goSource.GetFormat(FPB_ALL, FOB_ALL, true, true);
		goTarget.ApplyFormat(trFmt, TRUE, TRUE);
	}
}
///End KEEP_LAYER_AXES_TITLE_POSITION

//static bool _merge_graph(GraphPage& gp, bool bKeepRatio, bool bSetScaleElement, bool bPortrait = false, bool bAddGraph = true, bool bUpdateLayerNum = true, bool bArrangeLayers = true, string* pstrErrMsg = NULL)
///Jasmine 05/17/07 ADD_MORE_ERROR_CHECKING
//static bool _merge_graph(GraphPage& gp, string* pstrErrMsg = NULL, bool bSetScaleElement = false, bool bPortrait = false, bool bArrange = true, bool bKeepRatio = false, bool bAddGraph = true, bool bUpdateLayerNum = true, bool bReArrange = true)
static int _merge_graph(
GraphPage& 			gp, 
string		 		strPages,
string& 			strErrMsg1, 
string& 			strErrMsg2, 
stLayersGridFormat 	stFormat,
int 				nRow,
int 				nCol,
int 				nUnit,
double 				dWidth, 
double 				dHeight, 
int					nScaleMode,
double				dFactor,
bool 				bReArrange = true,
bool 				bKeepRatio = false, 
bool 				bNewLayer = false,	//Add Extra Layer(s) for Grid
/// Iris 01/22/2009 ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
bool				bLinkArrangedLayer = false,
bool				bSmarkObject = false
///end ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
)
{
	strErrMsg1 = strErrMsg2 = "";
	vector<string> vsPages;
	strPages.GetTokens(vsPages, STR_PAGE_LIST_SEPARATOR);
	if(!vsPages.GetSize())
	{
		strErrMsg1 = _L("Graphs");
		return CER_EMPTY_VARIABLE;
	}
	
	int nErr;
	if( !arrange_layer_check_spacing(nRow, nCol, stFormat, nErr) )
	{
		if(CER_INPUT_ARGUMENT_LESS_THAN_SPECIFIED_VALUE == nErr)
		{
			strErrMsg1 = _L("Spacing");
			strErrMsg2 = "0";
		}
		return nErr;
	}
	
	if(0 >= dWidth || 0 >= dHeight)
	{
		strErrMsg1 = _L("Page size");
		return CER_MUST_LARGE_THAN_0;
	}
	if(nUnit < unit_inch || nUnit > unit_point)
	{
		strErrMsg1 = _L("Unit");
		return XFERR_INVALID_MSG;
	}
	///Jasmine 01/25/07 RETURN_FALSE_TO_SHOW_PAGE_INVALID, this help to check s_vsPages validity
	//if((bAddGraph || !bArrange) && !page_add_to_one_graph(gp, s_vsPages))
	if(!page_add_to_one_graph(gp, vsPages))
		return CER_PAGE_NAME_WRONG;
		
	///Jasmine 08/06/07 GET_AND_APPLY_FIRST_PAGE_LENGEND_MODE
	GraphPage 	gpSource(vsPages[0]);
	int nMode = get_page_legend_mode(gpSource);
	int nWarn = CER_NO_ERROR;
	for(int nPage = 1; nPage < vsPages.GetSize(); nPage++)
	{
		GraphPage gpSc(vsPages[nPage]);
		if(nMode != get_page_legend_mode(gpSc))
		{
			nWarn = XFWARN_DIFF_LEGEND_SETTING;
			break;
		}
	}
	///End GET_AND_APPLY_FIRST_PAGE_LENGEND_MODE
	_get_scale_elements(vsPages, s_vdScFixFactor);
	//Tree 	tr;
	//tr = gp.GetFormat(FPB_DIMENSION);
	/*
	if(lstrlen(strErrMsg))
	{
		if(pstrErrMsg)
			*pstrErrMsg = strErrMsg;
		return false;				
	}
	*/
	///End RETURN_FALSE_TO_SHOW_PAGE_INVALID
///End ADD_MORE_ERROR_CHECKING
	if(bReArrange)
	{
		//if(bAddGraph)
			_get_layer_ratios(gp, s_vdRatios);
		//if(bUpdateLayerNum)
			_update_graph(gp, nRow, nCol, bNewLayer);
		//if(bReArrange)//bArrangeLayers)		
			/// Iris 01/22/2009 ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
			//page_arrange_layers(gp, nRow, nCol, &stFormat);//, &bPortrait);///Jasmine 05/17/07 MOVE_OUT_PORTRAIT_OPTION
			///Jasmine 01/22/09 ARRANGE_CHILD_IS_NEWLY_ADDED_IN_VARIABLE_LIST
			//page_arrange_layers(gp, nRow, nCol, &stFormat, false, true, NULL, bLinkArrangedLayer, bSmarkObject);
			page_arrange_layers(gp, nRow, nCol, &stFormat, false, true, NULL, bLinkArrangedLayer, false, bSmarkObject, SA_SHOW_INNER_AXIS);///Jasmine 09/11/09 SMART_SHOW_TICK_AS_LAYMANAGE
			///End ARRANGE_CHILD_IS_NEWLY_ADDED_IN_VARIABLE_LIST
			///end ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
		if(bKeepRatio)
			_set_layer_ratios(gp, s_vdRatios);
	}
	//if(bSetScaleElement)
		_set_layer_scale_elements(gp, s_vdScFixFactor, nScaleMode, dFactor);
			
	///Jasmine QA80-10204 THEME_ACCESS_TO_PAGE_AUTO_LEGEND_AXIS_ITEMS
	//set_page_legend_mode(gp, nMode);
	GraphPage gpSc(vsPages[0]);
	Tree trSc, tr;
	trSc = gpSc.GetFormat(FPB_OTHER, FOB_OTHER, true, true);
	tr = gp.GetFormat(FPB_OTHER, FOB_OTHER, true, true);
	TreeNode trScFmt = trSc.Root.Legends;
	TreeNode trFmt = tr.Root.Legends;
	octree_copy_values_by_id(&trScFmt, &trFmt, true, STR_ID_ATTRIB, STR_ID_ATTRIB);		
	gp.ApplyFormat(tr, TRUE, TRUE);
	///End THEME_ACCESS_TO_PAGE_AUTO_LEGEND_AXIS_ITEMS
	_set_graph_size(gp, dWidth, dHeight, nUnit);
	gp.LT_execute("page.zoomWhole=1");

	_copy_layer_axes_format(gp, vsPages);	///Jasmine 01/25/10 QA80-14963 KEEP_LAYER_AXES_TITLE_POSITION

	return nWarn;//CER_NO_ERROR;
}


void merge_graph(const int& option, const string& graphs, const int& keep, const int& arrange, const int& row, const int& col, const int& newlayer, const int& aspectratio, const int& linkarrange, const int& smartarrange, const string& hint, const int& xgap, const int& ygap, const int& leftmg, const int& rightmg, const int& topmg, const int& bottommg, const int& portrait, const double& width, const double& height, const int& unit, const int& scalemode, const double& fixfactor)
{
	GraphPage gp;  
	/// Kenny 08/25/2009 QA81-14203 RESET_PAGE_NAME_IF_CREATED_FROM_OC
	//gp.Create(MERGE_GRAPH_TEMPLATE);	///Jasmine 01/27/07 to fix legends moving left bug
	gp.Create(MERGE_GRAPH_TEMPLATE, CREATE_DEFAULT_OPTIONS | CREATE_ENUM_EXIST_PAGE);	///Jasmine 01/27/07 to fix legends moving left bug
	/// End QA81-14203 RESET_PAGE_NAME_IF_CREATED_FROM_OC
	//set size
	//if(unit < PAGE_UNIT_INCH || unit > PAGE_UNIT_POINT || width <= 0 || height <= 0)
		//XF_THROW(CER_INVALID_ARGUMENT);	
	//if(!_merge_graph(gp, NULL, scalemode, portrait, arrange, aspectratio))
	double dWidth, dHeight;
	int nUnit;
	_update_size_setting(gp, width, height, unit, portrait, dWidth, dHeight, nUnit);	
	
	stLayersGridFormat stFormat;
	stFormat.nXGap 		= xgap;		
	stFormat.nYGap 		= ygap;		
	stFormat.nLeftMg 	= leftmg;
	stFormat.nRightMg 	= rightmg;		
	stFormat.nTopMg 	= topmg;
	stFormat.nBottomMg 	= bottommg;
	
	string strErrMsg1, strErrMsg2;
	int nErr = _merge_graph(gp, graphs, strErrMsg1, strErrMsg2, stFormat, row, col, 
							nUnit, dWidth, dHeight, scalemode, fixfactor,
							/// Iris 01/22/2009 ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
							//arrange, aspectratio, newlayer);
							arrange, aspectratio, newlayer, linkarrange, smartarrange);
							///end ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
	///Jasmine 08/06/07 GET_AND_APPLY_FIRST_PAGE_LENGEND_MODE
	if(XFWARN_DIFF_LEGEND_SETTING == nErr)
		warning_msg_box(nErr, strErrMsg1, false, 'W');///Jasmine 08/10/07 CP's fixed bug in 'W'
	///End GET_AND_APPLY_FIRST_PAGE_LENGEND_MODE
	else if(CER_NO_ERROR != nErr)
	{
		gp.Destroy();
		if(nErr == CER_LAYER_TOO_SMALL)
		{
			string strInfo;
			ocu_load_msg_str(XFERR_INVALID_OPERATION, &strInfo);
			XF_THROW_EX(nErr, strInfo);
		}
		if(strErrMsg1.IsEmpty())
			XF_THROW(nErr);	
		if(strErrMsg2.IsEmpty())
			XF_THROW_EX(nErr, strErrMsg1);
		XF_THROW_EX2(nErr, strErrMsg1, atoi(strErrMsg2));
	}
	//if(0 != unit || (portrait? DEFAULT_LANDSCAPE_WIDTH:DEFAULT_PORTRAIT_WIDTH) != width || (portrait? DEFAULT_LANDSCAPE_HEIGHT:DEFAULT_PORTRAIT_HEIGHT) != height)
	//not yet
	/*
	double 	dWidth, dHeight;
	int 	nUnit;
	_get_graph_size(gp, dWidth, dHeight, &nUnit);
	if(width || height)
	{
		if(width)
			dWidth = width;
		if(height)
			dHeight = height;
		_set_graph_size(gp, dWidth, dHeight, unit);
	}*/
	//gp.LT_execute("page.zoomWhole=1");
	
	///Jasmine 09/17/09 QA81-14321 SAVE_SPACING_SETTING_FOR_ARRANGEMENT
	if( !save_arrange_spacing_settings(gp, col, row, xgap, ygap, leftmg, rightmg, topmg, bottommg) )
		ASSERT(0);
	///End SAVE_SPACING_SETTING_FOR_ARRANGEMENT
	
	//delete source
	vector<string> vsPages;	
	graphs.GetTokens(vsPages, STR_PAGE_LIST_SEPARATOR);
	if(!keep)
	{
		for(int ii=0; ii<vsPages.GetSize(); ii++)
		{
			GraphPage gp = Project.GraphPages(vsPages[ii]);
			if(gp && !gp.GetEmbeddingInfo())
				gp.Destroy();
		}
	}
	
}

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

}

int merge_graph_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	return 0;
}
//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 merge_graph_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	
	if(!trGetN.IsValid())
		return;
	//init parameters: option and graphs
	if(is_use_origin_chm())
		trGetN.SetAttribute(STR_HELPID_ATTRIB, IDD_XF_MERGE_GRAPH);
	vector<string> vsGraphs;
	string strNames = trGetN.graphs.strVal;
	//---- Iris 01/04/2007 v8.0536 ADD_ACTIVE_PAGE_INTO_PAGE_OPTION
	/*
	if(!strNames.IsEmpty() && PDS_AUTO != okutil_cvt_str_to_predefined_type(strNames))
		trGetN.option.nVal = OPTION_SPECIFIED;
	/// Iris 12/18/2006 v8.0527 COMBO_TO_SEL_ALL_PAGES_IN_FOLDER_FOR_EXPORT_PAGE
	//int nGraphs = _get_merge_graphs(vsGraphs, trGetN.option.nVal, strNames);
	int nGraphs = get_folder_pages_name(vsGraphs, trGetN.option.nVal, strNames);
	///end COMBO_TO_SEL_ALL_PAGES_IN_FOLDER_FOR_EXPORT_PAGE
	*/
	///Jasmine 03/24/07 GET_GRAPH_IN_WKBOOK
	if(PDS_AUTO == okutil_cvt_str_to_predefined_type(trGetN.option.strVal))
	{
		int nActivePageType = Project.Pages().GetType();
		//---Jasmine 01/15/09 QA80-12966-P1
		//trGetN.option.nVal = EXIST_WKS == nActivePageType? OPTION_ACTIVE_PAGE : OPTION_ALL_IN_ACTIVE_FOLDER;
		trGetN.option.nVal = EXIST_WKS == nActivePageType? OPTION_ACTIVE_PAGE : OPTION_ALL_OPEN_IN_ACTIVE_FOLDER;
		//--- 
	}
	///End GET_GRAPH_IN_WKBOOK
	if(!strNames.IsEmpty())
	{
		if(PDS_AUTO == okutil_cvt_str_to_predefined_type(strNames))
			strNames = "";
		else if(-1 != nGetNDialog)
			trGetN.option.nVal = OPTION_SPECIFIED - PAGE_OPTION_OFFSET;
	}
	int nGraphs = get_folder_pages_name(vsGraphs, trGetN.option.nVal, PAGE_OPTION_OFFSET, strNames);
	//---- 
	if(trGetN.defaultsize.IsValid())
		trGetN.defaultsize.Remove();
	//s_vsPages = vsGraphs;	
	strNames.SetTokens(vsGraphs, STR_PAGE_LIST_SEPARATOR);//'|');
	///Kenny 7/16/2009 QA80-13966-P1 IMPROVE_ERROR_CHECKING_FOR_MERGE_GRAPH_INPUT_NAMES
	//trGetN.graphs.strVal = strNames;
	if(!strNames.IsEmpty())
		trGetN.graphs.strVal = strNames;
	///End QA80-13966-P1 IMPROVE_ERROR_CHECKING_FOR_MERGE_GRAPH_INPUT_NAMES
	///Jasmine 03/06/09 QA80-13231 KEEP_ROW_COL_NUMBER_IF_ONLY_GRAPH_ORDER_CHANGE
	trGetN.graphs.SetAttribute(MY_OLD_VALUE, strNames);
	//End KEEP_ROW_COL_NUMBER_IF_ONLY_GRAPH_ORDER_CHANGE
	
	if(PDS_AUTO == okutil_cvt_str_to_predefined_type(trGetN.unit.strVal))
		trGetN.unit.nVal = -1;
	//auto compute nRow×nCol
	int nRow, nCol;
	_get_default_row_col_number(page_get_layer_count(vsGraphs), nRow, nCol);	
	if(PDS_AUTO == okutil_cvt_str_to_predefined_type(trGetN.row.strVal) || !is_numeric(trGetN.row.strVal))
		trGetN.row.strVal = nRow;
	//s_nRow = atoi(trGetN.row.strVal);
	if(PDS_AUTO == okutil_cvt_str_to_predefined_type(trGetN.col.strVal) || !is_numeric(trGetN.col.strVal))
		trGetN.col.strVal = nCol;
	//s_nCol = atoi(trGetN.col.strVal);
	//s_bNewlayer = trGetN.newlayer.nVal;	
	///Jasmine 05/17/07 CLEAN_UP_CODES, reduce unnecessay static variables
	/*
	s_stFormat.nXGap = trGetN.xgap.nVal;
	s_stFormat.nYGap = trGetN.ygap.nVal;	
	s_stFormat.nLeftMg = trGetN.leftmg.nVal;
	s_stFormat.nRightMg = trGetN.rightmg.nVal;	
	s_stFormat.nTopMg = trGetN.topmg.nVal;	
	s_stFormat.nBottomMg = trGetN.bottommg.nVal;
	*/
	_get_scale_elements(vsGraphs, s_vdScFixFactor);	///Jasmine 03/29/07 ADD_SCALE_ELEMENT
	//s_nMode = trGetN.scalemode.nVal;
	//s_dFactor = trGetN.fixfactor.dVal;
	///End CLEAN_UP_CODES
}
//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 merge_graph_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
	return;
}

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

// 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
	if(!pgTemp)
		return;
	GraphPage gp = pgTemp;
	if(!gp.IsValid())
		return;
	//---Jasmine 12/05/08 v8.0982d Max said each tool should have its own template
	GraphPage gpTemplate;
	if( gpTemplate.Create(MERGE_GRAPH_TEMPLATE, CREATE_HIDDEN|CREATE_KEEP_LAYER_NAMES) )
	{
		page_clone(gpTemplate, gp);
		gpTemplate.Destroy();
	}
	//---
	gp.AxisLayerIcons = true;
	string strTempGP = gp.GetName();
	if(!trGetN.IsValid())
		return;
	TreeNode trGraphs = trGetN.graphs;
	//---- Iris 01/04/2007 v8.0536 ADD_ACTIVE_PAGE_INTO_PAGE_OPTION
	//trGraphs.Enable = trGetN.option.nVal == OPTION_SPECIFIED;
	trGraphs.Enable = trGetN.option.nVal == (OPTION_SPECIFIED - PAGE_OPTION_OFFSET)? ENABLE : ENABLE_READONLY_SCROLL;	///Jasmine 07/15/08 QA80-11845 ENABLE_READONLY_SCROLL_FOR_MULTI_EDIT
	//----
	trGraphs.SetAttribute(STR_EXCLUDE_PAGE_ATTRIB, strTempGP);
	//add Default size node
	double 	dWidth, dHeight;
	int 	nUnit;
	/*
	_get_graph_size(gp, dWidth, dHeight, &nUnit);
	if(PDS_AUTO == okutil_cvt_str_to_predefined_type(trGetN.width.strVal) || 0 >= atof(trGetN.width.strVal))
		trGetN.width.dVal = dWidth;
	dWidth = trGetN.width.dVal;
	dWidth = round(dWidth, 3);
	trGetN.width.dVal = dWidth;
	if(PDS_AUTO == okutil_cvt_str_to_predefined_type(trGetN.height.strVal) || 0 >= atof(trGetN.height.strVal))
		trGetN.height.dVal = dHeight;
	dHeight = trGetN.height.dVal;
	dHeight = round(dHeight, 3);
	trGetN.height.dVal = dHeight;
	if(PDS_AUTO == okutil_cvt_str_to_predefined_type(trGetN.unit.strVal) || PAGE_UNIT_INCH > atoi(trGetN.unit.strVal) || PAGE_UNIT_POINT < atoi(trGetN.unit.strVal))
		trGetN.unit.nVal = nUnit;
	nUnit = trGetN.unit.nVal;
	*/
	_update_size_setting(gp, trGetN.width.dVal, trGetN.height.dVal, trGetN.unit.nVal, trGetN.portrait.nVal, dWidth, dHeight, nUnit);
	trGetN.width.dVal = dWidth;
	trGetN.height.dVal = dHeight;
	trGetN.unit.nVal = nUnit;
	
	if(trGetN.width.dVal > trGetN.height.dVal)
		trGetN.portrait.nVal = 0;
	if(trGetN.width.dVal < trGetN.height.dVal)
		trGetN.portrait.nVal = 1;
	
	vector<string> vsUnits = {"inch","cm","mm","pixel","point"};
	TreeNode trDefaultSize = trGetN.InsertNode(trGetN.width, "defaultsize");
	//string strWidth = (string)(trGetN.portrait.nVal? DEFAULT_LANDSCAPE_WIDTH:DEFAULT_PORTRAIT_WIDTH) + " inch";
	//string strHeight = (string)(trGetN.portrait.nVal? DEFAULT_LANDSCAPE_HEIGHT:DEFAULT_PORTRAIT_HEIGHT) + " inch";
	string strWidth = (string)dWidth + " " + vsUnits[nUnit];
	string strHeight = (string)dHeight + " " + vsUnits[nUnit];
	trDefaultSize.strVal = strWidth + " x " + strHeight;
	trDefaultSize.Enable = 2;
	trDefaultSize.Show = 0;
	trDefaultSize.SetAttribute(STR_LABEL_ATTRIB, "Original Size");
	//
	trGetN.fixfactor.Enable = 2==trGetN.scalemode.nVal;
	
	//set ids
	_tree_set_data_id(trGetN, "option", DLG_OPTION);
	_tree_set_data_id(trGetN, "graphs", DLG_GRAPHS_NAMES);
	_tree_set_data_id(trGetN, "arrange", DLG_ARRANGE);	
	_tree_set_data_id(trGetN, "row", DLG_ROW_NUM);
	_tree_set_data_id(trGetN, "col", DLG_COL_NUM);
	_tree_set_data_id(trGetN, "keep", DLG_KEEP_SOURCE);
	_tree_set_data_id(trGetN, "newlayer", DLG_NEW_LAYERS);	
	_tree_set_data_id(trGetN, "aspectratio", DLG_KEEP_RATIO);	
	_tree_set_data_id(trGetN, "scalemode", DLG_SCALE_MODE);	
	_tree_set_data_id(trGetN, "fixfactor", DLG_FIXED_FACTOR);	
	_tree_set_data_id(trGetN, "portrait", DLG_PORTRAIT);
	_tree_set_data_id(trGetN, "width", DLG_WIDTH);
	_tree_set_data_id(trGetN, "height", DLG_HEIGHT);
	_tree_set_data_id(trGetN, "unit", DLG_UNIT);
	_tree_set_data_id(trGetN, "xgap", DLG_X_GAP);
	_tree_set_data_id(trGetN, "ygap", DLG_Y_GAP);
	_tree_set_data_id(trGetN, "leftmg", DLG_LEFT_MARGIN);
	_tree_set_data_id(trGetN, "rightmg", DLG_RIGHT_MARGIN);
	_tree_set_data_id(trGetN, "topmg", DLG_TOP_MARGIN);
	_tree_set_data_id(trGetN, "bottommg", DLG_BOTTOM_MARGIN);
	/// Iris 01/22/2009 ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
	_tree_set_data_id(trGetN, "linkarrange", DLG_LINK_ARRANGE);
	_tree_set_data_id(trGetN, "smartarrange", DLG_SMART_ARRANGE);
	///end ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
	
	trGetN.hint.Show = trGetN.smartarrange.nVal == true;
	_enable_arrange_setting_node(trGetN, trGetN.arrange.nVal);
	//if(_merge_graph(gp, trGetN.aspectratio.nVal, trGetN.scalemode.nVal, trGetN.portrait.nVal))
	//if(_merge_graph(gp, &strErrMsg, trGetN.scalemode.nVal, trGetN.portrait.nVal, trGetN.arrange.nVal, trGetN.aspectratio.nVal))
	stLayersGridFormat stFormat;
	stFormat.nXGap = trGetN.xgap.nVal;
	stFormat.nYGap = trGetN.ygap.nVal;	
	stFormat.nLeftMg = trGetN.leftmg.nVal;
	stFormat.nRightMg = trGetN.rightmg.nVal;	
	stFormat.nTopMg = trGetN.topmg.nVal;	
	stFormat.nBottomMg = trGetN.bottommg.nVal;
	
	string strErrMsg1, strErrMsg2;
	int nErr = _merge_graph(gp, trGetN.graphs.strVal, strErrMsg1, strErrMsg2, 
							stFormat, trGetN.row.nVal, trGetN.col.nVal,
							trGetN.unit.nVal, trGetN.width.dVal, trGetN.height.dVal, 
							trGetN.scalemode.nVal, trGetN.fixfactor.dVal,
							trGetN.arrange.nVal, trGetN.aspectratio.nVal, trGetN.newlayer.nVal,
							trGetN.linkarrange.nVal, trGetN.smartarrange.nVal/// Iris 01/22/2009 ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
							);
	if(CER_NO_ERROR == nErr || XFWARN_DIFF_LEGEND_SETTING == nErr)	///Jasmine 08/06/07 GET_AND_APPLY_FIRST_PAGE_LENGEND_MODE
	{
		bUpdateGrid = true;
	}
	else
	{		
		strErrMsg = nErr;
		if(nErr == CER_LAYER_TOO_SMALL)
		{
			strErrMsg += ":";
			int nInfo;
			if(stFormat.nXGap || 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;			
		}
		if(!strErrMsg1.IsEmpty())
		{
			strErrMsg += ":";
			strErrMsg += strErrMsg1;
		}
		if(!strErrMsg2.IsEmpty())
		{
			strErrMsg += "|";
			strErrMsg += strErrMsg2;
		}
	}
	bOKEnable = strErrMsg.IsEmpty();
}

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

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

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

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
	GraphPage gp = pgTemp;
	if(!gp.IsValid())
		return;
	strErrMsg = "";
	int nID;
	if(trNode.IsValid())
		trNode.GetAttribute(STR_DATA_ATTRIB, nID);//STR_DATAID_ATTRIB
		
	bool bAddGraph, bUpdateLayerNum, bReArrangeLayers, bPortrait, bKeepRatio, bSetScaleElement, bArrange;
	if(!nID)
		bReArrangeLayers = true;
	if(!nID ||nID == DLG_OPTION || nID == DLG_GRAPHS_NAMES)
	{  
		vector<string> vsGraphs;
		//---- Iris 01/04/2007 v8.0536 ADD_ACTIVE_PAGE_INTO_PAGE_OPTION
		//int nOption = (nID == DLG_GRAPHS_NAMES)? OPTION_SPECIFIED : trGetN.option.nVal;
		int nOption = (nID == DLG_GRAPHS_NAMES)? (OPTION_SPECIFIED - PAGE_OPTION_OFFSET) : trGetN.option.nVal;
		//----
		
		///Jasmine 03/06/09 QA80-13231 KEEP_ROW_COL_NUMBER_IF_ONLY_GRAPH_ORDER_CHANGE
		string strOldName;
		///End KEEP_ROW_COL_NUMBER_IF_ONLY_GRAPH_ORDER_CHANGE
		string strNames;
		string strNameCurrent = gp.GetName();
		TreeNode trGraphs = trGetN.FindNodeByAttribute(STR_DATA_ATTRIB, DLG_GRAPHS_NAMES);//tree_get_node_by_dataid(trGetN, DLG_GRAPHS_NAMES);
		if(trGraphs.IsValid())
		{
			strNames = trGraphs.strVal;
			if(!strNames.Right(1).Compare("\n"))	///Jasmine 01/27/07 remove the last blank rows
				strNames.TrimRight(STR_PAGE_LIST_SEPARATOR);
			///Jasmine 03/06/09 QA80-13231 KEEP_ROW_COL_NUMBER_IF_ONLY_GRAPH_ORDER_CHANGE
			trGraphs.GetAttribute(MY_OLD_VALUE, strOldName);
			///End KEEP_ROW_COL_NUMBER_IF_ONLY_GRAPH_ORDER_CHANGE
		}
		
		//---- Iris 01/04/2007 v8.0536 ADD_ACTIVE_PAGE_INTO_PAGE_OPTION
		/*
		/// Iris 12/18/2006 v8.0527 COMBO_TO_SEL_ALL_PAGES_IN_FOLDER_FOR_EXPORT_PAGE
		//int nGraphs = _get_merge_graphs(vsGraphs, nOption, strNames, strNameCurrent);
		int nGraphs = get_folder_pages_name(vsGraphs, nOption, strNames, strNameCurrent);
		///end COMBO_TO_SEL_ALL_PAGES_IN_FOLDER_FOR_EXPORT_PAGE
		*/
		int nGraphs = get_folder_pages_name(vsGraphs, nOption, PAGE_OPTION_OFFSET, strNames, strNameCurrent);
		//----
		///Kenny 7/16/2009 QA80-13966-P1 IMPROVE_ERROR_CHECKING_FOR_MERGE_GRAPH_INPUT_NAMES
		if ( nGraphs <= 0 && !strNames.IsEmpty() )
		{
			strErrMsg = CER_PAGE_NAME_WRONG;
			bOKEnable = false;
			return;
		}
		///End QA80-13966-P1 IMPROVE_ERROR_CHECKING_FOR_MERGE_GRAPH_INPUT_NAMES
		
		//s_vsPages = vsGraphs;
		strNames.SetTokens(vsGraphs, STR_PAGE_LIST_SEPARATOR);//'|');
		trGraphs.strVal = strNames;
		//---- Iris 01/04/2007 v8.0536 ADD_ACTIVE_PAGE_INTO_PAGE_OPTION
		//trGraphs.Enable = nOption == OPTION_SPECIFIED;
		trGraphs.Enable = nOption == (OPTION_SPECIFIED - PAGE_OPTION_OFFSET)? ENABLE : ENABLE_READONLY_SCROLL;	///Jasmine 07/15/08 QA80-11845 ENABLE_READONLY_SCROLL_FOR_MULTI_EDIT
		//----
		trGetN.option.nVal = nOption;
		
		///Jasmine 03/06/09 QA80-13231 KEEP_ROW_COL_NUMBER_IF_ONLY_GRAPH_ORDER_CHANGE
		bool bPageChange = true;
		if(nID == DLG_OPTION || nID == DLG_GRAPHS_NAMES)
		{
			///Kenny 7/16/2009 QA80-13966-P1 IMPROVE_ERROR_CHECKING_FOR_MERGE_GRAPH_INPUT_NAMES
			//if(strOldName.Compare(strNames) == 0)
			if(!strNames.IsEmpty() && strOldName.Compare(strNames) == 0)
			///End QA80-13966-P1 IMPROVE_ERROR_CHECKING_FOR_MERGE_GRAPH_INPUT_NAMES
			{
				bPageChange = false;
				return;
			}
			else
			{
				vector<string> vsOldNames;
				int nOldCount = strOldName.GetTokens(vsOldNames, STR_PAGE_LIST_SEPARATOR);
				if(nOldCount == nGraphs)
				{
					remove_if_in_list(vsOldNames, vsGraphs);
					if(vsOldNames.GetSize() == 0)
						bPageChange = false;
				}
			}
		}
		///End KEEP_ROW_COL_NUMBER_IF_ONLY_GRAPH_ORDER_CHANGE
		if(bPageChange)
		{
			trGraphs.SetAttribute(MY_OLD_VALUE, strNames);
			///Jasmine 
			//if(nID)//auto compute the nRow¡ÁnCo
			//{
				//s_nRow = trGetN.row.nVal = nRow;
				//s_nCol = trGetN.col.nVal = nCol;
			//}
			int nRow, nCol;
			_get_default_row_col_number(page_get_layer_count(vsGraphs), nRow, nCol);
			if(nID || PDS_AUTO == okutil_cvt_str_to_predefined_type(trGetN.row.strVal) || !is_numeric(trGetN.row.strVal))
				trGetN.row.nVal = nRow;
			if(nID || PDS_AUTO == okutil_cvt_str_to_predefined_type(trGetN.col.strVal) || !is_numeric(trGetN.col.strVal))
				trGetN.col.nVal = nCol;
		}
		bAddGraph = bUpdateLayerNum = bReArrangeLayers = bSetScaleElement = true;
		_get_scale_elements(vsGraphs, s_vdScFixFactor);
	}
	bArrange = trGetN.arrange.nVal;
	if(!nID || nID == DLG_ARRANGE)
	{
		_enable_arrange_setting_node(trGetN, bArrange);
		bReArrangeLayers = bUpdateLayerNum = bSetScaleElement = bArrange;
	}
	if(bArrange)
	{
		if(!nID || nID == DLG_ROW_NUM)
		{
			trGetN.row.nVal;
			bUpdateLayerNum = bReArrangeLayers = true;
		}
		if(!nID || nID == DLG_COL_NUM)
		{
			trGetN.col.nVal;	
			bUpdateLayerNum = bReArrangeLayers = true;
		}
		if(!nID || nID == DLG_NEW_LAYERS)
		{
			//s_bNewlayer = trGetN.newlayer.nVal;	
			bUpdateLayerNum = bReArrangeLayers = bSetScaleElement = true;
		}
		///Jasmine 05/17/07 CLEAN_UP_CODES, reduce unnecessay static variables
		/*
		if(!nID || nID == DLG_X_GAP)
		{
			s_stFormat.nXGap = trGetN.xgap.nVal; 
			bReArrangeLayers = true;
		}
		if(!nID || nID == DLG_Y_GAP)
		{
			s_stFormat.nYGap = trGetN.ygap.nVal; 
			bReArrangeLayers = true;	
		}
		if(!nID || nID == DLG_LEFT_MARGIN)
		{
			s_stFormat.nLeftMg = trGetN.leftmg.nVal;
			bReArrangeLayers = true;
		}
		if(!nID || nID == DLG_RIGHT_MARGIN)
		{
			s_stFormat.nRightMg = trGetN.rightmg.nVal;
			bReArrangeLayers = true;
		}
		if(!nID || nID == DLG_TOP_MARGIN)
		{
			s_stFormat.nTopMg = trGetN.topmg.nVal;
			bReArrangeLayers = true;
		}
		if(!nID || nID == DLG_BOTTOM_MARGIN)
		{
			s_stFormat.nBottomMg = trGetN.bottommg.nVal;
			bReArrangeLayers = true;
		}
		*/
		///End CLEAN_UP_CODES
		if( !nID || nID == DLG_KEEP_RATIO)
		{
			bReArrangeLayers = true;
		}
	}
	
	double 	dWidth, dHeight;
	int 	nUnit;
	_get_graph_size(gp, dWidth, dHeight, &nUnit);
	if(PDS_AUTO == okutil_cvt_str_to_predefined_type(trGetN.width.strVal))
		trGetN.width.dVal = dWidth;
	if(PDS_AUTO == okutil_cvt_str_to_predefined_type(trGetN.height.strVal))
		trGetN.height.dVal = dHeight;
	if(PDS_AUTO == okutil_cvt_str_to_predefined_type(trGetN.unit.strVal))
		trGetN.unit.nVal = nUnit;
	
	if(nID == DLG_PORTRAIT)// !nID || nID == DLG_PORTRAIT)
	{
		string 	strLT;
		//if(pbPortrait)
		//{
			bool bPortrait = trGetN.portrait.nVal;
			//strLT.Format("page -o %s",bPortrait?"p":"l");
			//gp.LT_execute(strLT);	
		//}
		//double dw, dh;
		//_get_graph_size(gp, dw, dh);
		double dd = trGetN.width.dVal;
		trGetN.width.dVal = trGetN.height.dVal;
		trGetN.height.dVal = dd;
		bUpdateGrid = bUpdateGraph = true;//bArrangeLayers
	}
	//set width and height first, set unit later
	if(!nID || nID == DLG_WIDTH || nID == DLG_HEIGHT)
	{
		if(trGetN.width.dVal <= 0 )
		{
			strErrMsg = CER_MUST_LARGE_THAN_0;
			strErrMsg += ":Width";
		}
		if(strErrMsg.IsEmpty() && trGetN.height.dVal <= 0 )
		{
			strErrMsg = CER_MUST_LARGE_THAN_0;
			strErrMsg += ":Height";
		}
		if(!strErrMsg.IsEmpty())
		{
			bOKEnable = false;
			return;
		}
		if(trGetN.width.dVal > trGetN.height.dVal)
			trGetN.portrait.nVal = 0;
		if(trGetN.width.dVal < trGetN.height.dVal)
			trGetN.portrait.nVal = 1;
		_set_graph_size(gp, trGetN.width.dVal, trGetN.height.dVal, trGetN.unit.nVal);
		bUpdateGraph = bUpdateGrid = true;
	}	
	if(nID == DLG_UNIT)//!nID || nID == DLG_UNIT)
	{
		_set_graph_unit(gp, trGetN.unit.nVal);
		///Jasmine 02/26/10 QA81-15144 UPDATE_PAGE_SIZE_ON_UNIT_CHANGE
		int nNewUnit;
		_get_graph_size(gp, dWidth, dHeight, &nNewUnit);
		ASSERT(nNewUnit == trGetN.unit.nVal);
		//End UPDATE_PAGE_SIZE_ON_UNIT_CHANGE
		trGetN.width.dVal = dWidth;
		trGetN.height.dVal = dHeight;
		bUpdateGrid = true;
	}
	if( !nID || nID == DLG_SCALE_MODE || nID == DLG_FIXED_FACTOR)
	{
		trGetN.fixfactor.Enable = 2==trGetN.scalemode.nVal;
		//s_nMode = trGetN.scalemode.nVal;
		//s_dFactor = trGetN.fixfactor.dVal;
		bSetScaleElement = true;
	}
	if( !nID || nID == DLG_SMART_ARRANGE)
	{
		trGetN.hint.Show = trGetN.smartarrange.nVal == true;
	}
	if(nID >= DLG_LAST_ITEM || nID == DLG_KEEP_SOURCE 
		|| (nID == DLG_OPTION && trGetN.option.nVal == option_specified) )	///Jasmine 05/08/08 DO_NOTHING_BUT_ENABLE_GRAPHS_IF_CHANGE_OPTION_TO_SPECIFY
		return;
		
	//check	and merge
	bPortrait = trGetN.portrait.nVal;
	bKeepRatio = trGetN.aspectratio.nVal;
	//if(_merge_graph(gp, bKeepRatio, bSetScaleElement, bPortrait, bAddGraph, bUpdateLayerNum, bArrangeLayers, &strErrMsg))
	//if(_merge_graph(gp, &strErrMsg, bSetScaleElement, bPortrait, bArrange, bKeepRatio, bAddGraph, bUpdateLayerNum, bReArrangeLayers))
	stLayersGridFormat stFormat;
	stFormat.nXGap = trGetN.xgap.nVal;
	stFormat.nYGap = trGetN.ygap.nVal;	
	stFormat.nLeftMg = trGetN.leftmg.nVal;
	stFormat.nRightMg = trGetN.rightmg.nVal;	
	stFormat.nTopMg = trGetN.topmg.nVal;	
	stFormat.nBottomMg = trGetN.bottommg.nVal;
	
	string strErrMsg1, strErrMsg2;
	int nErr = _merge_graph(gp, trGetN.graphs.strVal, strErrMsg1, strErrMsg2, 
							stFormat, trGetN.row.nVal, trGetN.col.nVal,
							trGetN.unit.nVal, trGetN.width.dVal, trGetN.height.dVal, 
							trGetN.scalemode.nVal, trGetN.fixfactor.dVal,
							trGetN.arrange.nVal, trGetN.aspectratio.nVal, trGetN.newlayer.nVal,
							trGetN.linkarrange.nVal, trGetN.smartarrange.nVal /// Iris 01/22/2009 ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH
							);
	if(CER_NO_ERROR == nErr || XFWARN_DIFF_LEGEND_SETTING == nErr)	///Jasmine 08/06/07 GET_AND_APPLY_FIRST_PAGE_LENGEND_MODE
	{
		//double dw, dh;
		//_get_graph_size(gp, dw, dh);
		//trGetN.width.dVal = dw;
		//trGetN.height.dVal = dh;
		bUpdateGraph = bUpdateGrid = true;
	}
	else
	{		
		strErrMsg = nErr;
		if(nErr == CER_LAYER_TOO_SMALL)
		{
			strErrMsg += ":";
			int nInfo;
			if(stFormat.nXGap || 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;			
		}
		if(!strErrMsg1.IsEmpty())
		{
			strErrMsg += ":";
			strErrMsg += strErrMsg1;
		}
		if(!strErrMsg2.IsEmpty())
		{
			strErrMsg += "|";
			strErrMsg += strErrMsg2;
		}
		bOKEnable = false;
	}
}

// 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)
{
	return;
}

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

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

