/*------------------------------------------------------------------------------*
 * File Name:	TreeEditSplitter.h												*
 * Creation: 															*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * AW 03/16/05 v8.0205 CENTERLIZE_CODES_IN_FB									*
 *  DG 3/17/05 v8.0206 CLEAN_DOUBLE_STORAGE										*
 *	AW 03/17/05 v8.0206 CLEANING_CODES_IN_FO									*
 *  DG 3/21/05 v8.0207 REMOVE_DUPLICATE											*
 *  DG 3/23/05 v8.0209 FIX_LITTLE_PROBLEM										*
 *  DG 4/20/05 v8.0223 REWRITE_TREE_GET_NODE									*
 *	Jasmine 09/27/05 SPLITTER_INIT_SIZE_ON_READY								*
 *	Jasmine 12/16/05 QA70-8352 v8.0347 CREATE_POINTER							*
 *	Jasmine 12/05/05 QA70-8352 v8.0347 CHANGE_TO_TREE_GET_NODE					*
 *	Jasmine 12/13/05 QA70-8352 v8.0347 MOVE_TO_UPDATELISTPANEL					*
 *	Jasmine 12/16/05 QA70-8352 v8.0347 SET_CLASS_NAME_ATTRIB					*
 *------------------------------------------------------------------------------*/
#ifndef _TREE_EDIT_SPLITTER_H_
#define _TREE_EDIT_SPLITTER_H_

#include "SplitterControl.h"
// in order to use TreeEditControl in splitter pane, must derive splitter 
// window from TreeEditDlg
// since TreeEditDlg has its own base class, which can be a splitter or a regular dialog
// so the following macro must be defined
#define BASE_WINDOW SplitterControl
#include "TreeEditEvents.h"

#define RIGHT_PANE_ROW_COL 0,1
// this class supports a TreeEditControl in on main and another pane called
// the MainPane, which can be either a regular control (CreateMainPane) or
// an ActiveX control (CreateMainActiveXPane)
//
class TreeEditSplitter : public TreeEditDlg
{
public:
	TreeEditSplitter(bool bHorz = true, bool bTreeEditSecond = true)
	{
		m_bHorz = bHorz;
		m_bTreeEdit2ndCntrl = bTreeEditSecond;
	}
	void Init(int nCntrlID, WndContainer& wndParent, int nIndex, LPCSTR lpcszDlgName)
	{
		m_bReady = false;
		// control ID for panes
		// Must init these IDs before calls to InitMsgMap
		SetGridSize(getNumRows(), getNumCols()); // must call this before calls to GetDlgCtrlID
		m_ID1stPane = GetDlgCtrlID();
		m_ID2ndPane = GetDlgCtrlID(getCntrlRow(1), getCntrlCol(1));
		InitMsgMap();
		TreeEditDlg::Init(nCntrlID, wndParent, nIndex, lpcszDlgName);
	}

protected:
	//---- CPY 9/3/04
	BOOL CreateWindow(int nID, HWND hWnd)
	{
		Window wndParent(hWnd);
		/// TD 8-3-06 QA70-8843 DOWNCAST_BUG
		//Init(nID, wndParent, 0, NULL);
		//Dialog dlg;
		m_dlg = wndParent;
		Init(nID, m_dlg, 0, NULL);
		/// end DOWNCAST_BUG
		return TRUE;

	}
	//----
	
	///DG 6/13/05 GETN_GRAPH_DLG_NEEDED event handling
	virtual PEVENT_FUNC GetEventHandler()
	{
		return NULL;
	}
	void SetTreeEditPaneSize(int nSize, BOOL bPercent = TRUE)
	{
		int nIndex = m_bTreeEdit2ndCntrl ? 1 : 0;
		SetColSize(getCntrlCol(nIndex), nSize, bPercent);
	}
	int GetTreeEditPaneSize(BOOL bPercent = true)
	{
		int nSize=-1;
		int nIndex = m_bTreeEdit2ndCntrl ? 1 : 0;
		GetColSize(getCntrlCol(nIndex), nSize, bPercent);
		return nSize;
	}
	///end GETN_GRAPH_DLG_NEEDED
	//------------- CPY 9/2/05 GRAPH_TREE_SPLITTER_SAMPLE_CODE_CLEANUP
	void UpdateTreeEditPane()
	{
		m_treeEditCntrl.SetReady(false);
		m_treeEditCntrl.Update(m_paramTree, true, true);
		m_treeEditCntrl.SetReady(true);
	}
	//-------------
	// call this from ON_INIT
	BOOL CreateTreeEditPane()
	{
		GUID clsid;
		int nIndex = m_bTreeEdit2ndCntrl? 1:0;
		
		CreateActiveXPane(clsid, getCntrlRow(nIndex), getCntrlCol(nIndex));		
		
		PEVENT_FUNC pfn = GetEventHandler(); //NULL;// need to supply this for additional event handling
		/// AW 03/17/05 v8.0206 CLEANING_CODES_IN_FO 
		//ConstructTree();
		m_treeEditCntrl.Init(GetTreeEditPaneID(), false, true, pfn, *this);	///DG INIT_ONE_TIME : move out from ConstructWithoutTree
		//m_treeEditCntrl.Update(m_paramTree, true, true);
		ConstructWithoutTree();
		/// END CLEANING_CODES_IN_FO
		return TRUE;
	}
	// call this from ON_INIT for creating main pane as regular control
	BOOL CreateMainPane(Window &wnd)
	{
		int nIndex = m_bTreeEdit2ndCntrl? 0:1; 
		return CreatePane(wnd, getCntrlRow(nIndex), getCntrlCol(nIndex));
	}
	// call this from ON_INIT for creating main pane as ActiveX control
	BOOL CreateMainActiveXPane(GUID& clsid)
	{
		int nIndex = m_bTreeEdit2ndCntrl? 0:1; 
		return CreateActiveXPane(clsid, getCntrlRow(nIndex), getCntrlCol(nIndex));		
	}
	BOOL IsReady()	///Danice 11/12/04 : use to indicate init ready
	{
		return m_bReady;
	}
	BOOL SetReady()
	{
		m_bReady = true;
		return TreeEditDlg::SetReady(); // must call this in order for the splitter to show
	}
		
