/*------------------------------------------------------------------------------*
 * File Name:	ImageProfile.c 													*
 * Creation: 																	*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	Kyle 07/14/2010 ORG-572-P1 SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE		*
 *------------------------------------------------------------------------------*/
 
#include <Origin.h>

//#pragma labtalk(0) // to disable OC functions for LT calling.

#include "DialogEx.h"
/// Iris 5/28/2010 ORG-98 CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG
//#define BASE_WINDOW			ResizeDialog
#define BASE_WINDOW 	MultiPaneDlg
///End CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG
#include "DynaDlg.h"
#include "grobj_utils.h"
#include "graph_utils.h"
#include "ImageProfile.h"

/*----------------------------------------------------------------------------*/
/* ImageProfileDlg
/*----------------------------------------------------------------------------*/

#define STR_DLG_NAME_E		_LE("Image Profile")

///Kyle 07/01/2010 ORG-355-S7 OUTPUT_PROFILE_WIDTH
#define LABEL_PROFILE_WIDTH			RCLT_UDL
#define LABEL_LINE_POSITION			(RCLT_UDL + 1)
///End OUTPUT_PROFILE_WIDTH


#define STR_VTEXT_LOCATION_OPTIONS	_L("Top|Bottom")
#define STR_HTEXT_LOCATION_OPTIONS	_L("Left|Right")

enum{
	IPROFILE_TAB_MENU_RENAME			= 1,
};


enum
{
	IPROFILE_NUMBER_POINTS_ID = 1,
	IPROFILE_NUMBER_VPOINTS_ID,
	IPROFILE_NUMBER_HPOINTS_ID,

	///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	/*
	//IPROFILE_PROFILE_WIDTH_ID,			///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	IPROFILE_LINE_WIDTH_ID,
	*/
	///Kyle 06/17/2010 ORG-98-S40 NEW_WIDTH_CONTROL_WITHOUT_DROP_DOWN
	//IPROFILE_WIDTH_IN_PIXEL_ID,
	//IPROFILE_WIDTH_UNIT_ID,
	//IPROFILE_CUSTOM_WIDTH_IN_PIXEL_ID,
	//IPROFILE_CUSTOM_WIDTH_IN_SCALE_ID,
	IPROFILE_WIDTH_UNIT_ID,
	IPROFILE_WIDTH_IN_PIXEL_ID,
	IPROFILE_WIDTH_IN_SCALE_ID,
	///End NEW_WIDTH_CONTROL_WITHOUT_DROP_DOWN
	///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	///Kyle 06/09/2010 ORG-98-S30 SHOW_PROFILE_COLOR_AT_TOP, can be line or rect
	//IPROFILE_LINE_COLOR_ID,
	IPROFILE_PROFILE_COLOR_ID,
	///End SHOW_PROFILE_COLOR_AT_TOP

	IPROFILE_CROSS_LINE_X_ID,
	IPROFILE_CROSS_LINE_Y_ID,
	IPROFILE_CROSS_LINE_Z_ID,

	IPROFILE_VERTICAL_LINE_X_ID,
	IPROFILE_HORIZONTAL_LINE_Y_ID,
	
	IPROFILE_ARBITRARY_LINE_X1_ID,
	IPROFILE_ARBITRARY_LINE_Y1_ID,
	IPROFILE_ARBITRARY_LINE_X2_ID,
	IPROFILE_ARBITRARY_LINE_Y2_ID,

	IPROFILE_ADD_POINT_BTN_ID,
	
	/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
	IPROFILE_VERTICAL_TEXT_LOCATION_ID,
	IPROFILE_HORIZONTAL_TEXT_LOCATION_ID,	
	///End NEW_SUGGESTION_FOR_TEXT_OBJECT
};

//#define FTOA_DEFAULT(_dVal)		ftoa(_dVal, "*")			///Kyle 06/18/2010 ORG-98-S38 ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES

#define STR_EMPTY_PROFILE_HINT			\
_L("Use the first four buttons to select a layout type:\nCrossed Lines (same graph as data)\nVertical Line (same graph as data)\nHorizontal Line (same graph as data)\nProfile lines in separate graphs\n\nUse the other buttons to add additional vertical or\nhorizontal lines, or to delete or duplicate lines.\n\nClicking on line in image graph will activate the\ncorresponding tab.")

#define STR_LINE_WIDTH_HINT				\
_L("0 means line.")

class ImageProfileDlg : public DynaDlg
{
public:	
#ifdef _DEBUG
	bool	m_bDeleteOnDestroy;
#endif // _DEBUG
	
public:
	ImageProfileDlg() : DynaDlg(IDD_IMAGE_PROFILE_DLG, NULL, "ODlg8")
	{
#ifdef _DEBUG
		m_bDeleteOnDestroy 	= false;
#endif // _DEBUG
	}

	~ImageProfileDlg()
	{
	}

	int Create(HWND hWndParent = NULL)
	{
		InitMsgMap();
		
		DWORD dwDlgOptions = 0;
		int nRet = DynaDlg::Create(hWndParent, dwDlgOptions);
		return nRet;
	}

	void StartProfile(int nLayoutMode, DWORD dwOptions = IPROFILE_PROTECT_SOURCE);

protected :
EVENTS_BEGIN
	ON_INIT(OnInitDialog) 
	ON_RESTORESIZE(OnRestoreSize)
	ON_GETMINMAXINFO(OnMinMaxInfo)
	ON_SIZE(OnDlgResize)
	ON_OK(OnOK)
	ON_CANCEL(OnClose)
	ON_DESTROY(OnDestroy)
	ON_READY(OnReady)

	ON_SYSCOMMAND(OnSystemCommand)//make min button to rollup dialog
	ON_GETMINMAXINFO(OnMinMaxInfo)//customize minimum size

	ON_CONTEXTMENU(OnShowMenu)

	ON_USER_MSG(WM_USER_TREEEDITOR_VALUE_CHANGE, OnAfterValueChange)
	ON_USER_MSG(WM_USER_IMAGE_PROFILE_UPDATE, OnImageProfileUpdate)

	ON_CHANGE_LAYER(OnActiveLayerChange)
	ON_CHANGE_PAGE(OnActivePageChange)
	ON_OBJECT_MODIFY(OnOriginModify)
	///Kyle 07/01/2010 ORG-355-P11 FIX_PROFILE_IS_NOT_REMOVED_ON_CLOSE_PAGE_WHEN_THERE_IS_NO_PATH
	ON_LAYER_DESTROY(OnLayerDestroy)
	ON_PAGE_DESTROY(OnPageDestroy)
	///End FIX_PROFILE_IS_NOT_REMOVED_ON_CLOSE_PAGE_WHEN_THERE_IS_NO_PATH

	ON_TAB_SEL_CHANGE(IDC_IMAGE_PROFILE_TAB, OnTabChange)

	ON_BN_CLICKED(IDC_SAME_GRAPH_CLINE, OnSameGraphCLine)
	ON_BN_CLICKED(IDC_SAME_GRAPH_VLINE, OnSameGraphVLine)
	ON_BN_CLICKED(IDC_SAME_GRAPH_HLINE, OnSameGraphHLine)
	ON_BN_CLICKED(IDC_SEPARATE_GRAPH, OnSeparateGraph)

	ON_BN_CLICKED(IDC_IPROFILE_ADD_VLINE, OnAddVLine)
	ON_BN_CLICKED(IDC_IPROFILE_ADD_HLINE, OnAddHLine)

	ON_BN_CLICKED(IDC_IPROFILE_ACTIVATE_OUTPUT, OnActivateOutput)
	ON_BN_CLICKED(IDC_IPROFILE_DELETE, OnDeletePath)
	ON_BN_CLICKED(IDC_IPROFILE_DUPLICATE, OnDuplicatePath)

	/// Iris 5/28/2010 ORG-98 CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG
	ON_BN_CLICKED(IDC_IMG_PROFILE_UPDOWN, OnMyShowBottomPane)
	///End CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG

	//ON_BN_CLICKED(IDC_CHECK_KEEP_GRAPHS, OnKeepGraphsClick)
	ON_BN_CLICKED(IDC_CHECK_DEL_ALL, OnDeleteAllClick)
EVENTS_END

	BOOL OnInitDialog();
	BOOL OnRestoreSize(DWORD dwSizeInfo);
	int	GetTotalWidth(bool bMin = false);
	int	GetTotalHeight(bool bMin = false);
	BOOL OnDlgResize(int nType, int cx, int cy);
	BOOL OnOK();
	BOOL OnClose();
	BOOL OnDestroy();
	BOOL OnReady();
	BOOL OnHelp(int &nHelpID, int nIdCtrlFocus);

	BOOL OnShowMenu(UINT nResIDCtrl, int nx, int ny);

	void OnAfterValueChange(int nRow, DWORD lParam);
	BOOL OnImageProfileUpdate(uint wParam, uint lParam = 0);

	BOOL OnActiveLayerChange();
	BOOL OnActivePageChange();
	BOOL OnOriginModify(OriginObject obj, int nKind);
	///Kyle 07/01/2010 ORG-355-P11 FIX_PROFILE_IS_NOT_REMOVED_ON_CLOSE_PAGE_WHEN_THERE_IS_NO_PATH
	BOOL OnLayerDestroy(Layer lay, DWORD dwCntrl);
	BOOL OnPageDestroy(Page pg, DWORD dwCntrl);
	///End FIX_PROFILE_IS_NOT_REMOVED_ON_CLOSE_PAGE_WHEN_THERE_IS_NO_PATH

	BOOL OnTabChange(Control ctrl);

	BOOL	OnSameGraphCLine(Control ctrl);
	BOOL	OnSameGraphVLine(Control ctrl);
	BOOL	OnSameGraphHLine(Control ctrl);
	BOOL	OnSeparateGraph(Control ctrl);

	BOOL	OnAddVLine(Control ctrl);
	BOOL	OnAddHLine(Control ctrl);

	BOOL	OnActivateOutput(Control ctrl);
	BOOL	OnDeletePath(Control ctrl);
	BOOL	OnDuplicatePath(Control ctrl);

	/// Iris 5/28/2010 ORG-98 CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG
	BOOL	OnMyShowBottomPane(Control ctrl);
	///End CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG

	//BOOL	OnKeepGraphsClick(Control ctrl);
	BOOL	OnDeleteAllClick(Control ctrl);
	
protected:
	BOOL UpdateButtonState();

	BOOL OnAddPath(int nPathType);

	BOOL RenamePath(int nSelPath);

	BOOL DeleteProfilePath(ImageProfileManager* pProfile, int nIndex);
	BOOL DuplicateProfilePath(ImageProfileManager* pProfile, int nIndex);

	///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	//void ClearPathOnSwitchLayout(ImageProfileManager* pProfile);
	void ClearPathOnSwitchLayout(ImageProfileManager* pProfile, vector<int>& vnDeletedPathIndeces);
	///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS

	void CheckHideCloseDlg();

private:
	ImageProfileManager* getCurrentProfile();

	///Kyle 06/22/2010 ORG-355 BETTER_HANDLING_OF_DIALOG_SIZE
	int getDlgBorderSize(bool bWidth);
	int	getDlgMinWidth();
	int	getDlgMinHeight(bool bBottomPanelShow);
	
	int getGapBetweenGroups();
	int getGapInGroup();
	
	int getTopLeftBtns(vector<uint>& vnBtns);
	///End BETTER_HANDLING_OF_DIALOG_SIZE

	void initProfileControls(const ImageProfileManager* pProfile, int nIndex);
	///Kyle 06/17/2010 ORG-98 ADD_DIRTY_BITS_FOR_GUI_UPDATE
	//void loadProfilePathValues(const ImageProfileManager* pProfile, int nIndex);
	void loadProfilePathValues(const ImageProfileManager* pProfile, int nIndex, DWORD dwDirtyBits);
	///End ADD_DIRTY_BITS_FOR_GUI_UPDATE
	void showHideBottomControls(bool bShowTab);
	void initControls();

	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//int		getPolylineProfilePoints(GraphPage& gp, vector& vx, vector& vy);
	int		getPolylineProfilePoints(GraphLayer& gl, vector& vx, vector& vy);
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP

	void 	setDialogResizing();
	
	///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	bool	switchLayoutMode(int nNewMode);
	void 	checkAddProfilePath(ImageProfileManager* pProfile, vector<int>& vnPathTypes, int nPathType);
	///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS

private:
	TabControl			m_tab;
	
	//Button				m_ckKeepGraph;
	Button				m_ckDelAll;

	BitmapRadioButton	m_btnSameGraphCLine;
	BitmapRadioButton	m_btnSameGraphVLine;
	BitmapRadioButton	m_btnSameGraphHLine;
	BitmapRadioButton	m_btnSeparateGraph;

	BitmapRadioButton	m_btnAddVLine;
	BitmapRadioButton	m_btnAddHLine;

	BitmapRadioButton	m_btnActivateOutput;
	BitmapRadioButton	m_btnDeletePath;
	BitmapRadioButton	m_btnDuplicatePath;
};

static ImageProfileDlg* 		s_pProfileDlg;

void ImageProfileDlg::StartProfile(int nLayoutMode, DWORD dwOptions)
{
	GraphPage gp = Project.Pages();
	int nProfileIndex = get_image_profile_holder()->StartProfile(gp, nLayoutMode, dwOptions);
	if(nProfileIndex >= 0)
	{
		// default select same graph crossed line for a new profile
		ImageProfileManager* pProfile = getCurrentProfile();
		if( pProfile )
		{
			if(  pProfile->GetNumProfilePaths() == 0 )
			{
				if( pProfile->CanAddProfilePath(VERTICAL_LINE_IMAGE_PROFILE) )
					pProfile->AddProfilePath(VERTICAL_LINE_IMAGE_PROFILE);
				if( pProfile->CanAddProfilePath(HORIZONTAL_LINE_IMAGE_PROFILE) )
					pProfile->AddProfilePath(HORIZONTAL_LINE_IMAGE_PROFILE);
			}
			pProfile->SetKeepGraphsOnClosing(!m_ckDelAll.Check);
		}

		OnImageProfileUpdate(IPUPDATE_ACTIVE_PROFILE_CHANGE);
	}
	else
	{
		//SendMessage(WM_CLOSE);
		CheckHideCloseDlg();
	}
}

BOOL ImageProfileDlg:: OnInitDialog()
{
	/// Iris 5/28/2010 ORG-98 CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG
	//DynaDlg::OnInitDialog(IDC_IMAGE_PROFILE_TAB, STR_DLG_NAME_E);		
	vector<string> vstrTipsUpDown;
	vstrTipsUpDown.Add(_L("Show Tabs"));
	vstrTipsUpDown.Add(_L("Not Show Tabs"));
	DynaDlg::OnInitDialog(
		IDC_DYNA_CTRL,		// id of dyna control
		IDC_IMG_PROFILE_UPDOWN,		// id of button used to show/hide bottom pane
		IDC_IMAGE_PROFILE_TAB,				// id of bottom control
		vstrTipsUpDown,				// tips for button used to show/hide bottom pane
		STR_DLG_NAME_E, 0, NULL, -260);		
	///End CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG	

	InitDynaControl(IDC_DYNA_CTRL, *this);
	
	initControls();

	Text = GetLocalized(STR_DLG_NAME_E);

	setDialogResizing();

	return TRUE;
}

BOOL ImageProfileDlg::OnRestoreSize(DWORD dwSizeInfo)
{
	void * p = (void*)dwSizeInfo;
	DLGSIZEINFO *pSz = (DLGSIZEINFO*)p;
	
	lstrcpyn(pSz->szDialogName, STR_DLG_NAME_E, MAXLINE);

	pSz->top = -1;
	pSz->left = -1;
	///Kyle 06/22/2010 ORG-355 BETTER_HANDLING_OF_DIALOG_SIZE
	//pSz->width = 395;
	//pSz->height = 95;
	pSz->width = getDlgMinWidth();
	pSz->height = getDlgMinHeight(false);
	///End BETTER_HANDLING_OF_DIALOG_SIZE
	return TRUE;
}

int	ImageProfileDlg::GetTotalWidth(bool bMin)
{
	///Kyle 06/22/2010 ORG-355 BETTER_HANDLING_OF_DIALOG_SIZE
	//return 395;				// 
	if(bMin)
		return getDlgMinWidth();
	else
		return DynaDlg::GetTotalWidth(bMin);
	///End BETTER_HANDLING_OF_DIALOG_SIZE
}

int	ImageProfileDlg::GetTotalHeight(bool bMin)
{
	///Kyle 06/22/2010 ORG-355 BETTER_HANDLING_OF_DIALOG_SIZE
	/*
	if( IsBottomPaneShown() )
		return 250;
	return 95;				// 
	*/
	if( bMin )
		return getDlgMinHeight(IsBottomPaneShown());
	else
		return DynaDlg::GetTotalHeight(bMin);
	///End BETTER_HANDLING_OF_DIALOG_SIZE
}

///Kyle 06/22/2010 ORG-355 BETTER_HANDLING_OF_DIALOG_SIZE
int ImageProfileDlg::getDlgBorderSize(bool bWidth)
{
	RECT rtDlg;
	GetWindowRect(&rtDlg);
	ScreenToClient(&rtDlg);
	RECT rWindow;
	GetClientRect(&rWindow);

	return bWidth ? (RECT_WIDTH(rtDlg) - RECT_WIDTH(rWindow)) : (RECT_HEIGHT(rtDlg) - RECT_HEIGHT(rWindow));
}
int	ImageProfileDlg::getDlgMinWidth()
{
	static int nDlgMinWidth = 0;
	if( nDlgMinWidth == 0 )
	{
		vector<uint> vnBtns;
		getTopLeftBtns(vnBtns);

		int nGapBetweenGroups = getGapBetweenGroups();
		int nGapInGroup = getGapInGroup();

		Control btn = GetItem(IDC_SAME_GRAPH_CLINE);
		RECT rrButton;
		GetClientRect(btn, rrButton);
		int nHeight = RECT_HEIGHT(rrButton);

		for(int ii = 0; ii < vnBtns.GetSize(); ii++)
		{
			if( vnBtns[ii] )
			{
				nDlgMinWidth += nHeight;
				if( ii > 0 )
					nDlgMinWidth += (vnBtns[ii-1] ? nGapInGroup : nGapBetweenGroups);
			}
		}
		nDlgMinWidth += 2 * GetControlGap();
		
		nDlgMinWidth += getDlgBorderSize(true);
	}

	return nDlgMinWidth;
}

int	ImageProfileDlg::getDlgMinHeight(bool bBottomPanelShow)
{
	if( bBottomPanelShow )
		return 350;

	static int nDlgMinHeight = 0;
	if( nDlgMinHeight == 0 )
	{
		Control btn = GetItem(IDC_SAME_GRAPH_CLINE);
		RECT rrButton;
		GetClientRect(btn, rrButton);
		int nHeight = RECT_HEIGHT(rrButton);

		nDlgMinHeight += nHeight;
		
		RECT rrCheckBox;
		GetClientRect(m_ckDelAll, rrCheckBox);
		nDlgMinHeight += RECT_HEIGHT(rrCheckBox);
		
		nDlgMinHeight += 3 * GetControlGap();
		
		
		
		nDlgMinHeight += getDlgBorderSize(false);
	}

	return nDlgMinHeight;

}

int ImageProfileDlg::getGapBetweenGroups()
{
	return GetControlGap() * 2;
}

int ImageProfileDlg::getGapInGroup()
{
	return GetControlGap() / 2;
}

int ImageProfileDlg::getTopLeftBtns(vector<uint>& vnBtns)
{
	const vector<uint> vBtns = {	IDC_SAME_GRAPH_CLINE, IDC_SAME_GRAPH_VLINE, IDC_SAME_GRAPH_HLINE, IDC_SEPARATE_GRAPH, 0,
									IDC_IPROFILE_ADD_VLINE, IDC_IPROFILE_ADD_HLINE, 0,
									IDC_IPROFILE_ACTIVATE_OUTPUT, IDC_IPROFILE_DUPLICATE, IDC_IPROFILE_DELETE, 0,
									IDC_IMG_PROFILE_UPDOWN};
	vnBtns = vBtns;
	return vnBtns.GetSize();
}
///End BETTER_HANDLING_OF_DIALOG_SIZE

BOOL ImageProfileDlg::OnDlgResize(int nType, int cx, int cy)
{
	/// Iris 5/28/2010 ORG-98 CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG
	/*
	MoveControlsHelper	_temp(this);	
	vector<uint> nBtns = {IDCANCEL, 0};
	ArrangeMainItemAndControls(nBtns, IDC_IMAGE_PROFILE_TAB, NULL, false);

	int nGap = GetControlGap();
	Control btnCancel = GetItem(IDCANCEL);
	RECT rrCancel;
	GetClientRect(btnCancel, rrCancel);
	
	int nHeight = RECT_HEIGHT(rrCancel);
	int nX = nGap;
	int nY = rrCancel.top;
	
	vector<uint> vBtns = {	IDC_SAME_GRAPH_CLINE, IDC_SAME_GRAPH_VLINE, IDC_SAME_GRAPH_HLINE, IDC_SEPARATE_GRAPH, 0,
							IDC_IPROFILE_ADD_VLINE, IDC_IPROFILE_ADD_HLINE, 0, IDC_IPROFILE_ACTIVATE_OUTPUT, IDC_IPROFILE_DELETE, IDC_IPROFILE_DUPLICATE};
	
	*/		
	MoveControlsHelper	_temp(this);
	
	/// Iris 5/28/2010 ORG-98 CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG
	uint nIDs[] = {IDCANCEL, 0};
	MultiPaneDlg::OnDlgResize(nIDs, cx, cy, false);
	///End CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG
	
	int nGap = GetControlGap();
	
	RECT rrCheckBox;	
	GetClientRect(m_ckDelAll, rrCheckBox);
	
	int nHeight = RECT_HEIGHT(rrCheckBox);
	int nWidth = RECT_WIDTH(rrCheckBox);
	
	rrCheckBox.top = nGap;
	rrCheckBox.left = nGap;
	rrCheckBox.bottom = rrCheckBox.top + nHeight;
	rrCheckBox.right = rrCheckBox.left + nWidth;	
	MoveControl(m_ckDelAll, rrCheckBox);
	
	
	Control btn = GetItem(IDC_SAME_GRAPH_CLINE);
	RECT rrButton;
	GetClientRect(btn, rrButton);
	
	nHeight = RECT_HEIGHT(rrButton);
	int nX = nGap;
	int nY = rrCheckBox.bottom + nGap;
	
	///Kyle 06/22/2010 ORG-355 BETTER_HANDLING_OF_DIALOG_SIZE
	/*
	vector<uint> vBtns = {	IDC_SAME_GRAPH_CLINE, IDC_SAME_GRAPH_VLINE, IDC_SAME_GRAPH_HLINE, IDC_SEPARATE_GRAPH, 0,
							IDC_IPROFILE_ADD_VLINE, IDC_IPROFILE_ADD_HLINE, 0, IDC_IPROFILE_ACTIVATE_OUTPUT, IDC_IPROFILE_DUPLICATE, IDC_IPROFILE_DELETE,
							0, IDC_IMG_PROFILE_UPDOWN};
	*/
	vector<uint> vBtns;
	getTopLeftBtns(vBtns);

	int nGapBetweenGaps = getGapBetweenGroups();
	int nGapInGroup = getGapInGroup();
	///End BETTER_HANDLING_OF_DIALOG_SIZE
	///End CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG
	
	for(int ii = 0; ii < vBtns.GetSize(); ii++)
	{
		if( vBtns[ii] )
		{
			///Kyle 06/22/2010 ORG-355 BETTER_HANDLING_OF_DIALOG_SIZE
			if( ii > 0 )
			{
				if( vBtns[ii - 1] )
					nX += nGapInGroup;
				else
					nX += nGapBetweenGaps;
			}
			///End BETTER_HANDLING_OF_DIALOG_SIZE

			Control ctrl = GetItem(vBtns[ii]);
			if( ctrl )
			{
				RECT rr;
				rr.top = nY;
				rr.left = nX;
				rr.bottom = rr.top + nHeight;
				rr.right = rr.left + nHeight;
	
				MoveControl(ctrl, rr);

				///Kyle 06/22/2010 ORG-355 BETTER_HANDLING_OF_DIALOG_SIZE
				//nX += (nHeight + nGap);
				nX += nHeight;
				///End BETTER_HANDLING_OF_DIALOG_SIZE
			}
		}
		///Kyle 06/22/2010 ORG-355 BETTER_HANDLING_OF_DIALOG_SIZE
		/*
		else
			nX += nHeight / 2;
		*/
		///End BETTER_HANDLING_OF_DIALOG_SIZE
	}
	
	ImageProfileManager* pProfile = getCurrentProfile();
	showHideBottomControls( pProfile && pProfile->GetNumProfilePaths()>0 );

	return TRUE;
}

void ImageProfileDlg::CheckHideCloseDlg()
{
	ASSERT( NULL == getCurrentProfile() );

	if(get_image_profile_holder()->GetNumProfiles() > 0)
	{
		Visible = false;
	}
	else
	{
		SendMessage(WM_CLOSE);
	}
}

BOOL ImageProfileDlg::OnOK()
{
	return FALSE;		// do nothing on enter down
}

BOOL ImageProfileDlg::OnClose()
{
	//DWORD dwVal = m_ckKeepGraph.Check;
	//SaveSetting(STR_KEEP_GRAPH_REG_KEY, dwVal, STR_DLG_NAME_E);

	get_image_profile_holder()->RemoveProfile();			// remove active profile, do nothing if no profile actived
	Visible = false;

#ifdef _DEBUG
	if (m_bDeleteOnDestroy)
	{
		m_bDeleteOnDestroy = false;
		return TRUE;
	}
#endif // _DEBUG

	return get_image_profile_holder()->GetNumProfiles()==0;		// close dlg if no profiles, otherwise hide the dlg
}

BOOL ImageProfileDlg::OnDestroy()
{
	ASSERT( get_image_profile_holder()->GetNumProfiles()==0 );
	get_image_profile_holder()->ResetParentWnd();

	DynaDlg::OnDestroy();
	if(s_pProfileDlg)
	{
		delete this;
		s_pProfileDlg = NULL;
	}
	return TRUE;
}

BOOL ImageProfileDlg::OnReady()
{
	SetInitReady();
	return TRUE;
}

BOOL ImageProfileDlg::OnShowMenu(UINT nResIDCtrl, int nx, int ny)
{	
	if(IDC_IMAGE_PROFILE_TAB == nResIDCtrl)	
	{
		ImageProfileManager* pProfile = getCurrentProfile();
		if( !pProfile )
		{
			ASSERT(0);
			return false;
		}

		for(int nSelTab = pProfile->GetNumProfilePaths()-1; nSelTab >= 0; nSelTab--)
		{
			RECT rr;
			m_tab.GetItemRect(nSelTab, &rr);
			ClientToScreen(&rr);
			if(rr.left < nx && nx < rr.right)
				break;
		}
		if( nSelTab < 0 )
			return false;
		if( m_tab.GetCurSel() != nSelTab )
		{
			m_tab.SetCurSel(nSelTab);
			OnTabChange(m_tab);
		}

		IProfileTabMenu myMenu;
		int nCmd = 0;
		myMenu.TrackPopupMenu(0, nx, ny, GetSafeHwnd(), &nCmd);
		if( IPROFILE_TAB_MENU_RENAME == nCmd )
			return RenamePath(nSelTab);
	}
	
	return FALSE;
}

///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
static void _reset_string_value_from_old_value(TreeNode& trChange)
{
	string strOldVal;
	if( trChange && trChange.GetAttribute(STR_CHANGED_ATTRIB, strOldVal) )
		trChange.strVal = strOldVal;
}
///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE

void ImageProfileDlg::OnAfterValueChange(int nRow, DWORD lParam)
{
	ImageProfileManager* pProfile = getCurrentProfile();
	if( !pProfile )
	{
		ASSERT(0);
		return;
	}
	int nIndex = pProfile->GetActivePath();//m_tab.GetCurSel();		// pProfile->GetActivePath() != m_tab.GetCurSel() if from OnTabChange, should update path first and then switch the active path
	ImageProfilerPath* pActivePath = pProfile->GetProfilePath(nIndex);

	TreeNode trChange = m_DynaCntrl.GetTreeNode(nRow);

	int nID = -1;
	if(trChange.IsValid())
		trChange.GetAttribute(STR_DATAID_ATTRIB, nID);
	
	TreeNode trGUI = GetTree();				///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	TreeNode trWidth = trGUI.Width;			///Kyle 06/21/2010 ORG-355-S2 MAKE_CELL_AND_SCALE_CONTROLS_SUB_NODE_OF_WIDTH

	bool bUpdateGUI = false;
	switch(nID)
	{
	/*
	case IPROFILE_NUMBER_POINTS_ID:
	case IPROFILE_NUMBER_VPOINTS_ID:
	case IPROFILE_NUMBER_HPOINTS_ID:
		{
			bool bVertical = (IPROFILE_NUMBER_VPOINTS_ID==nID) || (IPROFILE_NUMBER_POINTS_ID==nID && VERTICAL_LINE_IMAGE_PROFILE==pActivePath->GetPathType());
			int nAuto;
			trChange.GetAttribute(STR_ATTRIB_AUTO, nAuto);
			if( nAuto )
			{
				pProfile->SetNumPoints(-1, nIndex, bVertical);
				trChange.nVal = pActivePath->GetNumPoints(bVertical);
				bUpdateGUI = true;
			}
			else
			{
				if( !pProfile->SetNumPoints(trChange.nVal, nIndex, bVertical) )
				{
					trChange.nVal = pActivePath->GetNumPoints(bVertical);
					bUpdateGUI = true;
				}
			}
		}
		break;
	*/
	///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	/*
	case IPROFILE_PROFILE_WIDTH_ID:
		pProfile->SetProfileWidth(nIndex, trChange.dVal);
		if( pActivePath )
		{
			double dLineWidth = pActivePath->GetLineWidth( VERTICAL_LINE_IMAGE_PROFILE == pActivePath->GetPathType());
			
			TreeNode trGUI = GetTree();
			trGUI.LineWidth.strVal = FTOA_DEFAULT(dLineWidth);
			
			bUpdateGUI = true;
		}
		break;
	*/
	///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	/*
	case IPROFILE_LINE_WIDTH_ID:
		if( !pProfile->SetLineWidth(nIndex, trChange.dVal) )
		{
			trChange.dVal = pActivePath->GetLineWidth();
			bUpdateGUI = true;
		}
		break;
	///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	*/
	///Kyle 06/17/2010 ORG-98-S40 NEW_WIDTH_CONTROL_WITHOUT_DROP_DOWN
	/*
	case IPROFILE_WIDTH_IN_PIXEL_ID:
		{
			string strCombo;
			trChange.GetAttribute(STR_COMBO_ATTRIB, strCombo);
			vector<string> vsCombo;
			strCombo.GetTokens(vsCombo, '|');

			bool bCustom = (trChange.nVal == vsCombo.GetSize()-1);
			pActivePath->SetProfileWidthCustom(bCustom);

			trGUI.WidthUnit.Show = bCustom;
			trGUI.CustomWidthInPixel.Show = bCustom && IPROFILE_PATH_WIDTH_PIXEL==trGUI.WidthUnit.nVal;
			trGUI.CustomWidthInScale.Show = bCustom && IPROFILE_PATH_WIDTH_SCALE==trGUI.WidthUnit.nVal;

			if( bCustom )
			{
				int nUnit = trGUI.WidthUnit.nVal;
				double dWidth = IPROFILE_PATH_WIDTH_PIXEL==nUnit ? trGUI.CustomWidthInPixel.dVal : trGUI.CustomWidthInScale.dVal;
				if( !pProfile->SetProfileWidth(nIndex, dWidth, nUnit) )
					trChange.dVal = pActivePath->GetProfileWidth(nUnit);
			}
			else
			{
				string str = vsCombo[trChange.nVal];
				str = str.Left(str.Find(' '));
				int nWidth = atoi(str);
				pProfile->SetProfileWidth(nIndex, nWidth, IPROFILE_PATH_WIDTH_PIXEL);
			}
			bUpdateGUI = true;
		}
		break;
	case IPROFILE_WIDTH_UNIT_ID:
		{
			int nUnit = trChange.nVal;
			bool bUnitInPixel = IPROFILE_PATH_WIDTH_PIXEL==nUnit;
			trGUI.CustomWidthInPixel.Show = bUnitInPixel;
			trGUI.CustomWidthInScale.Show = !bUnitInPixel;

			double dWidth = bUnitInPixel ? trGUI.CustomWidthInPixel.dVal : trGUI.CustomWidthInScale.dVal;
			if( !pProfile->SetProfileWidth(nIndex, dWidth, nUnit) )
			{
				trChange.dVal = pActivePath->GetProfileWidth(nUnit);
				bUpdateGUI = true;
			}
		}
		break;

	case IPROFILE_CUSTOM_WIDTH_IN_PIXEL_ID:
		{
			ASSERT( pActivePath->IsProfileWidthCustom() );
			if( !pProfile->SetProfileWidth(nIndex, trChange.dVal, IPROFILE_PATH_WIDTH_PIXEL) )
			{
				_reset_string_value_from_old_value(trChange);
				bUpdateGUI = true;
			}
		}
		break;
		
	case IPROFILE_CUSTOM_WIDTH_IN_SCALE_ID:
		{
			ASSERT( pActivePath->IsProfileWidthCustom() );
			if( !pProfile->SetProfileWidth(nIndex, trChange.dVal, IPROFILE_PATH_WIDTH_SCALE) )
			{
				_reset_string_value_from_old_value(trChange);
				bUpdateGUI = true;
			}
		}
		break;
	*/
	case IPROFILE_WIDTH_UNIT_ID:
		{
			int nUnit = trChange.nVal;
			bool bInPixelUnit = (IPROFILE_PATH_WIDTH_PIXEL==nUnit);
			///Kyle 06/21/2010 ORG-355-S2 MAKE_CELL_AND_SCALE_CONTROLS_SUB_NODE_OF_WIDTH
			//trGUI.WidthInPixel.Enable = bInPixelUnit;
			//trGUI.WidthInScale.Enable = !bInPixelUnit;
			//
			//double dWidth = bInPixelUnit ? trGUI.WidthInPixel.nVal : trGUI.WidthInScale.dVal;
			trWidth.WidthInPixel.Enable = bInPixelUnit;
			trWidth.WidthInScale.Enable = !bInPixelUnit;
			double dWidth = bInPixelUnit ? trWidth.WidthInPixel.nVal : trWidth.WidthInScale.dVal;
			///End MAKE_CELL_AND_SCALE_CONTROLS_SUB_NODE_OF_WIDTH

			if( pProfile->SetProfileWidth(nIndex, dWidth, nUnit) )
			{
				///Kyle 06/21/2010 ORG-355-S2 MAKE_CELL_AND_SCALE_CONTROLS_SUB_NODE_OF_WIDTH
				/*
				if( bInPixelUnit )
					_update_profile_width_to_treenode(trGUI.WidthInScale, pActivePath, IPROFILE_PATH_WIDTH_SCALE);
				else
					_update_profile_width_to_treenode(trGUI.WidthInPixel, pActivePath, IPROFILE_PATH_WIDTH_PIXEL);
				*/
				if( bInPixelUnit )
					_update_profile_width_to_treenode(trWidth.WidthInScale, pActivePath, IPROFILE_PATH_WIDTH_SCALE);
				else
					_update_profile_width_to_treenode(trWidth.WidthInPixel, pActivePath, IPROFILE_PATH_WIDTH_PIXEL);
				///End MAKE_CELL_AND_SCALE_CONTROLS_SUB_NODE_OF_WIDTH
			}
			else
			{
				ASSERT(0);
				_update_profile_width_to_treenode(trChange, pActivePath, nUnit);
			}
			bUpdateGUI = true;
		}
		break;

	case IPROFILE_WIDTH_IN_PIXEL_ID:
		{
			int nWidth = trChange.nVal;
			if( nWidth >= 1 && pProfile->SetProfileWidth(nIndex, trChange.nVal, IPROFILE_PATH_WIDTH_PIXEL) )			// SetProfileWidth() accepts num < 1
				///Kyle 06/21/2010 ORG-355-S2 MAKE_CELL_AND_SCALE_CONTROLS_SUB_NODE_OF_WIDTH
				//_update_profile_width_to_treenode(trGUI.WidthInScale, pActivePath, IPROFILE_PATH_WIDTH_SCALE);
				_update_profile_width_to_treenode(trWidth.WidthInScale, pActivePath, IPROFILE_PATH_WIDTH_SCALE);
				///End MAKE_CELL_AND_SCALE_CONTROLS_SUB_NODE_OF_WIDTH
			else
				_reset_string_value_from_old_value(trChange);
			bUpdateGUI = true;
		}
		break;
		
	case IPROFILE_WIDTH_IN_SCALE_ID:
		{
			if( pProfile->SetProfileWidth(nIndex, trChange.dVal, IPROFILE_PATH_WIDTH_SCALE) )
				///Kyle 06/21/2010 ORG-355-S2 MAKE_CELL_AND_SCALE_CONTROLS_SUB_NODE_OF_WIDTH
				//_update_profile_width_to_treenode(trGUI.WidthInPixel, pActivePath, IPROFILE_PATH_WIDTH_PIXEL);
				_update_profile_width_to_treenode(trWidth.WidthInPixel, pActivePath, IPROFILE_PATH_WIDTH_PIXEL);
				///End MAKE_CELL_AND_SCALE_CONTROLS_SUB_NODE_OF_WIDTH
			else
				_reset_string_value_from_old_value(trChange);
			bUpdateGUI = true;
		}
		break;
	///End NEW_WIDTH_CONTROL_WITHOUT_DROP_DOWN
	///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE


	///Kyle 06/09/2010 ORG-98-S30 SHOW_PROFILE_COLOR_AT_TOP
	//case IPROFILE_LINE_COLOR_ID:
	case IPROFILE_PROFILE_COLOR_ID:
	///End SHOW_PROFILE_COLOR_AT_TOP
		pActivePath->SetProfileLineColor(trChange.nVal, true);
		break;

	//case IPROFILE_CROSS_LINE_X_ID:
	//case IPROFILE_CROSS_LINE_Y_ID:
	//	{
	//		ImageProfilerCrossLinePath* clPath = (ImageProfilerCrossLinePath*)pActivePath;

	//		bool bVertical = IPROFILE_CROSS_LINE_X_ID==nID;
	//		if( !clPath->SetLinePosition(trChange.dVal, bVertical) )
	//		{
	//			double dValue;
	//			clPath->GetLinePosition(dValue, bVertical);
	//			trChange.strVal = FTOA_DEFAULT(dValue);
	//			bUpdateGUI = true;
	//		}
	//	}
	//	break;
		
	case IPROFILE_VERTICAL_LINE_X_ID:
	case IPROFILE_HORIZONTAL_LINE_Y_ID:
		{
			ImageProfilerHVPath* hvPath = (ImageProfilerHVPath*)pActivePath;
			bool bVertical = IPROFILE_VERTICAL_LINE_X_ID==nID;
			if( !hvPath->SetLinePosition(trChange.dVal, bVertical) )
			{
				///Kyle 06/18/2010 ORG-98-S38 ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
				/*
				double dValue;
				hvPath->GetLinePosition(dValue, bVertical);
				trChange.strVal = FTOA_DEFAULT(dValue);
				*/
				_reset_string_value_from_old_value(trChange);
				///End ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
				bUpdateGUI = true;
			}
		}
		break;

	case IPROFILE_ARBITRARY_LINE_X1_ID:
	case IPROFILE_ARBITRARY_LINE_Y1_ID:
	case IPROFILE_ARBITRARY_LINE_X2_ID:
	case IPROFILE_ARBITRARY_LINE_Y2_ID:
		{
			ASSERT( ARBITRARY_LINE_IMAGE_PROFILE == pActivePath->GetPathType() );
			vector vx, vy;
			if( pActivePath->GetLinePosition(vx, vy) )
			{
				ASSERT( vx.GetSize()==2 && vy.GetSize()==2 );
				switch(nID)
				{
				case IPROFILE_ARBITRARY_LINE_X1_ID:
					vx[0] = trChange.dVal;
					break;

				case IPROFILE_ARBITRARY_LINE_Y1_ID:
					vy[0] = trChange.dVal;
					break;

				case IPROFILE_ARBITRARY_LINE_X2_ID:
					vx[1] = trChange.dVal;
					break;

				case IPROFILE_ARBITRARY_LINE_Y2_ID:
					vy[1] = trChange.dVal;
					break;
				}
				pActivePath->SetLinePosition(vx, vy);
			}
		}
		break;
	/*
	case IPROFILE_ADD_POINT_BTN_ID:
		{
			ASSERT( POLYLINE_IMAGE_PROFILE == pActivePath->GetPathType() );

			GraphLayer gl = pActivePath->GetSourceLayer();
			set_active_layer(gl);
			
			GraphPage gp = gl.GetPage();
			vector vx, vy;
			if( getPolylineProfilePoints(gp, vx, vy) >= 1 )
			{
				ImageProfilerPolyLinePath* pPolylinePath = (ImageProfilerPolyLinePath*)pActivePath;
				pPolylinePath->AddAnchorPoints(vx, vy);
			}
		}
		break;
	*/
	
	/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
	case IPROFILE_VERTICAL_TEXT_LOCATION_ID:
	case IPROFILE_HORIZONTAL_TEXT_LOCATION_ID:
		{
			pActivePath->SetTextObjectLocation(trChange.nVal);
			
			ImageProfilerHVPath* hvPath = (ImageProfilerHVPath*)pActivePath;
			hvPath->ChangeTextObjectLocation();
			
			pProfile->SaveToStorage();
		}
		break;
	///End NEW_SUGGESTION_FOR_TEXT_OBJECT
	
	}

	if( bUpdateGUI )
	{
		UpdateDynaControl(true, GETNEVENT_ON_CHANGE_UPDATE_GUI);
	}
}

BOOL ImageProfileDlg::OnImageProfileUpdate(uint wParam, uint lParam)
{	
	const ImageProfileManager* pProfile = getCurrentProfile();
	if(pProfile)
	{
		if( !Visible )
			Visible = true;			// show dlg

		switch(wParam)
		{
		case IPUPDATE_ACTIVE_PROFILE_CHANGE:
			{
				m_ckDelAll.Check = !pProfile->IsKeepGraphsOnClosing();
		
				m_tab.DeleteAllItems();
				if( pProfile->GetNumProfilePaths() == 0 )
				{
					m_tab.InsertItem(0, "Hint");
					m_tab.SetCurSel(0);
				}
				else
				{
					for(int ii = pProfile->GetNumProfilePaths()-1; ii >= 0; ii--)
					{
						ImageProfilerPath* pPath = pProfile->GetProfilePath(ii);
						m_tab.InsertItem(0, pPath->GetPathName());
					}
				}
				// go on to update path info
			}
		case IPUPDATE_ACTIVE_PATH_CHANGE:
			{
				int nSelPath = pProfile->GetActivePath();
				if( nSelPath < 0 || nSelPath >= pProfile->GetNumProfilePaths() )
					nSelPath = 0;
				m_tab.SetCurSel(nSelPath);
				pProfile->SetActivePath(nSelPath);

				initProfileControls(pProfile, nSelPath);
				///Kyle 06/17/2010 ORG-98 ADD_DIRTY_BITS_FOR_GUI_UPDATE
				//loadProfilePathValues(pProfile, nSelPath);
				loadProfilePathValues(pProfile, nSelPath, IPUPDATE_PATH_CONTENTS);
				///End ADD_DIRTY_BITS_FOR_GUI_UPDATE
				
				UpdateButtonState();
			}
			break;
	
		case IPUPDATE_LAYOUT_MODE_CHANGE:
			{
				/*
				TreeNode trGUI = GetTree();
				int nSelPath = m_tab.GetCurSel();
				if( nSelPath >= 0 && nSelPath < pProfile->GetNumProfilePaths() && trGUI.Buttons )
				{
					ImageProfilerPath* pPath = pProfile->GetProfilePath(nSelPath);
					bool bCanDuplicate = pProfile->CanAddProfilePath(pPath->GetPathType());
					trGUI.Buttons.SetAttribute(STR_COMBO_ATTRIB, bCanDuplicate ? _L("Active Output|Delete|Duplicate"): _L("Active Output|Delete"));
					UpdateDynaControl(true, GETNEVENT_ON_CHANGE_UPDATE_GUI);
				}
				*/
				UpdateButtonState();
			}
			break;
		///Kyle 06/17/2010 ORG-98 ADD_DIRTY_BITS_FOR_GUI_UPDATE
		/*
		case IPUPDATE_PATH_CONTENT:
			{
				int nIndex = lParam;
				ASSERT( pProfile->GetActivePath() == m_tab.GetCurSel() );
				if( nIndex>=0 && nIndex<pProfile->GetNumProfilePaths() && nIndex==pProfile->GetActivePath() )
				{
					loadProfilePathValues(pProfile, nIndex);
				}
			}
			break;
		*/
		///End ADD_DIRTY_BITS_FOR_GUI_UPDATE
	
		default:
			///Kyle 06/17/2010 ORG-98 ADD_DIRTY_BITS_FOR_GUI_UPDATE
			//ASSERT(0);
			ASSERT(0 == (wParam&(~IPUPDATE_PATH_CONTENTS)));
			///End ADD_DIRTY_BITS_FOR_GUI_UPDATE
		}

		///Kyle 06/17/2010 ORG-98 ADD_DIRTY_BITS_FOR_GUI_UPDATE
		if( IPUPDATE_PATH_CONTENTS & wParam )
		{
			int nIndex = lParam;
			ASSERT( pProfile->GetActivePath() == m_tab.GetCurSel() );
			if( nIndex>=0 && nIndex<pProfile->GetNumProfilePaths() && nIndex==pProfile->GetActivePath() )
			{
				loadProfilePathValues(pProfile, nIndex, IPUPDATE_PATH_CONTENTS & wParam);
			}
		}
		///End ADD_DIRTY_BITS_FOR_GUI_UPDATE

	}
	else
	{
		//SendMessage(WM_CLOSE);	// no profile in the active layer, hide the window
		CheckHideCloseDlg();
	}

	return TRUE;
}

BOOL ImageProfileDlg::OnActiveLayerChange()
{
	if( !get_image_profile_holder()->IsUpdatingHolder() )
	{
		bool bRet = get_image_profile_holder()->OnActiveLayerChange();
		//if( bRet )
		//{
		//	ImageProfileManager* pProfile = getCurrentProfile();
		//	if( pProfile )
		//		m_ckDelAll.Check = !pProfile->IsKeepGraphsOnClosing();
		//}
		return bRet; 
	}

	return true;
}

BOOL ImageProfileDlg::OnActivePageChange()
{
	return OnActiveLayerChange();
}

BOOL ImageProfileDlg::OnOriginModify(OriginObject obj, int nKind)
{ 
	if( obj && !get_image_profile_holder()->IsUpdatingHolder() )
	{
		string strRange;
		obj.GetRangeString(strRange);

		DataRange drChange;
		if( okxf_init_range_from_string(&drChange, strRange) && drChange.IsValid() )
			get_image_profile_holder()->OnDataModify(drChange);
	}
	return TRUE;
}

///Kyle 07/01/2010 ORG-355-P11 FIX_PROFILE_IS_NOT_REMOVED_ON_CLOSE_PAGE_WHEN_THERE_IS_NO_PATH
BOOL ImageProfileDlg::OnLayerDestroy(Layer lay, DWORD dwCntrl)
{
	if( lay.IsValid() && !get_image_profile_holder()->IsUpdatingHolder() )
	{
		GraphLayer gl = lay;
		if( gl )
			get_image_profile_holder()->OnLayerDestroy(gl);
	}
	return TRUE;
}

BOOL ImageProfileDlg::OnPageDestroy(Page pg, DWORD dwCntrl)
{
	if( pg.IsValid() && !get_image_profile_holder()->IsUpdatingHolder() )
	{
		GraphPage gp = pg;
		if( gp )
			get_image_profile_holder()->OnPageDestroy(gp);
	}
	return TRUE;
}
///End FIX_PROFILE_IS_NOT_REMOVED_ON_CLOSE_PAGE_WHEN_THERE_IS_NO_PATH

BOOL ImageProfileDlg::OnTabChange(Control cntrl)
{
	m_DynaCntrl.AbjustFocusToSave();			// force updating current path before switch

	ImageProfileManager* pProfile = getCurrentProfile();
	if( pProfile )
	{
		///Kyle 06/11/2010 ORG-98-P13 NO_NEED_TO_BEING_OBJECT_TO_FRONT_ON_SELECT_OBJECT
		//pProfile->SetActivePath(m_tab.GetCurSel());
		pProfile->SetActivePath(m_tab.GetCurSel(), true);
		///End NO_NEED_TO_BEING_OBJECT_TO_FRONT_ON_SELECT_OBJECT
		OnImageProfileUpdate(IPUPDATE_ACTIVE_PATH_CHANGE);
		return TRUE;
	}
	else
		ASSERT(0);

	return TRUE;
}
///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
bool	ImageProfileDlg::switchLayoutMode(int nNewMode)
{
	ImageProfileManager* pProfile = getCurrentProfile();
	if( pProfile )
	{
		vector<int> vnDeletedPathIndeces, vnPathTypes;
		pProfile->SetLayoutMode(nNewMode, &vnDeletedPathIndeces, &vnPathTypes);	
			
		ImageProfileManager* pProfile = getCurrentProfile();
		if(pProfile)
		{
			checkAddProfilePath(pProfile, vnPathTypes, VERTICAL_LINE_IMAGE_PROFILE);
			checkAddProfilePath(pProfile, vnPathTypes, HORIZONTAL_LINE_IMAGE_PROFILE);
		}
		OnImageProfileUpdate(IPUPDATE_ACTIVE_PROFILE_CHANGE);			

		return true;
	}
	return false;
}

void 	ImageProfileDlg::checkAddProfilePath(ImageProfileManager* pProfile, vector<int>& vnPathTypes, int nPathType)
{
	if( pProfile && pProfile->CanAddProfilePath(nPathType) )
	{
		vector<uint> vn;
		if( vnPathTypes.GetSize() > 0 && vnPathTypes.Find(MATREPL_TEST_EQUAL, nPathType, vn) > 0 )
			return;
		
		pProfile->AddProfilePath(nPathType);	
	}
}
///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS

BOOL	ImageProfileDlg::OnSameGraphCLine(Control ctrl)
{
	if( m_btnSameGraphCLine.PressedDown )
		return false;
	HOLDER_BEFORE_UPDATE_NO_CHECK(get_image_profile_holder());

	///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	/*
	ImageProfileManager* pProfile = getCurrentProfile();
	if( pProfile )
	{
		ClearPathOnSwitchLayout(pProfile);
		pProfile->SetLayoutMode(IMAGE_PROFILE_LAYOUT_SAME_GRAPH_CLINE);

		pProfile->AddProfilePath(VERTICAL_LINE_IMAGE_PROFILE);
		pProfile->AddProfilePath(HORIZONTAL_LINE_IMAGE_PROFILE);
		OnImageProfileUpdate(IPUPDATE_ACTIVE_PROFILE_CHANGE);
		return TRUE;
	}
	
	ASSERT(0);
	return FALSE;
	*/
	return switchLayoutMode(IMAGE_PROFILE_LAYOUT_SAME_GRAPH_CLINE);
	///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
}

BOOL	ImageProfileDlg::OnSameGraphVLine(Control ctrl)
{
	if( m_btnSameGraphVLine.PressedDown )
		return false;
	HOLDER_BEFORE_UPDATE_NO_CHECK(get_image_profile_holder());

	///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	/*
	ImageProfileManager* pProfile = getCurrentProfile();
	if( pProfile )
	{
		ClearPathOnSwitchLayout(pProfile);
		pProfile->SetLayoutMode(IMAGE_PROFILE_LAYOUT_SAME_GRAPH_VLINE);
		pProfile->AddProfilePath(VERTICAL_LINE_IMAGE_PROFILE);
		OnImageProfileUpdate(IPUPDATE_ACTIVE_PROFILE_CHANGE);
		return TRUE;
	}
	
	ASSERT(0);
	return FALSE;
	*/
	return switchLayoutMode(IMAGE_PROFILE_LAYOUT_SAME_GRAPH_VLINE);
	///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
}

BOOL	ImageProfileDlg::OnSameGraphHLine(Control ctrl)
{
	if( m_btnSameGraphHLine.PressedDown )
		return false;
	HOLDER_BEFORE_UPDATE_NO_CHECK(get_image_profile_holder());

	///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	/*
	ImageProfileManager* pProfile = getCurrentProfile();
	if( pProfile )
	{
		ClearPathOnSwitchLayout(pProfile);
		pProfile->SetLayoutMode(IMAGE_PROFILE_LAYOUT_SAME_GRAPH_HLINE);
		pProfile->AddProfilePath(HORIZONTAL_LINE_IMAGE_PROFILE);
		OnImageProfileUpdate(IPUPDATE_ACTIVE_PROFILE_CHANGE);
		return TRUE;
	}
	
	ASSERT(0);
	return FALSE;
	*/
	return switchLayoutMode(IMAGE_PROFILE_LAYOUT_SAME_GRAPH_HLINE);	
	///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
}

BOOL	ImageProfileDlg::OnSeparateGraph(Control ctrl)
{
	if( m_btnSeparateGraph.PressedDown )
		return false;
	HOLDER_BEFORE_UPDATE_NO_CHECK(get_image_profile_holder());

	///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	/*
	ImageProfileManager* pProfile = getCurrentProfile();
	if( pProfile )
	{
		ClearPathOnSwitchLayout(pProfile);

		pProfile->SetLayoutMode(IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH);
		pProfile->AddProfilePath(VERTICAL_LINE_IMAGE_PROFILE);
		pProfile->AddProfilePath(HORIZONTAL_LINE_IMAGE_PROFILE);
		
		OnImageProfileUpdate(IPUPDATE_ACTIVE_PROFILE_CHANGE);
		return TRUE;
	}
	
	ASSERT(0);
	return FALSE;
	*/
	return switchLayoutMode(IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH);
	///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
}

BOOL	ImageProfileDlg::OnActivateOutput(Control ctrl)
{
	HOLDER_BEFORE_UPDATE_NO_CHECK(get_image_profile_holder());

	ImageProfileManager* pProfile = getCurrentProfile();
	if( pProfile )
	{
		ImageProfilerPath* pActivePath = pProfile->GetProfilePath(pProfile->GetActivePath());
		if( pActivePath )
			pActivePath->ActiveOutputPlots();
		return TRUE;
	}

	ASSERT(0);
	return FALSE;
}

BOOL	ImageProfileDlg::OnDeletePath(Control ctrl)
{
	ImageProfileManager* pProfile = getCurrentProfile();
	if( pProfile )
	{
		ASSERT( pProfile->GetActivePath() == m_tab.GetCurSel() );
		int nIndex = pProfile->GetActivePath();
		return DeleteProfilePath(pProfile, nIndex);
	}

	return false;
}

BOOL	ImageProfileDlg::OnDuplicatePath(Control ctrl)
{
	ImageProfileManager* pProfile = getCurrentProfile();
	if( pProfile )
	{
		ASSERT( pProfile->GetActivePath() == m_tab.GetCurSel() );
		int nIndex = pProfile->GetActivePath();
		return DuplicateProfilePath(pProfile, nIndex);
	}

	return false;
}

BOOL	ImageProfileDlg::OnAddVLine(Control ctrl)
{
	return OnAddPath(VERTICAL_LINE_IMAGE_PROFILE);
}

BOOL	ImageProfileDlg::OnAddHLine(Control ctrl)
{
	return OnAddPath(HORIZONTAL_LINE_IMAGE_PROFILE);
}

void 	ImageProfileDlg::setDialogResizing()
{
	int nStyleCurrent = GetWindowLong(Window::GetSafeHwnd(), GWL_STYLE);
	if( IsBottomPaneShown() )
	{
		nStyleCurrent |= WS_THICKFRAME;
	}
	else
	{
		nStyleCurrent &= (~WS_THICKFRAME);
	}
	SetWindowLong(Window::GetSafeHwnd(), GWL_STYLE, nStyleCurrent);	
}

/// Iris 5/28/2010 ORG-98 CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG
BOOL	ImageProfileDlg::OnMyShowBottomPane(Control ctrl)
{
	BOOL bRet = OnShowBottomPane(ctrl);
	
	ImageProfileManager* pProfile = getCurrentProfile();
	showHideBottomControls( pProfile && pProfile->GetNumProfilePaths()>0 );

	setDialogResizing();
	
	return bRet;	
}
///End CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG

//BOOL	ImageProfileDlg::OnKeepGraphsClick(Control ctrl)
BOOL	ImageProfileDlg::OnDeleteAllClick(Control ctrl)
{
	ImageProfileManager* pProfile = getCurrentProfile();
	pProfile->SetKeepGraphsOnClosing(!m_ckDelAll.Check);
	return true;
}

BOOL	ImageProfileDlg::UpdateButtonState()
{
	ImageProfileManager* pProfile = getCurrentProfile();
	if( pProfile )
	{
		ASSERT( pProfile->GetNumProfilePaths()==0 || pProfile->GetActivePath() == m_tab.GetCurSel() );
		int nLayoutMode = pProfile->GetLayoutMode();
		ImageProfilerPath* pActivePath = pProfile->GetProfilePath(pProfile->GetActivePath());

		bool	bLayoutSameGraphAllowed = pProfile->IsLayoutSameGraphAllowed();
		m_btnSameGraphCLine.Enable =
		m_btnSameGraphVLine.Enable =
		m_btnSameGraphHLine.Enable = bLayoutSameGraphAllowed;

		if( IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH == nLayoutMode )
		{
			m_btnSameGraphCLine.PressedDown = false;
			m_btnSameGraphVLine.PressedDown = false;
			m_btnSameGraphHLine.PressedDown = false;
			m_btnSeparateGraph.PressedDown = true;
		}
		else
		{
			ASSERT( bLayoutSameGraphAllowed );
			m_btnSameGraphCLine.PressedDown = nLayoutMode == IMAGE_PROFILE_LAYOUT_SAME_GRAPH_CLINE;
			m_btnSameGraphVLine.PressedDown = nLayoutMode == IMAGE_PROFILE_LAYOUT_SAME_GRAPH_VLINE;
			m_btnSameGraphHLine.PressedDown = nLayoutMode == IMAGE_PROFILE_LAYOUT_SAME_GRAPH_HLINE;
			m_btnSeparateGraph.PressedDown = false;
		}

		m_btnAddVLine.Enable = IMAGE_PROFILE_LAYOUT_SAME_GRAPH_HLINE != nLayoutMode;
		m_btnAddHLine.Enable = IMAGE_PROFILE_LAYOUT_SAME_GRAPH_VLINE != nLayoutMode;

		m_btnActivateOutput.Enable = pActivePath != NULL && IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH == nLayoutMode;
		m_btnDeletePath.Enable = pActivePath != NULL;// && pProfile->GetNumProfilePaths() > 1;
		m_btnDuplicatePath.Enable = pActivePath != NULL;// && pActivePath->GetPathType() != CROSSED_LINES_IMAGE_PROFILE;
	}
	else
	{
		ASSERT(0);
	}

	return TRUE;
}

BOOL ImageProfileDlg::OnAddPath(int nPathType)
{
	if( !IS_VALID_PATH_TYPE(nPathType) )
		return FALSE;

	ImageProfileManager* pProfile = getCurrentProfile();
	if( !pProfile )
		return false;

	int nIndex = -1;
	if( nPathType == POLYLINE_IMAGE_PROFILE )
	{
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//GraphPage gpSource = pProfile->GetSourcePage();
		//vector vx, vy;
		//if( getPolylineProfilePoints(gpSource, vx, vy) < 2 )
		//	return false;
		GraphLayer glSource = pProfile->GetSourceLayer();
		vector vx, vy;
		if( getPolylineProfilePoints(glSource, vx, vy) < 2 )
			return false;
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		nIndex = pProfile->AddProfilePath(nPathType, vx, vy);
	}
	else
	{
		nIndex = pProfile->AddProfilePath(nPathType);
	}

	if( nIndex >= 0 )
	{
		if( pProfile->GetNumProfilePaths() == 1 )
		{
			//ASSERT( m_tab.GetItemCount() == 1);
			OnImageProfileUpdate(IPUPDATE_ACTIVE_PROFILE_CHANGE);
		}
		else
		{

			ImageProfilerPath* pPath = pProfile->GetProfilePath(nIndex);
			ASSERT( pPath );
			m_tab.InsertItem(nIndex, pPath->GetPathName());

			pProfile->SetActivePath(nIndex);
			OnImageProfileUpdate(IPUPDATE_ACTIVE_PATH_CHANGE);
		}
	}

	return TRUE;
}

BOOL ImageProfileDlg::RenamePath(int nSelPath)
{
	ImageProfileManager* pProfile = getCurrentProfile();
	if( !pProfile || nSelPath < 0 || nSelPath >= pProfile->GetNumProfilePaths() )
		return false;

	ImageProfilerPath* pPath = pProfile->GetProfilePath(nSelPath);
	if( !pPath )
		return false;
	
	string strOldPathName = pPath->GetPathName(), strNewPathName;
	
	Tree tr;
	TreeNode trNewName = tr.AddNode();
	GETN_USE(trNewName)
	GETN_STR(name, _L("New Path Name"), strOldPathName)
	if(GetNBox(trNewName, "Rename Path"))
	{
		strNewPathName = trNewName.name.GetNodeText();
		strNewPathName.TrimLeft();
		strNewPathName.TrimRight();
		if( !strNewPathName.IsEmpty() && strOldPathName.CompareNoCase(strNewPathName) && pProfile->SetPathName(nSelPath, strNewPathName) )
			return m_tab.SetItemText(nSelPath, strNewPathName);
	}
	return false;
}

BOOL ImageProfileDlg::DeleteProfilePath(ImageProfileManager* pProfile, int nIndex)
{
	if( !pProfile || nIndex < 0 || nIndex >= pProfile->GetNumProfilePaths() )
		return false;
	
	HOLDER_BEFORE_UPDATE_NO_CHECK(get_image_profile_holder());

	if( pProfile->DeleteProfilePath(nIndex) )
	{
		int nSelPath = m_tab.GetCurSel();
		if( nSelPath > nIndex )
			nSelPath--;
		m_tab.DeleteItem(nIndex);

		if( pProfile->GetNumProfilePaths() == 0 )
		{
			// reconstruct the tab
			OnImageProfileUpdate(IPUPDATE_ACTIVE_PROFILE_CHANGE);
		}
		else
		{
			if( nSelPath >= pProfile->GetNumProfilePaths() )
				nSelPath = pProfile->GetNumProfilePaths() - 1;

			pProfile->SetActivePath(nSelPath);
			OnImageProfileUpdate(IPUPDATE_ACTIVE_PATH_CHANGE);
		}

		return true;
	}

	return false;
}

BOOL ImageProfileDlg::DuplicateProfilePath(ImageProfileManager* pProfile, int nIndex)
{
	if( !pProfile || nIndex < 0 || nIndex >= pProfile->GetNumProfilePaths() )
		return false;
	HOLDER_BEFORE_UPDATE_NO_CHECK(get_image_profile_holder());

	int nClonePath = pProfile->DuplicateProfilePath(nIndex);

	if( nClonePath >= 0 )
	{
		ImageProfilerPath* pClonePath = pProfile->GetProfilePath(nClonePath);
		m_tab.InsertItem(nClonePath, pClonePath->GetPathName());
		pProfile->SetActivePath(nClonePath);
		OnImageProfileUpdate(IPUPDATE_ACTIVE_PATH_CHANGE);
		return true;
	}
	return false;
}

///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
//void ImageProfileDlg::ClearPathOnSwitchLayout(ImageProfileManager* pProfile)
void ImageProfileDlg::ClearPathOnSwitchLayout(ImageProfileManager* pProfile, vector<int>& vnDeletedPathIndeces)
///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
{
	if(!pProfile)
		return;
	HOLDER_BEFORE_UPDATE_NO_CHECK(get_image_profile_holder());

	///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	/*
	//for(int ii = pProfile->GetNumProfilePaths() - 1; ii >= 0; ii--)
	//{
	//	ImageProfilerPath* pPath = pProfile->GetProfilePath(ii);
	//	ASSERT( FALSE == pPath->IsKeepOutput() );
	//	pProfile->DeleteProfilePath(ii);
	//}
	while( pProfile->GetNumProfilePaths() > 0 )
	{
		pProfile->DeleteProfilePath(0);
	}
	/// Iris 6/07/2010 ORG_98-P8 NEED_DEL_TABS_WHEN_SWITCH_LAYOUT_MODE
	m_tab.DeleteAllItems();
	///End NEED_DEL_TABS_WHEN_SWITCH_LAYOUT_MODE
	*/
	int nNumDel = 0;
	for(int index = 0; index < vnDeletedPathIndeces.GetSize(); index++)
	{
		int nOriginalIndex = vnDeletedPathIndeces[index] - nNumDel;
		m_tab.DeleteItem(nOriginalIndex);
		nNumDel++;
	}
	///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
}

ImageProfileManager* ImageProfileDlg::getCurrentProfile()
{
	return get_image_profile_holder()->GetActiveProfile();
}

void ImageProfileDlg::initProfileControls(const ImageProfileManager* pProfile, int nIndex)
{
	if( !pProfile )
	{
		ASSERT(0);
		return;
	}
	ASSERT( pProfile->GetNumProfilePaths()==0 || (nIndex>=0 && nIndex<pProfile->GetNumProfilePaths()) );

	ImageProfilerPath* pPath = pProfile->GetProfilePath(nIndex);
	
	TreeNode trGUI = InitTree();
	GETN_USE(trGUI)

	if( pPath )
	{
		showHideBottomControls(true);	// show tab

		/*
		if( CROSSED_LINES_IMAGE_PROFILE != pPath->GetPathType() )
		{
			GETN_NUM(Points, _L("Number of Points"), 100)					GETN_ID(IPROFILE_NUMBER_POINTS_ID)
			GETN_ADD_AUTO(1);
		}
		else
		{
			GETN_NUM(XPoints, _L("Number of Vertical Points"), 100)			GETN_ID(IPROFILE_NUMBER_VPOINTS_ID)
			GETN_ADD_AUTO(1);
			GETN_NUM(YPoints, _L("Number of Horizontal Points"), 100)		GETN_ID(IPROFILE_NUMBER_HPOINTS_ID)
			GETN_ADD_AUTO(1);
		}
		*/
		
		GETN_COLOR(ProfileColor, _L("Color"), 0)						GETN_ID(IPROFILE_PROFILE_COLOR_ID)	///Kyle 06/09/2010 ORG-98-S30 SHOW_PROFILE_COLOR_AT_TOP

		///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
		/*
		///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
		//GETN_COMBO(ProfileWidth, _L("Profile Width"), 0, "|1|2|5|8|10")		GETN_ID(IPROFILE_PROFILE_WIDTH_ID)
		//
		//GETN_NUM(LineWidth, _L("Line Width"), 0)							GETN_ID(IPROFILE_LINE_WIDTH_ID)		GETN_READ_ONLY_EX(ENABLE_READ_ONLY)
		GETN_COMBO(LineWidth, _L("Width"), 0, "|1|2|5|8|10")			GETN_ID(IPROFILE_LINE_WIDTH_ID)
		GETN_STR(Hint, STR_LINE_WIDTH_HINT, "")					 		GETN_HINT
		///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
		*/
		///Kyle 06/17/2010 ORG-98-S40 NEW_WIDTH_CONTROL_WITHOUT_DROP_DOWN
		//GETN_LIST(WidthInPixel, _L("Width"), 0, "|1|2|5|8|10")			GETN_ID(IPROFILE_WIDTH_IN_PIXEL_ID)
		//GETN_RADIO_INDEX(WidthUnit, 0, _L("by Pixel|by Scale"))			GETN_ID(IPROFILE_WIDTH_UNIT_ID)
		//GETN_NUM(CustomWidthInPixel, _L("Custom Width"), 0)				GETN_ID(IPROFILE_CUSTOM_WIDTH_IN_PIXEL_ID)
		//GETN_NUM(CustomWidthInScale, _L("Custom Width"), 0)				GETN_ID(IPROFILE_CUSTOM_WIDTH_IN_SCALE_ID)
		///Kyle 06/21/2010 ORG-355-S2 MAKE_CELL_AND_SCALE_CONTROLS_SUB_NODE_OF_WIDTH
		//GETN_RADIO_INDEX_EX(WidthUnit, _L("Width"), 0, _L("by Cell|by Scale"))		GETN_ID(IPROFILE_WIDTH_UNIT_ID)
		GETN_BEGIN_BRANCH(Width, _L("Width"))		GETN_OPTION_BRANCH(GETNBRANCH_OPEN)
			GETN_RADIO_INDEX(WidthUnit, 0, _L("By Pixel|By Scale"))		GETN_ID(IPROFILE_WIDTH_UNIT_ID)
		///End MAKE_CELL_AND_SCALE_CONTROLS_SUB_NODE_OF_WIDTH
			GETN_NUM(WidthInPixel, _L("Pixels"), 0)						GETN_ID(IPROFILE_WIDTH_IN_PIXEL_ID)
			GETN_NUM(WidthInScale, _L("Scale"), 0)						GETN_ID(IPROFILE_WIDTH_IN_SCALE_ID)		GETN_CURRENT_SUBNODE.SetAttribute(STR_ATTRIB_NUMFMT, "*4*");
		GETN_END_BRANCH(Width)							///Kyle 06/21/2010 ORG-355-S2 MAKE_CELL_AND_SCALE_CONTROLS_SUB_NODE_OF_WIDTH
		///End NEW_WIDTH_CONTROL_WITHOUT_DROP_DOWN
		///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE

		//GETN_COLOR(LineColor, _L("Line Color"), 0)						GETN_ID(IPROFILE_LINE_COLOR_ID)	///Kyle 06/09/2010 ORG-98-S30 SHOW_PROFILE_COLOR_AT_TOP
		
		switch( pPath->GetPathType() )
		{
		//case CROSSED_LINES_IMAGE_PROFILE:
		//	{
		//		GETN_NUM(VLine, _L("X ="), 0)			GETN_ID(IPROFILE_CROSS_LINE_X_ID)
		//		GETN_NUM(HLine, _L("Y ="), 0)			GETN_ID(IPROFILE_CROSS_LINE_Y_ID)
		//		GETN_NUM(ZValue, _L("Z Value"), 0)		GETN_ID(IPROFILE_CROSS_LINE_Z_ID)		GETN_READ_ONLY_EX(ENABLE_READ_ONLY)
		//	}
		//	break;

		case VERTICAL_LINE_IMAGE_PROFILE:
		case HORIZONTAL_LINE_IMAGE_PROFILE:
			{
				if( VERTICAL_LINE_IMAGE_PROFILE == pPath->GetPathType() )
				{
					GETN_NUM(VLine, _L("X"), 0)			GETN_ID(IPROFILE_VERTICAL_LINE_X_ID)
					GETN_CURRENT_SUBNODE.SetAttribute(STR_ATTRIB_NUMFMT, "*4*");		///Kyle 06/18/2010 ORG-98-S38 ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
					GETN_LIST(VTextLoc, _L("Text Location"), 0, STR_VTEXT_LOCATION_OPTIONS)	GETN_ID(IPROFILE_VERTICAL_TEXT_LOCATION_ID) /// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
				}
				else
				{
					GETN_NUM(HLine, _L("Y"), 0)			GETN_ID(IPROFILE_HORIZONTAL_LINE_Y_ID)
					GETN_CURRENT_SUBNODE.SetAttribute(STR_ATTRIB_NUMFMT, "*4*");		///Kyle 06/18/2010 ORG-98-S38 ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
					GETN_LIST(HTextLoc, _L("Text Location"), 0, STR_HTEXT_LOCATION_OPTIONS)	GETN_ID(IPROFILE_HORIZONTAL_TEXT_LOCATION_ID) /// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
				}
			}
			break;

		case ARBITRARY_LINE_IMAGE_PROFILE:
			{
				GETN_NUM(VLine1, _L("X1"), 0)			GETN_ID(IPROFILE_ARBITRARY_LINE_X1_ID)
				GETN_CURRENT_SUBNODE.SetAttribute(STR_ATTRIB_NUMFMT, "*4*");		///Kyle 06/18/2010 ORG-98-S38 ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
				GETN_NUM(HLine1, _L("Y1"), 0)			GETN_ID(IPROFILE_ARBITRARY_LINE_Y1_ID)
				GETN_CURRENT_SUBNODE.SetAttribute(STR_ATTRIB_NUMFMT, "*4*");		///Kyle 06/18/2010 ORG-98-S38 ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
				GETN_NUM(VLine2, _L("X2"), 0)			GETN_ID(IPROFILE_ARBITRARY_LINE_X2_ID)
				GETN_CURRENT_SUBNODE.SetAttribute(STR_ATTRIB_NUMFMT, "*4*");		///Kyle 06/18/2010 ORG-98-S38 ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
				GETN_NUM(HLine2, _L("Y2"), 0)			GETN_ID(IPROFILE_ARBITRARY_LINE_Y2_ID)
				GETN_CURRENT_SUBNODE.SetAttribute(STR_ATTRIB_NUMFMT, "*4*");		///Kyle 06/18/2010 ORG-98-S38 ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
			}
			break;
		/*
		case POLYLINE_IMAGE_PROFILE:
			{
				GETN_BUTTON_GROUP(BtnAddPoint, "", 0, _L("Add anchor point")) GETN_OPTION_DISPLAY_FORMAT(DISPLAY_EDITOR_CENTER)	GETN_ID(IPROFILE_ADD_POINT_BTN_ID)
			}
			break;
		*/

		default:
			ASSERT(0);
		}
	}
	else
	{
		showHideBottomControls(false);	// hide tab
		GETN_STR(Hint, STR_EMPTY_PROFILE_HINT, "") 		GETN_HINT
	}
	
	UpdateDynaControl(true, GETNEVENT_ON_INIT, true, DYNALAYOUT_NO_SET_FOCUS);
}

///Kyle 06/17/2010 ORG-98 ADD_DIRTY_BITS_FOR_GUI_UPDATE
//void ImageProfileDlg::loadProfilePathValues(const ImageProfileManager* pProfile, int nIndex)
void ImageProfileDlg::loadProfilePathValues(const ImageProfileManager* pProfile, int nIndex, DWORD dwDirtyBits)
///End ADD_DIRTY_BITS_FOR_GUI_UPDATE
{
	if( !pProfile )
	{
		ASSERT(0);
		return;
	}
	ASSERT( pProfile->GetNumProfilePaths()==0 || (nIndex>=0 && nIndex<pProfile->GetNumProfilePaths()) );
	///Kyle 06/17/2010 ORG-98 ADD_DIRTY_BITS_FOR_GUI_UPDATE, not dirty, do nothing
	if( !dwDirtyBits )
		return;
	///End ADD_DIRTY_BITS_FOR_GUI_UPDATE

	TreeNode trGUI = GetTree();
	if( !trGUI )
		return;			// not ready

	ImageProfilerPath* pPath = pProfile->GetProfilePath(nIndex);
	if( pPath )
	{
		/*
		bool bAuto;
		if( CROSSED_LINES_IMAGE_PROFILE != pPath->GetPathType() )
		{
			bool bVertical = VERTICAL_LINE_IMAGE_PROFILE==pPath->GetPathType();
			trGUI.Points.nVal = pPath->GetNumPoints(bVertical, &bAuto);
			trGUI.Points.SetAttribute(STR_ATTRIB_AUTO, bAuto);
		}
		else
		{
			trGUI.XPoints.nVal = pPath->GetNumPoints(true, &bAuto);
			trGUI.XPoints.SetAttribute(STR_ATTRIB_AUTO, bAuto);
			
			trGUI.YPoints.nVal = pPath->GetNumPoints(false, &bAuto);
			trGUI.YPoints.SetAttribute(STR_ATTRIB_AUTO, bAuto);
		}
		*/

		///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
		/*
		///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
		//trGUI.ProfileWidth.strVal = FTOA_DEFAULT(pPath->GetProfileWidth());
		//
		//double dLineWidth = pPath->GetLineWidth( VERTICAL_LINE_IMAGE_PROFILE == pPath->GetPathType());
		//trGUI.LineWidth.strVal = FTOA_DEFAULT(dLineWidth);
		vector vWidths;
		pPath->GetSuitableWidths(vWidths);
		vector<string> vsWidths;
		vector<string> vsFormat(vWidths.GetSize());
		for(int ii = 0; ii < vsFormat.GetSize(); ii++)
		{
			if( vWidths[ii] > 1.0 )
				vsFormat[ii] = ".2*";
			else
				vsFormat[ii] = "*2*";
		}
		convert_double_vector_to_string_vector(vWidths, vsWidths, vWidths.GetSize(), vsFormat);
		for(ii = vsWidths.GetSize() - 1; ii > 0; ii--)
		{
			if( vsWidths.Find(vsWidths[ii], 0, true, true, ii-1) >= 0 )
				vsWidths.RemoveAt(ii);
		}
		string strCombo;
		strCombo.SetTokens(vsWidths, '|');
		strCombo = "|" + strCombo;
		trGUI.LineWidth.SetAttribute(STR_COMBO_ATTRIB, strCombo);

		string strLineWidth;
		double dLineWidth = pPath->GetLineWidth();
		if( dLineWidth > 1.0 )
			strLineWidth = ftoa(dLineWidth, ".2*");
		else
			strLineWidth = ftoa(dLineWidth, "*2*");
		trGUI.LineWidth.strVal = strLineWidth;
		///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH

		double dProfileWidth;
		string strHint;
		if( pPath->GetProfileWidth(dProfileWidth, &strHint) )
		{
			strHint = STR_LINE_WIDTH_HINT + strHint;
		}
		else
		{
			strHint = STR_LINE_WIDTH_HINT;
		}
		trGUI.Hint.SetAttribute(STR_LABEL_ATTRIB, strHint);
		*/
		if(IPUPDATE_PATH_CONTENT_WIDTH & dwDirtyBits )		///Kyle 06/17/2010 ORG-98 ADD_DIRTY_BITS_FOR_GUI_UPDATE
		{
			///Kyle 06/17/2010 ORG-98-S40 NEW_WIDTH_CONTROL_WITHOUT_DROP_DOWN
			/*
			vector<int> vnWidthInPixel;
			string strWidths;
			_construct_default_profile_width(pPath, vnWidthInPixel, strWidths);
			strWidths = strWidths + "|" + _L("<Custom>");
			trGUI.WidthInPixel.SetAttribute(STR_COMBO_ATTRIB, strWidths);
	
			int nUnit = pPath->GetProfileWidthUnit();
			int nWidthInPixel = nint(pPath->GetProfileWidth(IPROFILE_PATH_WIDTH_PIXEL));
			bool bWidthCustom = pPath->IsProfileWidthCustom();
			int nWidthIndex;
			if( bWidthCustom )
				nWidthIndex = vnWidthInPixel.GetSize();
			else
			{
				vector<uint> vec;
				if( vnWidthInPixel.Find(vec, nWidthInPixel) > 0 )
					nWidthIndex = vec[0];
				else
					nWidthIndex = 0;
			}
	
			trGUI.WidthUnit.Show = bWidthCustom;
			trGUI.CustomWidthInPixel.Show = bWidthCustom && IPROFILE_PATH_WIDTH_PIXEL==nUnit;
			trGUI.CustomWidthInScale.Show = bWidthCustom && IPROFILE_PATH_WIDTH_SCALE==nUnit;
	
			trGUI.WidthInPixel.nVal = nWidthIndex;
			trGUI.WidthUnit.nVal = nUnit;
			trGUI.CustomWidthInPixel.nVal = nWidthInPixel;
	
			double dWidthInScale = pPath->GetProfileWidth(IPROFILE_PATH_WIDTH_SCALE);
			string strLineWidth;
			if( dWidthInScale > 1.0 )
				strLineWidth = ftoa(dWidthInScale, ".2*");
			else
				strLineWidth = ftoa(dWidthInScale, "*2*");
			trGUI.CustomWidthInScale.strVal = strLineWidth;
			*/
			int nUnit = pPath->GetProfileWidthUnit();
			
			///Kyle 06/21/2010 ORG-355-S2 MAKE_CELL_AND_SCALE_CONTROLS_SUB_NODE_OF_WIDTH
			/*
			trGUI.WidthUnit.nVal = nUnit;
			_update_profile_width_to_treenode(trGUI.WidthInPixel, pPath, IPROFILE_PATH_WIDTH_PIXEL);
			_update_profile_width_to_treenode(trGUI.WidthInScale, pPath, IPROFILE_PATH_WIDTH_SCALE);
			
			trGUI.WidthInPixel.Enable = IPROFILE_PATH_WIDTH_PIXEL==nUnit;
			trGUI.WidthInScale.Enable = IPROFILE_PATH_WIDTH_SCALE==nUnit;
			*/
			TreeNode trWidth = trGUI.Width;
			trWidth.WidthUnit.nVal = nUnit;
			_update_profile_width_to_treenode(trWidth.WidthInPixel, pPath, IPROFILE_PATH_WIDTH_PIXEL);
			_update_profile_width_to_treenode(trWidth.WidthInScale, pPath, IPROFILE_PATH_WIDTH_SCALE);
			
			trWidth.WidthInPixel.Enable = IPROFILE_PATH_WIDTH_PIXEL==nUnit;
			trWidth.WidthInScale.Enable = IPROFILE_PATH_WIDTH_SCALE==nUnit;
			///End MAKE_CELL_AND_SCALE_CONTROLS_SUB_NODE_OF_WIDTH
			///End NEW_WIDTH_CONTROL_WITHOUT_DROP_DOWN
		}
		///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE

		///Kyle 06/09/2010 ORG-98-S30 SHOW_PROFILE_COLOR_AT_TOP
		//trGUI.LineColor.nVal = pPath->GetProfileLineColor();
		if(IPUPDATE_PATH_CONTENT_COLOR & dwDirtyBits )		///Kyle 06/17/2010 ORG-98 ADD_DIRTY_BITS_FOR_GUI_UPDATE
			trGUI.ProfileColor.nVal = pPath->GetProfileLineColor();
		///End SHOW_PROFILE_COLOR_AT_TOP

		if(IPUPDATE_PATH_CONTENT_POSITION & dwDirtyBits )		///Kyle 06/17/2010 ORG-98 ADD_DIRTY_BITS_FOR_GUI_UPDATE
		{
			switch( pPath->GetPathType() )
			{
			//case CROSSED_LINES_IMAGE_PROFILE:
			//	{
			//		ImageProfilerCrossLinePath* clPath = (ImageProfilerCrossLinePath*)pPath;
	
			//		double dHLine, dVLine, dZValue;
			//		clPath->GetLinePosition(dHLine, false);
			//		clPath->GetLinePosition(dVLine, true);
			//		clPath->GetLineIntersection(dZValue);
	
			//		trGUI.VLine.strVal = FTOA_DEFAULT(dVLine);
			//		trGUI.HLine.strVal = FTOA_DEFAULT(dHLine);
			//		trGUI.ZValue.strVal = FTOA_DEFAULT(dZValue);
			//	}
			//	break;
	
			case VERTICAL_LINE_IMAGE_PROFILE:
			case HORIZONTAL_LINE_IMAGE_PROFILE:
				{
					double dValue;
					bool bVertical = VERTICAL_LINE_IMAGE_PROFILE == pPath->GetPathType();
					ImageProfilerHVPath* hvPath = (ImageProfilerHVPath*)pPath;
	
					hvPath->GetLinePosition(dValue, bVertical);
					int nTextObjectLocation = hvPath->GetTextObjectLocation(); /// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
					if( bVertical )
					{
						///Kyle 06/18/2010 ORG-98-S38 ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
						//trGUI.VLine.strVal = FTOA_DEFAULT(dValue);
						trGUI.VLine.dVal = dValue;
						///End ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
						trGUI.VTextLoc.nVal = nTextObjectLocation; /// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
					}
					else
					{
						///Kyle 06/18/2010 ORG-98-S38 ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
						//trGUI.HLine.strVal = FTOA_DEFAULT(dValue);
						trGUI.HLine.dVal = dValue;
						///End ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
						trGUI.HTextLoc.nVal = nTextObjectLocation; /// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
					}
				}
				break;
	
			case ARBITRARY_LINE_IMAGE_PROFILE:
				{
					vector vx, vy;
					if( !pPath->GetLinePosition(vx, vy) )
					{
						vx.SetSize(2);
						vy.SetSize(2);
						vx = NANUM;
						vy = NANUM;
					}
					ASSERT( vx.GetSize()==2 && vy.GetSize()==2 );
					///Kyle 06/18/2010 ORG-98-S38 ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
					/*
					trGUI.VLine1.strVal = FTOA_DEFAULT(vx[0]);
					trGUI.HLine1.strVal = FTOA_DEFAULT(vy[0]);
					trGUI.VLine2.strVal = FTOA_DEFAULT(vx[1]);
					trGUI.HLine2.strVal = FTOA_DEFAULT(vy[1]);
					*/
					trGUI.VLine1.dVal = vx[0];
					trGUI.HLine1.dVal = vy[0];
					trGUI.VLine2.dVal = vx[1];
					trGUI.HLine2.dVal = vy[1];
					///End ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
				}
				break;
	
			case POLYLINE_IMAGE_PROFILE:
				break;
	
			default:
				ASSERT(0);
			}
		}
		
		UpdateDynaControl(true, GETNEVENT_ON_CHANGE_UPDATE_GUI);
	}
}

void ImageProfileDlg::showHideBottomControls(bool bShowTab)
{
	/// Iris 5/28/2010 ORG-98 CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG
	//m_tab.Visible = bShowTab; 
	m_tab.Visible = IsBottomPaneShown() && bShowTab;
	m_DynaCntrl.Visible = IsBottomPaneShown();
	///End CHANGE_IMG_PROFILE_DLG_AS_MULTI_PANE_DLG
	
	RECT rr;
	GetClientRect(m_tab, rr);

	if( bShowTab )
		m_tab.AdjustRect(FALSE, &rr);
	MoveControl(m_DynaCntrl, rr);	
}

void ImageProfileDlg::initControls()
{
	m_tab = GetItem(IDC_IMAGE_PROFILE_TAB);
	m_tab.InsertItem(0, _L("Hint"));	// to arrange controls correctly in OnDlgResize() when m_tab shown, for save	
	
	m_ckDelAll = GetItem(IDC_CHECK_DEL_ALL);
	m_ckDelAll.Check = false;
	//DWORD dwVal = LoadSetting(STR_KEEP_GRAPH_REG_KEY, 1, STR_DLG_NAME_E);
	//m_ckKeepGraph.Check = dwVal;
	
	m_btnSameGraphCLine = GetItem(IDC_SAME_GRAPH_CLINE);
	m_btnSameGraphVLine = GetItem(IDC_SAME_GRAPH_VLINE);
	m_btnSameGraphHLine = GetItem(IDC_SAME_GRAPH_HLINE);
	m_btnSeparateGraph = GetItem(IDC_SEPARATE_GRAPH);

	m_btnAddVLine = GetItem(IDC_IPROFILE_ADD_VLINE);
	m_btnAddHLine = GetItem(IDC_IPROFILE_ADD_HLINE);

	m_btnActivateOutput = GetItem(IDC_IPROFILE_ACTIVATE_OUTPUT);
	m_btnDeletePath = GetItem(IDC_IPROFILE_DELETE);
	m_btnDuplicatePath = GetItem(IDC_IPROFILE_DUPLICATE);

	vector<string> vsTips(1);

	vsTips[0] = _L("Same Graph: Crossed Lines");
	m_btnSameGraphCLine.Init(1, IDB_IPROFILE_SAME_GRAPH_CLINE, 16, vsTips);
	
	vsTips[0] = _L("Same Graph: Vertical Line");
	m_btnSameGraphVLine.Init(1, IDB_IPROFILE_SAME_GRAPH_VLINE, 16, vsTips);
	
	vsTips[0] = _L("Same Graph: Horizontal Line");
	m_btnSameGraphHLine.Init(1, IDB_IPROFILE_SAME_GRAPH_HLINE, 16, vsTips);
	
	vsTips[0] = _L("Separate Graph");
	m_btnSeparateGraph.Init(1, IDB_IPROFILE_SEPARATE_GRAPH, 16, vsTips);
	
	vsTips[0] = _L("Add Vertical Line");
	m_btnAddVLine.Init(1, IDB_IPROFILE_ADD_VLINE, 16, vsTips);
	
	vsTips[0] = _L("Add Horizontal Line");
	m_btnAddHLine.Init(1, IDB_IPROFILE_ADD_HLINE, 16, vsTips);

	vsTips[0] = _L("Activate Output");
	m_btnActivateOutput.Init(1, IDB_IPROFILE_ACTIVATE_OUTPUT, 16, vsTips);
	
	vsTips[0] = _L("Delete Active Profile");
	m_btnDeletePath.Init(1, IDB_IPROFILE_DELETE, 16, vsTips);
	
	vsTips[0] = _L("Duplicate Active Profile");
	m_btnDuplicatePath.Init(1, IDB_IPROFILE_DUPLICATE, 16, vsTips);
}

#define STR_ADD_PROFILE_POINTS 		_L("Double-click on the graph layer to add points inside the layer for the profile line")
///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
//int ImageProfileDlg::getPolylineProfilePoints(GraphPage& gp, vector& vx, vector& vy)
int ImageProfileDlg::getPolylineProfilePoints(GraphLayer& gl, vector& vx, vector& vy)
///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
{
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	/*
	if(!gp)
		return FALSE;
	
	GraphLayer gl = gp.Layers();
	*/
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	if(!gl)
		return FALSE;
	set_active_layer(gl);
	
	graph_get_points(vx, vy, STR_ADD_PROFILE_POINTS);
	ASSERT(vx.GetSize()==vy.GetSize());
	return vx.GetSize();
}

/*----------------------------------------------------------------------------*/
/* Context Menu
/*----------------------------------------------------------------------------*/

class IProfileTabMenu : public Menu
{
public:
	IProfileTabMenu()
	{
		Add(_L("Rename"), OnMenuItem, MF_STRING, IPROFILE_TAB_MENU_RENAME);
	}
	void OnMenuItem(UINT nPos)
	{
	}
};


/*----------------------------------------------------------------------------*/
/* ImageProfileHVLine
/*----------------------------------------------------------------------------*/

bool ImageProfileHVLine::Create(GraphLayer& gl, double dLineWidth, int nColor, bool bVertical, double dPos, int nTextObjectLocation)
{
	if(!gl)
		return false;
	
	if( IsValid() )
		return true;

	dLineWidth = fabs(dLineWidth);

	/*
	double x1 = bVertical? 0.5*(gl.X.From + gl.X.To) : gl.X.From;
	double x2 = bVertical? 0.5*(gl.X.From + gl.X.To) : gl.X.To;
	
	double y1 = bVertical? gl.Y.From : 0.5*(gl.Y.From + gl.Y.To);
	double y2 = bVertical? gl.Y.To : 0.5*(gl.Y.From + gl.Y.To);
	
	bool bSpan		= true;//ATTACH_TO_LAYER
	bool bPercent	= false;
	bool bRet = add_line(gl, *this, x1, y1, ATTACH_TO_SCALE, bVertical? LN_VERTICAL:LN_HORIZONTAL, bSpan, bPercent, x2, y2, nColor);
	if( !bRet || !IsValid() )
	{
		ASSERT( FALSE );
		return false;
	}

	DWORD dw = bVertical? GOC_NO_VMOVE:GOC_NO_HMOVE;
	update_go_states(*this, dw|GOC_NO_RESIZE|GOC_NO_ROTATE|GOC_NO_SKEW|GOC_NO_EDIT);

	Tree trFmt;
	trFmt.Root.KeepInside.nVal = 1;
	if( 0 == UpdateThemeIDs(trFmt.Root) )
		ApplyFormat(trFmt, FALSE, TRUE);

	set_go_width(*this, dLineWidth);
	SetName(bVertical? STR_VERTICAL_NAME_PREFIX:STR_HORIZONTAL_NAME_PREFIX, OCD_ENUM_NEXT);	
	set_LT_script(*this, STR_IMAGE_PROFILE_OBJ_EVENT_LT_SCRIPT, GRCT_ANY_EVENT, 1);//GRCT_MOVE
	*/
	// use rectangle for V/H profile
	double x0, x1, y0, y1;
	if( bVertical )
	{
		double	dXFrom = gl.X.From,
				dXTo = gl.X.To;

		bool bMid = true;
		if( dPos!=NANUM )
		{
			x0 = dPos - 0.5*dLineWidth;
			x1 = dPos + 0.5*dLineWidth;
			if( (x0 >= dXFrom && x1 <= dXTo) || (x0 >= dXTo && x1 <= dXFrom) )
				bMid = false;
		}
		if( bMid )
		{
			double dXMid = 0.5*(dXFrom + dXTo);
			x0 = dXMid - 0.5*dLineWidth;
			x1 = dXMid + 0.5*dLineWidth;
		}

		y0 = gl.Y.From;
		y1 = gl.Y.To;
	}
	else
	{
		x0 = gl.X.From;
		x1 = gl.X.To;

		//double dYMid = 0.5*(gl.Y.From + gl.Y.To);
		//y0 = dYMid - 0.5*dLineWidth;
		//y1 = dYMid + 0.5*dLineWidth;
		double	dYFrom = gl.Y.From,
				dYTo = gl.Y.To;

		bool bMid = true;
		if( dPos!=NANUM )
		{
			y0 = dPos - 0.5*dLineWidth;
			y1 = dPos + 0.5*dLineWidth;
			if( (y0 >= dYFrom && y1 <= dYTo) || (y0 >= dYTo && y1 <= dYFrom) )
				bMid = false;
		}
		if( bMid )
		{
			double dYMid = 0.5*(dYFrom + dYTo);
			y0 = dYMid - 0.5*dLineWidth;
			y1 = dYMid + 0.5*dLineWidth;
		}
	}

	bool bSpan		= true;//ATTACH_TO_LAYER
	bool bPercent	= false;
	bool bRet = add_rect(gl, *this, x0, y0, x1, y1, INDEX_COLOR_TRANSPARENT, ATTACH_TO_SCALE, bVertical? LN_VERTICAL:LN_HORIZONTAL, bSpan, bPercent);
	set_go_border_color(*this, nColor);
	if( !bRet || !IsValid() )
	{
		ASSERT( FALSE );
		return false;
	}

	DWORD dw = bVertical? GOC_NO_VMOVE:GOC_NO_HMOVE;
	update_go_states(*this, dw|GOC_NO_TRANSPARENT|GOC_NO_RESIZE|GOC_NO_ROTATE|GOC_NO_SKEW|GOC_NO_EDIT);

	Tree trFmt;
	trFmt.Root.KeepInside.nVal = 1;
	if( 0 == UpdateThemeIDs(trFmt.Root) )
		ApplyFormat(trFmt, FALSE, TRUE);

	SetName(bVertical? STR_VERTICAL_NAME_PREFIX:STR_HORIZONTAL_NAME_PREFIX, OCD_ENUM_NEXT);	
	set_LT_script(*this, STR_IMAGE_PROFILE_OBJ_EVENT_LT_SCRIPT, GRCT_ANY_EVENT, 1);//GRCT_MOVE
	SetSelectEffect(false);		///Kyle 07/14/2010 ORG-571-S1 NO_SELECT_EFFECT_FOR_GRAPH_OBJECT
	SetDBClick(false);				///Kyle 07/16/2010 ORG-584-S2 PREVENT_DB_CLICK_ON_GRAPH_OBJECT
	set_go_printable(*this);				///Kyle 07/28/2010 ORG-662-P1 MAKE_PROFILE_OBJECT_PRINTABLE
	
	AddReadOut(gl, bVertical, dPos, nTextObjectLocation);

	return true;
}

static void _adjust_connected_text_object_location(GraphObject& goMain, GraphObject& goText, bool bVertical, int nLocation, LPCSTR lpcszText = NULL)
{
	if( !goMain || !goText )
		return;
	
	CTempDisConnect tmpDisConn(goText, goMain);			// change position will effect on the connected object, so disconnect the object temporarily
	
	if( lpcszText )
		goText.Text = lpcszText;
	
	double dGap = 0.2;
	int nLeft, nTop;
	
	if( bVertical )
	{
		double dMiddle = goMain.Left + 0.5 * goMain.Width;
		nLeft = dMiddle - 0.5 * goText.Width;
		
		if( TEXT_LOC_BOTTOM == nLocation )
			nTop = goMain.Top + goMain.Height + dGap * goText.Height;
		else
			nTop = goMain.Top - (1 + dGap ) * goText.Height;	
	}
	else
	{
		if ( TEXT_LOC_RIGHT == nLocation )
			nLeft = goMain.Left + goMain.Width + dGap * goText.Width;
		else
			nLeft = goMain.Left - (1 + dGap ) * goText.Width;
		
		double dMiddle = goMain.Top + 0.5 * goMain.Height;
		nTop = dMiddle - 0.5 * goText.Height;
	}
	goText.Left = nLeft;
	goText.Top = nTop;
}

bool ImageProfileHVLine::AddReadOut(GraphLayer& gl, bool bVertical, double dPos, int nTextObjectLocation)
{
	if( !(gl && IsValid()) )
		return false;

	/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
	/*
	GraphObject goLine(*this);
	Tree trSource;
	trSource = goLine.GetFormat(FPB_STYLE_COLOR, FOB_ALL, TRUE, TRUE);
	ASSERT(trSource.Root);
	*/
	///End NEW_SUGGESTION_FOR_TEXT_OBJECT
	
	GraphObject goText;
	goText = gl.CreateGraphObject(GROBJ_TN_TEXT);
	if( !goText.IsValid() )
		return false;
	goText.Attach = ATTACH_TO_SCALE;

	///Kyle 06/18/2010 ORG-98-S38 ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
	//goText.Text = ftoa(dPos, "*");
	goText.Text = _get_pos_string_for_label_text(dPos);
	///End ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
	///Kyle 06/10/2010 ORG-98-S30 MAKE_HV_LINE_AND_LABEL_TEXT_GROUP_MOVABLE, move Text first
	int nLeft, nTop;

	GraphObject goMain = *this;
	/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
	/*
	if( bVertical )
	{
		double dMiddle = goMain.Left + 0.5 * goMain.Width;
		nLeft = dMiddle - 0.5 * goText.Width;
		nTop = goMain.Top - 1.2 * goText.Height;					// 0.2 * goText.Height: Gap
	}
	else
	{
		nLeft = goMain.Left - goText.Width - 0.2 * goText.Height;	// 0.2 * goText.Height: Gap

		double dMiddle = goMain.Top + 0.5 * goMain.Height;
		nTop = dMiddle - 0.5 * goText.Height;
	}
	goText.Left = nLeft;
	goText.Top = nTop;
	*/
	_adjust_connected_text_object_location(goMain, goText, bVertical, nTextObjectLocation);
	///End NEW_SUGGESTION_FOR_TEXT_OBJECT
	///End MAKE_HV_LINE_AND_LABEL_TEXT_GROUP_MOVABLE

	Tree trFormat;
	trFormat.Root.Font.Size.nVal = 20;
	trFormat.Root.TextWhiteOut.nVal = 1;				///Kyle 06/21/2010 ORG-355-S1 TEXT_LABEL_SHOULD_BE_WHITE_OUT
	/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
	//trFormat.Root.Color.nVal = trSource.Root.Border.Color? trSource.Root.Border.Color.nVal : SYSCOLOR_BLUE;
	///End NEW_SUGGESTION_FOR_TEXT_OBJECT
	///Kyle 06/10/2010 ORG-98-S30 MAKE_HV_LINE_AND_LABEL_TEXT_GROUP_MOVABLE, disable h/v move
	//trFormat.Root.States.nVal = GOC_NO_RESIZE | GOC_NO_ROTATE | GOC_NO_SKEW | GOC_NO_EDIT | GOC_NO_BORDERSIZE | GOC_NO_IN_PLACE_EDIT;
	DWORD dw = bVertical? GOC_NO_VMOVE:GOC_NO_HMOVE;
	trFormat.Root.States.nVal = dw | GOC_NO_RESIZE | GOC_NO_ROTATE | GOC_NO_SKEW | GOC_NO_EDIT | GOC_NO_BORDERSIZE | GOC_NO_IN_PLACE_EDIT;
	///End MAKE_HV_LINE_AND_LABEL_TEXT_GROUP_MOVABLE
	/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
	//trFormat.Root.TextWhiteOut.nVal = 1;
	trFormat.Root.Background.Border.Color.nVal = 0;
	///End NEW_SUGGESTION_FOR_TEXT_OBJECT

	goText.UpdateThemeIDs(trFormat.Root);
	goText.ApplyFormat(trFormat, true, true);

	///Kyle 06/10/2010 ORG-98-S30 MAKE_HV_LINE_AND_LABEL_TEXT_GROUP_MOVABLE
	//connect_justify(*this, goText, bVertical ? CTP_TOP : CTP_LEFT);
	goText.ConnectTo(*this, -1, -1, false);
	///End MAKE_HV_LINE_AND_LABEL_TEXT_GROUP_MOVABLE
	
	set_LT_script(goText, STR_IMAGE_PROFILE_READ_OUT_LT_SCRIPT, GRCT_ANY_EVENT, 1);
	goText.SetDBClick(false);				///Kyle 07/16/2010 ORG-584-S2 PREVENT_DB_CLICK_ON_GRAPH_OBJECT
	set_go_printable(goText);				///Kyle 07/28/2010 ORG-662-P1 MAKE_PROFILE_OBJECT_PRINTABLE

	return true;
}


/*----------------------------------------------------------------------------*/
/* ImageProfileAbitraryLine
/*----------------------------------------------------------------------------*/

bool ImageProfileAbitraryLine::Create(GraphLayer& gl, double dLineWidth, int nColor)
{
	if(!gl)
		return false;
	
	if( IsValid() )
		return true;
	
	double x1 = gl.X.From + 0.2*(gl.X.To - gl.X.From);
	double y1 = gl.Y.To - 0.2*(gl.Y.To - gl.Y.From);
	double x2 = gl.X.To - 0.2*(gl.X.To - gl.X.From);
	double y2 = gl.Y.From + 0.2*(gl.Y.To - gl.Y.From);
	
	bool bSpan		= false;
	bool bPercent	= false;
	bool bRet = add_line(gl, *this, x1, y1, ATTACH_TO_SCALE, LN_FREE, bSpan, bPercent, x2, y2, nColor);	// SYSCOLOR_YELLOW
	if( !bRet || !IsValid() )
	{
		ASSERT( FALSE );
		return false;
	}

	Tree trFmt;
	trFmt.Root.KeepInside.nVal = 1;
	if( 0 == UpdateThemeIDs(trFmt.Root) )
		ApplyFormat(trFmt, FALSE, TRUE);

	update_go_states(*this, GOC_NO_RESIZE|GOC_NO_ROTATE|GOC_NO_SKEW);
	set_go_width(*this, dLineWidth);
	SetName(STR_ABITRARY_NAME_PREFIX, OCD_ENUM_NEXT);	
	set_LT_script(*this, STR_IMAGE_PROFILE_OBJ_EVENT_LT_SCRIPT, GRCT_ANY_EVENT, 1);//GRCT_SIZEMOVE
	SetSelectEffect(false);			///Kyle 07/14/2010 ORG-571-S1 NO_SELECT_EFFECT_FOR_GRAPH_OBJECT
	SetDBClick(false);				///Kyle 07/16/2010 ORG-584-S2 PREVENT_DB_CLICK_ON_GRAPH_OBJECT
	set_go_printable(*this);				///Kyle 07/28/2010 ORG-662-P1 MAKE_PROFILE_OBJECT_PRINTABLE
	
	return true;
}

/*----------------------------------------------------------------------------*/
/* ImageProfilePolyLine
/*----------------------------------------------------------------------------*/

bool ImageProfilePolyLine::Create(GraphLayer& gl, double dLineWidth, int nColor, const vector& vx, const vector& vy)
{
	if(!gl)
		return false;
	
	if( IsValid() )
		return true;

	ASSERT(vx.GetSize() == vy.GetSize());
	//temp, just in case, wait GetPtsDlg improved
	_check_min_max(vx, gl.X.From, gl.X.To);
	_check_min_max(vy, gl.Y.From, gl.Y.To);

	bool bPercent = false;
	bool bRet = add_polyline(gl, *this, vx, vy, ATTACH_TO_SCALE, bPercent, nColor);	//SYSCOLOR_YELLOW
	if( !bRet || !IsValid() )
	{
		ASSERT( FALSE );
		return false;
	}

	update_go_states(*this, GOC_NO_RESIZE|GOC_NO_ROTATE|GOC_NO_SKEW);
	set_go_width(*this, dLineWidth);

	// arrow, mark begin/end
	Tree trFmt;
	trFmt.Root.KeepInside.nVal = 1;
	trFmt.Root.Arrow.Begin.Style.nVal = 4;
	trFmt.Root.Arrow.Begin.Width.dVal = 15;
	trFmt.Root.Arrow.Begin.Length.dVal = 10;
	trFmt.Root.Arrow.End.Style.nVal = 1;
	trFmt.Root.Arrow.End.Width.dVal = 15;
	trFmt.Root.Arrow.End.Length.dVal = 10;
	if( 0 == UpdateThemeIDs(trFmt.Root) )
		ApplyFormat(trFmt, FALSE, TRUE);

	SetName(STR_POLYLINE_NAME_PREFIX, OCD_ENUM_NEXT);
	set_LT_script(*this, STR_IMAGE_PROFILE_OBJ_EVENT_LT_SCRIPT, GRCT_ANY_EVENT, 1);//GRCT_SIZEMOVE
	SetSelectEffect(false);			///Kyle 07/14/2010 ORG-571-S1 NO_SELECT_EFFECT_FOR_GRAPH_OBJECT
	SetDBClick(false);				///Kyle 07/16/2010 ORG-584-S2 PREVENT_DB_CLICK_ON_GRAPH_OBJECT
	set_go_printable(*this);				///Kyle 07/28/2010 ORG-662-P1 MAKE_PROFILE_OBJECT_PRINTABLE
	
	return true;
}

/*----------------------------------------------------------------------------*/
/* ImageProfilerPath
/*----------------------------------------------------------------------------*/

void ImageProfilerPath::BringObjToFront()
{
	for(int ii = m_arrPathInfo.GetSize() - 1; ii >= 0; ii--)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		GraphObject goLine = info.GetLineObject();
		if( goLine )
		{
			goLine.MoveObject(MO_TOP);
		}
	}
}

bool ImageProfilerPath::CheckResetCalculator(const DataRange& drChange)
{
	ASSERT( drChange.IsValid() );
	DataPlot dpSrc;
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//if( m_profileCalculator.GetSourcePlot(dpSrc) )
	if( m_pCalculator->GetSourcePlot(dpSrc) )
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	{
		DataRange drSrc;
		if( dpSrc.GetDataRange(drSrc) && drSrc.IsValid() && drSrc.Intersects(drChange) )
		{
			///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			//m_profileCalculator.ResetCalculator();
			m_pCalculator->ResetCalculator();
			///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			return true;
		}
	}
	return false;
}
///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
void	ImageProfilerPath::SetSourceLayer(GraphLayer& glSource)
{
	for(int ii = m_arrPathInfo.GetSize() - 1; ii >= 0 ; ii--)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		info.m_glSource = glSource;
	}
}
///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS

///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
void	ImageProfilerPath::SetSourcePlot(DataPlot& dpSource)
{
	for(int ii = m_arrPathInfo.GetSize() - 1; ii >= 0 ; ii--)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
		//info.m_dpSource = dpSource;
		info.m_uSourcePlot = dpSource.GetUID(true);
		///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	}
}

bool	ImageProfilerPath::GetSourcePlot(DataPlot& dpSource)
{
	for(int ii = m_arrPathInfo.GetSize() - 1; ii >= 0 ; ii--)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
		/*
		if( info.m_dpSource )
		{
			dpSource = info.m_dpSource;
			break;
		}
		*/
		if( info.GetSourcePlot(dpSource) )
			break;
		///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	}

	return dpSource.IsValid();
}
///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED

GraphLayer	ImageProfilerPath::GetSourceLayer()
{
	GraphLayer gl;
	for(int ii = m_arrPathInfo.GetSize() - 1; ii >= 0 ; ii--)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		if( info.m_glSource.IsValid() )
		{
			gl = info.m_glSource;
			break;
		}
	}

	return gl;
}

///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
//bool	ImageProfilerPath::IsRelatedLayer(const GraphLayer& gl)
bool	ImageProfilerPath::IsRelatedLayer(const GraphLayer& gl, bool bCheckSource)
///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
{
	for(int ii = m_arrPathInfo.GetSize() - 1; ii >= 0 ; ii--)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//if( is_same_layer(gl, info.m_glSource) || is_same_layer(gl, info.m_glOutput) )
		if( (bCheckSource && is_same_layer(gl, info.m_glSource)) || is_same_layer(gl, info.m_glOutput) )
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			return true;
	}

	return false;
}

bool	ImageProfilerPath::IsRelatedGrObj(UINT uObjUID)
{
	return GetPathInfoIndex(uObjUID) >= 0;
}

bool	ImageProfilerPath::GetOutputWP(WorksheetPage& wpOutput)
{
	int c1, c2;
	Worksheet wks;
	for( int ii = m_arrPathInfo.GetSize() - 1; ii >= 0 ; ii--)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		if( info.m_drOutput )
		{
			if( info.m_drOutput.GetRange(wks, c1, c2) && wks )
			{
				wpOutput = wks.GetPage();
				return true;
			}
		}
	}

	return false;
}

bool	ImageProfilerPath::GetOutputWks(Worksheet& wksOutput, bool bVertical)
{
	int nIndex = GetLineIndex(bVertical);
	if( nIndex >= 0 && nIndex < m_arrPathInfo.GetSize() )
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);
		if( info.m_drOutput )
		{
			int c1, c2;
			if( info.m_drOutput.GetRange(wksOutput, c1, c2) && wksOutput )
			{
				ASSERT(c1 == c2);
				return true;
			}
		}
	}
	return false;
}

bool	ImageProfilerPath::GetOutputLayer(GraphLayer& glOutput, bool bVertical)
{
	int nIndex = GetLineIndex(bVertical);
	if( nIndex >= 0 && nIndex < m_arrPathInfo.GetSize() )
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);
		if( info.m_glOutput )
		{
			glOutput = info.m_glOutput;
			return true;
		}
	}
	return false;
}

void	ImageProfilerPath::ClearProfile()
{
	for(int ii = m_arrPathInfo.GetSize() - 1; ii >= 0; ii--)
		RemovePathInfoAt(ii, !IsKeepOutput(), !IsKeepOutput());
}

bool	ImageProfilerPath::SetNumPoints(int nPoints, bool bVertical)
{
	int nIndex = GetLineIndex(bVertical);
	if(nIndex < 0 || nIndex >= m_arrPathInfo.GetSize() )
		return -1;

	if( nPoints < 0 )
		nPoints = -1;						// auto

	if( nPoints >= 0 && nPoints < 2 )		// no auto, wrong value
		return false;
	
	ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);
	info.m_nNumPoints = nPoints;
	
	//DoProfile(nIndex);

	return true;
}

int		ImageProfilerPath::GetNumPoints(bool bVertical, bool* pbAuto)
{
	int nIndex = GetLineIndex(bVertical);
	if(nIndex < 0 || nIndex >= m_arrPathInfo.GetSize() )
		return -1;

	ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);

	bool bAuto;
	///Kyle 06/18/2010 ORG-98 BETTER_AUTO_NUMBER_OF_POINTS_FOR_OUTPUT
	//int nNumPoints = GetPathNumPoints(info, bAuto);
	int nNumPoints = -1;		// auto
	if( info.m_nNumPoints >= 2 )
	{
		bAuto = false;
		nNumPoints = info.m_nNumPoints;
	}
	else
	{
		bAuto = true;

		///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
		/*
		DataPlot dpSrc;
		if( info.m_glSource )
			dpSrc = info.m_glSource.DataPlots();
		if( m_pCalculator->CheckInitSource(dpSrc) )
		*/
		/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
		//if( m_pCalculator->CheckInitSource(info.m_dpSource) )
		DataPlot dpSource;
		if( info.GetSourcePlot(dpSource) && m_pCalculator->CheckInitSource(dpSource) )
		///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
		///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
		{
			vector vxAPoints, vyAPoints;
			if( GetPathPosition(info, vxAPoints, vyAPoints) )
			{
				int nUnit = GetProfileWidthUnit();
				double dWidth = GetProfileWidth(nUnit);
	
				nNumPoints = m_pCalculator->CalcAutoOutputSize(dWidth, nUnit, vxAPoints, vyAPoints);
			}
		}
		if( nNumPoints < 0 )
			nNumPoints = 100;
	}
	///End BETTER_AUTO_NUMBER_OF_POINTS_FOR_OUTPUT
	if( pbAuto )
		*pbAuto = bAuto;
	
	return nNumPoints;
}

///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
/*
double	ImageProfilerPath::GetProfileWidth()
{
	return m_dProfileWidth;
}

bool	ImageProfilerPath::SetProfileWidth(double dWidth)
{
	if( dWidth <= 0 )
		return false;

	m_dProfileWidth = dWidth;

	for(int ii = m_arrPathInfo.GetSize() - 1; ii >= 0; ii--)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		double dLineWidth = GetLineWidth(info);
		SetPathWidth(info, dLineWidth);
	}

	return true;
}

double	ImageProfilerPath::GetLineWidth(bool bVertical)
{
	int nIndex = GetLineIndex(bVertical);
	if(nIndex < 0 || nIndex >= m_arrPathInfo.GetSize() )
		return NANUM;

	ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);
	return GetLineWidth(info);
}
*/
///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
//double	ImageProfilerPath::GetLineWidth()
//{
	//return m_dLineWidth;
//}
//
//bool	ImageProfilerPath::SetLineWidth(double dWidth)
//{
	//if( dWidth < 0 )
		//return false;
//
	//if( is_equal(m_dLineWidth, dWidth) )
		//return true;
//
	//m_dLineWidth = dWidth;
	//for(int ii = m_arrPathInfo.GetSize() - 1; ii >= 0; ii--)
	//{
		//ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		//SetPathWidth(info, m_dLineWidth);
//
		//GraphObject goLine = info.GetLineObject();
		//if( goLine )
			//goLine.PostMessage(OE_MOVE);
	//}
//
	//return true;
//}
//
/////Kyle 06/11/2010 ORG-98-S34 RESTRICT_LINE_WIDTH_AND_GIVE_HINT_FOR_PROFILE_WIDTH
//bool	ImageProfilerPath::GetProfileWidth(double& dWidth, string* pstrHint)
//{
	//DataPlot dpSrc;
	//ImageProfilePathInfo* pInfo = NULL;
//
	//for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	//{
		//ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		//if( info.m_glSource )
		//{
			//dpSrc = info.m_glSource.DataPlots();
			//if( dpSrc )
			//{
				//pInfo = &info;
				//break;
			//}
		//}
	//}
	//if( !dpSrc || !pInfo )
		//return false;
//
	//vector vxAPoints, vyAPoints;
	//if( !GetPathPosition(*pInfo, vxAPoints, vyAPoints) )
		//return false;
//
	//if( m_profileCalculator.CheckInitSource(dpSrc) && m_profileCalculator.CalcProfileWidth(dWidth, vxAPoints, vyAPoints, m_dLineWidth) )
	//{
		//ASSERT(is_good_plot_for_profile(dpSrc));
		//if( pstrHint )
		//{
			//string strHint;
			//if( IDM_PLOT_CONTOUR==dpSrc.GetPlotType() || IDM_PLOT_MATRIX_IMAGE==dpSrc.GetPlotType() )
			//{
				//DataRange rng;
				//if( dpSrc.GetDataRange(rng) && rng.IsValid() )
				//{
					//int c1, c2;
					//MatrixLayer ml;
					//rng.GetRange(ml, c1, c2);
//
					//MatrixObject mo(ml, c1);
					//if(mo && ml.HasImage() )
						//strHint.Format(_L("Number of pixels: %d"), nint(dWidth));
				//}
			//}
			//*pstrHint = strHint;
		//}
		//return true;
	//}
//
	//return false;
//}
/////End RESTRICT_LINE_WIDTH_AND_GIVE_HINT_FOR_PROFILE_WIDTH
//
/////Kyle 06/11/2010 ORG-98-S33 BETTER_DEFAULT_WIDTH_FOR_H_AND_V_LINE_WIDTH
///*
//int		ImageProfilerPath::GetSuitableWidths(vector& vWidths)
//{
	//vWidths.SetSize(0);
//
	//double dMargin = -1;
	//for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	//{
		//ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		//if( info.m_glSource )
		//{
			//double dXMargin = fabs(info.m_glSource.X.From - info.m_glSource.X.To);
			//double dYMargin = fabs(info.m_glSource.Y.From - info.m_glSource.Y.To);
			//dMargin = dXMargin > dYMargin ? dXMargin : dYMargin;
			//break;
		//}
	//}
//
	//vWidths.Add(0);
	//if( dMargin > 0 )
	//{
		//vWidths.Add(dMargin/10);
		//vWidths.Add(dMargin/8);
		//vWidths.Add(dMargin/4);
		//vWidths.Add(dMargin/2);
	//}
	//
	//return vWidths.GetSize();
//}
//*/
/////End BETTER_DEFAULT_WIDTH_FOR_H_AND_V_LINE_WIDTH
/////End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
double ImageProfilerPath::GetProfileWidth(int nUnit)
{
	double dWidth;
	int nSrcUnit = GetProfileWidthUnit();
	switch( nSrcUnit )
	{
	case IPROFILE_PATH_WIDTH_PIXEL:
		dWidth = m_dWidthInPixel;
		break;

	case IPROFILE_PATH_WIDTH_SCALE:
		dWidth = m_dWidthInScale;
		break;

	default:
		return NANUM;
	}
	if( nSrcUnit==nUnit )
		return dWidth;
	return ConvertWidth(dWidth, nSrcUnit, nUnit);
}

bool ImageProfilerPath::SetProfileWidth(double dWidth, int nUnit)
{
	if( dWidth < 0 )
		return false;

	double dOldLineWidth = GetProfileWidth(IPROFILE_PATH_WIDTH_SCALE);

	bool bUnitChanged = nUnit!=GetProfileWidthUnit();
	double dLineWidth;
	switch( nUnit )
	{
	case IPROFILE_PATH_WIDTH_PIXEL:
		{
			if( !bUnitChanged && is_equal(m_dWidthInPixel, dWidth) )
				return true;
			m_dWidthInPixel = dWidth;
			dLineWidth = ConvertWidth(dWidth, IPROFILE_PATH_WIDTH_PIXEL, IPROFILE_PATH_WIDTH_SCALE);
		}
		break;

	case IPROFILE_PATH_WIDTH_SCALE:
		{
			if( !bUnitChanged && is_equal(m_dWidthInScale, dWidth) )
				return true;
			m_dWidthInScale = dWidth;
			dLineWidth = m_dWidthInScale;
		}
		break;

	default:
		ASSERT(0);
		return false;
	}
	m_dwCntrl = SET_WIDTH_UNIT(m_dwCntrl, nUnit);

	if( is_equal(dOldLineWidth, dLineWidth, '!') )
	{
		for(int ii = m_arrPathInfo.GetSize() - 1; ii >= 0; ii--)
		{
			ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
			SetPathWidth(info, dLineWidth);

			GraphObject goLine = info.GetLineObject();
			if( goLine )
				goLine.PostMessage(OE_MOVE);
		}
	}
	
	UpdateOutputWidth();		///Kyle 07/01/2010 ORG-355-S7 OUTPUT_PROFILE_WIDTH

	return true;
}

int ImageProfilerPath::GetProfileWidthUnit()
{
	return (m_dwCntrl & IPROFILE_PATH_WIDTH_UNITS);
}

///Kyle 06/17/2010 ORG-98-S40 NEW_WIDTH_CONTROL_WITHOUT_DROP_DOWN
/*
bool ImageProfilerPath::IsProfileWidthCustom()
{
	return (m_dwCntrl & IPROFILE_PATH_WIDTH_CUSTOM) ? true : false;
}

void ImageProfilerPath::SetProfileWidthCustom(bool bSet)
{
	if( bSet )
		m_dwCntrl |= IPROFILE_PATH_WIDTH_CUSTOM;
	else
		m_dwCntrl &= (~IPROFILE_PATH_WIDTH_CUSTOM);
}
*/
///End NEW_WIDTH_CONTROL_WITHOUT_DROP_DOWN

double	ImageProfilerPath::ConvertWidth(double dWidth, int nSrcUnit, int nDestUnit)
{
	ASSERT( m_arrPathInfo.GetSize() > 0);			// call this only when path is ready
	if( dWidth == NANUM || dWidth < 0 )
		return NANUM;
	if( nSrcUnit == nDestUnit )
		return dWidth;

	DataPlot dpSrc;
	ImageProfilePathInfo* pInfo = NULL;

	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
		/*
		if( info.m_glSource )
		{
			dpSrc = info.m_glSource.DataPlots();
			if( dpSrc )
			{
				pInfo = &info;
				break;
			}
		}
		*/
		/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
		/*
		if( info.m_dpSource )
		{
			dpSrc = info.m_dpSource;
			pInfo = &info;
			break;
		}
		*/
		if( info.GetSourcePlot(dpSrc) )
		{
			pInfo = &info;
			break;
		}
		///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
		///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	}
	if( !dpSrc || !pInfo )
		return NANUM;

	vector vxAPoints, vyAPoints;
	if( !GetPathPosition(*pInfo, vxAPoints, vyAPoints) )
		return NANUM;

	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//if( m_profileCalculator.CheckInitSource(dpSrc) )
	//	return m_profileCalculator.ConvertWidth(dWidth, nSrcUnit, nDestUnit, vxAPoints, vyAPoints);
	if( m_pCalculator->CheckInitSource(dpSrc) )
		return m_pCalculator->ConvertWidth(dWidth, nSrcUnit, nDestUnit, vxAPoints, vyAPoints);
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	return NANUM;
}
///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE

bool ImageProfilerPath::SetLinePosition(const vector& vx, const vector& vy, bool bVertical)
{
	if( !CheckLinePosition(vx, vy, bVertical) )
		return false;

	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		if( SetPathPosition(info, vx, vy) )
		{
			//RefreshProfilePath(true, false);		// no OE_MOVE event, refresh path here
			//return true;
			GraphObject goLine = info.GetLineObject();
			goLine.PostMessage(OE_MOVE);
		}
	}
	return false;
}

bool ImageProfilerPath::GetLinePosition(vector& vx, vector& vy, bool bVertical)
{
	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		if( GetPathPosition(info, vx, vy) )
			return true;
	}
	return false;
}

/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
void ImageProfilerPath::SetTextObjectLocation(int nLocation)
{
	m_nTextObjectLocation = nLocation;
}

int	ImageProfilerPath::GetTextObjectLocation()
{
	return m_nTextObjectLocation;
}
///End NEW_SUGGESTION_FOR_TEXT_OBJECT

bool ImageProfilerPath::SetPathColor(const ImageProfilePathInfo& info, int nColor)
{
	return _set_graph_object_color(info.GetLineObject(), nColor);
}

int ImageProfilerPath::GetPathColor(const ImageProfilePathInfo& info)
{
	return _get_graph_object_color(info.GetLineObject());
}

///Kyle 06/23/2010 ORG-355-P8 MOVE_SELECTED_OBJECT_IN_OC_WILL_LEAVE_THE_REVERSE_OBJECT
class CTempUnSelect
{
public:
	CTempUnSelect(GraphObject go)
	{
		ASSERT(go);
		m_go = go;

		Selection sel;
		m_bSelected = sel.Remove(m_go);
	}

	~CTempUnSelect()
	{
		if( m_bSelected )
		{
			Selection sel;
			sel.Add(m_go);
		}
	}

private:
	GraphObject		m_go;
	bool			m_bSelected;
};
///End MOVE_SELECTED_OBJECT_IN_OC_WILL_LEAVE_THE_REVERSE_OBJECT

bool	ImageProfilerPath::SetPathPosition(const ImageProfilePathInfo& info, const vector& vx, const vector& vy)
{
	GraphObject goLine = info.GetLineObject();
	if( !goLine )
		return false;

	CheckPathPosition(info, vx, vy);		///Kyle 07/21/2010 ORG-584-P4 PREVENT_MOVE_LINE_OUT_OF_LAYER

	///Kyle 06/23/2010 ORG-355-P8 MOVE_SELECTED_OBJECT_IN_OC_WILL_LEAVE_THE_REVERSE_OBJECT
	// if the object is selected(in reverse video), the old object won't be erased after moving until it's unselected
	///Kyle 07/21/2010 ORG-584-P4 CHECK_RESET_LINE_WIDTH_FOR_LOG_SCALE
	// no need to do this now because the line is set no select effect, and this will crash origin
	//CTempUnSelect unsel(goLine);
	///End CHECK_RESET_LINE_WIDTH_FOR_LOG_SCALE
	///End MOVE_SELECTED_OBJECT_IN_OC_WILL_LEAVE_THE_REVERSE_OBJECT

	Tree trFmt;
	trFmt.Root.Data.X.dVals = vx;
	trFmt.Root.Data.Y.dVals = vy;
	return (0 == goLine.UpdateThemeIDs(trFmt.Root) && goLine.ApplyFormat(trFmt, true, true) );
}

bool	ImageProfilerPath::GetPathPosition(const ImageProfilePathInfo& info, vector& vx, vector& vy)
{
	GraphObject goLine = info.GetLineObject();
	if( goLine )
	{
		Tree trFmt;
		trFmt = goLine.GetFormat(FPB_DATA, FOB_ALL, true, true);
		TreeNode trData = trFmt.Root.Data;
		if( trData && trData.X && trData.Y )
		{
			vx = trData.X.dVals;
			vy = trData.Y.dVals;
			return true;
		}
	}

	return false;
}

///Kyle 07/21/2010 ORG-584-P4 PREVENT_MOVE_LINE_OUT_OF_LAYER
bool ImageProfilerPath::CheckPathPosition(const ImageProfilePathInfo& info, vector& vx, vector& vy, bool* pbModified)
{
	if( !info.m_glSource )
		return false;

	double dXScaleFrom	= info.m_glSource.X.From;
	double dXScaleTo	= info.m_glSource.X.To;
	double dYScaleFrom	= info.m_glSource.Y.From;
	double dYScaleTo	= info.m_glSource.Y.To;

	bool bModified = _check_min_max(vx, dXScaleFrom, dXScaleTo) || _check_min_max(vy, dYScaleFrom, dYScaleTo);
	if( pbModified )
		*pbModified = bModified;

	return true;
}
///End PREVENT_MOVE_LINE_OUT_OF_LAYER

bool ImageProfilerPath::SetPathWidth(const ImageProfilePathInfo& info, double dLineWidth)
{
	return set_go_width(info.GetLineObject(), dLineWidth);
}

double ImageProfilerPath::GetPathWidth(const ImageProfilePathInfo& info)
{
	return _get_go_width(info.GetLineObject());
}

//double ImageProfilerPath::GetLineWidth(const ImageProfilePathInfo& info)
//{
	////temp
	//return m_dProfileWidth;
//}

string	ImageProfilerPath::GetPathName()
{
	return m_strPathName;
}

bool	ImageProfilerPath::SetPathName(LPCSTR lpcszName)
{
	string strName(lpcszName);

	strName.TrimLeft();
	strName.TrimRight();
	if( strName.IsEmpty() )
		return false;

	m_strPathName = strName;
	SetOutputDepColComments(strName);
	return true;
}

bool	ImageProfilerPath::OnDeleteSrcLayer()
{
	for( int ii = m_arrPathInfo.GetSize()-1; ii >= 0; ii--)
	{
		RemovePathInfoAt(ii, !IsKeepOutput(), false);
	}

	return true;
}

int ImageProfilerPath::OnDeleteProfileLine(UINT uObjUID)
{
	vector<int> vnIndices;
	for( int ii = m_arrPathInfo.GetSize()-1; ii >= 0; ii--)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		if( info.m_uObjUID == uObjUID )
			vnIndices.Add(ii);
	}
	ASSERT(vnIndices.GetSize() > 0);
	AddRelatedPathInfo(vnIndices);

	int nCount = 0;
	if( vnIndices.GetSize() > 0 )
	{
		for(int ii = vnIndices.GetSize()-1; ii>=0; ii--)
		{
			bool bRemoveLine = true;
			{
				ImageProfilePathInfo& info = m_arrPathInfo.GetAt(vnIndices[ii]);
				bRemoveLine = info.m_uObjUID != uObjUID;
			}
			RemovePathInfoAt(vnIndices[ii], !IsKeepOutput(), bRemoveLine);
			nCount++;
		}
	}

	return nCount;
}

bool ImageProfilerPath::RemovePathInfoAt(int nIndex, bool bRemoveOutput, bool bRemoveLine)	// = true, true
{
	if( nIndex < 0 || nIndex >= m_arrPathInfo.GetSize() )
		return false;

	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);

		GraphObject goLine = info.GetLineObject();
		if( goLine )
		{
			if( bRemoveLine)
			{
				goLine.Destroy();
			}
			else
			{
				ASSERT(!bRemoveOutput);
				update_go_states(goLine, GOC_NO_SELECT | GOC_NO_MOVE | GOC_NO_RESIZE | GOC_NO_ROTATE | GOC_NO_SKEW | GOC_NO_EDIT | GOC_NO_BORDERSIZE );
			}
		}

		// no need to clear related dataset here, not sure if it's the last profile
		//if( info.m_glSource )
		//{
			//DataPlot dp = info.m_glSource.DataPlots();
			//if( dp )
				//_clear_related_dataset(dp);
		//}

		if( bRemoveOutput )
		{
			if( info.m_glOutput )
			{
				XYRange xyOutput;
				if( GetPreviewRange(info, xyOutput) )
				{
					vector<int> vnPlotIndices;
					if( check_has_plotted_in_graph(xyOutput, info.m_glOutput, vnPlotIndices) > 0 )
					{
						info.m_glOutput.RemovePlot(vnPlotIndices[0]);
						legend_update(info.m_glOutput);				///Kyle 06/23/2010 ORG-355-P9 UPDATE_LEGEND_AFTER_DELETE_PATH
					}
				}
			}

			if( info.m_drOutput )
			{
				Worksheet wks;
				int c1, c2;
				if( info.m_drOutput.GetRange(wks, c1, c2) && wks )
				{
					ASSERT(c1 == c2);
					wks.Destroy();
				}
			}
		}

		if( IsRemoveGraphIfEmpty() && info.m_glOutput )
		{
			if( info.m_glOutput.DataPlots.Count() == 0 )
				info.m_glOutput.Destroy();
		}
	}
	m_arrPathInfo.RemoveAt(nIndex);

	return true;
}

void	ImageProfilerPath::ActiveOutputPlots()
{
	UINT nActivePageUID = 0;
	GraphPage gpActive = Project.Pages();
	if( gpActive )
		nActivePageUID = gpActive.GetUID(TRUE);

	for(int ii = m_arrPathInfo.GetSize()-1; ii >= 0; ii--)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		if( info.m_glOutput && info.m_glOutput.GetPage().GetUID(TRUE) != nActivePageUID )
		{
			set_active_layer(info.m_glOutput);
			nActivePageUID = info.m_glOutput.GetPage().GetUID();
		}
	}
}

int		ImageProfilerPath::GetProfileLineColor()
{
	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		//GraphObject goLine = info.GetLineObject();
		//if( goLine )
		//{
			//int nColor = _get_graph_object_color(goLine);
			//if( nColor >= 0 )
				//return nColor;
		//}
		int nColor = GetPathColor(info);
		if( nColor >= 0 )
			return nColor;
	}
	return -1;
}

bool	ImageProfilerPath::ClonePath(ImageProfilerPath* pSrcPath)
{
	if( !pSrcPath || pSrcPath->IsPathEmpty() || GetPathType()!=pSrcPath->GetPathType() )
		return false;
	
	ClearProfile();
	ASSERT(m_arrPathInfo.GetSize()==0);

	///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	/*
	///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	//m_dProfileWidth = pSrcPath->GetProfileWidth();
	m_dLineWidth = pSrcPath->GetLineWidth();
	///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	*/
	m_dWidthInScale = pSrcPath->m_dWidthInScale;
	m_dWidthInPixel = pSrcPath->m_dWidthInPixel;
	m_dwCntrl = pSrcPath->m_dwCntrl;
	///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	m_strPathName = pSrcPath->GetPathName();
	m_bKeepOutput = pSrcPath->IsKeepOutput();
	m_bRemoveGraphIfEmpty = pSrcPath->m_bRemoveGraphIfEmpty;			///Kyle 06/22/2010 ORG-355-P6 REMOVE_OUTPUT_GRAPH_IF_EMPTY_ON_SEP_MODE

	vector<uint> vUID;
	for(int ii = 0; ii < pSrcPath->m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& srcInfo = pSrcPath->m_arrPathInfo.GetAt(ii);
		
		ImageProfilePathInfo* pInfo = new ImageProfilePathInfo;
		if(!pInfo)
			return false;
		pInfo->m_glSource = srcInfo.m_glSource;
		/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
		//pInfo->m_dpSource = srcInfo.m_dpSource;				///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
		pInfo->m_uSourcePlot = srcInfo.m_uSourcePlot;
		///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
		pInfo->m_nLineType = srcInfo.m_nLineType;
		pInfo->m_nNumPoints = srcInfo.m_nNumPoints;

		vector<uint> vecIndices;
		if( vUID.Find(vecIndices, srcInfo.m_uObjUID) > 0 )
		{
			ImageProfilePathInfo& preInfo = pSrcPath->m_arrPathInfo.GetAt(vecIndices[0]);
			pInfo->m_uObjUID = preInfo.m_uObjUID;
		}
		else
		{
			GraphObject goSrcLine = srcInfo.GetLineObject();
			if( goSrcLine )
			{
				int nType;
				goSrcLine.GetObjectType(&nType);
				string strName = goSrcLine.GetName();

				GraphObject go;
				go = pInfo->m_glSource.CreateGraphObject(nType, strName);

				Tree trFmt;
				trFmt = goSrcLine.GetFormat(FPB_ALL | FPB_DATA, FOB_ALL, true, true);
				go.ApplyFormat(trFmt, true, true);

				pInfo->m_uObjUID = go.GetUID(true);
			}
			else
			{
				ASSERT(0);
				pInfo->m_uObjUID = 0;		// for save
			}
		}

		m_arrPathInfo.Add(*pInfo);

		vUID.Add(srcInfo.m_uObjUID);
	}
	return true;
}

///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
TreeNode	ImageProfilerPath::backupOneGraphObject(GraphObject& go, TreeNode& tr)
{
	TreeNode trSub;
	if( go )
	{			
		trSub = tr.AddNode(go.GetName());
		trSub.SetAttribute(STR_DATAID_ATTRIB, go.GetUID(true)); // used to check graph object in AddBackProfileLines
		
		int nType;
		go.GetObjectType(&nType);
		trSub.AddNumericNode(nType, "Type");
		
		Tree trFormat;
		trFormat = go.GetFormat(0xFFFFFFFF, FOB_ALL, TRUE, TRUE);
		TreeNode trN = trSub.AddNode("Format");
		trN.AddNode(trFormat.Root);
	}	
	return trSub;
}

bool 	ImageProfilerPath::addBackGraphObject(GraphLayer gl, GraphObject& go, TreeNode& trSub)
{
	string strName = trSub.tagName;
	int nType = trSub.Type.nVal;
	TreeNode trFormat = trSub.Format;
	
	go = gl.CreateGraphObject(nType, strName);
	
	if( go )
		return go.ApplyFormat(trFormat, true, true);		
	return false;
}

bool	ImageProfilerPath::BackupProfileLineFormatSettings(TreeNode& tr)
{
	for(int index = 0; index < m_arrPathInfo.GetSize(); index++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(index);
		
		GraphObject goLine;
		goLine = Project.GetObject(info.m_uObjUID);
		ASSERT(goLine);	
		TreeNode trSub = backupOneGraphObject(goLine, tr);	

		return true;
	}	
	return false;
}

//virtual 
bool 	ImageProfilerPath::AddBackProfileLines(TreeNode& tr)
{
	for(int index = 0; index < m_arrPathInfo.GetSize(); index++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(index);
		
		TreeNode trSub = tree_get_node_by_dataid(tr, info.m_uObjUID, true);
		ASSERT(trSub);
		
		if( trSub )
		{
			GraphObject goLine;
			if( addBackGraphObject(info.m_glSource, goLine, trSub) )
				info.m_uObjUID = goLine.GetUID(true);				
		}	
		
		TreeNode trColor = trSub.Format.Root.Border.Color;
		ASSERT(trColor);
		int nColor = trColor ? trColor.nVal : 1;
		setProfileCurveColor(info, nColor);
		return true;
	}
	return false;
}

void	ImageProfilerPath::setProfileCurveColor(ImageProfilePathInfo& info, int nColor)
{
	XYRange xyOutput;
	vector<int> vnPlotIndices;
	if( GetPreviewRange(info, xyOutput) && check_has_plotted_in_graph(xyOutput, info.m_glOutput, vnPlotIndices) > 0 )
	{
		DataPlot dp = info.m_glOutput.DataPlots(vnPlotIndices[0]);
		if( dp )
			dp.SetColor(nColor, true);
	}	
}
///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS

bool	ImageProfilerPath::SetProfileLineColor(int nColor, bool bUpdateCurve)
{
	for(int ii = m_arrPathInfo.GetSize()-1; ii >= 0; ii--)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		if( SetPathColor(info, nColor) && bUpdateCurve )
		{
			///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
			/*
			XYRange xyOutput;
			vector<int> vnPlotIndices;
			if( GetPreviewRange(info, xyOutput) && check_has_plotted_in_graph(xyOutput, info.m_glOutput, vnPlotIndices) > 0 )
			{
				DataPlot dp = info.m_glOutput.DataPlots(vnPlotIndices[0]);
				if( dp )
					dp.SetColor(nColor, true);
			}
			*/
			setProfileCurveColor(info, nColor);
			///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
		}
	}
	return true;
}

void	ImageProfilerPath::DestroyOutputGraph()
{
	for(int ii = m_arrPathInfo.GetSize()-1; ii >= 0; ii--)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		if( info.m_glOutput )
			info.m_glOutput.Destroy();
	}
}

bool ImageProfilerPath::DoProfile(int nIndex)
{
	if( nIndex < 0 || nIndex >= m_arrPathInfo.GetSize() )
		return false;

	ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);
	if( !info.m_drOutput.IsValid() )
		return false;

	if( !BeforeDoProfile(info) )
		return false;

	return CalculateProfileData(info);

	/*
	if( info.m_xyOutput.SetData(&vy, &vx,  0, NULL, DRS_SET_COL_DESIGNATIONS) )
	{
		Column colY;
		if( info.m_xyOutput.GetYColumn(colY) && colY)
			colY.SetComments(strComments);

		return true;
	}

	return false;
	*/
}

void ImageProfilerPath::RefreshProfilePath(bool bDoProfile, bool bRescale)
{
	if( !(bDoProfile || bRescale) )
		return;

	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		if( bDoProfile )
			DoProfile(ii);

		if( bRescale )
		{
			ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
			if( info.m_glOutput )
				info.m_glOutput.Rescale(OKAXISTYPE_X);			// x axis should be the same as source layer
		}
	}
}

bool ImageProfilerPath::BeforeDoProfile(ImageProfilePathInfo& info)
{
	///Kyle 07/21/2010 ORG-584-P4 PREVENT_MOVE_LINE_OUT_OF_LAYER
	/*
	if( !info.m_glSource )
		return false;

	vector vx, vy;
	if( !GetPathPosition(info, vx, vy) )
		return false;

	double dXScaleFrom	= info.m_glSource.X.From;
	double dXScaleTo	= info.m_glSource.X.To;
	double dYScaleFrom	= info.m_glSource.Y.From;
	double dYScaleTo	= info.m_glSource.Y.To;

	if( _check_min_max(vx, dXScaleFrom, dXScaleTo) || _check_min_max(vy, dYScaleFrom, dYScaleTo) )
	{
		SetPathPosition(info, vx, vy);
	}

	return true;
	*/
	vector vx, vy;
	if( !ImageProfilerPath::GetPathPosition(info, vx, vy) )
		return false;
	bool bModified;
	bool bRet = CheckPathPosition(info, vx, vy, &bModified);
	if( bRet && bModified )
	{
		ImageProfilerPath::SetPathPosition(info, vx, vy);
	}

	return bRet;
	///End PREVENT_MOVE_LINE_OUT_OF_LAYER
}

int ImageProfilerPath::OnProfileEvent(int nEvent, UINT uObjUID)
{
	int nIndex = GetPathInfoIndex(uObjUID);
	if( nIndex < 0 || nIndex >= m_arrPathInfo.GetSize() )
		///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING
		//return -1;
		return IPUPDATE_NO_CHANGE;
		///End CENTRALIZE_EVENT_HANDLING
	ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);
	
	if( nEvent == OE_STYLE_CHANGE )
	{
		int nColor = GetPathColor(info);
		if( nColor >= 0 )
			SetProfileLineColor(nColor, true);

		///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE, no need to do this
		/*
		///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
		//double dWidth = GetPathWidth(info);
		//if( dWidth != NANUM && !is_equal(dWidth, GetLineWidth(info)) )
			//SetProfileWidth(dWidth);				// temp
		double dWidth = GetPathWidth(info);
		if( dWidth != NANUM && !is_equal(dWidth, m_dLineWidth) )
			SetLineWidth(dWidth);				// temp
		///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
		*/
		///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE

		///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING
		//return nIndex;
		///Kyle 06/17/2010 ORG-98 ADD_DIRTY_BITS_FOR_GUI_UPDATE
		//return IPUPDATE_PATH_CONTENT;
		return IPUPDATE_PATH_CONTENT_COLOR;
		///End ADD_DIRTY_BITS_FOR_GUI_UPDATE
		///End CENTRALIZE_EVENT_HANDLING
	}
	///Kyle 06/22/2010 ORG-355 CENTRALIZE_CODE_AND_CHANGE_CLASS_STRUCTURE, no need to copy source axis format for polyline profile
	/*
	///Kyle 06/07/2010 OGR-98 DELAY_EXECUTE_ON_RESCALE
	else if( OE_SCALE_CHANGE == nEvent )		// special handle, need delay execute
	{
		GraphObject go;
		go = (GraphObject)Project.GetObject(uObjUID);
		if( !go )
		{
			ASSERT(0);
			///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING
			//return -1;
			return IPUPDATE_NO_CHANGE;
			///End CENTRALIZE_EVENT_HANDLING
		}
		
		/// Iris 6/07/2010 ORG-98-S24 SCALUE_SOURCE_GRAPH_NEED_RESCALE_PROFILE_LAYER_IN_SEP_MODE
		// after source layer scale changed, need to copy scale settings to profile layers
		// SC, SV, and SH mode no need do this, since dest layer has linked to source layer.
		int nParentLayer;
		if( layer_get_link(info.m_glOutput, nParentLayer) && nParentLayer < 0 ) // nParentLayer<0 means no link
		{
			bool bVertical = info.m_nLineType == CROSSED_LINE_VERTICAL;
			if( bVertical )
			{
				_copy_axis_tick_label_scale(info.m_glSource.YAxis, info.m_glOutput.XAxis);
			}
			else
			{
				_copy_axis_tick_label_scale(info.m_glSource.XAxis, info.m_glOutput.XAxis);
			}
		}
		///End SCALUE_SOURCE_GRAPH_NEED_RESCALE_PROFILE_LAYER_IN_SEP_MODE

		// need to delay handling the event since the position of the object maybe not updated
		//go.PostMessage(OE_MOVE);
		info.m_glSource.Invalidate(true);
		go.Invalidate(true);
	}
	///End DELAY_EXECUTE_ON_RESCALE
	*/
	else if( OE_SCALE_CHANGE == nEvent )		// special handle, need delay execute
	{
		GraphObject go;
		go = (GraphObject)Project.GetObject(uObjUID);
		if( !go )
		{
			ASSERT(0);
			return IPUPDATE_NO_CHANGE;
		}
		
		// need to delay handling the event since the position of the object maybe not updated
		info.m_glSource.Invalidate(true);
		go.Invalidate(true);
	}
	///End CENTRALIZE_CODE_AND_CHANGE_CLASS_STRUCTURE
	
	if( DoProfile(nIndex) )
		///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING
		//return nIndex;
		///Kyle 06/17/2010 ORG-98 ADD_DIRTY_BITS_FOR_GUI_UPDATE
		//return IPUPDATE_PATH_CONTENT;
		return IPUPDATE_PATH_CONTENT_POSITION;
		///End ADD_DIRTY_BITS_FOR_GUI_UPDATE
		///End CENTRALIZE_EVENT_HANDLING

	///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING
	//return -1;
	return IPUPDATE_NO_CHANGE;
	///End CENTRALIZE_EVENT_HANDLING
}

int ImageProfilerPath::GetPathInfoIndex(UINT uObjUID)
{
	int nCount = m_arrPathInfo.GetSize();
	for(int ii = 0; ii < nCount; ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		if( uObjUID==info.m_uObjUID )
			return ii;
	}

	return -1;
}

bool ImageProfilerPath::SavePathToTree(TreeNode& trPath)
{
	if( !trPath )
		return false;
	ASSERT( m_arrPathInfo.GetSize() > 0);

	trPath.ProfileType.nVal = GetPathType();
	///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	/*
	///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	//trPath.ProfileWidth.dVal = m_dProfileWidth;
	trPath.LineWidth.dVal = m_dLineWidth;
	///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	*/
	trPath.WidthInScale.dVal = m_dWidthInScale;
	trPath.WidthInPixel.dVal = m_dWidthInPixel;
	trPath.PathControl.dVal = m_dwCntrl;
	///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	trPath.ProfileName.strVal = m_strPathName;
	trPath.TextLocation.nVal = m_nTextObjectLocation; /// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT

	TreeNode trPathInfos = trPath.AddNode("Infos");
	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);

		TreeNode trInfo = trPathInfos.AddNode("Info" + (string)ii);
		info.SaveToTree(trInfo);
	}

	return true;
}

///Kyle 07/20/2010 ORG-584-P2 NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
//bool ImageProfilerPath::InitPathFromTree(const TreeNode& trPath)
bool ImageProfilerPath::InitPathFromTree(const TreeNode& trPath, const GraphLayer& glSource)
///End NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
{
	///Kyle 07/20/2010 ORG-584-P2 NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
	if( !glSource )
		return false;
	///End NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE

	if( !trPath )
		return false;

	if( !(trPath.ProfileType && GetPathType()==trPath.ProfileType.nVal) )
		return false;

	///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	/*
	///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	//m_dProfileWidth = trPath.ProfileWidth ? trPath.ProfileWidth.dVal : 1.0;
	m_dLineWidth = trPath.LineWidth ? trPath.LineWidth.dVal : 0;
	///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	*/
	m_dWidthInScale = trPath.WidthInScale.dVal;
	m_dWidthInPixel = trPath.WidthInPixel.dVal;
	m_dwCntrl = trPath.PathControl.dVal;
	///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	m_strPathName = trPath.ProfileName ? trPath.ProfileName.strVal : "";
	m_nTextObjectLocation = trPath.TextLocation.nVal; /// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT

	TreeNode trPathInfos = trPath.Infos;
	if( !trPathInfos )
		return false;

	foreach(TreeNode trInfo in trPathInfos.Children)
	{
		ImageProfilePathInfo* pInfo = new ImageProfilePathInfo;
		if( !pInfo )
			return false;

		///Kyle 07/20/2010 ORG-584-P2 NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
		//if( !pInfo->InitFromTree(trInfo) )
		if( !pInfo->InitFromTree(trInfo, glSource) )
		///End NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
		{
			delete pInfo;
			return false;
		}
		m_arrPathInfo.Add(*pInfo);
	}
	
	///Kyle 06/09/2010 ORG-98 ADD_RANGE_TO_PROJECT_TO_MAKE_IT_UPDATED_CORRECTLY
	// if NOT add data range object to project, when delete one column will effect on the data range
	// because data range remembered is column index.
	// see ORG-98-P10
	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		if( info.m_drOutput )
			Project.AddDataRange(info.m_drOutput);
	}
	///End ADD_RANGE_TO_PROJECT_TO_MAKE_IT_UPDATED_CORRECTLY

	return true;
}

bool	ImageProfilerPath::FindOutputWks(Worksheet& wksOutput, WorksheetPage& wpOutput, const ImageProfilePathInfo& info)
{
	string strWksName = GetPathName() + "Profile";

	if(wpOutput)
	{
		int nLayer = wpOutput.AddLayer(strWksName, 0, "origin");
		wksOutput = wpOutput.Layers(nLayer);
	}
	else
	{
		wksOutput.Create("origin", CREATE_HIDDEN | CREATE_LOAD_1ST_LAYER_ONLY);
		if( wksOutput )
		{
			wksOutput.SetName(strWksName);
			wksOutput.GetPage().SetName(STR_PROFILE_BOOK, OCD_ENUM_NEXT);
		}
	}

	return wksOutput.IsValid();
}

bool	ImageProfilerPath::CheckPlotOutput(ImageProfilePathInfo& info)
{
	if( !(info.m_drOutput && info.m_glOutput) )
		return false;
	
	XYRange xyOutput;
	if( !GetPreviewRange(info, xyOutput) )
		return false;

	vector<int> vnPlotIndices;
	if( 0 >= check_has_plotted_in_graph(xyOutput, info.m_glOutput, vnPlotIndices) )
	{
		int nPlot = info.m_glOutput.AddPlot(xyOutput, IDM_PLOT_LINE);
		DataPlot dp = info.m_glOutput.DataPlots(nPlot);
		if( dp )
		{
			//GraphObject goLine = info.GetLineObject();
			//int nColor = _get_graph_object_color(goLine);
			int nColor = GetPathColor(info);
			if( nColor >= 0 )
				dp.SetColor(nColor);
			legend_update(info.m_glOutput);
		}
		
		///Sophy 5/31/2010 ORG-98-S28 SET_SOURCE_Z_SCALE_TO_RESULT_Y_SCALE
		{
			/// Hong 06/11/10 ORG-98 IMPROVE_SPEED
			/*
			DataPlot dpSrc = info.m_glSource.DataPlots();
			XYZRange drSrc;
			dpSrc.GetDataRange(drSrc);
			vector vX, vY, vZ;
			if ( !drSrc.GetData(vZ, vY, vX) )
				drSrc.GetData(&vZ, 0); //virtual matrix.
			double dMin, dMax;
			vZ.GetMinMax(dMin, dMax);
			*/
			///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			//m_profileCalculator.CheckInitSource(info.m_glSource.DataPlots());
			//double 		dMin, dMax;
			//m_profileCalculator.GetZMinMax(dMin, dMax);
			double dMin, dMax;
			///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
			//if( !(m_pCalculator->CheckInitSource(info.m_glSource.DataPlots()) && m_pCalculator->GetZMinMax(dMin, dMax)) )
			/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
			//if( !(m_pCalculator->CheckInitSource(info.m_dpSource) && m_pCalculator->GetZMinMax(dMin, dMax)) )
			DataPlot dpSource;
			if( info.GetSourcePlot(dpSource) && !(m_pCalculator->CheckInitSource(dpSource) && m_pCalculator->GetZMinMax(dMin, dMax)) )
			///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
			///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
				return true;
			///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			/// end IMPROVE_SPEED
			Tree trFormat;
			trFormat = info.m_glOutput.GetFormat(FPB_ALL, FOB_SCALE, true, true);
			trFormat.Root.Axes.Y.Scale.From.dVal = dMin;
			trFormat.Root.Axes.Y.Scale.To.dVal = dMax;
			trFormat.Root.Axes.Y.Scale.Rescale.nVal = 0; //manually
			info.m_glOutput.ApplyFormat(trFormat, true, true);
		}
		///end SET_SOURCE_Z_SCALE_TO_RESULT_Y_SCALE
	}

	return true;
}


void	ImageProfilerPath::SetOutputWksParametersLabel(Column& col, const vector& vxOutput, const vector& vyOutput, bool bVertical)
{
	ASSERT(col);
	if( !col )
		return;
	
	Worksheet wks;
	col.GetParent(wks);
	
	//Grid gg;
	//gg.Attach(wks);    
	//gg.ShowLabels(RCLT_UDL);
	
	ASSERT(vxOutput.GetSize()>0 && vyOutput.GetSize() > 0);
	double dVal = bVertical? vxOutput[0] : vyOutput[0];
	///Kyle 07/01/2010 ORG-355-S7 OUTPUT_PROFILE_WIDTH
	//col.SetExtendedLabel(ftoa(dVal, "*"), RCLT_UDL);
	col.SetExtendedLabel(ftoa(dVal, "*"), LABEL_LINE_POSITION);
	///End OUTPUT_PROFILE_WIDTH
	
	//vector<string> vsUDLs(1);
	//vsUDLs[0] = bVertical? STR_OUT_WKS_UDL_VLINE : STR_OUT_WKS_UDL_HLINE;
	//gg.SetUserDefinedLabelNames(vsUDLs);

}

bool 	ImageProfilerPath::SetOutputColComments(ImageProfilePathInfo& info, LPCSTR lpcszCol, LPCSTR lpcszComments)
{
	int r1, c1, r2, c2;
	Worksheet wks;
	if( info.m_drOutput.GetRange(lpcszCol, r1, c1, r2, c2, wks) >= 0 && wks.IsValid() )
	{
		Column col(wks, c1);
		ASSERT(col);
		return col.SetComments(lpcszComments);		
	}	
	return false;
}

///Kyle 07/01/2010 ORG-355-S7 OUTPUT_PROFILE_WIDTH
void	ImageProfilerPath::PrepareUserDefinedLabels(Worksheet& wks, const vector<uint>& vnLabels, const vector<string>& vsLabels)
{
	if( wks.IsValid() && vnLabels.GetSize() > 0 && vnLabels.GetSize() == vsLabels.GetSize() )
	{
		Grid gg;
		gg.Attach(wks);
		for( int ii = 0; ii < vnLabels.GetSize(); ii++)
		{
			ASSERT( vnLabels[ii] >= RCLT_UDL && vnLabels[ii] < RCLT_UDL + UDL_MAX_NUM );
			gg.ShowLabels(vnLabels[ii]);
		}

		gg.SetUserDefinedLabelNames(vsLabels);
	}
}

void	ImageProfilerPath::SetOutputWidth(Column& col)
{
	if( !col.IsValid() )
		return;

	string strLabel;
	switch( GetProfileWidthUnit() )
	{
	case IPROFILE_PATH_WIDTH_PIXEL:
		strLabel = _L("Pixel") + " = " + ftoa(m_dWidthInPixel, "*");
		break;
		
	case IPROFILE_PATH_WIDTH_SCALE:
		strLabel = _L("Scale") + " = " + ftoa(m_dWidthInScale, "*");
		break;
	}
	col.SetExtendedLabel(strLabel, LABEL_PROFILE_WIDTH);
}
///End OUTPUT_PROFILE_WIDTH

/*----------------------------------------------------------------------------*/
/* ImageProfilerPolyLinePath
/*----------------------------------------------------------------------------*/

int ImageProfilerPolyLinePath::AddProfileLine(GraphLayer& glSource, int nColor, DWORD dwOption, const vector& vx, const vector& vy)
{
	///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	if( !glSource )
		return -1;
	DataPlot dpSource = glSource.DataPlots();
	if( !is_good_plot_for_profile(dpSource) )
		return false;
	///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	ImageProfilePathInfo* pInfo = new ImageProfilePathInfo;
	if(!pInfo)
		return -1;

	ImageProfilePolyLine profileline;
	///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE, line width means nothing here
	//if( !profileline.Create(glSource, GetLineWidth(), nColor, vx, vy) )
	if( !profileline.Create(glSource, 1, nColor, vx, vy) )
	///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	{
		delete pInfo;
		return -1;
	}
	
	pInfo->m_uObjUID = profileline.GetUID(true);
	pInfo->m_nLineType = LTYPE_POLYLINE;		///Kyle 06/22/2010 ORG-355 CENTRALIZE_CODE_AND_CHANGE_CLASS_STRUCTURE
	pInfo->m_glSource = glSource;
	/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	//pInfo->m_dpSource = dpSource;		///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	pInfo->m_uSourcePlot = dpSource.GetUID(true);
	///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID

	return m_arrPathInfo.Add(*pInfo);
}

bool ImageProfilerPolyLinePath::AddAnchorPoints(const vector& vx, const vector& vy)
{
	vector vxPoints, vyPoints;
	if( GetLinePosition(vxPoints, vyPoints) )
	{
		vxPoints.Append(vx);
		vyPoints.Append(vy);
		return SetLinePosition(vxPoints, vyPoints);
	}

	return false;
}

bool ImageProfilerPolyLinePath::CheckSetProfileLayer(WorksheetPage& wpOutput, GraphLayer& glVertical, GraphLayer& glHorizontal)
{
	if( m_arrPathInfo.GetSize() < 1)
		return false;
	ASSERT( m_arrPathInfo.GetSize() == 1 );

	ImageProfilePathInfo& info = m_arrPathInfo.GetAt(0);

	if( !info.m_drOutput.IsValid() )
	{
		Worksheet wksTemp;
		if( !FindOutputWks(wksTemp, wpOutput, info) )
			return false;

		int nCols = 4;
		if(wksTemp.GetNumCols() < nCols)
			wksTemp.SetSize(-1, nCols);
		wksTemp.SetColDesignations("XXYZ");
		wksTemp.Columns(0).SetLongName("Distance");

		///Kyle 07/01/2010 ORG-355-S7 OUTPUT_PROFILE_WIDTH
		vector<uint> vnLabels = {LABEL_PROFILE_WIDTH};
		vector<string> vsLabels(1);
		vsLabels[0] = _L("Width");
		PrepareUserDefinedLabels(wksTemp, vnLabels, vsLabels);
		///End OUTPUT_PROFILE_WIDTH

		DataRange drResult;
		drResult.Add(wksTemp, 0, "D");		// Distance
		drResult.Add(wksTemp, 1, "X");
		drResult.Add(wksTemp, 2, "Y");
		drResult.Add(wksTemp, 3, "Z");
		info.m_drOutput = drResult;
		/// Iris 6/07/2010 ORG-98-P10 FIX_RENAME_TAB_UPDATED_INCORRECT_OUTPUT_COL_COMMENTS
		// if NOT add data range object to project, when delete one column will effect on data range
		// because data range remembered is column index.
		Project.AddDataRange(info.m_drOutput); 
		///End FIX_RENAME_TAB_UPDATED_INCORRECT_OUTPUT_COL_COMMENTS
		
		UpdateOutputWidth();		///Kyle 07/01/2010 ORG-355-S7 OUTPUT_PROFILE_WIDTH
	}


	if( !info.m_glOutput )
	{
		ASSERT( glVertical );
		info.m_glOutput = glVertical;
	}

	CheckPlotOutput(info);

	return true;

}

bool ImageProfilerPolyLinePath::CheckLinePosition(const vector& vx, const vector& vy, bool bVertical)
{
	return (vx && vy && vx.GetSize()>=2 && vy.GetSize()==vx.GetSize());
}

bool ImageProfilerPolyLinePath::GetPreviewRange(const ImageProfilePathInfo& info, XYRange& xyRange)
{
	if( !info.m_drOutput )
		return false;
	
	int r1, c1, r2, c2;
	Worksheet wks;
	if( info.m_drOutput.GetRange("Z", r1, c1, r2, c2, wks) >= 0 && wks.IsValid() )
	{
		xyRange.Add(wks, 0, "X");
		xyRange.Add(wks, 3, "Y");
	}

	return xyRange.IsValid();
}

bool ImageProfilerPolyLinePath::CalculateProfileData(const ImageProfilePathInfo& info)
{
	///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	//DataPlot dp = info.m_glSource.DataPlots();
	/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	//DataPlot dp = info.m_dpSource;
	DataPlot dp;
	if( !info.GetSourcePlot(dp) )
		return error_report("Fail to get source data plot");
	//End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	//if( !dp )
		//return false;

	vector vxVertices, vyVertices;
	if( !GetPathPosition(info, vxVertices, vyVertices) )
		return false;

	vector vxOutput, vyOutput, vzOutput;
	//ImageProfileCalculator helper;
	//if( helper.CheckInitSource(dp) && helper.DoLineProfile(vxOutput, vyOutput, vzOutput, GetNumPoints(), vxVertices, vyVertices, m_dProfileWidth) )
	///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	//if( m_profileCalculator.CheckInitSource(dp) && m_profileCalculator.DoLineProfile(vxOutput, vyOutput, vzOutput, GetNumPoints(), vxVertices, vyVertices, m_dProfileWidth) )
	///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	//if( m_profileCalculator.CheckInitSource(dp) && m_profileCalculator.DoLineProfile(vxOutput, vyOutput, vzOutput, GetNumPoints(), vxVertices, vyVertices, m_dLineWidth) )
	int nWidthUnit = GetProfileWidthUnit();
	double dWidth = GetProfileWidth(nWidthUnit);
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//if( m_profileCalculator.CheckInitSource(dp) && m_profileCalculator.DoLineProfile(vxOutput, vyOutput, vzOutput, GetNumPoints(), vxVertices, vyVertices, dWidth, nWidthUnit) )
	if( m_pCalculator->CheckInitSource(dp) &&
		m_pCalculator->DoLineProfile(vxOutput, vyOutput, vzOutput, -1, vxVertices, vyVertices, dWidth, nWidthUnit) )
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	{
		vector vxDiff, vyDiff;
		vxOutput.Difference(vxDiff);
		vyOutput.Difference(vyDiff);

		vector vDistance;
		vDistance = sqrt( vxDiff*vxDiff + vyDiff * vyDiff);
		vDistance.InsertAt(0, 0);
		ocmath_d_cumulative_sum(vDistance, 0, vDistance.GetSize(), vDistance);
		
		int r1, c1, r2, c2;
		Worksheet wks;
		if( info.m_drOutput.GetRange("Z", r1, c1, r2, c2, wks) >= 0 && wks.IsValid() )
		{
			Dataset dsDistance(wks, 0);
			if( dsDistance )
				dsDistance = vDistance;
			
			Dataset dsX(wks, 1);
			if( dsX )
				dsX = vxOutput;
			
			Dataset dsY(wks, 2);
			if( dsY )
				dsY = vyOutput;
			
			Dataset dsZ(wks, 3);
			if( dsZ )
			{
				dsZ = vzOutput;
				
				Column colZ(wks, 3);
				ASSERT(colZ);
				
				//string strComments;
				//strComments.Format(_L("Polyline profile of %s"), _get_data_plot_range_string(dp));
				colZ.SetComments(GetPathName());
				
				SetOutputWksParametersLabel(colZ, vxOutput, vyOutput);
				legend_update(info.m_glOutput);
			}
			
			return true;
		}


	}

	return false;
}

///Kyle 06/18/2010 ORG-98 BETTER_AUTO_NUMBER_OF_POINTS_FOR_OUTPUT
/*
int ImageProfilerPolyLinePath::GetPathNumPoints(const ImageProfilePathInfo& info, bool& bAuto)
{
	if( info.m_nNumPoints >= 2 )
	{
		bAuto = false;
		return info.m_nNumPoints;
	}

	bAuto = true;
	return 100;				// fixed points
}
*/
///End BETTER_AUTO_NUMBER_OF_POINTS_FOR_OUTPUT


///Kyle 06/21/2010 ORG-355 DISABLE_MOVE_LABEL_TEXT
///Kyle 07/20/2010 ORG-584-P2 NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
//bool ImageProfilerPolyLinePath::InitPathFromTree(const TreeNode& trPath)
bool ImageProfilerPolyLinePath::InitPathFromTree(const TreeNode& trPath, const GraphLayer& glSource)
///End NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
{
	///Kyle 07/20/2010 ORG-584-P2 NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
	//if( ImageProfilerPath::InitPathFromTree(trPath) )
	if( ImageProfilerPath::InitPathFromTree(trPath, glSource) )
	///End NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
	{
		for(int ii = m_arrPathInfo.GetSize() - 1; ii >= 0; ii--)
		{
			ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
			
			// disable movable and selectable for lines when close dialog. 
			// so need to cancel disable when reopen dialog.
			GraphObject goLine = info.GetLineObject();
			update_go_states(goLine, 0, GOC_NO_SELECT | GOC_NO_MOVE | GOC_NO_EDIT | GOC_NO_BORDERSIZE );
		}
		return true;
	}

	return false;
}
///End DISABLE_MOVE_LABEL_TEXT

///Kyle 07/01/2010 ORG-355-S7 OUTPUT_PROFILE_WIDTH
void ImageProfilerPolyLinePath::UpdateOutputWidth()
{
	ASSERT(1 == m_arrPathInfo.GetSize());
	ImageProfilePathInfo& info = m_arrPathInfo.GetAt(0);
	if( !info.m_drOutput )
		return;

	int r1, c1, r2, c2;
	Worksheet wks;
	if( info.m_drOutput.GetRange("Z", r1, c1, r2, c2, wks) >= 0 && wks.IsValid() )
	{
		ASSERT( c1 == c2 );
		Column colZ(wks, c1);
		SetOutputWidth(colZ);
	}
}
///End OUTPUT_PROFILE_WIDTH

/*----------------------------------------------------------------------------*/
/* ImageProfilerHVPath
/*----------------------------------------------------------------------------*/

int ImageProfilerHVPath::AddProfileLine(GraphLayer& glSource, int nColor, DWORD dwOption, const vector& vX, const vector& vY)
{
	ASSERT( GetPathType() == VERTICAL_LINE_IMAGE_PROFILE || GetPathType() == HORIZONTAL_LINE_IMAGE_PROFILE );

	if( !glSource )
		return -1;
	///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	DataPlot dpSource = glSource.DataPlots();
	if( !is_good_plot_for_profile(dpSource) )
		return -1;
	///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED

	ImageProfilePathInfo* pInfo = new ImageProfilePathInfo;
	if(!pInfo)
		return -1;

	bool bVertical = GetPathType() == VERTICAL_LINE_IMAGE_PROFILE;
	
	double dPos = NANUM;
	if( CheckLinePosition(vX, vY, bVertical) )
	{
		dPos = bVertical ? vX[0] : vY[0];
	}

	ImageProfileHVLine hvLine;
	///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	//if( !hvLine.Create(glSource, GetLineWidth(), nColor, bVertical, dPos) )
	int nWidthUnit = GetProfileWidthUnit();
	double dWidth = GetProfileWidth(nWidthUnit);
	if( nWidthUnit != IPROFILE_PATH_WIDTH_SCALE )
	{
		///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
		/*
		DataPlot dpSrc = glSource.DataPlots();
		ASSERT( dpSrc );
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//if( m_profileCalculator.CheckInitSource(dpSrc) )
		//	dWidth = m_profileCalculator.ConvertWidth(dWidth, nWidthUnit, IPROFILE_PATH_WIDTH_SCALE, vX, vY);
		if( m_pCalculator->CheckInitSource(dpSrc) )
		*/
		if( m_pCalculator->CheckInitSource(dpSource) )
		///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
			dWidth = m_pCalculator->ConvertWidth(dWidth, nWidthUnit, IPROFILE_PATH_WIDTH_SCALE, vX, vY);
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		if( dWidth == NANUM )
		{
			delete pInfo;
			return -1;
		}
	}
	if( !hvLine.Create(glSource, dWidth, nColor, bVertical, dPos) )
	///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	{
		delete pInfo;
		return -1;
	}

	pInfo->m_nLineType = (bVertical ? LTYPE_CROSSED_LINE_VERTICAL : LTYPE_CROSSED_LINE_HORIZONTAL);
	pInfo->m_uObjUID = hvLine.GetUID(true);
	pInfo->m_glSource = glSource;
	/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	//pInfo->m_dpSource = dpSource;			///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	pInfo->m_uSourcePlot = dpSource.GetUID(true);
	///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID

	return m_arrPathInfo.Add(*pInfo);
}

/// Iris 6/08/2010 ORG_98-P12 FIX_DUPLICATE_PATH_NOT_INCLUDED_VALUE_TEXT
bool	ImageProfilerHVPath::ClonePath(ImageProfilerPath* pSrcPath)
{
	if( ImageProfilerPath::ClonePath(pSrcPath) )
	{
		// to add the attached value text
		bool bVertical = GetPathType() == VERTICAL_LINE_IMAGE_PROFILE;
		int nIndex = GetLineIndex(bVertical);
		if( nIndex < 0 )
			return false;
	
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);
		
		GraphObject goLine;
		goLine = Project.GetObject(info.m_uObjUID);
		
		double dPos;
		GetLinePosition(dPos, bVertical);
		
		/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
		int nTextLocation = pSrcPath->GetTextObjectLocation();
		SetTextObjectLocation(nTextLocation);
		///End NEW_SUGGESTION_FOR_TEXT_OBJECT
		
		ImageProfileHVLine profileLine(goLine);
		/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
		//profileLine.AddReadOut(info.m_glSource, bVertical, dPos);
		profileLine.AddReadOut(info.m_glSource, bVertical, dPos, nTextLocation);
		///End NEW_SUGGESTION_FOR_TEXT_OBJECT
		return true;
	}
	return false;
}
///End FIX_DUPLICATE_PATH_NOT_INCLUDED_VALUE_TEXT

///Kyle 06/11/2010 ORG-98-S34 RESTRICT_LINE_WIDTH_AND_GIVE_HINT_FOR_PROFILE_WIDTH
#define MAX_LINE_WIDTH_MARGIN		0.8

///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
/*
bool ImageProfilerHVPath::SetLineWidth(double dWidth)
{
	ASSERT( GetPathType() == VERTICAL_LINE_IMAGE_PROFILE || GetPathType() == HORIZONTAL_LINE_IMAGE_PROFILE );

	bool bVertical = VERTICAL_LINE_IMAGE_PROFILE==GetPathType();
	double dMargin = -1;
	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		if( info.m_glSource )
		{
			dMargin = bVertical ? fabs(info.m_glSource.X.From - info.m_glSource.X.To) : fabs(info.m_glSource.Y.From - info.m_glSource.Y.To);
			break;
		}
	}

	if( dWidth < 0 || dWidth > MAX_LINE_WIDTH_MARGIN * dMargin )
		return false;

	return ImageProfilerPath::SetLineWidth(dWidth);
}
///End RESTRICT_LINE_WIDTH_AND_GIVE_HINT_FOR_PROFILE_WIDTH

///Kyle 06/11/2010 ORG-98-S33 BETTER_DEFAULT_WIDTH_FOR_H_AND_V_LINE_WIDTH
int ImageProfilerHVPath::GetSuitableWidths(vector& vWidths)
{
	ASSERT( GetPathType() == VERTICAL_LINE_IMAGE_PROFILE || GetPathType() == HORIZONTAL_LINE_IMAGE_PROFILE );
	bool bVertical = VERTICAL_LINE_IMAGE_PROFILE==GetPathType();

	double dMargin = -1;
	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		if( info.m_glSource )
		{
			dMargin = bVertical ? fabs(info.m_glSource.X.From - info.m_glSource.X.To) : fabs(info.m_glSource.Y.From - info.m_glSource.Y.To);
			break;
		}
	}

	vWidths.SetSize(0);
	vWidths.Add(0);
	if( dMargin > 0 )
	{
		vWidths.Add(dMargin/10);
		vWidths.Add(dMargin/8);
		vWidths.Add(dMargin/4);
		vWidths.Add(dMargin/2);
	}
	
	return vWidths.GetSize();
}
///End BETTER_DEFAULT_WIDTH_FOR_H_AND_V_LINE_WIDTH
*/
bool ImageProfilerHVPath::SetProfileWidth(double dWidth, int nUnit)
{
	ASSERT( GetPathType() == VERTICAL_LINE_IMAGE_PROFILE || GetPathType() == HORIZONTAL_LINE_IMAGE_PROFILE );

	bool bVertical = VERTICAL_LINE_IMAGE_PROFILE==GetPathType();
	double dLaySpan = -1;
	double dSize = -1;
	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
		/*
		if( info.m_glSource )
		{
			DataPlot dpSrc = info.m_glSource.DataPlots();
			if( dpSrc )
			{
				int nRows, nCols;
				_find_dp_coordinates(dpSrc, nRows, nCols);
				dSize = bVertical ? nRows : nCols;
				
				dLaySpan = bVertical ? fabs(info.m_glSource.X.From - info.m_glSource.X.To) : fabs(info.m_glSource.Y.From - info.m_glSource.Y.To);
				break;
			}			
		}
		*/
		/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
		//if( info.m_glSource && info.m_dpSource )
		DataPlot dpSource;
		if( info.m_glSource && info.GetSourcePlot(dpSource) )
		///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
		{
			int nRows, nCols;
			/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
			//_find_dp_coordinates(info.m_dpSource, nRows, nCols);
			_find_dp_coordinates(dpSource, nRows, nCols);
			///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
			dSize = bVertical ? nRows : nCols;
				
			dLaySpan = bVertical ? fabs(info.m_glSource.X.From - info.m_glSource.X.To) : fabs(info.m_glSource.Y.From - info.m_glSource.Y.To);
			break;
		}
		///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	}

	if( dWidth < 0 ||
		(IPROFILE_PATH_WIDTH_SCALE==nUnit && dWidth > MAX_LINE_WIDTH_MARGIN * dLaySpan) ||
		(IPROFILE_PATH_WIDTH_PIXEL==nUnit && dWidth > MAX_LINE_WIDTH_MARGIN * dSize) )
		return false;

	return ImageProfilerPath::SetProfileWidth(dWidth, nUnit);
}


int ImageProfilerHVPath::GetSuitableWidths(vector<int>& vnWidthInPixel, vector& vdWidthInScale)
{
	ASSERT( GetPathType() == VERTICAL_LINE_IMAGE_PROFILE || GetPathType() == HORIZONTAL_LINE_IMAGE_PROFILE );
	bool bVertical = VERTICAL_LINE_IMAGE_PROFILE==GetPathType();

	int nSize = -1;
	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
		/*
		if( info.m_glSource )
		{
			DataPlot dpSrc = info.m_glSource.DataPlots();
			if( dpSrc )
			{
				int nRows, nCols;
				_find_dp_coordinates(dpSrc, nRows, nCols);
				nSize = bVertical ? nRows : nCols;
				
				//dLaySpan = bVertical ? fabs(info.m_glSource.X.From - info.m_glSource.X.To) : fabs(info.m_glSource.Y.From - info.m_glSource.Y.To);
				break;
			}
		}
		*/
		/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
		//if( info.m_dpSource )
		DataPlot dpSource;
		if( info.GetSourcePlot(dpSource) )
		///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
		{
			int nRows, nCols;
			/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
			//_find_dp_coordinates(info.m_dpSource, nRows, nCols);
			_find_dp_coordinates(dpSource, nRows, nCols);
			///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
			nSize = bVertical ? nRows : nCols;
			break;
		}
		///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	}

	vnWidthInPixel.SetSize(0);
	vnWidthInPixel.Add(1);
	if( nSize > 0 )
	{
		double dSize = nSize;
		vnWidthInPixel.Add(nint(dSize/10));
		vnWidthInPixel.Add(nint(dSize/8));
		vnWidthInPixel.Add(nint(dSize/4));
		vnWidthInPixel.Add(nint(dSize/2));

		for(ii = 1; ii < vnWidthInPixel.GetSize(); ii++)
		{
			if( (vnWidthInPixel[ii] & 1)==0 )
				vnWidthInPixel[ii]++;
		}
	}

	vdWidthInScale.SetSize(vnWidthInPixel.GetSize());
	for(ii = vnWidthInPixel.GetSize()-1; ii >= 0; ii--)
	{
		if( ii > 0 && vnWidthInPixel[ii]==vnWidthInPixel[ii-1] )
		{
			vnWidthInPixel.RemoveAt(ii);
			vdWidthInScale.RemoveAt(ii);
		}
		else
			vdWidthInScale[ii] = ConvertWidth(vnWidthInPixel[ii], IPROFILE_PATH_WIDTH_PIXEL, IPROFILE_PATH_WIDTH_SCALE);
	}

	return vnWidthInPixel.GetSize();
}
///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE

bool ImageProfilerHVPath::SetLinePosition(const vector& vx, const vector& vy, bool bVertical)
{
	int nIndex = GetLineIndex(bVertical);
	if( nIndex < 0 )
		return false;

	if( !CheckLinePosition(vx, vy, bVertical) )
		return false;
	
	ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);
	if( SetPathPosition(info, vx, vy) )
	{
		//RefreshProfilePath(true, false);		// no OE_MOVE event, refresh path here
		//UpdateReadOut(info, -1);
		GraphObject goLine = info.GetLineObject();
		goLine.PostMessage(OE_MOVE);
		return true;
	}

	return false;
}

/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
// no place used it 
/*
bool ImageProfilerHVPath::UpdateReadOutText(bool bShowText)
{
	int nShowText = bShowText ? 1 : 0;
	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		UpdateReadOut(info, nShowText);
	}

	return true;
}
*/
///End NEW_SUGGESTION_FOR_TEXT_OBJECT

class CTempDisConnect
{
public:
	CTempDisConnect(GraphObject& goText, GraphObject& goRect)
	{
		m_goText = goText;
		m_goRect = goRect;
		ASSERT( m_goText.IsValid() && m_goRect.IsValid() );
				
		vector<uint> vUIDs;
		m_bIsConnected = false;
		if( goRect.GetConnectedObjects(vUIDs) > 0 )
		{
			ASSERT(vUIDs.GetSize() == 1);			
			m_bIsConnected = ( vUIDs[0] == goText.GetUID(true) );
		}
		
		if( m_bIsConnected )
			m_goText.ConnectTo(NULL);			// clear connection
	}
	
	~CTempDisConnect()
	{
		if( m_bIsConnected )
			m_goText.ConnectTo(m_goRect, -1, -1, false);
	}

private:
	GraphObject m_goText;
	GraphObject m_goRect;
	bool		m_bIsConnected;
};

/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
bool ImageProfilerHVPath::GetReadOutObject(const ImageProfilePathInfo& info, GraphObject& goText)
{
	GraphObject goLine = info.GetLineObject();
	if( !goLine )
		return false;

	vector<uint> vUIDs;
	if( !(goLine.GetConnectedObjects(vUIDs) > 0 && vUIDs.GetSize() > 0) )
		return false;

	ASSERT( vUIDs.GetSize() == 1 );

	goText = (GraphObject)Project.GetObject(vUIDs[0]);
	return goText.IsValid();	
}

void ImageProfilerHVPath::ChangeTextObjectLocation()
{	
	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		
		GraphObject goLine = info.GetLineObject();
		ASSERT( goLine );
		
		GraphObject goText;
		GetReadOutObject(info, goText);
		ASSERT( goText );		

		_adjust_connected_text_object_location(goLine, goText, LTYPE_CROSSED_LINE_VERTICAL == info.m_nLineType, m_nTextObjectLocation);
		
		info.m_glSource.GetPage().Refresh(); // need refresh graph after change text location
	}	
}
///End NEW_SUGGESTION_FOR_TEXT_OBJECT

//virtual 
bool 	ImageProfilerHVPath::AddBackProfileLines(TreeNode& tr)
{
	if( ImageProfilerPath::AddBackProfileLines(tr) )
	{
		ASSERT(1 == m_arrPathInfo.GetSize());
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(0);
		
		GraphObject goLine;
		goLine = Project.GetObject(info.m_uObjUID);
		ASSERT(goLine.IsValid());
		
		ImageProfileHVLine profileLine(goLine);
		
		bool bVertical = GetPathType() == VERTICAL_LINE_IMAGE_PROFILE;
		double dPos;
		GetLinePosition(dPos, bVertical);
		
		///Kyle 07/16/2010 ORG-584-S4 MORE_OPTION_FOR_THE_XY_LABEL_DEFAULT_POSITION
		//profileLine.AddReadOut(info.m_glSource, bVertical, dPos);	
		profileLine.AddReadOut(info.m_glSource, bVertical, dPos, m_nTextObjectLocation);	
		///End MORE_OPTION_FOR_THE_XY_LABEL_DEFAULT_POSITION
		return true;
	}
	return false;	
}

bool ImageProfilerHVPath::UpdateReadOut(const ImageProfilePathInfo& info, int nShowText)
{
	GraphObject goLine = info.GetLineObject();
	if( !goLine )
		return false;

	/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
	// centralize codes
	/*
	vector<uint> vUIDs;
	if( !(goLine.GetConnectedObjects(vUIDs) > 0 && vUIDs.GetSize() > 0) )
		return false;

	ASSERT( vUIDs.GetSize() == 1 );

	GraphObject goText;
	goText = (GraphObject)Project.GetObject(vUIDs[0]);
	if( !goText )
		return false;
	*/
	GraphObject goText;
	if( !GetReadOutObject(info, goText) )
		return false;
	///End NEW_SUGGESTION_FOR_TEXT_OBJECT

	if( nShowText >= 0 )
	{
		bool bShow = nShowText > 0 ? true : false;
		goText.Show(bShow);
	}
	if( !goText.Show )
		return true;

	double dPos;
	bool bVertical = LTYPE_CROSSED_LINE_VERTICAL == info.m_nLineType;
	if( GetLinePosition(dPos, bVertical) )
	{
		///Kyle 06/18/2010 ORG-98-S38 ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
		//string strText = ftoa(dPos, "*");
		///End ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
		
		//---- iris 6/21/2010 fix text location is incorrect when text at the right or bottom of line.
		/*
		// Adjust the place of text object
		CTempDisConnect tmpDisConn(goText, goLine);			// change position will effect on the connected object, so disconnect the object temporarily
		if( bVertical )
		{
			double dMid = goText.Left + 0.5 * goText.Width;
			goText.Text = strText;
			goText.Left = dMid - goText.Width / 2;
		}
		else
		{
			double dRight = goText.Left + goText.Width;
			goText.Text = strText;
			goText.Left = dRight - goText.Width;
		}
		*/
		_adjust_connected_text_object_location(goLine, goText, bVertical, m_nTextObjectLocation, _get_pos_string_for_label_text(dPos));
		//----
		
		/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
		/*
		// update text object color according to line color
		Tree trLine, trText;
		trLine = goLine.GetFormat(FPB_STYLE_COLOR, FOB_ALL, TRUE, TRUE);
		trText.Root.Color.nVal = trLine.Root.Border.Color.nVal;
		if( 0 == goText.UpdateThemeIDs(trText.Root) )
			goText.ApplyFormat(trText, true, true);
		*/
		///End NEW_SUGGESTION_FOR_TEXT_OBJECT		
	}

	return true;
}

/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
void ImageProfilerHVPath::SetReadOutActive(bool bActive)
{
	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		
		GraphObject goLine = info.GetLineObject();
		ASSERT( goLine );

		GraphObject goText;
		if( GetReadOutObject(info, goText) )
		{		
			CTempDisConnect temp(goText, goLine);
			
			Tree tr;			
			tr.Root.Background.Border.Width.dVal = bActive? 0.5 : 0;			
			if(0 == goText.UpdateThemeIDs(tr.Root) )
				goText.ApplyFormat(tr, true, true);
		}
	}
}
///End NEW_SUGGESTION_FOR_TEXT_OBJECT

bool ImageProfilerHVPath::GetLinePosition(vector& vx, vector& vy, bool bVertical)
{
	int nIndex = GetLineIndex(bVertical);
	if( nIndex < 0 )
		return false;

	ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);
	return GetPathPosition(info, vx, vy);
}

bool ImageProfilerHVPath::SetLinePosition(double dValue, bool bVertical)
{
	vector vx, vy;
	if( !GetLinePosition(vx, vy, bVertical) )
		return false;

	if( bVertical )
		vx = dValue;
	else
		vy = dValue;

	return SetLinePosition(vx, vy, bVertical);
}

bool ImageProfilerHVPath::GetLinePosition(double& dValue, bool bVertical)
{
	vector vx, vy;
	if( GetLinePosition(vx, vy, bVertical) )
	{
		dValue = bVertical ? vx[0] : vy[0];
		return true;
	}

	return false;
}

bool ImageProfilerHVPath::CheckLinePosition(const vector& vx, const vector& vy, bool bVertical)
{
	if( !(vx && vy && vx.GetSize()==2 && vy.GetSize()==2) )
		return false;

	return bVertical ? is_equal(vx[0], vx[1]) : is_equal(vy[0], vy[1]);
}

bool ImageProfilerHVPath::SetPathColor(const ImageProfilePathInfo& info, int nColor)
{
	return set_go_border_color(info.GetLineObject(), nColor);
}

int ImageProfilerHVPath::GetPathColor(const ImageProfilePathInfo& info)
{
	GraphObject go = info.GetLineObject();
	if( !go )
		return -1;

	Tree tr;
	tr = go.GetFormat(FPB_STYLE_COLOR, FOB_ALL, true, true);
	
	if( tr.Root.Border && tr.Root.Border.Color )
		return tr.Root.Border.Color.nVal;
	return -1;
}

bool ImageProfilerHVPath::SetPathPosition(const ImageProfilePathInfo& info, const vector& vx, const vector& vy)
{
	//ASSERT( GetPathType() == CROSSED_LINES_IMAGE_PROFILE || GetPathType() == VERTICAL_LINE_IMAGE_PROFILE || GetPathType() == HORIZONTAL_LINE_IMAGE_PROFILE );
	ASSERT( GetPathType() == VERTICAL_LINE_IMAGE_PROFILE || GetPathType() == HORIZONTAL_LINE_IMAGE_PROFILE );

	vector vxTemp, vyTemp;
	vxTemp = vx;
	vyTemp = vy;
	///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	//if( !_transfer_pos_for_rect(vxTemp, vyTemp, true, info.m_nLineType == CROSSED_LINE_VERTICAL, GetLineWidth(info)) )
	///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	//if( !_transfer_pos_for_rect(vxTemp, vyTemp, true, info.m_nLineType == CROSSED_LINE_VERTICAL, m_dLineWidth) )
	if( !_transfer_pos_for_rect(vxTemp, vyTemp, true, info.m_nLineType == LTYPE_CROSSED_LINE_VERTICAL, GetProfileWidth(IPROFILE_PATH_WIDTH_SCALE)) )
	///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
		return false;

	return ImageProfilerPath::SetPathPosition(info, vxTemp, vyTemp);
}

bool ImageProfilerHVPath::GetPathPosition(const ImageProfilePathInfo& info, vector& vx, vector& vy)
{
	//ASSERT( GetPathType() == CROSSED_LINES_IMAGE_PROFILE || GetPathType() == VERTICAL_LINE_IMAGE_PROFILE || GetPathType() == HORIZONTAL_LINE_IMAGE_PROFILE );
	ASSERT( GetPathType() == VERTICAL_LINE_IMAGE_PROFILE || GetPathType() == HORIZONTAL_LINE_IMAGE_PROFILE );

	if( ImageProfilerPath::GetPathPosition(info, vx, vy) )
	{
		return _transfer_pos_for_rect(vx, vy, false, info.m_nLineType == LTYPE_CROSSED_LINE_VERTICAL);
	}

	return false;
}

bool ImageProfilerHVPath::SetPathWidth(const ImageProfilePathInfo& info, double dLineWidth)
{
	vector vx, vy;
	if( GetPathPosition(info, vx, vy) && _transfer_pos_for_rect(vx, vy, true, info.m_nLineType == LTYPE_CROSSED_LINE_VERTICAL, dLineWidth) )
		return ImageProfilerPath::SetPathPosition(info, vx, vy);

	return false;
}

double ImageProfilerHVPath::GetPathWidth(const ImageProfilePathInfo& info)
{
	GraphObject goLine = info.GetLineObject();
	if( !goLine )
		return false;

	double dLeft, dTop, dRight, dBottom;
	if( rect_get_position(goLine, dLeft, dTop, dRight, dBottom) )
	{
		return (info.m_nLineType == LTYPE_CROSSED_LINE_VERTICAL) ? abs(dRight - dLeft) : abs(dBottom - dTop);
	}

	return NANUM;
}

///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
/*
double ImageProfilerHVPath::GetLineWidth(const ImageProfilePathInfo& info)
{
	DataPlot dpSrc;
	if( info.m_glSource )
		dpSrc = info.m_glSource.DataPlots();

	if( !dpSrc )
		return 0;

	int nRows, nCols;
	_find_dp_coordinates(dpSrc, nRows, nCols);

	int nSize;
	double dLayWidth;
	if(CROSSED_LINE_VERTICAL==info.m_nLineType)
	{
		dLayWidth = fabs(info.m_glSource.X.From - info.m_glSource.X.To);
		nSize = nCols;
	}
	else
	{
		dLayWidth = fabs(info.m_glSource.Y.From - info.m_glSource.Y.To);
		nSize = nRows;
	}

	return m_dProfileWidth * dLayWidth / nSize;
}
*/
///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH

int ImageProfilerHVPath::GetLineIndex(bool bVertical)
{
	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		if( (bVertical && info.m_nLineType == LTYPE_CROSSED_LINE_VERTICAL) || (!bVertical && info.m_nLineType == LTYPE_CROSSED_LINE_HORIZONTAL) )
			return ii;
	}

	return -1;
}

bool ImageProfilerHVPath::FindOutputWks(Worksheet& wksOutput, WorksheetPage& wpOutput, const ImageProfilePathInfo& info)
{
	if( GetPathType() != VERTICAL_LINE_IMAGE_PROFILE && GetPathType() != HORIZONTAL_LINE_IMAGE_PROFILE )
		return ImageProfilerPath::FindOutputWks(wksOutput, wpOutput, info);

	///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	/*
	DataPlot dpSrc;
	if( info.m_glSource )
		dpSrc = info.m_glSource.DataPlots();
	*/
	/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	//DataPlot dpSrc = info.m_dpSource;
	DataPlot dpSrc;
	if( !info.GetSourcePlot(dpSrc) )
		return error_report("Fail to get source data plot");
	///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED

	bool bNewSheet = false;
	bool bVertical = GetPathType() == VERTICAL_LINE_IMAGE_PROFILE;
	string strRelatedDs = bVertical ? "IProfileVLOutput" : "IProfileHLOutput";
	string strWksName = GetPathName() + "Profile";

	if(wpOutput)
	{
		DatasetObject dsObject;
		if( dpSrc.GetRelatedDataset(strRelatedDs, dsObject) && dsObject.IsValid() )
			dsObject.GetParent(wksOutput);

		if( !wksOutput )
		{
			bNewSheet = true;
			int nLayer = wpOutput.AddLayer(strWksName, 0, "origin");
			wksOutput = wpOutput.Layers(nLayer);
		}
	}
	else
	{
		bNewSheet = true;
		wksOutput.Create("origin", CREATE_HIDDEN | CREATE_LOAD_1ST_LAYER_ONLY);
		if( wksOutput )
		{
			wksOutput.SetName(strWksName);
			wksOutput.GetPage().SetName(STR_PROFILE_BOOK, OCD_ENUM_NEXT);
		}
	}

	if( bNewSheet && wksOutput )
	{
		wksOutput.SetSize(-1, 0);

		//DatasetObject dsObj(wksOutput.Columns(0));
		//dpSrc.SetRelatedDataset(strRelatedDs, dsObj);
	}

	return wksOutput.IsValid();
}

#define STR_V_OUTPUT_X_COLUMN_RELATED_DATASET			"IProfileVLOutput"
#define STR_H_OUTPUT_X_COLUMN_RELATED_DATASET			"IProfileHLOutput"

bool	ImageProfilerHVPath::RemovePathInfoAt(int nIndex, bool bRemoveOutput, bool bRemoveLine)
{
	if( GetPathType() != VERTICAL_LINE_IMAGE_PROFILE && GetPathType() != HORIZONTAL_LINE_IMAGE_PROFILE )
		return ImageProfilerPath::RemovePathInfoAt(nIndex, bRemoveOutput, bRemoveLine);

	///Kyle 06/21/2010 ORG-355 DISABLE_MOVE_LABEL_TEXT
	if( nIndex < 0 || nIndex >= m_arrPathInfo.GetSize() )
		return false;

	if( !bRemoveLine )
	{
		GraphObject goText;
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);
		if( GetReadOutObject(info, goText) && goText.IsValid() )
		{
			update_go_states(goText, GOC_NO_SELECT | GOC_NO_MOVE | GOC_NO_RESIZE | GOC_NO_ROTATE | GOC_NO_SKEW | GOC_NO_EDIT | GOC_NO_BORDERSIZE );
		}
	}
	///End DISABLE_MOVE_LABEL_TEXT

	if( bRemoveOutput )
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);
		if( info.m_glOutput )
		{
			XYRange xyOutput;
			if( GetPreviewRange(info, xyOutput) )
			{
				vector<int> vnPlotIndices;
				if( check_has_plotted_in_graph(xyOutput, info.m_glOutput, vnPlotIndices) > 0 )
				{
					info.m_glOutput.RemovePlot(vnPlotIndices[0]);

					legend_update(info.m_glOutput);				///Kyle 06/23/2010 ORG-355-P9 UPDATE_LEGEND_AFTER_DELETE_PATH
				}
			}
		}

		
		if( info.m_drOutput )
		{
			Worksheet wks;
			int r1, c1, r2, c2;
			if( info.m_drOutput.GetRange("Y", r1, c1, r2, c2, wks)>=0 && wks )
			{
				ASSERT(c1 == c2);
				bool bRet = wks.DeleteCol(c1);
				ASSERT(bRet);

				if( wks.GetNumCols() <= 1 )
				{
					wks.Destroy();
					
					///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
					/*
					DataPlot dpSrc;
					if( info.m_glSource )
						dpSrc = info.m_glSource.DataPlots();
					if( dpSrc )
					{
						string strRelatedDs = VERTICAL_LINE_IMAGE_PROFILE==GetPathType() ? STR_V_OUTPUT_X_COLUMN_RELATED_DATASET : STR_H_OUTPUT_X_COLUMN_RELATED_DATASET;
						dpSrc.RemoveRelatedDataset(strRelatedDs);
					}
					*/
					/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
					/*
					if( info.m_dpSource )
					{
						string strRelatedDs = VERTICAL_LINE_IMAGE_PROFILE==GetPathType() ? STR_V_OUTPUT_X_COLUMN_RELATED_DATASET : STR_H_OUTPUT_X_COLUMN_RELATED_DATASET;
						info.m_dpSource.RemoveRelatedDataset(strRelatedDs);
					}
					*/
					DataPlot dpSource;
					if( info.GetSourcePlot(dpSource) )
					{
						string strRelatedDs = VERTICAL_LINE_IMAGE_PROFILE==GetPathType() ? STR_V_OUTPUT_X_COLUMN_RELATED_DATASET : STR_H_OUTPUT_X_COLUMN_RELATED_DATASET;
						dpSource.RemoveRelatedDataset(strRelatedDs);
					}
					///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
					///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
				}
			}
		}
	}
	return ImageProfilerPath::RemovePathInfoAt(nIndex, false, bRemoveLine);
}

int ImageProfilerHVPath::OnProfileEvent(int nEvent, UINT uObjUID)
{
	///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING
	/*
	int nIndex = ImageProfilerPath::OnProfileEvent(nEvent, uObjUID);
	if( nIndex >= 0 && nIndex < m_arrPathInfo.GetSize() )
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);
		UpdateReadOut(info, -1);
		return nIndex;
	}

	return -1;
	*/
	int nUpdate = ImageProfilerPath::OnProfileEvent(nEvent, uObjUID);
	if( nUpdate != IPUPDATE_NO_CHANGE )
	{
		int nIndex = GetPathInfoIndex(uObjUID);
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);

		///Kyle 06/22/2010 ORG-355 CENTRALIZE_CODE_AND_CHANGE_CLASS_STRUCTURE, need to copy source axis format here
		if( OE_SCALE_CHANGE == nEvent )
		{
			// after source layer scale changed, need to copy scale settings to profile layers
			// SC, SV, and SH mode no need do this, since dest layer has linked to source layer.
			int nParentLayer;
			if( layer_get_link(info.m_glOutput, nParentLayer) && nParentLayer < 0 ) // nParentLayer<0 means no link
			{
				bool bVertical = info.m_nLineType == LTYPE_CROSSED_LINE_VERTICAL;
				if( bVertical )
					_copy_axis_tick_label_scale(info.m_glSource.YAxis, info.m_glOutput.XAxis);
				else
					_copy_axis_tick_label_scale(info.m_glSource.XAxis, info.m_glOutput.XAxis);
			}
		}
		///End CENTRALIZE_CODE_AND_CHANGE_CLASS_STRUCTURE

		UpdateReadOut(info, -1);
	}

	return nUpdate;
	///End CENTRALIZE_EVENT_HANDLING
}

int ImageProfilerHVPath::OnReadOutEvent(int nEvent, UINT uObjUID)
{
	/* to do, no this event now
	if( nEvent == OE_IN_PLACE_EDIT )
	{
		int nIndex = GetReadOutObjPathIndex(uObjUID);
		if( nIndex >= 0 && nIndex < m_arrPathInfo.GetSize() )
		{
			GraphObject goText; goText = (GraphObject)Project.GetObject(uObjUID);
			if( !goText )
				return -1;
	
			int nType;
			goText.GetObjectType(&nType);
			if( GROBJ_TN_TEXT != nType )
				return -1;
	
			double dNewPos = atof(goText.Text);
			if( dNewPos == NANUM )
				return -1;
	
			bool bVertical;
			{
				ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);
				bVertical = CROSSED_LINE_VERTICAL == info.m_nLineType;
			}
			double dValue;
			if( GetLinePosition(dValue, bVertical) && !is_equal(dValue, dNewPos) )
				SetLinePosition(dNewPos, bVertical);
		}
		return IPUPDATE_PATH_CONTENT_POSITION;
	}
	*/

	return IPUPDATE_NO_CHANGE;
}

bool ImageProfilerHVPath::IsReadOutObj(UINT uObjUID)
{
	return GetReadOutObjPathIndex(uObjUID) >= 0;
}

int ImageProfilerHVPath::GetReadOutObjPathIndex(UINT uObjUID)
{
	int nIndex = -1;
	int nCount = m_arrPathInfo.GetSize();
	for(int ii = 0; ii < nCount; ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		GraphObject go = info.GetLineObject();
		if( go )
		{
			vector<uint> vUIDs, vec;
			if( go.GetConnectedObjects(vUIDs) > 0 && vUIDs.Find(vec, uObjUID) > 0 )
			{
				nIndex = ii;
				break;
			}
		}
	}

	return nIndex;
}

bool ImageProfilerHVPath::CheckSetProfileLayer(WorksheetPage& wpOutput, GraphLayer& glVertical, GraphLayer& glHorizontal)
{
	ASSERT( GetPathType() == VERTICAL_LINE_IMAGE_PROFILE || GetPathType() == HORIZONTAL_LINE_IMAGE_PROFILE );

	if( m_arrPathInfo.GetSize() < 1 )
		return false;
	ASSERT( m_arrPathInfo.GetSize() == 1 );
	
	ImageProfilePathInfo& info = m_arrPathInfo.GetAt(0);

	bool bVertical = GetPathType() == VERTICAL_LINE_IMAGE_PROFILE;

	/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	/*
	///Kyle 06/21/2010 ORG-355-P5 FIX_MULTIPLE_OUTPUT_WORKSHEET_WHEN_SWITCH_LAYOUT_MODE
	DataPlot dpSrc = info.m_dpSource;
	///End FIX_MULTIPLE_OUTPUT_WORKSHEET_WHEN_SWITCH_LAYOUT_MODE
	*/
	DataPlot dpSrc;
	if( !info.GetSourcePlot(dpSrc) )
		return error_report("Fail to get source data plot in CheckSetProfileLayer");
	///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID

	if( !info.m_drOutput )
	{
		Worksheet wksTemp;
		if( !FindOutputWks(wksTemp, wpOutput, info) )
			return false;

		int nXCol = 0, nYCol;
		if( wksTemp.GetNumCols() > 0 )
		{
			nYCol = wksTemp.AddCol();
		}
		else
		{
			wksTemp.SetSize(-1, 2);		// X & Y columns
			wksTemp.SetColDesignations("XY");
			nYCol = 1;

			///Kyle 07/01/2010 ORG-355-S7 OUTPUT_PROFILE_WIDTH
			/*
			Grid gg;
			gg.Attach(wksTemp);    
			gg.ShowLabels(RCLT_UDL);
			
			vector<string> vsUDLs(1);
			vsUDLs[0] = bVertical? STR_OUT_WKS_UDL_VLINE : STR_OUT_WKS_UDL_HLINE;
			gg.SetUserDefinedLabelNames(vsUDLs);
			*/
			vector<uint> vnLabels = {LABEL_PROFILE_WIDTH, LABEL_LINE_POSITION};
			vector<string> vsLabels;
			vsLabels.Add(_L("Width"));
			vsLabels.Add(bVertical? STR_OUT_WKS_UDL_VLINE : STR_OUT_WKS_UDL_HLINE);
			PrepareUserDefinedLabels(wksTemp, vnLabels, vsLabels);
			///End OUTPUT_PROFILE_WIDTH
		}

		///Kyle 06/21/2010 ORG-355-P5 FIX_MULTIPLE_OUTPUT_WORKSHEET_WHEN_SWITCH_LAYOUT_MODE
		/////Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
		////DataPlot dpSrc = info.m_glSource.DataPlots();
		//DataPlot dpSrc = info.m_dpSource;
		/////End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
		//DatasetObject dsObj(wksTemp.Columns(0));
		//dpSrc.SetRelatedDataset(bVertical ? STR_V_OUTPUT_X_COLUMN_RELATED_DATASET : STR_H_OUTPUT_X_COLUMN_RELATED_DATASET, dsObj);
		///End FIX_MULTIPLE_OUTPUT_WORKSHEET_WHEN_SWITCH_LAYOUT_MODE
		///Sophy 5/31/2010 ORG-98-S17 SETUP_RESULT_COLUMN_HEADERS_BY_SOURCE
		int c1, c2, r1, r2;
		DataRange rng;
		if( !dpSrc.GetDataRange(rng) || !rng )
			return false;
		switch(dpSrc.GetPlotType())
		{
		case IDM_PLOT_CONTOUR:
		case IDM_PLOT_MATRIX_IMAGE:

			MatrixLayer ml;
			rng.GetRange(ml, c1, c2);

			MatrixObject mo(ml, c1);
			if(mo)
			{
				Column colY(wksTemp, nYCol);
				colY.SetLongName(mo.GetLongName());
				colY.SetUnits(mo.GetUnits());
				
				Column colX(wksTemp, nXCol);
				///Kyle 07/01/2010 ORG-355-P12 WRONG_LABEL_FOR_V_LINE_COPIED_FROM_MATRIX
				//colX.SetLongName(ml.GetAxesLongName(FALSE));
				//colX.SetUnits(ml.GetAxesUnits(FALSE));
				//colX.SetComments(ml.GetAxesComments(FALSE));
				bool bYAxes = bVertical;
				colX.SetLongName(ml.GetAxesLongName(bYAxes));
				colX.SetUnits(ml.GetAxesUnits(bYAxes));
				colX.SetComments(ml.GetAxesComments(bYAxes));
				///End WRONG_LABEL_FOR_V_LINE_COPIED_FROM_MATRIX
			}
			else //virtual matrix, nothing to do.
			{
			}
			break;
			
		case IDM_PLOT_TRI_CONTOUR:
			
			Worksheet wks;
			int nZIndex = rng.GetRange("Z", r1, c1, r2, c2, wks);
			Column colZ(wks, nZIndex);
			if ( colZ )
			{
				Column colY(wksTemp, nYCol);
				colY.SetLongName(colZ.GetLongName());
				colY.SetUnits(colZ.GetUnits());
			}
			int nXIndex = rng.GetRange("X", r1, c1, r2, c2, wks);
			Column colSrcX(wks, nXIndex);
			if ( colSrcX )
			{
				Column colX(wksTemp, nXCol);
				colX.SetLongName(colSrcX.GetLongName());
				colX.SetUnits(colSrcX.GetUnits());
			}
			break;
			
		default:
			ASSERT(false);
			break;
		}
		///end SETUP_RESULT_COLUMN_HEADERS_BY_SOURCE
		DataRange drResult;
		drResult.Add(wksTemp, nXCol, "X");
		drResult.Add(wksTemp, nYCol, "Y");

		info.m_drOutput = drResult;
		/// Iris 6/07/2010 ORG-98-P10 FIX_RENAME_TAB_UPDATED_INCORRECT_OUTPUT_COL_COMMENTS
		// if NOT add data range object to project, when delete one column will effect on data range
		// because data range remembered is column index.
		Project.AddDataRange(info.m_drOutput);
		///End FIX_RENAME_TAB_UPDATED_INCORRECT_OUTPUT_COL_COMMENTS
		
		UpdateOutputWidth();		///Kyle 07/01/2010 ORG-355-S7 OUTPUT_PROFILE_WIDTH
	}
	///Kyle 06/21/2010 ORG-355-P5 FIX_MULTIPLE_OUTPUT_WORKSHEET_WHEN_SWITCH_LAYOUT_MODE
	if( dpSrc )
	{
		ASSERT( info.m_drOutput );
		XYRange xyRange;
		xyRange = info.m_drOutput;
		Column colX;
		xyRange.GetXColumn(colX);
		DatasetObject dsObj(colX);
		dpSrc.SetRelatedDataset(bVertical ? STR_V_OUTPUT_X_COLUMN_RELATED_DATASET : STR_H_OUTPUT_X_COLUMN_RELATED_DATASET, dsObj);
	}
	///End FIX_MULTIPLE_OUTPUT_WORKSHEET_WHEN_SWITCH_LAYOUT_MODE
	
	//wksTemp.Columns(0).SetLongName(bVertical ? "X" : "Y");
	//wksTemp.Columns(1).SetLongName(bVertical ? "Vertical Profile" : "Horizontal Profile");

	//XYRange xyResult;
	//xyResult.Add(wksTemp, 0, "X");
	//xyResult.Add(wksTemp, 1, "Y");
	//info.m_xyOutput = xyResult;

	///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	// output graph layer will be changed when switch layout mode. Before info always be clear when
	// switch layout mode.
	//if( !info.m_glOutput )
	///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	{
		info.m_glOutput = bVertical ? glVertical : glHorizontal;
		ASSERT( info.m_glOutput );
	}
	CheckPlotOutput(info);

	return true;

}

int		ImageProfilerHVPath::AddRelatedPathInfo(vector<int>& vnIndices)
{
	//if( GetPathType() != CROSSED_LINES_IMAGE_PROFILE && GetPathType() != ARBITRARY_LINE_IMAGE_PROFILE )		// nothing to do
	if( GetPathType() != ARBITRARY_LINE_IMAGE_PROFILE )		// nothing to do
		return vnIndices.GetSize();

	if( vnIndices.GetSize() > 0 )
	{
		vnIndices.Sort();

		int ii = vnIndices.GetSize() - 1;
		while( ii >= 0 )
		{
			if( (vnIndices[ii]<0) || (ii>0 && vnIndices[ii]==vnIndices[ii-1]) )
			{
				vnIndices.RemoveAt(ii);
				ii--;
			}
			else
			{
				int nHIndex, nVIndex;
				if( vnIndices[ii]%2 == 0 )
				{
					#ifdef _DEBUG
					{
						vector<uint> vec;
						ASSERT(vnIndices.Find(vec, vnIndices[ii] + 1) <= 0);
					}
					#endif//_DEBUG
	
					if( ii == vnIndices.GetSize() - 1 )
						vnIndices.Add(vnIndices[ii] + 1);
					else
						vnIndices.InsertAt(ii+1, vnIndices[ii] + 1);
					ii--;
				}
				else
				{
					if( ii==0 || vnIndices[ii-1]!=vnIndices[ii]-1 )
					{
						vnIndices.InsertAt(ii, vnIndices[ii] - 1);
						ii--;
					}
					else
					{
						ii -= 2;
					}
				}
			}
		}
	}

	return vnIndices.GetSize();
}

bool ImageProfilerHVPath::GetPreviewRange(const ImageProfilePathInfo& info, XYRange& xyRange)
{
	if( !info.m_drOutput )
		return false;

	/*
	if( GetPathType() == VERTICAL_LINE_IMAGE_PROFILE )
	{
		xyRange.Add(info.m_wksOutput, 1, "X");
	}
	else
	{
		xyRange.Add(info.m_wksOutput, 0, "X");
	}
	xyRange.Add(info.m_wksOutput, 2, "Y");
	*/
	xyRange = info.m_drOutput;

	return xyRange.IsValid();
}

///Kyle 07/21/2010 ORG-584-P4 CHECK_RESET_LINE_WIDTH_FOR_LOG_SCALE
bool ImageProfilerHVPath::BeforeDoProfile(ImageProfilePathInfo& info)
{
	vector vx, vy;
	if( !ImageProfilerPath::GetPathPosition(info, vx, vy) )
		return false;

	// check set the width
	bool bWidthChange;
	_check_reset_rect_width(vx, vy, LTYPE_CROSSED_LINE_VERTICAL == info.m_nLineType, GetProfileWidth(IPROFILE_PATH_WIDTH_SCALE), bWidthChange);

	bool bPosModified;
	bool bRet = CheckPathPosition(info, vx, vy, &bPosModified);
	if( bRet && bPosModified || bWidthChange )
	{
		ImageProfilerPath::SetPathPosition(info, vx, vy);
	}

	return bRet;
}
///End CHECK_RESET_LINE_WIDTH_FOR_LOG_SCALE

bool ImageProfilerHVPath::CalculateProfileData(const ImageProfilePathInfo& info)
{
	ASSERT( GetPathType() == VERTICAL_LINE_IMAGE_PROFILE || GetPathType() == HORIZONTAL_LINE_IMAGE_PROFILE);

	///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	//DataPlot dp = info.m_glSource.DataPlots();
	/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	/*
	DataPlot dp = info.m_dpSource;
	///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	if( !dp )
		return false;
	*/
	DataPlot dp;
	if( !info.GetSourcePlot(dp) )
		return error_report("Fail to get source plot");
	///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	
	vector vxVertices, vyVertices;
	if( !GetPathPosition(info, vxVertices, vyVertices) )
		return false;
	
	bool bVertical = GetPathType() == VERTICAL_LINE_IMAGE_PROFILE;
	//if( bVertical )
	//	strComments.Format("X = %s", ftoa(vxVertices[0]));
	//else
	//	strComments.Format("Y = %s", ftoa(vyVertices[0]));
	
	vector vxOutput, vyOutput, vzOutput;
	//ImageProfileCalculator helper;
	//if( helper.CheckInitSource(dp) && helper.DoLineProfile(vxOutput, vyOutput, vzOutput, GetNumPoints(bVertical), vxVertices, vyVertices, m_dProfileWidth) )
	///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	//if( m_profileCalculator.CheckInitSource(dp) && m_profileCalculator.DoLineProfile(vxOutput, vyOutput, vzOutput, GetNumPoints(bVertical), vxVertices, vyVertices, m_dProfileWidth) )
	///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	//if( m_profileCalculator.CheckInitSource(dp) && m_profileCalculator.DoLineProfile(vxOutput, vyOutput, vzOutput, GetNumPoints(bVertical), vxVertices, vyVertices, m_dLineWidth) )
	int nWidthUnit = GetProfileWidthUnit();
	double dWidth = GetProfileWidth(nWidthUnit);
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//if( m_profileCalculator.CheckInitSource(dp) && m_profileCalculator.DoLineProfile(vxOutput, vyOutput, vzOutput, GetNumPoints(bVertical), vxVertices, vyVertices, dWidth, nWidthUnit) )
	if( m_pCalculator->CheckInitSource(dp) &&
		m_pCalculator->DoLineProfile(vxOutput, vyOutput, vzOutput, -1, vxVertices, vyVertices, dWidth, nWidthUnit) )
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	{
		XYRange xyOutput = info.m_drOutput;
		if( bVertical )
			xyOutput.SetData(&vzOutput, &vyOutput,  0, NULL, DRS_SET_COL_DESIGNATIONS);
		else
			xyOutput.SetData(&vzOutput, &vxOutput,  0, NULL, DRS_SET_COL_DESIGNATIONS);

		Column colY;
		if( xyOutput.GetYColumn(colY) && colY )
		{
			//string strComments;
			//string strFormat = bVertical ? _L("Vertical profile of %s") : _L("Horizontal profile of %s");
			//strComments.Format(strFormat, _get_data_plot_range_string(dp));
			//colY.SetComments(strComments);
			colY.SetComments(GetPathName());
			
			SetOutputWksParametersLabel(colY, vxOutput, vyOutput, bVertical);
			legend_update(info.m_glOutput);
		}
		return true;
	}

	return false;
}

///Kyle 06/18/2010 ORG-98 BETTER_AUTO_NUMBER_OF_POINTS_FOR_OUTPUT
/*
int ImageProfilerHVPath::GetPathNumPoints(const ImageProfilePathInfo& info, bool& bAuto)
{
	ASSERT( GetPathType() == VERTICAL_LINE_IMAGE_PROFILE || GetPathType() == HORIZONTAL_LINE_IMAGE_PROFILE);

	if( info.m_nNumPoints >= 2 )
	{
		bAuto = false;
		return info.m_nNumPoints;
	}
	bAuto = true;
	
	bool bVertical = (GetPathType() == VERTICAL_LINE_IMAGE_PROFILE);

	int nSize = 100;		// fixed

	DataPlot dpSrc;
	if( info.m_glSource )
		dpSrc = info.m_glSource.DataPlots();

	if( dpSrc )
	{
		int nRows, nCols;
		_find_dp_coordinates(dpSrc, nRows, nCols);
		nSize = bVertical ? nRows : nCols;
	}

	return nSize;
}
*/
///End BETTER_AUTO_NUMBER_OF_POINTS_FOR_OUTPUT

// virtual
bool ImageProfilerHVPath::SetOutputDepColComments(LPCSTR lpcszComments)
{
	ASSERT(1 == m_arrPathInfo.GetSize());
	if( m_arrPathInfo.GetSize() < 1 )
		return false;

	ImageProfilePathInfo& info = m_arrPathInfo.GetAt(0);		
	return SetOutputColComments(info, "Y", lpcszComments);	
}

///Kyle 06/21/2010 ORG-355 DISABLE_MOVE_LABEL_TEXT
///Kyle 07/20/2010 ORG-584-P2 NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
//bool ImageProfilerHVPath::InitPathFromTree(const TreeNode& trPath)
bool ImageProfilerHVPath::InitPathFromTree(const TreeNode& trPath, const GraphLayer& glSource)
///End NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
{
	///Kyle 07/20/2010 ORG-584-P2 NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
	//if( ImageProfilerPath::InitPathFromTree(trPath) )
	if( ImageProfilerPath::InitPathFromTree(trPath, glSource) )
	///End NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
	{
		for(int ii = m_arrPathInfo.GetSize() - 1; ii >= 0; ii--)
		{
			ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
			
			// disable movable and selectable for lines when close dialog. 
			// so need to cancel disable when reopen dialog.
			GraphObject goLine = info.GetLineObject();

			DWORD dwRemove = (GetPathType() == VERTICAL_LINE_IMAGE_PROFILE) ? GOC_NO_HMOVE : GOC_NO_VMOVE;
			dwRemove |= GOC_NO_SELECT | GOC_NO_BORDERSIZE;
			update_go_states(goLine, 0, dwRemove);
			
			GraphObject goText;
			if( GetReadOutObject(info, goText) && goText.IsValid() )
				update_go_states(goText, 0, dwRemove);
		}
		return true;
	}

	return false;
}
///End DISABLE_MOVE_LABEL_TEXT

///Kyle 07/01/2010 ORG-355-S7 OUTPUT_PROFILE_WIDTH
void ImageProfilerHVPath::UpdateOutputWidth()
{
	ASSERT(1 == m_arrPathInfo.GetSize());
	ImageProfilePathInfo& info = m_arrPathInfo.GetAt(0);

	Column colY;
	XYRange xyOutput = info.m_drOutput;
	if( xyOutput.IsValid() && xyOutput.GetYColumn(colY) && colY.IsValid() )
		SetOutputWidth(colY);
}
///End OUTPUT_PROFILE_WIDTH

/*----------------------------------------------------------------------------*/
/* ImageProfilerCrossLinePath
/*----------------------------------------------------------------------------*/
/*

bool ImageProfilerCrossLinePath::CheckSetProfileLayer(WorksheetPage& wpOutput, GraphLayer& glVertical, GraphLayer& glHorizontal)
{
	int nHIndex = 0,
		nVIndex = 1;

	if( nHIndex < 0 || nVIndex >= m_arrPathInfo.GetSize() )
		return false;

	ImageProfilePathInfo& hInfo = m_arrPathInfo.GetAt(nHIndex);
	ImageProfilePathInfo& vInfo = m_arrPathInfo.GetAt(nVIndex);

	if( !(hInfo.m_drOutput && vInfo.m_drOutput) )
	{
		Worksheet wksTemp;
		if( !FindOutputWks(wksTemp, wpOutput, hInfo) )
			return false;
		
		int nCols = 4;//XYXY
		if(wksTemp.GetNumCols() < nCols)
			wksTemp.SetSize(-1, nCols);
		wksTemp.SetColDesignations("XYXY");
		
		DataRange drH, drV;
		
		drH.Add(wksTemp, 0, "X");
		drH.Add(wksTemp, 1, "Y");

		drV.Add(wksTemp, 2, "X");
		drV.Add(wksTemp, 3, "Y");

		hInfo.m_drOutput = drH;
		vInfo.m_drOutput = drV;
	}

	
	//wksTemp.Columns(0).SetLongName("X");
	//wksTemp.Columns(2).SetLongName("Y");
	//if( GetPathType() == ARBITRARY_LINE_IMAGE_PROFILE )
	//{
	//	wksTemp.Columns(1).SetLongName("Arbitrary Profile");
	//	wksTemp.Columns(3).SetLongName("Arbitrary Profile");
	//}
	//else
	//{
	//	wksTemp.Columns(1).SetLongName("Horizontal Profile");
	//	wksTemp.Columns(3).SetLongName("Vertical Profile");
	//}

	//XYRange xyHResult, xyVResult;
	//
	//xyHResult.Add(wksTemp, 0, "X");
	//xyHResult.Add(wksTemp, 1, "Y");
	//hInfo.m_xyOutput = xyHResult;
	//
	//xyVResult.Add(wksTemp, 2, "X");
	//xyVResult.Add(wksTemp, 3, "Y");
	//vInfo.m_xyOutput = xyVResult;

	if( !vInfo.m_glOutput )
		vInfo.m_glOutput = glVertical;

	if( !hInfo.m_glOutput )
		hInfo.m_glOutput = glHorizontal;

	CheckPlotOutput(hInfo);
	CheckPlotOutput(vInfo);

	return true;
}

int ImageProfilerCrossLinePath::AddProfileLine(GraphLayer& glSource, int nColor, DWORD dwOption, const vector& vx, const vector& vy)
{
	if( GetNumProfileLines() > 0 )		// only one profile line allowed
		return -1;
	if( !glSource )
		return -1;

	ImageProfilePathInfo* pHInfo = new ImageProfilePathInfo;
	ImageProfilePathInfo* pVInfo = new ImageProfilePathInfo;
	if(!pHInfo || !pVInfo)
	{
		if( pHInfo )
			delete pHInfo;
		if( pVInfo )
			delete pVInfo;
		return -1;
	}

	ImageProfileHVLine hline, vline;
	if( !hline.Create(glSource, GetLineWidth(), nColor, false) || !vline.Create(glSource, GetLineWidth(), nColor, true) )		// only one profile line is allowed, so no need to enum the line color, SYSCOLOR_BLUE
	{
		delete pHInfo;
		delete pVInfo;
		
		if( hline.IsValid() )
			hline.Destroy();
		if( vline.IsValid() )
			vline.Destroy();

		return -1;
	}

	pHInfo->m_nLineType = CROSSED_LINE_HORIZONTAL;
	pHInfo->m_uObjUID = hline.GetUID(true);
	pHInfo->m_glSource = glSource;

	pVInfo->m_nLineType = CROSSED_LINE_VERTICAL;
	pVInfo->m_uObjUID = vline.GetUID(true);
	pVInfo->m_glSource = glSource;

	int nHIndex = m_arrPathInfo.Add(*pHInfo);
	int nVIndex = m_arrPathInfo.Add(*pVInfo);

	return nHIndex;
}

bool ImageProfilerCrossLinePath::RemovePathInfoAt(int nIndex, bool bRemoveOutput, bool bRemoveLine)
{
	return ImageProfilerPath::RemovePathInfoAt(nIndex, bRemoveOutput, bRemoveLine);
}

bool ImageProfilerCrossLinePath::GetPreviewRange(const ImageProfilePathInfo& info, XYRange& xyRange)
{
	if( !info.m_drOutput )
		return false;

	//if( info.m_nLineType == CROSSED_LINE_VERTICAL )
	//{
		//xyRange.Add(info.m_wksOutput, 2, "X");
		//xyRange.Add(info.m_wksOutput, 3, "Y");
	//}
	//else
	//{
		//xyRange.Add(info.m_wksOutput, 0, "X");
		//xyRange.Add(info.m_wksOutput, 1, "Y");
	//}

	xyRange = info.m_drOutput;

	return xyRange.IsValid();
}

bool ImageProfilerCrossLinePath::CalculateProfileData(const ImageProfilePathInfo& info)
{
	DataPlot dp = info.m_glSource.DataPlots();
	if( !dp )
		return false;

	vector vxVertices, vyVertices;
	if( !GetPathPosition(info, vxVertices, vyVertices) )
		return false;

	bool bVertical = info.m_nLineType == CROSSED_LINE_VERTICAL;
	//if( bVertical )
		//strComments.Format("X = %s", ftoa(vxVertices[0]));
	//else
		//strComments.Format("Y = %s", ftoa(vyVertices[0]));

	vector vxOutput, vyOutput, vzOutput;
	//ImageProfileCalculator helper;
	//if( helper.CheckInitSource(dp) && helper.DoLineProfile(vxOutput, vyOutput, vzOutput, GetNumPoints(bVertical), vxVertices, vyVertices, m_dProfileWidth) )
	if( m_profileCalculator.CheckInitSource(dp) && m_profileCalculator.DoLineProfile(vxOutput, vyOutput, vzOutput, GetNumPoints(bVertical), vxVertices, vyVertices, m_dProfileWidth) )
	{
		UpdateIntersect(vxOutput, vyOutput, vzOutput, bVertical);

		XYRange xyOutput = info.m_drOutput;
		if( bVertical )
			xyOutput.SetData(&vzOutput, &vyOutput);
		else
			xyOutput.SetData(&vzOutput, &vxOutput);
		
		Column colY;
		if( xyOutput.GetYColumn(colY) && colY )
		{
			string strComments;
			string strFormat = bVertical ? _L("Vertical profile of %s") : _L("Horizontal profile of %s");
			strComments.Format(strFormat, _get_data_plot_range_string(dp));
			colY.SetComments(strComments);
		}

		return true;
	}

	m_dIntersectZValue = NANUM;
	return false;
}

// virtual
int ImageProfilerCrossLinePath::GetPathNumPoints(const ImageProfilePathInfo& info, bool& bAuto)
{
	if( info.m_nNumPoints >= 2 )
	{
		bAuto = false;
		return info.m_nNumPoints;
	}
	bAuto = true;

	DataPlot dpSrc;
	if(info.m_glSource)
		dpSrc = info.m_glSource.DataPlots();

	if( dpSrc )
	{
		int nRows, nCols;
		_find_dp_coordinates(dpSrc, nRows, nCols);
		return (info.m_nLineType == CROSSED_LINE_VERTICAL) ? nRows : nCols;
	}

	ASSERT(0);
	return 100;
}

static double _find_intersect_value(const vector& vx, const vector& vy, double dXValue)
{
	double dYValue = NANUM;

	int nSize = vx.GetSize();

	int nNearestLeft, nNearestRight, nNearest;
	if( OE_NOERROR == ocmath_find_nearest_index(vx, nSize, dXValue, &nNearestLeft, &nNearestRight, &nNearest) )
	{
		dYValue = vy[nNearest];
	}
	else if( nNearestLeft >= 0 && nNearestLeft < nSize )
	{
		dYValue = vy[nNearestLeft];
	}
	else if( nNearestRight >= 0 && nNearestRight < nSize )
	{
		dYValue = vy[nNearestRight];
	}
	else
	{
		ASSERT(0);
	}

	return dYValue;
}

void ImageProfilerCrossLinePath::UpdateIntersect(const vector& vx, const vector& vy, const vector& vz, bool bVertical)
{
	m_dIntersectZValue = NANUM;

	const int nSize = vx.GetSize();
	if( nSize < 1 || vy.GetSize() != nSize )
		return;

	double dLine;
	if( GetLinePosition(dLine, !bVertical) )
	{
		//
		//vector vxIntersect(1), vyIntersect(1);
		//vxIntersect[0] = dLine;
		//if( OE_NOERROR == ocmath_interpolate(vxIntersect, vyIntersect, vyIntersect.GetSize(), vx, vy, vx.GetSize()) )
			//m_dIntersectZValue = vyIntersect[0];
		//
		//
		//int nNearestLeft, nNearestRight, nNearest;
		//if( OE_NOERROR == ocmath_find_nearest_index(vx, nSize, dLine, &nNearestLeft, &nNearestRight, &nNearest) )
		//{
			//m_dIntersectZValue = vy[nNearest];
		//}
		//else if( nNearestLeft >= 0 && nNearestLeft < nSize )
		//{
			//m_dIntersectZValue = vy[nNearestLeft];
		//}
		//else if( nNearestRight >= 0 && nNearestRight < nSize )
		//{
			//m_dIntersectZValue = vy[nNearestRight];
		//}
		//else
		//{
			//ASSERT(0);
		//}
		//
		m_dIntersectZValue = _find_intersect_value(bVertical ? vy : vx, vz, dLine);
	}
}

bool ImageProfilerCrossLinePath::GetLineIntersection(double& dZValue)
{
	if( GetNumProfileLines() <= 0 )
	{
		dZValue = NANUM;
		return false;
	}

	if( m_dIntersectZValue == NANUM )
	{
		string strComments;
		vector vx, vy, vz;
		int nIndex = GetLineIndex(true);
		if( nIndex >= 0 && nIndex < m_arrPathInfo.GetSize() )
		{
			ImageProfilePathInfo& info = m_arrPathInfo.GetAt(nIndex);
			CalculateProfileData(info);				// will update intersection
		}
	}

	dZValue = m_dIntersectZValue;
	return (dZValue != NANUM);
}
*/

/*----------------------------------------------------------------------------*/
/* ImageProfilerAbitraryLinePath
/*----------------------------------------------------------------------------*/

///Kyle 06/22/2010 ORG-355 CENTRALIZE_CODE_AND_CHANGE_CLASS_STRUCTURE
/*
#define ABITRARY_LINE_VERTICAL			1
#define ABITRARY_LINE_HORIZONTAL		2
*/
///End CENTRALIZE_CODE_AND_CHANGE_CLASS_STRUCTURE

bool ImageProfilerAbitraryLinePath::CheckSetProfileLayer(WorksheetPage& wpOutput, GraphLayer& glVertical, GraphLayer& glHorizontal)
{
	int nHIndex = 0,
		nVIndex = 1;
	if( nHIndex < 0 || nVIndex >= m_arrPathInfo.GetSize() )
		return false;

	ImageProfilePathInfo& hInfo = m_arrPathInfo.GetAt(nHIndex);
	ImageProfilePathInfo& vInfo = m_arrPathInfo.GetAt(nVIndex);

	if( !(hInfo.m_drOutput && vInfo.m_drOutput) )
	{
		Worksheet wksTemp;
		if( !FindOutputWks(wksTemp, wpOutput, hInfo) )
			return false;
		
		int nCols = 3;//X & Y & Z columns
		if(wksTemp.GetNumCols() < nCols)
			wksTemp.SetSize(-1, nCols);
		wksTemp.SetColDesignations("XYZ");
		
		///Kyle 07/01/2010 ORG-355-S7 OUTPUT_PROFILE_WIDTH
		vector<uint> vnLabels = {LABEL_PROFILE_WIDTH};
		vector<string> vsLabels(1);
		vsLabels[0] = _L("Width");
		PrepareUserDefinedLabels(wksTemp, vnLabels, vsLabels);
		///End OUTPUT_PROFILE_WIDTH
		
		DataRange drResult;
		drResult.Add(wksTemp, 0, "X");
		drResult.Add(wksTemp, 1, "Y");
		drResult.Add(wksTemp, 2, "Z");
		
		hInfo.m_drOutput = drResult;
		vInfo.m_drOutput = drResult;
		/// Iris 6/07/2010 ORG-98-P10 FIX_RENAME_TAB_UPDATED_INCORRECT_OUTPUT_COL_COMMENTS
		// if NOT add data range object to project, when delete one column will effect on data range
		// because data range remembered is column index.
		Project.AddDataRange(hInfo.m_drOutput);
		Project.AddDataRange(vInfo.m_drOutput);
		///End FIX_RENAME_TAB_UPDATED_INCORRECT_OUTPUT_COL_COMMENTS
		
		UpdateOutputWidth();		///Kyle 07/01/2010 ORG-355-S7 OUTPUT_PROFILE_WIDTH
	}
	
	
	//wksTemp.Columns(0).SetLongName("X");
	//wksTemp.Columns(2).SetLongName("Y");
	//if( GetPathType() == ARBITRARY_LINE_IMAGE_PROFILE )
	//{
	//	wksTemp.Columns(1).SetLongName("Arbitrary Profile");
	//	wksTemp.Columns(3).SetLongName("Arbitrary Profile");
	//}
	//else
	//{
	//	wksTemp.Columns(1).SetLongName("Horizontal Profile");
	//	wksTemp.Columns(3).SetLongName("Vertical Profile");
	//}

	//XYRange xyHResult, xyVResult;
	//
	//xyHResult.Add(wksTemp, 0, "X");
	//xyHResult.Add(wksTemp, 1, "Y");
	//hInfo.m_xyOutput = xyHResult;
	//
	//xyVResult.Add(wksTemp, 2, "X");
	//xyVResult.Add(wksTemp, 3, "Y");
	//vInfo.m_xyOutput = xyVResult;

	///Kyle 07/21/2010 OUTPUT_LAYER_MAY_CHANGE_AFTER_DUPLICATE_PROFILE_GRAPH
	/*
	if( !vInfo.m_glOutput )
		vInfo.m_glOutput = glVertical;
		
	if( !hInfo.m_glOutput )
		hInfo.m_glOutput = glHorizontal;
	*/
	vInfo.m_glOutput = glVertical;
	hInfo.m_glOutput = glHorizontal;
	///End OUTPUT_LAYER_MAY_CHANGE_AFTER_DUPLICATE_PROFILE_GRAPH

	CheckPlotOutput(hInfo);
	CheckPlotOutput(vInfo);

	return true;
}

int ImageProfilerAbitraryLinePath::AddProfileLine(GraphLayer& glSource, int nColor, DWORD dwOption, const vector& vx, const vector& vy)
{
	if( !glSource )
		return -1;
	///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	DataPlot dpSource = glSource.DataPlots();
	if( !is_good_plot_for_profile(dpSource) )
		return -1;
	///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED

	ImageProfilePathInfo* pHInfo = new ImageProfilePathInfo;
	ImageProfilePathInfo* pVInfo = new ImageProfilePathInfo;
	if(!(pHInfo && pVInfo) )
	{
		if( pHInfo )
			delete pHInfo;
		if( pVInfo )
			delete pVInfo;
		return -1;
	}

	ImageProfileAbitraryLine profileline;
	///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE, line width means nothing here
	//if( !profileline.Create(glSource, GetLineWidth(), nColor) )
	if( !profileline.Create(glSource, 1, nColor) )
	///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	{
		delete pHInfo;
		delete pVInfo;
		return -1;
	}

	pHInfo->m_uObjUID = profileline.GetUID(true);
	pHInfo->m_glSource = glSource;
	/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	//pHInfo->m_dpSource = dpSource;		///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	pHInfo->m_uSourcePlot = dpSource.GetUID(true);
	///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	pHInfo->m_nLineType = LTYPE_ABITRARY_LINE_HORIZONTAL;

	pVInfo->m_uObjUID = profileline.GetUID(true);
	pVInfo->m_glSource = glSource;
	/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	//pVInfo->m_dpSource = dpSource;		///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	pVInfo->m_uSourcePlot = dpSource.GetUID(true);
	///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	pVInfo->m_nLineType = LTYPE_ABITRARY_LINE_VERTICAL;

	int nHIndex = m_arrPathInfo.Add(*pHInfo);
	int nVIndex = m_arrPathInfo.Add(*pVInfo);

	return nHIndex;
}

///Kyle 06/22/2010 ORG-355 CENTRALIZE_CODE_AND_CHANGE_CLASS_STRUCTURE
/*
bool ImageProfilerAbitraryLinePath::RemovePathInfoAt(int nIndex, bool bRemoveOutput, bool bRemoveLine)
{
	return ImageProfilerPath::RemovePathInfoAt(nIndex, bRemoveOutput, bRemoveLine);
}
*/
///End CENTRALIZE_CODE_AND_CHANGE_CLASS_STRUCTURE

bool ImageProfilerAbitraryLinePath::GetPreviewRange(const ImageProfilePathInfo& info, XYRange& xyRange)
{
	if( !info.m_drOutput )
		return false;

	int r1, c1, r2, c2;
	Worksheet wks;
	if( info.m_drOutput.GetRange("Z", r1, c1, r2, c2, wks) >= 0 && wks.IsValid() )
	{
		if( info.m_nLineType == LTYPE_ABITRARY_LINE_VERTICAL )
		{
			xyRange.Add(wks, 1, "X");
			xyRange.Add(wks, 2, "Y");
		}
		else
		{
			xyRange.Add(wks, 0, "X");
			xyRange.Add(wks, 2, "Y");
		}
	}

	return xyRange.IsValid();
}

bool ImageProfilerAbitraryLinePath::CalculateProfileData(const ImageProfilePathInfo& info)
{
	vector vxVertices, vyVertices;
	if( !GetPathPosition(info, vxVertices, vyVertices) )
		return false;

	bool bVertical = info.m_nLineType == LTYPE_ABITRARY_LINE_VERTICAL;
	//strComments.Format("X1 = %s, Y1 = %s, X2 = %s, Y2 = %s", ftoa(vxVertices[0]), ftoa(vyVertices[0]), ftoa(vxVertices[1]), ftoa(vyVertices[1]));

	vector vxOutput, vyOutput, vzOutput;
		
	///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	//DataPlot dp = info.m_glSource.DataPlots();
	/// Iris 6/21/2010 ORG-355-P2 FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	//DataPlot dp = info.m_dpSource;
	DataPlot dp;
	if( !info.GetSourcePlot(dp) )
		return error_report("Fail to get source plot");
	///End FIX_AFTER_CHANGE_LAYER_BACKGROUND_COLOR_MOVING_PROFILE_LINE_INVALID
	///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	
	//ImageProfileCalculator helper;
	//if( helper.CheckInitSource(dp) && helper.DoLineProfile(vxOutput, vyOutput, vzOutput, GetNumPoints(bVertical), vxVertices, vyVertices, m_dProfileWidth) )
	///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	//if( m_profileCalculator.CheckInitSource(dp) && m_profileCalculator.DoLineProfile(vxOutput, vyOutput, vzOutput, GetNumPoints(bVertical), vxVertices, vyVertices, m_dProfileWidth) )
	///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	//if( m_profileCalculator.CheckInitSource(dp) && m_profileCalculator.DoLineProfile(vxOutput, vyOutput, vzOutput, GetNumPoints(bVertical), vxVertices, vyVertices, m_dLineWidth) )
	int nWidthUnit = GetProfileWidthUnit();
	double dWidth = GetProfileWidth(nWidthUnit);
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//if( m_profileCalculator.CheckInitSource(dp) && m_profileCalculator.DoLineProfile(vxOutput, vyOutput, vzOutput, GetNumPoints(bVertical), vxVertices, vyVertices, dWidth, nWidthUnit) )
	if( m_pCalculator->CheckInitSource(dp) &&
		m_pCalculator->DoLineProfile(vxOutput, vyOutput, vzOutput, -1, vxVertices, vyVertices, dWidth, nWidthUnit) )
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
	///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
	{
		XYZRange xyzOutput = info.m_drOutput;
		xyzOutput.SetData(&vzOutput, &vyOutput, &vxOutput);
		
		int r1, c1, r2, c2;
		Worksheet wks;
		if( xyzOutput.GetRange("Z", r1, c1, r2, c2, wks) >= 0 && wks.IsValid() )
		{
			ASSERT(c1 == c2);
			Column colZ(wks, c1);

			//string strComments;
			//strComments.Format(_L("Arbitrary profile of %s"), _get_data_plot_range_string(dp));
			//colZ.SetComments(strComments);
			colZ.SetComments(GetPathName());
			
			SetOutputWksParametersLabel(colZ, vxOutput, vyOutput, bVertical);
			legend_update(info.m_glOutput);
		}

		return true;
	}

	return false;
}

///Kyle 06/18/2010 ORG-98 BETTER_AUTO_NUMBER_OF_POINTS_FOR_OUTPUT
/*
int ImageProfilerAbitraryLinePath::GetPathNumPoints(const ImageProfilePathInfo& info, bool& bAuto)
{
	if( info.m_nNumPoints >= 2 )
	{
		bAuto = false;
		return info.m_nNumPoints;
	}
	bAuto = true;

	int nSize = 100;		// fixed

	DataPlot dpSrc;
	if( info.m_glSource )
		dpSrc = info.m_glSource.DataPlots();

	if( dpSrc )
	{
		int nRows, nCols;
		_find_dp_coordinates(dpSrc, nRows, nCols);
		nSize = nRows > nCols ? nRows : nCols;
	}
	
	return nSize;
}
*/
///End BETTER_AUTO_NUMBER_OF_POINTS_FOR_OUTPUT

int ImageProfilerAbitraryLinePath::OnProfileEvent(int nEvent, UINT uObjUID)
{
	if( nEvent == OE_STYLE_CHANGE )
		return ImageProfilerPath::OnProfileEvent(nEvent, uObjUID);

	int nIndex = GetPathInfoIndex(uObjUID);
	if( nIndex < 0 || nIndex >= m_arrPathInfo.GetSize() )
		///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING
		//return -1;
		return IPUPDATE_NO_CHANGE;
		///End CENTRALIZE_EVENT_HANDLING

	int nHIndex, nVIndex;
	if( nIndex % 2 )
	{
		nHIndex = nIndex - 1;
		nVIndex = nIndex;
	}
	else
	{
		nHIndex = nIndex;
		nVIndex = nIndex + 1;
	}
	
	///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING
	if( OE_SCALE_CHANGE == nEvent )
	{
		GraphObject goLine; goLine = (GraphObject)Project.GetObject(uObjUID);
		if( !goLine )
		{
			ASSERT(0);
			return IPUPDATE_NO_CHANGE;
		}
		
		ImageProfilePathInfo& vInfo = m_arrPathInfo.GetAt(nVIndex);
		ImageProfilePathInfo& hInfo = m_arrPathInfo.GetAt(nHIndex);
		ASSERT(	vInfo.GetLineObject() && vInfo.GetLineObject().GetUID()==uObjUID );
		ASSERT( hInfo.GetLineObject() && hInfo.GetLineObject().GetUID()==uObjUID );
		ASSERT( is_same_layer(vInfo.m_glSource, hInfo.m_glSource) );

		// after source layer scale changed, need to copy scale settings to profile layers
		// SC, SV, and SH mode no need do this, since dest layer has linked to source layer.
		int nParentLayer;
		if( (layer_get_link(vInfo.m_glOutput, nParentLayer) && nParentLayer < 0) &&
			(layer_get_link(hInfo.m_glOutput, nParentLayer) && nParentLayer < 0) ) // nParentLayer<0 means no link
		{
			_copy_axis_tick_label_scale(vInfo.m_glSource.YAxis, vInfo.m_glOutput.XAxis);
			_copy_axis_tick_label_scale(hInfo.m_glSource.XAxis, hInfo.m_glOutput.XAxis);
		}

		// need force to refresh layer and object since the position of the object maybe not updated
		vInfo.m_glSource.Invalidate(true);
		goLine.Invalidate(true);
	}
	///End CENTRALIZE_EVENT_HANDLING

	if( DoProfile(nHIndex) && DoProfile(nVIndex) )
		///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING
		//return nIndex;
		///Kyle 06/17/2010 ORG-98 ADD_DIRTY_BITS_FOR_GUI_UPDATE
		//return IPUPDATE_PATH_CONTENT;
		return IPUPDATE_PATH_CONTENT_POSITION;
		///End ADD_DIRTY_BITS_FOR_GUI_UPDATE
		///End CENTRALIZE_EVENT_HANDLING

	///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING
	//return -1;
	return IPUPDATE_NO_CHANGE;
	///End CENTRALIZE_EVENT_HANDLING
}

///Kyle 06/22/2010 ORG-355 CENTRALIZE_CODE_AND_CHANGE_CLASS_STRUCTURE
/*
bool ImageProfilerAbitraryLinePath::SetLinePosition(const vector& vx, const vector& vy, bool bVertical)
{
	return ImageProfilerPath::SetLinePosition(vx, vy, bVertical);
}

bool ImageProfilerAbitraryLinePath::GetLinePosition(vector& vx, vector& vy, bool bVertical)
{
	return ImageProfilerPath::GetLinePosition(vx, vy, bVertical);
}
*/
///End CENTRALIZE_CODE_AND_CHANGE_CLASS_STRUCTURE

bool ImageProfilerAbitraryLinePath::CheckLinePosition(const vector& vx, const vector& vy, bool bVertical)
{
	if( !(vx && vy && vx.GetSize()==2 && vy.GetSize()==2) )
		return false;

	return true;
}

///Kyle 06/22/2010 ORG-355 CENTRALIZE_CODE_AND_CHANGE_CLASS_STRUCTURE
/*
bool ImageProfilerAbitraryLinePath::SetPathColor(const ImageProfilePathInfo& info, int nColor)
{
	return ImageProfilerPath::SetPathColor(info, nColor);
}

int ImageProfilerAbitraryLinePath::GetPathColor(const ImageProfilePathInfo& info)
{
	return ImageProfilerPath::GetPathColor(info);
}

bool ImageProfilerAbitraryLinePath::SetPathPosition(const ImageProfilePathInfo& info, const vector& vx, const vector& vy)
{
	return ImageProfilerPath::SetPathPosition(info, vx, vy);
}

bool ImageProfilerAbitraryLinePath::GetPathPosition(const ImageProfilePathInfo& info, vector& vx, vector& vy)
{
	return ImageProfilerPath::GetPathPosition(info, vx, vy);
}

bool ImageProfilerAbitraryLinePath::SetPathWidth(const ImageProfilePathInfo& info, double dLineWidth)
{
	return ImageProfilerPath::SetPathWidth(info, dLineWidth);
}

double ImageProfilerAbitraryLinePath::GetPathWidth(const ImageProfilePathInfo& info)
{
	return ImageProfilerPath::GetPathWidth(info);
}
*/
///End CENTRALIZE_CODE_AND_CHANGE_CLASS_STRUCTURE

int ImageProfilerAbitraryLinePath::GetLineIndex(bool bVertical)
{
	for(int ii = 0; ii < m_arrPathInfo.GetSize(); ii++)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		if( (bVertical && info.m_nLineType == LTYPE_ABITRARY_LINE_VERTICAL) || (!bVertical && info.m_nLineType == LTYPE_ABITRARY_LINE_HORIZONTAL) )
			return ii;
	}

	return -1;
}

// virtual
bool ImageProfilerAbitraryLinePath::SetNumPoints(int nPoints, bool bVertical)
{
	if( m_arrPathInfo.GetSize() <= 0 )
		return -1;

	if( nPoints < 0 )
		nPoints = -1;						// auto

	if( nPoints >= 0 && nPoints < 2 )		// no auto, wrong value
		return false;

	for(int ii = m_arrPathInfo.GetSize()-1; ii >= 0; ii--)
	{
		ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
		info.m_nNumPoints = nPoints;

		//DoProfile(ii);
	}

	return true;

}

///Kyle 06/21/2010 ORG-355 DISABLE_MOVE_LABEL_TEXT
///Kyle 07/20/2010 ORG-584-P2 NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
//bool ImageProfilerAbitraryLinePath::InitPathFromTree(const TreeNode& trPath)
bool ImageProfilerAbitraryLinePath::InitPathFromTree(const TreeNode& trPath, const GraphLayer& glSource)
///End NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
{
	///Kyle 07/20/2010 ORG-584-P2 NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
	//if( ImageProfilerPath::InitPathFromTree(trPath) )
	if( ImageProfilerPath::InitPathFromTree(trPath, glSource) )
	///End NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
	{
		for(int ii = m_arrPathInfo.GetSize() - 1; ii >= 0; ii--)
		{
			ImageProfilePathInfo& info = m_arrPathInfo.GetAt(ii);
			
			// disable movable and selectable for lines when close dialog. 
			// so need to cancel disable when reopen dialog.
			GraphObject goLine = info.GetLineObject();
			update_go_states(goLine, 0, GOC_NO_SELECT | GOC_NO_MOVE | GOC_NO_EDIT | GOC_NO_BORDERSIZE);
		}
		return true;
	}

	return false;
}
///End DISABLE_MOVE_LABEL_TEXT

///Kyle 07/01/2010 ORG-355-S7 OUTPUT_PROFILE_WIDTH
void ImageProfilerAbitraryLinePath::UpdateOutputWidth()
{
	ASSERT( m_arrPathInfo.GetSize() > 0 );
	ImageProfilePathInfo& info = m_arrPathInfo.GetAt(0);
	
	XYZRange xyzOutput = info.m_drOutput;
	int r1, c1, r2, c2;
	Worksheet wks;
	if( xyzOutput.GetRange("Z", r1, c1, r2, c2, wks) >= 0 && wks.IsValid() )
	{
		ASSERT(c1 == c2);
		Column colZ(wks, c1);
		SetOutputWidth(colZ);
	}
}
///End OUTPUT_PROFILE_WIDTH


/*----------------------------------------------------------------------------*/
/* ImageProfileManager
/*----------------------------------------------------------------------------*/

///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
//ImageProfileManager::ImageProfileManager(GraphPage& gpSource, int nLayoutMode, DWORD dwOptions)
ImageProfileManager::ImageProfileManager(GraphLayer& glSource, int nLayoutMode, DWORD dwOptions)
///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
{
	m_arrProfilePath.SetAsOwner(TRUE);

	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//ASSERT(gpSource);
	//m_gpSource = gpSource;
	//set_gp_noclick(m_gpSource, NOCLICK_DATA_PLOT | NOCLICK_LAYER | NOCLICK_LAYERICON);				// set source page no click
	ASSERT(glSource);
	m_glSource = glSource;
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP

	m_nActivePath = -1;

	m_dwOptions = dwOptions;
	if( m_dwOptions & IPROFILE_PROTECT_SOURCE )
		nLayoutMode = IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH;

	m_nLayoutMode = -1;
	SetLayoutMode(nLayoutMode);
	
	m_bIsReady = false;
}

ImageProfileManager::~ImageProfileManager()
{
	int nNumProfilePaths = GetNumProfilePaths();
	ClearProfilePath(true);

	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//ASSERT(m_gpSource);
	ASSERT(m_glSource);
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP

	bool bAddReadOpenBtn = false;
	if( !IsKeepGraphsOnClosing() )
	{
		if( !(m_dwOptions & IPROFILE_PROTECT_SOURCE) ) // when the source window is not graph when open profile dialog
		{
			///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			//m_gpSource.Destroy();
			GraphPage gp = m_glSource.GetPage();
			ASSERT(gp);
			gp.Destroy();
			///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		}
	}
	else if( m_bIsReady )
	{
		if( nNumProfilePaths > 0 )
			bAddReadOpenBtn = true;
	}

	if(bAddReadOpenBtn)
		addReopenTextButton(true, true);
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//else if( m_gpSource )
	else if( m_glSource )
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	{
		GraphObject goText;
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//GraphLayer glSource = m_gpSource.Layers(GRAPH_SOURCE_LAYER);
		//if( glSource )
		//	goText =  glSource.GraphObjects(STR_REOPEN_TEXT_BOX_NAME);
		goText = m_glSource.GraphObjects(STR_REOPEN_TEXT_BOX_NAME);
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		if( goText.IsValid() )
			goText.Destroy();
	}

	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP, do this in holder
	//if(m_gpSource)
	//	set_gp_noclick(m_gpSource, NOCLICK_USE_DEFAULT);				// reset source page no click
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
}

///Kyle 07/14/2010 ORG-572-P1 SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE
GraphPage	ImageProfileManager::GetSourcePage()
{
	GraphPage gp;
	if(m_glSource)
		gp = m_glSource.GetPage();
	return gp;
}
///End SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE

bool	ImageProfileManager::IsRelatedLayer(const GraphLayer& gl)
{
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	ASSERT(m_glSource);
	if( !m_glSource )
		return false;

	if( !gl )
		return false;
	if( is_same_layer(gl, m_glSource) )
		return true;

	if( GetLayoutMode() != IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH )
	{
		GraphPage gpSource = m_glSource.GetPage();
		if( gpSource.GetUID(TRUE) == gl.GetPage().GetUID() )
			return true;
	}
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	for(int nIndex = m_arrProfilePath.GetSize()-1; nIndex >= 0; nIndex--)
	{
		ImageProfilerPath* pPath = GetProfilePath(nIndex);
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//if( pPath->IsRelatedLayer(gl) )
		if( pPath->IsRelatedLayer(gl, false) )
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			return true;
	}
	return false;
}

void	ImageProfileManager::ClearProfilePath(bool bOnDestroy)
{
	/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
	//Cancel text object the active status when dialog close
	ImageProfilerPath* pPath = GetProfilePath(GetActivePath());	
	if( pPath && (VERTICAL_LINE_IMAGE_PROFILE==pPath->GetPathType() || HORIZONTAL_LINE_IMAGE_PROFILE==pPath->GetPathType()) )
	{
		ImageProfilerHVPath* pHVPath = (ImageProfilerHVPath*)pPath;		
		pHVPath->SetReadOutActive(false);
	}
	///End NEW_SUGGESTION_FOR_TEXT_OBJECT
	
	if( !IsKeepGraphsOnClosing() )
	{
		///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
		//ClearStorage();
		clearAllStorage();
		///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	}

	for(int nIndex = m_arrProfilePath.GetSize()-1; nIndex >= 0; nIndex--)
	{
		if(bOnDestroy)
		{
			ImageProfilerPath* pPath = GetProfilePath(nIndex);
			ASSERT( FALSE == pPath->IsKeepOutput() );

			pPath->SetKeepOutput( IsKeepGraphsOnClosing() );
		}
		RemovePathAt(nIndex);
	}
}

///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
void	ImageProfileManager::removeInvalidProfilePath(int nOldLayoutMode, int nNewLayoutMode, vector<int>& vnDeletedPathIndeces)
{
	int nNumDel = 0;	
	for(int index = 0; index < m_arrProfilePath.GetSize();)
	{
		ImageProfilerPath* pPath = GetProfilePath(index);
		ASSERT(pPath);
		
		//if( !CanAddProfilePath(pPath->m_nPathType) )
		if( !checkProfilePathTypeWithLayoutMode(nNewLayoutMode, pPath->m_nPathType) )
		{
			pPath->SetKeepOutput(false);			
			RemovePathAt(index);
			
			int nOriginalIndex = index + nNumDel;
			vnDeletedPathIndeces.Add(nOriginalIndex);
			nNumDel++;
		}
		else
			index++;
	}
	clearStorages(vnDeletedPathIndeces);
}
///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS

int		ImageProfileManager::GetLayoutMode()
{
	return m_nLayoutMode;
}

///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
//bool	ImageProfileManager::SetLayoutMode(int nMode)
bool	ImageProfileManager::SetLayoutMode(int nMode, vector<int>* pvnDeletedPathIndeces, vector<int>* pnPathTypes)
///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
{
	if( nMode==m_nLayoutMode || !CanSwitchLayoutModeTo(nMode) )
		return false;
	/*
	m_nLayoutMode = nMode;

	if( GetNumProfilePaths() < 1 )
		return true;	// nothing to do

	if( m_gpSource )
	{
		Tree trStorage;
		if( m_gpSource.GetBinaryStorage(STR_IMAGE_PROFILE_STORAGE, trStorage) )
		{
			trStorage.LayoutMode.nVal = m_nLayoutMode;
			m_gpSource.PutBinaryStorage(STR_IMAGE_PROFILE_STORAGE, trStorage);
		}
	}

	for( int nIndex = 0; nIndex < m_arrProfilePath.GetSize(); nIndex++)
	{
		ImageProfilerPath* pPath = GetProfilePath(nIndex);
		pPath->DestroyOutputGraph();

		// switch from same graph to separate graph
		if( m_nLayoutMode == IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH )
		{
			GraphLayer glSrc = pPath->GetSourceLayer();
			if( glSrc )
				page_arrange_profile_layer(m_gpSource, glSrc.GetIndex());
		}
	}

	for(nIndex = 0; nIndex < m_arrProfilePath.GetSize(); nIndex++)
	{
		CheckSetProfileLayer(nIndex);
		ImageProfilerPath* pPath = GetProfilePath(nIndex);
		pPath->RefreshProfilePath(false, true);
	}
	*/
	///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	/*
	ClearProfilePath(false);		// clear all profile path, including output graph and worksheet

	m_nLayoutMode = nMode;
	ReloadTemplate();
	*/
	
	if( pvnDeletedPathIndeces )
		removeInvalidProfilePath(m_nLayoutMode, nMode, *pvnDeletedPathIndeces);
	
	int nOldLayoutMode = m_nLayoutMode;
	m_nLayoutMode = nMode;
	
	Tree tr;
	if( pvnDeletedPathIndeces )
	{
		bool bRemoveOutputGraph = nOldLayoutMode==IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH;			///Kyle 06/21/2010 ORG-98-P23 REMOVE_OUTPUT_GRAPH_WHEN_SWITCH_LAYOUT_MODE_FROM_SEPARATE_GRAPH
		for(int index  = 0; index < m_arrProfilePath.GetSize(); index++)
		{
			ImageProfilerPath* pPath = GetProfilePath(index);
			///Kyle 06/21/2010 ORG-98-P23 REMOVE_OUTPUT_GRAPH_WHEN_SWITCH_LAYOUT_MODE_FROM_SEPARATE_GRAPH
			if( bRemoveOutputGraph )
				pPath->DestroyOutputGraph();
			///End REMOVE_OUTPUT_GRAPH_WHEN_SWITCH_LAYOUT_MODE_FROM_SEPARATE_GRAPH
				
			TreeNode trPath = tr.AddNode("Path" + (string)index);
			pPath->BackupProfileLineFormatSettings(trPath);
			
			if( pnPathTypes )
				pnPathTypes->Add(pPath->GetPathType());
		}
	}
	else
	{
		ClearProfilePath(false);
	}

	ReloadTemplate();
	
	if( pvnDeletedPathIndeces )
	{
		for(int index  = 0; index < m_arrProfilePath.GetSize(); index++)
		{
			ImageProfilerPath* pPath = GetProfilePath(index);

			pPath->SetRemoveGraphIfEmpty(IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH == m_nLayoutMode);		///Kyle 06/22/2010 ORG-355-P6 REMOVE_OUTPUT_GRAPH_IF_EMPTY_ON_SEP_MODE

			CheckSetProfileLayer(index);

			TreeNode trPath = tr.GetNode("Path" + (string)index);
			ASSERT(trPath);
			pPath->AddBackProfileLines(trPath);
		}
	}
	///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS

	SaveToStorage();

	return true;
}

bool	ImageProfileManager::CanSwitchLayoutModeTo(int nMode)
{
	if( IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH==nMode )
		return true;

	for(int ii = m_arrProfilePath.GetSize() - 1; ii >= 0; ii--)
	{
		ImageProfilerPath* pPath = GetProfilePath(ii);
		if( pPath && pPath->GetPathType()==POLYLINE_IMAGE_PROFILE )
			return false;
	}

	return true;
}

int		ImageProfileManager::GetActivePath()
{
	return m_nActivePath;
}

///Kyle 06/11/2010 ORG-98-P13 NO_NEED_TO_BEING_OBJECT_TO_FRONT_ON_SELECT_OBJECT
//bool	ImageProfileManager::SetActivePath(int nPath)
bool	ImageProfileManager::SetActivePath(int nPath, bool bBringObjToFront)
///End NO_NEED_TO_BEING_OBJECT_TO_FRONT_ON_SELECT_OBJECT
{
	if( nPath >= 0 && nPath < GetNumProfilePaths() )
	{
		if( m_nActivePath != nPath )
		{
			m_nActivePath = nPath;
			
			for(int ii = 0; ii < GetNumProfilePaths(); ii++)
			{
				ImageProfilerPath* pPath = GetProfilePath(ii);
				if( VERTICAL_LINE_IMAGE_PROFILE==pPath->GetPathType() || HORIZONTAL_LINE_IMAGE_PROFILE==pPath->GetPathType() )
				{
					ImageProfilerHVPath* pHVPath = (ImageProfilerHVPath*)pPath;
					/// Iris 6/12/2010 ORG-98-S39 NEW_SUGGESTION_FOR_TEXT_OBJECT
					//pHVPath->UpdateReadOutText(ii == m_nActivePath);
					pHVPath->SetReadOutActive(ii == m_nActivePath);
					///End NEW_SUGGESTION_FOR_TEXT_OBJECT
				}
			}

			///Kyle 06/11/2010 ORG-98-P13 NO_NEED_TO_BEING_OBJECT_TO_FRONT_ON_SELECT_OBJECT
			if( bBringObjToFront )
			///End NO_NEED_TO_BEING_OBJECT_TO_FRONT_ON_SELECT_OBJECT
			{
				ImageProfilerPath* pActivePath = GetProfilePath(m_nActivePath);
				if( pActivePath )
				{
					pActivePath->BringObjToFront();
				}
			}
		}
		return true;
	}
	return false;
}

bool	ImageProfileManager::SetPathName(int nPath, LPCSTR lpcszPathName)
{
	ImageProfilerPath* pPath = GetProfilePath(nPath);
	if( pPath )
	{
		pPath->SetPathName(lpcszPathName);
		SaveToStorage();		// temp
		return true;
	}
	return false;
}

///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
/*
///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
//bool	ImageProfileManager::SetProfileWidth(int nPath, double dProfileWidth)
bool	ImageProfileManager::SetLineWidth(int nPath, double dLineWidth)
///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
{
	ImageProfilerPath* pPath = GetProfilePath(nPath);
	if( pPath )
	{
		///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
		//pPath->SetProfileWidth(dProfileWidth);
		//SaveToStorage();		// temp
		if( pPath->SetLineWidth(dLineWidth) )
		{
			SaveToStorage();		// temp
			return true;
		}
		///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH

		///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH, no need to update path here, OE_MOVE posted
		//CheckSetProfileLayer(nPath);
		//pPath->RefreshProfilePath(true, false);
		///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH

		//return true;
	}
	return false;
}
*/
bool	ImageProfileManager::SetProfileWidth(int nPath, double dWidth, int nUnit)
{
	ImageProfilerPath* pPath = GetProfilePath(nPath);
	if( pPath )
	{
		if( pPath->SetProfileWidth(dWidth, nUnit) )
		{
			SaveToStorage();		// temp
			return true;
		}
	}
	return false;
}
///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE

bool	ImageProfileManager::SetNumPoints(int nPoints, int nPath, bool bVertical)
{
	ImageProfilerPath* pPath = GetProfilePath(nPath);
	if( pPath )
	{
		if( pPath->SetNumPoints(nPoints, bVertical) )
		{
			SaveToStorage();		// temp
			
			CheckSetProfileLayer(nPath);
			pPath->RefreshProfilePath(true, false);

			return true;
		}
	}
	return false;
}

bool	ImageProfileManager::OnDeleteSrcPage()
{
	///Kyle 07/20/2010 ORG-584-P3 CRACH_WHEN_DEL_PAGE_ON_DELETE_GRAPH_AND_DATA_UPON_CLOSING_CHECKED
	SetKeepGraphsOnClosing(true);		// will try to delete the page in destructor if false
	///End CRACH_WHEN_DEL_PAGE_ON_DELETE_GRAPH_AND_DATA_UPON_CLOSING_CHECKED

	///Kyle 06/22/2010 ORG-355-P6 REMOVE_OUTPUT_GRAPH_IF_EMPTY_ON_SEP_MODE
	//bool bRemoveIfEmpty = (IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH == m_nLayoutMode);			///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	///End REMOVE_OUTPUT_GRAPH_IF_EMPTY_ON_SEP_MODE
	for(int ii = m_arrProfilePath.GetSize()-1; ii >= 0; ii--)
	{
		ImageProfilerPath* pPath = GetProfilePath(ii);
		///Kyle 06/22/2010 ORG-355-P6 REMOVE_OUTPUT_GRAPH_IF_EMPTY_ON_SEP_MODE
		//pPath->SetRemoveGraphIfEmpty(bRemoveIfEmpty);					///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		ASSERT( (IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH == m_nLayoutMode) == pPath->IsRemoveGraphIfEmpty() );
		///End REMOVE_OUTPUT_GRAPH_IF_EMPTY_ON_SEP_MODE
		pPath->OnDeleteSrcLayer();
		RemovePathAt(ii);
	}
	return true;
}

int		ImageProfileManager::OnDeleteProfileLine(UINT uObjUID)
{
	int nIndex = GetPathIndex(uObjUID);
	if( nIndex >= 0 )
	{
		ImageProfilerPath* pPath = GetProfilePath(nIndex);
		ASSERT( (IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH == m_nLayoutMode) == pPath->IsRemoveGraphIfEmpty() );			///Kyle 06/22/2010 ORG-355-P6 REMOVE_OUTPUT_GRAPH_IF_EMPTY_ON_SEP_MODE
		pPath->OnDeleteProfileLine(uObjUID);
		if( pPath->IsPathEmpty() )
			RemovePathAt(nIndex);

		SaveToStorage();
	}
	return nIndex;
}

int		ImageProfileManager::OnProfileEvent(int nEvent, UINT uObjUID, int* pnPath)
{
	///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING
	/*
	int nIndex = GetPathIndex(uObjUID);
	if( nIndex >= 0 )
	{
		CheckSetProfileLayer(nIndex);
		ImageProfilerPath* pPath = GetProfilePath(nIndex);
		pPath->OnProfileEvent(nEvent, uObjUID);
	}

	return nIndex;
	*/
	int nPath = GetPathIndex(uObjUID);
	if( pnPath )
		*pnPath = nPath;

	if( nPath < 0 || nPath >= GetNumProfilePaths() )
		return IPUPDATE_NO_CHANGE;

	int nUpdate = IPUPDATE_NO_CHANGE;
	switch( nEvent )
	{
	case OE_WIN_CLOSE:
		OnDeleteSrcPage();
		nUpdate = IPUPDATE_PROFILE_DELETED;
		break;

	case OE_SELECT:
		if( nPath != GetActivePath() )
		{
			SetActivePath(nPath);
			nUpdate = IPUPDATE_ACTIVE_PATH_CHANGE;
		}
		break;
		
	case OE_DELETE:
		{
			int nActivePath = GetActivePath();
			int nNumPaths = GetNumProfilePaths();
			int nPathChanged = OnDeleteProfileLine(uObjUID);
	
			ASSERT(nActivePath < 0 || nActivePath == nPathChanged);

			if( GetNumProfilePaths() < nNumPaths )
			{
				if( nPathChanged <= nActivePath )
				{
					nActivePath--;
					if(nActivePath < 0)
						nActivePath = 0;
					SetActivePath(nActivePath);
				}
				nUpdate = IPUPDATE_ACTIVE_PROFILE_CHANGE;		// force to update dlg, remove some tab in gui
			}
			else
			{
				ASSERT(0);		// group profile paths, to do
				if( nActivePath == nPathChanged )
					nUpdate = IPUPDATE_ACTIVE_PATH_CHANGE;
			}
		}
		break;

	case OE_MOVE:
	case OE_SCALE_CHANGE:
	case OE_GRAPHOBJ_EDIT:
	case OE_DELETE_PART:
	case OE_STYLE_CHANGE:
		{
			CheckSetProfileLayer(nPath);
			ImageProfilerPath* pPath = GetProfilePath(nPath);
			nUpdate = pPath->OnProfileEvent(nEvent, uObjUID);
		}
		break;
	}

	return nUpdate;
	///End CENTRALIZE_EVENT_HANDLING
}

int		ImageProfileManager::OnReadOutEvent(int nEvent, UINT uObjUID, int* pnPath)
{
	if( nEvent != OE_SELECT )			// only take care of select event for now
		return IPUPDATE_NO_CHANGE;

	int nPath = -1;
	for(int ii = m_arrProfilePath.GetSize()-1; ii >= 0; ii--)
	{
		ImageProfilerPath* pPath = GetProfilePath(ii);
		if( pPath->IsReadOutObj(uObjUID) )
		{
			nPath = ii;
			break;
		}
	}
	if( pnPath )
		*pnPath = nPath;
	if( nPath < 0 )
		return IPUPDATE_NO_CHANGE;

	int nUpdate = IPUPDATE_NO_CHANGE;
	switch( nEvent )
	{
	case OE_SELECT:
		if( nPath != GetActivePath() )
		{
			SetActivePath(nPath);
			nUpdate = IPUPDATE_ACTIVE_PATH_CHANGE;
		}
		break;
	}

	return nUpdate;
}

int		ImageProfileManager::GetPathIndex(UINT uObjUID)
{
	for(int ii = m_arrProfilePath.GetSize()-1; ii >= 0; ii--)
	{
		ImageProfilerPath* pPath = GetProfilePath(ii);
		if( pPath->IsRelatedGrObj(uObjUID) )
			return ii;
	}
	return -1;
}

int		ImageProfileManager::AddProfilePath(int nPathType, const vector& vX, const vector& vY)
{
	if( !CanAddProfilePath(nPathType) )
		return -1;

	if( POLYLINE_IMAGE_PROFILE == nPathType )
	{
		if( !vX || !vY || vX.GetSize() != vY.GetSize() || vX.GetSize() < 2 )
			return -1;
	}
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	/*
	GraphLayer glSource = m_gpSource.Layers();
	if( !is_good_layer_for_profile(glSource) )
	{
		bool bValid = false;
		foreach(GraphLayer gl in m_gpSource.Layers)
		{
			if( is_good_layer_for_profile(gl) )
			{
				glSource = gl;
				bValid = true;
				break;
			}
		}
		if( !bValid )
			return -1;
	}
	ASSERT( is_good_layer_for_profile(glSource) );
	*/
	ASSERT(m_glSource);
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP

	ImageProfilerPath* pPath = newPath(nPathType);
	if( pPath )
	{
		pPath->SetRemoveGraphIfEmpty(IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH == m_nLayoutMode);		///Kyle 06/22/2010 ORG-355-P6 REMOVE_OUTPUT_GRAPH_IF_EMPTY_ON_SEP_MODE

		ImageProfilerPath* pActivePath = GetProfilePath(m_nActivePath);

		///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
		/*
		///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
		//double dProfileWidth = pActivePath ? pActivePath->GetProfileWidth() : 1.0;
		pPath->SetLineWidth(pActivePath ? pActivePath->GetLineWidth() : 0);
		///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
		*/
		if( pActivePath )
		{
			int nUnit = pActivePath->GetProfileWidthUnit();
			pPath->SetProfileWidth(pActivePath->GetProfileWidth(nUnit), nUnit);
		}
		///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE

		if( POLYLINE_IMAGE_PROFILE == nPathType )
		{
			///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			//pPath->AddProfileLine(glSource, GetNextLineColor(), 0, vX, vY);
			pPath->AddProfileLine(m_glSource, GetNextLineColor(), 0, vX, vY);
			///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		}
		else
		{
			vector vxNew, vyNew;
			///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			/*
			if( FindBestLocation(vxNew, vyNew, glSource, nPathType) )
				pPath->AddProfileLine(glSource, GetNextLineColor(), 0, vxNew, vyNew);
			else
				pPath->AddProfileLine(glSource, GetNextLineColor());
			*/
			if( FindBestLocation(vxNew, vyNew, m_glSource, nPathType) )
				pPath->AddProfileLine(m_glSource, GetNextLineColor(), 0, vxNew, vyNew);
			else
				pPath->AddProfileLine(m_glSource, GetNextLineColor());
			///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		}
		string strPathName = GetNextPathName(nPathType);
		pPath->SetPathName(strPathName);
		
		///Kyle 07/16/2010 ORG-584-S4 MORE_OPTION_FOR_THE_XY_LABEL_DEFAULT_POSITION
		if( VERTICAL_LINE_IMAGE_PROFILE == nPathType )		// for virtual line only for now
		{
			ImageProfilerHVPath* hvPath = (ImageProfilerHVPath*)pPath;
			if( m_nLayoutMode == IMAGE_PROFILE_LAYOUT_SAME_GRAPH_CLINE )
			{
				hvPath->SetTextObjectLocation(TEXT_LOC_BOTTOM);
				hvPath->ChangeTextObjectLocation();
			}
		}
		///End MORE_OPTION_FOR_THE_XY_LABEL_DEFAULT_POSITION
		
		///Kyle 06/07/2010 ORG-98 REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
		//pPath->SetProfileWidth(dProfileWidth);
		///End REMOVE_PROFILE_WIDTH_AND_ONLY_KEEP_LINE_WIDTH
		
		int nIndex = m_arrProfilePath.Add(*pPath);
		CheckSetProfileLayer(nIndex);
		pPath->RefreshProfilePath();			// if same graph layout, rescale will change the source layer
		//pPath->RefreshProfilePath();
		//if( GetLayoutMode() != IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH )
		//	m_gpSource.Layers(0).Rescale();

		SaveToStorage();

		return nIndex;
	}

	return -1;
}

bool	ImageProfileManager::CanAddProfilePath(int nPathType)
{
	/*
	if( GetLayoutMode() == IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH )
		return true;

	if( nPathType == POLYLINE_IMAGE_PROFILE )
		return false;

	switch( GetLayoutMode() )
	{
	case IMAGE_PROFILE_LAYOUT_SAME_GRAPH_CLINE:
		return nPathType==VERTICAL_LINE_IMAGE_PROFILE || nPathType==HORIZONTAL_LINE_IMAGE_PROFILE;
		break;
	case IMAGE_PROFILE_LAYOUT_SAME_GRAPH_VLINE:
		return nPathType==VERTICAL_LINE_IMAGE_PROFILE;
	case IMAGE_PROFILE_LAYOUT_SAME_GRAPH_HLINE:
		return nPathType==HORIZONTAL_LINE_IMAGE_PROFILE;
	}

	return false;
	*/
	return checkProfilePathTypeWithLayoutMode(GetLayoutMode(), nPathType);
}

bool	ImageProfileManager::checkProfilePathTypeWithLayoutMode(int nLayoutMode, int nPathType)
{
	if( nLayoutMode == IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH )
		return true;

	if( nPathType == POLYLINE_IMAGE_PROFILE )
		return false;

	switch( nLayoutMode )
	{
	case IMAGE_PROFILE_LAYOUT_SAME_GRAPH_CLINE:
		return nPathType==VERTICAL_LINE_IMAGE_PROFILE || nPathType==HORIZONTAL_LINE_IMAGE_PROFILE;
		break;
	case IMAGE_PROFILE_LAYOUT_SAME_GRAPH_VLINE:
		return nPathType==VERTICAL_LINE_IMAGE_PROFILE;
	case IMAGE_PROFILE_LAYOUT_SAME_GRAPH_HLINE:
		return nPathType==HORIZONTAL_LINE_IMAGE_PROFILE;
	}

	return false;	
}

ImageProfilerPath* ImageProfileManager::GetProfilePath(int nIndex)
{
	ImageProfilerPath* pPath = NULL;
	if( nIndex >= 0 && nIndex < m_arrProfilePath.GetSize() )
	{
		ImageProfilerPath& path = m_arrProfilePath.GetAt(nIndex);
		pPath = &path;
	}
	return pPath;
}

bool	ImageProfileManager::DeleteProfilePath(int nIndex)
{
	/// Iris 6/07/2010 ORG_98-P8 NEED_DEL_TABS_WHEN_SWITCH_LAYOUT_MODE
	// delete profile path, need to remove the related output columns
	ImageProfilerPath* pPath = GetProfilePath(nIndex);
	ASSERT(pPath);
	if( pPath )
		pPath->SetKeepOutput(false);
	///End NEED_DEL_TABS_WHEN_SWITCH_LAYOUT_MODE
	
	if( RemovePathAt(nIndex) )
	{
		SaveToStorage();
		///Kyle 06/18/2010 ORG-98-P21 REFRESH_PROBLEM_ON_DELETE_PATH
		if( m_glSource )
			m_glSource.GetPage().Refresh();
		///End REFRESH_PROBLEM_ON_DELETE_PATH
		return true;
	}

	return false;
}

int		ImageProfileManager::DuplicateProfilePath(int nIndex)
{
	if( nIndex < 0 || nIndex >= GetNumProfilePaths() )
		return -1;

	ImageProfilerPath* pSrcPath = GetProfilePath(nIndex);
	ASSERT(pSrcPath);
	if( !CanAddProfilePath(pSrcPath->GetPathType()) )
		return -1;

	ImageProfilerPath* pClonePath = newPath(pSrcPath->GetPathType());
	if( !pClonePath )
	{
		ASSERT(0);
		return -1;
	}
	if( !pClonePath->ClonePath(pSrcPath) )
	{
		delete pClonePath;
		return -1;
	}

	int nCloneIndex = nIndex+1;

	//m_arrProfilePath.InsertAt(nCloneIndex, *pClonePath);
	m_arrProfilePath.SetAsOwner(false);
	for(int ii = m_arrProfilePath.GetSize()-1; ii >= nCloneIndex; ii--)
	{
		ImageProfilerPath* pPath = GetProfilePath(ii);
		m_arrProfilePath.SetAtGrow(ii+1, *pPath);
	}
	m_arrProfilePath.SetAtGrow(nCloneIndex, *pClonePath);
	m_arrProfilePath.SetAsOwner(TRUE);
	
	string strName = GetNextPathName(pClonePath->GetPathType(), pClonePath->GetPathName());
	pClonePath->SetPathName(strName);
	
	CheckSetProfileLayer(nCloneIndex);
	pClonePath->RefreshProfilePath(true, GetLayoutMode() == IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH);
	
	SaveToStorage();

	return nCloneIndex;
}

bool	ImageProfileManager::SaveToStorage()
{
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//if( !m_gpSource )
	if( !m_glSource )
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		return false;
	///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	//ClearStorage();
	clearAllStorage();
	///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	
	int nCount = m_arrProfilePath.GetSize();
	if( nCount )
	{
		Tree trStorage;

		trStorage.LayoutMode.nVal = m_nLayoutMode;
		trStorage.Options.nVal = m_dwOptions;

		TreeNode trProfilePaths = trStorage.AddNode("Paths");
		for(int ii = 0; ii < nCount; ii++)
		{
			TreeNode trPath = trProfilePaths.AddNode("Path" + (string)ii);
			trPath.SetAttribute(STR_IMAGE_PROFILE_PATH_INDEX_ATTRIB, ii);		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			ImageProfilerPath* pPath = GetProfilePath(ii);
			pPath->SavePathToTree(trPath);
		}
	
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//return m_gpSource.PutBinaryStorage(STR_IMAGE_PROFILE_STORAGE, trStorage);
		return m_glSource.PutBinaryStorage(STR_IMAGE_PROFILE_STORAGE, trStorage);
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	}

	return true;
}

bool	ImageProfileManager::InitFromStorage()
{
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//if( !m_gpSource )
	if( !m_glSource )
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		return false;

	ASSERT(0 == m_arrProfilePath.GetSize());
	m_arrProfilePath.SetSize(0);

	Tree trStorage;
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//if( !m_gpSource.GetBinaryStorage(STR_IMAGE_PROFILE_STORAGE, trStorage) )
	if( !m_glSource.GetBinaryStorage(STR_IMAGE_PROFILE_STORAGE, trStorage) )
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		return false;

	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	/*
	GraphLayer glSource = m_gpSource.Layers(GRAPH_SOURCE_LAYER);
	ASSERT(glSource);
	GraphObject goTextButton = glSource.GraphObjects(STR_REOPEN_TEXT_BOX_NAME);
	*/
	GraphObject goTextButton = m_glSource.GraphObjects(STR_REOPEN_TEXT_BOX_NAME);
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	if( goTextButton.IsValid() )
	{
		//set_go_selectable(goTextButton, false);
		goTextButton.Show(false);					///Kyle 06/09/2010 hide the button
	}

	m_nLayoutMode = trStorage.LayoutMode ? trStorage.LayoutMode.nVal : IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH;
	m_dwOptions = trStorage.Options ? trStorage.Options.nVal : 0;

	TreeNode trProfilePaths = trStorage.Paths;
	if( !trProfilePaths )
		return FALSE;

	foreach(TreeNode trPath in trProfilePaths.Children)
	{
		if( !trPath.ProfileType )
			return false;

		ImageProfilerPath* pPath = newPath(trPath.ProfileType.nVal);
		if( !pPath )
			return FALSE;
		///Kyle 07/20/2010 ORG-584-P2 NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
		//if( !pPath->InitPathFromTree(trPath) )
		if( !pPath->InitPathFromTree(trPath, m_glSource) )
		///End NO_NEED_TO_SAVE_SOURCE_LAYER_IN_STORAGE
		{
			delete pPath;
			return false;
		}
		pPath->SetRemoveGraphIfEmpty(IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH == m_nLayoutMode);	///Kyle 06/22/2010 ORG-355-P6 REMOVE_OUTPUT_GRAPH_IF_EMPTY_ON_SEP_MODE

		m_arrProfilePath.Add(*pPath);
	}

	for(int nIndex = 0; nIndex < m_arrProfilePath.GetSize(); nIndex++)
		CheckSetProfileLayer(nIndex);
	RefreshAllProfile();

	return TRUE;

}

///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
//bool	ImageProfileManager::ClearStorage()
bool	ImageProfileManager::clearAllStorage()
///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
{
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//return m_gpSource && m_gpSource.SetMemory(STR_IMAGE_PROFILE_STORAGE, NULL);
	return m_glSource && m_glSource.SetMemory(STR_IMAGE_PROFILE_STORAGE, NULL);
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
}

///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
bool	ImageProfileManager::clearStorages(const vector<int>& vnPathIndeces)
{	
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//ASSERT(m_gpSource);
	ASSERT(m_glSource);
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	
	Tree trStorage;
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//if( m_gpSource.GetBinaryStorage(STR_IMAGE_PROFILE_STORAGE, trStorage))
	if( m_glSource.GetBinaryStorage(STR_IMAGE_PROFILE_STORAGE, trStorage))
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	{	
		TreeNode trProfilePaths = trStorage.Paths;
		
		for(int ii = 0; ii < vnPathIndeces.GetSize(); ii++)
		{
			///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			//TreeNode trPath = trProfilePaths.GetNode("Path" + (string)vnPathIndeces[ii]);
			TreeNode trPath = trProfilePaths.FindNodeByAttribute(STR_IMAGE_PROFILE_PATH_INDEX_ATTRIB, vnPathIndeces[ii], false);
			///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			ASSERT(trPath.IsValid());
			if( trPath )
				trPath.Remove();
		}
		
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//if( 0 == trProfilePaths.Children.Count() )
			//m_gpSource.SetMemory(STR_IMAGE_PROFILE_STORAGE, NULL);
		if( 0 == trProfilePaths.Children.Count() )
		{
			m_glSource.SetMemory(STR_IMAGE_PROFILE_STORAGE, NULL);
		}
		else
		{
			int nIndex = 0;
			foreach(TreeNode trPath in trProfilePaths.Children)
			{
				ASSERT( nIndex < GetNumProfilePaths() );
				trPath.SetAttribute(STR_IMAGE_PROFILE_PATH_INDEX_ATTRIB, nIndex);
				nIndex++;
			}
			m_glSource.PutBinaryStorage(STR_IMAGE_PROFILE_STORAGE, trStorage);
		}
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			
		return true;
	}
	return false;
}
///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS

string	ImageProfileManager::GetNextPathName(int nPathType, LPCSTR lpcszPrefix)	// = NULL
{
	string strPre(lpcszPrefix);
	strPre.TrimLeft();
	strPre.TrimRight();
	if( strPre.IsEmpty() )
	{
		switch(nPathType)
		{
		//case CROSSED_LINES_IMAGE_PROFILE:
		//	strPre = "CLine";
		//	break;

		case VERTICAL_LINE_IMAGE_PROFILE:
			strPre = "VLine";
			break;

		case HORIZONTAL_LINE_IMAGE_PROFILE:
			strPre = "HLine";
			break;

		case ARBITRARY_LINE_IMAGE_PROFILE:
			strPre = "ALine";
			break;

		case POLYLINE_IMAGE_PROFILE:
			strPre = "PLine";
			break;

		default:
			strPre = "Path";
			break;
		}
	}

	vector<string> vsNames;
	for(int ii = 0; ii < GetNumProfilePaths(); ii++)
	{
		ImageProfilerPath* pPath = GetProfilePath(ii);
		vsNames.Add(pPath->GetPathName());
	}

	string strName;
	for(int nPos = 0; nPos <= vsNames.GetSize(); nPos++)
	{
		if( nPos == 0 )
			strName = strPre;
		else
			strName.Format("%s %d", strPre, nPos);

		if( vsNames.Find(strName) < 0 )
			break;
	}

	return strName;
}

int		ImageProfileManager::GetNextLineColor()
{
	int nColor = 0;

	vector<uint> vnUsedColors;
	for(int ii = m_arrProfilePath.GetSize()-1; ii>=0; ii--)
	{
		ImageProfilerPath* pPath = GetProfilePath(ii);
		if( (nColor = pPath->GetProfileLineColor()) >= 0 )
			vnUsedColors.Add(nColor);
	}

	const vector<uint> vnBestColors = {SYSCOLOR_RED, SYSCOLOR_BLUE, SYSCOLOR_YELLOW, SYSCOLOR_GREEN};
	for(ii = 0; ii < vnBestColors.GetSize(); ii++)
	{
		vector<uint> vec;
		if( vnUsedColors.Find(vec, vnBestColors[ii]) <= 0 )
			return vnBestColors[ii];
	}

	vnUsedColors.Sort();
	nColor = 0;
	for(ii = 0; ii < vnUsedColors.GetSize(); ii++)
	{
		if( nColor < vnUsedColors[ii] )
			break;

		if( nColor == vnUsedColors[ii] )
		{
			nColor++;
			if( nColor == SYSCOLOR_WHITE )
				nColor++;
		}
	}
	if( nColor > SYSCOLOR_DKGRAY )
		nColor = 0;

	return nColor;
}

static double _find_hv_line_next_location(double dFrom, double dTo, int nIndex)
{
#define MAX_STEP 20

	bool bRight = 0!=(nIndex % 2);
	int nStep = (nIndex / 2 + (bRight ? 1 : 0)) % MAX_STEP;
	
	double dMid = 0.5 * (dFrom + dTo);
	double dInc = nStep * fabs(dTo - dFrom) / (2 * MAX_STEP);

	return dMid + (bRight ? dInc : -dInc);
}

bool ImageProfileManager::FindBestLocation(vector& vx, vector& vy, const GraphLayer& gl, int nPathType)
{
	if( !gl )
		return false;

	int nCount = 0;
	for(int ii = GetNumProfilePaths() - 1; ii >= 0; ii--)
	{
		ImageProfilerPath* pPath = GetProfilePath(ii);
		if( nPathType == pPath->GetPathType() )
			nCount++;
	}

	switch( nPathType )
	{
	case VERTICAL_LINE_IMAGE_PROFILE:
	case HORIZONTAL_LINE_IMAGE_PROFILE:
		{
			vx.SetSize(2);
			vy.SetSize(2);
			double	dXFrom = gl.X.From,
					dXTo = gl.X.To,
					dYFrom = gl.Y.From,
					dYTo = gl.Y.To;


			if( VERTICAL_LINE_IMAGE_PROFILE == nPathType )
			{
				vx[0] = vx[1] = _find_hv_line_next_location(dXFrom, dXTo, nCount);
				vy[0] = dYFrom;
				vy[1] = dYTo;
			}
			else
			{
				vx[0] = dXFrom;
				vx[1] = dXTo;
				vy[0] = vy[1] = _find_hv_line_next_location(dYFrom, dYTo, nCount);
			}
		}
		break;
		
	case ARBITRARY_LINE_IMAGE_PROFILE:
		{
			// to do
			return false;
		}
		break;

	default:
		return false;
	}
	return true;
}

void	ImageProfileManager::RefreshAllProfile()
{
	for(int ii = m_arrProfilePath.GetSize() - 1; ii >= 0; ii--)
	{
		ImageProfilerPath* pPath = GetProfilePath(ii);

		CheckSetProfileLayer(ii);
		pPath->RefreshProfilePath(true, GetLayoutMode() == IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH);
	}
}

bool	ImageProfileManager::CheckSetProfileLayer(int nPath)
{
	ImageProfilerPath* pPath = GetProfilePath(nPath);
	if( !pPath )
		return false;

	WorksheetPage wpOutput;
	FindOutputWP(wpOutput);

	GraphLayer glVertical, glHorizontal;
	pPath->GetOutputLayer(glVertical, true);
	pPath->GetOutputLayer(glHorizontal, false);

	if( !PrepareOuptutLayer(pPath->GetPathType(), pPath->GetSourceLayer(), glVertical, glHorizontal) )
		return false;

	pPath->CheckSetProfileLayer(wpOutput, glVertical, glHorizontal);

	return true;
}

bool	ImageProfileManager::FindOutputWP(WorksheetPage& wpOutput)
{
	for(int ii = m_arrProfilePath.GetSize() - 1; ii >= 0; ii--)
	{
		ImageProfilerPath* pPath = GetProfilePath(ii);
		if( pPath->GetOutputWP(wpOutput) && wpOutput )
			break;
	}

	return wpOutput.IsValid();
}

///Kyle 07/16/2010 ORG-584-S3 RENAME_GRAPH_WINDOWS_IN_SEPERATE_GRAPH_MODE
//static GraphLayer _new_gl_for_profile(LPCSTR lpcszPageName)
static GraphLayer _new_gl_for_profile(LPCSTR lpcszPageName, LPCSTR lpcszSrcName)
///End RENAME_GRAPH_WINDOWS_IN_SEPERATE_GRAPH_MODE
{
	GraphPage gpTemp;
	/// Iris 6/07/2010 ORG-98-P11 FIX_SEP_PROFILE_LAYER_NOT_SHOW_VHLINE_VALUE_IN_LEGEND
	//if( !gpTemp.Create("origin", CREATE_LOAD_1ST_LAYER_ONLY | CREATE_DEFAULT_OPTIONS) )
	if( !gpTemp.Create("PROFILE_SEP_LINE", CREATE_LOAD_1ST_LAYER_ONLY | CREATE_DEFAULT_OPTIONS) )
	///End FIX_SEP_PROFILE_LAYER_NOT_SHOW_VHLINE_VALUE_IN_LEGEND
		return false;
	gpTemp.SetName(lpcszPageName, OCD_ENUM_NEXT);
	
	///Kyle 07/16/2010 ORG-584-S3 RENAME_GRAPH_WINDOWS_IN_SEPERATE_GRAPH_MODE
	if( lpcszSrcName && *lpcszSrcName )
	{
		string strLName;
		strLName.Format("%s - %s", gpTemp.GetName(), lpcszSrcName);
		gpTemp.SetLongName(strLName, false);
	}
	///End RENAME_GRAPH_WINDOWS_IN_SEPERATE_GRAPH_MODE

	return gpTemp.Layers(0);
}

static bool _copy_axis_tick_label_scale(const Axis& axSrc, Axis& axDest)
{
	if( axSrc.IsValid() && axDest.IsValid() )
	{
		Tree trFmt;
		trFmt = axSrc.GetFormat(FPB_ALL, FOB_AXIS_TICKS | FOB_AXIS_LABELS | FOB_SCALE, TRUE, TRUE);
		axDest.ApplyFormat(trFmt, false, true);
		return true;
	}

	return false;
}

bool	ImageProfileManager::PrepareOuptutLayer(int nPathType, GraphLayer& glSource, GraphLayer& glVertical, GraphLayer& glHorizontal)
{
	if( !glSource )
		return false;

	if( POLYLINE_IMAGE_PROFILE == nPathType )
	{
		ASSERT( IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH == m_nLayoutMode );
		if( !glVertical )
		{
			///Kyle 07/16/2010 ORG-584-S3 RENAME_GRAPH_WINDOWS_IN_SEPERATE_GRAPH_MODE
			//glVertical = _new_gl_for_profile(STR_PROFILE_GRAPH);
			glVertical = _new_gl_for_profile("PLine", glSource.GetPage().GetName());
			///End RENAME_GRAPH_WINDOWS_IN_SEPERATE_GRAPH_MODE
		}
		return glVertical.IsValid();
	}

	//bool bNeedVer = CROSSED_LINES_IMAGE_PROFILE==nPathType || ARBITRARY_LINE_IMAGE_PROFILE==nPathType || VERTICAL_LINE_IMAGE_PROFILE==nPathType;
	//bool bNeedHor = CROSSED_LINES_IMAGE_PROFILE==nPathType || ARBITRARY_LINE_IMAGE_PROFILE==nPathType || HORIZONTAL_LINE_IMAGE_PROFILE==nPathType;
	bool bNeedVer = ARBITRARY_LINE_IMAGE_PROFILE==nPathType || VERTICAL_LINE_IMAGE_PROFILE==nPathType;
	bool bNeedHor = ARBITRARY_LINE_IMAGE_PROFILE==nPathType || HORIZONTAL_LINE_IMAGE_PROFILE==nPathType;
	
	GraphPage gpSource = m_glSource.GetPage();			///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP

	switch( m_nLayoutMode )
	{
	case IMAGE_PROFILE_LAYOUT_SAME_GRAPH_CLINE:
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//glVertical = m_gpSource.Layers(GRAPH_VLINE_LAYER);
		//glHorizontal = m_gpSource.Layers(GRAPH_HLINE_LAYER);
		glVertical = gpSource.Layers(GRAPH_VLINE_LAYER);
		glHorizontal = gpSource.Layers(GRAPH_HLINE_LAYER);
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		break;
		
	case IMAGE_PROFILE_LAYOUT_SAME_GRAPH_VLINE:
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//glVertical = m_gpSource.Layers(GRAPH_SOURCE_LAYER+1);
		glVertical = gpSource.Layers(GRAPH_SOURCE_LAYER+1);
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		break;
		
	case IMAGE_PROFILE_LAYOUT_SAME_GRAPH_HLINE:
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//glHorizontal = m_gpSource.Layers(GRAPH_SOURCE_LAYER+1);
		glHorizontal = gpSource.Layers(GRAPH_SOURCE_LAYER+1);
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		break;
		
	case IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH:
		{
			bool bArbitraryLine = (nPathType == ARBITRARY_LINE_IMAGE_PROFILE);
			for(int ii = m_arrProfilePath.GetSize() - 1; ii >= 0; ii--)
			{
				if( (!bNeedVer || glVertical) && (!bNeedHor || glHorizontal) )		// found
					return true;
		
				ImageProfilerPath* pPath = GetProfilePath(ii);
				if(  bArbitraryLine == (pPath->GetPathType() == ARBITRARY_LINE_IMAGE_PROFILE) && is_same_layer(pPath->GetSourceLayer(), glSource) )
				{
					if( bNeedVer && !glVertical )
						pPath->GetOutputLayer(glVertical, true);
		
					if( bNeedHor && !glHorizontal )
						pPath->GetOutputLayer(glHorizontal, false);
				}
			}

			if( bNeedVer && !glVertical )
			{
				///Kyle 07/16/2010 ORG-584-S3 RENAME_GRAPH_WINDOWS_IN_SEPERATE_GRAPH_MODE
				//glVertical = _new_gl_for_profile(STR_PROFILE_GRAPH);
				string strGraphName = (VERTICAL_LINE_IMAGE_PROFILE==nPathType) ? "VLine" : "ALine";
				glVertical = _new_gl_for_profile(strGraphName, glSource.GetPage().GetName());
				///End RENAME_GRAPH_WINDOWS_IN_SEPERATE_GRAPH_MODE
				_copy_axis_tick_label_scale(glSource.YAxis, glVertical.XAxis);
			}
	
			if( bNeedHor && !glHorizontal )
			{
				///Kyle 07/16/2010 ORG-584-S3 RENAME_GRAPH_WINDOWS_IN_SEPERATE_GRAPH_MODE
				//glHorizontal = _new_gl_for_profile(STR_PROFILE_GRAPH);
				string strGraphName = (HORIZONTAL_LINE_IMAGE_PROFILE==nPathType) ? "HLine" : "ALineH";
				glHorizontal = _new_gl_for_profile(strGraphName, glSource.GetPage().GetName());
				///End RENAME_GRAPH_WINDOWS_IN_SEPERATE_GRAPH_MODE
				_copy_axis_tick_label_scale(glSource.XAxis, glHorizontal.XAxis);
			}
		}
		break;

	default:
		ASSERT(0);
		return false;
	}

	return (!bNeedVer || glVertical) && (!bNeedHor || glHorizontal);
}

bool	ImageProfileManager::RemovePathAt(int nIndex)
{
	if( nIndex >= 0 && nIndex < m_arrProfilePath.GetSize() )
	{
		//GraphLayer glSrc;
		//bool	bVertical = false,
				//bHorizontal = false;
		//ImageProfilerPath* pPath = GetProfilePath(nIndex);
		//if( pPath )
		//{
			//glSrc = pPath->GetSourceLayer();
			//
			//GraphLayer gl;
			//bVertical = pPath->GetOutputLayer(gl, true);
			//bHorizontal = pPath->GetOutputLayer(gl, false);
		//}

		///Kyle 06/22/2010 ORG-355-P6 REMOVE_OUTPUT_GRAPH_IF_EMPTY_ON_SEP_MODE
		/*
		ImageProfilerPath* pPath = GetProfilePath(nIndex);
		if( pPath )
		{
			bool bRemoveIfEmpty = m_nLayoutMode == IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH || m_dwOptions & IPROFILE_PROTECT_SOURCE;
			pPath->SetRemoveGraphIfEmpty(bRemoveIfEmpty);
		}
		*/
#ifdef _DEBUG
		ImageProfilerPath* pPath = GetProfilePath(nIndex);
		ASSERT( pPath && (m_nLayoutMode == IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH)==pPath->IsRemoveGraphIfEmpty());
#endif // _DEBUG
		///End REMOVE_OUTPUT_GRAPH_IF_EMPTY_ON_SEP_MODE

		m_arrProfilePath.RemoveAt(nIndex);
		if( nIndex == m_nActivePath )
			m_nActivePath = -1;

		//if( GetLayoutMode() != IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH && glSrc )
		//{
			//ASSERT( bVertical || bHorizontal);
//
			//GraphLayer glVertical, glHorizontal;
			//for(int ii = m_arrProfilePath.GetSize() - 1; ii >= 0; ii--)
			//{
				//if( glVertical && glHorizontal )
					//break;
//
				//ImageProfilerPath* pPath = GetProfilePath(ii);
				//if( !glVertical )
					//pPath->GetOutputLayer(glVertical, true);
				//if( !glHorizontal )
					//pPath->GetOutputLayer(glHorizontal, false);
			//}
//
			//if( (bVertical && !glVertical) || (bHorizontal && !glHorizontal) )
			//{
				//page_arrange_profile_layer(m_gpSource, glSrc.GetIndex(), glVertical ? glVertical.GetIndex() : -1, glHorizontal ? glHorizontal.GetIndex() : -1)
			//}
		//}

		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		/*
		GraphLayer glActive = Project.ActiveLayer();
		if( m_gpSource && !(glActive && IsRelatedLayer(glActive)) )
		{
			GraphLayer gl = m_gpSource.Layers();
			if( gl )
				set_active_layer(gl);
		}
		*/
		GraphLayer glActive = Project.ActiveLayer();
		if( m_glSource && !(glActive && IsRelatedLayer(glActive)) )
			set_active_layer(m_glSource);
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP

		return true;
	}

	return false;
}

bool ImageProfileManager::ReloadTemplate()
{
	if( m_dwOptions & IPROFILE_PROTECT_SOURCE )
		return false;

	DataPlot dpSrc;
	if( !GetSrcPlot(dpSrc) )
		return false;

	GraphLayer glSource;
	dpSrc.GetParent(glSource);
	
	bool bHasProfileTextButton = glSource.GraphObjects(STR_REOPEN_TEXT_BOX_NAME).IsValid();	
	
	DataRange dr;
	Tree trFmt;

	int nPlotType = dpSrc.GetPlotType();
	dpSrc.GetDataRange(dr);
	trFmt = dpSrc.GetFormat(FPB_ALL, FOB_ALL, true, true);

	TemplateLayerInfo stTemplateInfo;
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//page_load(m_gpSource, GetLayoutTemplate(m_nLayoutMode, nPlotType, &stTemplateInfo), NOCLICK_DATA_PLOT | NOCLICK_LAYER | NOCLICK_LAYERICON);
	//GraphLayer glSrc = m_gpSource.Layers(0);
	//if( !glSrc )
	//{
		//ASSERT(0);
		//return false;
	//}
	//glSrc.CheckShowActivate();
	GraphPage gpSource = m_glSource.GetPage();
	ASSERT(gpSource);
	page_load(gpSource, GetLayoutTemplate(m_nLayoutMode, nPlotType, &stTemplateInfo), NOCLICK_DATA_PLOT | NOCLICK_LAYER | NOCLICK_LAYERICON);
	m_glSource = gpSource.Layers(GRAPH_SOURCE_LAYER);
	if( !m_glSource )
	{
		ASSERT(0);
		return false;
	}
	m_glSource.CheckShowActivate();
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP

	/// Iris 6/02/2010 ORG-98-S4 CHECK_TEMPLATE_AFTER_LOAD_TEMPLATE_TO_PAGE
	int nNumLayers = 1;
	ASSERT(stTemplateInfo.nMainLayer >= 0);
	
	if( IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH != m_nLayoutMode )
	{
	if( stTemplateInfo.nVLineLayer >= 0 )
		nNumLayers++;
	
	if( stTemplateInfo.nHLineLayer >= 0 )
		nNumLayers++;
	}
	
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//if( m_gpSource.Layers.Count() != nNumLayers )
	//{
		//while ( m_gpSource.Layers.Count() < nNumLayers )
			//m_gpSource.AddLayer();
		//
		//page_arrange_profile_layer(m_gpSource, stTemplateInfo.nMainLayer, stTemplateInfo.nVLineLayer, stTemplateInfo.nHLineLayer, 15, 15);
	//}
	if( gpSource.Layers.Count() != nNumLayers )
	{
		while ( gpSource.Layers.Count() < nNumLayers )
			gpSource.AddLayer();
		
		page_arrange_profile_layer(gpSource, stTemplateInfo.nMainLayer, stTemplateInfo.nVLineLayer, stTemplateInfo.nHLineLayer, 15, 15);
	}
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	///End CHECK_TEMPLATE_AFTER_LOAD_TEMPLATE_TO_PAGE

	int nPlot;
	switch( nPlotType )
	{
	case IDM_PLOT_CONTOUR:
	case IDM_PLOT_MATRIX_IMAGE:
		{
			int c1, c2;
			MatrixLayer ml;
			dr.GetRange(ml, c1, c2);

			MatrixObject mo(ml, c1);
			if( mo )
			{
				///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
				//nPlot = glSrc.AddPlot(mo, nPlotType);
				nPlot = m_glSource.AddPlot(mo, nPlotType);
				///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			}
			else
			{
				// virtual matrix
				mo.Attach(dr);
				if( !mo )
					return false;
				///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
				//nPlot = glSrc.AddPlot(mo, nPlotType);
				nPlot = m_glSource.AddPlot(mo, nPlotType);
				///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			}
		}
		break;

	case IDM_PLOT_TRI_CONTOUR:
		{
			///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			//nPlot = glSrc.AddPlot(dr, nPlotType);
			nPlot = m_glSource.AddPlot(dr, nPlotType);
			///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		}
		break;
	}
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//dpSrc = glSrc.DataPlots(nPlot);
	dpSrc = m_glSource.DataPlots(nPlot);
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP

	if( dpSrc )
	{
		dpSrc.SetActive();
		dpSrc.ApplyFormat(trFmt, true, true);
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//glSrc.Rescale();
		m_glSource.Rescale();
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	}
	
	///Iris 6/11/2010 ORG-98-S36 SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	for(int index  = 0; index < m_arrProfilePath.GetSize(); index++)
	{
		ImageProfilerPath* pPath = GetProfilePath(index);
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//pPath->SetSourceLayer(glSrc);
		pPath->SetSourceLayer(m_glSource);
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		pPath->SetSourcePlot(dpSrc);			///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	}	
	///End SWITCH_MODE_NEED_KEEP_MEANINGFUL_PATHS
	
	// if has Profile button before reload template, so need add it back after tempalte load
	if( bHasProfileTextButton )
		addReopenTextButton(false, false);
	
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//m_gpSource.Refresh();
	gpSource.Refresh();
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP

	return true;
}

bool ImageProfileManager::GetSrcPlot(DataPlot& dpSrc)
{
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	/*
	foreach(GraphLayer gl in m_gpSource.Layers)
	{
		if( is_good_layer_for_profile(gl) )
		{
			dpSrc = gl.DataPlots();
			return true;
		}
	}
	*/
	///Kyle 06/18/2010 ORG-98 KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	/*
	if( is_good_layer_for_profile(m_glSource) )
	{
		dpSrc = m_glSource.DataPlots();
		return true;
	}
	*/
	for(int index  = 0; index < m_arrProfilePath.GetSize(); index++)
	{
		ImageProfilerPath* pPath = GetProfilePath(index);
		if( pPath->GetSourcePlot(dpSrc) )
			return true;
	}

	DataPlot dp = m_glSource.DataPlots();
	if( is_good_plot_for_profile(dp) )
	{
		dpSrc = dp;
		return true;
	}
	///End KEEP_SOURCE_DATA_PLOT_TO_PREVENT_ACTIVE_PLOT_CHANGED
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	return false;
}

string ImageProfileManager::GetLayoutTemplate(int nLayoutMode, int nPlotType, TemplateLayerInfo* pstTemplateInfo)
{
	TemplateLayerInfo stTemplateInfo;
	string strPlotType;
	switch( nPlotType )
	{
	case IDM_PLOT_CONTOUR:
		strPlotType = "CONTOUR";
		break;

	case IDM_PLOT_MATRIX_IMAGE:
		strPlotType = "IMAGE";
		break;

	case IDM_PLOT_TRI_CONTOUR:
		strPlotType = "TRICONTOUR";
		break;

	default:
		ASSERT(0);
		return "";
	}

	stTemplateInfo.nMainLayer = GRAPH_SOURCE_LAYER;
	string strPostfix;
	switch( nLayoutMode )
	{
	case IMAGE_PROFILE_LAYOUT_SAME_GRAPH_CLINE:
		strPostfix = "CLINE";
		stTemplateInfo.nVLineLayer = GRAPH_VLINE_LAYER;
		stTemplateInfo.nHLineLayer = GRAPH_HLINE_LAYER;
		break;
		
	case IMAGE_PROFILE_LAYOUT_SAME_GRAPH_VLINE:
		strPostfix = "VLINE";
		stTemplateInfo.nVLineLayer = GRAPH_SOURCE_LAYER + 1;
		stTemplateInfo.nHLineLayer = -1;
		break;
		
	case IMAGE_PROFILE_LAYOUT_SAME_GRAPH_HLINE:
		strPostfix = "HLINE";
		stTemplateInfo.nVLineLayer = -1;
		stTemplateInfo.nHLineLayer = GRAPH_SOURCE_LAYER + 1;
		break;
		
	case IMAGE_PROFILE_LAYOUT_SEPARATE_GRAPH:
		strPostfix = "SEP";
		break;
	}

	string strTemplate;
	if( strPostfix.IsEmpty() )
	{
		strTemplate = strPlotType;
	}
	else
	{
		strTemplate.Format("PROFILE_%s_%s", strPlotType, strPostfix);
	}

	if( pstTemplateInfo )
		*pstTemplateInfo = stTemplateInfo;

	return strTemplate;
}

ImageProfilerPath* ImageProfileManager::newPath(int nPathType)
{
	ImageProfilerPath* pPath = NULL;
	switch( nPathType )
	{
	//case CROSSED_LINES_IMAGE_PROFILE:
	//	pPath = new ImageProfilerCrossLinePath();
	//	break;

	case VERTICAL_LINE_IMAGE_PROFILE:
	case HORIZONTAL_LINE_IMAGE_PROFILE:
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//pPath = new ImageProfilerHVPath(nPathType);
		pPath = new ImageProfilerHVPath(nPathType, &m_profileCalculator);
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		break;

	case ARBITRARY_LINE_IMAGE_PROFILE:
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//pPath = new ImageProfilerAbitraryLinePath();
		pPath = new ImageProfilerAbitraryLinePath(&m_profileCalculator);
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		break;

	case POLYLINE_IMAGE_PROFILE:
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//pPath = new ImageProfilerPolyLinePath();
		pPath = new ImageProfilerPolyLinePath(&m_profileCalculator);
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		break;

	default:
		ASSERT(0);
	}

	return pPath;
}

bool	ImageProfileManager::addReopenTextButton(bool bRefresh, bool bVisible)
{
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	/*
	GraphLayer glSource = m_gpSource.Layers(GRAPH_SOURCE_LAYER);
	ASSERT(glSource);
	if( !glSource )
		return false;
	
	GraphObject goText;
	goText = glSource.GraphObjects(STR_REOPEN_TEXT_BOX_NAME);
	*/
	if( !m_glSource )
	{
		ASSERT(0);
		return false;
	}
	GraphObject goText;
	goText = m_glSource.GraphObjects(STR_REOPEN_TEXT_BOX_NAME);
	
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	
	///Kyle 07/16/2010 ORG-584-S1 RENAME_REOPEN_BUTTON_AND_GIVE_BETTER_POSITION
	//if( !goText )
	if( goText )
	{
		goText.Text = STR_REOPEN_TEXT_BOX_LABEL;
	}
	else
	///End RENAME_REOPEN_BUTTON_AND_GIVE_BETTER_POSITION
	{
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//add_text(glSource, goText, 90, 5, STR_REOPEN_TEXT_BOX_LABEL, 0, true, ATTACH_TO_LAYER);
		add_text(m_glSource, goText, 90, 5, STR_REOPEN_TEXT_BOX_LABEL, 0, true, ATTACH_TO_LAYER);
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		goText.SetName(STR_REOPEN_TEXT_BOX_NAME);
		set_LT_script(goText, "imageprofile", GRCT_MOUSEUP);			
		
		// Change position
		Tree trPage;
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//trPage = m_gpSource.GetFormat(FPB_DIMENSION, FOB_DIMENSION, TRUE, TRUE);
		GraphPage gp = m_glSource.GetPage();
		trPage = gp.GetFormat(FPB_DIMENSION, FOB_DIMENSION, TRUE, TRUE);
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		double dPageWidth = trPage.Root.Dimension.Width.dVal;
		double dPageHeight = trPage.Root.Dimension.Height.dVal;
		
		Tree tr;
		tr.Root.Dimension.Units.nVal = trPage.Root.Dimension.Units.nVal;
		tr.Root.Dimension.Left.dVal = dPageWidth * 0.7;
		///Kyle 07/16/2010 ORG-584-S1 RENAME_REOPEN_BUTTON_AND_GIVE_BETTER_POSITION, a little upper
		//tr.Root.Dimension.Top.dVal = dPageHeight * 0.05;
		tr.Root.Dimension.Top.dVal = dPageHeight * 0.02;
		///End RENAME_REOPEN_BUTTON_AND_GIVE_BETTER_POSITION
		if( 0 == goText.UpdateThemeIDs(tr.Root) )
			goText.ApplyFormat(tr, true, true);	

		if( bRefresh )
		{
			///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			//m_gpSource.Refresh();
			gp.Refresh();
			///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		}
	}

	//goText.Show(true);
	//set_go_selectable(goText, bSetEnable);
	goText.Show(bVisible);
	
	return true;
}

/*----------------------------------------------------------------------------*/
/* ImageProfileHolder
/*----------------------------------------------------------------------------*/


int ImageProfileHolder::StartProfile(GraphPage& gp, int nLayoutMode, DWORD dwOptions)			// = 0, = 0
{
	if( !gp )
		return -1;
	GraphLayer glActive = gp.Layers();
	if( !glActive )
		return -1;
	HOLDER_BEFORE_UPDATE_NO_CHECK(this);

	set_active_layer(glActive);

	int nProfileIndex = CheckLoadProfile(glActive, true);
	
	if( nProfileIndex >= 0 )
	{
		m_nActiveProfileIndex = nProfileIndex;
	}
	else
	{
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//ImageProfileManager* pNewProfiler = new ImageProfileManager(gp, nLayoutMode, dwOptions);
		ImageProfileManager* pNewProfiler = new ImageProfileManager(glActive, nLayoutMode, dwOptions);
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		pNewProfiler->SetReady(true);
		m_nActiveProfileIndex = m_arrProfileMngr.Add(*pNewProfiler);
		///Kyle 07/14/2010 ORG-572-P1 SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE
		GraphPage gp = pNewProfiler->GetSourcePage();
		checkSetPageNoClick(gp, true);
		///End SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE
	}
	return m_nActiveProfileIndex;
}

bool ImageProfileHolder::RemoveProfile(int nIndex)
{
	HOLDER_BEFORE_UPDATE_NO_CHECK(this);

	if( nIndex < 0 )
		nIndex = m_nActiveProfileIndex;

	if( nIndex >= 0 && nIndex < m_arrProfileMngr.GetSize() )
	{
		GraphPage gp = getProfileByIndex(nIndex)->GetSourcePage();		///Kyle 07/14/2010 ORG-572-P1 SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE

		m_arrProfileMngr.RemoveAt(nIndex);

		///Kyle 07/14/2010 ORG-572-P1 SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE
		if( gp )
			checkSetPageNoClick(gp, false, true);
		///End SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE
		if( m_nActiveProfileIndex == nIndex )
			m_nActiveProfileIndex = -1;
		return TRUE;
	}

	return FALSE;
}

bool ImageProfileHolder::ClearAllProfile()
{
	HOLDER_BEFORE_UPDATE(this);

	for(int ii = m_arrProfileMngr.GetSize()-1; ii >= 0; ii--)
	{
		GraphPage gp = getProfileByIndex(ii)->GetSourcePage();		///Kyle 07/14/2010 ORG-572-P1 SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE
		
		m_arrProfileMngr.RemoveAt(ii);

		///Kyle 07/14/2010 ORG-572-P1 SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE
		if( gp )
			checkSetPageNoClick(gp, false);
		///End SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE
	}
	
	m_nActiveProfileIndex = -1;

	return TRUE;
}

bool ImageProfileHolder::OnDataModify(const DataRange& drChange)
{
	HOLDER_BEFORE_UPDATE(this);
	if( !drChange.IsValid() )
		return false;

	for(int ii = 0; ii < m_arrProfileMngr.GetSize(); ii++)
	{
		ImageProfileManager& profile = m_arrProfileMngr.GetAt(ii);
		for(int nPath = 0; nPath < profile.GetNumProfilePaths(); nPath++)
		{
			ImageProfilerPath* pPath = profile.GetProfilePath(nPath);
			pPath->CheckResetCalculator(drChange);
		}
	}

	return true;
}

///Kyle 07/01/2010 ORG-355-P11 FIX_PROFILE_IS_NOT_REMOVED_ON_CLOSE_PAGE_WHEN_THERE_IS_NO_PATH
bool ImageProfileHolder::OnLayerDestroy(GraphLayer& gl)
{
	HOLDER_BEFORE_UPDATE(this);
	if( !gl.IsValid() )
		return false;

	bool bActive;
	if( onSrcLayerDestroy(gl, bActive) && bActive )
		sendMessage(IPUPDATE_ACTIVE_PROFILE_CHANGE);

	return true;
}

bool ImageProfileHolder::OnPageDestroy(GraphPage& gp)
{
	HOLDER_BEFORE_UPDATE(this);
	if( !gp.IsValid() )
		return false;

	bool bActiveProfile = false;
	foreach(GraphLayer gl in gp.Layers)
	{
		bool bActive;
		if( onSrcLayerDestroy(gl, bActive) && bActive )
			bActiveProfile = bActive;
	}

	if( bActiveProfile )
		sendMessage(IPUPDATE_ACTIVE_PROFILE_CHANGE);

	return true;
}

bool ImageProfileHolder::onSrcLayerDestroy(GraphLayer& glSrc, bool& bActive)
{
	ASSERT(glSrc);
	
	for(int nIndex = m_arrProfileMngr.GetSize() - 1; nIndex >= 0; nIndex--)
	{
		ImageProfileManager* pProfile = getProfileByIndex(nIndex);
		if( is_same_layer(pProfile->GetSourceLayer(), glSrc) )
		{
			pProfile->OnDeleteSrcPage();
			bActive = m_nActiveProfileIndex == nIndex;
			RemoveProfile(nIndex);

			return true;
		}
	}

	return false;
}
///End FIX_PROFILE_IS_NOT_REMOVED_ON_CLOSE_PAGE_WHEN_THERE_IS_NO_PATH

///Kyle 07/14/2010 ORG-572-P1 SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE
bool ImageProfileHolder::checkSetPageNoClick(GraphPage& gp, bool bSetNoClick, bool bIgnorePageInProfiling)	// = false
{
	if( !gp )
		return false;

	if( bIgnorePageInProfiling )
	{
		int nPageUID = gp.GetUID(true);
		for(int ii = m_arrProfileMngr.GetSize() - 1; ii >= 0; ii--)
		{
			GraphPage gpSrc = getProfileByIndex(ii)->GetSourcePage();
			if( gpSrc && gpSrc.GetUID() == nPageUID )
				return false;
		}
	}

	DWORD dwClicks = bSetNoClick ? (NOCLICK_DATA_PLOT | NOCLICK_LAYER | NOCLICK_LAYERICON) : (NOCLICK_USE_DEFAULT);
	return set_gp_noclick(gp, dwClicks);
}
///End SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE

void ImageProfileHolder::SetParentWnd(Window* 	pParentWnd)
{
	ASSERT(pParentWnd);
	m_pParentWnd = pParentWnd;
}

void ImageProfileHolder::ResetParentWnd()
{
	m_pParentWnd = NULL;
}

bool ImageProfileHolder::OnActiveLayerChange()
{
	HOLDER_BEFORE_UPDATE(this);

	GraphLayer glActive = Project.ActiveLayer();
	int nProfileIndex = CheckLoadProfile(glActive, false);
	if( m_nActiveProfileIndex != nProfileIndex )
	{
		// allow empty profile, but not saved in storage
		//if( m_nActiveProfileIndex >= 0 )		// remove empty profile
		//{
			//ImageProfileManager* pProfile = GetActiveProfile();
			//ASSERT(pProfile);
			//if( pProfile->GetNumProfilePaths() == 0 )
				//RemoveProfile(m_nActiveProfileIndex);
		//}

		m_nActiveProfileIndex = nProfileIndex;
		sendMessage(IPUPDATE_ACTIVE_PROFILE_CHANGE);
	}

	return true;
}

// object events
bool ImageProfileHolder::OnImageProfileEvent(int nEvent, UINT uPageUID, UINT uObjUID)
{
	HOLDER_BEFORE_UPDATE(this);

	GraphPage gp;gp = (GraphPage) Project.GetObject(uPageUID);
	if( !gp )
		return false;
	GraphLayer gl = gp.Layers();
	if( !gl )
		return false;

	///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING
	/*
	if( OE_WIN_CLOSE == nEvent )
	{
		int nIndex = CheckLoadProfile(gl, false);
		if( nIndex >= 0 )
		{
			if( true )
			{
				ImageProfileManager& profile = m_arrProfileMngr.GetAt(nIndex);
				profile.OnDeleteSrcPage();
			}

			bool bIsActive = m_nActiveProfileIndex == nIndex;

			RemoveProfile(nIndex);

			if( bIsActive )
			{
				m_nActiveProfileIndex = -1;
				sendMessage(IPUPDATE_ACTIVE_PROFILE_CHANGE);
			}
		}
		
		return true;
	}
	
	if( OE_SCALE_CHANGE!=nEvent && OE_STYLE_CHANGE!=nEvent && OE_SELECT!=nEvent && OE_GRAPHOBJ_EDIT!=nEvent && OE_MOVE!=nEvent && OE_DELETE!=nEvent && OE_DELETE_PART!=nEvent )
		return true;

	ImageProfileManager* pProfile = GetActiveProfile();
	if( !pProfile )
	{
		ASSERT(0);
		return false;
	}
	ASSERT( pProfile->GetSourcePage().GetUID() == uPageUID );
	
	TIME_PROFILER;

	if( OE_DELETE == nEvent )
	{
		int nActivePath = pProfile->GetActivePath();
		int nNumPaths = pProfile->GetNumProfilePaths();
		int nPathChanged = pProfile->OnDeleteProfileLine(uObjUID);

		ASSERT(nActivePath < 0 || nActivePath == nPathChanged);

		int nNewNumPaths = pProfile->GetNumProfilePaths();
		if( nNewNumPaths < nNumPaths )			// need to remove some tab in gui
		{
			if( nPathChanged <= nActivePath )
			{
				nActivePath--;
				if(nActivePath < 0)
					nActivePath = 0;
				pProfile->SetActivePath(nActivePath);
			}
			sendMessage(IPUPDATE_ACTIVE_PROFILE_CHANGE);
		}
		else
		{
			ASSERT(0);		// group profile paths, to do
			if( nActivePath == nPathChanged )
				sendMessage(IPUPDATE_ACTIVE_PATH_CHANGE);
		}
		return true;
	}
	else if( OE_SELECT == nEvent )
	{
		int nPath = pProfile->GetPathIndex(uObjUID);
		if( nPath != pProfile->GetActivePath() )
		{
			pProfile->SetActivePath(nPath);
			sendMessage(IPUPDATE_ACTIVE_PATH_CHANGE);
		}
		return true;
	}

	int nPathIndex = pProfile->OnProfileEvent(nEvent, uObjUID);
	if( nPathIndex >= 0 )
		sendMessage(IPUPDATE_PATH_CONTENT, nPathIndex);
	*/
	if( OE_WIN_CLOSE!=nEvent && OE_SCALE_CHANGE!=nEvent && OE_STYLE_CHANGE!=nEvent && OE_SELECT!=nEvent && OE_GRAPHOBJ_EDIT!=nEvent && OE_MOVE!=nEvent && OE_DELETE!=nEvent && OE_DELETE_PART!=nEvent )
		return true;

	int nIndex = CheckLoadProfile(gl, false);
	ImageProfileManager* pProfile = getProfileByIndex(nIndex);
	if( !pProfile )
	{
		return false;
	}
	///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	//ASSERT( pProfile->GetSourcePage().GetUID() == uPageUID );
	///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
	
	TIME_PROFILER;			// for speed testing

	int nPathIndex;
	int nUpdate = pProfile->OnProfileEvent(nEvent, uObjUID, &nPathIndex);
	if( nUpdate == IPUPDATE_PROFILE_DELETED )
	{
		bool bIsActive = m_nActiveProfileIndex == nIndex;
		RemoveProfile(nIndex);
		if( bIsActive )
		{
			m_nActiveProfileIndex = -1;
			sendMessage(IPUPDATE_ACTIVE_PROFILE_CHANGE);
		}
	}
	else if( nUpdate != IPUPDATE_NO_CHANGE )
		sendMessage(nUpdate, nPathIndex);
	///End CENTRALIZE_EVENT_HANDLING

	return true;
}

bool ImageProfileHolder::OnProfileReadOutEvent(int nEvent, UINT uPageUID, UINT uObjUID)
{
	HOLDER_BEFORE_UPDATE(this);
	if( OE_SELECT!=nEvent )
		return true;

	GraphObject go; go = (GraphObject)Project.GetObject(uObjUID);
	if( !go.IsValid() )
		return false;

	GraphLayer gl;
	go.GetParent(gl);
	if( !gl.IsValid() )
		return false;

	int nIndex = CheckLoadProfile(gl, false);
	ImageProfileManager* pProfile = getProfileByIndex(nIndex);
	if( !pProfile )
	{
		ASSERT(0);
		return false;
	}
	//ASSERT( pProfile->GetSourcePage().GetUID() == uPageUID );			///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP

	int nPathIndex;
	int nUpdate = pProfile->OnReadOutEvent(nEvent, uObjUID, &nPathIndex);
	if( nUpdate != IPUPDATE_NO_CHANGE )
		sendMessage(nUpdate, nPathIndex);

	return true;
}

const ImageProfileManager* ImageProfileHolder::GetActiveProfile()
{
	///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING
	/*
	ImageProfileManager* pProfile = NULL;

	if( 0<=m_nActiveProfileIndex && m_nActiveProfileIndex<m_arrProfileMngr.GetSize() )
	{
		ImageProfileManager& profileTemp = m_arrProfileMngr.GetAt(m_nActiveProfileIndex);
		pProfile = &profileTemp;
	}

	return pProfile;
	*/
	return getProfileByIndex(m_nActiveProfileIndex);
	///End CENTRALIZE_EVENT_HANDLING
}

///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING
const ImageProfileManager* ImageProfileHolder::getProfileByIndex(int nIndex)
{
	ImageProfileManager* pProfile = NULL;

	if( 0<=nIndex && nIndex<m_arrProfileMngr.GetSize() )
	{
		ImageProfileManager& profileTemp = m_arrProfileMngr.GetAt(nIndex);
		pProfile = &profileTemp;
	}

	return pProfile;
}
///End CENTRALIZE_EVENT_HANDLING

///Kyle 07/21/2010 ORG-584-P2 CHECK_SHOW_DIALOG_AFTER_LOADING_PROFILE
//int	ImageProfileHolder::CheckLoadProfile(GraphLayer& gl, bool bLoadProfile)
int	ImageProfileHolder::CheckLoadProfile(GraphLayer& gl, bool bLoadProfile, bool* pbIsActive)
///End CHECK_SHOW_DIALOG_AFTER_LOADING_PROFILE
{
	if( !gl )
		return -1;
	GraphPage gp; gp = gl.GetPage();
	
	///Kyle 07/21/2010 ORG-584-P2 CHECK_SHOW_DIALOG_AFTER_LOADING_PROFILE
	if( pbIsActive )
		*pbIsActive = false;
	///End CHECK_SHOW_DIALOG_AFTER_LOADING_PROFILE
	
	///Kyle 06/09/2010 ORG-98 CENTRALIZE_EVENT_HANDLING, check active profile first
	ImageProfileManager* pProfile = GetActiveProfile();
	if( pProfile )
	{
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//if( pProfile->GetSourcePage()==gp || pProfile->IsRelatedLayer(gl) )
		if( pProfile->IsRelatedLayer(gl) )
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		{
			///Kyle 07/21/2010 ORG-584-P2 CHECK_SHOW_DIALOG_AFTER_LOADING_PROFILE
			if( pbIsActive )
				*pbIsActive = true;
			///End CHECK_SHOW_DIALOG_AFTER_LOADING_PROFILE
			return m_nActiveProfileIndex;
		}
	}
	///End CENTRALIZE_EVENT_HANDLING

	for(int nIndex = m_arrProfileMngr.GetSize() - 1; nIndex >= 0; nIndex--)
	{
		ImageProfileManager& profile = m_arrProfileMngr.GetAt(nIndex);
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//if( profile.GetSourcePage()==gp || profile.IsRelatedLayer(gl) )
		if( profile.IsRelatedLayer(gl) )
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
			return nIndex;
	}

	nIndex = -1;
	if( bLoadProfile )
	{
		///Kyle 06/17/2010 ORG-98 ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		//ImageProfileManager* pProfile = new ImageProfileManager(gp, -1, 0);			// layout mode will load from page
		ImageProfileManager* pProfile = new ImageProfileManager(gl, -1, 0);			// layout mode will load from page
		///End ONE_LAYER_ONE_PROFILE_AND_SHARE_CALCULATOR_TO_SPEED_UP
		if( pProfile )
		{
			if( pProfile->InitFromStorage() )
			{
				pProfile->SetReady(true);
				nIndex = m_arrProfileMngr.Add(*pProfile);
				///Kyle 07/14/2010 ORG-572-P1 SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE
				GraphPage gp = pProfile->GetSourcePage();
				checkSetPageNoClick(gp, true);
				///End SET_GRAPH_NOCLICK_AND_RESET_NOCLICK_ON_CLOSE
				
				pProfile->SetKeepGraphsOnClosing(true);		///Kyle 07/21/2010 ORG-584-P2 KEEP_GRAPHS_ON_CLOSING_SHOULE_BE_CHECKED_FOR_A_PROFILE_LOAD_FROM_STORAGE
			}
			else
			{
				pProfile->SetReady(false);
				pProfile->SetKeepGraphsOnClosing(true);				// remove the profile class object only
				delete pProfile;
			}
		}
	}

	return nIndex;
}

void	ImageProfileHolder::sendMessage(DWORD wParam, DWORD lParam) // = 0
{
	if( m_pParentWnd )
		m_pParentWnd->SendMessage(WM_USER_IMAGE_PROFILE_UPDATE, wParam, lParam);
}


 
/*----------------------------------------------------------------------------*/
/* Public interface
/*----------------------------------------------------------------------------*/
BOOL ImageProfile(int nMsg, int nLayoutMode = IMAGE_PROFILE_LAYOUT_SAME_GRAPH_CLINE, DWORD dwOptions = IPROFILE_PROTECT_SOURCE)
{
	if (OMSG_CLOSE == nMsg)
	{
		if (s_pProfileDlg)
		{
			s_pProfileDlg->SendMessage(WM_CLOSE);
		}
		return TRUE;
	}

	if ( !s_pProfileDlg )
	{
		s_pProfileDlg = new ImageProfileDlg();

		if( !s_pProfileDlg || !s_pProfileDlg->Create(GetWindow()) )
			return error_report("Failed to create the tool window!", true);

		get_image_profile_holder()->SetParentWnd(s_pProfileDlg);
	}
	s_pProfileDlg->ShowWindow(SW_NORMAL);				// run time error if dlg hidden, show it first
	s_pProfileDlg->StartProfile(nLayoutMode, dwOptions);

	return TRUE;
}


bool	is_good_layer_for_profile(const GraphLayer& gl)
{
	if( !gl )
		return false;

	DataPlot dp = gl.DataPlots();
	if( !dp )
		return false;

	return is_good_plot_for_profile(dp);
}

bool	is_good_plot_for_profile(const DataPlot& dp)
{
	if( !dp )
		return false;

	// only xyz and matrix contour plot and gray scale image plot are supported for now
	switch( dp.GetPlotType() )
	{
	case IDM_PLOT_CONTOUR:
	case IDM_PLOT_MATRIX_IMAGE:
		{
			DataRange rng;
			if( !dp.GetDataRange(rng) || !rng )
				return false;

			int c1, c2;
			Datasheet ds;
			rng.GetRange(ds, c1, c2);
			MatrixLayer ml(ds);
			if(ml)
			{
				MatrixObject mo(ml, c1);
				if( !mo || (ml.HasImage() && !mo.HasData()) )
					return false;
			}
			else
			{
				// disable profiling in virtual matrix contour plot in 8.5.0
				/*
				// virtual matrix
				MatrixObject mo;
				mo.Attach(rng);
				if( !mo )
					return false;
				*/
				return false;
			}
			return true;
		}

	case IDM_PLOT_TRI_CONTOUR:
		//disable profiling in xyz contour plot in 8.5.0
		//return true;
		return false;
	}

	return false;
}


ImageProfileHolder* get_image_profile_holder()
{
	static ImageProfileHolder s_ImageProfileHolder;
	return &s_ImageProfileHolder;
}


static void _layer_set_postion_no_change_unit(GraphLayer& gl, double xx[TOTAL_POS], bool bUndo)
{
	ASSERT(gl);

	DWORD dwCtrl = bUndo ? OCD_UNDO : OCD_ASK;		// OCD_ASK is default setting in SetPosition

	// convert unit to Percent
	double xxTemp[TOTAL_POS];
	int nUnit = gl.GetPosition(xxTemp);
	gl.UnitsConvert(M_PERCENT, xxTemp);
	gl.SetPosition(xxTemp, M_PERCENT, dwCtrl);
	
	gl.UnitsConvert(nUnit, xx);
	gl.SetPosition(xx, nUnit, dwCtrl);
}


/*----------------------------------------------------------------------------*/
/* static
/*----------------------------------------------------------------------------*/

///Kyle 06/18/2010 ORG-98-S38 ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES
static string _get_pos_string_for_label_text(double dPos)
{
	return ftoa(dPos, "*4*");
}
///End ONLY_NEED_TO_SHOW_4_SIGNIFICANT_DIGITS_FOR_POS_VALUES

///Kyle 06/17/2010 ORG-98-S40 NEW_WIDTH_CONTROL_WITHOUT_DROP_DOWN
static void _update_profile_width_to_treenode(TreeNode& trn, ImageProfilerPath* pPath, int nUnit)
{
	ASSERT(trn && pPath);
	switch(nUnit)
	{
	case IPROFILE_PATH_WIDTH_PIXEL:
		{
			int nWidthInPixel = nint(pPath->GetProfileWidth(IPROFILE_PATH_WIDTH_PIXEL));
			if( nWidthInPixel < 1 )
				nWidthInPixel = 1;
			trn.nVal = nWidthInPixel;
		}
		break;
		
	case IPROFILE_PATH_WIDTH_SCALE:
		{
			double dWidthInScale = pPath->GetProfileWidth(IPROFILE_PATH_WIDTH_SCALE);
			//trn.strVal = dWidthInScale > 1.0 ? ftoa(dWidthInScale, ".2*") : ftoa(dWidthInScale, "*2*");
			trn.dVal = dWidthInScale;		// show full precision in edit mode
		}
		break;
		
	default:
		ASSERT(0);
	}
}
///End NEW_WIDTH_CONTROL_WITHOUT_DROP_DOWN

///Kyle 06/12/2010 ORG-98-S37 SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE
static void _construct_default_profile_width(ImageProfilerPath* pPath, vector<int>& vnWidthInPixel, string& strWidths)
{
	ASSERT(pPath);

	vector vWidthInScale;
	pPath->GetSuitableWidths(vnWidthInPixel, vWidthInScale);
	ASSERT( vnWidthInPixel.GetSize() == vWidthInScale.GetSize() );

	vector<string> vsFormat(vWidthInScale.GetSize());
	for(int ii = 0; ii < vsFormat.GetSize(); ii++)
	{
		if( vWidthInScale[ii] > 1.0 )
			vsFormat[ii] = ".2*";
		else
			vsFormat[ii] = "*2*";
	}
	vector<string> vsWidthInScale;
	convert_double_vector_to_string_vector(vWidthInScale, vsWidthInScale, vWidthInScale.GetSize(), vsFormat);

	for(ii = vnWidthInPixel.GetSize() - 1; ii > 0; ii--)
	{
		vector<uint> vec;
		if( vnWidthInPixel[ii]==vnWidthInPixel[ii-1] ||
			vsWidthInScale.Find(vsWidthInScale[ii], 0, true, true, ii-1) >= 0)
		{
			vnWidthInPixel.RemoveAt(ii);
			vsWidthInScale.RemoveAt(ii);
		}
	}
	for(ii = 0; ii < vnWidthInPixel.GetSize(); ii++)
	{
		string str;
		str.Format("%d pixel = %s", vnWidthInPixel[ii], vsWidthInScale[ii]);
		vsWidthInScale[ii] = str;
	}

	strWidths.SetTokens(vsWidthInScale, '|');
}
///End SUPPORT_WIDTH_IN_PIXEL_AND_IN_SCALE

///Kyle 07/21/2010 ORG-584-P4 CHECK_RESET_LINE_WIDTH_FOR_LOG_SCALE
static bool _is_width_diff(double dWidth1, double dWidth2)
{
	return is_equal(prec(dWidth1, 3), prec(dWidth2, 3), '!');
}

static bool _check_reset_rect_width(vector& vx, vector& vy, bool bVertical, double dWidth, bool& bChange)
{
	bChange = false;
	if( vx.GetSize() != 4 || vy.GetSize() != 4 )
		return false;

	double dXMin, dXMax, dYMin, dYMax;
	vx.GetMinMax(dXMin, dXMax);
	vy.GetMinMax(dYMin, dYMax);

	if( bVertical )
	{
		if( _is_width_diff(dXMax - dXMin, dWidth) )
		{
			bChange = true;
			double dMid = 0.5 * (dXMax + dXMin);
			double x0 = dMid - 0.5*dWidth;
			double x1 = dMid + 0.5*dWidth;
			
			vx[0] = x0, vx[1] = x1; vx[2] = x1; vx[3] = x0;
		}
	}
	else
	{
		if( _is_width_diff(dYMax - dYMin, dWidth) )
		{
			bChange = true;
			double 	dMid = 0.5 * (dYMax + dYMin),
					y0 = dMid - 0.5*dWidth,
					y1 = dMid + 0.5*dWidth;

			vy[0] = y0, vy[1] = y0; vy[2] = y1; vy[3] = y1;
		}
	}

	return true;
}
///End CHECK_RESET_LINE_WIDTH_FOR_LOG_SCALE

static bool _transfer_pos_for_rect(vector& vx, vector& vy, bool bLine2Rect, bool bVertical, double dWidth = 0)
{
	if( !(vx && vy) )
			return false;
	
	if( bLine2Rect )
	{
		if( !(vx.GetSize()==2 && vy.GetSize()==2) )
			return false;

		double x0, x1, y0, y1;
		if( bVertical )
		{
			ASSERT( is_equal(vx[0], vx[1]) );

			x0 = vx[0] - 0.5*dWidth;
			x1 = vx[0] + 0.5*dWidth;

			y0 = vy[0];
			y1 = vy[1];
		}
		else
		{
			ASSERT( is_equal(vy[0], vy[1]) );

			x0 = vx[0];
			x1 = vx[1];

			y0 = vy[0] - 0.5*dWidth;
			y1 = vy[0] + 0.5*dWidth;
		}

		vx.SetSize(4);
		vy.SetSize(4);

		vx[0] = x0, vx[1] = x1; vx[2] = x1; vx[3] = x0;
		vy[0] = y0, vy[1] = y0; vy[2] = y1; vy[3] = y1;
	}
	else
	{
		if( !(vx.GetSize()==4 && vy.GetSize()==4) )
			return false;

		double dXMin, dXMax, dYMin, dYMax;
		vx.GetMinMax(dXMin, dXMax);
		vy.GetMinMax(dYMin, dYMax);

		vx.SetSize(2);
		vy.SetSize(2);
		if( bVertical )
		{
			vx[0] = vx[1] = 0.5 * (dXMin + dXMax);
			vy[0] = dYMin;
			vy[1] = dYMax;
		}
		else
		{
			vx[0] = dXMin;
			vx[1] = dXMax;
			vy[0] = vy[1] = 0.5 * (dYMin + dYMax);
		}
	}

	return true;
}

//static bool _clear_related_dataset(DataPlot& dp)
//{
	//if( !dp )
		//return false;
//
	//vector<string> vs;
	//dp.GetRelatedDatasetNames(vs);
	//
	//for(int ii = vs.GetSize()-1; ii>=0; ii--)
	//{
		//if( vs[ii].Find(STR_IMAGE_PROFILE_RELATED_DATASET) == 0 )
			//dp.RemoveRelatedDataset(vs[ii]);
	//}
//
	//return true;
//}

static string _get_data_plot_range_string(const DataPlot& dp)
{
	string str;
	if( dp )
		dp.GetLegend(str);
	return str;
	//DataRange dr;
	//if( dp && dp.GetDataRange(dr) )
	//{
		//return get_input_data_range_string(dr);
	//}
//
	//return "";
}

static bool _find_dp_coordinates(const DataPlot& dpSrc, int& nRows, int& nCols)
{
	if( !dpSrc )
		return false;

	switch( dpSrc.GetPlotType() )
	{
	case IDM_PLOT_CONTOUR:
	case IDM_PLOT_MATRIX_IMAGE:
		{
			DataRange rng;
			if( !dpSrc.GetDataRange(rng) || !rng )
				return false;

			int c1, c2;
			MatrixLayer ml;
			rng.GetRange(ml, c1, c2);

			MatrixObject mo(ml, c1);
			if(mo)
			{
				nRows = mo.GetNumRows();
				nCols = mo.GetNumCols();
			}
			else
			{
				// virtual matrix
				mo.Attach(rng);
				if( !mo )
					return false;

				Worksheet wks;
				int r1, r2;

				int nZIndex = rng.GetRange("Z", r1, c1, r2, c2, wks);
				if( nZIndex < 0 || !wks )
					return false;
				if( c2 < 0 )
					c2 = wks.GetNumCols()-1;
				if( r2 < 0 )
					r2 = wks.GetNumRows()-1;

				nRows = r2 - r1 + 1;
				nCols = c2 - c1 + 1;
			}
		}
		break;

	case IDM_PLOT_TRI_CONTOUR:
		{
			TRIANGULATION	*pTriInfo = dpSrc.GetTriangulationData();
			if( !pTriInfo )
				return false;

			int nSize = pTriInfo->np;
			nRows = nCols = sqrt(nSize);
		}
		break;

	default:
		ASSERT(0);
		return false;
	}

	return true;

}

static double _get_go_width(GraphObject& go)
{
	if( !go )
		return NANUM;

	Tree trFmt;
	trFmt = go.GetFormat(FPB_STYLE_LINE, FOB_ALL, true, true);
	return trFmt.Root.Width ? trFmt.Root.Width.dVal : NANUM;
}

static int _get_graph_object_color(const GraphObject& go)
{
	if( !go )
		return -1;

	Tree tr; tr = go.GetFormat(FPB_STYLE_COLOR, FOB_ALL, true, true);
	return tr.Root.Color ? tr.Root.Color.nVal : -1;
}

static bool _set_graph_object_color(GraphObject& go, int nColor)
{
	if( !go )
		return false;

	Tree tr;
	tr.Root.Color.nVal = nColor;

	if( 0 == go.UpdateThemeIDs(tr.Root) )
		return go.ApplyFormat(tr, true, true);

	return false;
}

static bool _check_min_max(vector& vec, double dFrom, double dTo)
{
	double dMin, dMax;
	vec.GetMinMax(dMin, dMax);

	bool bUpdate = false;
	if( dMin < dFrom )
	{
		if(dMax + (dFrom - dMin) <= dTo)
			vec += (dFrom - dMin);
		else
		{
			for( int ii = vec.GetSize()-1; ii >= 0; ii--)
			{
				if( vec[ii] < dFrom )
					vec[ii] = dFrom;
			}
		}
		bUpdate = true;
		
	}

	if( dMax > dTo )
	{
		if(dMin - (dMax - dTo) >= dFrom)
			vec -= (dMax - dTo);
		else
		{
			for( int ii = vec.GetSize()-1; ii >= 0; ii--)
			{
				if( vec[ii] > dTo )
					vec[ii] = dTo;
			}
		}
		bUpdate = true;
	}
	
	return bUpdate;
}


//bool page_arrange_profile_layer(GraphPage& gp, int nXPercent, int nYPercent, bool bUndo)
bool	page_arrange_profile_layer(GraphPage& gp, int nMainLayer, int nVLayer, int nHLayer, int nVPercent, int nHPercent, bool bUndo)
{
	if( !gp.IsValid() || nMainLayer<0 ||
		(nVLayer >= 0 && (nVPercent < 0 || nVPercent >= 100)) ||
		(nHLayer >= 0 && (nHPercent < 0 || nHPercent >= 100)) )
		return false;

	GraphLayer glMain, glV, glH;
	glMain = gp.Layers(nMainLayer);
	if( !glMain )
		return false;
	if( nVLayer >= 0 )
	{
		glV = gp.Layers(nVLayer);
		if( !glV )
			return false;
	}
	else
		nVPercent = 0;
	if( nHLayer >= 0 )
	{
		glH = gp.Layers(nHLayer);
		if( !glH )
			return false;
	}
	else
		nHPercent = 0;

	stLayersGridFormat stFormat;
	stFormat.nXGap = 5;
	stFormat.nYGap = 5;
	stFormat.nLeftMg = 10;
	stFormat.nRightMg = 10;
	stFormat.nTopMg = 10;
	stFormat.nBottomMg = 10;

	int nXMain = 100 - stFormat.nLeftMg - stFormat.nRightMg - (nVPercent ? (nVPercent + stFormat.nXGap) : 0);
	int nYMain = 100 - stFormat.nTopMg - stFormat.nBottomMg - (nHPercent ? (nHPercent + stFormat.nYGap) : 0);

	if(nXMain < 5 || nYMain < 5)
		return false; //Error! Resulting main layer are too small.

	double xxMain[TOTAL_POS];

	// main layer, left bottom
	xxMain[WIDTH_POS] = nXMain;
	xxMain[HEIGHT_POS] = nYMain;
	xxMain[LEFT_POS] = stFormat.nLeftMg;
	xxMain[TOP_POS] = 100 - stFormat.nBottomMg - nYMain;
	_layer_set_postion_no_change_unit(glMain, xxMain, bUndo);

	if( glH )
	{
		double xxX[TOTAL_POS];

		xxX[WIDTH_POS] = nXMain;
		xxX[HEIGHT_POS] = nHPercent;
		xxX[LEFT_POS] = stFormat.nLeftMg;
		xxX[TOP_POS] = stFormat.nTopMg;

		_layer_set_postion_no_change_unit(glH, xxX, bUndo);

		layer_set_link(glH, 0, 1);
		layer_set_scale_elements(glH, 1, 1, bUndo);
	}

	if( glV )
	{
		double xxY[TOTAL_POS];

		xxY[WIDTH_POS] = nVPercent;
		xxY[HEIGHT_POS] = nYMain;
		xxY[LEFT_POS] = stFormat.nLeftMg + nXMain + stFormat.nXGap;
		xxY[TOP_POS] = xxMain[TOP_POS];
	
		_layer_set_postion_no_change_unit(glV, xxY, bUndo);

		vector<int> vnAxes(4), vnTicks(4);
		vnAxes[AXIS_BOTTOM] = true;
		vnAxes[AXIS_LEFT] = false;
		vnAxes[AXIS_TOP] = false;
		vnAxes[AXIS_RIGHT] = true;
	
		vnTicks[AXIS_BOTTOM] 	= TICK_OUT;
		vnTicks[AXIS_LEFT] 		= TICK_NONE;
		vnTicks[AXIS_TOP] 		= TICK_NONE;
		vnTicks[AXIS_RIGHT] 	= TICK_OUT;
		gl_smart_show_object(glV, vnAxes, vnAxes, vnAxes, vnTicks);

		string strLT;
		strLT.Format("%s!layer%d.exchangexy=%d", gp.GetName(), glV.GetIndex()+1, 1);
		LT_execute(strLT);

		layer_set_link(glV, 0, 2, 0, NULL, "Y1", "Y2");
		layer_set_scale_elements(glV, 1, 1, bUndo);
	}

	return true;
}



#ifdef _DEBUG
void DestroyImageProfileDlg()
{
	if(s_pProfileDlg)
	{
		s_pProfileDlg->m_bDeleteOnDestroy = TRUE;
		ImageProfile(OMSG_CLOSE);
	}
	get_image_profile_holder()->ClearAllProfile();
}
#endif//_DEBUG

/*----------------------------------------------------------------------------*/
/* graph object event
/*----------------------------------------------------------------------------*/

BOOL CheckInitImageProfileDlgAndExecEvent(int nEvent, string strLayerName, string strObjectName)
{
	///Kyle 06/24/2010 ORG-288 WALK_AROUND_ORIGIN_CRASH_ON_COPY_PASTE_FORMAT_FROM_SOURCE_LAYER_TO_OUTPUT_LAYER
	/*
	if( OE_WIN_CLOSE!=nEvent && OE_SCALE_CHANGE!=nEvent && OE_STYLE_CHANGE!=nEvent && OE_SELECT!=nEvent && OE_GRAPHOBJ_EDIT!=nEvent && OE_MOVE!=nEvent && OE_DELETE!=nEvent && OE_DELETE_PART!=nEvent )
		return true;

	{
	*/
	///End WALK_AROUND_ORIGIN_CRASH_ON_COPY_PASTE_FORMAT_FROM_SOURCE_LAYER_TO_OUTPUT_LAYER
		GraphLayer gl;
		 if( !okxf_resolve_string_get_origin_object(strLayerName, &gl) )
		 	return false;
		GraphObject go = gl.GraphObjects(strObjectName);
		if( !go )
			return false;
	
		if(OE_GRAPHOBJ_EDIT == nEvent || OE_SELECT == nEvent || OE_MOVE == nEvent || OE_MOVING == nEvent)
		{
			///Kyle 07/21/2010 ORG-584-P2 CHECK_SHOW_DIALOG_AFTER_LOADING_PROFILE
			//int nProfileIndex = get_image_profile_holder()->CheckLoadProfile(gl, true);
			//if(nProfileIndex >= 0 && !s_pProfileDlg)
			//{
			//	ImageProfile(OMSG_OPEN);		// new the dialog and save to profile holder
			//	ASSERT(s_pProfileDlg);
			//}
			bool bIsActive;
			int nProfileIndex = get_image_profile_holder()->CheckLoadProfile(gl, true, &bIsActive);
			if( nProfileIndex >= 0 && (!s_pProfileDlg || !bIsActive) )
			{
				if( s_pProfileDlg )
				{
					get_image_profile_holder()->OnActiveLayerChange();
				}
				else
				{
					ImageProfile(OMSG_OPEN);		// new the dialog and save to profile holder if dialog doesn't exist, and activate the current profile
					ASSERT(s_pProfileDlg);
				}
			}
			///End CHECK_SHOW_DIALOG_AFTER_LOADING_PROFILE
		}

		if( !get_image_profile_holder()->IsUpdatingHolder() )
		{
		const UINT uObjUID = go.GetUID(TRUE);
		const UINT uPageUID = gl.GetPage().GetUID(TRUE);
			get_image_profile_holder()->OnImageProfileEvent(nEvent, uPageUID, uObjUID);
		}
	//}		///Kyle 06/24/2010 ORG-288 WALK_AROUND_ORIGIN_CRASH_ON_COPY_PASTE_FORMAT_FROM_SOURCE_LAYER_TO_OUTPUT_LAYER

	return TRUE;
}


BOOL OnHVProfileReadOutChange(int nEvent, string strLayerName, string strObjectName)
{
	///Kyle 06/24/2010 ORG-288 WALK_AROUND_ORIGIN_CRASH_ON_COPY_PASTE_FORMAT_FROM_SOURCE_LAYER_TO_OUTPUT_LAYER
	/*
	if( OE_SELECT!=nEvent )
		return true;

	{
	*/
	///End WALK_AROUND_ORIGIN_CRASH_ON_COPY_PASTE_FORMAT_FROM_SOURCE_LAYER_TO_OUTPUT_LAYER
		GraphLayer gl;
		 if( !okxf_resolve_string_get_origin_object(strLayerName, &gl) )
		 	return false;
		GraphObject go = gl.GraphObjects(strObjectName);
		if( !go )
			return false;
	
		int nType;
		go.GetObjectType(&nType);
		if( GROBJ_TN_TEXT == nType && OE_SELECT == nEvent )			// take care of select event only for now
		{
			if( !get_image_profile_holder()->IsUpdatingHolder() )
			{
			const UINT uObjUID = go.GetUID(TRUE);
			const UINT uPageUID = gl.GetPage().GetUID(TRUE);
				get_image_profile_holder()->OnProfileReadOutEvent(nEvent, uPageUID, uObjUID);
			}
		}
	//}		///Kyle 06/24/2010 ORG-288 WALK_AROUND_ORIGIN_CRASH_ON_COPY_PASTE_FORMAT_FROM_SOURCE_LAYER_TO_OUTPUT_LAYER

	return TRUE;
}
