420 lines
11 KiB
C++
420 lines
11 KiB
C++
// 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 "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 >= (signed) 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();
|
|
}
|
|
|