/*------------------------------------------------------------------------------*
 * File Name: VerticalCursorDlg.c												*
 * Creation: Kenny 02/24/2009													*
 * Purpose: OriginC Source C file												*
 * Copyright (c) OriginLab Corp. 2009											*
 * All Rights Reserved															*
 *																				*
 * Modification Log:															*
 *	Jasmine 12/08/09 QA81-8980 MORE_CONFIGURATION_FOR_INFO_TABLE				*
 *	Folger 01/15/10 X_VALUE_IN_EDITBOX_SHOULD_NOT_CHANGE_AFTER_ENTER_A_NEW_VALUE*
 *	Jasmine 01/15/10 REORDER_CURSOR_VALUE_BY_LAYER_POS							*
 *	Jasmine 01/15/10 UPDATE_LIST_WITH_SORT_ORDER								*
 *	Jasmine 01/18/10 CONFIGURE_SHOW_HIDE_SETTING								*
 *	Jasmine 01/18/10 SHOW_MORE_THAN_ONE_PLOT_INFO_AT_A_TIME						*
 *	Jasmine 01/20/10 SHOW_XVALUE_WITH_FORMAT									*
 *	Jasmine 01/20/10 SHOW_NEAREST_POINT											*
 *	Jasmine 01/22/10 BTN_TO_ACTIVATE_OUTPUT_WKS									*
 *	Folger 01/22/09 ORIGIN_CRASH_WHEN_EXIT_IF_GRAPH_PAGE_HAS_VERTICAL_CURSOR_IS_NOT_ACTIVE
 *	Folger 01/22/10 CURSOR_X_COORDINATE_LOSE_PRECISION_IN_INFO_TABLE			*
 *	Kyle 01/26/2010 SNAP_CURSOR_TO_DATA_PLOT									*
 *	Folger 01/27/10 VERTICAL_CURSOR_DIALOG_STILL_SHOW_AFTER_CURSOR_LINE_DELETED	*
 *	Folger 01/27/10 VERTICAL_CURSOR_SNAP_TO_NEAREST_X_DATA						*
 *	Jasmine 01/28/10 RESTRICT_X_EDIT_TEXT										*
 *	Folger 01/28/10 SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG						*
 *	Jasminie 01/29/10 CONFIGURE_SHOW_HIDE_SETTING_BY_MENU						*
 *	Jasmine 02/08/10 HIDE_SNAP_OPTION_TO_SIMPLIFY_GUI							*
 *	Jasmine 02/08/10 REMEMBER_SNAP_OPTION										*
 *	Jasmine 02/08/10 MENU_NOT_HAVE_ALL_COLUMN_SO_CAN_HIDE_ALL_MENU_COL			*
 *	Jasmine 02/08/10 ENABLE_ACTIVATE_BTN_BY_CHECK_REPORT_SHEET					*
 *	Folger 07/06/10 ORG-436 BETTER_USE_OC_DEVICE_CONTEXT						*
 *------------------------------------------------------------------------------*/

#define REMOVE_TAG_FEATURE
#define REMOVE_LABEL_FEATURE
 
#include <Origin.h>
#include <..\Originlab\DialogEx.h>
#include "VerticalCursorManager.h"
#include "GridTableControl.h"

#define _CAT								"Vertical Cursor"

/*----------------------------------------------------------------------------*/
/* Macros/Enums
/*----------------------------------------------------------------------------*/

#define STR_NODE_TAG_NAME_DIALOG				"VDialog"


enum TAGINFOGRIDCOLTYPE
{
	TAGINFOGRIDCOLTYPE_TAG_UID					= 0,
	TAGINFOGRIDCOLTYPE_X_SCALE,
	TAGINFOGRIDCOLTYPE_Y_SCALE,
	TAGINFOGRIDCOLTYPE_PLOT_NAME,

	TAGINFOGRIDCOLTYPE_TOTAL,
};

#define STR_TAG_INFO_GRID_COLS					_LC("Tag UID|X|Y|Plot Name", _CAT)

#define INFO_LIST_CONTEXT_MENU_ID_INVALID		0
enum
{
	TAG_INFO_CONTEXT_MENU_ID_INVALUD			= INFO_LIST_CONTEXT_MENU_ID_INVALID,
	TAG_INFO_CONTEXT_MENU_ID_REMOVE,
	TAG_INFO_CONTEXT_MENU_ID_CLEAR_ALL,
};


//keep TEXTLABELINFOGRIDCOLTYPE and STR_TEXT_LABEL_INFO_GRID_COLS consistent
#define STR_TEXT_LABEL_INFO_GRID_COLS			_LC("Snap To|Nearest Index|X|Y|Nearest X|Nearest Y|ID", _CAT)+"|"+LABEL_SHORT_NAME+"|"+STR_LONG_NAME_LABEL+"|"+LABEL_SHEET_NAME+"|"+LABEL_BOOK_NAME	///Jasmine 12/08/09 QA81-8980 MORE_CONFIGURATION_FOR_INFO_TABLE
enum TEXTLABELINFOGRIDCOLTYPE
{
	TEXTLABELINFOGRIDCOLTYPE_SNAPTO			= 0,
	TEXTLABELINFOGRIDCOLTYPE_INDEX,				///Jasmine 12/08/09 QA81-8980 MORE_CONFIGURATION_FOR_INFO_TABLE
	TEXTLABELINFOGRIDCOLTYPE_X_SCALE,
	TEXTLABELINFOGRIDCOLTYPE_Y_SCALE,
	TEXTLABELINFOGRIDCOLTYPE_NEAREST_X,	///Jasmine 01/20/10 SHOW_NEAREST_POINT 		
	TEXTLABELINFOGRIDCOLTYPE_NEAREST_Y,
	TEXTLABELINFOGRIDCOLTYPE_ID,				///Jasmine 01/15/10 UPDATE_LIST_WITH_SORT_ORDER
	///Jasmine 01/18/10 CONFIGURE_SHOW_HIDE_SETTING
	TEXTLABELINFOGRIDCOLTYPE_SHORTNAME,
	TEXTLABELINFOGRIDCOLTYPE_LONGNAME,
	TEXTLABELINFOGRIDCOLTYPE_SHEETNAME,
	TEXTLABELINFOGRIDCOLTYPE_BOOKNAME,
	///End CONFIGURE_SHOW_HIDE_SETTING
	TEXTLABELINFOGRIDCOLTYPE_TOTAL,
};


/*----------------------------------------------------------------------------*/
/* Global Variable
/*----------------------------------------------------------------------------*/
class GraphVerticalCursorDlg;
static GraphVerticalCursorDlg* s_pVerticalCursorDlg = NULL;

#ifdef _DEBUG
static BOOL s_bDestroyDlgOnClose = FALSE;
#endif // _DEBUG

/*----------------------------------------------------------------------------*/
/* Local util functions
/*----------------------------------------------------------------------------*/

static void _move_control_no_size(Control& ctrl, RECT& rt, int nX, int nY)
{
	rt.right = nX + RECT_WIDTH(rt);
	rt.left = nX;
	rt.bottom = nY + RECT_HEIGHT(rt);
	rt.top = nY;
	ctrl.MoveWindow(&rt, TRUE);
}

/*----------------------------------------------------------------------------*/
/* InfoListContextMenu
/*----------------------------------------------------------------------------*/

class InfoListContextMenu : public MenuBase
{
public:
	InfoListContextMenu(const vector<int>& vnIDs, const vector<string>& vsText, const vector<bool>& vbEnables)
	{
		const int nIDSize = vnIDs.GetSize();
		if (nIDSize != vsText.GetSize() || nIDSize != vbEnables.GetSize())
		{
			ASSERT(FALSE);
			return;
		}
		for(int ii = 0; ii < nIDSize; ++ii)
		{
			int nFlags;
			if(INFO_LIST_CONTEXT_MENU_ID_INVALID == vnIDs[ii])
				nFlags = MF_SEPARATOR;
			else
			{
				nFlags = MF_STRING;
				if(!vbEnables[ii])
					nFlags |= MF_GRAYED | MF_DISABLED;
			}
			Add(vsText[ii], OnMenuItem, nFlags, vnIDs[ii]);
		}
	}
};

/*----------------------------------------------------------------------------*/
/* InfoGridTableControlBase class
/*----------------------------------------------------------------------------*/

class InfoGridTableControlBase : public GridTableControl
{
public:
	virtual void Init(int nID, Dialog& dlg, LPCSTR lpcszDlgName, int nCols, LPCSTR lpcszColHeader)
	{
		GridTableControl::Init(nID, dlg, lpcszDlgName);

		SetCols(nCols);
		SetColHeaderString(lpcszColHeader);

		SetupColTypes();
	}
	virtual void OnBeforeMouseDown(short nButton, short nShift, float X, float Y, BOOL* pCancel)
	{
		if(nButton != MK_RBUTTON || nShift != 0)
			return;
		int nRow = m_flx.MouseRow;
		int nCol = m_flx.MouseCol;
		vector<UINT> vnRows;
		GetSelRows(vnRows);
		if(nRow < 0 || nCol < 0)
		{
			RemoveSelection();
		}
		else
		{
			vector<uint> vec;
			if(vnRows.Find(vec, nRow) <= 0)
				SelRow(nRow);
		}
		GetSelRows(vnRows);

		int    nx = XTwipsToPixels(X);
		int    ny = YTwipsToPixels(Y);
		ClientToScreen(nx, ny);

		vector<int> vnIDs;
		vector<string> vsText;
		vector<bool> vbEnable;
		if ( !GetMenuInfo(vnIDs, vsText, vbEnable) )
			return;
		
		InfoListContextMenu contextMenu(vnIDs, vsText, vbEnable);

		int nID = 0;
		contextMenu.TrackPopupMenu(0, nx, ny, GetDlgSafeHwnd(), &nID);

		OnClickMenuItem(nID);
	}
	
	bool GetInfoTableContent(string& strData, LPCSTR lpcszRowSeparator = NULL, LPCSTR lpcszColSeparator = NULL);	///Jasmine 12/08/09 QA81-8980 MORE_CONFIGURATION_FOR_INFO_TABLE
	
protected:
	virtual void SetupColTypes() { ASSERT(FALSE); }
	virtual BOOL GetMenuInfo(vector<int>& vnIDs, vector<string>& vsText, vector<bool>& vbEnable) { return FALSE; }
	virtual void OnClickMenuItem(const int nID) {}
};

///Jasmine 12/08/09 QA81-8980 MORE_CONFIGURATION_FOR_INFO_TABLE
bool InfoGridTableControlBase::GetInfoTableContent(string& strData, LPCSTR lpcszRowSeparator/* = NULL*/, LPCSTR lpcszColSeparator/* = NULL*/)
{
	strData.Empty();
	
	string strRowSeparator(lpcszRowSeparator);
	if( strRowSeparator.IsEmpty() )
		strRowSeparator = "\r\n";
	
	string strColSeparator(lpcszColSeparator);
	if( strColSeparator.IsEmpty() )
		strColSeparator = "\t";
	
	int nRowCount = GetNumRows();
	if(nRowCount <= 0)
		return false;
	vector<string> vsContents;
	vsContents.SetSize(nRowCount);
	
	for(int nRow = GetRowOffset(), ii = 0; ii < nRowCount; ii++)
	{
		vector<string> vsRowVals;
		GetRowValues(nRow++, vsRowVals);
		if(vsRowVals.GetSize() > 0)
		{
			string strRowValues;
			strRowValues = str_combine(vsRowVals, strColSeparator);
			vsContents[ii] = strRowValues;
		}
	}
	
	strData = str_combine(vsContents, strRowSeparator);
	return true;
}
///End MORE_CONFIGURATION_FOR_INFO_TABLE

/*----------------------------------------------------------------------------*/
/* TagInfoTable class
/*----------------------------------------------------------------------------*/

class TagInfoTable : public InfoGridTableControlBase
{
public:
	TagInfoTable() {}	
	virtual void Init(int nID, Dialog& dlg, LPCSTR lpcszDlgName)
	{
		InfoGridTableControlBase::Init(nID, dlg, lpcszDlgName, TAGINFOGRIDCOLTYPE_TOTAL, STR_TAG_INFO_GRID_COLS);
		SetAllowSelection(true);
		SetSelection(flexSelectionListBox);
		HideCol(0);
	}
protected:
	virtual void SetupColTypes();
	virtual BOOL GetMenuInfo(vector<int>& vnIDs, vector<string>& vsText, vector<bool>& vbEnable);
	virtual void OnClickMenuItem(const int nID);
};

/*----------------------------------------------------------------------------*/
/* The implement of the member function of TagInfoTable class
/*----------------------------------------------------------------------------*/

//virtual 
void TagInfoTable::SetupColTypes()
{
	m_flx.Cols = TAGINFOGRIDCOLTYPE_TOTAL;

	int nCol;
	for(nCol = 0; nCol < m_flx.Cols; nCol++)
	{
		switch(nCol)
		{
		case TAGINFOGRIDCOLTYPE_TAG_UID:
			SetColDataType(nCol, flexDTLong);
			break;
		case TAGINFOGRIDCOLTYPE_X_SCALE:
		case TAGINFOGRIDCOLTYPE_Y_SCALE:
			SetColDataType(nCol, flexDTDouble);
			break;
		case TAGINFOGRIDCOLTYPE_PLOT_NAME:
		default:
			SetColDataType(nCol, flexDTString);
			break;
		}
		SetColAlignment(nCol, flexAlignCenterCenter);
	}		
}

BOOL TagInfoTable::GetMenuInfo( vector<int>& vnIDs, vector<string>& vsText, vector<bool>& vbEnable )
{
	vnIDs.RemoveAll();
	vsText.RemoveAll();
	vbEnable.RemoveAll();

	vector<uint> vnRows;
	GetSelRows(vnRows);

	if( vnRows.GetSize() > 0 )
	{
		vnIDs.Add(TAG_INFO_CONTEXT_MENU_ID_REMOVE);
		vsText.Add( _L("Remove Selected") );
		vbEnable.Add(true);
	}
	if (GetRows() > 1)
	{
		vnIDs.Add(TAG_INFO_CONTEXT_MENU_ID_CLEAR_ALL);
		vsText.Add(_L("Clear All"));
		vbEnable.Add(true);
	}
	return TRUE;
}

