//  Project     : general base class
//  Compiler    : Visual C++ 5.0 / 6.0
//  Plattform   : Windows 95/98, Windows NT 3.51/4.0/2000
//  File        : ST_SplitterWnd.cpp 
//  Programmer  : dz, SoftToys
//  Copyright   : 2001 SoftToys
//  Contact     : info@softtoys.com
//  Description : base class for handling splitter windows 
//  History     : 02.Sept. 2001 Version 1.0
//


#include "stdafx.h"
//#include "SplitterWndTest.h"
#include "ST_SplitterWnd.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

ST_SplitterWnd::ST_SplitterWnd(int nLevel/* = 0*/) : m_nHiddenCol(-1),m_nHiddenRow(-1),
                                                         m_sRegKey(_T("SplitterWnd")) , m_nLevel(nLevel)
{
	m_nPaneSize[0]    = 100;
	m_nPaneSize[1]    = 100;
	m_nPaneMinSize[0] = 10;
	m_nPaneMinSize[1] = 10;
   m_pSubSplitterWnd[0] = NULL;
   m_pSubSplitterWnd[1] = NULL;
	m_nCurrentView[0] = 0;
	m_nCurrentView[1] = 0;
}

ST_SplitterWnd::~ST_SplitterWnd()
{
   SaveToRegistry();
}

bool ST_SplitterWnd::Create(CWnd* pParentWnd, CRuntimeClass* pView1, CRuntimeClass* pView2,
									  CCreateContext* pContext, bool bVertical,int nID)
{
	int nRow, nCol;
   m_bVertical = bVertical;
	if (bVertical) {
		nRow = 1;
		nCol = 2;
	}
	else {
		nRow = 2;
		nCol = 1;
	}
	VERIFY(CreateStatic(pParentWnd,nRow,nCol,WS_CHILD|WS_VISIBLE|WS_BORDER,nID));
   if (pView1 != NULL) {
      VERIFY(CreateView(0,0,pView1,CSize(100,100),pContext));
   }
   if (pView2 != NULL) {
	   if (bVertical) {
		   VERIFY(CreateView(0,1,pView2,CSize(100,100),pContext));
	   }
	   else {
		   VERIFY(CreateView(1,0,pView2,CSize(100,100),pContext));
	   }
   }
	return(true);
}

void ST_SplitterWnd::SetInitialStatus()
{
	int c,r;
   CString sSubKey;
   sSubKey.Format(_T("Panes_%d"),m_nLevel);
   CString s;
	s = AfxGetApp()->GetProfileString(m_sRegKey,sSubKey,_T("-1 150 -1 150"));
	   sscanf(s,_T("%d %d %d %d"),&c,&m_nPaneSize[0],&r,&m_nPaneSize[1]);
   
   if (IsSplittverticaly()) {
		SetColumnInfo(0,m_nPaneSize[0],m_nPaneMinSize[0]);
		SetColumnInfo(1,m_nPaneSize[1],m_nPaneMinSize[1]);
		if (c > -1) ToggleSide(c); 
      if (c == -1)  RecalcLayout();
   }
	else {
		SetRowInfo(0,m_nPaneSize[0],m_nPaneMinSize[0]);
		SetRowInfo(1,m_nPaneSize[1],m_nPaneMinSize[1]);
		if (r > -1) ToggleSide(r); 
      if (r == -1) RecalcLayout();
	}
   if (m_pSubSplitterWnd[0] != NULL) m_pSubSplitterWnd[0]->SetInitialStatus();
   if (m_pSubSplitterWnd[1] != NULL) m_pSubSplitterWnd[1]->SetInitialStatus();
}



void ST_SplitterWnd::SaveToRegistry()
{
   CString s;
   CString sSubKey;
   sSubKey.Format(_T("Panes_%d"),m_nLevel);

   RememberSize();
   if (m_nPaneSize[0] == -1) m_nPaneSize[0] = 100;
   if (m_nPaneSize[1] == -1) m_nPaneSize[1] = 100;

   s.Format(_T("%d %d %d %d"),m_nHiddenCol,m_nPaneSize[0],m_nHiddenRow,m_nPaneSize[1]);
   AfxGetApp()->WriteProfileString(m_sRegKey,sSubKey,s);

   if (m_pSubSplitterWnd[0] != NULL) m_pSubSplitterWnd[0]->SaveToRegistry();
   if (m_pSubSplitterWnd[1] != NULL) m_pSubSplitterWnd[1]->SaveToRegistry();
}

bool ST_SplitterWnd::IsSideHidden(int nSide /* = LEFT_SIDE */)
{
   if (IsSplittverticaly()) {
      if (m_nHiddenCol == nSide) {
         return(true);
      }
   }
   else {
      if (m_nHiddenRow == nSide) {
         return(true);
      }
   }
   return(false);
}