	BOOL OnCtrlResize(int nType, int cx, int cy)
	{
		OutInt("OnCtrlResize cx = ", cx);
		TreeEditDlg::OnResize(nType, cx, cy);
		return TRUE;
	}
	virtual BOOL InitMsgMap() { return FALSE; }
	virtual void ConstructTree()
	{
		_DBSTR("calling base class ConstructTree")
		GETN_TREE(trTemp)
		GETN_NUM(StartLevel, "Start Level", 0)
		GETN_SLIDER(SearchRange, "Search Range(%)", 20, "1|51|50")
		GETN_COMBO(SearchLevels, "Num. of Levels", 5, "2|5|10|15|20|25|30|40|50")
		GETN_CHECK(Consolidate, "Consolidate Related Contours", true)
		m_paramTree = trTemp;
	}
	void Update(bool bChkCellResize = false, bool bCheckComboChange = false, bool bCheckChanged = false)
	{
		m_treeEditCntrl.UpdateGridValues(bChkCellResize, bCheckComboChange, bCheckChanged);
	}
	int GetTreeEditPaneID() {return m_bTreeEdit2ndCntrl? m_ID2ndPane : m_ID1stPane;}
	int GetMainPaneID() {return m_bTreeEdit2ndCntrl? m_ID1stPane : m_ID2ndPane;}
	/// AW 03/17/05 v8.0206 CLEANING_CODES_IN_FO

public:
	
	BOOL LoadListSource( LPCSTR strFileName )
	{
		if ( TRUE == m_trFunctions.Load(strFileName) )
		{
			//m_trSplitter = m_trFunctions; ///DG 3/22/05 REMOVE_DUPLICATE
			SetListTree(m_trFunctions);
			return TRUE;
		}
		//ASSERT(FALSE);   //  false to open ListSourceFile, please add error string display here
		//return FALSE;
		return error_report("false to open list source file");
	}
	/// END  CLEANING_CODES_IN_FO
	//------------- CPY 9/2/05 GRAPH_TREE_SPLITTER_SAMPLE_CODE_CLEANUP
	TreeNode GetListTree()
	{
		TreeNode trTemp = m_trFunctions;
		
		return trTemp;
	}
	void UpdateListTree()
	{
		SetListTree(m_trFunctions);
	}
	//------------- end GRAPH_TREE_SPLITTER_SAMPLE_CODE_CLEANUP
	///DG 3/22/05 REMOVE_DUPLICATE
	bool SetListTree(TreeNode &tr)
	{
		if(!tr)
			return false;
		m_trSplitter=tr;
		return true;
	}
	///end REMOVE_DUPLICATE
private:
	int getCntrlRow(int nIndex = 0)
	{
		if(nIndex && !m_bHorz)
			return 1;
		return 0;
	}
	int getCntrlCol(int nIndex = 0)
	{
		if(nIndex && m_bHorz)
			return 1;
		return 0;
	}
	int getNumCols() {return m_bHorz? 2:1;}
	int getNumRows() {return m_bHorz? 1:2;}
	
protected:
	bool				m_bReady;
	int					m_ID1stPane;
	int					m_ID2ndPane;
	/// AW 03/17/05 v8.0206 CLEANING_CODES_IN_FO
	// move from derived class ListTreeEditSplitter
	TreeNode			m_trSel;	
	int 				m_nSelRow;	
	TreeNode			m_trSplitter;
	/// END CLEANING_CODES_IN_FO

private:
	bool				m_bHorz;
	bool				m_bTreeEdit2ndCntrl;
	Tree				m_trFunctions;//------------- CPY 9/2/05 GRAPH_TREE_SPLITTER_SAMPLE_CODE_CLEANUP, moved from public area
	/// TD 8-31-07 QA70-8843 DOWNCAST_BUG
	Dialog m_dlg;
	/// end DOWNCAST_BUG
};

///---DG 1/28/05
enum {
		BRANCH_INFO_NAME,
		BRANCH_INFO_COMMENT
};
///---end


#define STR_LASTUSE_REG_ITEM		"LastUse"	///DG 3/11/05

// Sample class to show usage of TreeEditSplitter calss
class ListTreeEditSplitter : public TreeEditSplitter
{
public:
	ListTreeEditSplitter() : TreeEditSplitter(true, true)
	{
		///DG 4/18/05 REWRITE_TREE_GET_NODE
		/*
		///DG REMOVE_DUPLICATE
		m_nNodeStopLevel=-1;
		m_strNodeStopAttrib="";
		m_bNodeStopAtLastBranch=false;
		///end REMOVE_DUPLICATE
		*/
		///end REWRITE_TREE_GET_NODE
	}
	void InitGridList(GridTreeControl* pList)
	{
		m_pList=pList;
	}
	void InitSelection()
	{
		//m_pList->SelRow(0);  /// Iris 3/02/06
		SelectRow(0);
	}
	
	/// Iris 3/02/06 If the selected row already be 0, SelRow(0) will not invoke OnRowChange to update the Tree
	void SelectRow(int nRow)
	{
		int nCurrentRow = m_pList->GetSelectedRow();
		if(nRow == nCurrentRow)
		{
			m_pList->SetReady(false);
			m_pList->SelRow(-1);
			m_pList->SetReady(true);
		}
		m_pList->SelRow(nRow); 
	}
	
