/*------------------------------------------------------------------------------*
 * File Name:				 													*
 * Creation: 																	*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * Hong 12/26/06 QA80-8662 ADD_SECOND_HEIGHT_FOR_LINK_LAYER						*
 * Jasmine 02/08/07 LAYER_SET_LINK_AND_UNIT										*
 * Jasmine 03/06/07 QA70-9433 CONVERT_LAYER_UNITS								*
 * Jasmine 03/12/07 ADD_CUSTOM_TO_AXIS_SCALE_LINK								*
 * Jasmine 06/15/07 MODIFICATION_SET_COLOR_FUNCTION								*
 * Jake 07/17/07 GET_LEGEND_MODE_TYPE											*
 * Arvin 07/19/07 USE_STRING_TYPE_LEGEND_DIRECTLY as CP said					*
 * Folger 07/24/07 GET_RANGE_CONTENT_FROM_DATAPLOT								*
 *	Hong 08/08/07 QA80-10064 FIX_LEGEND_COMBINE_FAIL_KEEP_ORIGIN_ORDER			*
 * Jasmine 08/13/07 MAKE_APPLY_UNDOABLE											*
 *	Kyle 08/15/08 QA80-12022 CHANGE_PROTOTYPE_OF_AXIS_SET_SACLE					*
 *	Sophy 1/9/2009 v8.0995 QA80-12591-P7 FIX_USE_SOURCE_GRAPH_SCALE_TYPE_GIVE_WRONG_RESULT
 *	Folger 01/12/09 v8.0995c AVOID_MULTIPLE_GET_FORMAT_ALL_TO_SPEED_UP_LAYER_MANAGEMENT_ON_SELECTED_LAYER_CHANGE
 *	Jasmine 03/20/09 CENTRAILIZE_ADD_LAYER_CODE_IN_LAYADD_XF_AND_LAYERMANAGEMENT*
 * Kenny 03/28/2009 ADD_AXIS_TOTAL_ENUM											*
 * Kenny 03/31/2009 ADD_FUNC_GET_INSET_LAYER_SIZE								*
 * Kenny 03/31/2009 NO_OFFSET_TO_NEWLY_ADDED_LAYER_IF_NOT_OVERLAPPING			*
 * Kenny 03/31/2009 ADD_PARAM_ACTIVE_NEW_LAYER_TO_FUNC_PAGE_ADD_LAYER			*
 * Kenny 04/01/2009 ADD_FUNC_LINKED_LAYER_GET_OUTMOST_LAYER_AXES				*
 * Kenny 04/01/2009 ADD_FUNC_GET_LINKED_LAYER_ANCESTOR							*
 * Kenny 04/03/2009 QA80-13370 ADD_MACRO_AUTO_FIND_LAYER_LINK_TO				*
 * Kenny 05/31/2009 ADD_FUNC_GET_PLOT_COLOR_FOR_VERTICAL_CURSOR					*
 *	Kenny 07/24/2009 QA80-13992 NEW_XF_FOR_GENERAL_MULTI_AXES_PLOTTING			*
 *	Kenny 07/31/2009 QA80-13992 SUPPORT_GET_PAGE_SIZE_FOR_MULTI_Y_AXES_XF		*
 *	Kenny 08/12/2009 QA80-14100 USE_UNDEFINED_STATUS_FOR_UNCOMMON_PROPERTIES	*
 *	Jasmine 08/18/09 GUI_TO_ADD_2ND_NONLINEAR_AXIS								*
 *	Folger 09/10/09 PEAK_LABEL_PLOT_IN_PA_SHOULD_HAVE_CERTAIN_OFFSET			*
 *	Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
 *	Kyle 03/11/2010 PICK_PEAK_ROI_TOOL_SHARES_UTILS_FUNCTION_WITH_PA			*
 *------------------------------------------------------------------------------*/
 
#ifndef __GRAPH_UTILS_H__
#define __GRAPH_UTILS_H__

#define  	ACTIVE_LAYER		-1
#define		ALL_LAYER			99

enum
{
	AXIS_X,
	AXIS_Y,
	AXIS_Z,
	
	AXIS_LAST_ITEMS
};

enum
{
	AXIS_BOTTOM,
	AXIS_LEFT,
	AXIS_TOP,	
	AXIS_RIGHT,
	
	AXIS_TOTAL,	///Kenny 03/28/2009 ADD_AXIS_TOTAL_ENUM
};

enum
{
	POS_LEFT,
	POS_TOP,
	POS_RIGHT,
	POS_BOTTOM
};
enum
{
	TICK_IN_OUT,
	TICK_IN,
	TICK_OUT,
	TICK_NONE
};
///Jasmine 03/06/07 QA70-9433 CONVERT_LAYER_UNITS
//please use LAYER_OMETRICS in OC_const.h instead
/*enum
{
	UNIT_PAGE,
	UNIT_INCH,
	UNIT_CM,
	UNIT_MM,
	UNIT_PIXEL,
	UNIT_POINT,
	UNIT_LAYER
};*/
///End CONVERT_LAYER_UNITS
enum
{
	LINK_NONE,
	LINK_STRAIGHT,
	LINK_CUSTOM
};

/// Iris 01/22/2009 ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH, moved from LayerManagement.c
///Kyle 01/22/2009 SHOW_DEFAULT_TITLE_IF_TITLE_IS_EMPTY
#define STR_X_DEFAULT_TITLE "%(?X)"
#define STR_Y_DEFAULT_TITLE "%(?Y)"
///End SHOW_DEFAULT_TITLE_IF_TITLE_IS_EMPTY
///end ADDED_TWO_OPTIONS_LINK_TO_AND_SMART_OBJECTS_WHEN_ARRANGE_IN_MERGE_GRAPH

