/*------------------------------------------------------------------------------*
 * File Name: DynaSplitter.h 													*
 * Creation: ML 2/21/2006														*
 * Purpose: A General GetN dialog with a Graph Preview tab						*
 * Copyright (c) OriginLab Corp.	2006, 2007, 2008, 2009, 2010, 2011			*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	Cheney 2006-9-22 MOVE_BRANCH_LOADING_AND_SAVING_FROM_DYNABOX_TO_DYNADLG		*
 *	Jasmine 11/01/06 NOT_ALLOW_RENAME_TEMP										*
 *	Joseph 06/07/07 v8.0635 NLF_DIFF_EVENT_SHOULD_USE_DIFF_TREE					*
 *	Sim 10-09-2008 QA80-12345 ADD_STAR_INDICATE_THEME_VALUE_CHANGE				*
 * Kenny 04/09/2009 QA80-13422 COUNT_APPEAR_TIMES_OF_ERR_MSG					*
 *------------------------------------------------------------------------------*/
 
#ifndef	__DYNASPLITTER_H_
#define	__DYNASPLITTER_H_
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////


#define RIGHT_PANE_ROW_COL 0,1

#define BASE_WINDOW	SplitterControl
#include	"DynaDlg.h"
#define STR_LASTUSE_REG_ITEM		"LastUse"
//////////////////////////////////////////////////////////////////////////////
// class DynaSplitter
// this class supports a DynaControl in on main and another pane called
// the MainPane, which can be either a regular control (CreateMainPane) or
// an ActiveX control (CreateMainActiveXPane)
//////////////////////////////////////////////////////////////////////////////
class DynaSplitter : public DynaDlg
{
public:
	DynaSplitter(bool bHorz = true, bool bTreeEditSecond = true)
	{
		m_bHorz = bHorz;
		m_bTreeEdit2ndCntrl = bTreeEditSecond;
		m_dwErrMsgBlinkCtrl = COLORTEXTBLINK_DEFAULT;	///Kenny 04/09/2009 QA80-13422 COUNT_APPEAR_TIMES_OF_ERR_MSG
	}
	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));

		///Kenny 04/09/2009 QA80-13422 COUNT_APPEAR_TIMES_OF_ERR_MSG
		SetContainerTitle(lpcszDlgName);
		CheckInitErrMsgBox(wndParent, COLOR_RED, COLOR_BLACK, m_dwErrMsgBlinkCtrl);
		///End QA80-13422 COUNT_APPEAR_TIMES_OF_ERR_MSG

		InitMsgMap();
		//TreeEditDlg::Init(nCntrlID, wndParent, nIndex, lpcszDlgName);
		DynaDlg::Init(nCntrlID, wndParent, nIndex, lpcszDlgName);
		///Cheney 2006-9-22 MOVE_BRANCH_LOADING_AND_SAVING_FROM_DYNABOX_TO_DYNADLG
		LoadBranchSetting(lpcszDlgName);
		///end MOVE_BRANCH_LOADING_AND_SAVING_FROM_DYNABOX_TO_DYNADLG
	}
	///Joseph 01/31/07 QA70-9327 DDK_SAVING_OF_OCDDK_DIALOG_PLACEMENTS
	void SetTreeEditPaneSize(int nSize, BOOL bPercent = TRUE)
	{
		int nIndex = m_bTreeEdit2ndCntrl ? 1 : 0;
		SetColSize(getCntrlCol(nIndex), nSize, bPercent);
	}
	///End DDK_SAVING_OF_OCDDK_DIALOG_PLACEMENTS
	
	///---Sim 10-09-2008 QA80-12345 ADD_STAR_INDICATE_THEME_VALUE_CHANGE
	void SPLInitThemeControls(ResizeDialog* pdlg, TreeNode& tr, int nIDThemeCombo, int nIDThemeLabel, int nIDThemeSave, int nIDThemeSaveAs, int nIDThemeEdit=0, int nIDThemeEditLabel=0)
	{
		InitThemeControls(pdlg, tr, nIDThemeCombo, nIDThemeLabel, nIDThemeSave, nIDThemeSaveAs, nIDThemeEdit, nIDThemeEditLabel);
	}
	string SPLGetCurThemeName()
	{
		return m_vsThemes[m_comboTheme.GetCurSel()];
	}
	void SPLUpdateThemeUnSaveSign(bool bModified = false)
	{
		UpdateThemeCommbo(m_vsThemes, bModified);
	}
	///---END QA80-12345 ADD_STAR_INDICATE_THEME_VALUE_CHANGE
	