	int GetSelectedRow(bool bInit = false)
	{
		int nRow = m_pList->GetSelectedRow();
		if(nRow < 0 && bInit)
			nRow = 0;
		return nRow;
	}
	/// ----
	
	//Related Item can be more, ',' to separate
	int MarkItemByActive(int nActiveDataID, string strRelatedAttrib="")
	{
		int nActiveRow=-1, nData;
		for(int ii=0; ii<m_pList->GetRows(); ii++)
		{
			string strRelatedDataIDList;
			vector<string> vsRelatedDataIDs;
			TreeNode trNode=GetTreeNode(ii);
			trNode.GetAttribute(strRelatedAttrib, strRelatedDataIDList);
			strRelatedDataIDList.GetTokens(vsRelatedDataIDs, ',');
			if(nActiveDataID == trNode.DataID)
			{
				nData=0;
				if( -1 == nActiveRow ) //return the first row found
					nActiveRow=ii;
			}
			else if(-1 != vsRelatedDataIDs.Find((string)nActiveDataID))
			{
				if(!trNode.GetAttribute(STR_DATA_ATTRIB, nData))
					nData=0;	//no set, default bold
			}
			else
				nData = -1;
			
			markRowByData(ii, nData);	//clear
		}
		return nActiveRow;
	}
	//bool ShowList(TreeNode& tr, DWORD dwCntrl = 0, LPCSTR lpcstrAttrib=NULL)
	//bool ShowList(TreeNode& tr, LPCSTR lpcstrAttrib=NULL, int nStopLevel = -1, bool bStopAtLastBranch = false, int nLevel=-1, int *pnFromRow=NULL)	///DG 4/20/05 REWRITE_TREE_GET_NODE
	bool ShowList(TreeNode& tr, DWORD dwCntrl=0, LPCSTR lpcszAttribute=NULL, int nLevel=-1, int *pnFromRow=NULL)
	{
		if(!tr)
			return false;
		m_treeEditCntrl.SetReady(false);
		m_pList->SetReady(false);
		m_pList->ClearAll();
		//m_trSplitter=tr;
		SetListTree(tr);
		if(m_trSplitter.GetNodeCount() > 0)
		{
			///DG 4/18/05 REWRITE_TREE_GET_NODE
			/*
			//record the control bit
			m_nNodeStopLevel=nStopLevel;
			m_strNodeStopAttrib=lpcstrAttrib;
			m_bNodeStopAtLastBranch=bStopAtLastBranch;
			AddTreeRows(m_trSplitter, nLevel, pnFromRow);
			*/
			m_strAttribute = lpcszAttribute;
			m_dwCntrl = dwCntrl;
			AddTreeRows(m_trSplitter, nLevel, pnFromRow);
			///end REWRITE_TREE_GET_NODE
		}
		m_pList->SetReady(true);
		return true;
	}
	bool AddTreeRows(TreeNode &tr, int nLevel=-1, int *pnFromRow=NULL)
	{
		bool bCollapseAll = true;
		//return m_pList->AddTreeNodes(tr, m_nNodeStopLevel, m_strNodeStopAttrib, bCollapseAll, m_bNodeStopAtLastBranch, nLevel,pnFromRow, 0);	///DG 4/18/05 REWRITE_TREE_GET_NODE
		return m_pList->AddTreeNodes(tr, m_dwCntrl, m_strAttribute, nLevel, pnFromRow, bCollapseAll);
	}
	
	void SetAllCollapsed()
	{
		///Frank 1/27/05  ALWAYS_NEED_SET_ALL_COLLAPSED_IN_INIT
		///move the code to base class GridControl
		/*
		int		nRow = m_pList->GetRows();
		vector<byte>	vecCollapsed(nRow);
		vecCollapsed = flexOutlineSubtotals;
		m_pList->SetCollapsed(vecCollapsed, false);
		*/
		m_pList->SetAllCollapsed();
		///End  ALWAYS_NEED_SET_ALL_COLLAPSED_IN_INIT
	}

	TreeNode ShowListContent(int nSelList=-1, bool bShowBranchSubTree=false)
	{
		if(-1 == nSelList)
			nSelList=GetSelList();
		m_trSel=GetTreeNode(nSelList);
		if(!m_trSel)
			return m_trSel;//false;
		m_treeEditCntrl.SetReady(false);
		int nLevel=m_pList->GetLevel(nSelList), nNextLevel=m_pList->GetLevel(nSelList+1); //, nPreviousLevel=m_pList->GetLevel(nSelList-1);
		//if(!bShowBranchSubTree && (nLevel<nNextLevel || nLevel<nPreviousLevel))	///DG 1/27/05 bug
		if(!bShowBranchSubTree && (nLevel<nNextLevel || m_trSel.GetNodeCount()<1))
		{
			string strName, strComment;
			if(!m_trSel.GetAttribute(STR_LABEL_ATTRIB, strName) || strName.IsEmpty())
				strName=m_trSel.tagName;
			m_trSel.GetAttribute(STR_COMMENT_ATTRIB, strComment);
			
			m_paramTree.Reset();
			GETN_USE(m_paramTree)
			GETN_STR(name, "Name", strName)
			GETN_STR(comment, "Comment", strComment) GETN_READ_ONLY ///DG 2/25/05 : set read only
			m_treeEditCntrl.Update(m_paramTree, true, true);
		}
		else	//display sub GetN Tree
		{
			m_treeEditCntrl.Update(m_trSel, true, true);
		}
		m_treeEditCntrl.SetReady();
		return m_trSel;
	}