///Sophy 1/9/2009 v8.0995 QA80-12591-P7 FIX_USE_SOURCE_GRAPH_SCALE_TYPE_GIVE_WRONG_RESULT move to analysis_utils.h
////---- Iris 11/20/2008 v8.0975d QA80-12591-S1 CENTRALIZE_NEW_X_DATA_TYPE_AND_LOG_TYPE_CODES
//enum
//{
	//SCALE_TYPE_LINEAR,
	//SCALE_TYPE_LOG10,
	//SCALE_TYPE_PROBABILITY,
	//SCALE_TYPE_PROBIT,
	//SCALE_TYPE_PECIPROCA,
	//SCALE_TYPE_OFFSET_RECIPROCAL,
	//SCALE_TYPE_LOGIT,
	//SCALE_TYPE_IN,
	//SCALE_TYPE_LOG2
//};
////----
///end FIX_USE_SOURCE_GRAPH_SCALE_TYPE_GIVE_WRONG_RESULT
///Jasmine 02/08/07 LAYER_SET_LINK_AND_UNIT
///Jasmine 03/12/07 ADD_CUSTOM_TO_AXIS_SCALE_LINK
/**
	Make other layer link to nParentLayer layer and set X Axis Link and Y Axis Link and layer units.
	Parameters:
		gl = [input/output] graph layer to link to another layer
		nParentLayer = [input] layer index of the layer to link to
		XAxis = [input] option of X Axis Link. Can be one of
				0 : None
				1 : Straight(1 to 1)
				2 : Custom
		YAxis = [input] option of Y Axis Link. Same as XAxis
		pnUnit = [input] pointer of unit set to layer unit
	Return:
		true for success
*/
bool	layer_set_link(GraphLayer& gl, int nParentLayer = 0, int XAxis = 0, int YAxis = 0, int* pnUnit = NULL, string strX1 = "", string strX2 = "", string strY1 = "", string strY2 = "");
typedef bool (*FUNC_LAYER_SET_LINK) (GraphLayer& gl, int nParentLayer = 0, int XAxis = 0, int YAxis = 0, int* pnUnit = NULL, string strX1 = "", string strX2 = "", string strY1 = "", string strY2 = "");
///------ Folger 01/12/09 v8.0995c AVOID_MULTIPLE_GET_FORMAT_ALL_TO_SPEED_UP_LAYER_MANAGEMENT_ON_SELECTED_LAYER_CHANGE
//bool 	layer_get_link(GraphLayer& gl, int& nParentLayer, int* pXAxis = NULL, int* pYAxis = NULL, int* pnUnit = NULL, string* pX1 = NULL, string* pX2 = NULL, string* pY1 = NULL, string* pY2 = NULL);
bool 	layer_get_link(GraphLayer& gl, int& nParentLayer, int* pXAxis = NULL, int* pYAxis = NULL, int* pnUnit = NULL, string* pX1 = NULL, string* pX2 = NULL, string* pY1 = NULL, string* pY2 = NULL, TreeNode& trFmt = NULL);
///------ End AVOID_MULTIPLE_GET_FORMAT_ALL_TO_SPEED_UP_LAYER_MANAGEMENT_ON_SELECTED_LAYER_CHANGE
///End ADD_CUSTOM_TO_AXIS_SCALE_LINK
///End LAYER_SET_LINK_AND_UNIT
/**
	Make other layers link to bBaseLayer layer and prepare more layers if the current total number of layers less than specified number.
	The new layer duplicate on nBaseLayer+1 layer if this layer is valid, else duplicate nBaseLayer layer. The arrange all layers to 
	1 column and n rows with specified top margin and bottom margin.
	Parameters:
		gp = [input/output] graph page to prepare and link layers
		nLayers = [input] total number of layers in gp
		nBaseLayer = [input] base layer index, nBaseLayer+1 will be used as a template layer to duplicate to create other layers if the layer is valid, else use nBaseLayer layer as template.
		dTopMargin = [input] percent of page height as top margin for the top layer
		dBottomMargin = [input] percent of page height as bottom margin of bottom layer, < 0 to indicate not to change so original 1st layer bottom will be kept
	Return:
		true for success		
*/
bool arrange_x_link_layers(GraphPage& gp, int nLayers, double dTopMargin = 2, double dBottomMargin = 6, int nBaseLayer = 0, bool bReuseExisting = true);

/// SY 2006-11-06 v8.0505 ADD_SCALER_OBJECT
/**
	Prepare a graph page with multiple linked layers sharing X axis. We assume graph has at least two layers and the nBaseLayer+1 layer is used as a
	template to duplicate to form the other layers
	Parameters:
		gp = [input/output] graph page to prepare layers
		nLayers = [input] total number of layers in gp
		nBaseLayer = [input] base layer index, nBaseLayer+1 will be used as a template layer to duplicate to create other layers
		dTopMargin = [input] percent of page height as top margin for the top layer
		dBottomMargin = [input] percent of page height as bottom margin of bottom layer, < 0 to indicate not to change so original 1st layer bottom will be kept
	Return:
		true for success
*/
bool construct_x_link_layers_using_template_layer(GraphPage& gp, int nLayers, int nBaseLayer = 0, double dTopMargin = 2.0, double dBottomMargin = -1000);


/// Hong 12/26/06 QA80-8662 ADD_SECOND_HEIGHT_FOR_LINK_LAYER
/**
	Add a layer into a graph page and link the layer to the 1st layer to sharing X axis. We assume graph has at least two layers and the 2nd layer is used as a
	template to duplicate to form the other layers
	Parameters:
		gp = [input/output] graph page to prepare layers
		gl = [input/output] the new added layer
		nTemplateLayer [input] index of layer to duplicate to add new layers
		nBaseLayer = [input] index of layer as base to form link layer group
		nHeightChangeLayer = [input] index of layer to start use second heigth
		nSecondHeight = [input] the second height
	Return:
		true for success
*/
//bool add_x_link_layer(GraphPage& gp, GraphLayer& gl, int nTemplateLayer = 1, int nBaseLayer = 0);
bool add_x_link_layer(GraphPage& gp, GraphLayer& gl, int nTemplateLayer = 1, int nBaseLayer = 0, int nHeightChangeLayer = -1, int nSecondHeight = 50);