void ST_SplitterWnd::ShowColumn()
{
     ASSERT_VALID(this);
     ASSERT(m_nCols < m_nMaxCols);
     ASSERT(m_nHiddenCol != -1);

     int colNew = m_nHiddenCol;
     m_nHiddenCol = -1;
     m_nCols++;  // add a column
     ASSERT(m_nCols == m_nMaxCols);

    // fill the hidden column
     int col;
     for (int row = 0; row < m_nRows; row++)
     {
          CWnd* pPaneShow = GetDlgItem(
               AFX_IDW_PANE_FIRST + row * 16 + m_nCols);
          ASSERT(pPaneShow != NULL);
          pPaneShow->ShowWindow(SW_SHOWNA);

          for (col = m_nCols - 2; col >= colNew; col--)
          {
               CWnd* pPane = GetPane(row, col);
               ASSERT(pPane != NULL);
               pPane->SetDlgCtrlID(IdFromRowCol(row, col + 1));
          }

         pPaneShow->SetDlgCtrlID(IdFromRowCol(row, colNew));
     }
     // new panes have been created -- recalculate layout
     RecalcLayout();
}

void ST_SplitterWnd::HideColumn(int colHide)
{
     ASSERT_VALID(this);
     ASSERT(m_nCols > 1);
     ASSERT(colHide < m_nCols);
     ASSERT(m_nHiddenCol == -1);
     if (m_nHiddenCol != -1) return;

     RememberSize();

     m_nHiddenCol = colHide;

    // if the column has an active window -- change it
     int rowActive, colActive;
     if (GetActivePane(&rowActive, &colActive) != NULL &&
         colActive == colHide)
     {
          if (++colActive >= m_nCols)
              colActive = 0;
          SetActivePane(rowActive, colActive);
     }

    // hide all column panes
     for (int row = 0; row < m_nRows; row++)
     {
          CWnd* pPaneHide = GetPane(row, colHide);
          ASSERT(pPaneHide != NULL);
          pPaneHide->ShowWindow(SW_HIDE);
          pPaneHide->SetDlgCtrlID(
               AFX_IDW_PANE_FIRST + row * 16 + m_nCols);

          for (int col = colHide + 1; col < m_nCols; col++)
          {
               CWnd* pPane = GetPane(row, col);
               ASSERT(pPane != NULL);
               pPane->SetDlgCtrlID(IdFromRowCol(row, col - 1));
          }
     }
     m_nCols--;
     m_pColInfo[m_nCols].nCurSize = m_pColInfo[colHide].nCurSize;
     RecalcLayout();
}


void ST_SplitterWnd::ShowRow()
{
     ASSERT_VALID(this);
     ASSERT(m_nRows < m_nMaxRows);
     ASSERT(m_nHiddenRow != -1);

     int rowNew = m_nHiddenRow;
     m_nHiddenRow = -1;
     m_nRows++;  // add a row
     ASSERT(m_nRows == m_nMaxRows);

    // fill the hidden row
     int row;
     for (int col = 0; col < m_nCols; col++)
     {
          CWnd* pPaneShow = GetDlgItem(
               AFX_IDW_PANE_FIRST + m_nRows * 16 + col);
          ASSERT(pPaneShow != NULL);
          pPaneShow->ShowWindow(SW_SHOWNA);

          for (row = m_nRows - 2; row >= rowNew; row--)
          {
               CWnd* pPane = GetPane(row, col);
               ASSERT(pPane != NULL);
               pPane->SetDlgCtrlID(IdFromRowCol(row + 1, col));
          }

         pPaneShow->SetDlgCtrlID(IdFromRowCol(rowNew, col));
     }

    // new panes have been created -- recalculate layout
     RecalcLayout();
}

void ST_SplitterWnd::HideRow(int rowHide)
{
     ASSERT_VALID(this);
     ASSERT(m_nRows > 1);
     ASSERT(rowHide < m_nRows);
     ASSERT(m_nHiddenRow == -1);
     if (m_nHiddenRow != -1) return;

     RememberSize();

     m_nHiddenRow = rowHide;

    // if the column has an active window -- change it
     int rowActive, colActive;
     if (GetActivePane(&rowActive, &colActive) != NULL &&
         rowActive == rowHide)
     {
          if (++rowActive >= m_nRows)
              rowActive = 0;
          SetActivePane(rowActive, colActive);
     }

    // hide all row panes
     for (int col = 0; col < m_nCols; col++)
     {
          CWnd* pPaneHide = GetPane(rowHide, col);
          ASSERT(pPaneHide != NULL);
          pPaneHide->ShowWindow(SW_HIDE);
          pPaneHide->SetDlgCtrlID(
               AFX_IDW_PANE_FIRST + m_nRows * 16);

          for (int row = rowHide + 1; row < m_nRows; row++)
          {
               CWnd* pPane = GetPane(row, col);
               ASSERT(pPane != NULL);
               pPane->SetDlgCtrlID(IdFromRowCol(row - 1, col));
          }
     }
     m_nRows--;
     m_pRowInfo[m_nRows].nCurSize = m_pRowInfo[rowHide].nCurSize;
     
     RecalcLayout();
}


