/*------------------------------------------------------------------------------*
 * File Name:Splitter Control													*
 * Creation: CPY Feb 23 2004													*
 * Purpose: OriginC Source C file												*
 * Copyright (c) Originlab Corp., 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * Danice 9/11/04 v8.0132 LOAD_SETTING_FOR_STATIC_DIALOG						*
 *	Frank 11/10/04 v8.0160 QA70-6086   REMEMBER_LAST_USE_FUNCTION				*
 * DG 3/2/05 v8.0198 REMEMBER_COL_SIZE_NOT_BY_PERCENT							*
 * DG 4/6/05 v8.0217 COL_SIZE_BY_PERCENT										*
 *	CPY 9/22/05 SPLITTER_INIT_SIZE_ON_READY										*
 *	CPY 3/25/06 SPLITTER_INIT_SIZE_NOT_CALL										*
 *	Cheney 2006-9-22 MOVE_BRANCH_LOADING_AND_SAVING_FROM_DYNABOX_TO_DYNADLG		*
 *	Jasmine 06/05/07 QA80-9852 NOT_RESIZE_IF_HIDDEN								*
 *	Hong 08/18/08 QA80-12030 SPLITTER_1ST_PANE_SHOULD_NOT_TOO_NARROW_FIRST_LOADING
 *------------------------------------------------------------------------------*/

#ifndef _SPLITTER_CONTORL_H
#define _SPLITTER_CONTORL_H

class SplitterControl : public Splitter
{
public:
	/// TD 12-8-04 NEEDED_CONSTRUCTOR
	SplitterControl(UINT nDlgID, LPCSTR lpcszDLL, BOOL bReserved = 0)
	{
		m_bReady = false;
	}
	SplitterControl()
	{
		m_nRows = -1;
		m_nCols = -1;
		//m_nEntryToOnSize = 0;	///Danice LOAD_SETTING_FOR_STATIC_DIALOG
	}
	// nIndex = 0,1,2 for indicating which splitter in the dialog, arbitrary, only for saving and loading of settings
	void Init(int nCntrlID, WndContainer& wndParent, int nIndex = 0, LPCSTR lpcszDlgName = NULL)
	{
		m_pwndParent = &wndParent;
		m_nMainID = nCntrlID;	///Jasmine 06/05/07 QA80-9852 NOT_RESIZE_IF_HIDDEN	
		//----- CPY 9/22/05 SPLITTER_INIT_SIZE_ON_READY	
		//m_nEntryToOnSize = 0;	///Danice LOAD_SETTING_FOR_STATIC_DIALOG
		m_bReady = false;
		m_bInitSize1stPaneDone = false;
		m_bWaitPaneResize = true;
		m_vnPaneSizes.SetSize(0);
		//-----
		Control cntrl = wndParent.GetDlgItem( nCntrlID );
		if(cntrl) // cntrl already existed, replace with splitter
			CreateControl(cntrl.GetSafeHwnd());
		else // control not yet created, then create new
		{
			CreateControl(wndParent.GetSafeHwnd(), nCntrlID);
			m_nMainID = 0;//mark	///Jasmine 06/05/07 QA80-9852 NOT_RESIZE_IF_HIDDEN	
		}
			
		m_strDlgName = lpcszDlgName;
		if(!m_strDlgName.IsEmpty())
			m_str1stRowColSizeSavingName.Format("Splitter%d", nIndex + 1);
		
		//ResizePanes(false); //----- CPY 9/22/05 SPLITTER_INIT_SIZE_ON_READY, too early, equally devide for now
			
	}
	//----- CPY 9/22/05 SPLITTER_INIT_SIZE_ON_READY
	/*
	void OnResize(int nType, int cx, int cy)
	{
		// 1st time too early, control not properly sized, but after 1st time, user will do resizing on their own
		if(1 == m_nEntryToOnSize ++)
		{
			int n1stSize = -1;
			if(!m_strDlgName.IsEmpty())
				n1stSize = LoadSetting(m_str1stRowColSizeSavingName, 30);
			if(m_nCols > 1)
			{
				for(int ii = 0; ii < m_nCols - 1; ii++)				
					SetColSize(ii, 100/m_nCols);
				
				if(n1stSize > 0)
					SetColSize(0, n1stSize);	///DG REMEMBER_COL_SIZE_NOT_BY_PERCENT : remember by percent will decrease little by little
					//SetColSize(0, n1stSize, false); ///DG COL_SIZE_BY_PERCENT : the first time dialog open, left pane is so small
			}
			if(m_nRows > 1)
			{
				for(int jj = 0; jj < m_nRows - 1; jj++)
					SetRowSize(jj, 100/m_nRows);
				
				if(n1stSize > 0)
					SetRowSize(0, n1stSize);
			}
		}
	}
	*/
	void OnResize(int nType, int cx, int cy)
	{	
		if(!m_bReady)
		{
			OutInt("splitter OnResize not Ready, cy = ", cy);
			return;
		}
		///Jasmine 06/05/07 QA80-9852 NOT_RESIZE_IF_HIDDEN	
		if(0 < m_nMainID)
		{
			Control ctrl = GetDlgItem(m_nMainID);
			if(!ctrl || !ctrl.Visible)	
			{
				OutStr("splitter is hidden, exit");
				return;
			}
		}
		///End NOT_RESIZE_IF_HIDDEN
		OutInt("splitter OnResize, cy = ", cy);
		if(0==cx && 0==cy)// parent trying to force 1stPane init size
		{
			//----- CPY 3/25/06 SPLITTER_INIT_SIZE_NOT_CALL
			if(m_bWaitPaneResize)
			{
				OutStr("splitter OnResize 0,0 but m_bWaitPaneResize, exit");
				return;
			}
			//------
			
			if(m_bInitSize1stPaneDone)
			{
				OutStr("m_bInitSize1stPaneDone, exit");
				return;
			}
		}
		resizePanes();
	}
	BOOL OnReady()
	{
		if(!m_bInitSize1stPaneDone)
		{
			OutStr("splitter panes not init sized On Ready");
			//resizePanes();
			//----- CPY 3/25/06 SPLITTER_INIT_SIZE_NOT_CALL
			PostMessage(WM_USER_RESIZE_CONTROLS);
			m_bWaitPaneResize = true;
			//-----
		}
		
		m_bReady = true;
		return true;
	}
	//----- CPY 3/25/06 SPLITTER_INIT_SIZE_NOT_CALL
	void OnInitPaneSizs(int wParam, int lParam)
	{	
		m_bWaitPaneResize = false;
		OnResize(0,0,0);
	}
	//-----
	void OnDlgResize(int nType, int cx, int cy)
	{
		OnResize(0,0,0);
	}
	