	int GetSelList() { return m_pList->GetSelectedRow(); }
	int GetRowID(int nRow=-1)
	{
		TreeNode trRow;
		if(-1 == nRow)
			nRow=GetSelList();
		trRow = GetTreeNode(nRow);
		int nID=-1;
		if(trRow)
		{
			nID=trRow.DataID;
			//trRow.GetAttribute(STR_DATAID_ATTRIB, nID);
		}
		return nID;
	}
	///DG 3/22/05 REMOVE_DUPLICATE
	//TreeNode tree_get_node(int nRow)	///DG 3/11/05 : change name, as old name not good
	//TreeNode GetTreeNode(int nRow)	///DG 3/15/05 FB_SPEED_UP_LOADING_MECHANISM : separate list tree and shown tree
	//virtual TreeNode GetTreeNode(int nRow)
	//{
		/////DG REMOVE_DUPLICATE
		////int nStopLevel=-1;
		////if(0 != m_dwCntrl)
		////{
			////if(m_dwCntrl & ATRN_STOP_LEVEL)
				////nStopLevel=LOBYTE(m_dwCntrl);
		////}
		/////DG CLEAN_DOUBLE_STORAGE : Temp, as we may not use m_strStopAttrib
		/////*
		////bool bCheckStopAttrib=!m_strStopAttrib.IsEmpty();
		////return tree_get_node(m_trSplitter, nRow, nStopLevel, bCheckStopAttrib, m_strStopAttrib);
		////*/
		////LPCSTR lpcszSkipSubTreeAttrib;
		////if(!m_strStopAttrib.IsEmpty())
			////lpcszSkipSubTreeAttrib=m_strStopAttrib;
		////return tree_get_node(m_trSplitter, nRow, nStopLevel, lpcszSkipSubTreeAttrib);
		/////end CLEAN_DOUBLE_STORAGE
		//return tree_get_node(m_trSplitter, nRow, m_nNodeStopLevel, m_strNodeStopAttrib, m_bNodeStopAtLastBranch);
		/////end REMOVE_DUPLICATE
	//}
	///end REMOVE_DUPLICATE
	
	///DG 3/11/05 new added
	virtual void SaveDefaultSettings(char chDelimiter, LPCSTR lpcszDlgName=NULL)
	{
		string strRegItem(lpcszDlgName);
		strRegItem+=STR_LASTUSE_REG_ITEM;
		vector<string> vsRows;
		string strLastUseIndex;
		for(int nRow=GetSelList(); nRow>=0; nRow=m_pList->GetParent(nRow))
			vsRows.Add((string)nRow);
		strLastUseIndex.SetTokens(vsRows, chDelimiter);
		
		SaveSetting(strRegItem, strLastUseIndex, lpcszDlgName);
	}
	bool LoadDefaultSettings(vector<string> &vsLastUseItem, char chDelimiter, LPCSTR lpcszDlgName=NULL)
	{
		string strLastUse, strRegItem(lpcszDlgName);
		strRegItem+=STR_LASTUSE_REG_ITEM;
		if(!LoadSetting(strRegItem, strLastUse, lpcszDlgName))
			return false;
		return 0 < strLastUse.GetTokens(vsLastUseItem, chDelimiter);
	}
	///end

protected:
/*
EVENTS_BEGIN

	//------------- begin required events
	// the following events are required for the splitter and related controls
	ON_INIT(OnInitSplitter)
	ON_DESTROY(OnDestroy)
	ON_SIZE(OnCtrlResize)
	ON_GRID_ROW_COL_CHANGE(GetMainPaneID(), OnListRowChange)
	ON_GETNDLG_MSGS(GetTreeEditPaneID())
	//------------- end required events
	
EVENTS_END
*/
	virtual BOOL OnInitSplitter(GridTreeControl* pList=NULL)
	{
		GUID clsid; // defualt clsid will use vsFlexGrid, make sure you have the license to do development in vsFlexGridPro
		// the following creation order must follow 1st and 2nd pane
		// and must be consistent with the constructor argument bTreeEditSecond
		CreateMainActiveXPane(clsid);		
		CreateTreeEditPane(); // bTreeEditSecond = true, then put this as second creation
		
		m_pList=pList;
		m_pList->Init(GetMainPaneID(), *this);
		m_pList->SetSelection(flexSelectionByRow);
		return true;
	}
	
	/// AW 03/16/05 v8.0205 CENTERLIZE_CODES_IN_FB
	virtual BOOL OnInitSplitter(GridTreeControl* pList, LPCSTR strFileName)
	{
		OnInitSplitter(pList);
		//SetReady();	///DG 3/23/05 FIX_LITTLE_PROBLEM : should not setready here, set after finishing loading list
		if ( !LoadListSource(strFileName) )
			return FALSE;
		return true;
	}
	
	
						
	//virtual void UpdateList(LPCSTR lpcszStopAttribute = NULL, int nStopLevel = NOT_SET_STOP_LEVEL, bool bCollapseAll = TRUE)
	virtual void UpdateList(LPCSTR lpcszStopAttribute = NULL, int nStopLevel = NOT_SET_STOP_LEVEL, 
							bool bCollapseAll = TRUE, bool bStopAtLastBranch = false,int nLevel =-1,
							int nCols = 0, int *pnFromRow=NULL)
	{
		ASSERT(m_pList);
		///DG 3/22/05
		m_treeEditCntrl.SetReady(false);
		m_pList->SetReady(false);
		m_pList->ClearAll();
		///end

		///DG 4/18/05 REWRITE_TREE_GET_NODE : temp, wait for VC function, just for compilable
		/*
		m_strNodeStopAttrib=lpcszStopAttribute;
		m_nNodeStopLevel=nStopLevel;
		m_bNodeStopAtLastBranch=bStopAtLastBranch;
		m_pList->UpdateList(m_trSplitter, m_strNodeStopAttrib, m_nNodeStopLevel, bCollapseAll, 
							m_bNodeStopAtLastBranch, nLevel, nCols, pnFromRow);
		*/
		m_pList->UpdateList(m_trSplitter, lpcszStopAttribute, nStopLevel, bCollapseAll, 
							bStopAtLastBranch, nLevel, nCols, pnFromRow);
		///end REWRITE_TREE_GET_NODE
		
		if(m_trSplitter.GetNodeCount() < 1)
		{
			//ConstructTree();
			//m_treeEditCntrl.Update(m_paramTree, true, true);	//empty shown
			ConstructWithoutTree();	///DG 3/25/05
		}
		//SetAllCollapsed();	//this function takes more time to run, wait...
		m_pList->SetReady(true);	///DG 3/22/05
	}
	