/**
	Arrange all layers(linked) in page as 1 Column and n Row
	Parameters:
		gp = [input/output] graph page to prepare layers
		nFirstLayer = [input] index of first layer in the group
		nLastLayer = [input] index of last layer in the group, -1 if to the last layer
		dTopMargin = [input] percent of page height as top margin for the top layer
		dBottomMargin = [input] percent of page height as bottom margin of bottom layer, < 0 to indicate not to change so original 1st layer bottom will be kept
		nHeightChangeLayer = [input] index of layer to start use second heigth
		nSecondHeight = [input] the second height
	Return:
		true for success
*/
//bool page_arrange_link_layers(GraphPage& gp, int nFirstLayer = 0, int nLastLayer = -1, double dTopMargin = 2.0, double dBottomMargin = -1000);
bool page_arrange_link_layers(GraphPage& gp, int nFirstLayer = 0, int nLastLayer = -1, double dTopMargin = 2.0, double dBottomMargin = -1000, int nHeightChangeLayer = -1, int nSecondHeight = 50);
/// end ADD_SECOND_HEIGHT_FOR_LINK_LAYER
/// end ADD_SCALER_OBJECT

/**
		Toggles the axes and axes labels on or off for layer nLayer. 
		Use ALL_LAYER as layer index to toggle axes + labels for all layers, 
		or use ACTIVE_LAYER as layer index to toggle axes + labels for the active layer.
	Parameters:
		gp = [input] to indicate the graph page
		nLayer = [input] to indicate the layer index
		nAxis = [input] to indicate which axis to toggle
	Example1:
		void layer_toggle_axis()
		{
			GraphPage 	gl = Project.ActiveLayer();	
			axis_toggle_show(gl, AXIS_BOTTOM); //to toggle X axes and labels for the layer
			axis_toggle_show(gp, AXIS_LEFT); //to toggle Y axes and labels for the layer
		}
*/
//bool 	axis_toggle_show(GraphLayer& gl, int nAxis = AXIS_BOTTOM);

/**
*/
bool	page_zoom(GraphPage& gp);

///Jasmine 03/20/09 CENTRAILIZE_ADD_LAYER_CODE_IN_LAYADD_XF_AND_LAYERMANAGEMENT
class AddingLayerType
{
public:
	string 	GetTypeList(bool bLocalizd);
	string 	GetAddingName(int nAddingType);
	bool 	GetAxisSettings(int nAddingType, int& bottom, int& left, int& top, int& right, bool& link, int& xaxis, int& yaxis);
	bool 	IsLink(int nAddingType);
	bool	HasNoXAxis(int nAddingType);
	bool	HasNoYAxis(int nAddingType);
	bool	IsInset(int nAddingType);
	bool	IsInsetData(int nAddingType);
	bool 	IsValid(int nAddingType);
	void	GetInsetLayerSize(int* pnLeft, int* pnTop, int* pnWidth, int* pnHeight);	///Kenny 03/31/2009 ADD_FUNC_GET_INSET_LAYER_SIZE
};
///End CENTRAILIZE_ADD_LAYER_CODE_IN_LAYADD_XF_AND_LAYERMANAGEMENT

///Kenny 04/01/2009 ADD_FUNC_LINKED_LAYER_GET_OUTMOST_LAYER_AXES

// Comments last updated by Kenny on 04/01/2009
/**$
	Remarks:
		Find the target layer's outmost axes and the layers those axes belonged to from the linked layer family.
		For each axis, if there's not any other axis was shown and placed at the separate axis's default position, return result will be set to -1
	Example1:
		int linked_layer_get_outmost_layer_axes_ex1()
		{
			GraphLayer gl = Project.ActiveLayer();
			if (!gl)
			{
				out_str("No GraphPage!");
				return -1;
			}
			bool bGetAxes[AXIS_TOTAL];
			bGetAxes[AXIS_TOP] = true;		// Getting the axes and corresponding layers at the outmost position of target layer's top-X axis and right-Y
			bGetAxes[AXIS_RIGHT] = true;

			int nOutmostAxesPos[AXIS_TOTAL];
			int nOutmostLayerIndices[AXIS_TOTAL];
			int nOutmostAxesType[AXIS_TOTAL];

			int nRet = linked_layer_get_outmost_layer_axes(gl, bGetAxes, nOutmostAxesPos, nOutmostLayerIndices, nOutmostAxesType);
			return nRet;
		}
	Parameters:
		gl = [input] Target layer object.
		pbGetAxes = [input] Indicates whether or not find separate axis, e.g. setting pbGetAxes[AXIS_BOTTOM] = true means finding bottommost axis that outside target layer's bottom-X axis.
		pnOutmostAxesPos = [output] The outmost axes' position, in logical units(M_PIXEL), or -1 if not found or pbGetAxes[n] == false
		pnOutmostLayerIndices = [output] The layer indices that the outmost axes' belonged to, or -1 as commentation of pnOutmostAxesPos
		pnOutmostAxesType = [output] The outmost axes' type, such as AXIS_BOTTOM/AXIS_LEFT/.../etc, or -1 as commentation of pnOutmostAxesPos
		nTolerance = [input] A tolerance value for determinating whether separate axis is placed at the default position
	Return:
		Return 0 if success
*/
int linked_layer_get_outmost_layer_axes(
	const GraphLayer& gl,			// Target layer object.
	const bool* pbGetAxes,			// Indicates whether or not find separate axis
	int* pnOutmostAxesPos,			// Return the outmost axes' position
	int* pnOutmostLayerIndices,		// Return the layer indices that the outmost axes' belonged to
	int* pnOutmostAxesType,			// Return the outmost axes' type
	const uint nTolerance = 0		// A tolerance value for determinating whether separate axis is placed at the default position
	);
///End ADD_FUNC_LINKED_LAYER_GET_OUTMOST_LAYER_AXES

///Kenny 04/01/2009 ADD_FUNC_GET_LINKED_LAYER_ANCESTOR
bool	is_valid_layer_index(GraphPage& gp, int index);
int get_linked_layer_ancestor(const GraphPage& gp, const uint nLayerIndex, bool bGetOverlappedLayer = false);
///End ADD_FUNC_GET_LINKED_LAYER_ANCESTOR