	///Cheney 2006-9-22 MOVE_BRANCH_LOADING_AND_SAVING_FROM_DYNABOX_TO_DYNADLG
	string GetDlgName()
	{
		return m_strDlgName;
	}
	///end MOVE_BRANCH_LOADING_AND_SAVING_FROM_DYNABOX_TO_DYNADLG
private:
	void resizePanes(bool bTryInit1stPaneSize = true)
	{	
		/// Hong 08/18/08 QA80-12030 SPLITTER_1ST_PANE_SHOULD_NOT_TOO_NARROW_FIRST_LOADING
		/*
		int n1stPaneSize = -1;
		if(bTryInit1stPaneSize && m_bInitSize1stPaneDone)
			bTryInit1stPaneSize = false;
				
		if(bTryInit1stPaneSize)
		{			
			if(!m_strDlgName.IsEmpty())
				n1stPaneSize = LoadSetting(m_str1stRowColSizeSavingName, 30);
			else
				n1stPaneSize = 50;
			OutInt("setting pane size now to ", n1stPaneSize);
			m_bInitSize1stPaneDone = true;		
		}
		else
			OutStr("resizePanes called with bTryInit1stPaneSize = false");
		
		if(n1stPaneSize > 0)
		{
			if(m_nCols > 1)
			{			
				if(n1stPaneSize > 0)
					SetColSize(0, n1stPaneSize);
				else
				{
					for(int ii = 0; ii < m_nCols - 1; ii++)				
						SetColSize(ii, 100/m_nCols);
				}
			}
			if(m_nRows > 1)
			{
				if(n1stPaneSize > 0)
					SetRowSize(0, n1stPaneSize);
				else
				{
					for(int jj = 0; jj < m_nRows - 1; jj++)
						SetRowSize(jj, 100/m_nRows);
				}
			}
		}
		*/	
#define		SET_SPLITTER_SIZE(_nNumPanes, _n1stPaneSizeInPercentage, _fn) \
			if ( _nNumPanes > 1 ) \
			{ \
				int		nSizeInPercentage; \
				for ( int iIndex = 0; iIndex < _nNumPanes - 1; iIndex++ ) \
				{ \
					nSizeInPercentage = 0 == iIndex ? _n1stPaneSizeInPercentage : (100 - _n1stPaneSizeInPercentage) / (_nNumPanes - 1); \
					_fn(iIndex, nSizeInPercentage); \
				} \
			}
		
		if ( m_bInitSize1stPaneDone )
			bTryInit1stPaneSize = false;		
		if ( bTryInit1stPaneSize )
		{
			int			n1stPaneDefauleSize = -1;			
			int			nNumPanes = 0;
			if ( m_nCols > 1 )
			{
				ASSERT(!(m_nRows > 1)); // NOT support yet?
				nNumPanes = m_nCols;
			}
			else if ( m_nRows > 1 )
				nNumPanes = m_nRows;				
			if ( 2 == nNumPanes ) // currently, all spiltter only divided into two panes
			{
				n1stPaneDefauleSize = m_strDlgName.IsEmpty() ? 50 : 30;
			}
			else if ( nNumPanes > 0 )
			{
				n1stPaneDefauleSize = 100 / nNumPanes;
			}			
			
			int 		n1stPaneSize = -1;
			if ( !m_strDlgName.IsEmpty() )			
				n1stPaneSize = LoadSetting(m_str1stRowColSizeSavingName, n1stPaneDefauleSize);			
			if ( n1stPaneSize <= 0 || n1stPaneSize >= 100 )
				n1stPaneSize = n1stPaneDefauleSize;

			OutInt("setting pane size now to ", n1stPaneSize);
			
			SET_SPLITTER_SIZE(m_nCols, n1stPaneSize, SetColSize);
			SET_SPLITTER_SIZE(m_nRows, n1stPaneSize, SetRowSize);
		
			m_bInitSize1stPaneDone = true;		
		}
		else
			OutStr("resizePanes called with bTryInit1stPaneSize = false");						
		/// end SPLITTER_1ST_PANE_SHOULD_NOT_TOO_NARROW_FIRST_LOADING
		
		resizeTabItems();

	}
	//---- end SPLITTER_INIT_SIZE_ON_READY
protected:
	void OutInt(LPCSTR lpc, int n)
	{
		//out_int(lpc, n);
	}
	void OutStr(LPCSTR lpc)
	{
		//out_str(lpc);
	}
	//---- CPY 5/31/06, I added this so FO code can be converted to Dyna based
	// basically to channel to call base class SetReady
	BOOL SetReady(bool bSet = true)
	{
		//m_bReady = bSet; // this must not be touched
		if(bSet)
			Splitter::SetReady();
		return true;
	}
	//----
	// ML: This function is needed for saving MDI child splitter configuration.
	// It is called from GetSplitterSettings() in OCMsgMap.cpp in VC.
	virtual	BOOL GetSettings(TreeNode &nodeSettings)
	{
		return TRUE;
	}
	// ML: This function is needed for loading MDI child splitter configuration.
	// It is called from CreateSplitterPanelWindow() in OCMsgMap.cpp in VC.
	virtual	BOOL SetSettings(TreeNode &nodeSettings)
	{
		return TRUE;
	}
	BOOL	SetGridSize(int nRows, int nCols)
	{
		m_nRows = nRows;
		m_nCols = nCols;
		return Splitter :: SetGridSize(nRows, nCols);
	}
	virtual BOOL OnDestroy(void)
	{
		if(m_strDlgName.IsEmpty())
			return true;
		
		int nSize = 50;
		if( m_nCols > 1 )
			GetColSize(0, nSize);	///DG REMEMBER_COL_SIZE_NOT_BY_PERCENT
			//GetColSize(0, nSize, false); ///DG COL_SIZE_BY_PERCENT
		else
			GetRowSize(0, nSize);
		//----- CPY 9/22/05 SPLITTER_INIT_SIZE_ON_READY
		// to prevent progressive change due to limited size and round off err
		int nOldSize = LoadSetting(m_str1stRowColSizeSavingName, -1);
		if(abs(nOldSize - nSize) < 2)
		{
			OutInt("OnDestroy, size too similar, not saved, =", nSize);
			return true;
		}
		OutInt("OnDestroy, saving new size =", nSize);
		//-----
		SaveSetting(m_str1stRowColSizeSavingName, nSize);
		return true;
	}
	DWORD LoadSetting(LPCSTR lpcszValName, DWORD dwDefault = 0, LPCSTR lpcszDlgName = NULL)
	{
		string strSecName = lpcszDlgName;
		if(strSecName.IsEmpty())
			strSecName = m_strDlgName;
		
		DWORD dwVal = dwDefault;
		if(dlg_load_registry(strSecName, lpcszValName, dwVal))
			return dwVal;
		
		return dwDefault;
	}
	void SaveSetting(LPCSTR lpcszValName, DWORD dwVal, LPCSTR lpcszDlgName = NULL)
	{
		string strSecName = lpcszDlgName;
		if(strSecName.IsEmpty())
			strSecName = m_strDlgName;
		
		dlg_save_to_registry(strSecName, lpcszValName, dwVal);
	}
	///Frank 11/10/04 v8.0160 QA70-6086   REMEMBER_LAST_USE_FUNCTION
	//Add two more function to save and load string to reg.
	//--- CPY 2/11/05 NO_REASON_TO_RETURN_LPCSTR
	//LPCSTR LoadSetting(LPCSTR lpcszValName, string &strVal , LPCSTR lpcszDlgName = NULL)
	bool LoadSetting(LPCSTR lpcszValName, string &strVal , LPCSTR lpcszDlgName = NULL)
	{
		string strSecName = lpcszDlgName;
		if(strSecName.IsEmpty())
			strSecName = m_strDlgName;
		
		if(dlg_load_registry(strSecName, lpcszValName, strVal))
			return true;
		
		return false;
	}
	void SaveSetting(LPCSTR lpcszValName, LPCSTR lpcstrVal = NULL, LPCSTR lpcszDlgName = NULL)
	{
		string strSecName = lpcszDlgName;
		if(strSecName.IsEmpty())
			strSecName = m_strDlgName;
		
		dlg_save_to_registry(strSecName, lpcszValName, lpcstrVal);
	}
	///End   REMEMBER_LAST_USE_FUNCTION
private:
	int		m_nMainID;	///Jasmine 06/05/07 QA80-9852 NOT_RESIZE_IF_HIDDEN	
	//----- CPY 9/22/05 SPLITTER_INIT_SIZE_ON_READY
	//int		m_nEntryToOnSize;
	bool	m_bReady;
	bool	m_bInitSize1stPaneDone;
	bool	m_bWaitPaneResize;
	vector<int>		m_vnPaneSizes;
	//-----
	int		m_nRows;
	int		m_nCols;
	string	m_strDlgName;
	string	m_str1stRowColSizeSavingName;
	//------ CPY 3/5/06 XF_INTERNAL_DIALOG
	WndContainer*	m_pwndParent; 
protected:
	Control GetDlgItem(int nID)
	{
		if(!m_pwndParent)
			return NULL;
		
		return m_pwndParent->GetDlgItem(nID);
	}
	bool GetClientRect(Control& cc, RECT& rr)
	{
		if(!m_pwndParent)
			return false;
		if(cc)
		{
			cc.GetWindowRect(&rr);
			m_pwndParent->ScreenToClient(&rr);
			return true;
		}
		return false;
	}
	void MoveControl(Control& cc, RECT& rr) {cc.MoveWindow(&rr);}
	BOOL OnTabChange(Control cntrl)
	{
		updateShowTabItems(); 
		return true;
	}
	void SetupTabItems(const vector<uint>& vnTabItems, LPCSTR lpcszTabStrs)
	{
		string strNames = lpcszTabStrs;
		strNames.GetTokens(m_vsTabNames, '|');
		m_vnTabItems = vnTabItems;
	}
	void CreateTabPane(int nRow, int nCol)
	{
		CreatePane(m_tabPane, nRow, nCol, -1, -1);
		for(int ii = 0; ii < m_vnTabItems.GetSize(); ii++)
		{
			m_tabPane.InsertItem(m_vnTabItems[ii], m_vsTabNames[ii]);
		}
	}
private:
	void 	updateShowTabItems(int nTabToShow = -1) // = -1
	{
		if(nTabToShow >= 0)
		{
			m_tabPane.SetCurSel(nTabToShow);
		}
	
		int nSelTab = m_tabPane.GetCurSel();
		for(int ii = 0; ii < m_vnTabItems.GetSize(); ii++)
		{
			Control cc = GetDlgItem(m_vnTabItems[ii]);
			if(ii == nSelTab)
				cc.Visible = true;
			else
				cc.Visible = false;
		}
	}
	void resizeTabItems()
	{
		if(!m_tabPane)
			return;
		RECT rTab;
		if(!GetClientRect(m_tabPane, rTab))
			return;
		
		m_tabPane.AdjustRect(FALSE, &rTab);
		// debug
		rTab.bottom += 30;
		for(int ii = 0; ii < m_vnTabItems.GetSize(); ii++)
		{
			Control cc = GetDlgItem(m_vnTabItems[ii]);
			MoveControl(cc, rTab);
			if(cc.Visible)
			{
				SetWindowPos(cc.GetSafeHwnd(), this->GetSafeHwnd(), 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
			}
		}
	}
public:
	TabControl 		m_tabPane;
protected:
	int				m_nTabID;
private:
	vector<uint>	m_vnTabItems;
	vector<string>	m_vsTabNames;
	//---- end CPY 3/5/06 XF_INTERNAL_DIALOG
};
#endif //_SPLITTER_CONTORL_H

