/*------------------------------------------------------------------------------*
 * File Name:	TreeTable.h 													*
 * Creation: 	Frank															*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * Frank 10/10/04 v8.0147  SUPPORT_SUBHEADER_TITLE								*
 * Frank 10/12/04 v8.0147  MORE_SUPPORT_SUBHEADER_TITLE							*
 * Frank 10/27/04 v8.0156  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING				*
 * Frank 01/18/05 v8.0184b SUPPORT_DISPLAY_FORMATS_NULL_NOT_JUSTIFY				*
 * Frank 5/26/05  	GETN_EVENT_SUPPORT_GRID_VIEW								*
 * AW 08/31/05 FIXING_SAME_TAGNAME_IN_TREE_TABLE								*
 *	Frank 9/29/05 v8.0311 CHANGE_ENTER_TO_ENTER_WITH_RETURN_CHAR				*
 * Frank 10/17/06 ADD_DOUBLE_OUTPUR_FORMAT_IN_TREE_OUT							*
 * Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE								*
 *	Frank 11/04/05 FIXED_SUB_COL_WHEN_PASS_BY_REF_OF_VECTOR						*
 * Jim 01/16/06 v8.0357 APPEND_BLANK_TABLE_CELL_VALUE  
 * Alex 03/13/06 v8.0374 FIXED_INSERTAT_WHEN_PASS_BY_0
 * Hong 04/04/06 QA70-6903 FIXED_ERROR_OUTPUT_OF_HIDDEN_NODE                    *
 *------------------------------------------------------------------------------*/
#ifndef _TREE_TABLE_H_
#define _TREE_TABLE_H_
///Frank 10/27/04 v8.0156  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING
///Move to OC_const.h
//enum {TREENODE_DATA_TYPE_NORMAL, TREENODE_DATA_TYPE_VECTOR,TREENODE_DATA_TYPE_MATRIX};
///End  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING

class	TreeTable
{
public:
	//void			TreeTable(TreeNode &tr, vector<int> &vnDisplayFormat,bool bSkipHidden = true, bool bTranspose = false,bool bLev1AsCols = true , string strDoubleValueFormat = "*" );
	///Add argument of treeTable
	void			TreeTable(TreeNode &tr, vector<int> &vnDisplayFormat,bool bSkipHidden = true, bool bTranspose = false,bool bLev1AsCols = true , string strDoubleValueFormat = "*" , int nTableType = 0 );
	void			TreeTable();
	BOOL			IsValid();
	int				GetNumCols();
	int 			GetNumRows();
	string			GetCell(int nCol, int nRow);
	BOOL			SetCell(int nCol, int nRow, LPCSTR lpcstr);
	uint 			GetColWidth(int nCol);
	//string			GetTable(int nExtraSpace = 1, int nXoffset = 0, bool bShowSeparator = true);
	string			GetTable(int nExtraSpace = 1, int nXoffset = 0,bool bShowSubHeaders = true, bool bShowSeparator = true);
	
	//bool			SetTree(TreeNode &tr,vector<int> &vnDisplayFormat ,bool bSkipHidden = true, bool bTranspose = false,bool bLev1AsCols = true , string strDoubleValueFormat = "*" );
	//bool			SetTree(TreeNode &tr,vector<int> &vnDisplayFormat = NULL ,bool bSkipHidden = true, bool bTranspose = false,bool bLev1AsCols = true , string strDoubleValueFormat = "*");
	///Add argument of treeTable
	bool			SetTree(TreeNode &tr,vector<int> &vnDisplayFormat = NULL ,bool bSkipHidden = true, bool bTranspose = false,bool bLev1AsCols = true , string strDoubleValueFormat = "*", int nTableType = 0);
	TreeNode		GetTreeNode(int nCol, int nRow);
	
	void			GetTreeTableRowCol(int nTreeRow, int &nViewRow, int &nViewCol );///-----Frank 5/26/05  	GETN_EVENT_SUPPORT_GRID_VIEW

	///-----
private:
	//void			addTreeFirstLevelNameAndLable(TreeNode &tr,vector<string> &vsTagName, vector<string> &vsLabel, bool bSkipHidden);	
	//void			addTreeSecondLevelNameAndLable(TreeNode &tr, vector<string> &vsTagName, vector<string> &vsLabel, bool bSkipHidden);	
	///Frank 10/10/04 v8.0147  SUPPORT_SUBHEADER_TITLE
	void			addTreeFirstLevelNameAndLable(TreeNode &tr,vector<string> &vsTagName, vector<string> &vsLabel,vector<string>& vsSubHeaders, bool bSkipHidden);	
	void			addTreeSecondLevelNameAndLable(TreeNode &tr, vector<string> &vsTagName, vector<string> &vsLabel,vector<string>& vsSubHeaders, bool bSkipHidden);	
	void			prepareSubHeadersString(vector<string> &vsColSubHeaders, vector<string> &vsRowSubHeaders, vector<uint> &vuColWidths, vector<int> &vnDisplayFormat);
	///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE
	//void			padStringVector(vector<string> &vsHeader, int nPadedWidth, int nDisaplyFormat );
	void			padStringVector(vector<string> &vsHeader, uint &nPadedWidth, int nDisaplyFormat, int nBegin =0, int nEnd =-1 );
	///-----End SUPPORT_MULTIPLE_SUBHEADER_TITLE
	int 			getTreeNodeSubHeaders(TreeNode trNode, vector<string> &vsSubHeaders, int nStartIndex = 0, LPCSTR lpcszHeaderPrefix = NULL);// 0, NULL
	///End  SUPPORT_SUBHEADER_TITLE
	//int			GetNumCols();
	//int 			GetNumRows();
	///-----Hong 04/04/06 QA70-6903 FIXED_ERROR_OUTPUT_OF_HIDDEN_NODE	
	//void			processTwoDimensionTreeNodeValue(TreeNode &tr, vector<string> &vsColTagNames, vector<string> &vsRowTagNames,vector<string> &vsTableCellValues, string strDoubleValueFormat);
	void			processTwoDimensionTreeNodeValue(TreeNode &tr, vector<string> &vsColTagNames, vector<string> &vsRowTagNames,vector<string> &vsTableCellValues, string strDoubleValueFormat, bool bSkipHidden = true);
	///-----End FIXED_ERROR_OUTPUT_OF_HIDDEN_NODE
	void 			processLeafTreeNodeValue(TreeNode &tr, vector<string> &vsColTagNames,vector<string> &vsTableCellValues, string strDoubleValueFormat );
	
	bool			addTreeNodeTagAndLable(TreeNode &tr,vector<string> &vsTagName, vector<string> &vsLableName, bool bSkipHidden,bool bSkipSameTagNameNode = true);
	
	void			getColsWidth(vector<string> &vsRowLables, vector<string> &vsColLables, vector<string> &vsTableCellValues, vector<uint> &vuColWidths, uint &uRowHeadingWidth);
	///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE
	//uint			getColMaxWidth(const vector<string> &vsColData);
	uint			getColMaxWidth(const vector<string> &vsColData, int nBegin =0, int nEnd =-1);
	///-----End SUPPORT_MULTIPLE_SUBHEADER_TITLE

	string 			getCell(int nCol, int nRow);
	void			setCell(int nCol, int nRow, LPCSTR lpcstr);
	string			getRowHeader(int nRow);
	string			getColHeader(int nCol);
	void			setRowHeader(int nRow,  LPCSTR lpcstr);
	void			setColHeader(int nCol,  LPCSTR lpcstr);
	