///Kenny 03/31/2009 NO_OFFSET_TO_NEWLY_ADDED_LAYER_IF_NOT_OVERLAPPING
enum 
{
	ADD_LAYER_INIT_SIZE_POS_NONE				= 0,
	ADD_LAYER_INIT_SIZE_POS_MOVE_OFFSET			= 1,
	ADD_LAYER_INIT_SIZE_POS_SAME_AS_PREVIOUS	= 2, 
};
///End NO_OFFSET_TO_NEWLY_ADDED_LAYER_IF_NOT_OVERLAPPING

#define AUTO_FIND_LAYER_LINK_TO		-1	///Kenny 04/03/2009 QA80-13370 ADD_MACRO_AUTO_FIND_LAYER_LINK_TO

/**
*/
///Kenny 03/31/2009 ADD_PARAM_ACTIVE_NEW_LAYER_TO_FUNC_PAGE_ADD_LAYER
/////Kenny 03/31/2009 NO_OFFSET_TO_NEWLY_ADDED_LAYER_IF_NOT_OVERLAPPING
/////// Iris 01/06/2009 v8.0993e ADD_LAYER_BY_INSET8_OTP_TO_SET_SIZE_ON_AXIS_LABEL
//////int	page_add_layer(GraphPage& gp, bool bBottom = true, bool bLeft = true, bool bTop = false, bool bRight = false, bool bAutoInitSizePosition = true, int nLinkTo = -1, int nXAxisLink = LINK_NONE, int nYAxisLink = LINK_NONE, int *pnNewLayerSizeUnit = NULL, int *pnNewLayerLeft = NULL, int *pnNewLayerTop = NULL, int *pnNewLayerWidth = NULL, int *pnNewHeight = NULL, int nTemplateLayer = -1);
////int	page_add_layer(GraphPage& gp, bool bBottom = true, bool bLeft = true, bool bTop = false, bool bRight = false, bool bAutoInitSizePosition = true, int nLinkTo = -1, int nXAxisLink = LINK_NONE, int nYAxisLink = LINK_NONE, int *pnNewLayerSizeUnit = NULL, int *pnNewLayerLeft = NULL, int *pnNewLayerTop = NULL, int *pnNewLayerWidth = NULL, int *pnNewHeight = NULL, int nTemplateLayer = -1, LPCSTR lpcszTemplate = NULL);
//int	page_add_layer(GraphPage& gp, bool bBottom = true, bool bLeft = true, bool bTop = false, bool bRight = false, int nAutoInitSizePosition = ADD_LAYER_INIT_SIZE_POS_MOVE_OFFSET, int nLinkTo = -1, int nXAxisLink = LINK_NONE, int nYAxisLink = LINK_NONE, int *pnNewLayerSizeUnit = NULL, int *pnNewLayerLeft = NULL, int *pnNewLayerTop = NULL, int *pnNewLayerWidth = NULL, int *pnNewHeight = NULL, int nTemplateLayer = -1, LPCSTR lpcszTemplate = NULL);
int	page_add_layer(GraphPage& gp, bool bBottom = true, bool bLeft = true, bool bTop = false, bool bRight = false, int nAutoInitSizePosition = ADD_LAYER_INIT_SIZE_POS_MOVE_OFFSET, bool bActivateNewLayer = true, int nLinkTo = -1, int nXAxisLink = LINK_NONE, int nYAxisLink = LINK_NONE, int *pnNewLayerSizeUnit = NULL, int *pnNewLayerLeft = NULL, int *pnNewLayerTop = NULL, int *pnNewLayerWidth = NULL, int *pnNewHeight = NULL, int nTemplateLayer = -1, LPCSTR lpcszTemplate = NULL);
///////end ADD_LAYER_BY_INSET8_OTP_TO_SET_SIZE_ON_AXIS_LABEL
/////End NO_OFFSET_TO_NEWLY_ADDED_LAYER_IF_NOT_OVERLAPPING
///End ADD_PARAM_ACTIVE_NEW_LAYER_TO_FUNC_PAGE_ADD_LAYER

///Jasmine 03/06/07 QA70-9433 CONVERT_LAYER_UNITS
/*no need
int		layer_get_unit(GraphLayer& gl);
bool	layer_set_unit(GraphLayer& gl, int nUnit);
*/
///End CONVERT_LAYER_UNITS
/**
*/
string	unit_index_to_str(int unit);

/**
		Reports size of layer nLayer in active units. Use ALL_LAYER as layer index to report size of all layers.
	Example1:
		void layer_get_size_ex1()
		{
			GraphPage 	gl = Project.ActiveLayer();	
			
			int			nUnit;
			double 		dWidth, dHeight;
			layer_get_size(gl, dWidth, dHeight, &nUnit); //get the width and height of the active layer	
		}
*/
bool	layer_get_size(GraphLayer& gl, double& dWidth, double& dHeight, int* pUnit = NULL);

/**
*/
bool	layer_set_width(GraphLayer& gl, double& dWidth, int* pUnit = NULL);

/**
*/
bool	layer_set_height(GraphLayer& gl, double& dHeight, int* pUnit = NULL);

/**
*/
bool	layer_set_size(GraphLayer& gl, double& dWidth, double& dHeight, int* pUnit = NULL);

/**
*/
bool	layer_copy_size(GraphLayer& glSource, GraphLayer glDest);

/**
*/
bool	layer_swap_size(GraphLayer& glSource, GraphLayer glDest);	

/**
*/
bool	layer_get_position(GraphLayer& gl, double* pLeft = NULL, double* pTop = NULL, double* pRight = NULL, double* pBottom = NULL, int* pUnit = NULL);

/**
*/
bool 	layer_set_position(GraphLayer& gl, double dLeft = 0, double dTop = 0, int* pUnit = NULL);

/**
*/
bool	layer_swap_position(GraphLayer& glSource, GraphLayer glDest);

/**
*/
bool	layer_set_left(GraphLayer& gl, double dLeft = 0, int* pUnit = NULL);