void TagInfoTable::OnClickMenuItem( const int nID )
{
	switch (nID)
	{
	case TAG_INFO_CONTEXT_MENU_ID_REMOVE:
		{
			vector<UINT> vnRows;
			GetSelRows(vnRows);
			vector<UINT> vnRemoveTagUID;
			for (int ii = 0; ii < vnRows.GetSize(); ++ii)
			{
				const string strUID = GetCell(vnRows[ii], 0);
				const UINT uTagUID = atoi(strUID);
				vnRemoveTagUID.Add(uTagUID);
			}
			THE_VCURSOR_MANAGER.RemoveTag(vnRemoveTagUID);
		}
		break;
	case TAG_INFO_CONTEXT_MENU_ID_CLEAR_ALL:
		THE_VCURSOR_MANAGER.ClearAllTags();
		break;
	}
}

/*----------------------------------------------------------------------------*/
/* CursorDataInfoTable class
/*----------------------------------------------------------------------------*/

class CursorDataInfoTable : public InfoGridTableControlBase
{
public:
	CursorDataInfoTable() {}	
	virtual void Init(int nID, Dialog& dlg, LPCSTR lpcszDlgName)
	{
		InfoGridTableControlBase::Init(nID, dlg, lpcszDlgName, TEXTLABELINFOGRIDCOLTYPE_TOTAL, STR_TEXT_LABEL_INFO_GRID_COLS);
		
		///Jasminie 01/29/10 CONFIGURE_SHOW_HIDE_SETTING_BY_MENU
		m_vnColMap.Data(0, TEXTLABELINFOGRIDCOLTYPE_TOTAL - 1);		///Jasmine 12/08/09 QA81-8980 MORE_CONFIGURATION_FOR_INFO_TABLE
		
		vector<int> vnPublicCols;
		for(int nType = 0; nType < TEXTLABELINFOGRIDCOLTYPE_TOTAL; nType++)
		{
			if(	TEXTLABELINFOGRIDCOLTYPE_SNAPTO == nType ||
				TEXTLABELINFOGRIDCOLTYPE_ID == nType ||
				TEXTLABELINFOGRIDCOLTYPE_X_SCALE == nType ||
				TEXTLABELINFOGRIDCOLTYPE_Y_SCALE == nType) 
				continue;
			vnPublicCols.Add(nType);
		}
		vector<uint> vnDefaultShows;
		vnDefaultShows.SetSize( vnPublicCols.GetSize() );
		vnDefaultShows = 1;		 
		int nGroup = AddGroup(vnPublicCols, vnDefaultShows);
		ASSERT(0 == nGroup);
		SetGroup(0);
		HideCol(TEXTLABELINFOGRIDCOLTYPE_ID);
		HideCol(TEXTLABELINFOGRIDCOLTYPE_SNAPTO);		///Jasmine 02/08/10 HIDE_SNAP_OPTION_TO_SIMPLIFY_GUI
		///End CONFIGURE_SHOW_HIDE_SETTING_BY_MENU
		
		SetAllowSelection(false);		
		//SetExplorerBar(flexExMove);	///Jasmine 12/08/09 QA81-8980 MORE_CONFIGURATION_FOR_INFO_TABLE
		SetExplorerBar(flexExSortAndMove);	///Jasmine 01/15/10 UPDATE_LIST_WITH_SORT_ORDER
		
		string strToolTips = _L("Drag and drop the column header to reorder the column list");
		SetToolTipsText(strToolTips);
	}

	virtual void OnBeforeMouseDown(short nButton, short nShift, float X, float Y, BOOL* pCancel)
	{
		///Jasminie 01/29/10 CONFIGURE_SHOW_HIDE_SETTING_BY_MENU
		Control ctrl;
		OnBeforeMouseDown(ctrl, nButton, nShift, X, Y, pCancel);
		///End CONFIGURE_SHOW_HIDE_SETTING_BY_MENU
	}
		
	///Jasmine 12/08/09 QA81-8980 MORE_CONFIGURATION_FOR_INFO_TABLE
	void 	OnAfterMoveColumns(long lCol, long *pnPosition);	
	int 	GetColType(int nPosition);
	int		GetColPos(int nType);
	///End MORE_CONFIGURATION_FOR_INFO_TABLE
	
protected:
	virtual void SetupColTypes()
	{
		//in this function can use TEXTLABELINFOGRIDCOLTYPE_* directly as column position 
		//since the order is not changed by drag&drop
		for(int nCol = 0; nCol < m_flx.Cols; nCol++)
		{
			switch(nCol)
			{
			///------ Folger 01/28/10 SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
			case TEXTLABELINFOGRIDCOLTYPE_SNAPTO:
				SetColDataType(nCol, flexDTBoolean);
				break;
			///------ End SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
			case TEXTLABELINFOGRIDCOLTYPE_INDEX:
			case TEXTLABELINFOGRIDCOLTYPE_X_SCALE:
			case TEXTLABELINFOGRIDCOLTYPE_Y_SCALE:
			case TEXTLABELINFOGRIDCOLTYPE_NEAREST_X:	///Jasmine 01/20/10 SHOW_NEAREST_POINT 		
			case TEXTLABELINFOGRIDCOLTYPE_NEAREST_Y:	
			case TEXTLABELINFOGRIDCOLTYPE_ID:
				SetColDataType(nCol, flexDTDouble);
				break;
			default:
				SetColDataType(nCol, flexDTString);
				break;
			}
			SetColAlignment(nCol, flexAlignCenterCenter);
		}
	}
private:
	///Jasmine 02/08/10 MENU_NOT_HAVE_ALL_COLUMN_SO_CAN_HIDE_ALL_MENU_COL
	virtual bool 	toggleShowCol(int nCol, int nNumShowCols = -1)
	{   
		HideCol(nCol, IsColHidden(nCol)? false:true);
	    return true;
  	}
  	///End MENU_NOT_HAVE_ALL_COLUMN_SO_CAN_HIDE_ALL_MENU_COL
private:
	vector<int>		m_vnColMap;		///Jasmine 12/08/09 QA81-8980 MORE_CONFIGURATION_FOR_INFO_TABLE
};

///Jasmine 12/08/09 QA81-8980 MORE_CONFIGURATION_FOR_INFO_TABLE
void CursorDataInfoTable::OnAfterMoveColumns(long lCol, long *pnPosition)	
{
	int nOldPostion = lCol;
	int nNewPostion = -1;
	if(pnPosition)
		nNewPostion = *pnPosition;
	
	int nColMoved = GetColType(nOldPostion);	
	if(nColMoved < 0 || GetColType(nNewPostion) < 0)//lCol or pnPosition may be invalid
	{
		ASSERT(0);
		return;
	}
	
	m_vnColMap.RemoveAt(nOldPostion);
	m_vnColMap.InsertAt(nNewPostion, nColMoved);
	
	///Jasminie 01/29/10 CONFIGURE_SHOW_HIDE_SETTING_BY_MENU
	vector<int> vnPublicCols;
	vector<byte> vnDefaultShows;
	for(int nType = 0; nType < TEXTLABELINFOGRIDCOLTYPE_TOTAL; nType++)
	{
		if(	TEXTLABELINFOGRIDCOLTYPE_SNAPTO == nType ||
			TEXTLABELINFOGRIDCOLTYPE_ID == nType ||
			TEXTLABELINFOGRIDCOLTYPE_X_SCALE == nType ||
			TEXTLABELINFOGRIDCOLTYPE_Y_SCALE == nType) 
			continue;
		
		int nPos = GetColPos(nType);
		vnPublicCols.Add(nPos);
		vnDefaultShows.Add( !IsColHidden(nPos) );
	}
	SetGroupColShows(0, vnPublicCols, vnDefaultShows);
	
	m_strColHeader = "";
	for(int nCol = 0; nCol < m_flx.Cols; nCol++)
	{
		if(nCol != 0)
			m_strColHeader += "|";
		m_strColHeader += GetCell(0, nCol);
	}
	///End CONFIGURE_SHOW_HIDE_SETTING_BY_MENU
}

int CursorDataInfoTable::GetColType(int nPosition)
{
	if( m_vnColMap.GetSize() < TEXTLABELINFOGRIDCOLTYPE_TOTAL //in case m_vnColMap is not ready
		||	0 > nPosition 
		|| nPosition >= TEXTLABELINFOGRIDCOLTYPE_TOTAL)
		return -1;
	
	return m_vnColMap[nPosition];
}

int CursorDataInfoTable::GetColPos(int nType)
{
	if( m_vnColMap.GetSize() < TEXTLABELINFOGRIDCOLTYPE_TOTAL //in case m_vnColMap is not ready
		||	0 > nType 
		|| nType >= TEXTLABELINFOGRIDCOLTYPE_TOTAL)
		return -1;
		
	vector<uint> vecIndex;
	if(m_vnColMap.Find(vecIndex, nType) > 0)
		return vecIndex[0];
	
	return -1;
}
///End MORE_CONFIGURATION_FOR_INFO_TABLE

/*----------------------------------------------------------------------------*/
/* GraphVerticalCursorDlg class
/*----------------------------------------------------------------------------*/

#define STR_DLG_NAME 						_L("Vertical Cursor")

enum
{
	LABEL_INFO_TAB = 0,
	TAG_INFO_TAB,
};