	///DG 3/22/05 REMOVE_DUPLICATE
	/*
	//virtual
	//TreeNode GetTreeNode(int nStopLevel, int nRow, bool bCheckSkipSubTreeAttrib = false, LPCSTR lpcstrSkipSubTreeAttrib = NULL, int nCurrentLevel = 0, int* lpInc = NULL)	///DG CLEAN_DOUBLE_STORAGE
	TreeNode GetTreeNode(int nStopLevel, int nRow, LPCSTR lpcstrSkipSubTreeAttrib = NULL)
	{
		//return tree_get_node(m_trFunctions, nRow, nStopLevel, bCheckSkipSubTreeAttrib, lpcstrSkipSubTreeAttrib, nCurrentLevel, lpInc); ///DG CLEAN_DOUBLE_STORAGE
		return tree_get_node(m_trFunctions, nRow, nStopLevel, lpcstrSkipSubTreeAttrib);
	}
	*/
	virtual TreeNode GetTreeNode(int nRow, int nStopLevel=-1)
	{
		///DG 4/18/05 REWRITE_TREE_GET_NODE
		/*
		if(-1 == nStopLevel)
			nStopLevel=m_nNodeStopLevel;
		return tree_get_node(m_trSplitter, nRow, nStopLevel, m_strNodeStopAttrib, m_bNodeStopAtLastBranch);
		*/
		DWORD dwCntrl = m_dwCntrl;
		if(-1 != nStopLevel)
		{
			dwCntrl|=ATRN_STOP_LEVEL;
			dwCntrl|=nStopLevel;
		}
		return tree_get_node(m_trSplitter, nRow, dwCntrl, m_strAttribute);
		///end REWRITE_TREE_GET_NODE
	}
	///end REMOVE_DUPLICATE
	
	///DG 3/22/05 REMOVE_DUPLICATE : nLevel is not needed, the Row number is ordered by another level
	/*
	TreeNode ShowListContent(int nLevel=-1, int nSelList=-1, bool bShowBranchSubTree=false)
	{
		if(-1 == nSelList)
			nSelList=GetSelList();
		///DG 3/22/05 REMOVE_DUPLICATE
		//m_trSel=GetTreeNode(nLevel, nSelList);
		if(-1 == nLevel)
			nLevel=m_pList->GetLevel(nSelList);
		m_trSel=GetTreeNode(nSelList, -1);
		///end REMOVE_DUPLICATE
		if(!m_trSel)
			return m_trSel;//false;
		m_treeEditCntrl.SetReady(false);
		int nNextLevel=m_pList->GetLevel(nSelList+1); //, nPreviousLevel=m_pList->GetLevel(nSelList-1);
		//if(!bShowBranchSubTree && (nLevel<nNextLevel || nLevel<nPreviousLevel))	///DG 1/27/05 bug
		if(!bShowBranchSubTree && (nLevel<nNextLevel || m_trSel.GetNodeCount()<1))
		{
			string strName, strComment;
			if(!m_trSel.GetAttribute(STR_LABEL_ATTRIB, strName) || strName.IsEmpty())
				strName=m_trSel.tagName;
			m_trSel.GetAttribute(STR_COMMENT_ATTRIB, strComment);
			
			m_paramTree.Reset();
			GETN_USE(m_paramTree)
			GETN_STR(name, "Name", strName)
			GETN_STR(comment, "Comment", strComment) GETN_READ_ONLY ///DG 2/25/05 : set read only
			m_treeEditCntrl.Update(m_paramTree, true, true);
		}
		else	//display sub GetN Tree
		{
			m_treeEditCntrl.Update(m_trSel, true, true);
		}
		m_treeEditCntrl.SetReady();
		return m_trSel;
	}
	*/
	///end REMOVE_DUPLICATE
	
	void loadDefaultRow(char chDelimiter, LPCSTR lpcszDlgName=NULL)
	{
		vector<string> vsRows;
		//ASSERT(m_pList); ///DG FIX_LITTLE_PROBLEM : assert is slow
		if(!m_pList)
			ASSERT(0);
		if(!LoadDefaultSettings(vsRows, chDelimiter, lpcszDlgName))
		{
			m_pList->SelRow(0);
			return;
		}
		int nParentRow=-1, nSize=vsRows.GetSize(), nSelRow;
		for(int ii=nSize-1; ii>0; ii--)
		{
			nParentRow=atof(vsRows[ii]);
			if(0 > nParentRow)
				break;
			m_pList->SetCollapsed(nParentRow, flexOutlineExpanded);
		}
		nSelRow=atof(vsRows[0]);
		if(m_pList->GetParent(nSelRow) != nParentRow)
			nSelRow=nParentRow;
		m_pList->SelRow(nSelRow);
	}

