www.pudn.com > ÍøÂç¶Ë¿Ú¼àÊÓ.rar > BCGPDockBarRow.cpp
// BCGPDockBarRow.cpp: implementation of the CBCGPDockBarRow class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "BCGPControlBar.h"
#include "BCGPDockBar.h"
#include "BCGPDockBarRow.h"
#include "BCGPAutoHideButton.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
IMPLEMENT_DYNAMIC(CBCGPDockBarRow, CObject)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBCGPDockBarRow::CBCGPDockBarRow (CBCGPDockBar* pParentDockBar, int nOffset, int nHeight) :
m_pParentDockBar (pParentDockBar), m_nRowOffset (nOffset),
m_nRowHeight (nHeight)
{
ASSERT_VALID (pParentDockBar);
m_dwRowAlignment = pParentDockBar->GetCurrentAlignment ();
m_nMinHeight = 0;
m_nExtraSpace = 0;
m_nExtraAlignment = BCGP_ROW_ALIGN_TOP;
m_bVisible = TRUE;
m_nRowSavedHeight = 0;
m_bIgnoreBarVisibility = FALSE;
}
//**********************************************************************************************
CBCGPDockBarRow::~CBCGPDockBarRow ()
{
}
//**********************************************************************************************
void CBCGPDockBarRow::AddControlBar (CBCGPControlBar* pControlBar, BCGP_DOCK_METHOD dockMethod,
LPCRECT lpRect, BOOL bAddLast)
{
ASSERT_VALID (this);
ASSERT_VALID (pControlBar);
CRect rectRow;
CPoint ptOffset (0, 0);
if (lpRect != NULL && !IsRectEmpty (lpRect))
{
CRect rectDockBar;
m_pParentDockBar->GetClientRect (&rectDockBar);
GetWindowRect (rectRow);
if (IsHorizontal ())
{
ptOffset.x = lpRect->left - rectRow.left;
ptOffset.y = rectDockBar.top + m_nRowOffset;
}
else
{
ptOffset.x = rectDockBar.left + m_nRowOffset;
ptOffset.y = lpRect->top - rectRow.top;
}
}
else
{
int nAdditionalBarOffset = 0;
if (bAddLast)
{
nAdditionalBarOffset = CalcLastBarOffset ();
if (nAdditionalBarOffset > 0)
{
nAdditionalBarOffset += globalData.m_nAutoHideToolBarSpacing;
}
}
GetClientRect (rectRow);
if (IsHorizontal ())
{
ptOffset.x = rectRow.left + nAdditionalBarOffset;
ptOffset.y = m_nRowOffset;
// align the bar to the bottom of the row
if (m_nExtraAlignment == BCGP_ROW_ALIGN_BOTTOM)
{
ptOffset.y += m_nExtraSpace;
}
}
else
{
ptOffset.x = m_nRowOffset;
ptOffset.y = rectRow.top + nAdditionalBarOffset;
// align the bar to the right side of the row
if (m_nExtraAlignment == BCGP_ROW_ALIGN_BOTTOM)
{
ptOffset.x += m_nExtraSpace;
}
}
}
CSize szBarSize = pControlBar->CalcFixedLayout (FALSE, IsHorizontal ());
pControlBar->SetWindowPos (NULL, ptOffset.x, ptOffset.y, szBarSize.cx, szBarSize.cy,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
OnInsertControlBar (pControlBar);
pControlBar->UpdateVirtualRect ();
}
//**********************************************************************************************
void CBCGPDockBarRow::AddControlBarFromRow (CBCGPControlBar* pControlBar, BCGP_DOCK_METHOD dockMethod)
{
ASSERT_VALID (this);
ASSERT_VALID (pControlBar);
CRect rectWnd;
pControlBar->GetWindowRect (&rectWnd);
int nOffsetOnRow = 0;
if (dockMethod == DM_MOUSE)
{
// position the bar at the mouse cursor
CPoint ptMouse;
GetCursorPos (&ptMouse);
m_pParentDockBar->ScreenToClient (&ptMouse);
CPoint ptHot = pControlBar->GetClientHotSpot ();
// take the grippers and borders int account
CRect rectClient;
pControlBar->GetClientRect (rectClient);
pControlBar->ClientToScreen (rectClient);
int nNCOffset = rectClient.left - rectWnd.left;
nOffsetOnRow = IsHorizontal () ? ptMouse.x - ptHot.x - nNCOffset:
ptMouse.y - ptHot.y - nNCOffset;
}
else
{
m_pParentDockBar->ScreenToClient (&rectWnd);
nOffsetOnRow = IsHorizontal () ? rectWnd.left : rectWnd.top;
}
CRect rectPos;
if (IsHorizontal ())
{
rectPos.SetRect (nOffsetOnRow, m_nRowOffset, nOffsetOnRow + rectWnd.Width (), m_nRowOffset + rectWnd.Height ());
}
else
{
rectPos.SetRect (m_nRowOffset, nOffsetOnRow, m_nRowOffset + rectWnd.Width (), nOffsetOnRow + rectWnd.Height ());
}
pControlBar->SetWindowPos (NULL, rectPos.left, rectPos.top, rectPos.right, rectPos.bottom,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
OnInsertControlBar (pControlBar);
pControlBar->UpdateVirtualRect ();
}
//**********************************************************************************************
void CBCGPDockBarRow::OnInsertControlBar (CBCGPControlBar* pControlBar)
{
ASSERT_VALID (this);
ASSERT_VALID (pControlBar);
CRect rectBarWnd;
pControlBar->GetWindowRect (&rectBarWnd);
CBCGPControlBar* pPrevControlBar = NULL;
bool bWasInserted = false;
POSITION posSave = NULL;
// the existing bars are ordered from the left to right or from top to bottom
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
posSave = pos;
CBCGPControlBar* pBarWnd = DYNAMIC_DOWNCAST (CBCGPControlBar,
m_lstControlBars.GetNext (pos));
pPrevControlBar = pBarWnd;
ASSERT_VALID (pBarWnd);
// the new bar should be inserted before the next bar it is left of
bWasInserted = pBarWnd->IsLeftOf (rectBarWnd);
if (bWasInserted)
{
m_lstControlBars.InsertBefore (posSave, pControlBar);
break;
}
}
// if the bar wasn't inserted
if (!bWasInserted)
{
m_lstControlBars.AddTail (pControlBar);
}
UpdateVisibleState (TRUE);
int nNewRowHeight = IsHorizontal () ? rectBarWnd.Height () : rectBarWnd.Width ();
if (nNewRowHeight > GetRowHeight ())
{
m_pParentDockBar->ResizeRow (this, nNewRowHeight + m_nExtraSpace);
}
pControlBar->SetDockBarRow (this);
ArrangeBars (pControlBar);
}
//**********************************************************************************************
void CBCGPDockBarRow::RemoveControlBar (CBCGPControlBar* pControlBar)
{
ASSERT_VALID (this);
ASSERT_VALID (pControlBar);
POSITION pos = m_lstControlBars.Find (pControlBar);
if (pos != NULL)
{
// expand the bar before it leaves the row
HDWP hdwp = NULL;
pControlBar->StretchBar (0xFFFF, hdwp);
m_lstControlBars.RemoveAt (pos);
pControlBar->SetDockBarRow (NULL);
if (!m_lstControlBars.IsEmpty ())
{
FixupVirtualRects (true, pControlBar);
// expand stretched bars (if any)
ExpandStretchedBars ();
//
UpdateVisibleState (FALSE);
// find the biggest control bar and resize the row according to its size
int nMaxBarSize = GetMaxBarSize (FALSE);
if (nMaxBarSize < GetRowHeight ())
{
m_pParentDockBar->ResizeRow (this, nMaxBarSize);
m_nRowHeight = nMaxBarSize;
}
}
else
{
m_pParentDockBar->RemoveRow (this);
}
}
}
//**********************************************************************************************
CSize CBCGPDockBarRow::CalcFixedLayout (BOOL bStretch, BOOL bHorz)
{
if (!m_bVisible)
{
if (IsHorizontal ())
{
return CSize (32767, 0);
}
return CSize (0, 32767);
}
BOOL bHorzBar = IsHorizontal ();
CSize sizeRequired (0, 0);
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pBar = DYNAMIC_DOWNCAST (CBCGPControlBar, m_lstControlBars.GetNext (pos));
ASSERT_VALID (pBar);
if (!pBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
CSize sizeBar = pBar->CalcFixedLayout (bStretch, bHorz);
if (bHorzBar)
{
sizeRequired.cx += sizeBar.cx;
sizeRequired.cy = max (sizeRequired.cy, sizeBar.cy);
}
else
{
sizeRequired.cx = max (sizeRequired.cx, sizeBar.cx);
sizeRequired.cy += sizeBar.cy;
}
}
if (bHorzBar && sizeRequired.cy > 0)
{
sizeRequired.cy += m_nExtraSpace;
}
if (!bHorzBar && sizeRequired.cx > 0)
{
sizeRequired.cx += m_nExtraSpace;
}
return sizeRequired;
}
//**********************************************************************************************
void CBCGPDockBarRow::OnResizeControlBar (CBCGPBaseControlBar* pControlBar)
{
}
//**********************************************************************************************
int CBCGPDockBarRow::Resize (int nOffset)
{
int nNewHeight = m_nRowHeight + nOffset;
int nActualOffset = nNewHeight - m_nRowHeight;
m_nRowHeight = nNewHeight;
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pBar = DYNAMIC_DOWNCAST (CBCGPControlBar, m_lstControlBars.GetNext (pos));
if (pBar != NULL)
{
pBar->RecalcLayout ();
}
}
// return the actual resize offset
return nActualOffset;
}
//**********************************************************************************************
void CBCGPDockBarRow::Move (int nOffset)
{
ASSERT_VALID (this);
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pBar = DYNAMIC_DOWNCAST (CBCGPControlBar, m_lstControlBars.GetNext (pos));
if (pBar != NULL)
{
pBar->MoveByAlignment (m_dwRowAlignment, nOffset);
}
}
m_nRowOffset += nOffset;
}
//**********************************************************************************************
void CBCGPDockBarRow::GetWindowRect (CRect& rect) const
{
ASSERT_VALID (this);
rect.SetRectEmpty ();
if (m_pParentDockBar == NULL)
{
return;
}
m_pParentDockBar->GetWindowRect (&rect);
if (IsHorizontal ())
{
rect.top += m_nRowOffset;
rect.bottom = rect.top + GetRowHeight ();
}
else
{
rect.left += m_nRowOffset;
rect.right = rect.left + GetRowHeight ();
}
}
//**********************************************************************************************
void CBCGPDockBarRow::GetClientRect (CRect& rect) const
{
ASSERT_VALID (this);
GetWindowRect (rect);
m_pParentDockBar->ScreenToClient (&rect);
if (IsHorizontal ())
{
rect.top -= m_nRowOffset;
rect.bottom = rect.top + GetRowHeight ();
}
else
{
rect.left -= m_nRowOffset;
rect.right = rect.left + GetRowHeight ();
}
}
//**********************************************************************************************
void CBCGPDockBarRow::ScreenToClient (CRect& rect) const
{
ASSERT_VALID (this);
m_pParentDockBar->ScreenToClient (&rect);
}
//**********************************************************************************************
BOOL CBCGPDockBarRow::ShowControlBar (CBCGPControlBar* pControlBar, BOOL bShow,
BOOL bDelay)
{
ASSERT_VALID (this);
ASSERT_VALID (pControlBar);
if (!HasControlBar (pControlBar))
{
return FALSE;
}
pControlBar->ShowWindow (bShow ? SW_SHOW : SW_HIDE);
UpdateVisibleState (bDelay);
if (!bShow)
{
ExpandStretchedBars ();
}
else
{
pControlBar->AdjustLayout ();
ArrangeBars (pControlBar);
}
if (!bDelay)
{
CRect rect;
GetClientRect (rect);
m_pParentDockBar->RepositionBars (rect);
RepositionBars (rect);
}
return TRUE;
}
//**********************************************************************************************
void CBCGPDockBarRow::UpdateVisibleState (BOOL bDelay)
{
BOOL bUseRecentVisibleState = !m_pParentDockBar->GetParent ()->IsWindowVisible ();
BOOL bOldVisibleState = m_bVisible;
BOOL bNewVisibleState = FALSE;
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPBaseControlBar* pNextWnd = (CBCGPBaseControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextWnd);
if (bUseRecentVisibleState && pNextWnd->IsRestoredFromRegistry ())
{
bNewVisibleState = pNextWnd->GetRecentVisibleState ();
if (bNewVisibleState)
{
break;
}
}
else if (pNextWnd->GetStyle () & WS_VISIBLE)
{
bNewVisibleState = TRUE;
break;
}
}
if (bOldVisibleState != bNewVisibleState)
{
ShowDockBarRow (bNewVisibleState, bDelay);
}
m_bVisible = bNewVisibleState;
}
//**********************************************************************************************
void CBCGPDockBarRow::ShowDockBarRow (BOOL bShow, BOOL bDelay)
{
m_bVisible = bShow;
m_pParentDockBar->ShowRow (this, bShow, !bDelay);
}
//**********************************************************************************************
void CBCGPDockBarRow::ExpandStretchedBars ()
{
ASSERT_VALID (this);
if (m_lstControlBars.IsEmpty ())
{
return;
}
// do not use virt. rects - we need real row space
int nAvalableLen = GetAvailableLength (FALSE);
HDWP hdwp = NULL;
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextBar);
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
int nRetSize = pNextBar->StretchBar (nAvalableLen, hdwp);
nAvalableLen -= nRetSize;
if (nAvalableLen <= 0)
{
break;
}
}
ArrangeBars (NULL);
}
//**********************************************************************************************
void CBCGPDockBarRow::ExpandStretchedBarsRect ()
{
ASSERT_VALID (this);
if (m_lstControlBars.IsEmpty ())
{
return;
}
BeginTrans ();
// do not use virt. rects - we need real row space
int nAvalableLen = GetAvailableLengthRect ();
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextBar);
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
int nRetSize = StretchBarRect (pNextBar, nAvalableLen);
nAvalableLen -= nRetSize;
if (nAvalableLen <= 0)
{
break;
}
}
ArrangeBarsRect (NULL);
CommitTrans ();
}
//**********************************************************************************************
void CBCGPDockBarRow::ShiftControlBars (CBCGPControlBar* pControlBar, int nOffset, BOOL bForward)
{
ASSERT_VALID (this);
ASSERT (!m_lstControlBars.IsEmpty ());
if (nOffset == 0)
{
return;
}
POSITION pos = NULL;
if (pControlBar != NULL)
{
pos = m_lstControlBars.Find (pControlBar);
}
else
{
pos = bForward ? m_lstControlBars.GetHeadPosition () : m_lstControlBars.GetTailPosition ();
pControlBar = (CBCGPControlBar*) m_lstControlBars.GetAt (pos);
}
int nMoveOffset = nOffset;
CRect rectBar; rectBar.SetRectEmpty ();
while (pos != NULL)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) (bForward ? m_lstControlBars.GetNext (pos)
: m_lstControlBars.GetPrev (pos));
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
ASSERT_VALID (pNextBar);
CRect rectNextBar;
pNextBar->GetWindowRect (rectNextBar);
if (pNextBar != pControlBar && !rectBar.IsRectEmpty ())
{
if (IsHorizontal ())
{
nMoveOffset -= bForward ? rectNextBar.left - rectBar.right
: rectNextBar.right - rectBar.left;
}
else
{
nMoveOffset -= bForward ? rectNextBar.top - rectBar.bottom
: rectNextBar.bottom - rectBar.top;
}
}
if (nMoveOffset <= 0 && bForward || nMoveOffset >= 0 && !bForward)
{
break;
}
rectBar = rectNextBar;
IsHorizontal () ? rectNextBar.OffsetRect (nMoveOffset, 0) : rectNextBar.OffsetRect (0, nMoveOffset);
m_pParentDockBar->ScreenToClient (rectNextBar);
pNextBar->SetWindowPos (NULL, rectNextBar.left, rectNextBar.top,
rectNextBar.Width (), rectNextBar.Height (), SWP_NOZORDER | SWP_NOACTIVATE);
}
}
//**********************************************************************************************
void CBCGPDockBarRow::MoveControlBar (CBCGPControlBar* pControlBar, CPoint ptOffset,
BOOL bSwapControlBars, HDWP& hdwp)
{
ASSERT_VALID (this);
ASSERT_VALID (pControlBar);
CRect rectVirtual;
pControlBar->GetVirtualRect (rectVirtual);
CRect rectBarWnd;
pControlBar->GetWindowRect (&rectBarWnd);
CRect rectVirualNew = rectVirtual;
rectVirualNew.OffsetRect (ptOffset);
// the bar is being moved within the row, just move it horizontally or vertically
bool bForward = true;
CPoint ptMove (0, 0);
int nAllowedOffset = 0;
if (IsHorizontal ())
{
nAllowedOffset = ptMove.x = ptOffset.x;
bForward = (ptMove.x >= 0);
}
else
{
nAllowedOffset = ptMove.y = ptOffset.y;
bForward = (ptMove.y >= 0);
}
if (!IsEnoughSpaceToMove (pControlBar, bForward, nAllowedOffset))
{
return;
}
if (IsHorizontal () && abs (nAllowedOffset) < abs (ptMove.x))
{
ptMove.x = nAllowedOffset;
}
else if (!IsHorizontal () && abs (nAllowedOffset) < abs (ptMove.y))
{
ptMove.y = nAllowedOffset;
}
rectBarWnd.OffsetRect (ptMove);
if (CheckControlBars (rectBarWnd, pControlBar, bForward, ptMove, bSwapControlBars, hdwp))
{
m_pParentDockBar->ScreenToClient (&rectBarWnd);
pControlBar->SetWindowPos (NULL, rectBarWnd.left, rectBarWnd.top,
rectBarWnd.Width (), rectBarWnd.Height (), SWP_NOZORDER | SWP_NOACTIVATE);
}
ArrangeBars (pControlBar);
}
//**********************************************************************************************
void CBCGPDockBarRow::MoveControlBar (CBCGPControlBar* pControlBar, CRect rectTarget, HDWP& hdwp)
{
ASSERT_VALID (this);
ASSERT_VALID (pControlBar);
CRect rectBarWnd;
pControlBar->GetWindowRect (&rectBarWnd);
if (IsHorizontal ())
{
rectBarWnd.left = rectTarget.left;
rectBarWnd.right = rectTarget.right;
}
else
{
rectBarWnd.top = rectTarget.top;
rectBarWnd.bottom = rectTarget.bottom;
}
m_pParentDockBar->ScreenToClient (&rectBarWnd);
pControlBar->SetWindowPos (NULL, rectBarWnd.left, rectBarWnd.top,
rectBarWnd.Width (), rectBarWnd.Height (), SWP_NOZORDER | SWP_NOACTIVATE);
}
//**********************************************************************************************
void CBCGPDockBarRow::MoveControlBar (CBCGPControlBar* pControlBar, int nOffset, bool bForward, HDWP& hdwp)
{
ASSERT_VALID (this);
ASSERT_VALID (pControlBar);
if (nOffset == 0)
{
return;
}
CRect rectBarWnd;
pControlBar->GetWindowRect (&rectBarWnd);
if (IsHorizontal ())
{
rectBarWnd.OffsetRect (bForward ? nOffset : -nOffset, 0);
}
else
{
rectBarWnd.OffsetRect (0, bForward ? nOffset : -nOffset);
}
m_pParentDockBar->ScreenToClient (&rectBarWnd);
pControlBar->SetWindowPos (NULL, rectBarWnd.left, rectBarWnd.top,
rectBarWnd.Width (), rectBarWnd.Height (),
SWP_NOZORDER | SWP_NOACTIVATE);
}
//**********************************************************************************************
void CBCGPDockBarRow::MoveControlBar (CBCGPControlBar* pControlBar, int nAbsolutOffset, HDWP& hdwp)
{
ASSERT_VALID (this);
ASSERT_VALID (pControlBar);
CRect rectBarWnd;
pControlBar->GetWindowRect (&rectBarWnd);
CRect rectRow;
GetWindowRect (rectRow);
int nBarLength = 0;
if (IsHorizontal ())
{
nBarLength = rectBarWnd.Width ();
rectBarWnd.left = rectRow.left + nAbsolutOffset;
rectBarWnd.right = rectBarWnd.left + nBarLength;
}
else
{
nBarLength = rectBarWnd.Height ();
rectBarWnd.top = rectRow.top + nAbsolutOffset;
rectBarWnd.bottom = rectBarWnd.top + nBarLength;
}
m_pParentDockBar->ScreenToClient (&rectBarWnd);
pControlBar->SetWindowPos (NULL, rectBarWnd.left, rectBarWnd.top,
rectBarWnd.Width (), rectBarWnd.Height (), SWP_NOZORDER | SWP_NOACTIVATE);
}
//**********************************************************************************************
int CBCGPDockBarRow::GetVisibleCount ()
{
int nVisibleCount = 0;
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextBar);
if (!m_bIgnoreBarVisibility)
{
if (pNextBar->IsVisible ())
{
nVisibleCount++;
}
}
else
{
nVisibleCount++;
}
}
return nVisibleCount;
}
//**********************************************************************************************
BOOL CBCGPDockBarRow::CheckControlBars (CRect& rectCurrentBar, CBCGPControlBar* pCurrentBar,
bool bForward, CPoint ptOffset,
BOOL bSwapControlBars, HDWP& hdwp)
{
ASSERT_VALID (this);
if (m_lstControlBars.GetCount () < 2 ||
GetVisibleCount () < 2)
{
// nothing to check - there is only one control bar on the dock bar
return TRUE;
}
CRect rectNextControlBar;
CRect rectNextControlBarVirt;
CBCGPControlBar* pNextBar = NULL;
CRect rectIntersect;
BOOL bIntersect = FALSE;
POSITION posCurrentBar = m_lstControlBars.Find (pCurrentBar);
// position of the bar which intersects with the current bar
POSITION posIntersect = NULL;
// find a control bar which whill intersect with the current bar
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
posIntersect = pos;
pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
if (pNextBar != pCurrentBar)
{
ASSERT_VALID (pNextBar);
pNextBar->GetWindowRect (&rectNextControlBar);
bIntersect = rectIntersect.IntersectRect (rectNextControlBar, rectCurrentBar);
if (bIntersect)
{
break;
}
}
}
if (!bIntersect || pNextBar == NULL)
{
// the current bar does not intersect with any bar on the row, check whether
// we need to move "trailing bars" - whose virtual rectangle is out of place
MoveTrailingBars (posCurrentBar, ptOffset, bForward, pCurrentBar, hdwp);
return TRUE;
}
// get the virtual rectangle of the bar that intersects with the curr. bar
pNextBar->GetVirtualRect (rectNextControlBarVirt);
// if the current bar has just crossed a point when it is no more on the left side
// from the virtual rect (when moving forward), or it is no more on the right side
// when moving backward;
// the next control bar should be transferred to the opposite side
CRect rectIntersectVirt;
if (rectIntersectVirt.IntersectRect (rectNextControlBarVirt, rectCurrentBar) && bSwapControlBars)
{
if (bForward && pCurrentBar->IsLeftOf (rectNextControlBarVirt) ||
!bForward && !pCurrentBar->IsLeftOf (rectNextControlBarVirt))
{
CRect rectNew = rectNextControlBar;
if (IsHorizontal ())
{
bForward ? rectNew.right = rectCurrentBar.left
: rectNew.left = rectCurrentBar.right ;
bForward ? rectNew.left = rectNew.right - rectNextControlBar.Width ()
: rectNew.right = rectNew.left + rectNextControlBar.Width ();
}
else
{
bForward ? rectNew.bottom = rectCurrentBar.top
: rectNew.top = rectCurrentBar.bottom;
bForward ? rectNew.top = rectNew.bottom - rectNextControlBar.Height ()
: rectNew.bottom = rectNew.top + rectNextControlBar.Height ();
}
MoveControlBar (pNextBar, rectNew, hdwp);
m_lstControlBars.RemoveAt (posIntersect);
bForward ? m_lstControlBars.InsertBefore (posCurrentBar, pNextBar) :
m_lstControlBars.InsertAfter (posCurrentBar, pNextBar);
ResolveIntersection (pNextBar, !bForward, hdwp);
// now we need to shift all control bars behind pNextBar to make them closer
// to the current bar
CRect rectWnd;
CRect rectVirt;
bForward ? m_lstControlBars.GetNext (posCurrentBar) : m_lstControlBars.GetPrev (posCurrentBar);
for (POSITION pos = posCurrentBar; pos != NULL;)
{
CBCGPControlBar* pMovedBar = (CBCGPControlBar*)
(bForward ? m_lstControlBars.GetNext (pos) : m_lstControlBars.GetPrev (pos));
ASSERT_VALID (pMovedBar);
if (!pMovedBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
pMovedBar->GetWindowRect (&rectWnd);
pMovedBar->GetVirtualRect (rectVirt);
if (rectWnd != rectVirt)
{
int nOffset = IsHorizontal () ? rectNew.Width () : rectNew.Height ();
nOffset -= IsHorizontal () ? abs (ptOffset.x) : abs (ptOffset.y);
MoveControlBar (pMovedBar, nOffset, !bForward, hdwp); // move in opposite direction
}
}
return TRUE;
}
}
int nMoveOffset = IsHorizontal () ? rectIntersect.Width () : rectIntersect.Height ();
MoveControlBar (pNextBar, nMoveOffset, bForward, hdwp);
ResolveIntersection (pNextBar, bForward, hdwp);
MoveTrailingBars (posCurrentBar, ptOffset, bForward, pCurrentBar, hdwp);
return TRUE;
}
//**********************************************************************************************
void CBCGPDockBarRow::MoveTrailingBars (POSITION posStart, CPoint ptOffset, bool bForward,
CBCGPControlBar* pBarToSkip, HDWP& hdwp)
{
ASSERT_VALID (this);
CRect rectNextControlBar;
CRect rectNextControlBarVirt;
for (POSITION pos = posStart; pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) (bForward ? m_lstControlBars.GetPrev (pos) : m_lstControlBars.GetNext (pos));
ASSERT_VALID (pNextBar);
if (pNextBar == pBarToSkip)
{
continue;
}
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
pNextBar->GetWindowRect (&rectNextControlBar);
pNextBar->GetVirtualRect (rectNextControlBarVirt);
if (rectNextControlBar != rectNextControlBarVirt)
{
int nOffsetToMove = 0;
if (bForward && pNextBar->IsLeftOf (rectNextControlBarVirt) ||
!bForward && !pNextBar->IsLeftOf (rectNextControlBarVirt))
{
nOffsetToMove = IsHorizontal () ? abs (ptOffset.x) : abs (ptOffset.y);
}
else if (bForward && !pNextBar->IsLeftOf (rectNextControlBarVirt) ||
!bForward && pNextBar->IsLeftOf (rectNextControlBarVirt))
{
if (IsHorizontal ())
{
nOffsetToMove = min (abs (ptOffset.x),
abs (rectNextControlBarVirt.left - rectNextControlBar.left));
}
else
{
nOffsetToMove = min (abs (ptOffset.y),
abs (rectNextControlBarVirt.top - rectNextControlBar.top));
}
}
MoveControlBar (pNextBar, nOffsetToMove, bForward, hdwp);
ResolveIntersection (pNextBar, !bForward, hdwp);
}
}
}
//**********************************************************************************************
void CBCGPDockBarRow::ResolveIntersection (CBCGPControlBar* pBar, bool bForward, HDWP& hdwp)
{
ASSERT_VALID (this);
ASSERT_VALID (pBar);
POSITION posStart = m_lstControlBars.Find (pBar);
CRect rectBarWnd;
rectBarWnd.SetRectEmpty ();
CRect rectRowWnd;
GetWindowRect (rectRowWnd);
CRect rectIntersect;
CRect rectMovedBar;
for (POSITION pos = posStart; pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*)
(bForward ? m_lstControlBars.GetNext (pos) : m_lstControlBars.GetPrev (pos));
ASSERT_VALID (pNextBar);
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
pNextBar->GetWindowRect (&rectBarWnd);
CBCGPControlBar* pMovedBar = NULL;
POSITION posSave = NULL;
for (POSITION posMoved = pos; posMoved != NULL;)
{
posSave = posMoved;
pMovedBar = (CBCGPControlBar*)
(bForward ? m_lstControlBars.GetNext (posMoved) : m_lstControlBars.GetPrev (posMoved));
if (pMovedBar->IsVisible () || m_bIgnoreBarVisibility)
{
break;
}
}
if (pMovedBar == NULL)
{
break;
}
pMovedBar->GetWindowRect (&rectMovedBar);
if (bForward &&
(IsHorizontal () && rectMovedBar.left > rectBarWnd.right ||
!IsHorizontal () && rectMovedBar.top > rectBarWnd.bottom) ||
!bForward &&
(IsHorizontal () && rectMovedBar.right < rectBarWnd.left ||
!IsHorizontal () && rectMovedBar.bottom < rectBarWnd.top))
{
pos = posSave;
continue;
}
int nMoveOffset = 0;
if (bForward)
{
nMoveOffset = IsHorizontal () ? rectBarWnd.right - rectMovedBar.left
: rectBarWnd.bottom - rectMovedBar.top;
}
else
{
nMoveOffset = IsHorizontal () ? rectMovedBar.right - rectBarWnd.left
: rectMovedBar.bottom - rectBarWnd.top;
}
MoveControlBar (pMovedBar, nMoveOffset, bForward, hdwp);
pos = posSave;
}
}
//**********************************************************************************************
BOOL CBCGPDockBarRow::IsEnoughSpaceToMove (CBCGPControlBar* pControlBar, bool bForward, int& nAllowedOffset)
{
ASSERT_VALID (this);
ASSERT_VALID (pControlBar);
int nLen = 0;
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CRect rectBar;
CBCGPControlBar* pBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pBar);
if (!pBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
pBar->GetWindowRect (&rectBar);
if (pBar == pControlBar)
{
continue;
}
if (bForward && !pControlBar->IsLeftOf (rectBar) ||
!bForward && pControlBar->IsLeftOf (rectBar))
{
IsHorizontal () ? nLen += rectBar.Width () : nLen += rectBar.Height ();
}
}
CRect rectControlBar;
pControlBar->GetWindowRect (&rectControlBar);
CRect rectRow;
GetWindowRect (rectRow);
nAllowedOffset = 0;
if (IsHorizontal ())
{
nAllowedOffset = bForward ? rectRow.right - rectControlBar.right :
rectRow.left - rectControlBar.left;
}
else
{
nAllowedOffset = bForward ? rectRow.bottom - rectControlBar.bottom :
rectRow.top - rectControlBar.top;
}
nAllowedOffset = bForward ? nAllowedOffset - nLen : nAllowedOffset + nLen;
if (bForward && nAllowedOffset <= 0 ||
!bForward && nAllowedOffset >= 0)
{
return FALSE;
}
return TRUE;
}
//**********************************************************************************************
void CBCGPDockBarRow::OffsetFromRect (const CRect& rect, CPoint& pt, bool bForward)
{
switch (m_dwRowAlignment & CBRS_ALIGN_ANY)
{
case CBRS_ALIGN_TOP:
case CBRS_ALIGN_BOTTOM:
bForward ? pt.x = rect.Width () : pt.x = -rect.Width ();
break;
case CBRS_ALIGN_LEFT:
case CBRS_ALIGN_RIGHT:
bForward ? pt.y = rect.Height () : pt.y = -rect.Height ();
break;
}
}
//**********************************************************************************************
void CBCGPDockBarRow::FixupVirtualRects (bool bMoveBackToVirtualRect, CBCGPControlBar* pBarToExclude)
{
ASSERT_VALID (this);
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextBar);
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
if (pNextBar == pBarToExclude)
{
continue;
}
CRect rectBarWnd;
pNextBar->GetWindowRect (&rectBarWnd);
if (bMoveBackToVirtualRect)
{
CRect rectVirtual;
pNextBar->GetVirtualRect (rectVirtual);
if (rectVirtual != rectBarWnd)
{
HDWP hdwp = BeginDeferWindowPos (m_lstControlBars.GetCount ());
MoveControlBar (pNextBar, rectVirtual, hdwp);
EndDeferWindowPos (hdwp);
}
}
else
{
pNextBar->UpdateVirtualRect ();
}
}
}
//**********************************************************************************************
int CBCGPDockBarRow::GetAvailableLength (BOOL bUseVirtualRect) const
{
ASSERT_VALID (this);
CRect rectRow;
GetClientRect (rectRow);
int nTotalBarLength = 0;
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextBar);
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
CRect rectWnd;
bUseVirtualRect ? pNextBar->GetVirtualRect (rectWnd) : pNextBar->GetWindowRect (&rectWnd);
nTotalBarLength += IsHorizontal () ? rectWnd.Width () : rectWnd.Height ();
}
// debug variable
int nAvailableLength = IsHorizontal () ? rectRow.Width () - nTotalBarLength :
rectRow.Height () - nTotalBarLength;
return nAvailableLength;
}
//**********************************************************************************************
int CBCGPDockBarRow::GetMaxBarSize (BOOL bSkipHiddenBars) const
{
ASSERT_VALID (this);
int nMaxSize = 0;
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextBar);
if (!pNextBar->IsVisible () && bSkipHiddenBars && !m_bIgnoreBarVisibility)
{
continue;
}
CRect rectWnd;
pNextBar->GetWindowRect (&rectWnd);
nMaxSize = max (nMaxSize, IsHorizontal () ? rectWnd.Height () : rectWnd.Width ());
}
// don't use extra space if there are no visible bars
if (nMaxSize != 0)
{
nMaxSize += m_nExtraSpace;
}
return nMaxSize;
}
//**********************************************************************************************
void CBCGPDockBarRow::GetAvailableSpace (CRect& rect)
{
ASSERT_VALID (this);
GetWindowRect (rect);
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextBar);
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
CRect rectWnd;
pNextBar->GetWindowRect (&rectWnd);
IsHorizontal () ? rect.DeflateRect (rectWnd.Width (), 0) :
rect.DeflateRect (0, rectWnd.Height ());
}
}
//**********************************************************************************************
void CBCGPDockBarRow::ArrangeControlBars (int nMargin, int nSpacing)
{
CRect rectRow;
CRect rectBar;
CPoint ptOffset (0, 0);
GetWindowRect (rectRow);
bool bFistBar = true;
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pBar);
if (!pBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
pBar->GetWindowRect (rectBar);
if (bFistBar)
{
IsHorizontal () ? ptOffset.x = rectRow.left + nMargin :
ptOffset.y = rectRow.top + nMargin;
bFistBar = false;
}
if (!pBar->m_bFirstInGroup)
{
IsHorizontal () ? ptOffset.x -= (nSpacing + CBCGPAutoHideButton::m_nBorderSize):
ptOffset.y -= (nSpacing + + CBCGPAutoHideButton::m_nBorderSize);
}
int nLen = 0;
if (IsHorizontal ())
{
int nWidth = rectBar.Width ();
rectBar.left = ptOffset.x;
rectBar.right = rectBar.left + nWidth;
nLen = nWidth;
}
else
{
int nHeight = rectBar.Height ();
rectBar.top = ptOffset.y;
rectBar.bottom = rectBar.top + nHeight;
nLen = nHeight;
}
ScreenToClient (rectBar);
pBar->SetWindowPos (NULL, rectBar.left, rectBar.top,
rectBar.Width (), rectBar.Height (), SWP_NOZORDER | SWP_NOACTIVATE);
pBar->StretchControlBar (nLen, !IsHorizontal ());
// get the rect after stretch
pBar->GetWindowRect (rectBar);
IsHorizontal () ? ptOffset.x += rectBar.Width () + nSpacing :
ptOffset.y += rectBar.Height () + nSpacing;
}
}
//**********************************************************************************************
void CBCGPDockBarRow::ArrangeBars (CBCGPControlBar* pInitialBar)
{
ASSERT_VALID (this);
if (m_lstControlBars.IsEmpty ())
{
return;
}
CRect rectRow;
GetClientRect (rectRow);
if (rectRow.IsRectEmpty ())
{
// the row still is not initialized
return;
}
HDWP hdwp = NULL;
int nAvailLength = GetAvailableLength ();
// handle single bar
if (m_lstControlBars.GetCount () == 1)
{
if (pInitialBar == NULL)
{
pInitialBar = (CBCGPControlBar*) m_lstControlBars.GetHead ();
}
ASSERT_VALID (pInitialBar);
if (nAvailLength < 0)
{
pInitialBar->StretchBar (nAvailLength, hdwp);
CRect rectBar;
pInitialBar->GetWindowRect (rectBar);
m_pParentDockBar->ScreenToClient (rectBar);
if (IsHorizontal ())
{
rectBar.OffsetRect (-rectBar.TopLeft ().x, -rectBar.TopLeft ().y + m_nRowOffset);
}
else
{
rectBar.OffsetRect (-rectBar.TopLeft ().x + m_nRowOffset, -rectBar.TopLeft ().y);
}
pInitialBar->SetWindowPos (NULL, rectBar.left, rectBar.top,
rectBar.Width (), rectBar.Height (), SWP_NOZORDER | SWP_NOACTIVATE);
return;
}
}
if (pInitialBar != NULL)
{
ResolveIntersection (pInitialBar, false, hdwp);
}
if (pInitialBar == NULL)
{
pInitialBar = (CBCGPControlBar*) m_lstControlBars.GetHead ();
}
ResolveIntersection (pInitialBar, true, hdwp);
CBCGPControlBar* pFirstBar = FindFirstVisibleBar (TRUE);
// how far the first bar is out of row bounds
int nLeftOuterOffset = GetOutOfBoundsOffset (pFirstBar, TRUE);
if (nLeftOuterOffset > 0)
{
ShiftControlBars (pFirstBar, nLeftOuterOffset, TRUE);
}
CBCGPControlBar* pLastBar = FindFirstVisibleBar (FALSE);
int nRightOuterOffset = GetOutOfBoundsOffset (pLastBar, FALSE);
int nStretchSize = 0;
if (nRightOuterOffset > 0 && nAvailLength > 0)
{
ShiftControlBars (pLastBar, -nRightOuterOffset, FALSE);
}
else if (nRightOuterOffset > 0 && nAvailLength <= 0)
{
nStretchSize = nAvailLength;
ShiftControlBars (pLastBar, -(nRightOuterOffset - abs (nAvailLength)), FALSE);
}
else if (nRightOuterOffset < 0)
{
// nothing to do
}
if (nStretchSize < 0)
{
for (POSITION pos = m_lstControlBars.GetTailPosition (); pos != NULL;)
{
CBCGPControlBar* pPrevBar = (CBCGPControlBar*) m_lstControlBars.GetPrev (pos);
ASSERT_VALID (pPrevBar);
if (!pPrevBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
int nRetSize = pPrevBar->StretchBar (nStretchSize, hdwp);
MoveControlBar (pPrevBar, abs (nStretchSize) - abs (nRetSize), false, hdwp);
if (nRetSize == nStretchSize)
{
break;
}
else
{
nStretchSize -= nRetSize;
}
}
}
}
//**********************************************************************************************
CBCGPControlBar* CBCGPDockBarRow::FindFirstVisibleBar (BOOL bForward)
{
ASSERT_VALID (this);
if (m_lstControlBars.IsEmpty ())
{
return NULL;
}
for (POSITION pos = bForward ? m_lstControlBars.GetHeadPosition () :
m_lstControlBars.GetTailPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*)
(bForward ? m_lstControlBars.GetNext (pos) : m_lstControlBars.GetPrev (pos));
ASSERT_VALID (pNextBar);
if (!m_bIgnoreBarVisibility)
{
if (pNextBar->IsVisible ())
{
return pNextBar;
}
}
else
{
return pNextBar;
}
}
return NULL;
}
//**********************************************************************************************
int CBCGPDockBarRow::GetOutOfBoundsOffset (CBCGPControlBar* pBar, BOOL bLeftTopBound)
{
ASSERT_VALID (this);
CRect rectBar;
CRect rectRow;
if (pBar == NULL)
{
pBar = (CBCGPControlBar* )
(bLeftTopBound ? m_lstControlBars.GetHead () : m_lstControlBars.GetTail ());
}
ASSERT_VALID (pBar);
pBar->GetWindowRect (rectBar);
GetWindowRect (rectRow);
int nBoundOffset = 0;
// the offset is greater than zero if the bar is out of bounds
if (IsHorizontal ())
{
nBoundOffset = bLeftTopBound ? rectRow.left - rectBar.left :
rectBar.right - rectRow.right;
}
else
{
nBoundOffset = bLeftTopBound ? rectRow.top - rectBar.top :
rectBar.bottom - rectRow.bottom;
}
return nBoundOffset;
}
//**********************************************************************************************
void CBCGPDockBarRow::RepositionBars (CRect& rectNewParentBarArea, UINT nSide, BOOL bExpand, int nOffset)
{
ASSERT_VALID (this);
if (m_lstControlBars.IsEmpty () ||
GetVisibleCount () == 0)
{
return;
}
CRect rectNewParentWnd = rectNewParentBarArea;
ASSERT_VALID (m_pParentDockBar);
m_pParentDockBar->ClientToScreen (rectNewParentWnd);
CRect rectRowWnd;
GetWindowRect (rectRowWnd);
if (rectRowWnd.IsRectEmpty ())
{
return;
}
int nStretchSize = IsHorizontal () ? rectNewParentWnd.Width () - rectRowWnd.Width () :
rectNewParentWnd.Height () - rectRowWnd.Height ();
HDWP hdwp = NULL; //BeginDeferWindowPos (m_lstControlBars.GetCount ());
// handle exclusive bars first
if (IsExclusiveRow ())
{
CBCGPControlBar* pBar = (CBCGPControlBar*) m_lstControlBars.GetHead ();
ASSERT_VALID (pBar);
ASSERT (!pBar->DoesAllowSiblingBars ());
if (IsHorizontal ())
{
pBar->SetWindowPos (NULL, rectRowWnd.left, rectRowWnd.top,
rectNewParentWnd.Width (),
rectRowWnd.Height (), SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
}
else
{
pBar->SetWindowPos (NULL, rectRowWnd.left, rectRowWnd.top,
rectRowWnd.Width (),
rectNewParentWnd.Height (), SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
}
pBar->RedrawWindow ();
return;
}
int nAvailSpace = GetAvailableLength (TRUE);
bool bResizeBars = nAvailSpace < 0 ||
!bExpand && nAvailSpace >= 0 && nAvailSpace < abs (nStretchSize);
if (bResizeBars)
{
if (!bExpand)
{
// there is some available space on the row
// we need to move control bars first and then stretch
bool bTopLeftSide = (nSide == WMSZ_TOP || nSide == WMSZ_LEFT);
int nActualStretchSize = nStretchSize;
if (nAvailSpace >= 0)
{
int nSign = nStretchSize < 0 ? (-1) : 1;
int nOutOfBoundOffset = GetOutOfBoundsOffset (NULL, bTopLeftSide);
int nOffsetToShift = nAvailSpace - abs (nOutOfBoundOffset);
ShiftControlBars (NULL, nSign * nOffsetToShift, bTopLeftSide);
nActualStretchSize = (abs (nStretchSize) - nAvailSpace) * nSign;
}
for (POSITION pos = m_lstControlBars.GetTailPosition (); pos != NULL;)
{
CBCGPControlBar* pPrevBar = (CBCGPControlBar*) m_lstControlBars.GetPrev (pos);
ASSERT_VALID (pPrevBar);
if (!pPrevBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
int nRetSize = pPrevBar->StretchBar (nActualStretchSize, hdwp);
MoveControlBar (pPrevBar, abs (nActualStretchSize) - abs (nRetSize), bTopLeftSide, hdwp);
if (nRetSize == nActualStretchSize)
{
break;
}
else
{
nActualStretchSize -= nRetSize;
}
}
return;
}
else
{
int nActualStretchSize = nStretchSize;
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextBar);
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
int nRetSize = pNextBar->StretchBar (nActualStretchSize, hdwp);
if (nRetSize != 0 && pos != NULL)
{
for (POSITION posMovedBars = pos; posMovedBars != NULL;)
{
CBCGPControlBar* pBarToMove = (CBCGPControlBar*) m_lstControlBars.GetNext (posMovedBars);
ASSERT_VALID (pBarToMove);
if (!pBarToMove->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
MoveControlBar (pBarToMove, nRetSize, true, hdwp);
}
}
nActualStretchSize -= nRetSize;
if (nActualStretchSize <= 0)
{
break;
}
}
}
}
// adlust control bars (first and last) to the row area and try to move
// them as close as it possible to their virtual rectangle
if (IsHorizontal ())
{
rectRowWnd.left = rectNewParentWnd.left;
rectRowWnd.right = rectNewParentWnd.right;
}
else
{
rectRowWnd.top = rectNewParentWnd.top;
rectRowWnd.bottom = rectNewParentWnd.bottom;
}
// check the first and last control bars
CBCGPControlBar* pBarFirst = FindFirstVisibleBar (TRUE);
ASSERT_VALID (pBarFirst);
AdjustBarToRowArea (pBarFirst, rectRowWnd, hdwp);
CBCGPControlBar* pBarLast = FindFirstVisibleBar (FALSE);
ASSERT_VALID (pBarLast);
if (pBarFirst != pBarLast)
{
AdjustBarToRowArea (pBarLast, rectRowWnd, hdwp);
}
if (nSide != (UINT)-1 && bExpand && GetAvailableLength (TRUE) + nStretchSize > 0)
{
CRect rectNextControlBar;
CRect rectNextControlBarVirt;
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextBar);
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
pNextBar->GetWindowRect (&rectNextControlBar);
pNextBar->GetVirtualRect (rectNextControlBarVirt);
if (rectNextControlBar != rectNextControlBarVirt)
{
// always try to move to the virtual rect's direction
// if the bar is currently on the left side of its virtual rect
// move it forward, otherwise - backward
bool bMoveBackward = (IsHorizontal () && rectNextControlBar.left > rectNextControlBarVirt.left) ||
(!IsHorizontal () && rectNextControlBar.top > rectNextControlBarVirt.top);
int nOffsetToMove = 0;
if (IsHorizontal () && (nSide == WMSZ_LEFT || nSide == WMSZ_RIGHT))
{
nOffsetToMove = min (abs (nOffset),
abs (rectNextControlBarVirt.left - rectNextControlBar.left));
}
else if (!IsHorizontal () && (nSide == WMSZ_TOP || nSide == WMSZ_BOTTOM))
{
nOffsetToMove = min (abs (nOffset),
abs (rectNextControlBarVirt.top - rectNextControlBar.top));
}
int nSaveOffset = nOffsetToMove;
if (IsEnoughSpaceToMove (pNextBar, !bMoveBackward, nSaveOffset))
{
MoveControlBar (pNextBar, nOffsetToMove, !bMoveBackward, hdwp);
}
}
}
}
}
//**********************************************************************************************
void CBCGPDockBarRow::AdjustBarToRowArea (CBCGPControlBar* pBar, const CRect& rectRow, HDWP& hdwp)
{
ASSERT_VALID (this);
ASSERT_VALID (pBar);
CRect rectBarWnd;
pBar->GetWindowRect (rectBarWnd);
CPoint ptOffset (0, 0);
if (IsHorizontal ())
{
if (rectBarWnd.left < rectRow.left)
{
ptOffset = CPoint (rectRow.left - rectBarWnd.left, 0);
MoveControlBar (pBar, ptOffset, FALSE, hdwp);
}
if (rectBarWnd.right > rectRow.right)
{
ptOffset = CPoint (rectRow.right - rectBarWnd.right, 0);
MoveControlBar (pBar, ptOffset, FALSE, hdwp);
}
}
else
{
if (rectBarWnd.top < rectRow.top)
{
ptOffset = CPoint (0, rectRow.top - rectBarWnd.top);
MoveControlBar (pBar, ptOffset, FALSE, hdwp);
}
if (rectBarWnd.bottom > rectRow.bottom)
{
ptOffset = CPoint (0, rectRow.bottom - rectBarWnd.bottom);
MoveControlBar (pBar, ptOffset, FALSE, hdwp);
}
}
}
//**********************************************************************************************
BOOL CBCGPDockBarRow::ReplaceControlBar (CBCGPControlBar* pBarOld, CBCGPControlBar* pBarNew)
{
ASSERT_VALID (this);
POSITION pos = m_lstControlBars.Find (pBarOld);
if (pos != NULL)
{
m_lstControlBars.InsertAfter (pos, pBarNew);
m_lstControlBars.RemoveAt (pos);
return TRUE;
}
return FALSE;
}
//**********************************************************************************************
BOOL CBCGPDockBarRow::IsExclusiveRow () const
{
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextBar);
if (!pNextBar->DoesAllowSiblingBars ())
{
return TRUE;
}
}
return FALSE;
}
//**********************************************************************************************
int CBCGPDockBarRow::CalcLastBarOffset ()
{
if (m_lstControlBars.IsEmpty ())
{
return 0;
}
CBCGPControlBar* pLastBar = (CBCGPControlBar*) m_lstControlBars.GetTail ();
ASSERT_VALID (pLastBar);
CRect rect;
pLastBar->GetWindowRect (rect);
m_pParentDockBar->ScreenToClient (rect);
return IsHorizontal () ? rect.right : rect.bottom;
}
//**********************************************************************************************
void CBCGPDockBarRow::RedrawAll ()
{
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextBar);
pNextBar->RedrawWindow (NULL, NULL, RDW_FRAME | RDW_INVALIDATE);
}
}
//**********************************************************************************************
void CBCGPDockBarRow::GetGroupFromBar (CBCGPControlBar* pBar, CObList& lst)
{
POSITION pos = m_lstControlBars.Find (pBar);
if (pos == NULL)
{
return;
}
// find first control bar in group
for (POSITION posGrp = pos; posGrp != NULL;)
{
CBCGPControlBar* pPrevBar = (CBCGPControlBar*) m_lstControlBars.GetPrev (posGrp);
ASSERT_VALID (pPrevBar);
if (pPrevBar->m_bFirstInGroup)
{
if (posGrp == NULL)
{
posGrp =m_lstControlBars.GetHeadPosition ();
}
else
{
m_lstControlBars.GetNext (posGrp);
}
break;
}
}
// collect all bars in the group
while (posGrp != NULL)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (posGrp);
ASSERT_VALID (pNextBar);
lst.AddTail (pNextBar);
if (pNextBar->m_bLastInGroup)
{
break;
}
}
}
//**********************************************************************************************
void CBCGPDockBarRow::BeginTrans ()
{
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextBar);
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
pNextBar->FillWindowRect ();
}
}
//**********************************************************************************************
void CBCGPDockBarRow::CommitTrans ()
{
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextBar);
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
CRect rect = pNextBar->GetBarRect ();
CRect rectWnd;
pNextBar->GetWindowRect (rectWnd);
if (rect == rectWnd)
{
continue;
}
pNextBar->GetParent ()->ScreenToClient (rect);
pNextBar->SetWindowPos (NULL, rect.left, rect.top, rect.Width (),
rect.Height (), SWP_NOZORDER | SWP_NOACTIVATE);
}
}
//**********************************************************************************************
int CBCGPDockBarRow::GetAvailableLengthRect ()
{
CRect rectRow;
GetClientRect (rectRow);
int nTotalBarLength = 0;
for (POSITION pos = m_lstControlBars.GetHeadPosition (); pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) m_lstControlBars.GetNext (pos);
ASSERT_VALID (pNextBar);
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
CRect rectWnd = pNextBar->GetBarRect ();
nTotalBarLength += IsHorizontal () ? rectWnd.Width () : rectWnd.Height ();
}
// debug variable
int nAvailableLength = IsHorizontal () ? rectRow.Width () - nTotalBarLength :
rectRow.Height () - nTotalBarLength;
return nAvailableLength;
}
//**********************************************************************************************
int CBCGPDockBarRow::StretchBarRect (CBCGPControlBar* pBar, int nStretchSize)
{
// the bar is stretched - calculate how far it can be expanded and do not
// exceed its original size
int nAvailExpandSize = pBar->GetAvailableExpandSize ();
int nAvailStretchSize = pBar->GetAvailableStretchSize ();
int nActualStretchSize = 0;
if (nStretchSize > 0)
{
if (nAvailExpandSize == 0)
{
return 0;
}
// the bar is expanded
nActualStretchSize = nAvailExpandSize > nStretchSize ? nStretchSize : nAvailExpandSize;
}
else
{
nActualStretchSize = nAvailStretchSize < abs (nStretchSize) ? -nAvailStretchSize : nStretchSize;
}
CRect rect = pBar->GetBarRect ();
if (IsHorizontal ())
{
rect.right += nActualStretchSize;
}
else
{
rect.bottom += nActualStretchSize;
}
if (abs (nActualStretchSize) > 0)
{
pBar->SetBarRect (rect);
}
return nActualStretchSize;
}
//**********************************************************************************************
void CBCGPDockBarRow::ArrangeBarsRect (CBCGPControlBar* pInitialBar)
{
ASSERT_VALID (this);
if (m_lstControlBars.IsEmpty ())
{
return;
}
CRect rectRow;
GetClientRect (rectRow);
if (rectRow.IsRectEmpty ())
{
// the row still is not initialized
return;
}
HDWP hdwp = NULL;
int nAvailLength = GetAvailableLengthRect ();
// handle single bar
if (m_lstControlBars.GetCount () == 1)
{
if (pInitialBar == NULL)
{
pInitialBar = (CBCGPControlBar*) m_lstControlBars.GetHead ();
}
ASSERT_VALID (pInitialBar);
if (nAvailLength < 0)
{
StretchBarRect (pInitialBar, nAvailLength);
CRect rectBar = pInitialBar->GetBarRect ();
pInitialBar->SetBarRect (rectBar);
return;
}
}
if (pInitialBar != NULL)
{
ResolveIntersectionRect (pInitialBar, false);
}
if (pInitialBar == NULL)
{
pInitialBar = (CBCGPControlBar*) m_lstControlBars.GetHead ();
}
ResolveIntersectionRect (pInitialBar, true);
CBCGPControlBar* pFirstBar = FindFirstVisibleBar (TRUE);
// how far the first bar is out of row bounds
int nLeftOuterOffset = GetOutOfBoundsOffsetRect (pFirstBar, TRUE);
if (nLeftOuterOffset > 0)
{
ShiftControlBarsRect (pFirstBar, nLeftOuterOffset, TRUE);
}
CBCGPControlBar* pLastBar = FindFirstVisibleBar (FALSE);
int nRightOuterOffset = GetOutOfBoundsOffsetRect (pLastBar, FALSE);
int nStretchSize = 0;
if (nRightOuterOffset > 0 && nAvailLength > 0)
{
ShiftControlBarsRect (pLastBar, -nRightOuterOffset, FALSE);
}
else if (nRightOuterOffset > 0 && nAvailLength <= 0)
{
nStretchSize = nAvailLength;
ShiftControlBarsRect (pLastBar, -(nRightOuterOffset - abs (nAvailLength)), FALSE);
}
else if (nRightOuterOffset < 0)
{
// nothing to do
}
if (nStretchSize < 0)
{
for (POSITION pos = m_lstControlBars.GetTailPosition (); pos != NULL;)
{
CBCGPControlBar* pPrevBar = (CBCGPControlBar*) m_lstControlBars.GetPrev (pos);
ASSERT_VALID (pPrevBar);
if (!pPrevBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
int nRetSize = pPrevBar->StretchBar (nStretchSize, hdwp);
MoveControlBarRect (pPrevBar, abs (nStretchSize) - abs (nRetSize), false);
if (nRetSize == nStretchSize)
{
break;
}
else
{
nStretchSize -= nRetSize;
}
}
}
}
//**********************************************************************************************
void CBCGPDockBarRow::ResolveIntersectionRect (CBCGPControlBar* pBar, bool bForward)
{
ASSERT_VALID (this);
ASSERT_VALID (pBar);
POSITION posStart = m_lstControlBars.Find (pBar);
CRect rectBarWnd;
rectBarWnd.SetRectEmpty ();
CRect rectRowWnd;
GetWindowRect (rectRowWnd);
CRect rectIntersect;
CRect rectMovedBar;
for (POSITION pos = posStart; pos != NULL;)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*)
(bForward ? m_lstControlBars.GetNext (pos) : m_lstControlBars.GetPrev (pos));
ASSERT_VALID (pNextBar);
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
rectBarWnd = pNextBar->GetBarRect ();
CBCGPControlBar* pMovedBar = NULL;
POSITION posSave = NULL;
for (POSITION posMoved = pos; posMoved != NULL;)
{
posSave = posMoved;
pMovedBar = (CBCGPControlBar*)
(bForward ? m_lstControlBars.GetNext (posMoved) : m_lstControlBars.GetPrev (posMoved));
if (pMovedBar->IsVisible () || m_bIgnoreBarVisibility)
{
break;
}
}
if (pMovedBar == NULL)
{
break;
}
rectMovedBar = pMovedBar->GetBarRect ();
if (bForward &&
(IsHorizontal () && rectMovedBar.left > rectBarWnd.right ||
!IsHorizontal () && rectMovedBar.top > rectBarWnd.bottom) ||
!bForward &&
(IsHorizontal () && rectMovedBar.right < rectBarWnd.left ||
!IsHorizontal () && rectMovedBar.bottom < rectBarWnd.top))
{
pos = posSave;
continue;
}
int nMoveOffset = 0;
if (bForward)
{
nMoveOffset = IsHorizontal () ? rectBarWnd.right - rectMovedBar.left
: rectBarWnd.bottom - rectMovedBar.top;
}
else
{
nMoveOffset = IsHorizontal () ? rectMovedBar.right - rectBarWnd.left
: rectMovedBar.bottom - rectBarWnd.top;
}
MoveControlBarRect (pMovedBar, nMoveOffset, bForward);
pos = posSave;
}
}
//**********************************************************************************************
int CBCGPDockBarRow::GetOutOfBoundsOffsetRect (CBCGPControlBar* pBar, BOOL bLeftTopBound)
{
ASSERT_VALID (this);
CRect rectBar;
CRect rectRow;
if (pBar == NULL)
{
pBar = (CBCGPControlBar* )
(bLeftTopBound ? m_lstControlBars.GetHead () : m_lstControlBars.GetTail ());
}
ASSERT_VALID (pBar);
rectBar = pBar->GetBarRect ();
GetWindowRect (rectRow);
int nBoundOffset = 0;
// the offset is greater than zero if the bar is out of bounds
if (IsHorizontal ())
{
nBoundOffset = bLeftTopBound ? rectRow.left - rectBar.left :
rectBar.right - rectRow.right;
}
else
{
nBoundOffset = bLeftTopBound ? rectRow.top - rectBar.top :
rectBar.bottom - rectRow.bottom;
}
return nBoundOffset;
}
//**********************************************************************************************
void CBCGPDockBarRow::ShiftControlBarsRect (CBCGPControlBar* pControlBar, int nOffset,
BOOL bForward)
{
ASSERT_VALID (this);
ASSERT (!m_lstControlBars.IsEmpty ());
if (nOffset == 0)
{
return;
}
POSITION pos = NULL;
if (pControlBar != NULL)
{
pos = m_lstControlBars.Find (pControlBar);
}
else
{
pos = bForward ? m_lstControlBars.GetHeadPosition () : m_lstControlBars.GetTailPosition ();
pControlBar = (CBCGPControlBar*) m_lstControlBars.GetAt (pos);
}
int nMoveOffset = nOffset;
CRect rectBar; rectBar.SetRectEmpty ();
while (pos != NULL)
{
CBCGPControlBar* pNextBar = (CBCGPControlBar*) (bForward ? m_lstControlBars.GetNext (pos)
: m_lstControlBars.GetPrev (pos));
if (!pNextBar->IsVisible () && !m_bIgnoreBarVisibility)
{
continue;
}
ASSERT_VALID (pNextBar);
CRect rectNextBar = pNextBar->GetBarRect ();
if (pNextBar != pControlBar && !rectBar.IsRectEmpty ())
{
if (IsHorizontal ())
{
nMoveOffset -= bForward ? rectNextBar.left - rectBar.right
: rectNextBar.right - rectBar.left;
}
else
{
nMoveOffset -= bForward ? rectNextBar.top - rectBar.bottom
: rectNextBar.bottom - rectBar.top;
}
}
if (nMoveOffset <= 0 && bForward || nMoveOffset >= 0 && !bForward)
{
break;
}
rectBar = rectNextBar;
IsHorizontal () ? rectNextBar.OffsetRect (nMoveOffset, 0) : rectNextBar.OffsetRect (0, nMoveOffset);
pNextBar->SetBarRect (rectNextBar);
}
}
//**********************************************************************************************
void CBCGPDockBarRow::MoveControlBarRect (CBCGPControlBar* pControlBar, int nOffset,
bool bForward)
{
ASSERT_VALID (this);
ASSERT_VALID (pControlBar);
if (nOffset == 0)
{
return;
}
CRect rectBarWnd = pControlBar->GetBarRect ();
if (IsHorizontal ())
{
rectBarWnd.OffsetRect (bForward ? nOffset : -nOffset, 0);
}
else
{
rectBarWnd.OffsetRect (0, bForward ? nOffset : -nOffset);
}
pControlBar->SetBarRect (rectBarWnd);
}