#ifdef REMOVE_TAG_FEATURE
class GraphVerticalCursorDlg : public ResizeDialog
#else
class GraphVerticalCursorDlg : public MultiPaneDlg
#endif
{	
public:
	GraphVerticalCursorDlg();
	~GraphVerticalCursorDlg();
	
	BOOL	Create(HWND hWndParent = NULL);
	BOOL 	StartVerticalCursor();
	void	UpdateDialogData();
	BOOL	ApplyToolSettings(const TreeNode& tnSettings);

protected:
	
EVENTS_BEGIN
	ON_INIT(OnInitDialog) 
	ON_READY(OnReady)
	ON_SIZE(OnDlgResize)
	ON_RESTORESIZE(OnRestoreSize)
	ON_DESTROY(OnDestroy)
	ON_HELPINFO(OnHelp)
	ON_CANCEL(OnClose)
	ON_CHANGE_PAGE(OnActivePageChange)
	ON_OBJECT_MODIFY(OnOriginModify)///Jasmine 02/08/10 ENABLE_ACTIVATE_BTN_BY_CHECK_REPORT_SHEET
	ON_OK(OnOK)
	ON_GETMINMAXINFO(OnMinMaxInfo)
#ifndef REMOVE_TAG_FEATURE
	ON_TAB_SEL_CHANGE(IDC_BOTTOM_INFO_TAB, OnTabChange)
#endif//REMOVE_TAG_FEATURE
	ON_GRID_BEFORE_MOUSE_DOWN(IDC_TAG_INFO_LIST_BOX, OnBeforeMouseDownInfoList)
	ON_GRID_BEFORE_MOUSE_DOWN(IDC_LABEL_INFO_LIST_BOX, OnBeforeMouseDownInfoList)

	ON_GRID_BEFORE_EDIT(IDC_TAG_INFO_LIST_BOX, OnBeforeEditInfoList)
	ON_GRID_BEFORE_EDIT(IDC_LABEL_INFO_LIST_BOX, OnBeforeEditInfoList)
	///------ Folger 01/28/10 SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
	ON_GRID_AFTER_EDIT(IDC_LABEL_INFO_LIST_BOX, OnAfterEditInfoList)
	ON_BN_CLICKED(IDC_SNAP_NEAREST_X, OnCheckUseNearestX)
	///------ End SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
	
	ON_GRID_AFTER_MOVE_COLUMNS(IDC_LABEL_INFO_LIST_BOX, OnAfterMoveColumns)	///Jasmine 12/08/09 QA81-8980 MORE_CONFIGURATION_FOR_INFO_TABLE
	ON_GRID_AFTER_SORT(IDC_LABEL_INFO_LIST_BOX, OnAfterSort)	///Jasmine 01/15/10 UPDATE_LIST_WITH_SORT_ORDER 

	ON_KEY(IDC_TAG_INFO_LIST_BOX, OnKey)
	ON_KEY(IDC_LABEL_INFO_LIST_BOX, OnKey)
	
	ON_USER_MSG(WM_USER_CURSOR_DELETED, OnCursorDeleted)
	ON_USER_MSG(WM_USER_UPDATE_CURSOR_POSITION, OnUpdateCursorPosition)

	ON_USER_MSG(WM_USER_TAG_ADDED, OnTagAdded)
	ON_USER_MSG(WM_USER_TAG_DELETED, OnTagDeleted)
	ON_USER_MSG(WM_USER_UPDATE_TAG_SELECT_STATE, OnUpdateTagSelectState)

	ON_USER_MSG(WM_USER_UPDATE_CURSOR_INTERSECT_POINT_BEGIN, OnUpdateCursorIntersectPointBegin)
	ON_USER_MSG(WM_USER_NEW_CURSOR_INTERSECT_POINT, OnAfterMoveCursor)///Jasmine 01/15/10 REORDER_CURSOR_VALUE_BY_LAYER_POS

	///------ Folger 01/22/10 CURSOR_X_COORDINATE_LOSE_PRECISION_IN_INFO_TABLE
	ON_USER_MSG(WM_USER_QUERY_POSITION_CHANGE_BY_EDITING, OnQueryPositionChangeByEditing)
	///------ End CURSOR_X_COORDINATE_LOSE_PRECISION_IN_INFO_TABLE

	ON_BN_CLICKED(IDC_CHECK_USE_X, OnMoveLineTo)
	
#ifndef REMOVE_LABEL_FEATURE
	ON_USER_MSG(WM_USER_UPDATE_TEXT_LABELS_SHOW_STATE, OnUpdateTextLabelsShowState)
	ON_BN_CLICKED(IDC_BTN_SHOW_LABEL, OnShowLabels)
	ON_BN_CLICKED(IDC_BTN_INCREASE_FONT, OnIncreaseFontSize)
	ON_BN_CLICKED(IDC_BTN_DECREASE_FONT, OnDecreaseFontSize)
#endif//REMOVE_LABEL_FEATURE

#ifndef REMOVE_TAG_FEATURE
	ON_BN_CLICKED(IDC_BTN_ADD_TAG, OnAddTags)
	ON_BN_CLICKED(IDC_BTN_REMOVE_SELECTED_TAGS_GROUPS, OnRemoveSelectedTagsGroups)
	ON_BN_CLICKED(IDC_BTN_CLEAR_ALL_TAGS, OnClearAllTags)
	ON_BN_CLICKED(IDC_BTN_NEXT_TAG, OnSelectNextTagsGroup)
	ON_BN_CLICKED(IDC_BTN_PREVIOUS_TAG, OnSelectPreviousTagsGroup)	
	ON_BN_CLICKED(IDC_BTN_DOWNUP, OnShowBottomPane)
#endif//REMOVE_TAG_FEATURE

	ON_BN_CLICKED(IDC_BTN_CONFIG_OUTPUT, OnConfigureOutput)
	///Jasmine MOVE_OUT_RESULT_SHEET_EDITBOX
	ON_KEY(IDC_EDIT_RESULT_SHEET, OnKeyEditWks)		
	ON_EN_KILLFOCUS(IDC_EDIT_RESULT_SHEET, OnUpdateEditWks)
	///End MOVE_OUT_RESULT_SHEET_EDITBOX
	ON_BN_CLICKED(IDC_BTN_DUMP_TAG_INTO_WKS, OnDumpData)	
	ON_BN_CLICKED(IDC_BTN_ACTIVATE_WKS, OnActivateOutputWks)		///Jasmine 01/22/10 BTN_TO_ACTIVATE_OUTPUT_WKS	
	
EVENTS_END

	BOOL OnInitDialog();
	BOOL OnReady();
	BOOL OnDlgResize(int nType, int cx, int cy);
	BOOL OnRestoreSize(DWORD dwSizeInfo);
	BOOL OnDestroy();
	BOOL OnHelp(int &nHelpID, int nIdCtrlFocus);
	BOOL OnClose();
	BOOL OnActivePageChange();
	BOOL OnOriginModify(OriginObject obj, int nKind);///Jasmine 02/08/10 ENABLE_ACTIVATE_BTN_BY_CHECK_REPORT_SHEET
	BOOL OnOK();
	virtual int GetTotalWidth(bool bGetMin = false);
	virtual int GetTotalHeight(bool bGetMin = false);

	BOOL OnTabChange(Control ctrl);
	BOOL OnKey(Control ctrl, UINT msg, UINT wParam, UINT lParam);
	
	BOOL OnCursorDeleted(uint wParam, uint lParam);
	BOOL OnUpdateCursorPosition(uint wParam, uint lParam);
#ifndef REMOVE_LABEL_FEATURE
	BOOL OnUpdateTextLabelsShowState(uint wParam, uint lParam);
#endif
	BOOL OnTagAdded(uint wParam, uint lParam);
	BOOL OnTagDeleted(uint wParam, uint lParam);
	BOOL OnUpdateTagSelectState(uint wParam, uint lParam);

	BOOL OnUpdateCursorIntersectPointBegin(uint wParam, uint lParam);
	BOOL OnAfterMoveCursor( uint wParam, uint lParam );

	///------ Folger 01/22/10 CURSOR_X_COORDINATE_LOSE_PRECISION_IN_INFO_TABLE
	BOOL	OnQueryPositionChangeByEditing(DWORD wParam, DWORD lParam);
	///------ End CURSOR_X_COORDINATE_LOSE_PRECISION_IN_INFO_TABLE

	BOOL OnMoveLineTo(Control ctrl);
	BOOL OnShowLabels(Control ctrl);
	BOOL OnAddTags(Control ctrl);
	BOOL OnRemoveSelectedTagsGroups(Control ctrl);
	BOOL OnClearAllTags(Control ctrl);
	BOOL OnSelectNextTagsGroup(Control ctrl);
	BOOL OnSelectPreviousTagsGroup(Control ctrl);
	BOOL OnIncreaseFontSize(Control ctrl);
	BOOL OnDecreaseFontSize(Control ctrl);
	BOOL OnConfigureOutput(Control ctrl);
	///Jasmine MOVE_OUT_RESULT_SHEET_EDITBOX
	BOOL OnKeyEditWks(Control ctrl, UINT msg, UINT wParam, UINT lParam);		
	BOOL OnUpdateEditWks(Control ctrl);
	///End MOVE_OUT_RESULT_SHEET_EDITBOX
	BOOL OnDumpData(Control ctrl);
	BOOL OnActivateOutputWks(Control ctrl);		///Jasmine 01/22/10 BTN_TO_ACTIVATE_OUTPUT_WKS	
	
#ifndef REMOVE_TAG_FEATURE
	BOOL OnShowBottomPane(Control ctrl);
#endif
	BOOL OnBeforeMouseDownInfoList(Control cntrl, short nButton, short nShift, float X, float Y, BOOL* pCancel);
	void OnBeforeEditInfoList(Control flxControl, long nRow, long nCol, BOOL* pCancel);
	
	///------ Folger 01/28/10 SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
	void OnAfterEditInfoList(Control flxControl, int nRow, int nCol);
	BOOL OnCheckUseNearestX(Control cntrl);
	///------ End SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
	
	void OnAfterMoveColumns(Control ctrl, long lCol, long *pnPosition);	///Jasmine 12/08/09 QA81-8980 MORE_CONFIGURATION_FOR_INFO_TABLE
	void OnAfterSort(Control ctrl, long lCol, int* pnOrder);	///Jasmine 01/15/10 UPDATE_LIST_WITH_SORT_ORDER 
	
protected:
	int GetBottomPaneSubControls(vector<uint>& vnCntrls);
	int GetMinTopPaneHeight();
	void AllowResizing(BOOL bResizing = TRUE);
		
private:
	void initButtons();
	void arrangeControls();
	void PositionSnapNearestXCheckbox();
	
	void enableActivateBtn(bool bEnable);		///Jasmine 01/22/10 BTN_TO_ACTIVATE_OUTPUT_WKS
	updateSnapCheckBoxes(const VManagerSetting& managerSetting);///Jasmine 02/08/10 REMEMBER_SNAP_OPTION
#ifndef REMOVE_LABEL_FEATURE
	void updateShowHideLabelsBtnState();
#endif
	void updateTagRelatedBtnState(BOOL bEnableBtn = FALSE);
	void updateRemoveSelTagsGrpsBtnState();
	
	void updateCursorPos(bool bIsMoving = false);

	void updateTagsInfo();
	void updateCursorDataInfo();	
	void showCursorInfos(const VCursorShow& cursorshow);///Jasmine 01/18/10 CONFIGURE_SHOW_HIDE_SETTING
	void checkUpdateShowCursorInfos();///Jasminie 01/29/10 CONFIGURE_SHOW_HIDE_SETTING_BY_MENU
	
	void addTagInfoToTable(const VTagUnit& vTagUnit);
	//void removeTagInfoFromTable(const UINT uTagUID);
	void removeTagInfoFromTable(const VTagUnit& vTagUnit);

	int getTitleWidth();
	void getDlgFrameSpace(int* pnFrameHoriz = NULL, int* pnFrameVert = NULL);

	BOOL constructSettingGUITree(TreeNode& tnSettingGUI, const VManagerSetting& managerSetting);
	void showReportSheetName(const VManagerSetting& managerSetting);	///Jasmine MOVE_OUT_RESULT_SHEET_EDITBOX

	BOOL shouldUpdateDialogDataForPage(UINT uPageUID);
	
	BOOL updatePointsIDs(UINT uPageUID);	///Jasmine 01/15/10 UPDATE_LIST_WITH_SORT_ORDER
	
	string	PlotListAttr()		{ return "PlotList"; }
	
private:
#ifdef REMOVE_TAG_FEATURE
	TabControl 				m_BottomTab;
#endif
	Control					m_editPos;
	TagInfoTable			m_TagInfoTable;
	CursorDataInfoTable		m_CursorDataInfoTable;

	int						m_nGroupedBtnTotalWidth;
	///------ Folger 01/15/10 X_VALUE_IN_EDITBOX_SHOULD_NOT_CHANGE_AFTER_ENTER_A_NEW_VALUE
	BOOL					m_bPositionChangeByEditing;
	///------ End X_VALUE_IN_EDITBOX_SHOULD_NOT_CHANGE_AFTER_ENTER_A_NEW_VALUE
};

/*----------------------------------------------------------------------------*/
/* Constructors/Destructors of GraphVerticalCursorDlg
/*----------------------------------------------------------------------------*/

GraphVerticalCursorDlg::GraphVerticalCursorDlg()
#ifdef REMOVE_TAG_FEATURE
	: ResizeDialog(IDD_VERTICAL_CURSOR_DLG, "ODlg8")
#else
	: MultiPaneDlg(IDD_VERTICAL_CURSOR_DLG, "ODlg8")
#endif
{
	MY_DBG_OUTPUT("Constructing Dialog!");
	m_nGroupedBtnTotalWidth = -1;
	///------ Folger 01/15/10 X_VALUE_IN_EDITBOX_SHOULD_NOT_CHANGE_AFTER_ENTER_A_NEW_VALUE
	m_bPositionChangeByEditing = FALSE;
	///------ End X_VALUE_IN_EDITBOX_SHOULD_NOT_CHANGE_AFTER_ENTER_A_NEW_VALUE
}

GraphVerticalCursorDlg::~GraphVerticalCursorDlg()
{
	MY_DBG_OUTPUT("Destructing Dialog!");
}

/*----------------------------------------------------------------------------*/
/* Event handlers of GraphVerticalCursorDlg
/*----------------------------------------------------------------------------*/

BOOL GraphVerticalCursorDlg::OnInitDialog()
{	
	arrangeControls();

#ifdef REMOVE_TAG_FEATURE
	ResizeDialog::OnInitDialog(IDC_BOTTOM_INFO_TAB, STR_DLG_NAME);
	GetItem(IDC_BTN_DOWNUP).Visible = false;
	GetItem(IDC_TAG_INFO_LIST_BOX).Visible = false;
	GetItem(IDC_LABEL_INFO_LIST_BOX).Visible = true;
	m_BottomTab = GetItem(IDC_BOTTOM_INFO_TAB);
#else//REMOVE_TAG_FEATURE
	vector<string>  vstrTipsUpDown;
	vstrTipsUpDown.SetSize(2);
	vstrTipsUpDown[0] = _L("Show Details");
	vstrTipsUpDown[1] = _L("Hide Details");
	MultiPaneDlg::OnInitDialog(IDC_FRAME_TOP_PANE, IDC_BTN_DOWNUP, IDC_BOTTOM_INFO_TAB, vstrTipsUpDown, STR_DLG_NAME, 0, NULL);
	
	m_TagInfoTable.Init(IDC_TAG_INFO_LIST_BOX, *this, STR_DLG_NAME);
#endif//REMOVE_TAG_FEATURE
	m_CursorDataInfoTable.Init(IDC_LABEL_INFO_LIST_BOX, *this, STR_DLG_NAME);
	
	m_BottomTab = GetItem(IDC_BOTTOM_INFO_TAB);
	m_BottomTab.InsertItem(LABEL_INFO_TAB, _LC("Cursor", _CAT));
#ifndef REMOVE_TAG_FEATURE
	m_BottomTab.InsertItem(TAG_INFO_TAB, _LC("Tags", _CAT));
	m_BottomTab.SetCurSel(0);
	OnTabChange(m_BottomTab);
#endif//REMOVE_TAG_FEATURE
	PositionSnapNearestXCheckbox();

	m_editPos	= GetItem(IDC_EDIT_X);
	Text		= STR_DLG_NAME;

	initButtons();	
	
#ifdef REMOVE_TAG_FEATURE
	AllowResizing(true);
#else
	AllowResizing(IsBottomPaneShown());
#endif
	
	if ( !StartVerticalCursor() )
	{
		SendMessage(WM_CLOSE);
		return TRUE;
	}

	UpdateDialogData();
	
	return TRUE;
}

BOOL GraphVerticalCursorDlg::StartVerticalCursor()
{
	return THE_VCURSOR_MANAGER.StartVerticalCursor(this);
}

BOOL GraphVerticalCursorDlg::OnReady()
{	
#ifndef REMOVE_TAG_FEATURE
	UpdateDlgSize();
#endif
	SetInitReady();
	
	return TRUE;
}

int GraphVerticalCursorDlg::GetMinTopPaneHeight()
{
	Button btnCheckX;
	RECT rCheckX;
	GetControlClientRect(IDC_CHECK_USE_X, rCheckX, &btnCheckX);
	int nHeight = RECT_HEIGHT(rCheckX);
	if(nHeight < 5)
		nHeight = 10;
	return nHeight*2 + 3 * GetControlGap();
}

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

	pSz->top = -1;
	pSz->left = -1;

#ifndef REMOVE_TAG_FEATURE
	pSz->width = GetTotalWidth(TRUE) * 1.5;
	pSz->height = GetTotalHeight(TRUE) * 2;
	
	if(0 == HasPreviousSize(STR_DLG_NAME))
	{
		SetBottomPaneHeight(150);
	}
#else
	pSz->width = GetTotalWidth(TRUE) * 1.5;
	pSz->height = GetTotalHeight(TRUE) * 4;
#endif
	
	return TRUE;
}