/**
*/
bool	layer_set_top(GraphLayer& gl, double dTop = 0, int* pUnit = NULL);

/**
*/
bool	layer_set_right(GraphLayer& gl, double dRight, int* pUnit = NULL);

/**
*/
bool	layer_set_bottom(GraphLayer& gl, double dBottom, int* pUnit = NULL);

/**
*/
bool	layer_aligns(GraphLayer& glSource, GraphLayer& glDest, int nDirection = POS_LEFT);

/**
*/
bool	layer_reorder(GraphLayer& gl, int nNewIndex);

/**
*/
bool	layer_zoom(GraphLayer& gl);

/**
*/
bool	layer_toggle(GraphLayer& gl);

/**
*/
bool	layer_set_ratio(GraphLayer& gl, double dRatio);

/**
*/
double	layer_get_ratio(GraphLayer& gl);

/**
*/
bool	layer_set_scale_elements(GraphLayer& gl, int nMode = 0, double dFactor = 1, bool bUndo = false);///Jasmine 08/13/07 MAKE_APPLY_UNDOABLE 

/**
*/
bool	layer_get_scale_elements(GraphLayer& gl, int& nMode, double* pdFactor = NULL);

/**
*/
bool	has_z_axis(GraphLayer& gl);

/**
*/
bool	axis_get_sacle(GraphLayer& gl, string strAxis, double& dFrom, double& dTo);

/**
*/
///Kyle 08/15/08 QA80-12022 CHANGE_PROTOTYPE_OF_AXIS_SET_SACLE
//bool	axis_set_sacle(GraphLayer& gl, string strAxis, double dFrom, double dTo);
bool	axis_set_sacle(GraphLayer& gl, string strAxis, double dFrom, double dTo, double dInc = -1);
///End CHANGE_PROTOTYPE_OF_AXIS_SET_SACLE
/**
*/
///Jasmine 01/07/09 v8.0994d QA80-10257 REWRTIE_WITH_APPLY_FORMAT_TO_UNDO
//bool	axis_set_scale_type(GraphLayer& gl, string strAxis, int nType);
bool	axis_set_scale_type(GraphLayer& gl, string strAxis, int nType, bool bUndo = false);
///End REWRTIE_WITH_APPLY_FORMAT_TO_UNDO

/**
*/
bool	axis_get_scale_type(GraphLayer& gl, int* pnXScale = NULL, int* pnYScale = NULL);

/**
*/
bool	layer_copy_axis_scales(GraphLayer& glSource, GraphLayer& glDest, LPCSTR lpcszAxis = NULL);

/**$
*/
//------- CPY 5/14/07 BETTER_X_AXIS_HIDE_SHOW_BASED_ON_LAYER_GAP_AND_POSITION
//bool	axis_set_show(GraphLayer& gl, int nAxis, bool bShow = true, bool bCreateIfNotExist = true);
bool	axis_set_show(GraphLayer& gl, int nAxis, bool bShow = true, int nTickLabels = -1, int nTitle = -1);
//-------

/**
*/
bool	axis_get_show(GraphLayer& gl, bool* pbBottom = NULL, bool* pbLeft = NULL, bool* pbTop = NULL, bool* pbRight = NULL);

/**
*/
bool	axis_label_set_show(GraphLayer& gl, int nAxis, bool bShow = true, bool bCreateIfNotAxis = true);

/**
	Return:
		returns -1 means no this axis, 0 means the axis exists but hidden, 1 means axis shows.
*/
int		axis_label_get_show(GraphLayer& gl, int nAxis);

///Jasmine 08/18/09 GUI_TO_ADD_2ND_NONLINEAR_AXIS	
/**$
		Get or set the axes tick label formula. 
	Parameters:
		gl = [input] to indicate the graph layer
		nAxis = [input] to indicate the axes. It can be AXIS_BOTTOM, AXIS_LEFT, AXIS_TOP or AXIS_RIGHT.
		strFormula = [input/output] axes tick label formula
	Example1:
		void get_set_axis_label_formula_ex()
		{
			GraphLayer gl = Project.ActiveLayer();	
			string strFormula = "2*x";
			if(	!get_set_axis_label_formula(gl, AXIS_BOTTOM, strFormula, false) )
				out_str("fail");
			
			string strResult;
			get_set_axis_label_formula(gl, AXIS_BOTTOM, strResult, true);
			out_str(strResult);
		}
*/
bool	get_set_axis_label_formula(GraphLayer& gl, int nAxis, string& strFormula, bool bGet = true);
///End GUI_TO_ADD_2ND_NONLINEAR_AXIS	

/**
*/
bool	axis_tick_set_show(GraphLayer& gl, int nAxis, bool bShow = true, bool bCreateIfNotAxis = true);

/**
	Return:
		returns -1 means no this axis, 0 means the axis exists but hidden, 1 means axis shows.
*/
int		axis_tick_get_show(GraphLayer& gl, int nAxis);

/**
*/
bool	axis_set_tick_format(GraphLayer& gl, int nAxis, int nFormat, bool bMajor = true);

/**
*/
int		axis_get_tick_format(GraphLayer& gl, int nAxis, bool bMajor = true);

/**
*/
bool	axis_title_set_show(GraphLayer& gl, int nAxis, bool bShow = true, bool bCreateIfNotAxis = true);

/**
	Return:
		returns -1 means no this axis, 0 means the axis exists but hidden, 1 means axis shows.
*/
int		axis_title_get_show(GraphLayer& gl, int nAxis);


/**
	change an existing line graph into an area graph
	Example:
	void plot_area_graph(int nY=1, int nX = 0)
	{
		Worksheet wks = Project.ActiveLayer();
		DataRange dr;
		
		dr.Add(wks, nX, "X");
		dr.Add(wks, nY, "Y");
		
		GraphPage gp;
		gp.Create("Origin");
		if( gp )
		{
			GraphLayer gl = gp.Layers();
			if( gl )
			{
				int nPlot = gl.AddPlot(dr, IDM_PLOT_LINE);
				DataPlot dp = gl.DataPlots(nPlot);
				plot_change_to_area_graph(dp);
				gl.Rescale();
			}
		}
	}
*/
bool plot_change_to_area_graph(DataPlot& dp, int nColor = SYSCOLOR_LTGRAY);

