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++
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);
|
|
}
|
|
}
|
|
|