BOOL GraphVerticalCursorDlg::OnDlgResize(int nType, int cx, int cy)
{
	if(!IsInitReady())
		return FALSE;

 	MoveControlsHelper	_temp(this);

#ifdef REMOVE_TAG_FEATURE
	Control cc;
	RECT rr;
	GetControlClientRect(IDC_BOTTOM_INFO_TAB, rr, &cc);
	rr.bottom = cy;
	rr.right = cx;
	MoveControl(cc, rr);
		
#else//REMOVE_TAG_FEATURE
	vector<uint> vnBtnIDs = {
		IDC_CHECK_USE_X,
		0
	};
	
	MultiPaneDlg::OnDlgResize(vnBtnIDs, cx, cy, false);
	
	const int nControlGap		= GetControlGap();
	Button btnCheckX;
	RECT rCheckX;
	GetControlClientRect(IDC_CHECK_USE_X, rCheckX, &btnCheckX);
	vector<uint> vnOtherCtrlIDs = {IDC_STATIC_TIPS_X, IDC_EDIT_X, IDC_CHECK_USE_X, 0};
	ArrangeControlsLeftRight(vnOtherCtrlIDs, nControlGap, rCheckX.top, nControlGap);
#endif//REMOVE_TAG_FEATURE
	
	Control ctrlTab;
	RECT rTab;
	GetControlClientRect(IDC_BOTTOM_INFO_TAB, rTab, &ctrlTab);
	m_BottomTab.AdjustRect(FALSE, &rTab);
	MoveControl(GetItem(IDC_TAG_INFO_LIST_BOX), rTab);
	MoveControl(GetItem(IDC_LABEL_INFO_LIST_BOX), rTab);
	
	return TRUE;
}

BOOL GraphVerticalCursorDlg::OnDestroy()
{
	///------ Folger 01/22/09 ORIGIN_CRASH_WHEN_EXIT_IF_GRAPH_PAGE_HAS_VERTICAL_CURSOR_IS_NOT_ACTIVE
	THE_VCURSOR_MANAGER.ResetParentWnd();
	///------ End ORIGIN_CRASH_WHEN_EXIT_IF_GRAPH_PAGE_HAS_VERTICAL_CURSOR_IS_NOT_ACTIVE

#ifdef REMOVE_TAG_FEATURE
	ResizeDialog::OnDestroy();
#else
	MultiPaneDlg::OnDestroy();
#endif

	if (s_pVerticalCursorDlg)
	{
		delete this;
		s_pVerticalCursorDlg = NULL;
	}
	
	return TRUE;
}

BOOL GraphVerticalCursorDlg::OnHelp(int &nHelpID, int nIdCtrlFocus)
{
	return TRUE;
}

BOOL GraphVerticalCursorDlg::OnClose()
{
	BOOL bRemoveOK = THE_VCURSOR_MANAGER.RemoveVerticalCursor();
	Visible = !bRemoveOK;
#ifdef _DEBUG
	if (s_bDestroyDlgOnClose)
	{
		s_bDestroyDlgOnClose = FALSE;
		return TRUE;
	}
#endif // _DEBUG
	return FALSE;	// return FALSE to prevent calling OnDestroy() since we just simply want this dialog to be hidden
}

BOOL GraphVerticalCursorDlg::OnActivePageChange()
{
	BOOL bIsPageHasVerticalCursor = THE_VCURSOR_MANAGER.HasCursorHolderForPage();
	Visible = bIsPageHasVerticalCursor;
	if ( bIsPageHasVerticalCursor && StartVerticalCursor() )
	{
		UpdateDialogData();
	}
	return TRUE;
}
///Jasmine 02/08/10 ENABLE_ACTIVATE_BTN_BY_CHECK_REPORT_SHEET
BOOL GraphVerticalCursorDlg::OnOriginModify(OriginObject obj, int nKind)
{
	Edit editWks = GetDlgItem(IDC_EDIT_RESULT_SHEET);
	if(editWks)
	{
		Worksheet wks(editWks.Text);
		enableActivateBtn( wks.IsValid() );
	}
	return TRUE;
}
//End ENABLE_ACTIVATE_BTN_BY_CHECK_REPORT_SHEET
BOOL GraphVerticalCursorDlg::OnOK()
{
	return FALSE;	// return FALSE to prevent dialog from closing since 'return' wanted to be received by the X edit control.
}

//virtual
int GraphVerticalCursorDlg::GetTotalWidth(bool bGetMin/* = false*/)
{
	static int s_nWidth = -1;
	if (-1 == s_nWidth)
	{
		// Make the dialog to show at least the grouped buttons all the time.
		const int nTitleWidth = getTitleWidth();

		int nFrameHorizSpace;
		getDlgFrameSpace(&nFrameHorizSpace);

		s_nWidth = max(nTitleWidth, m_nGroupedBtnTotalWidth) + GetControlGap()*2 + nFrameHorizSpace;
	}

	return s_nWidth;
}

//virtual
int GraphVerticalCursorDlg::GetTotalHeight( bool bGetMin /*= false*/ )
{
	if(bGetMin)
	{
		int nHeight = GetMinTopPaneHeight();
#ifndef REMOVE_TAG_FEATURE
		if(IsBottomPaneShown())
			nHeight += GetMinBottomPaneHeight();
#endif
		return nHeight;
	}
#ifdef REMOVE_TAG_FEATURE
 	return	ResizeDialog::GetTotalHeight(bGetMin);
#else
	return MultiPaneDlg::GetTotalHeight(bGetMin);
#endif
}

BOOL GraphVerticalCursorDlg::OnTabChange( Control ctrl )
{
	const int nCurSelTab = m_BottomTab.GetCurSel();
	const bool bShowTagInfo = (TAG_INFO_TAB == nCurSelTab);

	m_TagInfoTable.SetVisible(bShowTagInfo);
	m_CursorDataInfoTable.SetVisible(!bShowTagInfo);

	return TRUE;
}

BOOL GraphVerticalCursorDlg::OnKey( Control ctrl, UINT msg, UINT wParam, UINT lParam )
{
	if( msg == WM_KEYDOWN )
	{
		switch(wParam)
		{
		case VK_F2:
			return TRUE;
		case VK_DELETE:
			//m_builtInGridCtrl.OnDelete(ctrl);
			break;
		default:
			return FALSE;
		}
		return TRUE;
	}
	return FALSE;
}

BOOL GraphVerticalCursorDlg::OnCursorDeleted( uint wParam, uint lParam )
{
	// wParam == uPageUID, lParam == not used
	///------ Folger 01/27/10 VERTICAL_CURSOR_DIALOG_STILL_SHOW_AFTER_CURSOR_LINE_DELETED
	//if ( !shouldUpdateDialogDataForPage(wParam) )
		//return FALSE;
	///------ eND VERTICAL_CURSOR_DIALOG_STILL_SHOW_AFTER_CURSOR_LINE_DELETED
	Visible = THE_VCURSOR_MANAGER.HasCursorHolderForPage();
	
	///------ Folger 01/27/10 VERTICAL_CURSOR_DIALOG_STILL_SHOW_AFTER_CURSOR_LINE_DELETED
	//return TRUE;
	return shouldUpdateDialogDataForPage(wParam);
	///------ End VERTICAL_CURSOR_DIALOG_STILL_SHOW_AFTER_CURSOR_LINE_DELETED
}

BOOL GraphVerticalCursorDlg::OnUpdateCursorPosition(uint wParam, uint lParam)
{
	// wParam == uPageUID, lParam == A flag that indicating whether the cursor is moving or moved
	if ( !shouldUpdateDialogDataForPage(wParam) )
		return FALSE;
	const bool bIsMoving = CURSOR_MOVING == lParam;
	updateCursorPos( bIsMoving );
	return TRUE;
}
#ifndef REMOVE_LABEL_FEATURE
BOOL GraphVerticalCursorDlg::OnUpdateTextLabelsShowState( uint wParam, uint lParam )
{
	// wParam == uPageUID, lParam == not used
	if ( !shouldUpdateDialogDataForPage(wParam) )
		return FALSE;
	updateShowHideLabelsBtnState();
	return TRUE;
}
#endif//REMOVE_LABEL_FEATURE
BOOL GraphVerticalCursorDlg::OnTagAdded( uint wParam, uint lParam )
{
	// wParam == uPageUID, lParam == Newly added tag's index
	if ( !shouldUpdateDialogDataForPage(wParam) )
		return FALSE;
	if (THE_VCURSOR_MANAGER.GetNumTags() == 1)
		updateTagRelatedBtnState(TRUE);
	return TRUE;
}

BOOL GraphVerticalCursorDlg::OnTagDeleted( uint wParam, uint lParam )
{
	// wParam == uPageUID, lParam == Deleted tag's UID
	if ( !shouldUpdateDialogDataForPage(wParam) )
		return FALSE;
	if (THE_VCURSOR_MANAGER.GetNumTags() <= 0)
		updateTagRelatedBtnState(FALSE);
	return TRUE;
}

BOOL GraphVerticalCursorDlg::OnUpdateTagSelectState( uint wParam, uint lParam )
{
	// wParam == uPageUID, lParam == The index of TagUnit within the array of holder
	if ( !shouldUpdateDialogDataForPage(wParam) )
		return FALSE;
	const GraphVerticalCursorHolder* pgvcHolder = THE_VCURSOR_MANAGER.GetCursorHolderPointer(wParam);
	if (pgvcHolder)
	{
		GetItem(IDC_BTN_REMOVE_SELECTED_TAGS_GROUPS).Enable = pgvcHolder->m_nSelectedTagsCount > 0;

		const VTagUnit& vTagUnit = pgvcHolder->m_arrTagUnits.GetAt(lParam);
		if (vTagUnit.m_bIsSelected)
		{
			addTagInfoToTable(vTagUnit);
		}
		else
		{
			//removeTagInfoFromTable( vTagUnit.m_vTag.GetUID() );
			removeTagInfoFromTable( vTagUnit );
		}
	}
	return TRUE;
}

BOOL GraphVerticalCursorDlg::OnUpdateCursorIntersectPointBegin( uint wParam, uint lParam )
{
	// wParam == uPageUID, lParam == Not used
	if ( !shouldUpdateDialogDataForPage(wParam) )
		return FALSE;
	
	m_CursorDataInfoTable.ClearAll();
	return TRUE;
}

///Jasmine 01/20/10 SHOW_XVALUE_WITH_FORMAT
static string _ftoa(const XInfo& xinfo, double dd, int nSigificantDigits)
{
	string strOut = _convert_double_to_date_time_str(xinfo, dd);
	if( strOut.IsEmpty() )
		strOut = ftoa_sd(dd, nSigificantDigits);
	return strOut;
}

static double _atof(const XInfo& xinfo, LPCSTR lpcsz)
{
	double ddOut =_convert_date_time_str_to_double(xinfo, lpcsz);
	if( is_missing_value(ddOut) )
		ddOut = atof(lpcsz);
	return ddOut;
}
///End SHOW_XVALUE_WITH_FORMAT

///------ Folger 01/22/10 CURSOR_X_COORDINATE_LOSE_PRECISION_IN_INFO_TABLE
BOOL	GraphVerticalCursorDlg::OnQueryPositionChangeByEditing(DWORD wParam, DWORD lParam)
{
	double*		pr = (double*)wParam;
	if ( !m_bPositionChangeByEditing )
		return FALSE;
	
	if ( pr )
		*pr = atof(m_editPos.Text);
	return TRUE;
}
///------ End CURSOR_X_COORDINATE_LOSE_PRECISION_IN_INFO_TABLE