/**$
*/
void update_axis_list(GraphLayer &gl, string &strAxisList);

/**$
*/
bool reorder_graph_layer(GraphPage& gp, const vector<int> vnDest);

/**$
*/
int graph_get_draw_order(GraphPage& gp);
/**$
*/
void graph_set_draw_order(GraphPage& gp, bool bSequence = false);

///Jasmine 01/07/09 v8.0994d QA80-10257 REWRTIE_WITH_APPLY_FORMAT_TO_UNDO
///Jasmine 06/15/07 MODIFICATION_SET_COLOR_FUNCTION
/**$
*/
//void fill_layer_background_color(GraphLayer &layer, int nColor, bool bBorder = false);
//bool fill_layer_background_color(GraphLayer &layer, int* pnColor = NULL, int* pnFillColor = NULL, int* pnBorderColor = NULL);
bool fill_layer_background_color(GraphLayer &layer, int* pnColor = NULL, int* pnFillColor = NULL, int* pnBorderColor = NULL, bool bUndo = false);
///End REWRTIE_WITH_APPLY_FORMAT_TO_UNDO

bool fill_layer_background_color(GraphLayer &layer, int* pnColor = NULL, int* pnFillColor = NULL, int* pnBorderColor = NULL);
/**$
*/
bool get_layer_background_color(GraphLayer &layer, int& nColor, int* pnFillColor = NULL, int* pnBorderColor = NULL);

/**$
*/
///Jasmine 01/07/09 v8.0994d QA80-10257 REWRTIE_WITH_APPLY_FORMAT_TO_UNDO
//bool set_layer_border_width(GraphLayer &layer, double* pdLeft = NULL, double* pdTop = NULL, double* pdRight = NULL, double* pdBottom = NULL);
bool set_layer_border_width(GraphLayer &layer, double* pdLeft = NULL, double* pdTop = NULL, double* pdRight = NULL, double* pdBottom = NULL, bool bUndo = false);
///End REWRTIE_WITH_APPLY_FORMAT_TO_UNDO

/**$
*/
bool get_layer_border_width(GraphLayer &layer, double* pdLeft = NULL, double* pdTop = NULL, double* pdRight = NULL, double* pdBottom = NULL);
/**$
*/
bool fill_graph_background_color(GraphPage &gp, int nColor, int* pnGradColor = NULL, int* pnGradCntrl = NULL);
/**$
*/
bool get_graph_background_color(GraphPage &gp, int& nColor, int* pnGradColor = NULL, int* pnGradCntrl = NULL); 
///End MODIFICATION_SET_COLOR_FUNCTION
///Arvin 03/08/07 AXIS_TITILE_SHOULD_ADD_FACTOR_INFO_IN_HISTOGRAM_GRAPH
bool get_axis_title(GraphLayer& gl, string& strTitle, int nAxis = AXIS_BOTTOM);
bool set_axis_title(GraphLayer& gl, string& strNewTitle, int nAxis = AXIS_BOTTOM);
///END AXIS_TITILE_SHOULD_ADD_FACTOR_INFO_IN_HISTOGRAM_GRAPH

/**
	Parameters:
		gp = [input] the graph page.
		bAllPlotsInOneLegend = [input] true, want to show only one legend for this graph to show all plots in all layers;
		false, one legend for one layer to show all plots in this layer.
		nLayerHasLegend = [input] only be effective when bAllPlotsInOneLegend is true, to decide put the only legend to which layer.
	Example1:
		void legend_update_text_property_ex1()
		{
			GraphPage 	gp = Project.Pages();
			if(gp)
			{	
				bool		bAllPlotsInOneLegend = true;	//true, want to show only one legend for this graph
				int			nLayer = 0; //the layer to put legend
				legend_update_text_property(gp, bAllPlotsInOneLegend, nLayer);
			}
		}
*/
/// Hong 08/08/07 QA80-10064 FIX_LEGEND_COMBINE_FAIL_KEEP_ORIGIN_ORDER
// replace by new fucntion legend_combine
//bool legend_update_text_property(GraphPage& gp, bool bAllPlotsInOneLegend, int nLayerHasLegend = 0);
/// end /// Hong 08/08/07 QA80-10064 FIX_LEGEND_COMBINE_FAIL_KEEP_ORIGIN_ORDER

/// Iris 07/20/2007 IMPROVE_LEGEND_UPDATE, moved to page_utils
/*
///Arvin 06/07/07 CHANGE_LEGEND_TO_USE_LONG_NAME_AND_UNIT as max's suggestion
//string construct_one_legend_LT_text(const GraphObject& goLegend, const GraphLayer& gl, int nPlot);
///Arvin 07/19/07 USE_STRING_TYPE_LEGEND_DIRECTLY as CP said
//string construct_one_legend_LT_text(const GraphObject& goLegend, const GraphLayer& gl, int nPlot, int nLegendType = LEGEND_DEFAULT);
string construct_one_legend_LT_text(const GraphObject& goLegend, const GraphLayer& gl, int nPlot, LPCSTR lpcszExtraFormat = NULL);
///END USE_STRING_TYPE_LEGEND_DIRECTLY
///end CHANGE_LEGEND_TO_USE_LONG_NAME_AND_UNIT
*/
///end IMPROVE_LEGEND_UPDATE

//----Iris 07/31/2007 moved to page_utils to avoid always called by FindFunction since the two functions used in many place.
/*
///Arvin 06/07/07 CHANGE_LEGEND_TO_USE_LONG_NAME_AND_UNIT as max's suggestion
//bool legend_append_plot(GraphLayer& gl, int nPlot);
///Arvin 07/19/07 USE_STRING_TYPE_LEGEND_DIRECTLY as CP said
//bool legend_append_plot(GraphLayer& gl, int nPlot, int nLegendType = LEGEND_DEFAULT);
bool legend_append_plot(GraphLayer& gl, int nPlot, LPCSTR lpcszExtraFormat = NULL, LPCSTR lpcszSep = NULL); //The seperator string may not be "\r\n" as Iris said, default is "\r\n"
///end USE_STRING_TYPE_LEGEND_DIRECTLY
///end CHANGE_LEGEND_TO_USE_LONG_NAME_AND_UNIT

bool legend_delete_plot(GraphLayer& gl, int nPlot);
*/
//----