	void ListRowChange(bool bShowBranchSubTree=false)
	{
		/// AW 03/16/05 v8.0205 CENTERLIZE_CODES_IN_FB
		//ASSERT(m_pList);	///DG FIX_LITTLE_PROBLEM : assert is slow
		if(!m_pList)
			ASSERT(0);
		if(!m_pList->IsReady())
			return ;
		
		int nNewSelRow=GetSelList();
		//int nLevel = m_pList->GetLevel(nNewSelRow); ///DG 3/22/05 REMOVE_DUPLICATE
		if(m_nSelRow != nNewSelRow)
		{
			m_nSelRow=nNewSelRow;
			//m_trSel=ShowListContent(nLevel, m_nSelRow, bShowBranchSubTree); ///DG 3/22/05 REMOVE_DUPLICATE
			m_trSel=ShowListContent(m_nSelRow, bShowBranchSubTree);
		}
		/// END CENTERLIZE_CODES_IN_FB
	}
	
	/// END CENTERLIZE_CODES_IN_FB
	
	/// AW 03/17/05 v8.0206 CLEANING_CODES_IN_FO 
	/*
	//virtual
	void ConstructTree()
	{
		///DG 3/15/05 : this no need, change to welcome message
		/*
		GETN_TREE(trTemp)
		GETN_NUM(StartLevel, "Start Level", 0)
		GETN_SLIDER(SearchRange, "Search Range(%)", 20, "1|51|50")
		GETN_COMBO(SearchLevels, "Num. of Levels", 5, "2|5|10|15|20|25|30|40|50")
		GETN_BEGIN_BRANCH(Limits, "Basic Limits, 0=ignore")
			GETN_SLIDER(minPts, "Min Coutour Pts", 30, "0|120|60")
			GETN_SLIDER(maxPts, "Max Coutour Pts", 0, "0|600|60")
			GETN_SLIDER(minArea, "Min Area", 0, "0|5000|200")
			GETN_SLIDER(maxArea, "Max Area", 0, "0|1000|200")
			GETN_SLIDER(minRoundness, "Min Roundness", 0.3, "0.0|1|50")
			GETN_SLIDER(maxRoundness, "Max Roundness", 1,   "0.5|1.2|50")
		GETN_END_BRANCH(Limits)
		GETN_CHECK(Consolidate, "Consolidate Related Contours", true)
		m_paramTree = trTemp;
		*/
/*		GETN_TREE(trTemp)
		GETN_STR(empty, "", "") GETN_READ_ONLY
		m_paramTree=trTemp;
		///end
	}
	*/
	/// END CLEANING_CODES_IN_FO 

protected:
	int ShowTreeCollapsedSymbol(bool bShow=true)
	{
		int nMode= bShow ? flexOutlineBarSimpleLeaf : flexOutlineBarNone;
		return m_treeEditCntrl.SetOutlineBar(nMode);
	}
private:
	void markRowByData(int nRow, int nData=-1)
	{
		bool bBold = 0 == nData ? true : false;
		uint nColor = nData > 0 ? nData : 0;
		
		m_pList->SetBold(nRow, LABEL_COL_INDEX, bBold);
		m_pList->SetCellColor(nRow, LABEL_COL_INDEX, nColor);
	}
/// AW 03/17/05 v8.0206 CLEANING_CODES_IN_FO
// move to base class
//protected:
//	TreeNode			m_trSel;	//DG 3/16/05 move from private
//	int 				m_nSelRow;	//DG 3/17/05 
/// END CLEANING_CODES_IN_FO
	
private:
	GridTreeControl*	m_pList;
	/// AW 03/17/05 v8.0206 CLEANING_CODES_IN_FO
	//TreeNode			m_trSplitter;
	/// AW 03/16/05 v8.0205 CENTERLIZE_CODES_IN_FB
	// Tree				m_trFunctions;  // move to base class
	/// END CLEANING_CODES_IN_FO
	//int 				m_nSelRow;		///DG 3/17/05 protected member
	/// END CENTERLIZE_CODES_IN_FB
	
	///DG 4/18/05 REWRITE_TREE_GET_NODE
	/*
	int					m_nNodeStopLevel;
	string				m_strNodeStopAttrib;
	bool				m_bNodeStopAtLastBranch;
	*/
	DWORD				m_dwCntrl;
	string				m_strAttribute;
	///end REWRITE_TREE_GET_NODE
};

#define TREE_LIST_SPLITTER_TREE_PANEL		0,0
#define TREE_LIST_SPLITTER_LIST_PANEL		0,1

#define NUM_DEFAULT_COL_COUNT				10
#define NUM_DEFAULT_ROW_COUNT				10

#define WM_USER_UPDATE_DATA_VIEW			(WM_USER +1050)

class TreeListEditSplitter: public SplitterControl
{
public:
	TreeListEditSplitter()
	{
		m_bReady = false;
		
		// control ID for panes
		// Must init these IDs before calls to InitMsgMap
		SetGridSize(1,2);
		m_nIDTree = GetDlgCtrlID(TREE_LIST_SPLITTER_TREE_PANEL);
		m_nIDList = GetDlgCtrlID(TREE_LIST_SPLITTER_LIST_PANEL);
		m_pTree = NULL;
		m_pList = NULL;
		
		InitMsgMap();
		
		m_bReady = true;
	}
	~TreeListEditSplitter()
	{
	}

	/// Iris 11/28/05 INIT_GRID_LIST
	//void InitGridList(GridListControl* pList)
	bool InitGridList(GridListControl* pList)
	{
		if(!pList)
			return false;
		m_pList=pList;
		return true;
	}
	void InitSelection()
	{
		m_pList->SelRow(0);
	}
	///End INIT_GRID_LIST