///Jasmine 01/15/10 REORDER_CURSOR_VALUE_BY_LAYER_POS
BOOL GraphVerticalCursorDlg::OnAfterMoveCursor( uint wParam, uint lParam )
{
	if ( !shouldUpdateDialogDataForPage(wParam) )
		return FALSE;
	
	int		nSize = THE_VCURSOR_MANAGER.GetPointsCount();
	if(nSize <= 0)
		return FALSE;
	
	vector<uint> vnIndeces;	
	THE_VCURSOR_MANAGER.GetCursorDisplayOrder(vnIndeces, wParam);
	
	///------ Folger 01/28/10 SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
	VManagerSetting		managerSetting;
	THE_VCURSOR_MANAGER.GetSetting(managerSetting);
	///------ End SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
	
	const int nSigificantDigits = THE_VCURSOR_MANAGER.GetLabelsSignificantDigits();
	
	for(int ii = 0; ii < nSize; ii++)
	{
		VIntersectPoint* pti = THE_VCURSOR_MANAGER.GetPoint( vnIndeces[ii] );
		if ( NULL == pti )
		{
			ASSERT(FALSE);
			return FALSE;
		}
		
		vector<string> vsRowVals(TEXTLABELINFOGRIDCOLTYPE_TOTAL);
		for(int jj = 0; jj < TEXTLABELINFOGRIDCOLTYPE_TOTAL; jj++)
		{
			switch( m_CursorDataInfoTable.GetColType(jj) )
			{
			case TEXTLABELINFOGRIDCOLTYPE_INDEX:
				vsRowVals[jj] = ftoa(pti->index);
				break;
			case TEXTLABELINFOGRIDCOLTYPE_X_SCALE:
				vsRowVals[jj] = _ftoa(pti->xinfo, pti->fpPoint.x, nSigificantDigits);///Jasmine 01/20/10 SHOW_XVALUE_WITH_FORMAT
				break;
			case TEXTLABELINFOGRIDCOLTYPE_Y_SCALE:
				vsRowVals[jj] = ftoa_sd(pti->fpPoint.y, nSigificantDigits);
				break;
			///Jasmine 01/20/10 SHOW_NEAREST_POINT
			case TEXTLABELINFOGRIDCOLTYPE_NEAREST_X:
				vsRowVals[jj] = _ftoa(pti->xinfo, pti->fpNearPoint.x, nSigificantDigits);///Jasmine 01/20/10 SHOW_XVALUE_WITH_FORMAT
				break;
			case TEXTLABELINFOGRIDCOLTYPE_NEAREST_Y:
				vsRowVals[jj] = ftoa_sd(pti->fpNearPoint.y, nSigificantDigits);
				break;
			///End SHOW_NEAREST_POINT
			case TEXTLABELINFOGRIDCOLTYPE_ID:				///Jasmine 01/15/10 UPDATE_LIST_WITH_SORT_ORDER
				///------ Folger 01/28/10 SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
				//int id = 10 * pti->layer + pti->plot;
				int		id = pti->plotuid;
				///------ End SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
				vsRowVals[jj] = (string)id;
				break;
			///Jasmine 01/18/10 SHOW_MORE_THAN_ONE_PLOT_INFO_AT_A_TIME
			case TEXTLABELINFOGRIDCOLTYPE_BOOKNAME:
				vsRowVals[jj] = pti->plotinfo.book;
				break;
			case TEXTLABELINFOGRIDCOLTYPE_SHEETNAME:
				vsRowVals[jj] = pti->plotinfo.sheet;
				break;
			case TEXTLABELINFOGRIDCOLTYPE_SHORTNAME:
				vsRowVals[jj] = pti->plotinfo.colname;
				break;
			case TEXTLABELINFOGRIDCOLTYPE_LONGNAME:
				vsRowVals[jj] = pti->plotinfo.collongname;
				break;
			///End SHOW_MORE_THAN_ONE_PLOT_INFO_AT_A_TIME
			///------ Folger 01/28/10 SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
			case TEXTLABELINFOGRIDCOLTYPE_SNAPTO:
				{
					DataPlot		dp;
					dp = (DataPlot)Project.GetObject(pti->plotuid);
					if ( dp )
					{
						string		strDescription;
						_get_plot_legend_and_description(dp, NULL, &strDescription);
						vsRowVals[jj] = strDescription.Compare(managerSetting.m_strSnappedPlot) == 0 ? "1" : "0";
					}
				}
				break;
			///------ End SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
			}
		}
		m_CursorDataInfoTable.SetCells(vsRowVals, m_CursorDataInfoTable.GetRows()-1, false);
	}
	
	m_CursorDataInfoTable.ResizeCols();
	return TRUE;
}
///End REORDER_CURSOR_VALUE_BY_LAYER_POS
BOOL GraphVerticalCursorDlg::OnMoveLineTo( Control ctrl )
{	
	///------ Folger 01/15/10 X_VALUE_IN_EDITBOX_SHOULD_NOT_CHANGE_AFTER_ENTER_A_NEW_VALUE
	m_bPositionChangeByEditing = TRUE;
	///------ End X_VALUE_IN_EDITBOX_SHOULD_NOT_CHANGE_AFTER_ENTER_A_NEW_VALUE
	///Jasmine 01/20/10 SHOW_XVALUE_WITH_FORMAT
	VIntersectPoint* pti = THE_VCURSOR_MANAGER.GetPoint( 0 );
	double dd;
	if(pti)
		dd = _atof(pti->xinfo, m_editPos.Text);
	else
		dd = atof(m_editPos.Text);
	
	///Jasmine 01/28/10 RESTRICT_X_EDIT_TEXT
	if( THE_VCURSOR_MANAGER.IsOutOfView(dd) )
	{
		MessageBox(GetSafeHwnd(), _L("Input X value is out of range."), ERROR_TITLE);
		m_bPositionChangeByEditing = FALSE;
		updateCursorPos(false);
		return FALSE;
	}
	///End RESTRICT_X_EDIT_TEXT
	
	return THE_VCURSOR_MANAGER.SetLinePosition(dd);
	///End SHOW_XVALUE_WITH_FORMAT
}

BOOL GraphVerticalCursorDlg::OnShowLabels(Control ctrl)
{
	Button btn(ctrl);
	if(!btn)
		return FALSE;
	return THE_VCURSOR_MANAGER.ShowTextLabels(btn.Check);
}

BOOL GraphVerticalCursorDlg::OnAddTags(Control ctrl)
{
	return THE_VCURSOR_MANAGER.AddTags();
}
 
BOOL GraphVerticalCursorDlg::OnRemoveSelectedTagsGroups( Control ctrl )
{
	return THE_VCURSOR_MANAGER.RemoveSelectedTagsGroups();
}

BOOL GraphVerticalCursorDlg::OnClearAllTags(Control ctrl)
{
	return THE_VCURSOR_MANAGER.ClearAllTags();
}

BOOL GraphVerticalCursorDlg::OnSelectNextTagsGroup( Control ctrl )
{
	return THE_VCURSOR_MANAGER.SelectTagsGroup(TRUE);
}

BOOL GraphVerticalCursorDlg::OnSelectPreviousTagsGroup( Control ctrl )
{
	return THE_VCURSOR_MANAGER.SelectTagsGroup(FALSE);
}

BOOL GraphVerticalCursorDlg::OnIncreaseFontSize(Control ctrl)
{
	const  bool bIncrease = true;
	return THE_VCURSOR_MANAGER.UpdateLabelsFontSize(bIncrease);
}

BOOL GraphVerticalCursorDlg::OnDecreaseFontSize(Control ctrl)
{
	const  bool bIncrease = false;
	return THE_VCURSOR_MANAGER.UpdateLabelsFontSize(bIncrease);
}

static int _config_tool_getnbox_event(TreeNode& trGetN, int nRow, int nEvent, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& getNContainer, string& strAux, string& strErrMsg)
{
	if (GETNE_ON_INIT == nEvent)
	{
		//dwEnables &= ~GETNGEVT_APPLY_ENABLE;
	}
	else if ( GETNE_ON_VALUE_CHANGE == nEvent )
	{
		if ( trGetN.Dump.WksName.strVal.IsEmpty() )
		{
			dwEnables &= ~GETNGEVT_OK_ENABLE;
			strErrMsg = IDS_INVALID_DUMP_WKS_NAME;
			return 0;
		}
		if ( LTT_CUSTOM == trGetN.Label.TextType.nVal && trGetN.Label.CustomText.strVal.IsEmpty() )
		{
			dwEnables &= ~GETNGEVT_OK_ENABLE;
			strErrMsg = IDS_INVALID_CUSTOM_LABEL_TEXT;
			return 0;
		}
		dwEnables |= GETNGEVT_APPLY_ENABLE;
	}
	else if( GETNE_ON_APPLY == nEvent )
	{
		GraphVerticalCursorDlg* pDlg = NULL;
		TreeNode trDlgPtr = trGetN.GetNode(STR_NODE_TAG_NAME_DIALOG);
		if (!trDlgPtr)
			return 0;
		DWORD dwDlgPtr = (DWORD)trDlgPtr.nVal;
		pDlg = (GraphVerticalCursorDlg*)dwDlgPtr;
		if (pDlg)
		{
			BOOL bApplyOK = pDlg->ApplyToolSettings(trGetN);
			dwEnables &= ~GETNGEVT_APPLY_ENABLE;
		}
	}
	return 0;
}

BOOL GraphVerticalCursorDlg::OnConfigureOutput(Control ctrl)
{
	VManagerSetting managerSetting;
	if( THE_VCURSOR_MANAGER.GetSetting(managerSetting) )
	{
		Tree trSettingGUI;
		if ( constructSettingGUITree(trSettingGUI, managerSetting) )
		{
			TreeNode tnConfig = trSettingGUI.ConfigGUI;
			if (!tnConfig)
				return FALSE;
			int nRet = GetNBox(tnConfig, _config_tool_getnbox_event, _L("Preferences"), NULL, GetSafeHwnd(), true);
			if (nRet)
			{
				BOOL bRet = ApplyToolSettings(tnConfig);
				return bRet;
			}
		}
	}
	return TRUE;
}
///Jasmine MOVE_OUT_RESULT_SHEET_EDITBOX
BOOL GraphVerticalCursorDlg::OnKeyEditWks(Control ctrl, UINT msg, UINT wParam, UINT lParam)
{
	if( msg != WM_KEYDOWN )
		return FALSE;
	
	switch(wParam)
	{
	case VK_RETURN:
		break;
	default:
		return FALSE;
	}
	
	return TRUE;
}
BOOL GraphVerticalCursorDlg::OnUpdateEditWks(Control ctrl)
{
	Edit editWks = GetDlgItem(IDC_EDIT_RESULT_SHEET);
	if(!editWks)
		return FALSE;
	
	VManagerSetting		managerSetting;
	THE_VCURSOR_MANAGER.GetSetting(managerSetting);
	if(editWks.Text.Compare(managerSetting.m_strDumpWksName) != 0)
	{
		managerSetting.m_strDumpWksName = editWks.Text;
		THE_VCURSOR_MANAGER.SetSetting(managerSetting);
	}		
	///Jasmine 02/08/10 ENABLE_ACTIVATE_BTN_BY_CHECK_REPORT_SHEET
	Worksheet wks(editWks.Text);
	enableActivateBtn( wks.IsValid() );
	///End ENABLE_ACTIVATE_BTN_BY_CHECK_REPORT_SHEET
	return TRUE;
}
///End MOVE_OUT_RESULT_SHEET_EDITBOX
BOOL GraphVerticalCursorDlg::OnDumpData(Control ctrl)
{
	bool bRet;
	if ( m_BottomTab.GetCurSel() == TAG_INFO_TAB )
		bRet = THE_VCURSOR_MANAGER.DumpTagValues();//DumpData();
	else
		bRet = THE_VCURSOR_MANAGER.DumpCursorValues();
	
	if(bRet)
		enableActivateBtn(true);		///Jasmine 01/22/10 BTN_TO_ACTIVATE_OUTPUT_WKS
	
	return bRet;
}
///Jasmine 01/22/10 BTN_TO_ACTIVATE_OUTPUT_WKS	
BOOL GraphVerticalCursorDlg::OnActivateOutputWks(Control ctrl)
{
	return THE_VCURSOR_MANAGER.ActivateOutputWks();
}
void GraphVerticalCursorDlg::enableActivateBtn(bool bEnable)
{
	Control ctrl = GetDlgItem(IDC_BTN_ACTIVATE_WKS);
	if(ctrl)
		ctrl.Enable = bEnable;
}
///End 01/22/10 BTN_TO_ACTIVATE_OUTPUT_WKS	
///Jasmine 02/08/10 REMEMBER_SNAP_OPTION
void GraphVerticalCursorDlg::updateSnapCheckBoxes(const VManagerSetting& managerSetting)
{
	Button chkSnapNearestX = GetDlgItem(IDC_SNAP_NEAREST_X);
	if(chkSnapNearestX)
		chkSnapNearestX.Check = managerSetting.m_bSnapToNearestX;
	
	//if snap to checkbox column shows, here should also update it
}
///End REMEMBER_SNAP_OPTION
#ifndef REMOVE_TAG_FEATURE
BOOL GraphVerticalCursorDlg::OnShowBottomPane(Control cntrl)
{
	MultiPaneDlg::OnShowBottomPane(cntrl);
	AllowResizing(IsBottomPaneShown());
	OnDlgResize(0, GetDlgExtent(false), GetDlgExtent(true));
	return TRUE;
}
#endif//REMOVE_TAG_FEATURE
BOOL GraphVerticalCursorDlg::OnBeforeMouseDownInfoList( Control cntrl, short nButton, short nShift, float X, float Y, BOOL* pCancel )
{
	if(MK_RBUTTON == nButton)
	{
#ifndef REMOVE_TAG_FEATURE
		if ( m_BottomTab.GetCurSel() == TAG_INFO_TAB )
			m_TagInfoTable.OnBeforeMouseDown(nButton, nShift, X, Y, pCancel);
		else
#endif//REMOVE_TAG_FEATURE
		{
			m_CursorDataInfoTable.OnBeforeMouseDown(nButton, nShift, X, Y, pCancel);
			checkUpdateShowCursorInfos();		///Jasminie 01/29/10 CONFIGURE_SHOW_HIDE_SETTING_BY_MENU
		}
		return TRUE;
	}
	if(pCancel)
		*pCancel = FALSE;
	return FALSE;
}

void GraphVerticalCursorDlg::OnBeforeEditInfoList( Control flxControl, long nRow, long nCol, BOOL* pCancel )
{
	///------ Folger 01/28/10 SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
	if ( TEXTLABELINFOGRIDCOLTYPE_SNAPTO == m_CursorDataInfoTable.GetColType(nCol) )
	{
		if (pCancel)
		{
			Button	btn = GetItem(IDC_SNAP_NEAREST_X);
			*pCancel = btn.Check;
		}
		return;
	}
	///------ End SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG

	if (pCancel)
		*pCancel = TRUE;
}

///------ Folger 01/28/10 SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
void GraphVerticalCursorDlg::OnAfterEditInfoList(Control flxControl, int nRow, int nCol)
{
	int		nColType = m_CursorDataInfoTable.GetColType(nCol);
	if ( TEXTLABELINFOGRIDCOLTYPE_SNAPTO == nColType )
	{		
		string	str = m_CursorDataInfoTable.GetCell(nRow, nColType);

		vector<string>		vs(m_CursorDataInfoTable.GetNumRows());
		m_CursorDataInfoTable.SetCells(vs, nColType);
		m_CursorDataInfoTable.SetCell(nRow, nColType, str);

		VManagerSetting		managerSetting;
		THE_VCURSOR_MANAGER.GetSetting(managerSetting);
				
		if ( atoi(str) )
		{
			DataPlot		dp;
			dp = (DataPlot)Project.GetObject(atoi(m_CursorDataInfoTable.GetCell(nRow, m_CursorDataInfoTable.GetColType(TEXTLABELINFOGRIDCOLTYPE_ID))));
			if ( dp )
			{
				_get_plot_legend_and_description(dp, NULL, &managerSetting.m_strSnappedPlot);
			}
		}
		else
		{
			managerSetting.m_strSnappedPlot.Empty();
		}

		THE_VCURSOR_MANAGER.SetSetting(managerSetting);
		return;
	}

	ASSERT(FALSE);
}