protected:
	//---- CPY 9/3/04
	BOOL CreateWindow(int nID, HWND hWnd)
	{
		Window wndParent(hWnd);
		/// TD 8-3-06 QA70-8843 DOWNCAST_BUG
		//WndContainer wcParent;
		m_wcParent = wndParent;
		/// end DOWNCAST_BUG
		Init(nID, m_wcParent, 0, NULL);
		return TRUE;

	}
	//----
	
	///DG 6/13/05 GETN_GRAPH_DLG_NEEDED event handling
	virtual PEVENT_FUNC GetEventHandler()
	{
		return NULL;
	}
	
	///Joseph 01/31/07 QA70-9327 DDK_SAVING_OF_OCDDK_DIALOG_PLACEMENTS
	//void SetTreeEditPaneSize(int nSize, BOOL bPercent = TRUE)
	//{
		//int nIndex = m_bTreeEdit2ndCntrl ? 1 : 0;
		//SetColSize(getCntrlCol(nIndex), nSize, bPercent);
	//}
	///End DDK_SAVING_OF_OCDDK_DIALOG_PLACEMENTS
	
	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(bool bInit = false, bool bCallNodesHandlers = false)
	{
		//m_treeEditCntrl.SetReady(false);
		//m_treeEditCntrl.Update(m_paramTree, true, true);
		//m_treeEditCntrl.SetReady(true);
		UpdateDynaControl(true, bInit?GETNEVENT_ON_INIT:0, bCallNodesHandlers);
	}
	//-------------
	// call this from ON_INIT
	BOOL CreateTreeEditPane()
	{
		GUID clsid;
		int nIndex = m_bTreeEdit2ndCntrl? 1:0;
		CreatePane(m_DynaCntrl, getCntrlRow(nIndex), getCntrlCol(nIndex));		
		PEVENT_FUNC pfn = GetEventHandler(); //NULL;// need to supply this for additional event handling
		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));
	}
	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(bool bSet = true)
	{
		m_bReady = bSet;
		return DynaDlg::SetReady(bSet); // must call this in order for the splitter to show
	}
		
	BOOL OnCtrlResize(int nType, int cx, int cy)
	{
		//TreeEditDlg::OnResize(nType, cx, cy);
		DynaDlg::OnResize(nType, cx, cy);
		return TRUE;
	}
	virtual BOOL InitMsgMap() { return FALSE; }
	virtual void ConstructTree()
	{
		out_str("calling base class ConstructTree")
	}
	// ML 2/16/2006: I can't see that this function is used anywhere.
	/*
	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:

	///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
	WndContainer m_wcParent;
	/// end DOWNCAST_BUG
};


// Tree of List (vsFlex) on one side and DynaControl on another
class TreeDynaSplitter : public DynaSplitter
{
public:
	TreeDynaSplitter() : DynaSplitter(true, true)
	{
	}
	void InitGridList(GridTreeControl* pList)
	{
		m_pList=pList;
	}
	void InitSelection()
	{
		SelectRow(0);
	}
	bool SetListTree(TreeNode &tr)
	{
		if(!tr)
			return false;
		m_trSplitter=tr;
		return true;
	}
private:
	TreeNode 			m_trSplitter;
protected: //CPY 5/29/06 CHANGE_FO_TO_USE_NEW_DYNA_CTRL
	int 				m_nSelRow;
	TreeNode			m_trSel;	
public:
	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;
	}
	/// ----
	
	//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 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()
	{
		m_pList->SetAllCollapsed();
	}
	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/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);
	}

protected:
	virtual BOOL OnInitSplitter(GridTreeControl* pList=NULL)
	{
		SetGrayBackground();
		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;
	}
		
						
	//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

		m_pList->UpdateList(m_trSplitter, lpcszStopAttribute, nStopLevel, bCollapseAll, 
							bStopAtLastBranch, nLevel, nCols, pnFromRow);
		
		if(m_trSplitter.GetNodeCount() < 1)
		{
			ConstructWithoutTree();	///DG 3/25/05
		}
		m_pList->SetReady(true);	///DG 3/22/05
	}
	
	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);
	}
private:
	GridTreeControl*	m_pList;
	DWORD				m_dwCntrl;
	string				m_strAttribute;
protected:
	virtual TreeNode GetTreeNode(int nRow, int nStopLevel=-1)
	{
		DWORD dwCntrl = m_dwCntrl;
		if(-1 != nStopLevel)
		{
			dwCntrl|=ATRN_STOP_LEVEL;
			dwCntrl|=nStopLevel;
		}
		return tree_get_node(m_trSplitter, nRow, dwCntrl, m_strAttribute);
	}	
	
	///Joseph 06/07/07 v8.0635 NLF_DIFF_EVENT_SHOULD_USE_DIFF_TREE
	//on dialog init, then Call funciton UpdateDynaControl, invoke GENE_ON_INIT event
	//if we just need to update gui, should not invoke GENE_ON_INIT event.
	//then we use the GETNEVENT_ON_CHANGE_UPDATE_GUI bit to update GUI.
	//TreeNode ShowListContent(int nSelList=-1, bool bShowBranchSubTree=false)
	TreeNode ShowListContent(int nSelList=-1, bool bShowBranchSubTree=false, bool bIsInitEvent = true)
	///End NLF_DIFF_EVENT_SHOULD_USE_DIFF_TREE
	{
		if(-1 == nSelList)
			nSelList=GetSelList();
		m_trSel=GetTreeNode(nSelList);
		if(!m_trSel)
			return m_trSel;//false;
		int nLevel=m_pList->GetLevel(nSelList), nNextLevel=m_pList->GetLevel(nSelList+1); //, nPreviousLevel=m_pList->GetLevel(nSelList-1);
		
		///Joseph 06/07/07 v8.0635 NLF_DIFF_EVENT_SHOULD_USE_DIFF_TREE
		UINT nEventID;
		if(bIsInitEvent)
			nEventID = GETNEVENT_ON_INIT;
		else
			nEventID = GETNEVENT_ON_CHANGE_UPDATE_GUI;
		///End NLF_DIFF_EVENT_SHOULD_USE_DIFF_TREE
		
		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)
			///Jasmine 11/01/06 NOT_ALLOW_RENAME_TEMP
			//GETN_STR(name, "Name", strName) 
			//GETN_STR(comment, "Comment", strComment) GETN_READ_ONLY ///DG 2/25/05 : set read only
			GETN_STR(name, _L("Name"), strName) GETN_READ_ONLY_COLOR
			GETN_STR(comment, _L("Comment"), strComment) GETN_READ_ONLY_COLOR
			m_paramTree.comment.Show = false;
			SetbUseInputTree();//Hong 8/01/06
			
			///Joseph 06/07/07 v8.0635 NLF_DIFF_EVENT_SHOULD_USE_DIFF_TREE
			//UpdateDynaControl(true, GETNEVENT_ON_INIT, true, 0, false);//show not only the first node
			UpdateDynaControl(true, nEventID, true, 0, false);
			///End NLF_DIFF_EVENT_SHOULD_USE_DIFF_TREE
			
			return m_trSel;
			///End NOT_ALLOW_RENAME_TEMP
		}
		else
		{
			SetInputTree(m_trSel, false);
		}
		
		///Joseph 06/07/07 v8.0635 NLF_DIFF_EVENT_SHOULD_USE_DIFF_TREE
		//UpdateDynaControl(true, GETNEVENT_ON_INIT, true);
		UpdateDynaControl(true, nEventID, true);
		///End NLF_DIFF_EVENT_SHOULD_USE_DIFF_TREE
		
		return m_trSel;
	}	
	void ListRowChange(bool bShowBranchSubTree=false)
	{
		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
	}
	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)
		{
			m_strAttribute = lpcszAttribute;
			m_dwCntrl = dwCntrl;
			AddTreeRows(m_trSplitter, nLevel, pnFromRow);
			///end REWRITE_TREE_GET_NODE
		}
		m_pList->SetReady(true);
		return true;
	}

/*
	//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;
	}

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);
	}
*/

};





//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
#endif		// __DYNASPLITTER_H_

 