	void Init(int nID, Dialog& dlg, LPCSTR lpcszDlgName)
	{
		///Jasmine 12/16/05 CREATE_POINTER
		if(!m_pTree)
			m_pTree = new GridTreeControl;
		if(!m_pList)
			m_pList = new GridListControl;
		if(m_strGridListClass.IsEmpty())///Jasmine 12/16/05 SET_CLASS_NAME_ATTRIB
			m_strGridListClass = "GridListControl";
		///End CREATE_POINTER
		m_strDlgName = lpcszDlgName;
		SplitterControl::Init(nID, dlg, 1, lpcszDlgName);// 1 = 2nd splitter in dialog
		
		if( !m_bReady )
			return;
		
		InitTreePanel();
		InitListPanel();
	}
	///Jasmine 09/27/05 SPLITTER_INIT_SIZE_ON_READY
	void OnReady()
	{
		SplitterControl::OnReady();
	}
	///End SPLITTER_INIT_SIZE_ON_READY
protected:
EVENTS_BEGIN
	ON_INIT(OnInitDialog)
	ON_DESTROY(OnDestroy)
	ON_SIZE(OnCtrlResize)
	//ON_GRID_SEL_CHANGE(m_nIDTree, OnSelectTreeNode)	///Jasmine 12/16/05 in tree panel no need to respond to selection changes 
	ON_GRID_ROW_COL_CHANGE(m_nIDTree, OnSelectTreeNode)	///to support single selete is ok
	ON_USER_MSG(WM_USER_UPDATE_DATA_VIEW, OnUpdateDataView)

EVENTS_END

	BOOL OnInitDialog()
	{
		m_bReady = false;
		
		GUID clsid; // later, for now, only vsFlex		
		CreateActiveXPane(clsid, TREE_LIST_SPLITTER_TREE_PANEL);		
		m_pTree->Init(m_nIDTree, *this);
		
		CreateActiveXPane(clsid, TREE_LIST_SPLITTER_LIST_PANEL);
		m_pList->Init(m_nIDList, *this);	
		//m_strGridListClass = "GridListControl";///Jasmine 12/16/05 SET_CLASS_NAME_ATTRIB
		
		SetReady();
		m_bReady = true;
		return TRUE;
	}
	
	BOOL OnCtrlResize(int nType, int cx, int cy)
	{
		SplitterControl::OnResize(nType, cx, cy);
		
		m_pList->ResizeCols();
		
		return TRUE;
	}
	
	virtual void InitTreePanel()
	{
		m_pTree->SetAllowSelection(false);	///If false , support single selete; else multi seletion
		//m_pTree->SetSelection( flexSelectionListBox );
	}
	
	virtual void InitListPanel()
	{
		//m_pList->SetGridLines(flexGridInset);		
		m_pList->SetExplorerBar(flexExSortShow);
		m_pList->SetAllowSelection(true);	///If false , support single selete; else multi seletion
		//m_pList->SetSelection( flexSelectionListBox );
		//m_pList->SetEditable( );
		//m_pList->SetupRowsCols(1, 1, 1, 1);
	}
	
	virtual BOOL OnSelectTreeNode(Control cntrl)
	{
		///Jasmine 12/05/05 CHANGE_TO_TREE_GET_NODE , compile OK, release comment
		//--- CPY 12/3/05 the following cannot compile
		  
		if(!m_bReady)
			return FALSE;
		int nSelRow = m_pTree->GetSelectedRow();
		if(nSelRow < 0)
			return FALSE;
		//TreeNode trNode = getFolderTree(nSelRow);	///Jasmine 12/05/05 CHANGE_TO_TREE_GET_NODE
		TreeNode trNode = tree_get_node(m_tree, nSelRow);
		///Jasmine 12/13/05 MOVE_TO_UPDATELISTPANEL
		/*
		string strClass;
		trNode.GetAttribute(STR_CLASS_NAME_ATTRIB, strClass);
		if(!strClass.IsEmpty() && (strClass.CompareNoCase(m_strGridListClass) == 0))
		{
			CreateGridList(strClass);
			UpdateListPanel(trNode);
			m_strGridListClass = strClass;
		}
		return FALSE;
		*/
		return UpdateListPanel(trNode);
		///End MOVE_TO_UPDATELISTPANEL
		//return false;
		//----
		///End CHANGE_TO_TREE_GET_NODE
	}
	virtual BOOL CreateGridList(string strGridList)
	{
		if(strGridList.IsEmpty())
			return FALSE;
		GridListControl& newGridList = (GridListControl&) Project.FindClass(strGridList);
		if(newGridList == NULL)
			return FALSE;
		return InitGridList(&newGridList);
	}
	virtual BOOL UpdateListPanel(TreeNode trNode)
	{
		///Jasmine 12/13/05 MOVE_TO_UPDATELISTPANEL
		string strClass;
		trNode.GetAttribute(STR_CLASS_NAME_ATTRIB, strClass);
		if(!strClass.IsEmpty() && (strClass.CompareNoCase(m_strGridListClass) == 0))
			CreateGridList(strClass);
		m_strGridListClass = strClass;
		//...
		return TRUE;
		///End MOVE_TO_UPDATELISTPANEL
	}	
	virtual BOOL OnUpdateDataView(uint wParam, uint lParam)
	{
		return FALSE;		
	}	
	
public:	
	void SetTree(TreeNode tr)
	{
		if( !tr )
			return;
		bool flag = m_tree.AddNode(tr, TRUE);
		int nAddRow = m_pTree->GetRows();
		m_pTree->AddTreeNodes(tr, 0, NULL, 1, NULL, true, 0);
		m_pTree->SetCollapsed(nAddRow,flexOutlineCollapsed);
	}
	void SetList(string strName, vector<string> vs)
	{
		addColumn(strName, vs, m_pList->GetCols());
		SetColAlignments();
	}
	void CleanDataList(bool bCleanTree = true, bool bCleanList = true)
	{
		if(bCleanTree)
		{
			m_pTree->ClearAll();
			m_tree.Reset();
		}
		if(bCleanList)
		{
			m_pList->SetCols(0, true);
			m_pList->SetRows(0, true);
		}
		m_treeShow.Reset();
	}