BOOL GraphVerticalCursorDlg::OnCheckUseNearestX(Control cntrl)
{
	VManagerSetting		managerSetting;
	THE_VCURSOR_MANAGER.GetSetting(managerSetting);
	Button				btn = cntrl;
	managerSetting.m_bSnapToNearestX = btn.Check;
	//---Jasmine 02/08/10 when uncheck, turn off snap
	if(!managerSetting.m_bSnapToNearestX)
		managerSetting.m_strSnappedPlot = "";
	//---
	THE_VCURSOR_MANAGER.SetSetting(managerSetting);	

	return TRUE;
}
///------ End SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG

///Jasmine 12/08/09 QA81-8980 MORE_CONFIGURATION_FOR_INFO_TABLE
void GraphVerticalCursorDlg::OnAfterMoveColumns(Control ctrl, long lCol, long *pnPosition)
{
	m_CursorDataInfoTable.OnAfterMoveColumns(lCol, pnPosition);	
}
///End MORE_CONFIGURATION_FOR_INFO_TABLE
///Jasmine 01/15/10 UPDATE_LIST_WITH_SORT_ORDER 
void GraphVerticalCursorDlg::OnAfterSort(Control ctrl, long lCol, int* pnOrder)
{
	updatePointsIDs(0);
}
///End UPDATE_LIST_WITH_SORT_ORDER
void GraphVerticalCursorDlg::AllowResizing( BOOL bResizing /*= TRUE*/ )
{
	int nStyleCurrent = GetWindowLong(Window::GetSafeHwnd(), GWL_STYLE);
	if(bResizing)
	{
		nStyleCurrent |= WS_THICKFRAME;
	}
	else
	{
		nStyleCurrent &= (~WS_THICKFRAME);
	}
	SetWindowLong(Window::GetSafeHwnd(), GWL_STYLE, nStyleCurrent);
	UpdateWindow(TRUE);
}
	
/*----------------------------------------------------------------------------*/
/* Protected functions(interfaces) of GraphVerticalCursorDlg
/*----------------------------------------------------------------------------*/
void GraphVerticalCursorDlg::initButtons()
{
	vector<int> 	vnBtnIDs = {
		 IDC_CHECK_USE_X
		 
#ifndef REMOVE_TAG_FEATURE
		,IDC_BTN_ADD_TAG
		,IDC_BTN_REMOVE_SELECTED_TAGS_GROUPS
		,IDC_BTN_CLEAR_ALL_TAGS
		,IDC_BTN_NEXT_TAG
		,IDC_BTN_PREVIOUS_TAG
#endif//REMOVE_TAG_FEATURE

#ifndef REMOVE_LABEL_FEATURE
		,IDC_BTN_INCREASE_FONT
		,IDC_BTN_DECREASE_FONT
#endif//REMOVE_LABEL_FEATURE

		,IDC_BTN_CONFIG_OUTPUT
		,IDC_BTN_DUMP_TAG_INTO_WKS
		,IDC_BTN_ACTIVATE_WKS		///Jasmine 01/22/10 BTN_TO_ACTIVATE_OUTPUT_WKS
	};
	
	vector<int> 	vnBitmaps = {
		 IDB_APPLY_BTN
		 
#ifndef REMOVE_TAG_FEATURE
		,IDB_TOGGLE_TAG
		,IDB_REMOVE_SELECTED_TAGS_GROUPS
		,IDB_REMOVE_ALL_TAGS
		,IDB_NEXT_TAG
		,IDB_PREVIOUS_TAG
#endif//REMOVE_TAG_FEATURE

#ifndef REMOVE_LABEL_FEATURE
		,IDB_INCREASE_FONT
		,IDB_DECREASE_FONT
#endif//REMOVE_LABEL_FEATURE

		,IDB_PF_ADV
		,IDB_DUMP_DATA_INTO_WKS
		,IDB_ACTIVATE_WKS			///Jasmine 01/22/10 BTN_TO_ACTIVATE_OUTPUT_WKS
	};
	
	vector<string> 	vsBtnTips;
	vsBtnTips.SetSize( vnBtnIDs.GetSize() );
	int nn = 0;
	vsBtnTips[nn++] = _L("Move Cursor to X");		  
#ifndef REMOVE_TAG_FEATURE
	vsBtnTips[nn++] = _L("Add Tags");
	vsBtnTips[nn++] = _L("Clear Selected Tags Groups");
	vsBtnTips[nn++] = _L("Clear All Tags");
	vsBtnTips[nn++] = _L("Select Next Tags Group");
	vsBtnTips[nn++] = _L("Select Previous Tags Group");
#endif//REMOVE_TAG_FEATURE

#ifndef REMOVE_LABEL_FEATURE
	vsBtnTips[nn++] = _L("Increase Font Size");
	vsBtnTips[nn++] = _L("Decrease Font Size");
#endif//REMOVE_LABEL_FEATURE
	vsBtnTips[nn++] = _L("Preferences");
	vsBtnTips[nn++] = _L("Output Report");
	vsBtnTips[nn++] = _L("Go to Report");

	const int nIDSize = vnBtnIDs.GetSize();
	const int nBtnTipsSize = vsBtnTips.GetSize();
	const int nBitMapSize = vnBitmaps.GetSize();
	ASSERT(nBitMapSize == nIDSize && nBtnTipsSize == nIDSize);
	
	for(int ii = 0; ii < nIDSize; ii++)
	{
		BitmapRadioButton btn = GetItem( vnBtnIDs[ii] );
		vector<string> vsTips(1);
		vsTips[0] = ii < nBtnTipsSize ? vsBtnTips[ii] : "";
		btn.Init(1, ii < nBitMapSize ? vnBitmaps[ii] : 0, 16, vsTips);
	}
#ifndef REMOVE_LABEL_FEATURE
	BitmapRadioButton btnShowHideLabels = GetItem(IDC_BTN_SHOW_LABEL);
	vector<string> vsTips(2);
	vsTips[0] = _L("Show Label");
	vsTips[1] = _L("Hide Label");
	btnShowHideLabels.Init(2, IDB_SHOW_LABEL, 16, vsTips);
	btnShowHideLabels.Check = 1;
#else
	vector<int> 	vnHideLabelBtnIDs = {
		IDC_BTN_SHOW_LABEL
		,IDC_BTN_INCREASE_FONT
		,IDC_BTN_DECREASE_FONT
	}
	for(ii = 0; ii < vnHideLabelBtnIDs.GetSize(); ii++)
	{
		Control btn = GetItem( vnHideLabelBtnIDs[ii] );
		if(btn)
			btn.Visible = false;
	}
#endif//REMOVE_LABEL_FEATURE
	
#ifdef REMOVE_TAG_FEATURE
	vector<int> 	vnHideIDs = {
		IDC_BTN_ADD_TAG
		,IDC_BTN_REMOVE_SELECTED_TAGS_GROUPS
		,IDC_BTN_CLEAR_ALL_TAGS
		,IDC_BTN_NEXT_TAG
		,IDC_BTN_PREVIOUS_TAG
	}
	for(ii = 0; ii < vnHideIDs.GetSize(); ii++)
	{
		Control btn = GetItem( vnHideIDs[ii] );
		if(btn)
			btn.Visible = false;
	}
#endif//REMOVE_TAG_FEATURE
}

/*----------------------------------------------------------------------------*/
/* Public functions(interfaces) of GraphVerticalCursorDlg
/*----------------------------------------------------------------------------*/

BOOL GraphVerticalCursorDlg::Create(HWND hWndParent /*= NULL*/)
{
	InitMsgMap();
	
	DWORD dwDlgOptions = 0;
#ifdef REMOVE_TAG_FEATURE
	BOOL bRet = ResizeDialog::Create(hWndParent, dwDlgOptions);
#else
	BOOL bRet = MultiPaneDlg::Create(hWndParent, dwDlgOptions);
#endif
	Visible = true;
	return bRet;
}

void GraphVerticalCursorDlg::UpdateDialogData()
{
	VManagerSetting managerSetting;
	if( THE_VCURSOR_MANAGER.GetSetting(managerSetting) )
		THE_VCURSOR_MANAGER.SetSetting(managerSetting);
	
	updateCursorPos();
#ifndef REMOVE_LABEL_FEATURE
	updateShowHideLabelsBtnState();
#endif

	updateRemoveSelTagsGrpsBtnState();
	
#ifndef REMOVE_TAG_FEATURE
	BOOL bEnableBtn = THE_VCURSOR_MANAGER.GetNumTags() > 0;
	updateTagRelatedBtnState(bEnableBtn);

	updateTagsInfo();
#endif//REMOVE_TAG_FEATURE
	showCursorInfos(managerSetting.m_cursorshow);	///Jasmine 01/18/10 CONFIGURE_SHOW_HIDE_SETTING
	updateCursorDataInfo();

	//---report controls
	showReportSheetName(managerSetting);	///Jasmine MOVE_OUT_RESULT_SHEET_EDITBOX
	//---
	
	updateSnapCheckBoxes(managerSetting);///Jasmine 02/08/10 REMEMBER_SNAP_OPTION
	
	Visible = TRUE;
}

BOOL GraphVerticalCursorDlg::ApplyToolSettings( const TreeNode& tnSettings )
{
	VManagerSetting managerSetting;
	///Kyle 01/26/2010 SNAP_CURSOR_TO_DATA_PLOT
	//managerSetting.m_bSnapLineToData 		= tnSettings.Misc.SnapLine.nVal;
	TreeNode trSnapLine = tnSettings.Misc.SnapLine;
	string strSnappedPlot;
	if( trSnapLine.nVal )
	{
		int nIndex = trSnapLine.nVal;
		string strPlots;
		trSnapLine.GetAttribute(PlotListAttr(), strPlots);

		vector<string> vsPlots;
		strPlots.GetTokens(vsPlots, '|');
		if(nIndex > 0 && nIndex < vsPlots.GetSize() )
			strSnappedPlot = vsPlots[nIndex];
	}
	managerSetting.m_strSnappedPlot 		= strSnappedPlot;
	///End SNAP_CURSOR_TO_DATA_PLOT
	managerSetting.m_strDumpWksName 		= tnSettings.Dump.WksName.strVal;
	managerSetting.m_labelSetting.nSignificantDigits = 	tnSettings.Label.SD.nVal;
	managerSetting.m_labelSetting.nTextType = tnSettings.Label.TextType.nVal;
	managerSetting.m_labelSetting.strLTCustomTextType = tnSettings.Label.CustomText.strVal;
	///Jasmine 01/18/10 CONFIGURE_SHOW_HIDE_SETTING
	managerSetting.m_cursorshow.BookName 	= tnSettings.CursorShow.BookName.nVal;
	managerSetting.m_cursorshow.SheetName 	= tnSettings.CursorShow.SheetName.nVal;
	managerSetting.m_cursorshow.ShortName 	= tnSettings.CursorShow.ShortName.nVal;
	managerSetting.m_cursorshow.LongName 	= tnSettings.CursorShow.LongName.nVal;
	managerSetting.m_cursorshow.CursorX 	= tnSettings.CursorShow.CursorX.nVal;
	managerSetting.m_cursorshow.CursorY 	= tnSettings.CursorShow.CursorY.nVal;
	///Jasmine 01/20/10 SHOW_NEAREST_POINT 			
	managerSetting.m_cursorshow.CursorNearX = tnSettings.CursorShow.CursorNearX.nVal;
	managerSetting.m_cursorshow.CursorNearY = tnSettings.CursorShow.CursorNearY.nVal;
	///End SHOW_NEAREST_POINT
	managerSetting.m_cursorshow.Index 		= tnSettings.CursorShow.Index.nVal;
	
	showCursorInfos(managerSetting.m_cursorshow);
	///End CONFIGURE_SHOW_HIDE_SETTING

	BOOL bRet = THE_VCURSOR_MANAGER.SetSetting(managerSetting);
	updateCursorPos();
#ifndef REMOVE_TAG_FEATURE
	updateTagsInfo();
#endif//REMOVE_TAG_FEATURE
	updateCursorDataInfo();
	showReportSheetName(managerSetting);///Jasmine MOVE_OUT_RESULT_SHEET_EDITBOX
	
	return bRet;
}

/*----------------------------------------------------------------------------*/
/* Private functions(implementations) of GraphVerticalCursorDlg
/*----------------------------------------------------------------------------*/

int GraphVerticalCursorDlg::getTitleWidth()
{
	///------ Folger 07/06/10 ORG-436 BETTER_USE_OC_DEVICE_CONTEXT
	//DeviceContext dc = GetDC();
	DeviceContext	dc(m_wndDlg);
	///------ End BETTER_USE_OC_DEVICE_CONTEXT
	SIZE sz;
	sz = dc.GetTextExtent(STR_DLG_NAME, strlen(STR_DLG_NAME));
	return sz.cx;
}

void GraphVerticalCursorDlg::getDlgFrameSpace( int* pnFrameHoriz /*= NULL*/, int* pnFrameVert /*= NULL*/ )
{
	RECT rtWindow, rtClient;
	GetWindowRect(&rtWindow);
	GetClientRect(&rtClient);
	if(pnFrameHoriz)
		*pnFrameHoriz = RECT_WIDTH(rtWindow)-RECT_WIDTH(rtClient);
	if(pnFrameVert)
		*pnFrameVert = RECT_HEIGHT(rtWindow)-RECT_HEIGHT(rtClient);
}

static bool _config_chg_text_type_event(TreeNode& trGetN, int nRow, int nCol, TreeNode& trNode, DWORD dwCntrl, int nType, WndContainer& theDlg)
{
	if ( !(dwCntrl & GETNEVENT_ON_INIT) )
	{
		const BOOL bCustomText = trNode.nVal == LTT_CUSTOM;
		trGetN.Label.CustomText.Show = bCustomText;
		trGetN.Label.CustomText.Use = bCustomText;
	}
	return true;
}