enum
{
	LEGEND_POS_LEFT = 0,
	LEGEND_POS_TOP = LEGEND_POS_LEFT,
	LEGEND_POS_MID,
	LEGEND_POS_RIGHT,
	LEGEND_POS_BOTTOM = LEGEND_POS_RIGHT,
	
	LEGEND_POS_COUNT
};

enum
{
	LAYER_UNIT_PERCENT_OF_PAGE = 0,
	LAYER_UNIT_INCH,
	LAYER_UNIT_CM,
	LAYER_UNIT_MM,
	LAYER_UNIT_PIXEL,
	LAYER_UNIT_POINT,
	
	LAYER_UNIT_COUNT
};

bool legend_position(GraphObject& goLegend, int bHorizontal = true, int nPosition = LEGEND_POS_RIGHT);

///Jake 07/19/07 GET_LEGEND_EXTRA_FORMAT
//int legend_get_type(const GraphLayer& gl, int nPlot = -1);///Jake 07/17/07 GET_LEGEND_MODE_TYPE
string legend_get_extra_format(const GraphLayer& gl, int nPlot);
///GET_LEGEND_EXTRA_FORMAT

//---------Folger 07/24/07 GET_RANGE_CONTENT_FROM_DATAPLOT
//#define	STR_RANGE_FORMAT "%s(%s,%s)" //---- CPY 7/24/07 RANGE_BROWSER_NEED_BETTER_RANGE_STR
//#define STR_XYRANGE_FORMAT "(%s,%s)"
//string get_content(const DataPlot &dp);
//---------End GET_RANGE_CONTENT_FROM_DATAPLOT


////Sandy 2007-11-7 move from XF speedmode, need description later
#define SPEED_MODE_OFF 0
#define SPEED_MODE_LOW 1
#define SPEED_MODE_MEDIAM 2
#define SPEED_MODE_HIGH 3
#define SPEED_MODE_CUSTOM 4

#define SPEED_MODE_LOW_WKS_MAX 5000
#define SPEED_MODE_LOW_MAT_XYMAX 48

#define SPEED_MODE_MEDIAM_WKS_MAX 3000
#define SPEED_MODE_MEDIAM_MAT_XYMAX 32

#define SPEED_MODE_HIGH_WKS_MAX 800
#define SPEED_MODE_HIGH_MAT_XYMAX 16
///end add by Sandy

///Sandy 2007-1-4 add for detecting what type of dataplot in gl and decide the factor
#define PLOT_BASE_ON_WKS 0
#define PLOT_BASE_ON_MAT 1

int get_gl_plot_data_base(GraphLayer& gl);// 0 for wks, 1 for matrix
double get_factor_by_dataplot_type(int nTypeID);
int get_lowest_speed_plot_type_in_gl(GraphLayer& gl, int nPlotBase);

bool apply_speed_mode( GraphLayer& gl, int nSpeedMode, int nWks, int nMax, int nMatrix, int nX, int nY );
////end of move from XF speedmode

bool set_dataplot_format(DataPlot& dp, int nSymbolShape = -1,int nSymbolSize = 0, int nEdgeColor = FOB_INCREMENT, int nFillColor = FOB_INCREMENT); //default rectangle

bool set_dataplot_selectable(DataPlot &dp, bool bEnable); /// Iris 10/23/2008 v8.0959b SET_PA_FIT_LINE_NOT_SELECTABLE

///Sandy add 2008-3-31 for PA XFs, thread would be pending until "Done" button on the page is clicked.

//---- CPY 4/5/08 ADD_TITLE_TO_SMALL_GRAPH_DIALOG
#define STR_GRAPH_ADD_PTS_MSG1	_L("Double-click on the graph to add points")
#define STR_GRAPH_ADD_PTS_MSG2	_L("You have added %d points, Click DONE to finish")
//----

bool active_gl_to_add_points_and_sort(GraphLayer gl, vector& vx, vector& vy);

bool hide_lengends_of_unshow_dataplots(GraphLayer& gl);///sandy move from blpwiz.h

///Iris 1/28/2010 SET_PARETO_CHAR_LABEL_SIZE_AND_OFFSET
typedef bool (* ROTATE_OFFSET_RESIZE_LABEL_PLOT_FUNC_POINTER) (DataPlot& dpLabel, int nRotate, int nYOffset, int nXOffset, int nSize);
///End SET_PARETO_CHAR_LABEL_SIZE_AND_OFFSET

///------ Folger 09/10/09 PEAK_LABEL_PLOT_IN_PA_SHOULD_HAVE_CERTAIN_OFFSET
//bool rotate_offset_resize_label_plot(DataPlot& dpLabel, int nRotate = 90 ,  int nOffset = 20 , int nSize = 20); ///Sandy move from blpwiz.h
bool rotate_offset_resize_label_plot(DataPlot& dpLabel, int nRotate = 90 ,  int nYOffset = 20, int nXOffset = 30, int nSize = 20);
///------ End PEAK_LABEL_PLOT_IN_PA_SHOULD_HAVE_CERTAIN_OFFSET

bool copy_xy_axises_format(GraphLayer& glDest, GraphLayer& glSource);

/// Hong 03/19/09 QA80-13282 DATA_PLOT_SAFE_WAY_TO_GET_FORMAT_TREE
Tree	dataplot_get_format_safely(DataPlot& dp, DWORD dwPropertiesFilter = FPB_ALL, DWORD dwObjFilter = FOB_ALL, BOOL bGetTagNames = TRUE,
		BOOL bRelative = FALSE, DWORD dwPropertiesFilter2 = FPBEX_ALL, DWORD dwObjFilter2 = FOB2_ALL,
		vector<int>* piaErrors = NULL, vector<string>* psaErrors = NULL);