	void			formatingHeaderAndData(vector<int> &vnDisplayFormat, const vector<uint> &vuColWidths, uint uRowHeadingWidth, bool bLev1AsCols);
	///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE
	//void			convertColBaseToRowBase(vector<string> &vsColLables ,vector<string> &vsRowLables,vector<string> &vsTableCellValues);
	void			convertColBaseToRowBase(vector<string> &vsColLables ,vector<string> &vsRowLables,vector<string> &vsTableCellValues, vector<string> &vsRowSubHeaders, vector<string> &vsColSubHeaders);
	///-----End SUPPORT_MULTIPLE_SUBHEADER_TITLE
	///Frank 10/27/04 v8.0156  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING
	void			clearMemberVariable();
	int				separateTreeNodeMatrixToCell(TreeNode &trMatNode, vector<string> &vsTableCellValues, LPCSTR strDoubleValueFormat, int &nMatCols);
	int				getVectorTreeNodeToCell(TreeNode &tr, vector<string> &vsTableCellValues, LPCSTR strDoubleValueFormat, int &nVecCols);
	///End  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING
private:
	TreeNode		m_trNode;
	bool			m_bTranspose;
	bool			m_bIsValid;
	vector<string>	m_vsRowLables;
	vector<string>	m_vsColLables;
	vector<string>	m_vsRowTagNames;
	vector<string>	m_vsColTagNames;
	vector<string>	m_vsTableCellValues;
	
	vector<string>	m_vsColSubHeaders;
	vector<string>	m_vsRowSubHeaders;
	uint			m_uRowSubHeadingWidth;
	//int				m_nColSubHeaderCount;
	//int				m_nRowSubHeaderCount;
	
	int				m_nNumCols;
	int				m_nNumRows;
	vector<uint>	m_uColWidths;
	uint			m_uRowHeadingWidth;
	int				m_nDimension;
	
	bool			m_bLev1AsCols;
};
void 		TreeTable::TreeTable()
{
	m_bIsValid = false;
	//m_nColSubHeaderCount = 0;
}
///Frank 10/27/04 v8.0156  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING
/*
void 		TreeTable::TreeTable(TreeNode &tr, vector<int> &vnDisplayFormat,bool bSkipHidden,bool bTranspose , bool bLev1AsCols,string strDoubleValueFormat )
{
	SetTree(tr, vnDisplayFormat,bSkipHidden , bTranspose , bLev1AsCols, strDoubleValueFormat);
}
*/
void 		TreeTable::TreeTable(TreeNode &tr, vector<int> &vnDisplayFormat,bool bSkipHidden,bool bTranspose , bool bLev1AsCols,string strDoubleValueFormat ,int nTableType )
{
	SetTree(tr, vnDisplayFormat,bSkipHidden , bTranspose , bLev1AsCols, strDoubleValueFormat, nTableType);
}
///End  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING

//bool		TreeTable::SetTree(TreeNode &tr,vector<int> &vnDisplayFormat,bool bSkipHidden , bool bTranspose ,bool bLev1AsCols , string strDoubleValueFormat )
bool		TreeTable::SetTree(TreeNode &tr,vector<int> &vnDisplayFormat,bool bSkipHidden , bool bTranspose ,bool bLev1AsCols , string strDoubleValueFormat ,int nTableType)
{
	if(!tr || (bSkipHidden && tr.Show == 0))
	{
		m_bIsValid = false;
		clearMemberVariable();///Frank 10/27/04 v8.0156  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING
		return false;
	}
	m_bIsValid = true;
	m_trNode = tr;
	
	m_bLev1AsCols = bLev1AsCols;

	vector<string>	vsColTagNames;
	vector<string>	vsColLables;
	vector<string>	vsColSubHeaders;
	//addTreeFirstLevelNameAndLable(tr, vsColTagNames, vsColLables, bSkipHidden);
	addTreeFirstLevelNameAndLable(tr, vsColTagNames, vsColLables,vsColSubHeaders,  bSkipHidden);	///Frank 10/10/04 v8.0147  SUPPORT_SUBHEADER_TITLE
	
	int nNumCols	= vsColTagNames.GetSize();

	if(nNumCols ==0 )
	{
		m_bIsValid = false;
		clearMemberVariable();
		return false;
	}
	//m_nNumCols = nNumCols;
	
	vector<string>	vsRowTagNames ;
	vector<string>	vsRowLables ;
	vector<string>	vsRowSubHeaders;
	//addTreeSecondLevelNameAndLable(tr, vsRowTagNames,vsRowLables , bSkipHidden);
	addTreeSecondLevelNameAndLable(tr, vsRowTagNames,vsRowLables ,vsRowSubHeaders, bSkipHidden);	///Frank 10/10/04 v8.0147  SUPPORT_SUBHEADER_TITLE
	
	int nNumRows = vsRowTagNames.GetSize();
	
	vector<string>	vsTableCellValues;
	string strLableTemp;
	///--Check if the second now is empty, if yes, then use first level lable as column lable and value as row value to show, use zero level's label as Row name,
	if(nNumRows == 0)
	{
		///Frank 10/27/04 v8.0156  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING
		////If just one level branch, swap name of cols and rows
		//nNumRows = nNumCols;
		//nNumCols = 1;
		
		if(!tr.GetAttribute(STR_LABEL_ATTRIB,strLableTemp))
			strLableTemp = " ";
		
		vsRowLables = vsColLables;
		/////Temp for vector treenode, because now cant know what node of table.
		//if(bTranspose)
			//nTableType = TREENODE_DATA_TYPE_NORMAL;
		//else
			//nTableType = TREENODE_DATA_TYPE_VECTOR;
		/////Temp end
		vsColLables.RemoveAll();
		switch(nTableType)
		{
			case TREENODE_DATA_TYPE_NORMAL:
				//If just one level branch, swap name of cols and rows
				nNumRows = nNumCols;
				nNumCols = 1;
				vsColLables.Add(strLableTemp);
				processLeafTreeNodeValue(tr, vsColTagNames, vsTableCellValues, strDoubleValueFormat);
				bTranspose = !bTranspose;
				break;
				
			case TREENODE_DATA_TYPE_VECTOR:
				//nNumRows = nNumCols;
				//nNumCols = getVectorTreeNodeToCell(tr,  vsTableCellValues, strDoubleValueFormat);
				nNumRows = getVectorTreeNodeToCell(tr,  vsTableCellValues, strDoubleValueFormat, nNumCols);
				vsColLables = vsRowLables;
				vsRowLables.RemoveAll();
				vsRowLables.SetSize(nNumRows);
				break;
				
			case TREENODE_DATA_TYPE_MATRIX:
				//nNumRows = nNumCols;
				//nNumCols = separateTreeNodeMatrixToCell(tr, vsTableCellValues, strDoubleValueFormat);
				//vsColLables.SetSize(nNumCols);
				nNumRows = separateTreeNodeMatrixToCell(tr,  vsTableCellValues, strDoubleValueFormat,nNumCols);
				vsColLables = vsRowLables;
				vsRowLables.RemoveAll();
				vsRowLables.SetSize(nNumRows);
				vsColLables.SetSize(nNumCols);
				bTranspose = false;
				break;
		default:
				///Frank 11/23/04 v8.0167 			CHECK_TREE_TABLE_TYPE_VISIABLE	
				///Will output empty table as string, will just one row header or just col header.
				nNumRows = nNumCols;
				nNumCols = 0;
				vsColLables.Add("");
				bTranspose = !bTranspose;
				break;
				///End	CHECK_TREE_TABLE_TYPE_VISIABLE	
		}
		//vsColLables.Add(strLableTemp);
		//processLeafTreeNodeValue(tr, vsColTagNames, vsTableCellValues, strDoubleValueFormat);
		//bTranspose = !bTranspose;

		///End  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING

	}
	else
		///-----Hong 04/04/06 QA70-6903 FIXED_ERROR_OUTPUT_OF_HIDDEN_NODE	
		//processTwoDimensionTreeNodeValue(tr, vsColTagNames, vsRowTagNames,vsTableCellValues, strDoubleValueFormat);
		processTwoDimensionTreeNodeValue(tr, vsColTagNames, vsRowTagNames,vsTableCellValues, strDoubleValueFormat, bSkipHidden);
		///-----End FIXED_ERROR_OUTPUT_OF_HIDDEN_NODE	
		
	if(bTranspose)
	{
		m_nNumRows	= nNumRows ;
		m_nNumCols	= nNumCols;
		//convertColBaseToRowBase(vsColLables, vsRowLables, vsTableCellValues);
		convertColBaseToRowBase(vsColLables, vsRowLables, vsTableCellValues,vsRowSubHeaders, vsColSubHeaders);///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE
		int nTemp = nNumRows;
		nNumRows = nNumCols ;
		nNumCols = nTemp;
		///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE
		///Frank 10/10/04 v8.0147  SUPPORT_SUBHEADER_TITLE
		//m_vsRowSubHeaders = vsColSubHeaders;	
		///End	 SUPPORT_SUBHEADER_TITLE
	}
	//else
		//m_vsColSubHeaders = vsColSubHeaders;	///Frank 10/10/04 v8.0147  SUPPORT_SUBHEADER_TITLE
		m_vsColSubHeaders = vsColSubHeaders;
		m_vsRowSubHeaders = vsRowSubHeaders;	
		///-----End SUPPORT_MULTIPLE_SUBHEADER_TITLE

		
	//Save data 
	m_nNumRows	= nNumRows ;
	m_nNumCols	= nNumCols;
	m_vsTableCellValues = vsTableCellValues;
	m_vsColLables = vsColLables;
	m_vsRowLables = vsRowLables;
	
	m_vsRowTagNames = vsRowTagNames; ///If just one column, this vector will empty.
	m_vsColTagNames = vsColTagNames;
	m_bTranspose = bTranspose;		///Store bTranspose to member data, will be use in gettreeNode.
	///calculate all col width and store into m_uColWidths;
	getColsWidth(m_vsRowLables, m_vsColLables, m_vsTableCellValues, m_uColWidths, m_uRowHeadingWidth);
	///Frank 01/18/05 v8.0184b SUPPORT_DISPLAY_FORMATS_NULL_NOT_JUSTIFY
	/*
	///Frank 10/12/04 v8.0147  MORE_SUPPORT_SUBHEADER_TITLE	
	vector<int> vnDispFormatTemp= { DISPLAY_CENTER, DISPLAY_RIGHT, DISPLAY_RIGHT};
	if(vnDisplayFormat != NULL)
		vnDispFormatTemp = vnDisplayFormat;
	///End  MORE_SUPPORT_SUBHEADER_TITLE	
	
	//prepareSubHeadersString(m_vsColSubHeaders, m_vsRowSubHeaders,m_uColWidths, vnDisplayFormat);	///Frank 10/10/04 v8.0147  SUPPORT_SUBHEADER_TITLE
	//formatingHeaderAndData(vnDisplayFormat,m_uColWidths, m_uRowHeadingWidth,  bLev1AsCols);
	prepareSubHeadersString(m_vsColSubHeaders, m_vsRowSubHeaders,m_uColWidths, vnDispFormatTemp);	
	formatingHeaderAndData(vnDispFormatTemp,m_uColWidths, m_uRowHeadingWidth,  bLev1AsCols);
	*/
	if(vnDisplayFormat != NULL)
	{
		prepareSubHeadersString(m_vsColSubHeaders, m_vsRowSubHeaders,m_uColWidths, vnDisplayFormat);	
		formatingHeaderAndData(vnDisplayFormat,m_uColWidths, m_uRowHeadingWidth,  bLev1AsCols);
	}
	///End SUPPORT_DISPLAY_FORMATS_NULL_NOT_JUSTIFY
	return true;
}
///Frank 10/27/04 v8.0156  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING
int		TreeTable::separateTreeNodeMatrixToCell(TreeNode &trMatNode, vector<string> &vsTableCellValues, LPCSTR strDoubleValueFormat, int &nMatCols)
{
	matrix	matTrN;
	vector<double>	vdColValue;
	vector<string>	vstColValue;
	//int nMatCols;

	///Frank 11/1/04	v8.0157	GET_NUMERICA_VECTOR_OR_MATRIX_FROM_TREENODE	
	vsTableCellValues.RemoveAll();
	TreeNode trMatTemp = trMatNode;
	if(trMatTemp.GetNodeCount() == 0)
		trMatTemp = trMatNode.Parent();
	foreach(TreeNode trMat in trMatTemp.Children)
	{
		if(get_numerica_matrix_treenode(trMat, matTrN))
		{
			nMatCols = matTrN.GetNumCols();
			for(int nColIndex = 0; nColIndex < nMatCols; nColIndex++)
			{
				if(!matTrN.GetColumn(vdColValue, nColIndex))
					return 0;
				
				///Frank 10/17/06 ADD_DOUBLE_OUTPUR_FORMAT_IN_TREE_OUT
				//convert_double_vector_to_string_vector(vdColValue, vstColValue, vdColValue.GetSize(),strDoubleValueFormat);
				vector<string> vsFormat;
				vsFormat.InsertAt(0, strDoubleValueFormat, vdColValue.GetSize());
				convert_double_vector_to_string_vector(vdColValue, vstColValue, vdColValue.GetSize(),vsFormat);
				///End ADD_DOUBLE_OUTPUR_FORMAT_IN_TREE_OUT
				vsTableCellValues.Append(vstColValue);
			}		
		}
		else 
			return -1;
	}
	
	//matTrN = trMatNode.dVals2;
	//vsTableCellValues.RemoveAll();
	//nMatCols = matTrN.GetNumCols();
	//
	//for(int nColIndex = 0; nColIndex < nMatCols; nColIndex++)
	//{
		//if(!matTrN.GetColumn(vdColValue, nColIndex))
			//return 0;
		//
		//convert_double_vector_to_string_vector(vdColValue, vstColValue, vdColValue.GetSize(),strDoubleValueFormat);
		//vsTableCellValues.Append(vstColValue);
	//}
	///End	GET_NUMERICA_VECTOR_OR_MATRIX_FROM_TREENODE	
	return vstColValue.GetSize();
}
int		TreeTable::getVectorTreeNodeToCell(TreeNode &tr, vector<string> &vsTableCellValues, LPCSTR strDoubleValueFormat, int &nVecCols)
{
	vector<double>	vdColValue;
	vector<string>	vstColValue;
	//int nMatCols;
	nVecCols=0;
	vsTableCellValues.RemoveAll();
	//nMatCols = matTrN.GetNumCols();
	int nVectorSize = 0;
	
	foreach(TreeNode trNode in tr.Children )
	{
		///Frank 11/1/04	v8.0157	GET_NUMERICA_VECTOR_OR_MATRIX_FROM_TREENODE	
		if(!get_numerica_vector_treenode(trNode, vdColValue) && trNode.TypeID == TNVAL_TYPE_CSTRING_VECTOR)
		{
			vstColValue = trNode.strVals;			
		}
		else
			///Frank 10/17/06 ADD_DOUBLE_OUTPUR_FORMAT_IN_TREE_OUT
			//convert_double_vector_to_string_vector(vdColValue, vstColValue, vdColValue.GetSize(),strDoubleValueFormat);
		{
			vector<string> vsFormat;
			if(vdColValue.GetSize() > 0) ///Jim 01/16/06 v8.0357 APPEND_BLANK_TABLE_CELL_VALUE
			{	
				vsFormat.InsertAt(0, strDoubleValueFormat, vdColValue.GetSize());
				convert_double_vector_to_string_vector(vdColValue, vstColValue, vdColValue.GetSize(),vsFormat);
			}
			else
			{
				//vstColValue.InsertAt(0, "", nVectorSize);///Alex 03/13/06 v8.0374 FIXED_INSERTAT_WHEN_PASS_BY_0///for the nVectorSize will be 0 and will cause runtime error
				
				vstColValue.InsertAt(0, "");
			}
			
		}
		
		///End ADD_DOUBLE_OUTPUR_FORMAT_IN_TREE_OUT
		//vdColValue = trNode.dVals;
		//convert_double_vector_to_string_vector(vdColValue, vstColValue, vdColValue.GetSize(),strDoubleValueFormat);
		///End	GET_NUMERICA_VECTOR_OR_MATRIX_FROM_TREENODE	
		///Frank 11/23/04 v8.0167 			CHECK_TREE_TABLE_TYPE_VISIABLE	
		nVecCols++;
		///Get the first valid vector's size of default size.
		if(nVectorSize <= 0)
			nVectorSize = vstColValue.GetSize();
		else
			vstColValue.SetSize(nVectorSize);
		if(vstColValue.GetSize() == 0)
			vsTableCellValues.SetSize(nVectorSize*nVecCols);
		///End		CHECK_TREE_TABLE_TYPE_VISIABLE	
	
		vsTableCellValues.Append(vstColValue);
		
	}
	return vstColValue.GetSize();
}
void		TreeTable::clearMemberVariable()
{
	m_nNumCols = 0;
	m_nNumRows = 0;
	m_vsRowLables.RemoveAll();
	m_vsColLables.RemoveAll();
	m_vsTableCellValues.RemoveAll();
}
///End  MATRIX_OR_VECTOR_TREENODE_OUTPUT_STRING
/// AW 08/31/05 FIXING_SAME_TAGNAME_IN_TREE_TABLE
// move this method to getnbox.c
/*
TreeNode	TreeTable::GetTreeNode(int nCol, int nRow)
{
	TreeNode  trNode;
	if(nCol < 0 || nRow<0 || nCol >= GetNumCols() || nRow >= GetNumRows())
		return trNode;
	int nTemp;
	if(m_bTranspose)
	{
		nTemp = nRow;
		nRow = nCol;
		nCol = nTemp;
	}
	///If the tree just have one column.
	if(m_vsRowTagNames.GetSize() == 0)
		return m_trNode.GetNode(m_vsColTagNames[nCol]);
	///If the tree just have one row.
	if(m_vsColTagNames.GetSize() == 0)
		return m_trNode.GetNode(m_vsRowTagNames[nRow]);
	TreeNode trFirstLevelNode;
	trFirstLevelNode = m_trNode.GetNode(m_vsColTagNames[nCol]);
	if(trFirstLevelNode)
		trNode	= trFirstLevelNode.GetNode(m_vsRowTagNames[nRow]);
	return trNode;
}
*/
/// END FIXING_SAME_TAGNAME_IN_TREE_TABLE