///Kyle 01/26/2010 SNAP_CURSOR_TO_DATA_PLOT

static void _get_plot_legend_and_description(const DataPlot& dp, string* pstrLegend, string* pstrDescrip)
{
	ASSERT(dp.IsValid());

	if ( pstrLegend )
	{
		pstrLegend->Empty();
		dp.GetLegend(*pstrLegend);
	}

	if ( pstrDescrip )
	{
		get_dataplot_range_description(*pstrDescrip, dp, VERTICAL_CURSOR_DATAPLOT_GET_DESCRIPTION_STYLE);
	}
}

static int _get_plot_list(string& strCombo, string& strPlots, const GraphPage& gp, const DataPlot& dpSnapped, LPCSTR lpcszCurrent)
{
	vector<string> vsCombo, vsPlots;
	vsCombo.Add(_L("None"));
	vsPlots.Add("");
	///------ Folger 01/27/10 VERTICAL_CURSOR_SNAP_TO_NEAREST_X_DATA
	vsCombo.Add(_L("Nearest X"));
	vsPlots.Add(STR_PLOT_NEAREST_X);
	///------ End VERTICAL_CURSOR_SNAP_TO_NEAREST_X_DATA

	string strLegend, strDescrip;
	if (gp)
	{
		foreach(GraphLayer gl in gp.Layers)
		{
			int nLayIndex = gl.GetIndex() + 1;
			foreach (DataPlot dp in gl.DataPlots)
			{
				_get_plot_legend_and_description(dp, &strLegend, &strDescrip);
				vsPlots.Add(strDescrip);
				if( strLegend.IsEmpty() )
				{
					int nSep;
					if( (nSep = strDescrip.Find(']')) >= 0 )		// remove book name
					{
						strDescrip = strDescrip.Mid(nSep + 1);
						strDescrip.TrimLeft();
			}
					vsCombo.Add(strDescrip);
		}
				else
				{
					vsCombo.Add(strLegend);
	}
			}
		}
	}
	strCombo.SetTokens(vsCombo, '|');
	strPlots.SetTokens(vsPlots, '|');

	int nRet = 0;
	///------ Folger 01/27/10 VERTICAL_CURSOR_SNAP_TO_NEAREST_X_DATA
	if ( lstrcmp(lpcszCurrent, STR_PLOT_NEAREST_X) == 0 )
		nRet = 1;
	else
	///------ End VERTICAL_CURSOR_SNAP_TO_NEAREST_X_DATA
	if( dpSnapped && vsPlots.GetSize() > 1 )
	{
		_get_plot_legend_and_description(dpSnapped, &strLegend, &strDescrip);
		nRet = vsPlots.Find(strDescrip);
		if(nRet < 0)
			nRet = 0;
	}

	return nRet;
}
///End SNAP_CURSOR_TO_DATA_PLOT

BOOL GraphVerticalCursorDlg::constructSettingGUITree( TreeNode& tnSettingGUI, const VManagerSetting& managerSetting )
{	
	tnSettingGUI.Reset();
	TreeNode trGUI = tnSettingGUI.AddNode("ConfigGUI");

	GETN_USE(trGUI)
	GETN_DLG_OPTIONS(DYNALAYOUT_CONTROL_APPLY_UNDO_BTN_STATUS_SEPARATELY)

	GETN_BEGIN_BRANCH( Dump, _L("Output") )	GETN_OPTION_BRANCH(GETNBRANCH_OPEN) 
		GETN_STR( WksName, _L("Worksheet"), managerSetting.m_strDumpWksName)
	GETN_END_BRANCH( Dump )

	GETN_BEGIN_BRANCH( Label, _L("Display") )	GETN_OPTION_BRANCH(GETNBRANCH_OPEN)
		GETN_LIST( SD, _L("Significant Digits"), managerSetting.m_labelSetting.nSignificantDigits, _L("System|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15") )
		GETN_LIST( TextType, _L("Text Type"), managerSetting.m_labelSetting.nTextType, _L("Y|(X,Y)|Custom") )
			GETN_OPTION_EVENT_EX(_config_chg_text_type_event)
		GETN_STR( CustomText, _L("Custom Text"), managerSetting.m_labelSetting.strLTCustomTextType)
		GETN_CURRENT_SUBNODE.Show = managerSetting.m_labelSetting.nTextType == LTT_CUSTOM;
		GETN_CURRENT_SUBNODE.Use = FALSE;
		
	GETN_END_BRANCH( Label )

	///Jasmine 01/18/10 CONFIGURE_SHOW_HIDE_SETTING
	GETN_BEGIN_BRANCH( CursorShow, _L("Show") )	GETN_OPTION_BRANCH(GETNBRANCH_OPEN)
		GETN_CHECK(Index, 		_L("Nearest Index"), 		managerSetting.m_cursorshow.Index)
		GETN_CHECK(CursorX, 	_L("Cursor X"), 	true)//managerSetting.m_cursorshow.CursorX)///Jasmine 01/19/10 VCURSOR_ALWAYS_SHOW_XY_VALUE
			GETN_CURRENT_SUBNODE.Show = false;
		GETN_CHECK(CursorY,		_L("Cursor Y"), 	true)//managerSetting.m_cursorshow.CursorY)
			GETN_CURRENT_SUBNODE.Show = false;
		///Jasmine 01/20/10 SHOW_NEAREST_POINT 		
		GETN_CHECK(CursorNearX, _L("Nearest X"), 	managerSetting.m_cursorshow.CursorNearX)
		GETN_CHECK(CursorNearY, _L("Nearest Y"), 	managerSetting.m_cursorshow.CursorNearY)		
		///End SHOW_NEAREST_POINT
		GETN_CHECK(ShortName, 	LABEL_SHORT_NAME, 	managerSetting.m_cursorshow.ShortName)
		GETN_CHECK(LongName, 	STR_LONG_NAME_LABEL,	managerSetting.m_cursorshow.LongName)
		GETN_CHECK(SheetName,	LABEL_SHEET_NAME, 	managerSetting.m_cursorshow.SheetName)
		GETN_CHECK(BookName, 	LABEL_BOOK_NAME, 	managerSetting.m_cursorshow.BookName)
	GETN_END_BRANCH( CursorShow )
	///End CONFIGURE_SHOW_HIDE_SETTING
	
	GETN_BEGIN_BRANCH( Misc, _L("Misc") )	GETN_OPTION_BRANCH(GETNBRANCH_OPEN)
		///Kyle 01/26/2010 SNAP_CURSOR_TO_DATA_PLOT
		//GETN_CHECK( SnapLine, _L("Snap Cursor to Data"), managerSetting.m_bSnapLineToData)
		GraphPage gp;
		DataPlot dpSnapped;
		string strComboList, strPlots;
		const GraphVerticalCursorHolder* pgvcHolder = THE_VCURSOR_MANAGER.GetCursorHolderPointer();
		if (pgvcHolder)
			gp = pgvcHolder->GetPage();
		THE_VCURSOR_MANAGER.IsLineSnappedToData(&dpSnapped);
		int nIndex = _get_plot_list(strComboList, strPlots, gp, dpSnapped, managerSetting.m_strSnappedPlot);
		GETN_LIST(SnapLine,_L("Snap Cursor to Data"), nIndex, strComboList)			_tmpSubNode.SetAttribute(PlotListAttr(), strPlots);
		///End SNAP_CURSOR_TO_DATA_PLOT
	GETN_END_BRANCH( Misc )

#ifdef REMOVE_LABEL_FEATURE
	trGUI.Label.TextType.Show = false;
#endif
	
	///------ Folger 01/28/10 SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
	trGUI.Misc.Show = 0;
	///------ End SHOW_SNAP_TO_DATAPLOT_ON_MAIN_DIALOG
	
	DWORD dwDlgPtr = (DWORD)this;		
	GraphVerticalCursorDlg* pDialog = (GraphVerticalCursorDlg*)dwDlgPtr;
	TreeNode trDlgPtr = tree_check_get_node(trGUI, STR_NODE_TAG_NAME_DIALOG);
	trDlgPtr.nVal = dwDlgPtr;
	trDlgPtr.Show = FALSE;

	return TRUE;
}
///Jasmine MOVE_OUT_RESULT_SHEET_EDITBOX
void GraphVerticalCursorDlg::showReportSheetName(const VManagerSetting& managerSetting)
{
	Control editWks = GetDlgItem(IDC_EDIT_RESULT_SHEET);
	if(!editWks)
		return;
	
	editWks.Text = managerSetting.m_strDumpWksName;
	///Jasmine 02/08/10 ENABLE_ACTIVATE_BTN_BY_CHECK_REPORT_SHEET
	Worksheet wks(editWks.Text);
	enableActivateBtn( wks.IsValid() );
	///End ENABLE_ACTIVATE_BTN_BY_CHECK_REPORT_SHEET
}
///End MOVE_OUT_RESULT_SHEET_EDITBOX

#define SET_DEFAULT_CONTROL_GAP			3
void GraphVerticalCursorDlg::arrangeControls()
{
	if(!m_wndDlg)
		m_wndDlg = GetWindow();

	// 1. Arrange the toolbar buttons
		vector<uint> vnGroupBtnIDs = {
#ifndef REMOVE_LABEL_FEATURE
			IDC_BTN_SHOW_LABEL,																IDC_GROUP_GAP
#endif//REMOVE_LABEL_FEATURE
#ifndef REMOVE_TAG_FEATURE
		, 	IDC_BTN_ADD_TAG, IDC_BTN_REMOVE_SELECTED_TAGS_GROUPS, IDC_BTN_CLEAR_ALL_TAGS,	IDC_GROUP_GAP
		, 	IDC_BTN_NEXT_TAG, IDC_BTN_PREVIOUS_TAG,											IDC_GROUP_GAP
#endif//REMOVE_TAG_FEATURE
#ifndef REMOVE_LABEL_FEATURE
		,	IDC_BTN_INCREASE_FONT, IDC_BTN_DECREASE_FONT,									IDC_GROUP_GAP
		, 	
#endif//REMOVE_LABEL_FEATURE
			IDC_BTN_CONFIG_OUTPUT,  														IDC_GROUP_GAP 
		,	IDC_STATIC_RESULT_SHEET, IDC_EDIT_RESULT_SHEET, 	///Jasmine MOVE_OUT_RESULT_SHEET_EDITBOX
			IDC_BTN_DUMP_TAG_INTO_WKS, IDC_BTN_ACTIVATE_WKS		///Jasmine 01/22/10 BTN_TO_ACTIVATE_OUTPUT_WKS
		,	0
	};

	SetControlGap(SET_DEFAULT_CONTROL_GAP);
	const int nControlGap		= GetControlGap();

	//ArrangeMainItemAndControls(vnGroupBtnIDs, 0, NULL, false, cx, cy, nControlGap, nGroupBtnGap);
	int nBottom = ArrangeControlsLeftRight(vnGroupBtnIDs, nControlGap, nControlGap, nControlGap);
	
	Button btnFirst;
	RECT rFirstBtn;
	GetControlClientRect(vnGroupBtnIDs[0], rFirstBtn, &btnFirst);
	
	vector<uint>	vnIndices;
	if(vnGroupBtnIDs.Find(vnIndices, 0) > 0)
	{
		int nLast = vnIndices[0] - 1;
		Button btnLast;
		RECT rLastBtn;
		GetControlClientRect(vnGroupBtnIDs[nLast], rLastBtn, &btnLast);
		m_nGroupedBtnTotalWidth = max(m_nGroupedBtnTotalWidth, rLastBtn.right-rFirstBtn.left);
	}

	// 2. Arrange the other controls
	vector<uint> vnOtherCtrlIDs = {IDC_STATIC_TIPS_X, IDC_EDIT_X, IDC_CHECK_USE_X, IDC_BTN_DOWNUP, 0};
	nBottom = ArrangeControlsLeftRight(vnOtherCtrlIDs, nControlGap, nBottom + nControlGap*2, nControlGap);
	
	if(vnOtherCtrlIDs.Find(vnIndices, 0) > 0)
	{
		int nLast = vnIndices[0] - 1;
		Button btnLast;
		RECT rLastBtn;
		GetControlClientRect(vnOtherCtrlIDs[nLast], rLastBtn, &btnLast);
		m_nGroupedBtnTotalWidth = max(m_nGroupedBtnTotalWidth, rLastBtn.right-rFirstBtn.left);
	}
	
	// 3. junk frame
	Control cFrame = GetItem(IDC_FRAME_TOP_PANE);
	MoveControl(cFrame, rFirstBtn);
	cFrame.Visible = false;
	
	// 4. tab
	Control tab;
	RECT rTab;
	GetControlClientRect(IDC_BOTTOM_INFO_TAB, rTab, &tab);
	rTab.top = nBottom + nControlGap;
	rTab.left = nControlGap;
	MoveControl(tab, rTab);
}

void GraphVerticalCursorDlg::PositionSnapNearestXCheckbox()
{
	TabControl tab;
	RECT rTab;
	GetControlClientRect(IDC_BOTTOM_INFO_TAB, rTab, &tab);
	
	///------ Folger 07/06/10 ORG-436 BETTER_USE_OC_DEVICE_CONTEXT
	//DeviceContext dc = tab.GetDC();
	DeviceContext	dc(tab);
	///------ End BETTER_USE_OC_DEVICE_CONTEXT

	vector<int> vnTab = {	LABEL_INFO_TAB
					#ifndef REMOVE_TAG_FEATURE
							,TAG_INFO_TAB
					#endif
						};
						
	int nTabTitleWidth = 0;
	for(int ii = 0; ii < vnTab.GetSize(); ii++)
	{
		string strTitle = tab.GetItemText( vnTab[ii] );
		SIZE sz;
		sz = dc.GetTextExtent(strTitle, strlen(strTitle));
		nTabTitleWidth += sz.cx + GetControlGap()*2;
	}
	
	PositionControl(IDC_SNAP_NEAREST_X, rTab.left+nTabTitleWidth+GetControlGap()*2, rTab.top);
}