/// end DATA_PLOT_SAFE_WAY_TO_GET_FORMAT_TREE

///Kenny 05/31/2009 ADD_FUNC_GET_PLOT_COLOR_FOR_VERTICAL_CURSOR
// Comments last updated by Kenny on 05/31/2009
/**$
	Remarks:
		Get the color index in the Origin palette (such as SYSCOLOR_BLACK) of specific types of DataPlot
	Example1:
		int get_plot_color_ex1()
		{
			GraphLayer gl = Project.ActiveLayer();
			if (gl)
			{
				foreach(DataPlot dp in gl.DataPlots)
				{
					printf("The color index of DataPlot [%s] is %d.\n", dp.GetName(), get_plot_color(dp));
				}
			}
			return 0;
		}
	Parameters:
		dp = [input] The DataPlot object.
	Return:
		Return the color index.
*/
int get_plot_color(const DataPlot& dp);
///End ADD_FUNC_GET_PLOT_COLOR_FOR_VERTICAL_CURSOR

/// Kenny 07/24/2009 QA80-13992 NEW_XF_FOR_GENERAL_MULTI_AXES_PLOTTING, centralize codes for xf plotmaxes
AxisObject get_axis_object(const GraphLayer& gl, const int nAxisType);

bool set_axis_color(GraphLayer& gl, const int nAxisType, int nColor, BOOL bRepaint = TRUE, BOOL bUndo = FALSE);

bool get_axis_color(GraphLayer& gl, const int nAxisType, int& nColor);
/// End QA80-13992 NEW_XF_FOR_GENERAL_MULTI_AXES_PLOTTING

/// Kenny 07/31/2009 QA80-13992 SUPPORT_GET_PAGE_SIZE_FOR_MULTI_Y_AXES_XF
int get_graph_size(const GraphPage& gp, double& dWidth, double& dHeight);
/// End QA80-13992 SUPPORT_GET_PAGE_SIZE_FOR_MULTI_Y_AXES_XF

/// Kenny 08/12/2009 QA80-14100 USE_UNDEFINED_STATUS_FOR_UNCOMMON_PROPERTIES
BOOL layer_get_axes_object_properties(GraphLayer& gl, vector<int>& vnAxes, vector<int>& vnLabels, vector<int>& vnTitles, vector<int>& vnMajorTicks, vector<int>& vnMinorTicks, TreeNode& trFmt = NULL);
/// End QA80-14100 USE_UNDEFINED_STATUS_FOR_UNCOMMON_PROPERTIES

///------ Folger 11/12/09 QA81-14636 PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS
class	DataPlotsArrangeHelper
{
public:
	DataPlotsArrangeHelper(GraphPage& gp, const string& strPlotArrange, const string& strPlotTypes = NULL, const vector<int>& vnPlotTypes = NULL, LPCSTR lpcszTemplate = "Origin", UINT nMaxNumLayers = -1);

	GraphLayer		GetLayerAdvanced();

	GraphLayer		GetLayer();
	int				GetPlotType();
	BOOL			IsNewLayer();
	BOOL			IsDataPlotsGroupAllowed();
	
	int				GetTotalLayers(int nPlots, vector<int>* pnArrangement = NULL, UINT nMaxLayer = -1);
	void			CheckLayerCount();	//void			CheckAppendLayers();///Jasmine 11/19/09 QA80-14619-P3 CHECK_USE_EXISTING_LAYERS_IN_PAGE
	string			MakeActualNumPlotsInLayerString(int nPlots);

private:
	void			InitIntArray(vector<int>& vn, const string& str, int nDefaultValue, LPCSTR lpcszFilterFunction);
	void			GetIntTokens(vector<int>& vn, const string& str);
	int				GetArrayItem(vector<int>& vn, int nIndex, int nDefaultValue);
	int				IsAddLayerAllowed();
	int				CheckGetLayerPos(int nPos);	//int				CheckAddLayers(int nMax);///Jasmine 11/19/09 QA80-14619-P3 CHECK_USE_EXISTING_LAYERS_IN_PAGE
	
private:
	GraphPage		m_gp;
	int				m_nPlotPos;
	int				m_nLayerPos;
	GraphLayer		m_glCurrent;
	int				m_nCurrentPlotType;
	BOOL			m_bIsNewLayer;
	string			m_strTemplate;
	vector<int>		m_vnPlotsInLayer;
	vector<int>		m_vnPlotTypes;
	UINT			m_nMaxNumLayers;
};
///------ End PLOT_STACK_AND_MYAXES_REARRANGE_DATAPLOTS_IN_MULTIPLE_LAYERS

///Kyle 03/11/2010 PICK_PEAK_ROI_TOOL_SHARES_UTILS_FUNCTION_WITH_PA
bool		update_peaks_labels(GraphLayer gl, XYRange xyPeaksCenter,  bool bShowCenter, bool bShowLabel, int nLabelXYType = LABEL_Y_VAL_GUI, bool bRotateLabel = false, int nLabelColor = -1);

bool		plot_xyr_to_graph(XYRange& xy,  GraphLayer gl, int nPlotType = IDM_PLOT_LINE, int nColor = SYSCOLOR_BLACK, DataPlot& dpXY = NULL);

bool		get_plot_from_xyr_in_gl(GraphLayer gl, XYRange& xy,  DataPlot& dp, int nPlotType = -1);

DataPlot	add_label_plot(GraphLayer& gl, XYRange& xy, int nLabelXYType = LABEL_Y_VAL_GUI, int nYOffset = 0,  int nXOffset = 0,  bool bRotateLabel = false, int nLabelColor = -1);
///End PICK_PEAK_ROI_TOOL_SHARES_UTILS_FUNCTION_WITH_PA

bool 		set_axis_thinkness(GraphLayer& gl, double dThinkness, int nAxis = AXIS_TOTAL);

#endif	//__GRAPH_UTILS_H__