void ST_SplitterWnd::ToggleSide(int rc)
{
   if (IsSplittverticaly()) {
      if (m_nHiddenCol == -1) {
         // can only hide this row, if the other row in not hidden
         HideColumn(rc);
      }
      else if (m_nHiddenCol == rc) {
         // show this row, only if this row is hidden
   	   ShowColumn();
      }
   }
   else {
      if (m_nHiddenRow == -1) {
         // can only hide this column, if the other colum in not hidden
         HideRow(rc);
      }
      else if (m_nHiddenRow == rc) {
         // show this column, only if this column is hidden
   	   ShowRow();
      }
   }
}

void ST_SplitterWnd::RememberSize()
{
   if (m_pSubSplitterWnd[0] != NULL) m_pSubSplitterWnd[0]->RememberSize();
   if (m_pSubSplitterWnd[1] != NULL) m_pSubSplitterWnd[1]->RememberSize();

   if (IsSplittverticaly()) {
      if (m_nHiddenCol == -1) { // if not hidden
		   GetColumnInfo(0,m_nPaneSize[0],m_nPaneMinSize[0]);
		   GetColumnInfo(1,m_nPaneSize[1],m_nPaneMinSize[1]);
      }
	}
	else {
      if (m_nHiddenRow == -1) { // if not hidden
		   GetRowInfo(0,m_nPaneSize[0],m_nPaneMinSize[0]);
		   GetRowInfo(1,m_nPaneSize[1],m_nPaneMinSize[1]);
      }
	}
}

ST_SplitterWnd* ST_SplitterWnd::AddSubDivision(int nSide,
                                CRuntimeClass* pView1,CRuntimeClass* pView2,CCreateContext* pContext,bool bVertical)
{
   ASSERT((nSide == 0) || (nSide == 1));
   ASSERT(m_pSubSplitterWnd[nSide] == NULL);

	int nRow, nCol;
	SideToRowCol(nSide,&nRow,&nCol);

   int nID = IdFromRowCol(nRow,nCol);
   m_pSubSplitterWnd[nSide] = new  ST_SplitterWnd(m_nLevel+1);
   m_pSubSplitterWnd[nSide]->Create(this,pView1,pView2,pContext,bVertical,nID);
   return(m_pSubSplitterWnd[nSide]);
}

bool ST_SplitterWnd::HideView(int nRow,int nCol)
{
	CWnd* pWnd = GetPane(nRow,nCol);
	if (!pWnd) return(false);
	pWnd->SetDlgCtrlID(0);
	pWnd->ShowWindow(SW_HIDE);
	return(true);
}


bool ST_SplitterWnd::ShowView(int nRow,int nCol,CWnd* pWnd)
{
	pWnd->SetDlgCtrlID(IdFromRowCol(nRow, nCol));
	pWnd->ShowWindow(SW_SHOW);
	return(true);
}


int ST_SplitterWnd::AddView(int nSide, CRuntimeClass * pViewClass, CCreateContext* pContext)
{
	int nRow, nCol;
	SideToRowCol(nSide,&nRow,&nCol);

   // hide the current view of the pane if there is a view attached already
	if (GetDlgItem(IdFromRowCol(nRow, nCol))) {	
		HideView(nRow, nCol);
	}

	// create the new view, if fail, set the previous view current 
	if (CreateView(nRow, nCol, pViewClass, CSize(10,10), pContext) == 0) return -1;

	// get and store the new view
	CWnd* pWnd = GetPane(nRow, nCol);
	m_views[nSide].push_back(pWnd);
	m_nCurrentView[nSide] = m_views[nSide].size() - 1;

	ShowView(nRow, nCol,pWnd);

	RedrawWindow();
	return(m_nCurrentView[nSide]);

}


void ST_SplitterWnd::SwitchToView(int nSide,int nViewIX /* = -1 */)
{
	// if the View is -1 then just use the next view...
	if (nViewIX == -1) {
		nViewIX = m_nCurrentView[nSide] + 1;
		if (nViewIX >= m_views[nSide].size()) nViewIX = 0; // rollover to first view
	}
	
	CWnd* pWnd = m_views[nSide][nViewIX];

	int nRow, nCol;

	if (IsSideHidden(LEFT_SIDE)) {
		nRow = 0;
		nCol = 0;
	}
	else {
		SideToRowCol(nSide,&nRow,&nCol);
	}
	HideView(nRow, nCol);
	ShowView(nRow, nCol, pWnd);

	m_nCurrentView[nSide] = nViewIX;
	RecalcLayout();
	RedrawWindow();
}