int GraphVerticalCursorDlg::GetBottomPaneSubControls(vector<uint>& vnCntrls)
{
	vnCntrls.SetSize(0);
	vnCntrls.Add(IDC_LABEL_INFO_LIST_BOX);
	vnCntrls.Add(IDC_TAG_INFO_LIST_BOX);
	return m_BottomTab.GetCurSel();
}
#ifndef REMOVE_LABEL_FEATURE
void GraphVerticalCursorDlg::updateShowHideLabelsBtnState()
{
	Button btnShowLabel = GetItem(IDC_BTN_SHOW_LABEL);
	btnShowLabel.Check = THE_VCURSOR_MANAGER.IsTextLabelsShown();
}
#endif//REMOVE_LABEL_FEATURE
void GraphVerticalCursorDlg::updateTagRelatedBtnState( BOOL bEnableBtn /*= FALSE*/ )
{
	BitmapRadioButton btnClearTags			= GetDlgItem(IDC_BTN_CLEAR_ALL_TAGS);
	BitmapRadioButton btnNextTag			= GetDlgItem(IDC_BTN_NEXT_TAG);
	BitmapRadioButton btnPreviousTag		= GetDlgItem(IDC_BTN_PREVIOUS_TAG);
	BitmapRadioButton btnDumpData			= GetDlgItem(IDC_BTN_DUMP_TAG_INTO_WKS);

	btnClearTags.Enable		= bEnableBtn;
	btnNextTag.Enable		= bEnableBtn;
	btnPreviousTag.Enable	= bEnableBtn;
	btnDumpData.Enable		= bEnableBtn;
}

void GraphVerticalCursorDlg::updateRemoveSelTagsGrpsBtnState()
{
	BitmapRadioButton btnRemoveSelTagsGrps	= GetDlgItem(IDC_BTN_REMOVE_SELECTED_TAGS_GROUPS);
	btnRemoveSelTagsGrps.Enable = (THE_VCURSOR_MANAGER.GetSelectedTagsCount() > 0);
}

void GraphVerticalCursorDlg::updateCursorPos(bool bIsMoving /*= false*/)
{
	///------ Folger 01/15/10 X_VALUE_IN_EDITBOX_SHOULD_NOT_CHANGE_AFTER_ENTER_A_NEW_VALUE
	if ( m_bPositionChangeByEditing )
	{
		m_bPositionChangeByEditing = FALSE;
		return;
	}
	///------ End X_VALUE_IN_EDITBOX_SHOULD_NOT_CHANGE_AFTER_ENTER_A_NEW_VALUE
	double dPosX;
	if( THE_VCURSOR_MANAGER.GetLinePosition(dPosX, bIsMoving) )
	{
		const int nSigificantDigits = THE_VCURSOR_MANAGER.GetLabelsSignificantDigits();
		///Jasmine 01/20/10 SHOW_XVALUE_WITH_FORMAT
		VIntersectPoint* pti = THE_VCURSOR_MANAGER.GetPoint(0);
		if (pti )
			m_editPos.Text = _ftoa(pti->xinfo, dPosX, nSigificantDigits);
		else
			m_editPos.Text = ftoa_sd(dPosX, nSigificantDigits);
		///End SHOW_XVALUE_WITH_FORMAT
	}
}

void GraphVerticalCursorDlg::updateTagsInfo()
{
	const GraphVerticalCursorHolder* pgvcHolder = THE_VCURSOR_MANAGER.GetCursorHolderPointer();
	if (pgvcHolder)
	{
		m_TagInfoTable.ClearAll();
		const int nTagUnitSize = pgvcHolder->m_arrTagUnits.GetSize();
		const UINT uPageUID = pgvcHolder->m_uPageUID;

		for (int ii = 0; ii < nTagUnitSize; ++ii)
		{
			OnTagAdded(uPageUID, ii);
		}
	}
}

void GraphVerticalCursorDlg::updateCursorDataInfo()
{
	THE_VCURSOR_MANAGER.RetrieveCursorInfo();
}

///Jasmine 01/18/10 CONFIGURE_SHOW_HIDE_SETTING
void GraphVerticalCursorDlg::showCursorInfos(const VCursorShow& cursorshow)
{
	int nColPos;
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_BOOKNAME);
	if(nColPos > -1)
		m_CursorDataInfoTable.HideCol(nColPos, !cursorshow.BookName);
	
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_SHEETNAME);
	if(nColPos > -1)
		m_CursorDataInfoTable.HideCol(nColPos, !cursorshow.SheetName);
	
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_SHORTNAME);
	if(nColPos > -1)
		m_CursorDataInfoTable.HideCol(nColPos, !cursorshow.ShortName);
	
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_LONGNAME);
	if(nColPos > -1)
		m_CursorDataInfoTable.HideCol(nColPos, !cursorshow.LongName);
	
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_X_SCALE);
	if(nColPos > -1)
		m_CursorDataInfoTable.HideCol(nColPos, !cursorshow.CursorX);
	
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_Y_SCALE);
	if(nColPos > -1)
		m_CursorDataInfoTable.HideCol(nColPos, !cursorshow.CursorY);
	
	///Jasmine 01/20/10 SHOW_NEAREST_POINT 		
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_NEAREST_X);
	if(nColPos > -1)
		m_CursorDataInfoTable.HideCol(nColPos, !cursorshow.CursorNearX);
	
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_NEAREST_Y);
	if(nColPos > -1)
		m_CursorDataInfoTable.HideCol(nColPos, !cursorshow.CursorNearY);
	///End SHOW_NEAREST_POINT
	
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_INDEX);
	if(nColPos > -1)
		m_CursorDataInfoTable.HideCol(nColPos, !cursorshow.Index);	
}
///Jasminie 01/29/10 CONFIGURE_SHOW_HIDE_SETTING_BY_MENU
void GraphVerticalCursorDlg::checkUpdateShowCursorInfos()
{	
	VManagerSetting managerSetting;
	if( !THE_VCURSOR_MANAGER.GetSetting(managerSetting) )
		return;
		
	int nColPos;
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_BOOKNAME);	
	managerSetting.m_cursorshow.BookName 	= !m_CursorDataInfoTable.IsColHidden(nColPos);
	
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_SHEETNAME);
	managerSetting.m_cursorshow.SheetName 	= !m_CursorDataInfoTable.IsColHidden(nColPos);
	
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_SHORTNAME);
	managerSetting.m_cursorshow.ShortName 	= !m_CursorDataInfoTable.IsColHidden(nColPos);
	
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_LONGNAME);
	managerSetting.m_cursorshow.LongName 	= !m_CursorDataInfoTable.IsColHidden(nColPos);
	
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_NEAREST_X);
	managerSetting.m_cursorshow.CursorNearX = !m_CursorDataInfoTable.IsColHidden(nColPos);
	
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_NEAREST_Y);
	managerSetting.m_cursorshow.CursorNearY = !m_CursorDataInfoTable.IsColHidden(nColPos);
	
	nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_INDEX);
	managerSetting.m_cursorshow.Index 		= !m_CursorDataInfoTable.IsColHidden(nColPos);
	
	BOOL bRet = THE_VCURSOR_MANAGER.SetSetting(managerSetting);
}
///End CONFIGURE_SHOW_HIDE_SETTING_BY_MENU
///End CONFIGURE_SHOW_HIDE_SETTING

void GraphVerticalCursorDlg::addTagInfoToTable( const VTagUnit& vTagUnit )
{
	const int nSigificantDigits = THE_VCURSOR_MANAGER.GetLabelsSignificantDigits();

	for(int ii = 0; ii < vTagUnit.m_arrTagLabels.GetSize(); ii++)
	{
		VTagLabel& vTagLabel = vTagUnit.m_arrTagLabels.GetAt(ii);
		
		vector<string> vsRowVals;
		vsRowVals.Add( vTagLabel.GetValidObj().GetUID() );

		vsRowVals.Add( ftoa_sd(vTagLabel.GetMarkedPointXScale(), nSigificantDigits) );
		vsRowVals.Add( ftoa_sd(vTagLabel.GetMarkedPointYScale(), nSigificantDigits) );
		vsRowVals.Add( vTagLabel.GetAttachedPlotName() );

		m_TagInfoTable.SetCells(vsRowVals, m_TagInfoTable.GetRows()-1, false);
	}
	m_TagInfoTable.ResizeCols();
}

//void GraphVerticalCursorDlg::removeTagInfoFromTable( const UINT uTagUID )
void GraphVerticalCursorDlg::removeTagInfoFromTable(const VTagUnit& vTagUnit)
{
	for(int ii = 0; ii < vTagUnit.m_arrTagLabels.GetSize(); ii++)
	{
		VTagLabel& vTagLabel = vTagUnit.m_arrTagLabels.GetAt(ii);
		string strTagUID = vTagLabel.GetValidObj().GetUID();
		const int nRow = m_TagInfoTable.FindRow(strTagUID);
		m_TagInfoTable.DeleteRow(nRow);
	}
}

BOOL GraphVerticalCursorDlg::shouldUpdateDialogDataForPage( UINT uPageUID )
{
	const BOOL bShouldUpdate = (!IsInitReady() || Visible) && THE_VCURSOR_MANAGER.IsPageCurrentTarget(uPageUID);
	return bShouldUpdate;
}

///Jasmine 01/15/10 UPDATE_LIST_WITH_SORT_ORDER
BOOL GraphVerticalCursorDlg::updatePointsIDs(UINT uPageUID)
{
	vector<string> vsPointIDs;
	int nColPos = m_CursorDataInfoTable.GetColPos(TEXTLABELINFOGRIDCOLTYPE_ID);
	m_CursorDataInfoTable.GetColValues(nColPos, vsPointIDs, m_CursorDataInfoTable.GetRowOffset() );
	
	const GraphVerticalCursorHolder* pgvcHolder = THE_VCURSOR_MANAGER.GetCursorHolderPointer(uPageUID);
	if(pgvcHolder)
	{
		pgvcHolder->m_vsPointIDs = vsPointIDs;
		return TRUE;
	}
	return FALSE;	
}
///End UPDATE_LIST_WITH_SORT_ORDER
	
/*----------------------------------------------------------------------------*/
/* Public interface of GraphVerticalCursorDlg
/*----------------------------------------------------------------------------*/

BOOL VerticalCursorDlg(BOOL bRemoveActiveCursorAndHideDlg = FALSE)
{
	if (bRemoveActiveCursorAndHideDlg)
	{
		if (s_pVerticalCursorDlg)
		{
			s_pVerticalCursorDlg->SendMessage(WM_CLOSE);
		}
		return TRUE;
	}

	// FALSE == bRemoveActiveCursorAndHideDlg now
	BOOL bRet = FALSE;
	if ( s_pVerticalCursorDlg )
	{
		if ( s_pVerticalCursorDlg->Visible )
			return FALSE;
		bRet = s_pVerticalCursorDlg->StartVerticalCursor();
		if (bRet)
			s_pVerticalCursorDlg->UpdateDialogData();
		s_pVerticalCursorDlg->Visible = bRet;
	}
	else
	{
		if ( !THE_VCURSOR_MANAGER.CanStartVerticalCursor() )
			return FALSE;
		s_pVerticalCursorDlg = new GraphVerticalCursorDlg;
		if (s_pVerticalCursorDlg)
			bRet = s_pVerticalCursorDlg->Create( GetWindow() );

		if (!bRet)
			return error_report("Failed to create the tool window!", true);
	}
	return bRet;
}

/*----------------------------------------------------------------------------*/
/* For initializing the GraphVerticalCursorManager's holder, creating/showing the dialog, etc.
/*----------------------------------------------------------------------------*/

BOOL CheckInitVerticalCursorAndExecEvent(int nEvent, const string strObjectName, int nObjType)
{
	if (OE_SELECT == nEvent || OE_MOVE == nEvent || OE_MOVING == nEvent)
	{
		const int nLoadCursorResult = THE_VCURSOR_MANAGER.LoadCursorInfoFromPage();
		switch (nLoadCursorResult)
		{
		case LOAD_CURSOR_INFO_FAILED:
			MY_DBG_OUTPUT1("Failed to load the cursor holder info at event %d", nEvent);
			return FALSE;
			break;
		case LOAD_CURSOR_INFO_OK:
			MY_DBG_OUTPUT1("Successfully loaded the cursor holder info at event %d", nEvent);
			break;
		case CURSOR_INFO_EXIST_IN_MANAGER:
			break;
		}
		BOOL bRet = VerticalCursorDlg();
	}
	BOOL bRet = on_vertical_cursor_object_event(nEvent, strObjectName, nObjType);
	return bRet;
}

/*----------------------------------------------------------------------------*/
/* For debugging use only
/*----------------------------------------------------------------------------*/

#ifdef _DEBUG
void DestroyVerticalCursorDlg()
{
	if (s_pVerticalCursorDlg)
	{
		s_bDestroyDlgOnClose = TRUE;
		VerticalCursorDlg(TRUE);
	}
	THE_VCURSOR_MANAGER.ClearAllCursorHolders();
}

void ShowAllCursorPropertiesTree()
{
	THE_VCURSOR_MANAGER.ShowPropertiesTree();
}

void ShowCurrentPageCursorBinaryTree()
{
	GraphLayer glActive = Project.ActiveLayer();
	if (glActive)
	{
		GraphPage gp = glActive.GetPage();
		if (gp)
		{
			CStopWatch watch("ShowCurrentPageBinaryTree()");
			Tree trProperties;
			BOOL bRet = gp.GetBinaryStorage(STR_VERTICAL_CURSOR_BINARY_STORAGE_NAME, trProperties);
			out_tree(trProperties);
		}
	}
}
#endif // _DEBUG
