Viewing file: splitex.cpp (10.85 KB) -rw-rw-rw- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
////////////////////////////////////////////////////////////////////////////
//
// splitex.cpp
// Based upon code from Oleg G. Galkin
// Modified to handle multiple hidden rows
#include "stdafx.h"
#include "splitex.h"
#if defined(_DEBUG) && !defined(MMGR)
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
////////////////////////////////////////////////////////////////////////////
//
// CSplitterWndEx
CSplitterWndEx::CSplitterWndEx()
{
m_arr = 0;
m_length = 0;
}
CSplitterWndEx::~CSplitterWndEx()
{
delete [] m_arr;
}
int CSplitterWndEx::Id_short(int row, int col)
{
return AFX_IDW_PANE_FIRST + row * 16 + col;
}
void CSplitterWndEx::ShowRow(int r)
{
ASSERT_VALID(this);
ASSERT(m_nRows < m_nMaxRows);
ASSERT(m_arr);
ASSERT(r < m_length);
ASSERT(m_arr[r] >= m_nRows);
ASSERT(m_arr[r] < m_length);
int rowNew = r;
int cyNew = m_pRowInfo[m_arr[r]].nCurSize;
int cyIdealNew = m_pRowInfo[m_arr[r]].nIdealSize;
int new_val = 0;
for (int i = rowNew - 1; i >= 0; i--)
if (m_arr[i] < m_nRows) // not hidden
{
new_val = m_arr[i] + 1;
break;
}
int old_val = m_arr[rowNew];
m_nRows++; // add a row
// fill the hided row
int row;
for (int col = 0; col < m_nCols; col++)
{
CWnd* pPaneShow = GetDlgItem(
Id_short(old_val, col));
ASSERT(pPaneShow != NULL);
pPaneShow->ShowWindow(SW_SHOWNA);
for (row = m_length - 1; row >= 0; row--)
{
if ((m_arr[row] >= new_val) &&
(m_arr[row] < old_val))
{
CWnd* pPane = CSplitterWnd::GetPane(m_arr[row], col);
ASSERT(pPane != NULL);
pPane->SetDlgCtrlID(Id_short(m_arr[row] + 1, col));
}
}
pPaneShow->SetDlgCtrlID(Id_short(new_val, col));
}
for (row = 0; row < m_length; row++)
if ((m_arr[row] >= new_val) &&
(m_arr[row] < old_val))
m_arr[row]++;
m_arr[rowNew] = new_val;
//new panes have been created -- recalculate layout
for (row = new_val + 1; row < m_length; row++)
{
if (m_arr[row]<m_nRows)
{
m_pRowInfo[m_arr[row]].nIdealSize = m_pRowInfo[m_arr[row-1]].nCurSize;
m_pRowInfo[m_arr[row]].nCurSize = m_pRowInfo[m_arr[row-1]].nCurSize;
}
}
if (cyNew>=0x10000)
{
int rowToResize=(cyNew>>16)-1;
cyNew%=0x10000;
cyIdealNew%=0x10000;
m_pRowInfo[m_arr[rowToResize]].nCurSize-=cyNew+m_cxSplitter;
m_pRowInfo[m_arr[rowToResize]].nIdealSize=m_pRowInfo[m_arr[rowToResize]].nCurSize;//-=cyIdealNew+m_cxSplitter;
}
m_pRowInfo[new_val].nIdealSize = cyNew;
m_pRowInfo[new_val].nCurSize = cyNew;
RecalcLayout();
}
void CSplitterWndEx::ShowColumn(int c)
{
ASSERT_VALID(this);
ASSERT(m_nCols < m_nMaxCols);
ASSERT(m_arr);
ASSERT(c < m_length);
ASSERT(m_arr[c] >= m_nRows);
ASSERT(m_arr[c] < m_length);
int colNew = c;
int cxNew = m_pColInfo[m_arr[c]].nCurSize;
int cxIdealNew = m_pColInfo[m_arr[c]].nIdealSize;
int new_val = 0;
for (int i = colNew - 1; i >= 0; i--)
if (m_arr[i] < m_nCols) // not hidden
{
new_val = m_arr[i] + 1;
break;
}
int old_val = m_arr[colNew];
m_nCols++; // add a col
// fill the hided col
int col;
for (int row = 0; row < m_nRows; row++)
{
CWnd* pPaneShow = GetDlgItem(
Id_short(row, old_val));
ASSERT(pPaneShow != NULL);
pPaneShow->ShowWindow(SW_SHOWNA);
for (col = m_length - 1; col >= 0; col--)
{
if ((m_arr[col] >= new_val) &&
(m_arr[col] < old_val))
{
CWnd* pPane = CSplitterWnd::GetPane(row, m_arr[col]);
ASSERT(pPane != NULL);
pPane->SetDlgCtrlID(Id_short(row, m_arr[col]+1));
}
}
pPaneShow->SetDlgCtrlID(Id_short(row, new_val));
}
for (col = 0; col < m_length; col++)
if ((m_arr[col] >= new_val) &&
(m_arr[col] < old_val))
m_arr[col]++;
m_arr[colNew] = new_val;
//new panes have been created -- recalculate layout
for (col = new_val + 1; col < m_length; col++)
{
if (m_arr[col]<m_nCols)
{
m_pColInfo[m_arr[col]].nIdealSize = m_pColInfo[m_arr[col-1]].nCurSize;
m_pColInfo[m_arr[col]].nCurSize = m_pColInfo[m_arr[col-1]].nCurSize;
}
}
if (cxNew>=0x10000)
{
int colToResize=(cxNew>>16)-1;
cxNew%=0x10000;
cxIdealNew%=0x10000;
m_pColInfo[m_arr[colToResize]].nCurSize-=cxNew+m_cySplitter;
m_pColInfo[m_arr[colToResize]].nIdealSize=m_pColInfo[m_arr[colToResize]].nCurSize;//-=cxIdealNew+m_cySplitter;
}
m_pColInfo[new_val].nIdealSize = cxNew;
m_pColInfo[new_val].nCurSize = cxNew;
RecalcLayout();
}
void CSplitterWndEx::HideRow(int rowHide,int rowToResize)
{
ASSERT_VALID(this);
ASSERT(m_nRows > 1);
if (m_arr)
ASSERT(m_arr[rowHide] < m_nRows);
// if the row has an active window -- change it
int rowActive, colActive;
if (!m_arr)
{
m_arr = new int[m_nRows];
for (int i = 0; i < m_nRows; i++)
m_arr[i] = i;
m_length = m_nRows;
}
if (GetActivePane(&rowActive, &colActive) != NULL &&
rowActive == rowHide) //colActive == rowHide)
{
if (++rowActive >= m_nRows)
rowActive = 0;
//SetActivePane(rowActive, colActive);
SetActivePane(rowActive, colActive);
}
// hide all row panes
for (int col = 0; col < m_nCols; col++)
{
CWnd* pPaneHide = CSplitterWnd::GetPane(m_arr[rowHide], col);
ASSERT(pPaneHide != NULL);
pPaneHide->ShowWindow(SW_HIDE);
for (int row = rowHide + 1; row < m_length; row++)
{
if (m_arr[row] < m_nRows )
{
CWnd* pPane = CSplitterWnd::GetPane(m_arr[row], col);
ASSERT(pPane != NULL);
pPane->SetDlgCtrlID(Id_short(row-1, col));
m_arr[row]--;
}
}
pPaneHide->SetDlgCtrlID(
Id_short(m_nRows -1 , col));
}
int oldsize=m_pRowInfo[m_arr[rowHide]].nCurSize;
for (int row=rowHide;row<(m_length-1);row++)
{
if (m_arr[row+1] < m_nRows )
{
m_pRowInfo[m_arr[row]].nCurSize=m_pRowInfo[m_arr[row+1]].nCurSize;
m_pRowInfo[m_arr[row]].nIdealSize=m_pRowInfo[m_arr[row+1]].nCurSize;
}
}
if (rowToResize!=-1)
{
m_pRowInfo[m_arr[rowToResize]].nCurSize+=oldsize+m_cySplitter;
m_pRowInfo[m_arr[rowToResize]].nIdealSize+=oldsize+m_cySplitter;
oldsize+=0x10000*(rowToResize+1);
}
m_pRowInfo[m_nRows - 1].nCurSize =oldsize;
m_pRowInfo[m_nRows - 1].nIdealSize =oldsize;
m_arr[rowHide] = m_nRows-1;
m_nRows--;
RecalcLayout();
}
void CSplitterWndEx::HideColumn(int colHide, int colToResize)
{
ASSERT_VALID(this);
ASSERT(m_nCols > 1);
if (m_arr)
ASSERT(m_arr[colHide] < m_nCols);
// if the col has an active window -- change it
int colActive, rowActive;
if (!m_arr)
{
m_arr = new int[m_nCols];
for (int i = 0; i < m_nCols; i++)
m_arr[i] = i;
m_length = m_nCols;
}
if (GetActivePane(&rowActive, &colActive) != NULL &&
colActive == colHide)
{
if (++colActive >= m_nCols)
colActive = 0;
SetActivePane(rowActive, colActive);
}
// hide all row panes
for (int row = 0; row < m_nRows; row++)
{
CWnd* pPaneHide = CSplitterWnd::GetPane(row, m_arr[colHide]);
ASSERT(pPaneHide != NULL);
pPaneHide->ShowWindow(SW_HIDE);
for (int col = colHide + 1; col < m_length; col++)
{
if (m_arr[col] < m_nCols )
{
CWnd* pPane = CSplitterWnd::GetPane(row, m_arr[col]);
ASSERT(pPane != NULL);
pPane->SetDlgCtrlID(Id_short(row, col-1));
m_arr[col]--;
}
}
pPaneHide->SetDlgCtrlID(
Id_short(row, m_nCols -1));
}
int oldsize = m_pColInfo[m_arr[colHide]].nCurSize;
for (int col = colHide; col < (m_length - 1); ++col)
{
if (m_arr[col + 1] < m_nCols)
{
m_pColInfo[m_arr[col]].nCurSize = m_pColInfo[m_arr[col + 1]].nCurSize;
m_pColInfo[m_arr[col]].nIdealSize = m_pColInfo[m_arr[col + 1]].nCurSize;
}
}
if (colToResize != -1)
{
m_pColInfo[m_arr[colToResize]].nCurSize += oldsize + m_cxSplitter;
m_pColInfo[m_arr[colToResize]].nIdealSize += oldsize + m_cxSplitter;
oldsize += 0x10000 * (colToResize + 1);
}
m_pColInfo[m_nCols - 1].nCurSize = oldsize;
m_pColInfo[m_nCols - 1].nIdealSize = oldsize;
m_arr[colHide] = m_nCols - 1;
m_nCols--;
RecalcLayout();
}
BEGIN_MESSAGE_MAP(CSplitterWndEx, CSplitterWnd)
//{{AFX_MSG_MAP(CSplitterWndEx)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CWnd* CSplitterWndEx::GetPane(int row, int col)
{
if (!m_arr)
return CSplitterWnd::GetPane(row,col);
else
{
ASSERT_VALID(this);
CWnd* pView = GetDlgItem(IdFromRowCol(m_arr[row], col));
ASSERT(pView != NULL); // panes can be a CWnd, but are usually CViews
return pView;
}
}
int CSplitterWndEx::IdFromRowCol(int row, int col) const
{
ASSERT_VALID(this);
ASSERT(row >= 0);
ASSERT(row < (m_arr?m_length:m_nRows));
ASSERT(col >= 0);
ASSERT(col < m_nCols);
return AFX_IDW_PANE_FIRST + row * 16 + col;
}
BOOL CSplitterWndEx::IsChildPane(CWnd* pWnd, int* pRow, int* pCol)
{
ASSERT_VALID(this);
ASSERT_VALID(pWnd);
UINT nID = ::GetDlgCtrlID(pWnd->m_hWnd);
if (IsChild(pWnd) && nID >= AFX_IDW_PANE_FIRST && nID <= AFX_IDW_PANE_LAST)
{
if (pWnd->GetParent()!=this)
return FALSE;
if (pRow != NULL)
*pRow = (nID - AFX_IDW_PANE_FIRST) / 16;
if (pCol != NULL)
*pCol = (nID - AFX_IDW_PANE_FIRST) % 16;
ASSERT(pRow == NULL || *pRow < (m_arr?m_length:m_nRows));
ASSERT(pCol == NULL || *pCol < m_nCols);
return TRUE;
}
else
{
if (pRow != NULL)
*pRow = -1;
if (pCol != NULL)
*pCol = -1;
return FALSE;
}
}
CWnd* CSplitterWndEx::GetActivePane(int* pRow, int* pCol)
// return active view, NULL when no active view
{
ASSERT_VALID(this);
// attempt to use active view of frame window
CWnd* pView = NULL;
CFrameWnd* pFrameWnd = GetParentFrame();
ASSERT_VALID(pFrameWnd);
pView = pFrameWnd->GetActiveView();
// failing that, use the current focus
if (pView == NULL)
pView = GetFocus();
// make sure the pane is a child pane of the splitter
if (pView != NULL && !IsChildPane(pView, pRow, pCol))
pView = NULL;
return pView;
}
BOOL CSplitterWndEx::IsRowHidden(int row)
{
return m_arr[row]>=m_nRows;
}
void CSplitterWndEx::GetRowInfoEx(int row, int &cyCur, int &cyMin)
{
if (!m_arr)
GetRowInfo(row,cyCur,cyMin);
else
{
if (m_pRowInfo[m_arr[row]].nCurSize>0x10000)
cyCur=m_pRowInfo[m_arr[row]].nCurSize/0x10000;
else
cyCur=m_pRowInfo[m_arr[row]].nCurSize%0x10000;
cyMin=0;
}
}
__int64 CSplitterWndEx::GetSizes() const
{
LARGE_INTEGER v;
int dummy;
int s1, s2;
if (BarIsHorizontal())
{
GetRowInfo(0, s1, dummy);
GetRowInfo(1, s2, dummy);
v.HighPart = s1;
v.LowPart = s2;
}
else
{
GetColumnInfo(0, s1, dummy);
GetColumnInfo(1, s2, dummy);
v.HighPart = s1;
v.LowPart = s2;
}
return v.QuadPart;
}
|