///-----Frank 5/26/05  	GETN_EVENT_SUPPORT_GRID_VIEW
void	TreeTable::GetTreeTableRowCol(int nTreeRow, int &nViewRow, int &nViewCol )
{
	if(!IsValid() || nTreeRow < 0)
		return;
	
	nViewRow = 0;
	nViewCol = 0;
	
	if(nTreeRow == 0)
		return ;
	
	int nRowCount = 0;///Because TreeNode row is zero base index
	int nCurNodeCount =0;
	int nSectionCount =0 ;
	
	foreach(TreeNode cNode in m_trNode.Children)
	{
		nViewRow++;
		//nCurNodeCount = cNode.GetNodeCount();
		nCurNodeCount = tree_count_items(cNode, &nSectionCount);
		nCurNodeCount += nSectionCount;
		
		nRowCount += nCurNodeCount +1;
		
		if(nRowCount < nTreeRow)
			continue;
		else 
			if(nRowCount > nTreeRow)
			{
				nViewCol = nCurNodeCount - (nRowCount -1 - nTreeRow);
				break;
			}
			else
			//if(nRowCount == nTreeRow)
			{
				nViewCol = 0;
				break;
			}
	}
	if(!m_bTranspose)
	{
		int nTemp;
		nTemp = nViewCol;
		nViewCol = nViewRow;
		nViewRow = nTemp;
	}
	
}
///-----End	GETN_EVENT_SUPPORT_GRID_VIEW

//void	TreeTable::addTreeFirstLevelNameAndLable(TreeNode &tr,vector<string> &vsTagNames, vector<string> &vsLableNames, vector<string>& vsSubHeaders,int nSubHeaderCount, bool bSkipHidden)	
void	TreeTable::addTreeFirstLevelNameAndLable(TreeNode &trSor,vector<string> &vsTagNames, vector<string> &vsLableNames, vector<string>& vsSubHeaders, bool bSkipHidden)	
{
	TreeNode	tr = trSor;
	if(!tr)
		return ;
	
	//if(bSkipHidden && tr.Show == 0)  /// Iris 5/22/06 FOOTNODE_WORK_IN_NOTE_WIN
	if(bSkipHidden && tr.Show == 0 || tree_is_foot_node(tr))
		return ;
	//vector<string>	vsSubHeaders;
	
	int nSubHeaderCount =0;
	int nCurrentHeaderCount =0;
	bool	bSubHeaderFirstTime = false;
	
	string	strLableTemp;
	int nColIndex =1;
	
	if(tr.GetNodeCount() == 0 )
		tr = trSor.Parent();
	
	foreach(TreeNode trFirstLevNode in tr.Children	)
	{
		//if(bSkipHidden && trFirstLevNode.Show == 0)  /// Iris 5/22/06 FOOTNODE_WORK_IN_NOTE_WIN
		if(bSkipHidden && trFirstLevNode.Show == 0 || tree_is_foot_node(trFirstLevNode))
			continue;		
		
		vsTagNames.Add(trFirstLevNode.tagName);
		
		///Get lable from treenode, if not exist , will get empty string.
		if(m_bLev1AsCols)
		{
			if(!trFirstLevNode.GetAttribute(STR_LABEL_ATTRIB,strLableTemp))
				strLableTemp = trFirstLevNode.tagName;///If not label, save tagName as label.
		}
		else
			strLableTemp = "Col" + nColIndex++;
		vsLableNames.Add(strLableTemp);
		
		///Frank 10/10/04 v8.0147  SUPPORT_SUBHEADER_TITLE
		nCurrentHeaderCount = getTreeNodeSubHeaders(trFirstLevNode, vsSubHeaders, 0 );
		
		if(!bSubHeaderFirstTime )
		{
			nSubHeaderCount = nCurrentHeaderCount;
			bSubHeaderFirstTime = true;
		}
		else
			if(nSubHeaderCount > 0 )
			{
				nCurrentHeaderCount = nSubHeaderCount - nCurrentHeaderCount;
				if(nCurrentHeaderCount > 0)
				{
					for(int nIndexAdd =0; nIndexAdd < nSubHeaderCount - nCurrentHeaderCount; nIndexAdd++)
						vsSubHeaders.Add(" ");
				}
				else
					if(nCurrentHeaderCount < 0)
					{
						int nSize = vsSubHeaders.GetSize();
						vsSubHeaders.RemoveAt(nSize + nCurrentHeaderCount -1, - nCurrentHeaderCount);
					}
			}
	}
}