	void AddToShowTree(TreeNode tr)
	{
		if(!tr || !tr.GetNodeCount())
			return;
		if(tr.FirstNode.GetNodeCount() > 0)
		{
			foreach(TreeNode cNode in tr.Children)
				AddToShowTree(cNode);
		}
		else
			bool flag = m_treeShow.AddNode(tr, TRUE);
	}
	void ShowTree()
	{
		if(!m_treeShow || m_treeShow.IsEmpty())
			return;
		
		vector<int> vnTableDisplayFormat = { DISPLAY_CENTER, DISPLAY_RIGHT, DISPLAY_RIGHT};
		TreeTable tTable(m_treeShow, vnTableDisplayFormat, true, false);
		//showToGridList(tTable);		
	}
	void SetColAlignments()
	{
		m_pList->SetFixedColAlignment(-1, flexAlignCenterCenter);
		m_pList->SetColAlignment(-1, flexAlignRightCenter);//flexAlignGeneral);
		m_pList->ResizeCols();
	}
private:
	void showToGridList(TreeTable trTable)
	{
		if(!trTable.IsValid())
			return;
		
		int nFixedRows = m_pList->GetRowOffset();	
		int nRows=trTable.GetNumRows(), nCols=trTable.GetNumCols();
		
		if(m_pList->GetRows() - nFixedRows < nCols)
			m_pList->SetRows(nCols);			
		
		string strVal;
		for(int ii=-1; ii< nCols; ii++)
		{ 
			for(int jj=-1; jj<nRows; jj++)
			{
				strVal=trTable.GetCell(ii, jj);
				if(-1 == ii)
				{
					m_pList->SetColHeading(jj, strVal);
					m_pList->AddCol();
				}
				if(-1 == jj)
					m_pList->SetRowHeading(ii, strVal);
				m_pList->SetCell(ii+1, jj+1, strVal);
			}
		}
		m_pList->SetCols(nRows, true);
		m_pList->SetRows(nCols, true);
		SetColAlignments();
	}
	
	//update data view according to the selection in tree view or in the top panel
	/*
	void showTreeData(TreeNode tr)//need some change
	{
		if(!tr)
			return;
	
		if(tr.GetNodeCount() > 0) // branch node
		{
			foreach(TreeNode cNode in tr.Children)
				showTreeData(cNode);
		}
		else // leaf node
		{
			vector<string> vs;
			string strLabel;
			if(!tr.GetAttribute(STR_LABEL_ATTRIB, strLabel))
				strLabel = tr.tagName;
			
			if(TNVAL_TYPE_BIT_VECTOR <= tr.TypeID && TNVAL_TYPE_VARIANT_VECTOR >= tr.TypeID)
				vs = tr.strVals;
			else
				vs.Add(tr.Text);
			
			addColumn(strLabel, vs, m_pList->GetCols());
		}
	}
	
	void getPosition(TreeNode tr, int& nRow, int& nCol)
	{
		if(!tr)
			return;
		TreeNode trP = tr.Parent();
		if(!trP)
			return;
		string strRow = tr.tagName, strCol = trP.tagName;
		if(!strCol.CompareNoCase("OriginStorage"))
			trP.GetAttribute(STR_LABEL_ATTRIB, strCol);
		string str;
		for(nRow = 1; nRow < m_pList->GetRows(); nRow++)
		{
			str = m_pList->GetCell(nRow, 0);
			str.TrimRight();
			str.TrimLeft();
			if(!strCol.CompareNoCase(str))
				break;
		}
		for(nCol = 1; nCol < m_pList->GetCols(); nCol++)
		{
			str = m_pList->GetCell(0, nCol);
			str.TrimRight();
			str.TrimLeft();
			if(!strRow.CompareNoCase(str))
				break;
		}
	}
	

	bool addColumn(string strName, const vectorbase& vsList, int nCol = 0)
	{
		int nFixedRows = m_pList->GetRowOffset();
		int nSize = vsList.GetSize();
		if(nCol < 0 || nSize == 0)
			return false;
		
		m_pList->AddCol();
		m_pList->SetColHeading(nCol-1, strName);
		if(m_pList->GetRows() - nFixedRows < nSize)
			m_pList->SetRows(nSize);
		
		for(int ii = 0; ii < nSize; ii++)
			m_pList->SetCell(nFixedRows + ii, nCol, vsList[ii]);
		
		return true;	
	}
	*/
	
	bool addColumn(string strName, const vector<string>& vsList, int nCol = 0)
	{
		int nFixedRows = m_pList->GetRowOffset();
		int nSize = vsList.GetSize();
		if(nCol < 0 || nSize == 0)
			return false;
		
		m_pList->AddCol();
		m_pList->SetColHeading(nCol-1, strName);
		if(m_pList->GetRows() - nFixedRows < nSize)
			m_pList->SetRows(nSize);
		
		for(int ii = 0; ii < nSize; ii++)
			m_pList->SetCell(nFixedRows + ii, nCol, vsList[ii]);
		
		return true;
	}	
private:	
	Tree						m_treeShow;	
	
	string						m_strDlgName;
protected:
	GridTreeControl* 		 	m_pTree;
	GridListControl* 		 	m_pList;
	int							m_nIDTree;
	int							m_nIDList;
	
	Tree						m_tree;
	bool						m_bReady;
	
	string						m_strGridListClass;
};

#endif //_TREE_EDIT_SPLITTER_H_
