You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

911 lines
22 KiB
C++

// XTPDockingPaneSplitterContainer.cpp : implementation of the CXTPDockingPaneSplitterContainer class.
//
// This file is a part of the XTREME DOCKINGPANE MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Common/Resource.h"
#include "Common/XTPDrawHelpers.h"
#include "Common/XTPColorManager.h"
#include "Common/XTPResourceManager.h"
#include "Common/XTPSystemHelpers.h"
#include "TabManager/XTPTabManager.h"
#include "XTPDockingPaneDefines.h"
#include "XTPDockingPaneBase.h"
#include "XTPDockingPaneBaseContainer.h"
#include "XTPDockingPaneLayout.h"
#include "XTPDockingPaneManager.h"
#include "XTPDockingPaneSplitterContainer.h"
#include "XTPDockingPanePaintManager.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CXTPDockingPaneSplitterWnd::CXTPDockingPaneSplitterWnd()
{
m_hCursor = 0;
m_pFirst = 0;
m_pSecond = 0;
m_pContainer = 0;
m_pManager = 0;
m_bHoriz = FALSE;
}
void CXTPDockingPaneSplitterWnd::Create(CXTPDockingPaneManager* pManager, BOOL bHoriz)
{
m_bHoriz = bHoriz;
m_pManager = pManager;
CWnd::Create(_T("XTPDockingPaneSplitter"), _T("Splitter"), WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, CRect(0, 0, 0, 0), pManager->GetSite(), 0);
}
void CXTPDockingPaneSplitterWnd::Create(CXTPDockingPaneSplitterContainer* pContainer, CXTPDockingPaneBase* pFirst, CXTPDockingPaneBase* pSecond)
{
m_pFirst = pFirst;
m_pSecond = pSecond;
m_pContainer = pContainer;
m_bHoriz = !m_pContainer->IsHoriz();
m_pManager = m_pContainer->GetDockingPaneManager();
m_hCursor = XTPResourceManager()->LoadCursor(pContainer->m_bHoriz ? XTP_IDC_HSPLITBAR : XTP_IDC_VSPLITBAR);
XTPResourceManager()->AssertValid(m_hCursor != 0);
CWnd::Create(_T("XTPDockingPaneSplitter"), _T("Splitter"), WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, CRect(0, 0, 0, 0), pContainer->GetDockingSite(), 0);
}
CXTPDockingPaneSplitterWnd::~CXTPDockingPaneSplitterWnd()
{
if (m_hWnd) DestroyWindow();
}
BEGIN_MESSAGE_MAP(CXTPDockingPaneSplitterWnd, CWnd)
ON_WM_PAINT()
ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
ON_WM_LBUTTONDOWN()
ON_WM_ERASEBKGND()
ON_WM_SETCURSOR()
END_MESSAGE_MAP()
BOOL CXTPDockingPaneSplitterWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (m_pContainer == 0)
return CWnd::OnSetCursor(pWnd, nHitTest, message);
if (GetDockingPaneManager()->IsSplittersLocked())
return CWnd::OnSetCursor(pWnd, nHitTest, message);
CRect rcAvail, rcUnion;
if (!GetAvailableRect(rcAvail, rcUnion))
return CWnd::OnSetCursor(pWnd, nHitTest, message);
::SetCursor(m_hCursor);
return TRUE;
}
void CXTPDockingPaneSplitterWnd::OnPaint()
{
CPaintDC dc(this);
if (m_pManager)
m_pManager->GetPaintManager()->DrawSplitter(&dc, this);
}
LRESULT CXTPDockingPaneSplitterWnd::OnPrintClient(WPARAM wParam, LPARAM /*lParam*/)
{
CDC* pDC = CDC::FromHandle((HDC)wParam);
if (pDC && m_pManager)
{
m_pManager->GetPaintManager()->DrawSplitter(pDC, this);
}
return TRUE;
}
BOOL CXTPDockingPaneSplitterWnd::OnEraseBkgnd(CDC* /*pDC*/)
{
return TRUE;
}
BOOL CXTPDockingPaneSplitterWnd::IsHorizontal() const
{
return m_bHoriz;
}
void CXTPDockingPaneSplitterWnd::Reposition(CRect rc, CRect rcAvail)
{
CXTPDockingPanePaintManager* pPaintManager = m_pContainer->GetDockingPaneManager()->GetPaintManager();
int nSplitterSize = pPaintManager->m_nSplitterSize;
int nSplitterIndent = pPaintManager->m_bShowCaption ? pPaintManager->m_nSplitterIndent : 0;
if (m_pContainer->m_bHoriz)
{
double d = double(rc.left + nSplitterIndent - rcAvail.left) / rcAvail.Width();
int nSum = m_pFirst->m_szDocking.cx + m_pSecond->m_szDocking.cx + nSplitterSize;
m_pFirst->m_szDocking.cx = GetExStyle() & WS_EX_LAYOUTRTL ? nSum - int(d * nSum) - nSplitterSize : int(d * nSum);
m_pSecond->m_szDocking.cx = nSum - m_pFirst->m_szDocking.cx - nSplitterSize;
}
else
{
double d = double(rc.top + nSplitterIndent - rcAvail.top) / rcAvail.Height();
int nSum = m_pFirst->m_szDocking.cy + m_pSecond->m_szDocking.cy + nSplitterSize;
m_pFirst->m_szDocking.cy = int(d * nSum);
m_pSecond->m_szDocking.cy = nSum - m_pFirst->m_szDocking.cy - nSplitterSize;
}
}
void CXTPDockingPaneSplitterContainer::NormalizeDockingSize()
{
if (m_bHoriz) m_szDocking.cx = m_rcWindow.Width();
else m_szDocking.cy = m_rcWindow.Height();
POSITION pos = GetHeadPosition();
while (pos)
{
CXTPDockingPaneBase* pPane = GetNext(pos);
if (!pPane->IsEmpty())
{
if (m_bHoriz) pPane->m_szDocking.cx = pPane->m_rcWindow.Width();
else pPane->m_szDocking.cy = pPane->m_rcWindow.Height();
}
}
}
BOOL CXTPDockingPaneSplitterWnd::GetAvailableRect(CRect& rcAvail, CRect& rcUnion)
{
CXTPDockingPaneManager* pManager = GetDockingPaneManager();
if (!pManager)
return FALSE;
int nSplitterSize = pManager->GetPaintManager()->m_nSplitterSize;
BOOL bHoriz = m_pContainer->m_bHoriz;
ASSERT(m_pFirst && m_pSecond);
if (!m_pFirst || !m_pSecond)
return FALSE;
CRect rcFirst = m_pFirst->GetPaneWindowRect();
CRect rcSecond = m_pSecond->GetPaneWindowRect();
MINMAXINFO mmiFirst, mmiSecond;
m_pFirst->GetMinMaxInfo(&mmiFirst);
m_pSecond->GetMinMaxInfo(&mmiSecond);
rcAvail.UnionRect(rcFirst, rcSecond);
rcUnion = rcAvail;
int nGap = pManager->m_nSplitterGap;
if (bHoriz)
{
rcAvail.DeflateRect(max(mmiFirst.ptMinTrackSize.x, nGap), 0,
max(mmiSecond.ptMinTrackSize.x + nSplitterSize, nGap), 0);
if (rcUnion.Width() > mmiFirst.ptMaxTrackSize.x)
rcAvail.right = min(rcAvail.right, rcUnion.left + mmiFirst.ptMaxTrackSize.x);
if (rcUnion.Width() > mmiSecond.ptMaxTrackSize.x)
rcAvail.left = max(rcAvail.left, rcUnion.right - mmiSecond.ptMaxTrackSize.x - nSplitterSize);
if (rcAvail.left >= rcAvail.right)
return FALSE;
}
else
{
rcAvail.DeflateRect(0, max(mmiFirst.ptMinTrackSize.y, nGap),
0, max(mmiSecond.ptMinTrackSize.y + nSplitterSize, nGap));
if (rcUnion.Height() > mmiFirst.ptMaxTrackSize.y)
rcAvail.bottom = min(rcAvail.bottom, rcUnion.top + mmiFirst.ptMaxTrackSize.y);
if (rcUnion.Height() > mmiSecond.ptMaxTrackSize.y)
rcAvail.top = max(rcAvail.top, rcUnion.bottom - mmiSecond.ptMaxTrackSize.y - nSplitterSize);
if (rcAvail.top >= rcAvail.bottom)
return FALSE;
}
return TRUE;
}
void CXTPDockingPaneSplitterWnd::OnLButtonDown(UINT /*nFlags*/, CPoint point)
{
if (m_pContainer == 0)
return;
CXTPDockingPaneManager* pManager = GetDockingPaneManager();
if (pManager->IsSplittersLocked())
return;
CXTPWindowRect rc(this);
CRect rcAvail, rcUnion;
if (!GetAvailableRect(rcAvail, rcUnion))
return;
if (m_pContainer->OnAction(xtpPaneActionSplitterResizing))
return;
m_pContainer->NormalizeDockingSize();
BOOL bHoriz = m_pContainer->m_bHoriz;
//point = rc.TopLeft();
ClientToScreen(&point);
if (pManager->IsSplitterTrackerUsed())
{
CXTPSplitterTracker tracker;
BOOL bAccept = tracker.Track(this, rcAvail, rc, point, bHoriz);
if (bAccept)
{
Reposition(rc, rcUnion);
pManager->RecalcFrameLayout(m_pContainer, TRUE);
}
}
else
{
CPoint ptOffset = bHoriz ? CPoint(rc.left - point.x, 0) :
CPoint(0, rc.top - point.y);
SetCapture();
while (::GetCapture() == m_hWnd)
{
MSG msg;
while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE | PM_NOYIELD))
{
DispatchMessage(&msg);
}
if (!GetMessage(&msg, NULL, 0, 0))
break;
if (msg.message == WM_MOUSEMOVE)
{
point = CPoint(msg.lParam);
ClientToScreen(&point);
point += ptOffset;
point.x = max(min(point.x, rcAvail.right), rcAvail.left);
point.y = max(min(point.y, rcAvail.bottom), rcAvail.top);
if (bHoriz)
{
if (rc.left == point.x)
continue;
rc.OffsetRect(point.x - rc.left, 0);
}
else
{
if (rc.top == point.y)
continue;
rc.OffsetRect(0, point.y - rc.top);
}
Reposition(rc, rcUnion);
pManager->RecalcFrameLayout(m_pContainer);
}
else if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) break;
else if (msg.message == WM_LBUTTONUP) break;
else ::DispatchMessage(&msg);
}
if (CWnd::GetCapture() == this) ReleaseCapture();
}
m_pContainer->OnAction(xtpPaneActionSplitterResized);
}
CXTPDockingPaneManager* CXTPDockingPaneSplitterWnd::GetDockingPaneManager() const
{
return m_pManager;
}
CXTPDockingPaneSplitterContainer::CXTPDockingPaneSplitterContainer(CXTPDockingPaneLayout* pLayout)
: CXTPDockingPaneBaseContainer(xtpPaneTypeSplitterContainer, pLayout)
{
m_bRecalcLayout = FALSE;
m_bHoriz = FALSE;
}
void CXTPDockingPaneSplitterContainer::Init(CXTPDockingPaneBase* pPane, BOOL bHoriz, CWnd* pFrame)
{
ASSERT(pPane);
if (!pPane)
return;
m_bHoriz = bHoriz;
m_pDockingSite = pFrame;
_InsertPane(pPane);
m_szDocking = pPane->m_szDocking;
}
void CXTPDockingPaneSplitterContainer::_UpdateSplitters()
{
if (m_bRecalcLayout)
return;
if (m_pLayout->IsUserLayout())
return;
while (!m_lstSpliters.IsEmpty())
{
delete m_lstSpliters.RemoveTail();
}
if (m_lstPanes.GetCount() > 1)
{
POSITION posPane = GetHeadPosition();
CXTPDockingPaneBase* pFirstPane = NULL;
// Finding first nonempty pane
while (posPane)
{
pFirstPane = GetNext(posPane);
if (!pFirstPane->IsEmpty())
break;
}
// Splitting
while (posPane)
{
CXTPDockingPaneBase* pSecondPane = GetNext(posPane);
if (pSecondPane->IsEmpty())
continue;
CXTPDockingPaneSplitterWnd* pSplitter = OnCreateSplitter();
pSplitter->Create(this, pFirstPane, pSecondPane);
m_lstSpliters.AddTail(pSplitter);
pFirstPane = pSecondPane;
}
}
}
CXTPDockingPaneSplitterWnd* CXTPDockingPaneSplitterContainer::OnCreateSplitter()
{
return new CXTPDockingPaneSplitterWnd();
}
void CXTPDockingPaneSplitterContainer::_Replace(CXTPDockingPaneBase* pPane, CXTPDockingPaneBase* pReplace)
{
ASSERT(pPane && pReplace);
POSITION pos = m_lstPanes.Find(pPane);
ASSERT(pos);
m_lstPanes.InsertAfter(pos, pReplace);
m_lstPanes.RemoveAt(pos);
pReplace->m_pParentContainer = this;
_UpdateSplitters();
if (m_pParentContainer)
{
m_pParentContainer->OnChildContainerChanged(this);
}
}
void CXTPDockingPaneSplitterContainer::_InsertPane(CXTPDockingPaneBase* pPane, CXTPDockingPaneBase* pNeighbour, BOOL bAfter)
{
POSITION pos = pNeighbour ? m_lstPanes.Find(pNeighbour) : NULL;
if (bAfter)
{
if (pos == NULL) pos = m_lstPanes.GetTailPosition();
m_lstPanes.InsertAfter(pos, pPane);
}
else
{
if (pos == NULL) pos = GetHeadPosition();
m_lstPanes.InsertBefore(pos, pPane);
}
pPane->m_pParentContainer = this;
pPane->SetDockingSite(GetDockingSite());
GetDockingPaneManager()->RecalcFrameLayout(this, TRUE);
_UpdateSplitters();
if (m_pParentContainer)
{
m_pParentContainer->OnChildContainerChanged(this);
}
pPane->OnParentContainerChanged(this);
}
void CXTPDockingPaneSplitterContainer::RemovePane(CXTPDockingPaneBase* pPane)
{
POSITION pos = m_lstPanes.Find(pPane);
ASSERT(pos);
m_lstPanes.RemoveAt(pos);
_UpdateSplitters();
GetDockingPaneManager()->RecalcFrameLayout(this, TRUE);
if (m_pParentContainer)
{
m_pParentContainer->OnChildContainerChanged(this);
}
if (m_lstPanes.IsEmpty())
{
m_pParentContainer->RemovePane(this);
}
pPane->m_pParentContainer = NULL;
}
void CXTPDockingPaneSplitterContainer::OnChildContainerChanged(CXTPDockingPaneBase* pContainer)
{
if (m_pParentContainer)
{
m_pParentContainer->OnChildContainerChanged(pContainer);
}
_UpdateSplitters();
GetDockingPaneManager()->RecalcFrameLayout(this, TRUE);
}
void CXTPDockingPaneSplitterContainer::OnParentContainerChanged(CXTPDockingPaneBase* pContainer)
{
m_pDockingSite = pContainer->m_pDockingSite;
_UpdateSplitters();
POSITION pos = GetHeadPosition();
while (pos)
{
GetNext(pos)->OnParentContainerChanged(pContainer);
}
}
CXTPDockingPaneSplitterContainer::~CXTPDockingPaneSplitterContainer()
{
while (!m_lstSpliters.IsEmpty())
{
delete m_lstSpliters.RemoveTail();
}
}
void CXTPDockingPaneSplitterContainer::OnSizeParent(CWnd* pParent, CRect rect, LPVOID lParam)
{
CXTPDockingPaneManager* pManager = GetDockingPaneManager();
CXTPDockingPanePaintManager* pPaintManager = pManager->GetPaintManager();
int nSplitterSize = pPaintManager->m_nSplitterSize;
int nSplitterIndent = pPaintManager->m_bShowCaption ? pPaintManager->m_nSplitterIndent : 0;
CXTPDockingPaneBase* pClient = pManager->GetClientPane();
AFX_SIZEPARENTPARAMS* lpLayout = (AFX_SIZEPARENTPARAMS*)lParam;
m_pDockingSite = pParent;
m_rcWindow = rect;
BOOL bClientPane = !pManager->m_bHideClient;
// getting list of nonempty panes
CXTPDockingPaneBaseList lst;
POSITION pos = GetHeadPosition();
while (pos)
{
CXTPDockingPaneBase* pPane = GetNext(pos);
if (!pPane->IsEmpty())
lst.AddTail(pPane);
if (!bClientPane && pPane->ContainPane(pClient))
bClientPane = TRUE;
}
if (!lst.IsEmpty() && bClientPane && pManager->m_bHideClient)
{
pClient->OnSizeParent(pParent, CXTPEmptyRect(), lParam);
}
if (lst.GetCount() == 0)
return;
if (lst.GetCount() == 1)
{
lst.GetHead()->OnSizeParent(pParent, rect, lParam);
return;
}
if (m_bRecalcLayout)
return;
m_bRecalcLayout = TRUE;
//ASSERT(m_lstSpliters.GetCount() == lst.GetCount() - 1);
int nTotalLength = 0;
int nLengthAvail = 0;
_AdjustPanesLength(pManager, lst, rect, m_bHoriz, TRUE, nTotalLength, nLengthAvail);
pos = lst.GetHeadPosition();
POSITION posSplitter = m_lstSpliters.GetHeadPosition();
CRect rcPane(rect);
while (pos)
{
CXTPDockingPaneBase* pPane = lst.GetNext(pos);
int nLength = -pPane->m_nLength;
if (pPane->m_nLength > 0)
{
nLength = nTotalLength == 0 ? 0 : int((nLengthAvail * pPane->m_nLength) / nTotalLength);
nTotalLength -= pPane->m_nLength;
nLengthAvail = max(nLengthAvail - nLength, 0);
}
CRect rcSplitter;
if (m_bHoriz)
{
rcPane.right = pos == NULL ? rect.right : rcPane.left + nLength;
rcSplitter.SetRect(rcPane.right - nSplitterIndent, rect.top, rcPane.right + nSplitterSize + nSplitterIndent, rect.bottom);
}
else
{
rcPane.bottom = pos == NULL ? rect.bottom : rcPane.top + nLength;
rcSplitter.SetRect(rect.left, rcPane.bottom - nSplitterIndent, rect.right, rcPane.bottom + nSplitterSize + nSplitterIndent);
}
if (lpLayout->hDWP != NULL && posSplitter)
{
CXTPDockingPaneSplitterWnd* pSplitter = m_lstSpliters.GetNext(posSplitter);
if (pSplitter)
{
rcSplitter.IntersectRect(rcSplitter, rect);
pSplitter->SetWindowPos(&CWnd::wndBottom, rcSplitter.left, rcSplitter.top, rcSplitter.Width(), rcSplitter.Height(), 0);
pSplitter->Invalidate(FALSE);
}
}
pPane->OnSizeParent(pParent, rcPane, lParam);
if (m_bHoriz)
{
rcPane.left = rcPane.right + nSplitterSize;
}
else
{
rcPane.top = rcPane.bottom + nSplitterSize;
}
}
m_bRecalcLayout = FALSE;
}
void CXTPDockingPaneSplitterContainer::FindChildPane(XTPDockingPaneType type, CXTPDockingPaneBaseList* pList) const
{
POSITION pos = GetHeadPosition();
while (pos)
{
CXTPDockingPaneBase* pPane = GetNext(pos);
if (pPane->GetType() == type && !pPane->IsEmpty())
{
pList->AddTail(pPane);
}
}
}
void CXTPDockingPaneSplitterContainer::Copy(CXTPDockingPaneBase* pCloneBase, CXTPPaneToPaneMap* pMap, DWORD /*dwIgnoredOptions*/)
{
CXTPDockingPaneSplitterContainer* pClone = (CXTPDockingPaneSplitterContainer*)pCloneBase;
ASSERT(pClone);
if (!pClone)
return;
m_bHoriz = pClone->m_bHoriz;
m_pDockingSite = GetDockingPaneManager()->GetSite();
POSITION pos = pClone->GetHeadPosition();
while (pos)
{
CXTPDockingPaneBase* pPane = pClone->GetNext(pos);
if (!pPane->IsEmpty() || pMap)
{
_InsertPane(pPane->Clone(m_pLayout, pMap));
}
}
m_szDocking = pClone->m_szDocking;
m_rcWindow = pClone->m_rcWindow;
}
BOOL CXTPDockingPaneSplitterContainer::_Before(const CXTPDockingPaneBase* pPane, POSITION pos) const
{
POSITION p = GetHeadPosition();
while (p)
{
if (p == pos) return FALSE;
CXTPDockingPaneBase* pBase = GetNext(p);
if (pBase == pPane) return TRUE;
}
ASSERT(FALSE);
return FALSE;
}
void CXTPDockingPaneSplitterContainer::_AdjustPanesLength(CXTPDockingPaneManager* pManager, CXTPDockingPaneBaseList& lst, CRect rect, BOOL bHoriz, BOOL bApply, int& nTotalLength, int& nLengthAvail)
{
nTotalLength = 0;
nLengthAvail = 0;
CXTPDockingPaneBase* pClientPane = NULL;
CXTPDockingPaneBase* pClient = pManager->GetClientPane();
int nSplitterSize = pManager->GetPaintManager()->m_nSplitterSize;
POSITION pos = lst.GetHeadPosition();
while (pos)
{
CXTPDockingPaneBase* pPane = lst.GetNext(pos);
pPane->m_nLength = bHoriz ? pPane->m_szDocking.cx : pPane->m_szDocking.cy;
MINMAXINFO mmi;
pPane->GetMinMaxInfo(&mmi);
pPane->m_nLength = max(GetMinSize(&mmi, bHoriz), min(GetMaxSize(&mmi, bHoriz), pPane->m_nLength));
if (pClientPane == NULL && pPane->ContainPane(pClient))
{
if (!pManager->m_bHideClient || pPane->m_szDocking == CSize(0, 0))
{
pClientPane = pPane;
if (bApply) pClientPane->m_szDocking = CSize(0, 0);
pClientPane->m_nLength = 0;
}
}
nTotalLength += pPane->m_nLength;
}
nLengthAvail = (bHoriz ? rect.Width() : rect.Height()) - (nSplitterSize * ((int)lst.GetCount() - 1));
if (pClientPane && nTotalLength < nLengthAvail)
{
pClientPane->m_nLength = nLengthAvail - nTotalLength;
if (bApply)
{
if (bHoriz) pClientPane->m_szDocking.cx = pClientPane->m_nLength;
else pClientPane->m_szDocking.cy = pClientPane->m_nLength;
}
nTotalLength = nLengthAvail;
}
if (nLengthAvail > 0)
{
pos = lst.GetHeadPosition();
while (pos)
{
CXTPDockingPaneBase* pPane = lst.GetNext(pos);
if ((pPane->m_nLength < 0) || (nTotalLength == 0))
continue;
MINMAXINFO mmi;
pPane->GetMinMaxInfo(&mmi);
int nLength = pPane->m_nLength;
if (nLengthAvail * nLength / nTotalLength < GetMinSize(&mmi, bHoriz))
pPane->m_nLength = -GetMinSize(&mmi, bHoriz);
else if (nLengthAvail * nLength / nTotalLength > GetMaxSize(&mmi, bHoriz))
pPane->m_nLength = -GetMaxSize(&mmi, bHoriz);
if (pPane->m_nLength < 0)
{
nLengthAvail += pPane->m_nLength;
nTotalLength -= nLength;
if (nLengthAvail < 0)
{
pPane->m_nLength -= nLengthAvail;
nLengthAvail = 0;
break;
}
pos = lst.GetHeadPosition();
}
}
}
}
CRect CXTPDockingPaneSplitterContainer::_CalculateResultDockingRect(BOOL bHoriz, CXTPDockingPaneBaseList& lst, CRect rect, CXTPDockingPaneBase* pPaneI)
{
CXTPDockingPaneManager* pManager = pPaneI->GetDockingPaneManager();
int nSplitterSize = pManager->GetPaintManager()->m_nSplitterSize;
int nTotalLength = 0;
int nLengthAvail = 0;
_AdjustPanesLength(pManager, lst, rect, bHoriz, FALSE, nTotalLength, nLengthAvail);
POSITION pos = lst.GetHeadPosition();
CRect rcPane(rect);
while (pos)
{
CXTPDockingPaneBase* pPane = lst.GetNext(pos);
int nLength = -pPane->m_nLength;
if (pPane->m_nLength > 0)
{
nLength = nTotalLength == 0 ? 0 : int((nLengthAvail * pPane->m_nLength) / nTotalLength);
nTotalLength -= pPane->m_nLength;
nLengthAvail = max(nLengthAvail - nLength, 0);
}
if (bHoriz)
{
rcPane.right = pos == NULL ? rect.right : rcPane.left + nLength;
if (pPaneI == pPane)
break;
rcPane.left = rcPane.right + nSplitterSize;
}
else
{
rcPane.bottom = pos == NULL ? rect.bottom : rcPane.top + nLength;
if (pPaneI == pPane)
break;
rcPane.top = rcPane.bottom + nSplitterSize;
}
}
return rcPane;
}
CRect CXTPDockingPaneSplitterContainer::_CalculateResultDockingRectSelf(CXTPDockingPaneBase* pPaneI, XTPDockingPaneDirection direction, CXTPDockingPaneBase* pNeighbour)
{
direction = GetDockingPaneManager()->GetRTLDirection(direction);
ASSERT(pNeighbour);
BOOL bAfter = (direction == xtpPaneDockRight || direction == xtpPaneDockBottom);
// getting list of nonempty panes
CXTPDockingPaneBaseList lst;
POSITION posPanes = GetHeadPosition();
while (posPanes)
{
CXTPDockingPaneBase* pPane = GetNext(posPanes);
if (pPane->IsEmpty() || (pPane == pPaneI))
continue;
POSITION pos = lst.AddTail(pPane);
if (pPane == pNeighbour)
{
if (bAfter)
lst.InsertAfter(pos, pPaneI);
else
lst.InsertBefore(pos, pPaneI);
}
}
CRect rcResult = _CalculateResultDockingRect(m_bHoriz, lst, m_rcWindow, pPaneI);
m_pDockingSite->ClientToScreen(rcResult);
return rcResult;
}
CRect CXTPDockingPaneSplitterContainer::_CalculateResultDockingRectChild(CXTPDockingPaneBase* pSplitter, CXTPDockingPaneBase* pPane, XTPDockingPaneDirection direction)
{
BOOL bAfter = (direction == xtpPaneDockRight || direction == xtpPaneDockBottom);
BOOL bHoriz = (direction == xtpPaneDockLeft || direction == xtpPaneDockRight);
CXTPDockingPaneBaseList lst;
lst.AddTail(pSplitter);
if (bAfter)
lst.AddTail(pPane);
else
lst.AddHead(pPane);
CRect rect = pSplitter->GetPaneWindowRect();
return _CalculateResultDockingRect(bHoriz, lst, rect, pPane);
}
void CXTPDockingPaneSplitterContainer::DeletePane()
{
InternalRelease();
}
void CXTPDockingPaneSplitterContainer::GetMinMaxInfo(LPMINMAXINFO pMinMaxInfo) const
{
CXTPDockingPaneBase::GetMinMaxInfo(pMinMaxInfo);
int nCount = 0;
POSITION pos = GetHeadPosition();
while (pos)
{
CXTPDockingPaneBase* pPane = GetNext(pos);
if (pPane->IsEmpty())
continue;
nCount++;
MINMAXINFO info;
pPane->GetMinMaxInfo(&info);
if (nCount == 1)
{
*pMinMaxInfo = info;
}
else
{
GetMinSize(pMinMaxInfo, m_bHoriz) += GetMinSize(&info, m_bHoriz);
GetMaxSize(pMinMaxInfo, m_bHoriz) += GetMaxSize(&info, m_bHoriz);
GetMinSize(pMinMaxInfo, !m_bHoriz) = max(GetMinSize(pMinMaxInfo, !m_bHoriz), GetMinSize(&info, !m_bHoriz));
GetMaxSize(pMinMaxInfo, !m_bHoriz) = min(GetMaxSize(pMinMaxInfo, !m_bHoriz), GetMaxSize(&info, !m_bHoriz));
}
}
if (nCount > 0)
{
GetMinSize(pMinMaxInfo, m_bHoriz) += GetPaintManager()->m_nSplitterSize * (nCount - 1);
GetMaxSize(pMinMaxInfo, m_bHoriz) += GetPaintManager()->m_nSplitterSize * (nCount - 1);
}
}