int	TreeTable::getTreeNodeSubHeaders(TreeNode trNode, vector<string> &vsSubHeaders, int nStartIndex , LPCSTR lpcszHeaderPrefix )// 0, NULL
{
	if(!trNode)
		return -1;
	string		strAttName;
	string		strAttValue;
	string		strTempPrefix;//Temp use , because string = lpcstr + int not work.
	
	if(NULL == lpcszHeaderPrefix)
		lpcszHeaderPrefix = STR_SUB_HEADER_ATTRIB_PREFIX;
	strTempPrefix = lpcszHeaderPrefix;
	strAttName = strTempPrefix + nStartIndex;
	///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE
	///ifct == 0 mean just one subheader, temp use.
	//for (int ifct = nStartIndex; trNode.GetAttribute(strAttName, strAttValue) && ifct == 0; ifct++,strAttName = strTempPrefix + ifct)
	for (int ifct = nStartIndex; trNode.GetAttribute(strAttName, strAttValue); ifct++,strAttName = strTempPrefix + ifct)
	///-----End SUPPORT_MULTIPLE_SUBHEADER_TITLE
	{
		vsSubHeaders.Add(strAttValue);
	}
	///Frank 10/12/04 v8.0147  MORE_SUPPORT_SUBHEADER_TITLE	
	//return vsSubHeaders.GetSize() - nStartIndex;
	return ifct - nStartIndex;
	///End  MORE_SUPPORT_SUBHEADER_TITLE	
}
///End  SUPPORT_SUBHEADER_TITLE

void	TreeTable::addTreeSecondLevelNameAndLable(TreeNode &tr, vector<string> &vsTagNames, vector<string> &vsLableNames,  vector<string>& vsSubHeaders, bool bSkipHidden)
{
	if(!tr)
		return ;
	if(bSkipHidden && tr.Show == 0)
		return ;

	foreach(TreeNode trFirstLevNode in tr.Children	)
		addTreeNodeTagAndLable(trFirstLevNode,vsTagNames ,vsLableNames,bSkipHidden );	
}

bool	TreeTable::addTreeNodeTagAndLable(TreeNode &tr,vector<string> &vsTagNames, vector<string> &vsLableNames, bool bSkipHidden, bool bSkipSameTagNameNode )
{
	if(!tr)
		return false;
	string			strLableTemp;
	string			strtagName;
	foreach(TreeNode trFirstLevNode in tr.Children	)
	{
		if(bSkipHidden && trFirstLevNode.Show == 0)
			continue;
		
		strtagName = trFirstLevNode.tagName; 
		if(bSkipSameTagNameNode && vsTagNames.Find(strtagName) >= 0)
			continue;
		vsTagNames.Add(strtagName);
		//Get lable from treenode, if not exist , will get empty string.
		if(!trFirstLevNode.GetAttribute(STR_LABEL_ATTRIB,strLableTemp))
			strLableTemp = strtagName;
			
		vsLableNames.Add(strLableTemp);
	}
	return true;
}

void 	TreeTable::processLeafTreeNodeValue(TreeNode &tr, vector<string> &vsColTagNames,vector<string> &vsTableCellValues, string strDoubleValueFormat )
{
	/// Iris 5/22/06 FOOTNODE_WORK_IN_NOTE_WIN
	if( tree_is_foot_node(tr) )
		return;
	///End FOOTNODE_WORK_IN_NOTE_WIN
	
	for(int nColIndex = 0 ; nColIndex < vsColTagNames.GetSize() ;nColIndex++)
	{
		TreeNode	trNode = tr.GetNode(vsColTagNames[nColIndex]);
		
		//Check is leaf or not ro exist.
		string 		strTemp = " ";
		if(trNode && trNode.GetNodeCount() ==0)
		{
			strTemp = trNode.strVal;
			if(strDoubleValueFormat.Compare(" ") != 0 && is_numeric(strTemp))
			{
				double	dTempValue = atof(strTemp);
				char	chDValue[30];
				DoubleToStr(dTempValue,chDValue, 30, strDoubleValueFormat);
				strTemp = chDValue;
			}
		}
		vsTableCellValues.Add(strTemp);
	}
}

/// AW 08/31/05 FIXING_SAME_TAGNAME_IN_TREE_TABLE
// move this method to getnbox.c
/*
void	TreeTable::processTwoDimensionTreeNodeValue(TreeNode &tr, vector<string> &vsColTagNames, vector<string> &vsRowTagNames,vector<string> &vsTableCellValues, string strDoubleValueFormat)
{
	TreeNode		tr1LevNode;
	TreeNode		tr2LevNode;
	string			strTemp;
	vector<string>	vsTempValus;
	for(int nColIndex = 0; nColIndex < vsColTagNames.GetSize(); nColIndex++)
	{
		vsTempValus.RemoveAll();
		vector<string>	vsTreeNodeSectionValue;
		tr1LevNode = tr.GetNode(vsColTagNames[nColIndex]);
		if(!tr1LevNode)
			continue;		
		processLeafTreeNodeValue(tr1LevNode, vsRowTagNames, vsTempValus, strDoubleValueFormat);
		vsTableCellValues.Append(vsTempValus);
	}
}
*/
/// END FIXING_SAME_TAGNAME_IN_TREE_TABLE

