www.pudn.com > ÍøÂç¶Ë¿Ú¼àÊÓ.rar > BCGPDockBar.cpp
// BCGPDockBar.cpp : implementation file
//
#include "stdafx.h"
#include "BCGPFrameWnd.h"
#include "BCGPMDIFrameWnd.h"
#include "BCGPOleIPFrameWnd.h"
#include "BCGPOleDocIPFrameWnd.h"
#include "BCGPMDIChildWnd.h"
#include "BCGPOleCntrFrameWnd.h"
#include "BCGPControlBar.h"
#include "BCGPDockBarRow.h"
#include "BCGPReBar.h"
#include "BCGPGlobalUtils.h"
#include "BCGPDockBar.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CBCGPDockBar, CBCGPBaseControlBar)
/////////////////////////////////////////////////////////////////////////////
// CBCGPDockBar
CBCGPDockBar::CBCGPDockBar() : m_nDockBarID (0)
{
}
CBCGPDockBar::~CBCGPDockBar()
{
while (!m_lstDockBarRows.IsEmpty ())
{
delete m_lstDockBarRows.RemoveHead ();
}
}
BEGIN_MESSAGE_MAP(CBCGPDockBar, CBCGPBaseControlBar)
//{{AFX_MSG_MAP(CBCGPDockBar)
ON_WM_PAINT()
ON_WM_SIZE()
ON_WM_ERASEBKGND()
ON_WM_CONTEXTMENU()
ON_WM_NCDESTROY()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBCGPDockBar message handlers
BOOL CBCGPDockBar::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, DWORD dwBCGStyle, CCreateContext* pContext)
{
ASSERT_VALID (this);
return CBCGPDockBar::CreateEx (0, dwStyle, rect, pParentWnd, dwBCGStyle, pContext);
}
//----------------------------------------------------------------------------------//
BOOL CBCGPDockBar::CreateEx(DWORD dwStyleEx, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, DWORD dwBCGStyle, CCreateContext* pContext)
{
ASSERT_VALID (this);
DWORD dwEnableAlignment = GetEnabledAlignment ();
EnableDocking (dwEnableAlignment | dwStyle);
SetBarAlignment (dwStyle);
dwStyle |= WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPED;
dwStyleEx = WS_EX_LEFT;
//-----------------------------
// Register a new window class:
//-----------------------------
HINSTANCE hInst = AfxGetInstanceHandle();
UINT uiClassStyle = CS_DBLCLKS;
HCURSOR hCursor = ::LoadCursor (NULL, IDC_ARROW);
HBRUSH hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
CString strClassName;
strClassName.Format (_T("BCGDockBar:%x:%x:%x:%x"),
(UINT)hInst, uiClassStyle, (UINT)hCursor, (UINT)hbrBackground);
//---------------------------------
// See if the class already exists:
//---------------------------------
WNDCLASS wndcls;
if (::GetClassInfo (hInst, strClassName, &wndcls))
{
//-----------------------------------------------
// Already registered, assert everything is good:
//-----------------------------------------------
ASSERT (wndcls.style == uiClassStyle);
}
else
{
//-------------------------------------------
// Otherwise we need to register a new class:
//-------------------------------------------
wndcls.style = uiClassStyle;
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
wndcls.hInstance = hInst;
wndcls.hIcon = NULL;
wndcls.hCursor = hCursor;
wndcls.hbrBackground = hbrBackground;
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = strClassName;
if (!AfxRegisterClass (&wndcls))
{
AfxThrowResourceException();
}
}
// Align the bar along borders; initially, create the dock bar with zero height/width
CRect rectDockBar = rect;
CRect rectParent;
pParentWnd->GetClientRect (&rectParent);
rectDockBar = rectParent;
switch (GetCurrentAlignment ())
{
case CBRS_ALIGN_LEFT:
rectDockBar.right = 0;
m_nDockBarID = AFX_IDW_DOCKBAR_LEFT;
break;
case CBRS_ALIGN_RIGHT:
rectDockBar.left = rectParent.right;
m_nDockBarID = AFX_IDW_DOCKBAR_RIGHT;
break;
case CBRS_ALIGN_TOP:
rectDockBar.bottom = rectParent.top;
m_nDockBarID = AFX_IDW_DOCKBAR_TOP;
break;
case CBRS_ALIGN_BOTTOM:
rectDockBar.top = rectParent.bottom;
m_nDockBarID = AFX_IDW_DOCKBAR_BOTTOM;
break;
}
m_dwBCGStyle = dwBCGStyle;
m_pDockSite = pParentWnd;
return CWnd::CreateEx (dwStyleEx, strClassName, NULL, dwStyle, rectDockBar, pParentWnd, m_nDockBarID, pContext);
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::AlignDockBar (const CRect& rectToAlignBy, CRect& rectResult,
BOOL bMoveImmediately)
{
ASSERT_VALID (this);
if (rectResult.IsRectEmpty ())
{
GetWindowRect (rectResult);
}
CRect rectOld;
GetWindowRect (rectOld);
int nCurrWidth = rectResult.Width ();
int nCurrHeight = rectResult.Height ();
switch (GetCurrentAlignment ())
{
case CBRS_ALIGN_LEFT:
rectResult.TopLeft () = rectToAlignBy.TopLeft ();
rectResult.bottom = rectResult.top + rectToAlignBy.Height ();
rectResult.right = rectResult.left + nCurrWidth;
break;
case CBRS_ALIGN_TOP:
rectResult.TopLeft () = rectToAlignBy.TopLeft ();
rectResult.right = rectResult.left + rectToAlignBy.Width ();
rectResult.bottom = rectResult.top + nCurrHeight;
break;
case CBRS_ALIGN_RIGHT:
rectResult.BottomRight () = rectToAlignBy.BottomRight ();
rectResult.top = rectResult.bottom - rectToAlignBy.Height ();
rectResult.left = rectResult.right - nCurrWidth;
break;
case CBRS_ALIGN_BOTTOM:
rectResult.BottomRight () = rectToAlignBy.BottomRight ();
rectResult.left = rectResult.right - rectToAlignBy.Width ();
rectResult.top = rectResult.bottom - nCurrHeight;
break;
}
if (rectResult != rectOld && bMoveImmediately)
{
CRect rectNew = rectResult;
ASSERT_VALID (GetParent ());
GetParent ()->ScreenToClient (rectNew);
OnSetWindowPos (&wndBottom, rectNew, SWP_NOACTIVATE | SWP_NOZORDER);
}
}
//----------------------------------------------------------------------------------//
// Moves control bar within row; floats the bar or moves it to an adjustent row
// if the bar' virtual rectangle is being moved out of row beyond a limit
//----------------------------------------------------------------------------------//
BOOL CBCGPDockBar::MoveControlBar (CBCGPControlBar* pControlBar, UINT /*nFlags*/,
CPoint ptOffset)
{
ASSERT_VALID (this);
ASSERT_VALID (pControlBar);
CBCGPDockBarRow* pRow = pControlBar->GetDockBarRow ();
ASSERT_VALID (pRow);
CRect rectVirtual;
pControlBar->GetVirtualRect (rectVirtual);
// where the virtual rectangle will be if it's moved according to ptOffset
rectVirtual.OffsetRect (ptOffset);
CPoint ptMouse;
GetCursorPos (&ptMouse);
CRect rectRow;
pRow->GetWindowRect (rectRow);
CPoint ptDelta (0, 0);
// check whether the control bar should change its state from docked to floated
CBCGPBaseControlBar* pDockBar = NULL;
if (pControlBar->IsChangeState (15, &pDockBar))
{
pControlBar->UpdateVirtualRect (ptOffset);
pControlBar->GetVirtualRect (rectVirtual);
pControlBar->FloatControlBar (rectVirtual, DM_MOUSE);
return TRUE; // indicates that the bar was floated and shouldn't be moved anymore within the dock bar
}
bool bOuterRow = false;
CBCGPDockBarRow* pNextRow = RowFromPoint (rectVirtual.CenterPoint (), bOuterRow);
int nBaseLineOffset = 0;
int nOffsetLimit = 0;
if (IsHorizontal ())
{
nBaseLineOffset = min (rectRow.bottom - rectVirtual.bottom, rectRow.top - rectVirtual.top);
nOffsetLimit = rectVirtual.Height () * 2 / 3; // / 2;
}
else
{
nBaseLineOffset = min (rectRow.right - rectVirtual.right, rectRow.left - rectVirtual.left);
nOffsetLimit = rectVirtual.Width () * 2 /3 ; // / 2;
}
if (abs (nBaseLineOffset) > nOffsetLimit)
{
if (pRow->GetBarCount () > 1 && nBaseLineOffset < pRow->GetRowHeight ())
{
// the bar should be put on the separate row, find a position to insert the row
POSITION pos = m_lstDockBarRows.Find (pRow);
ASSERT (pos != NULL);
if (nBaseLineOffset < 0) // moving down - find the next visible row
{
// the new row should be inserted before next visible row
FindNextVisibleRow (pos);
}
// otherwise the new row will be inserted before the current row
// (that's visible for sure) by AddRow (it inserts a row before spec. pos).
pRow->RemoveControlBar (pControlBar);
CBCGPDockBarRow* pNewRow =
AddRow (pos, IsHorizontal () ? rectVirtual.Height () : rectVirtual.Width ());
pNewRow->AddControlBarFromRow (pControlBar, DM_MOUSE);
return FALSE;
}
else if (pRow != pNextRow && pNextRow != NULL)
{
ASSERT_VALID (pNextRow);
//the bar is moved from the separate row to adjustent row (if exist)
if (pRow->IsExclusiveRow ())
{
SwapRows (pNextRow, pRow);
}
else
{
if (pNextRow->IsExclusiveRow ())
{
SwapRows (pRow, pNextRow);
}
else
{
pRow->RemoveControlBar (pControlBar);
pNextRow->AddControlBarFromRow (pControlBar, DM_MOUSE);
}
}
pControlBar->m_bDisableMove = true;
return FALSE;
}
}
// just move the bar within the row
if (abs (nBaseLineOffset) < rectRow.Height ())
{
HDWP hdwp = BeginDeferWindowPos (pRow->GetBarCount ());
pRow->MoveControlBar (pControlBar, ptOffset, TRUE, hdwp);
EndDeferWindowPos (hdwp);
return FALSE;
}
return FALSE;
}
//----------------------------------------------------------------------------------//
CBCGPDockBarRow* CBCGPDockBar::FindNextVisibleRow (POSITION& pos, BOOL bForward)
{
if (m_lstDockBarRows.IsEmpty ())
{
pos = NULL;
return NULL;
}
if (pos == NULL)
{
pos = bForward ? m_lstDockBarRows.GetHeadPosition ()
: m_lstDockBarRows.GetTailPosition ();
}
else
{
// we need to skip to the next / prev row from the current position
bForward ? m_lstDockBarRows.GetNext (pos) : m_lstDockBarRows.GetPrev (pos);
}
while (pos != NULL)
{
POSITION posSave = pos;
CBCGPDockBarRow* pRow = (CBCGPDockBarRow*)
(bForward ? m_lstDockBarRows.GetNext (pos)
: m_lstDockBarRows.GetPrev (pos));
ASSERT_VALID (pRow);
if (pRow->IsVisible ())
{
pos = posSave;
return pRow;
}
}
return NULL;
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType)
{
ASSERT_VALID (this);
CWnd::CalcWindowRect(lpClientRect, nAdjustType);
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::DockControlBar (CBCGPControlBar* pControlBar, BCGP_DOCK_METHOD dockMethod,
LPCRECT lpRect)
{
ASSERT_VALID (this);
ASSERT_VALID (pControlBar);
CRect rectDockArea; rectDockArea.SetRectEmpty ();
if (lpRect != NULL)
{
rectDockArea = lpRect;
}
BOOL bVertDock = !IsHorizontal ();
CSize szBarSize = pControlBar->CalcFixedLayout (FALSE, !bVertDock);
if (!m_lstControlBars.Find (pControlBar))
{
CBCGPDockBarRow* pRowToDock = NULL;
bool bOuterRow = false;
if (dockMethod == DM_MOUSE)
{
// calculate from which side the control bar is coming, using mouse cursor position.
// the default bar width (for side bars) and height (for top/bottom bars)
// is 30 for this example
CPoint ptMouse;
GetCursorPos (&ptMouse);
CRect rectDockBar;
GetWindowRect (&rectDockBar);
// get pointer to the row on which the bar should be placed
pRowToDock = RowFromPoint (ptMouse, bOuterRow);
}
else if (dockMethod == DM_DBL_CLICK || dockMethod == DM_RECT)
{
if (dockMethod == DM_DBL_CLICK &&
m_lstDockBarRows.Find (pControlBar->m_recentDockInfo.m_pRecentDockBarRow) != NULL)
{
pRowToDock = pControlBar->m_recentDockInfo.m_pRecentDockBarRow;
}
else
{
int nRowCount = m_lstDockBarRows.GetCount ();
if (CBCGPDockManager::m_bRestoringDockState)
{
if (pControlBar->m_recentDockInfo.m_nRecentRowIndex > nRowCount - 1)
{
for (int i = 0;
i < pControlBar->m_recentDockInfo.m_nRecentRowIndex - nRowCount + 1; i++)
{
AddRow (NULL, bVertDock ? szBarSize.cx : szBarSize.cy);
}
}
POSITION posRow = m_lstDockBarRows.FindIndex (pControlBar->m_recentDockInfo.m_nRecentRowIndex);
pRowToDock = (CBCGPDockBarRow*) m_lstDockBarRows.GetAt (posRow);
}
else
{
if (pControlBar->m_recentDockInfo.m_nRecentRowIndex < nRowCount &&
dockMethod == DM_DBL_CLICK)
{
POSITION pos = m_lstDockBarRows.FindIndex (pControlBar->m_recentDockInfo.m_nRecentRowIndex);
pRowToDock = (CBCGPDockBarRow*) m_lstDockBarRows.GetAt (pos);
}
else if (dockMethod == DM_DBL_CLICK &&
!pControlBar->m_recentDockInfo.m_recentSliderInfo.m_rectDockedRect.IsRectEmpty ())
{
pRowToDock = FindRowByRect (pControlBar->m_recentDockInfo.m_recentSliderInfo.m_rectDockedRect);
}
else if (dockMethod == DM_RECT && lpRect != NULL)
{
pRowToDock = FindRowByRect (lpRect);
}
}
if (pRowToDock == NULL)
{
AddRow (NULL, bVertDock ? szBarSize.cx : szBarSize.cy);
pRowToDock = (CBCGPDockBarRow*) m_lstDockBarRows.GetTail ();
}
}
ASSERT_VALID (pRowToDock);
rectDockArea = &pControlBar->m_recentDockInfo.m_recentSliderInfo.m_rectDockedRect;
ClientToScreen (rectDockArea);
}
// if the bar is being placed on the exclusive row
// (with menu bar, for example) we should create a new row, put the
// bar on new row and put this row after/before the exclusive row
POSITION posSwapRow = NULL;
if (pRowToDock != NULL && pRowToDock->IsExclusiveRow () ||
pRowToDock != NULL && !pControlBar->DoesAllowSiblingBars () &&
!pRowToDock->IsEmpty ())
{
posSwapRow = m_lstDockBarRows.Find (pRowToDock);
ASSERT (posSwapRow != NULL);
pRowToDock = NULL;
}
if (pRowToDock == NULL)
{
POSITION posNewBar = NULL;
if (posSwapRow != NULL)
{
// the bar is inserted before the specified position in AddRow
posNewBar = posSwapRow;
if (!bOuterRow)
{
m_lstDockBarRows.GetNext (posNewBar);
}
}
else
{
posNewBar = bOuterRow ? m_lstDockBarRows.GetHeadPosition () : NULL;
}
pRowToDock = AddRow (posNewBar, bVertDock ? szBarSize.cx : szBarSize.cy);
}
ASSERT_VALID (pRowToDock);
// the bar should be placed on the existing row or new row
pRowToDock->AddControlBar (pControlBar, dockMethod, rectDockArea);
// if the bar suudently changed its size we need to resize the row again
CSize sizeBarNew = pControlBar->CalcFixedLayout (FALSE, !bVertDock);
if (sizeBarNew != szBarSize)
{
ResizeRow (pRowToDock, bVertDock ? sizeBarNew.cx : sizeBarNew.cy);
}
m_lstControlBars.AddTail (pControlBar);
AdjustDockingLayout ();
ShowWindow (SW_SHOW);
}
}
//----------------------------------------------------------------------------------//
CBCGPDockBarRow* CBCGPDockBar::FindRowByRect (CRect rectRow)
{
bool b;
CPoint pt = rectRow.TopLeft ();
ClientToScreen (&pt);
return RowFromPoint (pt, b);
}
//----------------------------------------------------------------------------------//
BOOL CBCGPDockBar::DockControlBarLeftOf (CBCGPControlBar* pBarToDock,
CBCGPControlBar* pTargetBar)
{
ASSERT_VALID (this);
ASSERT_VALID (pBarToDock);
ASSERT_VALID (pTargetBar);
CBCGPDockBarRow* pTargetRow = RowFromControlBar (pTargetBar);
if (pTargetRow == NULL)
{
return FALSE;
}
CRect rectTargetBar;
pTargetBar->GetWindowRect (rectTargetBar);
ScreenToClient (rectTargetBar);
BOOL bVertDock = !IsHorizontal ();
CSize szBarSize = pBarToDock->CalcFixedLayout (FALSE, !bVertDock);
CRect rectFinal;
if (IsHorizontal ())
{
rectFinal.SetRect (rectTargetBar.left - szBarSize.cx - 10,
rectTargetBar.top, rectTargetBar.left - 10, rectTargetBar.bottom);
}
else
{
rectFinal.SetRect (rectTargetBar.left,
rectTargetBar.top - szBarSize.cy - 10,
rectTargetBar.right, rectTargetBar.top - 10);
}
pBarToDock->PrepareToDock (this, DM_RECT);
ClientToScreen (rectFinal);
pTargetRow->m_bIgnoreBarVisibility = TRUE;
pTargetRow->AddControlBar (pBarToDock, DM_RECT, &rectFinal);
POSITION pos = m_lstControlBars.Find (pTargetBar);
ASSERT (pos != NULL);
m_lstControlBars.InsertBefore (pos, pBarToDock);
AdjustDockingLayout ();
FixupVirtualRects ();
pTargetRow->m_bIgnoreBarVisibility = FALSE;
return TRUE;
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::RemoveControlBar (CBCGPControlBar* pControlBar, BCGP_DOCK_METHOD /*dockMethod*/)
{
ASSERT_VALID (this);
ASSERT_VALID (pControlBar);
if (!m_lstControlBars.IsEmpty ())
{
POSITION pos = m_lstControlBars.Find (pControlBar);
if (pos != NULL)
{
m_lstControlBars.RemoveAt (pos);
// we need to reposition bars according to the new situation
// 1. expand bars that were stretched due to presence of this bar
// 2. remove empty rows
CBCGPDockBarRow* pRow = pControlBar->GetDockBarRow ();
if (pRow != NULL)
{
pRow->RemoveControlBar (pControlBar);
}
}
}
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::FixupVirtualRects ()
{
ASSERT_VALID (this);
for (POSITION pos = m_lstDockBarRows.GetHeadPosition (); pos != NULL;)
{
CBCGPDockBarRow* pNextRow = (CBCGPDockBarRow*) m_lstDockBarRows.GetNext (pos);
ASSERT_VALID (pNextRow);
pNextRow->FixupVirtualRects (false);
}
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::RepositionBars (CRect& rectNewClientArea)
{
ASSERT_VALID (this);
CRect rectOldArea;
GetClientRect (rectOldArea);
CSize sizeNew = rectNewClientArea.Size ();
CSize sizeOld = rectOldArea.Size ();
if (sizeNew != sizeOld)
{
int nHorzOffset = sizeNew.cx - sizeOld.cx;
int nVertOffset = sizeNew.cy - sizeOld.cy;
for (POSITION pos = m_lstDockBarRows.GetHeadPosition (); pos != NULL;)
{
CBCGPDockBarRow* pNextRow = (CBCGPDockBarRow*) m_lstDockBarRows.GetNext (pos);
ASSERT_VALID (pNextRow);
if (nHorzOffset != 0)
{
pNextRow->RepositionBars (rectNewClientArea, WMSZ_RIGHT, nHorzOffset > 0, abs (nHorzOffset));
}
if (nVertOffset != 0)
{
pNextRow->RepositionBars (rectNewClientArea, WMSZ_BOTTOM, nVertOffset > 0, abs (nVertOffset));
}
}
}
else
{
// sanity check
for (POSITION pos = m_lstDockBarRows.GetHeadPosition (); pos != NULL;)
{
CBCGPDockBarRow* pNextRow = (CBCGPDockBarRow*) m_lstDockBarRows.GetNext (pos);
ASSERT_VALID (pNextRow);
pNextRow->ExpandStretchedBarsRect ();
}
}
}
//----------------------------------------------------------------------------------//
CBCGPDockBarRow* CBCGPDockBar::CreateRow (CBCGPDockBar* /*pParentDocBar*/, int nOffset, int nRowHeight)
{
ASSERT_VALID (this);
CBCGPDockBarRow* pRow = new CBCGPDockBarRow (this, nOffset, nRowHeight);
if (!pRow->Create ())
{
delete pRow;
return NULL;
}
return pRow;
}
//----------------------------------------------------------------------------------//
CBCGPDockBarRow* CBCGPDockBar::AddRow (POSITION posRowBefore, int nRowHeight)
{
ASSERT_VALID (this);
// claculate the row offset
int nOffset = 0;
for (POSITION pos = m_lstDockBarRows.GetHeadPosition (); pos != posRowBefore;)
{
CBCGPDockBarRow* pNextRow = (CBCGPDockBarRow*) m_lstDockBarRows.GetNext (pos);
ASSERT_VALID (pNextRow);
if (pNextRow->IsVisible ())
{
nOffset += pNextRow->GetRowHeight ();
}
}
ResizeDockBarByOffset (nRowHeight);
CBCGPDockBarRow* pNewRow = CreateRow (this, nOffset, nRowHeight);
if (pNewRow == NULL)
{
ASSERT (FALSE);
return NULL;
}
if (posRowBefore != NULL)
{
POSITION pos = m_lstDockBarRows.InsertBefore (posRowBefore, pNewRow);
OnInsertRow (pos);
}
else
{
m_lstDockBarRows.AddTail (pNewRow);
}
return pNewRow;
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::RemoveRow (CBCGPDockBarRow* pRow)
{
ASSERT_VALID (this);
ASSERT_VALID (pRow);
ASSERT (!m_lstDockBarRows.IsEmpty ());
int nRowHeight = pRow->GetRowHeight ();
if (pRow->IsVisible ())
{
ResizeDockBarByOffset (-nRowHeight);
}
POSITION pos = m_lstDockBarRows.Find (pRow);
if (pos != NULL)
{
OnRemoveRow (pos);
m_lstDockBarRows.RemoveAt (pos);
delete pRow;
}
}
//----------------------------------------------------------------------------------//
int CBCGPDockBar::ResizeRow (CBCGPDockBarRow* pRow, int nNewSize, BOOL bAdjustLayout)
{
ASSERT_VALID (this);
ASSERT_VALID (pRow);
int nOffset = nNewSize - pRow->GetRowHeight ();
if (nOffset < 0 && !pRow->IsEmpty ())
{
CSize size = pRow->CalcFixedLayout (TRUE, IsHorizontal ());
if (IsHorizontal () && nNewSize - size.cy < 0 ||
!IsHorizontal () && nNewSize - size.cx < 0)
{
return 0;
}
}
int nActualOffset = OnResizeRow (pRow, nOffset);
ResizeDockBarByOffset (nActualOffset, bAdjustLayout);
return nActualOffset;
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::ShowRow (CBCGPDockBarRow* pRow, BOOL bShow, BOOL bAdjustLayout)
{
ASSERT_VALID (this);
ASSERT_VALID (pRow);
ASSERT (!m_lstDockBarRows.IsEmpty ());
POSITION pos = m_lstDockBarRows.Find (pRow);
OnShowRow (pos, bShow);
int nRowHeight = pRow->GetRowHeight ();
ResizeDockBarByOffset (bShow ? nRowHeight : -nRowHeight, bAdjustLayout);
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::OnInsertRow (POSITION pos)
{
ASSERT_VALID (this);
ASSERT (pos != NULL);
CBCGPDockBarRow* pNewRow = (CBCGPDockBarRow*) m_lstDockBarRows.GetNext (pos);
ASSERT_VALID (pNewRow);
int nRowSize = pNewRow->GetRowHeight ();
// when the row is inserted, all control bars that belongs to the rows after new,
// should be moved down
while (pos != NULL)
{
CBCGPDockBarRow* pNextRow = (CBCGPDockBarRow*) m_lstDockBarRows.GetNext (pos);
ASSERT_VALID (pNextRow);
pNextRow->Move (nRowSize);
}
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::OnRemoveRow (POSITION pos, BOOL bByShow)
{
ASSERT_VALID (this);
ASSERT (pos != NULL);
CBCGPDockBarRow* pRowToRemove = (CBCGPDockBarRow*) m_lstDockBarRows.GetNext (pos);
ASSERT_VALID (pRowToRemove);
if (!pRowToRemove->IsVisible () && !bByShow)
{
return;
}
int nRowSize = pRowToRemove->GetRowHeight ();
while (pos != NULL)
{
CBCGPDockBarRow* pNextRow = (CBCGPDockBarRow*) m_lstDockBarRows.GetNext (pos);
ASSERT_VALID (pNextRow);
pNextRow->Move (-nRowSize);
}
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::OnShowRow (POSITION pos, BOOL bShow)
{
ASSERT_VALID (this);
ASSERT (pos != NULL);
bShow ? OnInsertRow (pos) : OnRemoveRow (pos, TRUE);
}
//----------------------------------------------------------------------------------//
int CBCGPDockBar::OnResizeRow (CBCGPDockBarRow* pRowToResize, int nOffset)
{
ASSERT_VALID (this);
ASSERT_VALID (pRowToResize);
int nActualOffset = pRowToResize->Resize (nOffset);
POSITION pos = m_lstDockBarRows.Find (pRowToResize);
m_lstDockBarRows.GetNext (pos);
// skip to next row
while (pos != NULL)
{
CBCGPDockBarRow* pNextRow = (CBCGPDockBarRow*) m_lstDockBarRows.GetNext (pos);
ASSERT_VALID (pNextRow);
pNextRow->Move (nActualOffset);
}
return nActualOffset;
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::SwapRows (CBCGPDockBarRow* pFirstRow, CBCGPDockBarRow* pSecondRow)
{
POSITION posFirstRow = m_lstDockBarRows.Find (pFirstRow);
POSITION posSecondRow = m_lstDockBarRows.Find (pSecondRow);
ASSERT (posFirstRow != NULL);
ASSERT (posSecondRow != NULL);
POSITION posTmp = posFirstRow;
FindNextVisibleRow (posTmp);
bool bSwapDown = (posTmp == posSecondRow);
if (!bSwapDown)
{
posTmp = posFirstRow;
FindNextVisibleRow (posTmp, FALSE);
if (posTmp != posSecondRow)
{
return;
}
}
m_lstDockBarRows.InsertAfter (posFirstRow, pSecondRow);
m_lstDockBarRows.InsertAfter (posSecondRow, pFirstRow);
m_lstDockBarRows.RemoveAt (posFirstRow);
m_lstDockBarRows.RemoveAt (posSecondRow);
int nRowHeight = pFirstRow->GetRowHeight ();
pSecondRow->Move (bSwapDown ? -nRowHeight : nRowHeight);
nRowHeight = pSecondRow->GetRowHeight ();
pFirstRow->Move (bSwapDown ? nRowHeight : -nRowHeight);
FixupVirtualRects ();
}
//----------------------------------------------------------------------------------//
CBCGPDockBarRow* CBCGPDockBar::RowFromPoint (CPoint pt, bool& bOuterRow) const
{
ASSERT_VALID (this);
bOuterRow = false;
CRect rectRow;
for (POSITION pos = m_lstDockBarRows.GetHeadPosition (); pos != NULL;)
{
CBCGPDockBarRow* pRow = (CBCGPDockBarRow*) m_lstDockBarRows.GetNext (pos);
ASSERT_VALID (pRow);
if (!pRow->IsVisible ())
{
continue;
}
pRow->GetWindowRect (rectRow);
if (rectRow.PtInRect (pt))
{
return pRow;
}
}
CRect rectWnd;
GetWindowRect (&rectWnd);
if (IsHorizontal () && pt.y < rectWnd.top ||
!IsHorizontal () && pt.x < rectWnd.left)
{
bOuterRow = true;
}
return NULL;
}
//----------------------------------------------------------------------------------//
CBCGPDockBarRow* CBCGPDockBar::RowFromControlBar (CBCGPBaseControlBar* pBar) const
{
ASSERT_VALID (this);
ASSERT_VALID (pBar);
for (POSITION pos = m_lstDockBarRows.GetHeadPosition (); pos != NULL;)
{
CBCGPDockBarRow* pRow = (CBCGPDockBarRow*) m_lstDockBarRows.GetNext (pos);
ASSERT_VALID (pRow);
if (pRow->HasControlBar (pBar) != NULL)
{
return pRow;
}
}
return NULL;
}
//----------------------------------------------------------------------------------//
BOOL CBCGPDockBar::ShowControlBar (CBCGPBaseControlBar* pBar, BOOL bShow, BOOL bDelay, BOOL bActivate)
{
CBCGPDockBarRow* pRow = RowFromControlBar (pBar);
if (pRow != NULL)
{
CBCGPControlBar* pBarToShow = DYNAMIC_DOWNCAST (CBCGPControlBar, pBar);
// allows to show/hide only CBCGPControlBar-derived bars (other bars
// has no docking abilitty)
if (pBarToShow != NULL)
{
return pRow->ShowControlBar (pBarToShow, bShow, bDelay);
}
}
return FALSE;
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::ResizeDockBarByOffset (int nOffset, BOOL bAdjustLayout)
{
ASSERT_VALID (this);
CRect rect;
GetWindowRect (&rect);
GetParent ()->ScreenToClient (&rect);
switch (GetCurrentAlignment ())
{
case CBRS_ALIGN_LEFT:
rect.right += nOffset;
break;
case CBRS_ALIGN_RIGHT:
rect.left -= nOffset;
break;
case CBRS_ALIGN_TOP:
rect.bottom += nOffset;
break;
case CBRS_ALIGN_BOTTOM:
rect.top -= nOffset;
break;
}
MoveWindow (rect);
if (bAdjustLayout)
{
AdjustDockingLayout ();
}
}
//----------------------------------------------------------------------------------//
bool CBCGPDockBar::IsLastRow (CBCGPDockBarRow* pRow) const
{
ASSERT_VALID (this);
return (!m_lstDockBarRows.IsEmpty () &&
(pRow == m_lstDockBarRows.GetHead () ||
pRow == m_lstDockBarRows.GetTail ()));
}
//----------------------------------------------------------------------------------//
CSize CBCGPDockBar::CalcFixedLayout (BOOL bStretch, BOOL bHorz)
{
ASSERT_VALID (this);
int nTotalHeightRequired = 0;
BOOL bHorzBar = IsHorizontal ();
for (POSITION pos = m_lstDockBarRows.GetHeadPosition (); pos != NULL;)
{
CBCGPDockBarRow* pNextRow = (CBCGPDockBarRow*) m_lstDockBarRows.GetNext (pos);
ASSERT_VALID (pNextRow);
if (!pNextRow->IsVisible ())
{
continue;
}
int nCurrHeight = pNextRow->GetRowHeight ();
CSize sizeRowRequired = pNextRow->CalcFixedLayout (bStretch, bHorz);
int nHeightRequired = bHorzBar ? sizeRowRequired.cy : sizeRowRequired.cx;
if (nHeightRequired != nCurrHeight && nHeightRequired > 0)
{
ResizeRow (pNextRow, nHeightRequired, FALSE);
}
nTotalHeightRequired += nHeightRequired;
}
CRect rectWnd;
GetWindowRect (rectWnd);
return rectWnd.Size ();
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::ResizeDockBar (int nNewWidth, int nNewHeight) // not called from anywhere !!!
{
ASSERT_VALID (this);
CWnd* pParentWnd = GetParent ();
ASSERT_VALID (pParentWnd);
CRect rectDockBar;
GetClientRect (&rectDockBar);
MapWindowPoints (pParentWnd, &rectDockBar);
switch (GetCurrentAlignment ())
{
case CBRS_ALIGN_LEFT:
if (nNewHeight != -1)
{
rectDockBar.bottom = rectDockBar.top + nNewHeight;
}
break;
case CBRS_ALIGN_RIGHT:
if (nNewHeight != -1)
{
rectDockBar.bottom = rectDockBar.top + nNewHeight;
}
break;
case CBRS_ALIGN_TOP:
if (nNewWidth != -1)
{
rectDockBar.right = rectDockBar.left + nNewWidth;
}
break;
case CBRS_ALIGN_BOTTOM:
if (nNewWidth != -1)
{
rectDockBar.right = rectDockBar.left + nNewWidth;
}
break;
}
OnSetWindowPos (&wndBottom, rectDockBar, SWP_NOACTIVATE | SWP_NOZORDER);
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::OnPaint()
{
CPaintDC dc(this); // device context for painting
}
//----------------------------------------------------------------------------------//
BOOL CBCGPDockBar::IsRectWithinDockBar (CRect rect, CPoint& ptDelta)
{
ASSERT_VALID (this);
CRect rectWnd;
GetWindowRect (&rectWnd);
ptDelta.x = ptDelta.y = 0;
if (IsHorizontal ())
{
if (rect.left < rectWnd.left)
{
ptDelta.x = rectWnd.left - rect.left;
return FALSE;
}
if (rect.right > rectWnd.right)
{
ptDelta.x = rectWnd.right - rect.right;
return FALSE;
}
}
else
{
if (rect.top < rectWnd.top)
{
ptDelta.y = rectWnd.top - rect.top;
return FALSE;
}
if (rect.bottom > rectWnd.bottom)
{
ptDelta.y = rect.bottom - rectWnd.bottom;
return FALSE;
}
}
return TRUE;
}
//----------------------------------------------------------------------------------//
BOOL CBCGPDockBar::CanAcceptBar (const CBCGPBaseControlBar* pBar) const
{
ASSERT_VALID (this);
if (pBar == NULL)
{
ASSERT (FALSE);
return FALSE;
}
return !IsResizable ();
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::OnSize(UINT nType, int cx, int cy)
{
ASSERT_VALID (this);
CWnd::OnSize(nType, cx, cy);
}
//----------------------------------------------------------------------------------//
CBCGPControlBar* CBCGPDockBar::ControlBarFromPoint (CPoint pt)
{
ASSERT_VALID (this);
CRect rectBar;
CBCGPControlBar* pBar = NULL;
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
pBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pBar);
pBar->GetWindowRect (rectBar);
if (rectBar.PtInRect (pt))
{
return pBar;
}
}
return NULL;
}
//----------------------------------------------------------------------------------//
int CBCGPDockBar::RectSideFromPoint (const CRect& rect, const CPoint& point)
{
int nDeltaLeft = point.x - rect.left;
int nDeltaTop = point.y - rect.top;
int nDeltaRight = rect.right - point.x;
int nDeltaBottom = rect.bottom - point.y;
// use hit test definition to describe the side
UINT nHitTestLR = (nDeltaLeft <= nDeltaRight) ? HTLEFT : HTRIGHT;
UINT nHitTetsTB = (nDeltaTop <= nDeltaBottom) ? HTTOP : HTBOTTOM;
int nHitTest = HTERROR;
if (nHitTestLR == HTLEFT && nHitTetsTB == HTTOP)
{
nHitTest = (nDeltaLeft <= nDeltaTop) ? HTLEFT : HTTOP;
}
else if (nHitTestLR == HTRIGHT && nHitTetsTB == HTTOP)
{
nHitTest = (nDeltaRight <= nDeltaTop) ? HTRIGHT : HTTOP;
}
else if (nHitTestLR == HTLEFT && nHitTetsTB == HTBOTTOM)
{
nHitTest = (nDeltaLeft <= nDeltaBottom) ? HTLEFT : HTBOTTOM;
}
else if (nHitTestLR == HTRIGHT && nHitTetsTB == HTBOTTOM)
{
nHitTest = (nDeltaRight <= nDeltaBottom) ? HTRIGHT : HTBOTTOM;
}
else
{
return HTERROR;
}
return nHitTest;
}
//----------------------------------------------------------------------------------//
BOOL CBCGPDockBar::ReplaceControlBar (CBCGPControlBar* pOldBar, CBCGPControlBar* pNewBar)
{
ASSERT_VALID (this);
POSITION pos = m_lstControlBars.Find (pOldBar);
if (pos != NULL)
{
m_lstControlBars.InsertAfter (pos, pNewBar);
m_lstControlBars.RemoveAt (pos);
return TRUE;
}
return FALSE;
}
//----------------------------------------------------------------------------------//
BOOL CBCGPDockBar::OnSetWindowPos (const CWnd* pWndInsertAfter,
const CRect& rectWnd, UINT nFlags)
{
ASSERT_VALID (this);
return (BOOL)SetWindowPos (pWndInsertAfter,
rectWnd.left, rectWnd.top, rectWnd.Width (), rectWnd.Height (),
nFlags | SWP_NOACTIVATE);
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::OnNcDestroy()
{
CWnd::OnNcDestroy();
delete this;
}
//----------------------------------------------------------------------------------//
BOOL CBCGPDockBar::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetClientRect (rect);
CBCGPVisualManager::GetInstance ()->OnFillBarBackground (pDC, this, rect, rect, FALSE);
return TRUE;
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::AdjustLayout ()
{
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPBaseControlBar* pBar = (CBCGPBaseControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pBar);
pBar->AdjustLayout ();
}
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::AdjustDockingLayout ()
{
ASSERT_VALID (this);
CWnd* pParent = GetParent ();
ASSERT_VALID (pParent);
if (pParent->IsKindOf (RUNTIME_CLASS (CBCGPFrameWnd)))
{
((CBCGPFrameWnd*) pParent)->AdjustDockingLayout ();
}
else if (pParent->IsKindOf (RUNTIME_CLASS (CBCGPMDIFrameWnd)))
{
((CBCGPMDIFrameWnd*) pParent)->AdjustDockingLayout (NULL);
}
else if (pParent->IsKindOf (RUNTIME_CLASS (CBCGPOleIPFrameWnd)))
{
((CBCGPOleIPFrameWnd*) pParent)->AdjustDockingLayout ();
}
else if (pParent->IsKindOf (RUNTIME_CLASS (CBCGPOleDocIPFrameWnd)))
{
((CBCGPOleDocIPFrameWnd*) pParent)->AdjustDockingLayout ();
}
else if (pParent->IsKindOf (RUNTIME_CLASS (CBCGPOleCntrFrameWnd)))
{
((CBCGPOleCntrFrameWnd*) pParent)->AdjustDockingLayout ();
}
else if (pParent->IsKindOf (RUNTIME_CLASS (CBCGPMDIChildWnd)))
{
((CBCGPMDIChildWnd*) pParent)->AdjustDockingLayout ();
}
else if (pParent->IsKindOf (RUNTIME_CLASS (CDialog)))
{
globalUtils.m_bDialogApp = TRUE;
}
}
//----------------------------------------------------------------------------------//
int CBCGPDockBar::FindRowIndex (CBCGPDockBarRow* pRow)
{
ASSERT_VALID (this);
if (pRow == NULL)
{
return 0;
}
int nIndex = 0;
for (POSITION pos = m_lstDockBarRows.GetHeadPosition (); pos != NULL; nIndex++)
{
CBCGPDockBarRow* pNextRow = (CBCGPDockBarRow*) m_lstDockBarRows.GetNext (pos);
if (pNextRow == pRow)
{
return nIndex;
}
}
return 0;
}
//----------------------------------------------------------------------------------//
void CBCGPDockBar::OnContextMenu(CWnd* pWnd, CPoint point)
{
if (!CBCGPToolBar::IsCustomizeMode () && !IsDragMode ())
{
CFrameWnd* pParentFrame = BCGCBProGetTopLevelFrame (this);
if (pParentFrame == NULL)
{
ASSERT (FALSE);
return;
}
ASSERT_VALID(pParentFrame);
pParentFrame->SendMessage (BCGM_TOOLBARMENU,
(WPARAM) NULL,
MAKELPARAM(point.x, point.y));
}
}
//----------------------------------------------------------------------------------//
BOOL CBCGPDockBar::IsDragMode () const
{
ASSERT_VALID (this);
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pBar = DYNAMIC_DOWNCAST
(CBCGPControlBar, m_lstControlBars.GetNext (pos));
if (pBar == NULL)
{
continue;
}
if (pBar->IsDragMode ())
{
return TRUE;
}
}
return FALSE;
}
//----------------------------------------------------------------------------------//
CBCGPControlBar* CBCGPDockBar::FindBarByID (UINT nID)
{
ASSERT_VALID (this);
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pBar);
if (pBar->GetDlgCtrlID () == (int) nID)
{
return pBar;
}
//-----------------
// Check for rebar:
//-----------------
CBCGPReBar* pRebar = DYNAMIC_DOWNCAST (CBCGPReBar, pBar);
if (pRebar != NULL)
{
ASSERT_VALID(pRebar);
CBCGPControlBar* pBarPane = DYNAMIC_DOWNCAST(CBCGPControlBar,
pRebar->GetDlgItem (nID));
if (pBarPane != NULL)
{
return pBarPane;
}
}
}
return NULL;
}
void CBCGPDockBar::OnDestroy()
{
RemoveControlBarFromDockManager (this, FALSE);
CBCGPBaseControlBar::OnDestroy();
}