void	TreeTable::getColsWidth(vector<string> &vsRowLables, vector<string> &vsColLables, vector<string> &vsTableCellValues, vector<uint> &vuColWidths, uint &uRowHeadingWidth)
{
	int nMaxWidth = 0;
	uint nTemp;
	
	///Save column width to vector 
	for(int nIndex = 0 ; nIndex < vsColLables.GetSize() ; nIndex++ )
	{
		vuColWidths.Add(lstrlen(vsColLables[nIndex]));
	}
	
	nTemp = getColMaxWidth(vsRowLables);
	uRowHeadingWidth = nTemp;
	
	int		nDataCols = GetNumCols();
	int		nDataRows = GetNumRows();
	vector<string>	vsTemp;
	
	if(vuColWidths.GetSize() < nDataCols)
		vuColWidths.SetSize(nDataCols);
	
	for(int nDataColIndex =0 ; nDataColIndex < nDataCols; nDataColIndex++)
	{
		vsTemp.RemoveAll();
		for(int nDataRowIndex = 0 ; nDataRowIndex < nDataRows; nDataRowIndex++ )
			vsTemp.Add(getCell(nDataColIndex, nDataRowIndex));
		
		nTemp = getColMaxWidth(vsTemp);
		//if(nDataColIndex > vuColWidths.GetSize())
			 //vuColWidths.Add( nTemp);
		//else
			if(nTemp > vuColWidths[nDataColIndex])
				 vuColWidths[nDataColIndex] = nTemp;
	}
}
///Frank 10/10/04 v8.0147  SUPPORT_SUBHEADER_TITLE
void	TreeTable::prepareSubHeadersString(vector<string> &vsColSubHeaders, vector<string> &vsRowSubHeaders, vector<uint> &vuColWidths, vector<int> &vnDisplayFormat)
{
	int		nDataCols = GetNumCols();
	int		nDataRows = GetNumRows();
	uint		nTemp;
	string	strTemp;
	vector<string> vsTemp;
		
	if(vsColSubHeaders.GetSize() > 0)
	{
		///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE
		vsTemp = vsColSubHeaders;
		_convertColBaseToRowBase(vsTemp, vsTemp.GetSize()/nDataCols, nDataCols);
		int nSubHeadersCount1 = vsTemp.GetSize()/nDataCols;
		
		for(int nColIndex =0 ;nColIndex< nDataCols;nColIndex++)
			///Frank 11/04/05 FIXED_SUB_COL_WHEN_PASS_BY_REF_OF_VECTOR
			//padStringVector(vsTemp,vuColWidths[nColIndex], vnDisplayFormat[0], nSubHeadersCount1*nColIndex, (nColIndex+1)*nSubHeadersCount1-1);
			{
				padStringVector(vsTemp,vuColWidths[nColIndex], vnDisplayFormat[0], nSubHeadersCount1*nColIndex, (nColIndex+1)*nSubHeadersCount1);
			}
			///End FIXED_SUB_COL_WHEN_PASS_BY_REF_OF_VECTOR
		
		_convertColBaseToRowBase(vsTemp, nDataCols, vsTemp.GetSize()/nDataCols);
		vsColSubHeaders = vsTemp;		
		///-----End SUPPORT_MULTIPLE_SUBHEADER_TITLE
	};
	
	if(vsRowSubHeaders.GetSize() > 0)
	{
		//vsTemp = vsRowSubHeaders;
		///Frank : just support one subheader now, so comment the code of operation multilayer subheaders
		/*
		int nSubHeadersCount = vsRowSubHeaders.GetSize()/nDataRows;
		for(int	nDataRowIndex= 0; nDataRowIndex < nDataRows; nDataRowIndex++ )
		{
			for(int	nDataColIndex = 0 ; nDataColIndex < nSubHeadersCount ;nDataColIndex++)
			{
				strTemp = vsTemp[ nDataRowIndex + nSubHeadersCount*nDataRows ];
				vsRowSubHeaders[ nSubHeadersCount + nDataRowIndex*nDataRows ] = strTemp;
			}
		}
		for(int nRow =0; nRow<nDataRows ; nRow++)
		{
			vsRowSubHeaders.GetSubVector(vsTemp, nRow*nDataRows, (n+1)* nDataRows);
			//vsTemp = vsRowSubHeaders;///Temp solution
			nTemp = getColMaxWidth(vsTemp);
			padStringVector(vsTemp,nTemp,vnDisplayFormat[1]);
			vsRowSubHeaders.SetSubVector(vsTemp, nRow*nDataRows);
			//m_uRowSubHeadingWidth = nTemp;
			//vsRowSubHeaders = vsTemp;///Temp solution
		}
		*/
		///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE
		/*
		///Temp solution
		vsTemp = vsRowSubHeaders;
		nTemp = getColMaxWidth(vsTemp);
		padStringVector(vsTemp,nTemp,vnDisplayFormat[1]);
		m_uRowSubHeadingWidth = nTemp;
		vsRowSubHeaders = vsTemp;
		//End
		*/
		int nSubHeadersCount = vsRowSubHeaders.GetSize()/nDataRows;
		
		for(int nSubIndex =0 ;nSubIndex<  nSubHeadersCount;nSubIndex++)
		{
			padStringVector(vsRowSubHeaders, nTemp,vnDisplayFormat[1], nDataRows * nSubIndex,(nSubIndex+1)*nDataRows);
			m_uRowSubHeadingWidth +=nTemp;
		}
		///-----End SUPPORT_MULTIPLE_SUBHEADER_TITLE
		
	}
}
///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE
/*
void	TreeTable::padStringVector(vector<string> &vsHeader, int nPadedWidth, int nDisaplyFormat )
{
	for(int n = 0 ; n < vsHeader.GetSize(); n++)
		vsHeader[n] = str_pad_char(vsHeader[n],nPadedWidth, nDisaplyFormat );
	
}
*/
void	TreeTable::padStringVector(vector<string> &vsHeader, uint &nPadedWidth, int nDisplayFormat, int nBegin, int nEnd)
{
 	if(nEnd <0)
		nEnd = vsHeader.GetSize();
	if(nBegin > nEnd || nEnd > vsHeader.GetSize() || nBegin <0 )
		return;
	///Frank 11/04/05 FIXED_SUB_COL_WHEN_PASS_BY_REF_OF_VECTOR
	//nPadedWidth = getColMaxWidth(vsHeader, nBegin, nEnd);
	int nColWid;
	nColWid = getColMaxWidth(vsHeader, nBegin, nEnd);
	if(nColWid > nPadedWidth)
		nPadedWidth = nColWid;
	///End FIXED_SUB_COL_WHEN_PASS_BY_REF_OF_VECTOR
	
	for(int n = nBegin ; n < nEnd; n++)
		vsHeader[n] = str_pad_char(vsHeader[n],nPadedWidth, nDisplayFormat );
}
///-----End SUPPORT_MULTIPLE_SUBHEADER_TITLE
///End SUPPORT_SUBHEADER_TITLE

string TreeTable::getCell(int nCol, int nRow)
{
	return m_vsTableCellValues[nRow + nCol*GetNumRows()];
}
void	TreeTable::setCell(int nCol, int nRow,  LPCSTR lpcstr)
{
	m_vsTableCellValues[nRow + nCol*GetNumRows()] = lpcstr;
}

///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE
/*
uint	TreeTable::getColMaxWidth(vector<string> &vsColValue)
{
	int nMaxWidth = 0;
	int nTemp;
	for(int nIndex = 0 ; nIndex < vsColValue.GetSize() ; nIndex++ )
	{
		nTemp = lstrlen(vsColValue[nIndex]);
		if(nTemp > nMaxWidth)
			nMaxWidth = nTemp;
	}
	return nMaxWidth;
}
*/
uint	TreeTable::getColMaxWidth(vector<string> &vsColValue, int nBegin, int nEnd)
{
	if(nEnd <0)
		nEnd = vsColValue.GetSize();
	if(nBegin > nEnd || nEnd > vsColValue.GetSize() || nBegin <0 )
		return 0;

	int nMaxWidth = 0;
	int nTemp;
	for(int nIndex = nBegin ; nIndex < nEnd ; nIndex++ )
	{
		nTemp = lstrlen(vsColValue[nIndex]);
		if(nTemp > nMaxWidth)
			nMaxWidth = nTemp;
	}
	return nMaxWidth;
}
///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE

BOOL	TreeTable::IsValid()
{
	return m_bIsValid;
}
//int TreeTable::GetNumCols()
//{
	//return GetNumCols()+1;
//}

//int TreeTable::GetNumRows()
//{
	//return GetNumRows()+1;
//}
int TreeTable::GetNumCols()
{
	return m_nNumCols;
}

int TreeTable::GetNumRows()
{
	return m_nNumRows;
}

uint 	TreeTable::GetColWidth(int nCol)
{
	if(nCol > m_uColWidths.GetSize())
		return 0;
	else
		return m_uColWidths[nCol];
}

string		TreeTable::GetCell(int nCol, int nRow)
{
	//if( nCol<0 || nCol > GetNumCols() || nRow < 0 || nRow > GetNumRows() ) 
	if( nCol > GetNumCols() || nRow > GetNumRows() ) 
		return "";
	if(nCol < 0 && nRow< 0)
		return " ";
	if( nCol < 0 )
		return getRowHeader(nRow);
	if( nRow < 0 )
		return getColHeader(nCol);
	return getCell(nCol, nRow);	 
		
}
string	TreeTable::getRowHeader(int nRow)
{
	return m_vsRowLables[nRow];
}
string	TreeTable::getColHeader(int nCol)
{
	return m_vsColLables[nCol];
}
void	TreeTable::setRowHeader(int nRow, LPCSTR lpcstr)
{
	m_vsRowLables[nRow] = lpcstr;
}
void	TreeTable::setColHeader(int nCol, LPCSTR lpcstr)
{
	 m_vsColLables[nCol] = lpcstr ;
}

BOOL		TreeTable::SetCell(int nCol, int nRow, LPCSTR lpcstr)
{
/*	if( nCol<0 || nCol > GetNumCols() || nRow < 0 || nRow > GetNumRows() || (nCol==0 && nRow == 0))
		return false;
	if( nCol ==0 )
	{
		setRowHeader(nRow-1, strVal );
		return true;
	}
	if( nRow ==0 )
	{
		setColHeader( nCol-1, strVal );
		return true;
	}
	setCell(nCol-1, nRow-1, strVal);	 
	return true;
	*/
	//if( nCol<0 || nCol > GetNumCols() || nRow < 0 || nRow > GetNumRows() ) 
	if( nCol > GetNumCols() || nRow > GetNumRows() ) 
		return false;
	if(nCol < 0 && nRow< 0)
		return false;
	if( nCol < 0 )
	{
		setRowHeader(nRow, lpcstr);
		return true;
	}
	if( nRow < 0 )
	{
		setColHeader( nCol, lpcstr );
		return true;
	}
	setCell(nCol, nRow, lpcstr);	 

	///new set to tree value;
	TreeNode  trNode;
	int nTemp;
	if(m_bTranspose)
	{
		nTemp = nRow;
		nRow = nCol;
		nCol = nTemp;
	}
	///If the tree just have one column.
	if(m_vsRowTagNames.GetSize() == 0)
		trNode = m_trNode.GetNode(m_vsColTagNames[nCol]);
	else
		///If the tree just have one row.
		if(m_vsColTagNames.GetSize() == 0)
			trNode = m_trNode.GetNode(m_vsRowTagNames[nRow]);
		else
		{
			TreeNode trFirstLevelNode;
			trFirstLevelNode = m_trNode.GetNode(m_vsColTagNames[nCol]);
			if(!trFirstLevelNode)
				return false;
			trNode	= trFirstLevelNode.GetNode(m_vsRowTagNames[nRow]);
		}
	if(!trNode)
		return false;
	trNode.strVal = lpcstr;
	return true;
}


void	TreeTable::formatingHeaderAndData(vector<int> &vnDisplayFormat, const vector<uint> &vuColWidths, uint uRowHeadingWidth, bool bLev1AsCols)
{
	///m_vsRowLables, m_vsColLables, m_vsTableCellValues
	vector<string> vsLableNames ;
	vsLableNames = m_vsColLables;
	
	int nMaxWidth = 0;
	uint nTemp;
	string	strTemp;
	for(int nIndex = 0 ; nIndex < vsLableNames.GetSize() ; nIndex++ )
	{
		if(!bLev1AsCols)
			strTemp = "Col" + nIndex;
		else
			strTemp = vsLableNames[nIndex];
		vsLableNames[nIndex] = str_pad_char(strTemp,vuColWidths[nIndex], vnDisplayFormat[0] );
	}
	m_vsColLables = vsLableNames;
	
	vsLableNames = m_vsRowLables;
	
	for(int nRowHeaderIndex = 0 ; nRowHeaderIndex < vsLableNames.GetSize() ; nRowHeaderIndex++ )
	{
		strTemp = vsLableNames[nRowHeaderIndex];
		vsLableNames[nRowHeaderIndex] = str_pad_char(strTemp,uRowHeadingWidth, vnDisplayFormat[1] );
	}
	m_vsRowLables = vsLableNames;
	
	vector<string>	vsDatas ;
	vector<string>	vsData;
	vsDatas = m_vsTableCellValues;
	
	int		nDataCols = GetNumCols();
	int		nDataRows = GetNumRows();
	vector<string>	vsTemp;
	for(int nDataColIndex =0 ; nDataColIndex < nDataCols; nDataColIndex++)
	{
		for(int nDataRowIndex = 0 ; nDataRowIndex < nDataRows; nDataRowIndex++ )
		{
			////I think pointer is better than other type.
			strTemp = getCell(nDataColIndex, nDataRowIndex);
			strTemp = str_pad_char(strTemp,vuColWidths[nDataColIndex], vnDisplayFormat[2] );
			setCell(nDataColIndex, nDataRowIndex, strTemp);
		}
	}
}

///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE
/*
void	TreeTable::convertColBaseToRowBase(vector<string> &vsColLables ,vector<string> &vsRowLables,vector<string> &vsTableCellValues)
{
	//Swap rows label and columns label.
	vector<string> vsColLablesTemp ;
	vsColLablesTemp = vsRowLables ;
	vsRowLables	= vsColLables;
	vsColLables = vsColLablesTemp;
	
	vector<string>	vecAllDataTemp;
	vecAllDataTemp = vsTableCellValues;
	string 	strTemp;
	///Reconstruct the data of tree. From col base to Row base.
	for(int	nDataRowIndex= 0; nDataRowIndex < GetNumRows(); nDataRowIndex++ )
	{
		for(int	nDataColIndex = 0 ; nDataColIndex <  GetNumCols();nDataColIndex++)
		{
			strTemp = vecAllDataTemp[ nDataRowIndex + nDataColIndex*GetNumRows() ];
			vsTableCellValues[ nDataColIndex + nDataRowIndex*GetNumCols() ] = strTemp;
		}
	}
}
*/
void	TreeTable::convertColBaseToRowBase(vector<string> &vsColLables ,vector<string> &vsRowLables,vector<string> &vsTableCellValues, vector<string> &vsRowSubHeaders, vector<string> &vsColSubHeaders)
{
	//Swap rows label and columns label.
	vector<string> vsSubHeaderTemp;
	_convertColBaseToRowBase(vsRowSubHeaders, vsRowLables.GetSize(),vsRowSubHeaders.GetSize()/vsRowLables.GetSize() );
	_convertColBaseToRowBase(vsColSubHeaders, vsColSubHeaders.GetSize()/vsColLables.GetSize(),vsColLables.GetSize() );
	vsSubHeaderTemp = vsRowSubHeaders;
	vsRowSubHeaders = vsColSubHeaders;
	vsColSubHeaders = vsSubHeaderTemp;
	
	vector<string> vsColLablesTemp ;
	vsColLablesTemp = vsRowLables ;
	vsRowLables	= vsColLables;
	vsColLables = vsColLablesTemp;

	_convertColBaseToRowBase(vsTableCellValues, GetNumRows(),GetNumCols() );

}
static bool _convertColBaseToRowBase(vector<string> &vs, int nRows, int nCols)
{
	if(vs.GetSize() <= 0 || vs.GetSize() != nRows*nCols)
		return false;
	
	vector<string>	vsTemp;
	vsTemp = vs;
	string 	strTemp;
	///Reconstruct the data of tree. From col base to Row base.
	for(int	nRowIndex= 0; nRowIndex < nRows; nRowIndex++ )
	{
		for(int	nColIndex = 0 ; nColIndex < nCols;nColIndex++)
		{
			strTemp = vsTemp[ nRowIndex + nColIndex*nRows ];
			vs[ nColIndex + nRowIndex*nCols ] = strTemp;
		}
	}	
	return true;
}
///-----End SUPPORT_MULTIPLE_SUBHEADER_TITLE
string	TreeTable::GetTable(int nExtraSpace , int nXoffset,bool bShowSubHeaders, bool bShowSeparator )
{
	
	if(!IsValid())
		return "";
	
	string	strTabelTitle;
	string	strXoffset;
	string	strExtraSpace;
	string	strSeparator;
	string	strTreeTable;
	int		nFirstTowTotalLength;
	vector<string>	vecAllDataTemp;
	
	///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE
	int nRowSubHeaderCounts= 0;
	int nIndexTemp ;
	//if(m_vsRowSubHeaders.GetSize()% m_vsRowLables.GetSize()==0)// Hong 8/14/06 FIX_0_CASE
	if((m_vsRowLables.GetSize() != 0) && (m_vsRowSubHeaders.GetSize()% m_vsRowLables.GetSize()==0))
		nRowSubHeaderCounts =  m_vsRowSubHeaders.GetSize()/m_vsRowLables.GetSize();
	///-----End SUPPORT_MULTIPLE_SUBHEADER_TITLE
	
	//Prepare	TableTitle string
   	int nRowHeaderIndex;
   	int nTableTitleLength = m_uRowHeadingWidth + nXoffset;
	//for(nRowHeaderIndex =0; nRowHeaderIndex < m_uRowHeadingWidth + nXoffset;nRowHeaderIndex++)
	//if(bShowSubHeaders && ( m_vsColSubHeaders.GetSize() > 0 || m_vsRowSubHeaders.GetSize() > 0))
	if(bShowSubHeaders &&  m_vsRowSubHeaders.GetSize() > 0)
		///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE
		 //nTableTitleLength = nTableTitleLength + m_uRowSubHeadingWidth + nXoffset ;
		 nTableTitleLength = nTableTitleLength + m_uRowSubHeadingWidth + nXoffset*nRowSubHeaderCounts ;
		///-----End SUPPORT_MULTIPLE_SUBHEADER_TITLE
	
	for(nRowHeaderIndex =0; nRowHeaderIndex < nTableTitleLength; nRowHeaderIndex++)//m_uRowHeadingWidth + nXoffset + m_uRowSubHeadingWidth;nRowHeaderIndex++)
		strTabelTitle += " ";

	strTreeTable +=strTabelTitle; 
	//Prepare offset of table
	for(nRowHeaderIndex =0; nRowHeaderIndex < nXoffset;nRowHeaderIndex++)
		strXoffset += " ";
	//Prepare Extra Space of columns
	for(nRowHeaderIndex =0; nRowHeaderIndex < nExtraSpace;nRowHeaderIndex++)
		strExtraSpace += " ";
	
	//prepare column title string
	int nIndex=0;
	for( ; nIndex < m_vsColLables.GetSize() ; nIndex++ )
	{
		strTreeTable =  strTreeTable + strExtraSpace + m_vsColLables[nIndex];
	}
	nFirstTowTotalLength = lstrlen(strTreeTable);
	
	string strColsubHeader;
	//bool	bRowSubHeaderExist = false;
	vector<string> vsRowTitle;
	vsRowTitle =  m_vsRowLables;
	
	if(bShowSubHeaders)
	{
		///-----Frank 10/26/05 SUPPORT_MULTIPLE_SUBHEADER_TITLE
		/*
		if(m_vsColSubHeaders.GetSize() > 0)
		{
			strColsubHeader = "\n" + strTabelTitle ;
			for(nIndex =0 ; nIndex < m_vsColSubHeaders.GetSize() ; nIndex++ )
			{
				strColsubHeader =  strColsubHeader + strExtraSpace + m_vsColSubHeaders[nIndex];
			}
		};
		if(m_vsRowSubHeaders.GetSize() > 0 && m_vsRowSubHeaders.GetSize() == m_vsRowLables.GetSize())
			//bRowSubHeaderExist = true;
			for(int nInRow = 0 ;nInRow <  m_vsRowLables.GetSize(); nInRow++)
				vsRowTitle[nInRow] = vsRowTitle[nInRow] + strXoffset + m_vsRowSubHeaders[nInRow];
		*/
		if(m_vsColSubHeaders.GetSize() > 0)
		{
			for(nIndex =0 ; nIndex < m_vsColSubHeaders.GetSize() ; nIndex++ )
			{
				if((nIndex)%m_vsColLables.GetSize() == 0)
					strColsubHeader = "\n" + strTabelTitle ;
					
				strColsubHeader =  strColsubHeader + strExtraSpace + m_vsColSubHeaders[nIndex];
			}
		};
		if(m_vsRowSubHeaders.GetSize() > 0)
		{
			for(int nInRow = 0 ;nInRow <  m_vsRowLables.GetSize(); nInRow++)
				for(int nSubInRow = 0 ;nSubInRow <  nRowSubHeaderCounts; nSubInRow++)
				{
					nIndexTemp = nInRow + nSubInRow*m_vsRowLables.GetSize();
					vsRowTitle[nInRow] = vsRowTitle[nInRow] + strXoffset + m_vsRowSubHeaders[nIndexTemp ];	///Frank 10/26/05 Support one sub header now
				}
		}
		///-----End SUPPORT_MULTIPLE_SUBHEADER_TITLE
		
		strTreeTable =  strTreeTable + strColsubHeader ;
	}
	
	///Frank 9/30/04 QA70-6903	MODIF_TREETABLE_TITLE_OUPUT	
	string strJudgeSpace = strTreeTable;
	if(strJudgeSpace.Remove(' ') > 0)
		if(strJudgeSpace.Compare("") == 0)
			bShowSeparator = false;
	///End	MODIF_TREETABLE_TITLE_OUPUT	
		
	//nFirstTowTotalLength = lstrlen(strTreeTable);
	strTreeTable +="\n";
	
	//prepare separator line with Xoffset space
	for( nRowHeaderIndex =0; nRowHeaderIndex < nFirstTowTotalLength - nXoffset ;nRowHeaderIndex++)
		strSeparator += '-';
	
	//Save separator to str Table
	if(bShowSeparator)
		//strTreeTable += strXoffset + strSeparator + "\r\n";
		strTreeTable = strXoffset + strSeparator + "\n"+ strTreeTable + strXoffset + strSeparator + "\n";
	///Frank 9/30/04 QA70-6903	MODIF_TREETABLE_TITLE_OUPUT	
	else
		strTreeTable = strXoffset + strSeparator + "\n";
	///End	MODIF_TREETABLE_TITLE_OUPUT	
		
	
	string	strTemp;
	int nRows = GetNumRows();
	
	for(int	nDataRowIndex= 0; nDataRowIndex < GetNumRows(); nDataRowIndex++ )
	{
		//strTreeTable = strTreeTable + strXoffset + m_vsRowLables[nDataRowIndex];
		strTreeTable = strTreeTable + strXoffset + vsRowTitle[nDataRowIndex];
		
		for(int	nDataColIndex = 0 ; nDataColIndex <  GetNumCols();nDataColIndex++)
		{
			strTemp = m_vsTableCellValues[nDataRowIndex + nDataColIndex*nRows];
			strTreeTable =  strTreeTable + strExtraSpace + strTemp;
		}
		
		strTreeTable += "\n"; 
	}
	
	return strTreeTable;
}
#endif _TREE_TABLE_H_

