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.

1075 lines
26 KiB
C++

// XTPDockingPaneLayout.cpp : implementation of the CXTPDockingPaneLayout 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/XTPPropExchange.h"
#include "Common/XTPColorManager.h"
#include "Common/XTPSystemHelpers.h"
#include "TabManager/XTPTabManager.h"
#include "XTPDockingPaneDefines.h"
#include "XTPDockingPaneBase.h"
#include "XTPDockingPaneBaseContainer.h"
#include "XTPDockingPaneLayout.h"
#include "XTPDockingPaneSplitterContainer.h"
#include "XTPDockingPaneTabbedContainer.h"
#include "XTPDockingPane.h"
#include "XTPDockingPaneMiniWnd.h"
#include "XTPDockingPaneManager.h"
#include "XTPDockingPaneAutoHidePanel.h"
#include "XTPDockingPaneSidePanel.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
AFX_STATIC_DATA const TCHAR _xtRootSection[] = _T("DockingPaneLayouts");
AFX_STATIC_DATA const TCHAR _xtPaneSection[] = _T("Pane-%d");
AFX_STATIC_DATA const TCHAR _xtPanes[] = _T("Panes");
AFX_STATIC_DATA const TCHAR _xtSummary[] = _T("Summary");
CXTPDockingPaneLayout::CXTPDockingPaneLayout(CXTPDockingPaneManager* pManager)
: m_pManager(pManager)
{
m_bUserLayout = TRUE;
memset(m_wndPanels, 0, sizeof(m_wndPanels));
memset(m_wndMargins, 0, sizeof(m_wndMargins));
m_pClient = m_pManager->OnCreatePane(xtpPaneTypeClient, this);
m_pTopContainer = (CXTPDockingPaneSplitterContainer*)m_pManager->OnCreatePane(xtpPaneTypeSplitterContainer, this);
m_pTopContainer->Init(m_pClient, TRUE, m_pManager->GetSite());
}
CXTPDockingPaneLayout::~CXTPDockingPaneLayout()
{
Free();
}
BOOL CXTPDockingPaneLayout::IsValid() const
{
return (m_pTopContainer != NULL) && (m_pClient != NULL)
&& (m_pClient->GetType() == xtpPaneTypeClient) && (m_pManager != NULL);
}
void CXTPDockingPaneLayout::Free()
{
m_pTopContainer = 0;
m_pClient = 0;
while (!m_lstStack.IsEmpty())
{
CXTPDockingPaneBase* pPane = m_lstStack.RemoveTail();
pPane->DeletePane();
}
m_lstPanes.RemoveAll();
memset(m_wndPanels, 0, sizeof(m_wndPanels));
for (int i = 0; i < 4; i++)
{
SAFE_DELETE(m_wndMargins[i]);
}
}
BOOL CXTPDockingPaneLayout::_Load(CXTPPropExchange* pPX)
{
if (!pPX->OnBeforeExchange())
return FALSE;
ASSERT(pPX->IsLoading());
Free();
CXTPPropExchangeSection secSummary(pPX->GetSection(_xtSummary));
int nCount = 0;
PX_Int(&secSummary, _xtPanes, nCount);
if (nCount < 2)
return FALSE;
pPX->ExchangeSchema();
TCHAR szSection[256];
CXTPPaneIndexToPaneMap map;
for (int i = 1; i <= nCount; i++)
{
wsprintf(szSection, _xtPaneSection, i);
CXTPPropExchangeSection secPane(pPX->GetSection(szSection));
int nType = -1;
PX_Int(&secPane, _T("Type"), nType, -1);
CXTPDockingPaneBase* pPane = m_pManager->OnCreatePane((XTPDockingPaneType)nType, this);
if (!pPane)
{
return FALSE;
}
pPane->m_nIndex = i;
map.SetAt(i, pPane);
}
ASSERT(map.GetCount() == m_lstStack.GetCount());
POSITION pos = m_lstStack.GetHeadPosition();
while (pos)
{
CXTPDockingPaneBase* pPane = m_lstStack.GetNext(pos);
wsprintf(szSection, _xtPaneSection, pPane->m_nIndex);
CXTPPropExchangeSection secPane(pPX->GetSection(szSection));
secPane->m_dwData = (DWORD_PTR)&map;
if (!pPane->DoPropExchange(&secPane))
{
return FALSE;
}
}
int nIndex = 0;
if (!PX_Int(&secSummary, _T("TopContainer"), nIndex))
return FALSE;
m_pTopContainer = (CXTPDockingPaneSplitterContainer*)map[nIndex];
if (!m_pTopContainer)
return FALSE;
if (!PX_Int(&secSummary, _T("Client"), nIndex))
return FALSE;
m_pClient = map[nIndex];
if (!m_pClient || m_pClient->GetType() != xtpPaneTypeClient)
return FALSE;
return TRUE;
}
// The main difference between the .Net versions and the normal versions of _Save is that in the .Net
// versions all the save is done is done in the exact same order of the load.
void CXTPDockingPaneLayout::_Save(CXTPPropExchange* pPX)
{
ASSERT(!pPX->IsLoading());
pPX->EmptySection();
_FreeEmptyPanes();
CXTPPropExchangeSection secSummary(pPX->GetSection(_xtSummary));
int nCount = (int)m_lstStack.GetCount();
PX_Int(&secSummary, _xtPanes, nCount);
pPX->ExchangeSchema();
TCHAR szSection[256];
// Assign an unique value to each pane
int nIndex = 1; // important
POSITION pos = m_lstPanes.GetHeadPosition();
while (pos)
{
CXTPDockingPane* pPane = m_lstPanes.GetNext(pos);
pPane->m_nIndex = nIndex++;
wsprintf(szSection, _xtPaneSection, pPane->m_nIndex);
CXTPPropExchangeSection secPane(pPX->GetSection(szSection));
int nType = pPane->m_type;
PX_Int(&secPane, _T("Type"), nType);
}
pos = m_lstStack.GetHeadPosition();
while (pos)
{
CXTPDockingPaneBase* pPane = m_lstStack.GetNext(pos);
if (pPane->GetType() == xtpPaneTypeDockingPane) continue;
pPane->m_nIndex = nIndex++;
wsprintf(szSection, _xtPaneSection, pPane->m_nIndex);
CXTPPropExchangeSection secPane(pPX->GetSection(szSection));
int nType = pPane->m_type;
PX_Int(&secPane, _T("Type"), nType);
}
pos = m_lstPanes.GetHeadPosition();
while (pos)
{
CXTPDockingPane* pPane = m_lstPanes.GetNext(pos);
wsprintf(szSection, _xtPaneSection, pPane->m_nIndex);
CXTPPropExchangeSection secPane(pPX->GetSection(szSection));
pPane->DoPropExchange(&secPane);
}
// Save all panes
pos = m_lstStack.GetHeadPosition();
while (pos)
{
CXTPDockingPaneBase* pPane = m_lstStack.GetNext(pos);
if (pPane->GetType() == xtpPaneTypeDockingPane) continue;
wsprintf(szSection, _xtPaneSection, pPane->m_nIndex);
CXTPPropExchangeSection secPane(pPX->GetSection(szSection));
pPane->DoPropExchange(&secPane);
}
PX_Int(&secSummary, _T("TopContainer"), m_pTopContainer->m_nIndex);
PX_Int(&secSummary, _T("Client"), m_pClient->m_nIndex);
}
BOOL CXTPDockingPaneLayout::DoPropExchange(CXTPPropExchange* pPX)
{
if (pPX->IsLoading())
return _Load(pPX);
_Save(pPX);
return TRUE;
}
BOOL CXTPDockingPaneLayout::Load(LPCTSTR strSection)
{
CXTPPropExchangeSection pxRoot(TRUE, _xtRootSection);
CXTPPropExchangeSection pxSection(pxRoot->GetSection(strSection));
return DoPropExchange(&pxSection);
}
void CXTPDockingPaneLayout::Save(LPCTSTR strSection)
{
CXTPPropExchangeSection pxRoot(FALSE, _xtRootSection);
CXTPPropExchangeSection pxSection(pxRoot->GetSection(strSection));
DoPropExchange(&pxSection);
}
void CXTPDockingPaneLayout::Serialize(CArchive& ar)
{
CXTPPropExchangeArchive px(ar);
DoPropExchange(&px);
}
#ifndef _XTP_EXCLUDE_XML
BOOL CXTPDockingPaneLayout::LoadFromNode(XTPXML::IXMLDOMNode* xmlNode, LPCTSTR strSection)
{
if (xmlNode == 0)
return FALSE;
CXTPPropExchangeXMLNode px(TRUE, xmlNode, strSection);
return DoPropExchange(&px);
}
BOOL CXTPDockingPaneLayout::LoadFromFile(LPCTSTR strFileName, LPCTSTR strSection)
{
CXTPPropExchangeXMLNode px(TRUE, 0, _xtRootSection);
if (!px.LoadFromFile(strFileName))
return FALSE;
CXTPPropExchangeSection pxSection(px.GetSection(strSection));
if (!pxSection->OnBeforeExchange())
return FALSE;
return DoPropExchange(&pxSection);
}
void CXTPDockingPaneLayout::SaveToNode (XTPXML::IXMLDOMNode* xmlNode, LPCTSTR strSection)
{
if (xmlNode == 0)
return;
CXTPPropExchangeXMLNode px(FALSE, xmlNode, strSection);
DoPropExchange(&px);
}
void CXTPDockingPaneLayout::SaveToFile (LPCTSTR strFileName, LPCTSTR strSection)
{
CXTPPropExchangeXMLNode px(FALSE, 0, _xtRootSection);
CXTPPropExchangeSection pxSection(px.GetSection(strSection));
DoPropExchange(&pxSection);
px.SaveToFile(strFileName);
}
#endif
BOOL CXTPDockingPaneBase::DoPropExchange(CXTPPropExchange* pPX)
{
PX_Long(pPX, _T("DockingCX"), m_szDocking.cx, 0);
PX_Long(pPX, _T("DockingCY"), m_szDocking.cy, 0);
return TRUE;
}
BOOL CXTPDockingPane::DoPropExchange(CXTPPropExchange* pPX)
{
CXTPDockingPaneBase::DoPropExchange(pPX);
if (pPX->IsStoring())
{
CString strTitle = m_strTitle + '\n' + m_strTabCaption + '\n' + m_strTitleToolTip;
PX_String(pPX, _T("Title"), strTitle);
}
else
{
CString strTitle;
PX_String(pPX, _T("Title"), strTitle);
AfxExtractSubString(m_strTitle, strTitle, 0, '\n');
AfxExtractSubString(m_strTabCaption, strTitle, 1, '\n');
AfxExtractSubString(m_strTitleToolTip, strTitle, 2, '\n');
}
PX_Int(pPX, _T("ID"), m_nID, 0);
PX_Int(pPX, _T("IconID"), m_nIconID, -1);
PX_ULong(pPX, _T("Options"), m_dwOptions, 0);
int nIndex = 0;
CXTPPaneIndexToPaneMap* pMap = (CXTPPaneIndexToPaneMap*)pPX->m_dwData;
if (!pPX->IsLoading())
{
XTP_DOCKINGPANE_INFO* pInfo = m_pLayout->FindPaneInfo(this);
ASSERT(pInfo);
if (pInfo)
{
nIndex = pInfo->pDockingHolder ? pInfo->pDockingHolder->m_nIndex : 0;
PX_Int(pPX, _T("DockingHolder"), nIndex, 0);
nIndex = pInfo->pFloatingHolder ? pInfo->pFloatingHolder->m_nIndex : 0;
PX_Int(pPX, _T("FloatingHolder"), nIndex, 0);
nIndex = pInfo->pLastHolder ? pInfo->pLastHolder->m_nIndex : 0;
PX_Int(pPX, _T("LastHolder"), nIndex, 0);
}
}
else
{
XTP_DOCKINGPANE_INFO info (this);
PX_Int(pPX, _T("DockingHolder"), nIndex, 0);
if (nIndex) info.pDockingHolder = (CXTPDockingPaneBase*)(*pMap)[nIndex];
PX_Int(pPX, _T("FloatingHolder"), nIndex, 0);
if (nIndex) info.pFloatingHolder = (CXTPDockingPaneBase*)(*pMap)[nIndex];
PX_Int(pPX, _T("LastHolder"), nIndex, 0);
if (nIndex) info.pLastHolder = (CXTPDockingPaneBase*)(*pMap)[nIndex];
m_pLayout->m_lstPanes.AddTail(info);
}
PX_Long(pPX, _T("MinTrackX"), m_ptMinTrackSize.x, 0);
PX_Long(pPX, _T("MinTrackY"), m_ptMinTrackSize.y, 0);
PX_Long(pPX, _T("MaxTrackX"), m_ptMaxTrackSize.x, 32000);
PX_Long(pPX, _T("MaxTrackY"), m_ptMaxTrackSize.y, 32000);
if (pPX->GetSchema() > _XTP_SCHEMA_97)
{
PX_DWord(pPX, _T("TabColor"), (DWORD&)m_clrItemTab, COLORREF_NULL);
PX_Int(pPX, _T("HelpId"), m_nIDHelp, 0);
DWORD dwData = (DWORD)m_dwData;
PX_DWord(pPX, _T("Tag"), dwData, 0);
if (pPX->IsLoading()) m_dwData = dwData;
}
return m_nID > 0;
}
BOOL CXTPDockingPaneSplitterContainer::DoPropExchange(CXTPPropExchange* pPX)
{
CXTPDockingPaneBase::DoPropExchange(pPX);
PX_Bool(pPX, _T("Horiz"), m_bHoriz, FALSE);
int nCount = 0;
if (!pPX->IsLoading())
{
nCount = (int)m_lstPanes.GetCount();
PX_Int(pPX, _xtPanes, nCount);
int nIndex = 1;
TCHAR szPane[256];
POSITION pos = m_lstPanes.GetHeadPosition();
while (pos)
{
CXTPDockingPaneBase* pPane = m_lstPanes.GetNext(pos);
wsprintf(szPane, _xtPaneSection, nIndex++);
PX_Int(pPX, szPane, pPane->m_nIndex);
}
}
else
{
PX_Int(pPX, _xtPanes, nCount, 0);
int nIndex = 0;
TCHAR szPane[256];
CXTPPaneIndexToPaneMap* pMap = (CXTPPaneIndexToPaneMap*)pPX->m_dwData;
for (int i = 1; i <= nCount; i++)
{
wsprintf(szPane, _xtPaneSection, i);
PX_Int(pPX, szPane, nIndex, 0);
ASSERT(nIndex > 0);
CXTPDockingPaneBase* pPane = NULL;
ASSERT(pMap->Lookup(nIndex, pPane));
pPane = (CXTPDockingPaneBase*)((*pMap)[nIndex]);
if (!pPane) return FALSE;
_InsertPane(pPane);
}
ASSERT(nCount > 0);
}
return TRUE;
}
BOOL CXTPDockingPaneSidePanel::DoPropExchange(CXTPPropExchange* pPX)
{
CXTPDockingPaneBase::DoPropExchange(pPX);
int direction = m_direction;
PX_Int(pPX, _T("Direction"), direction);
PX_Rect(pPX, _T("WindowRect"), m_rcWindow, CRect(0, 0, 0, 0));
PX_Bool(pPX, _T("Collapsed"), m_bCollapsed, FALSE);
if (!pPX->IsLoading())
{
int nTopContainer = GetTopContainer() ? GetTopContainer()->m_nIndex : 0;
PX_Int(pPX, _T("TopContaner"), nTopContainer);
}
else
{
m_direction = (XTPDockingPaneDirection)direction;
int nTopContainer = 0;
PX_Int(pPX, _T("TopContaner"), nTopContainer);
if (nTopContainer == 0)
return FALSE;
CXTPPaneIndexToPaneMap* pMap = (CXTPPaneIndexToPaneMap*)pPX->m_dwData;
CXTPDockingPaneBase* pTop = (CXTPDockingPaneBase*)(*pMap)[nTopContainer];
if (!pTop || pTop->GetType() != xtpPaneTypeTabbedContainer)
return FALSE;
_InsertPane(pTop);
}
return TRUE;
}
BOOL CXTPDockingPaneAutoHidePanel::DoPropExchange(CXTPPropExchange* pPX)
{
CXTPDockingPaneBase::DoPropExchange(pPX);
int direction = m_direction;
PX_Int(pPX, _T("Direction"), direction);
int nCount = 0;
if (!pPX->IsLoading())
{
nCount = (int)m_lstPanes.GetCount();
PX_Int(pPX, _xtPanes, nCount);
int nIndex = 1;
TCHAR szPane[256];
POSITION pos = m_lstPanes.GetHeadPosition();
while (pos)
{
CXTPDockingPaneBase* pPane = m_lstPanes.GetNext(pos);
wsprintf(szPane, _xtPaneSection, nIndex++);
PX_Int(pPX, szPane, pPane->m_nIndex);
}
}
else
{
m_direction = (XTPDockingPaneDirection)direction;
PX_Int(pPX, _xtPanes, nCount, 0);
int nIndex = 0;
TCHAR szPane[256];
CXTPPaneIndexToPaneMap* pMap = (CXTPPaneIndexToPaneMap*)pPX->m_dwData;
for (int i = 1; i <= nCount; i++)
{
wsprintf(szPane, _xtPaneSection, i);
PX_Int(pPX, szPane, nIndex, 0);
ASSERT(nIndex > 0);
CXTPDockingPaneBase* pPane = NULL;
ASSERT(pMap->Lookup(nIndex, pPane));
pPane = (CXTPDockingPaneBase*)((*pMap)[nIndex]);
if (!pPane) return FALSE;
_InsertPane(pPane);
}
m_pLayout->m_wndPanels[m_direction] = this;
}
return TRUE;
}
BOOL CXTPDockingPaneTabbedContainer::DoPropExchange(CXTPPropExchange* pPX)
{
CXTPDockingPaneBase::DoPropExchange(pPX);
int nCount, nSelected;
if (!pPX->IsLoading())
{
nCount = (int)m_lstPanes.GetCount();
PX_Int(pPX, _xtPanes, nCount);
nSelected = m_pSelectedPane ? m_pSelectedPane->m_nIndex : 0;
PX_Int(pPX, _T("Selected"), nSelected, 0);
PX_Bool(pPX, _T("Maximized"), m_bMaximized, FALSE);
POSITION pos = m_lstPanes.GetHeadPosition();
int nIndex = 1;
while (pos)
{
CXTPDockingPaneBase* pPane = m_lstPanes.GetNext(pos);
TCHAR szPane[256];
wsprintf(szPane, _xtPaneSection, nIndex++);
PX_Int(pPX, szPane, pPane->m_nIndex);
}
}
else
{
PX_Int(pPX, _xtPanes, nCount);
PX_Int(pPX, _T("Selected"), nSelected, 0);
if (pPX->GetSchema() > _XTP_SCHEMA_1122)
{
PX_Bool(pPX, _T("Maximized"), m_bMaximized, FALSE);
}
TCHAR szPane[256];
CXTPDockingPane* pSelected = NULL;
int nIndex = 0;
CXTPPaneIndexToPaneMap* pMap = (CXTPPaneIndexToPaneMap*)pPX->m_dwData;
for (int i = 1; i <= nCount; i++)
{
wsprintf(szPane, _xtPaneSection, i);
PX_Int(pPX, szPane, nIndex, 0);
ASSERT(nIndex > 0);
CXTPDockingPaneBase* pPane = NULL;
ASSERT(pMap->Lookup(nIndex, pPane));
pPane = (CXTPDockingPaneBase*)((*pMap)[nIndex]);
if (!pPane || pPane->GetType() != xtpPaneTypeDockingPane) return FALSE;
_InsertPane((CXTPDockingPane*)pPane);
if (nIndex == nSelected) pSelected = (CXTPDockingPane*)pPane;
}
if (pSelected)
{
SelectPane(pSelected);
}
}
return TRUE;
}
BOOL CXTPDockingPaneMiniWnd::DoPropExchange(CXTPPropExchange* pPX)
{
CXTPDockingPaneBase::DoPropExchange(pPX);
PX_Long(pPX, _T("WindowRectTopPos"), m_rcWindow.top);
PX_Long(pPX, _T("WindowRectBottomPos"), m_rcWindow.bottom);
PX_Long(pPX, _T("WindowRectLeftPos"), m_rcWindow.left);
PX_Long(pPX, _T("WindowRectRightPos"), m_rcWindow.right);
PX_Bool(pPX, _T("Collapsed"), m_bCollapsed, FALSE);
PX_Int(pPX, _T("ExpandedHeight"), m_nExpandedHeight, 0);
if (!pPX->IsLoading())
{
int nTopContainer = m_pTopContainer ? m_pTopContainer->m_nIndex : 0;
PX_Int(pPX, _T("TopContaner"), nTopContainer);
}
else
{
int nTopContainer = 0;
PX_Int(pPX, _T("TopContaner"), nTopContainer);
if (nTopContainer == 0)
return FALSE;
CXTPPaneIndexToPaneMap* pMap = (CXTPPaneIndexToPaneMap*)pPX->m_dwData;
CXTPDockingPaneBase* pTop = (CXTPDockingPaneBase*)(*pMap)[nTopContainer];
if (!pTop || pTop->GetType() != xtpPaneTypeSplitterContainer)
return FALSE;
m_pTopContainer = (CXTPDockingPaneSplitterContainer*)pTop;
m_pTopContainer->m_pParentContainer = this;
}
return TRUE;
}
void CXTPDockingPaneLayout::Copy(const CXTPDockingPaneLayout* pLayout)
{
Free();
CXTPPaneToPaneMap map;
// Clone them
POSITION pos = pLayout->m_lstStack.GetHeadPosition();
while (pos)
{
CXTPDockingPaneBase* pPane = pLayout->m_lstStack.GetNext(pos);
if (pPane->m_pParentContainer == NULL) // hidden pane, top pane, miniwnd.
{
pPane->Clone(this, &map);
}
}
ASSERT(map.GetCount() == pLayout->m_lstStack.GetCount());
ASSERT(map.Lookup(pLayout->m_pClient, m_pClient));
ASSERT(map.Lookup(pLayout->m_pTopContainer, (CXTPDockingPaneBase*&)m_pTopContainer));
m_pClient = map[pLayout->m_pClient];
m_pTopContainer = (CXTPDockingPaneSplitterContainer*)map[pLayout->m_pTopContainer];
for (int i = 0; i < 4; i++)
if (pLayout->m_wndPanels[i]) m_wndPanels[i] = (CXTPDockingPaneAutoHidePanel*)map[pLayout->m_wndPanels[i]];
// Map Holders
pos = pLayout->m_lstPanes.GetHeadPosition();
while (pos)
{
XTP_DOCKINGPANE_INFO& info = pLayout->GetPaneList().GetNext(pos);
XTP_DOCKINGPANE_INFO infoCopy;
ASSERT(map.Lookup((CXTPDockingPaneBase*)info.pPane, (CXTPDockingPaneBase*&)infoCopy.pPane));
infoCopy.pPane = (CXTPDockingPane*)map[(CXTPDockingPaneBase*)info.pPane];
if (info.pDockingHolder) infoCopy.pDockingHolder = (CXTPDockingPaneBase*)map[info.pDockingHolder];
if (info.pLastHolder) infoCopy.pLastHolder = (CXTPDockingPaneBase*)map[info.pLastHolder];
if (info.pFloatingHolder) infoCopy.pFloatingHolder = (CXTPDockingPaneBase*)map[info.pFloatingHolder];
m_lstPanes.AddTail(infoCopy);
}
}
void CXTPDockingPaneLayout::_FreeEmptyPanes()
{
WORD w;
CMapPtrToWord map;
POSITION pos = m_lstPanes.GetHeadPosition();
while (pos)
{
XTP_DOCKINGPANE_INFO& info = m_lstPanes.GetNext(pos);
map.SetAt(info.pDockingHolder, TRUE);
map.SetAt(info.pFloatingHolder, TRUE);
map.SetAt(info.pPane->m_pParentContainer, TRUE);
}
BOOL bFound = TRUE;
while (bFound)
{
bFound = FALSE;
POSITION posRemove = pos = m_lstStack.GetHeadPosition();
while (pos)
{
CXTPDockingPaneBase* pPane = m_lstStack.GetNext(pos);
CXTPDockingPaneBase* pParentContainer = pPane->m_pParentContainer;
switch (pPane->GetType())
{
case xtpPaneTypeTabbedContainer:
if (!map.Lookup(pPane, w))
{
SAFE_CALLPTR(pParentContainer, RemovePane(pPane));
m_lstStack.RemoveAt(posRemove);
pPane->DeletePane();
bFound = TRUE;
}
break;
case xtpPaneTypeSplitterContainer:
if (((CXTPDockingPaneSplitterContainer*)pPane)->m_lstPanes.GetCount() == 0)
{
SAFE_CALLPTR(pParentContainer, RemovePane(pPane));
m_lstStack.RemoveAt(posRemove);
pPane->DeletePane();
bFound = TRUE;
}
else if (pParentContainer && (pParentContainer->GetType() == xtpPaneTypeSplitterContainer)
&& (((CXTPDockingPaneSplitterContainer*)pPane)->m_lstPanes.GetCount() == 1)
&& (((CXTPDockingPaneSplitterContainer*)pParentContainer)->m_lstPanes.GetCount() == 1))
{
CXTPDockingPaneBase* pChildPane = ((CXTPDockingPaneSplitterContainer*)pPane)->m_lstPanes.RemoveHead();
((CXTPDockingPaneSplitterContainer*)pParentContainer)->m_lstPanes.RemoveHead();
((CXTPDockingPaneSplitterContainer*)pParentContainer)->m_lstPanes.AddHead(pChildPane);
pChildPane->m_pParentContainer = pParentContainer;
m_lstStack.RemoveAt(posRemove);
pPane->DeletePane();
bFound = TRUE;
}
break;
case xtpPaneTypeMiniWnd:
if (((CXTPDockingPaneMiniWnd*)pPane)->m_pTopContainer == NULL)
{
m_lstStack.RemoveAt(posRemove);
pPane->DeletePane();
bFound = TRUE;
}
break;
case xtpPaneTypeSidePanel:
if (((CXTPDockingPaneSidePanel*)pPane)->m_lstPanes.GetCount() == 0)
{
m_lstStack.RemoveAt(posRemove);
pPane->DeletePane();
bFound = TRUE;
}
break;
}
posRemove = pos;
}
}
}
XTP_DOCKINGPANE_INFO* CXTPDockingPaneLayout::FindPaneInfo(CXTPDockingPane* pPane)
{
POSITION pos = m_lstPanes.GetHeadPosition();
while (pos)
{
XTP_DOCKINGPANE_INFO& info = m_lstPanes.GetNext(pos);
if (info.pPane == pPane)
return &info;
}
return 0;
}
XTPDockingPaneDirection CXTPDockingPaneLayout::_GetPaneDirection(const CXTPDockingPaneBase* pPane) const
{
if (pPane->GetType() == xtpPaneTypeMiniWnd)
return (XTPDockingPaneDirection)4;
if (!pPane->m_pParentContainer || pPane->GetType() == xtpPaneTypeClient)
return (XTPDockingPaneDirection)-1;
if (pPane->m_pParentContainer->GetType() == xtpPaneTypeAutoHidePanel)
{
return ((CXTPDockingPaneAutoHidePanel*)pPane->m_pParentContainer)->m_direction;
}
if (pPane->GetType() == xtpPaneTypeSidePanel)
{
return ((CXTPDockingPaneSidePanel*)pPane)->m_direction;
}
if (pPane->m_pParentContainer->GetType() == xtpPaneTypeSplitterContainer)
{
POSITION pos = pPane->m_pParentContainer->ContainPane(m_pClient);
if (pos)
{
CXTPDockingPaneSplitterContainer* pSplitter = (CXTPDockingPaneSplitterContainer*)pPane->m_pParentContainer;
if (pSplitter->_Before(pPane, pos))
{
return pSplitter->IsHoriz() ? xtpPaneDockLeft : xtpPaneDockTop;
}
else
{
return pSplitter->IsHoriz() ? xtpPaneDockRight : xtpPaneDockBottom;
}
}
}
return _GetPaneDirection(pPane->m_pParentContainer);
}
void CXTPDockingPaneLayout::_AddPanesTo(CXTPDockingPaneTabbedContainer* pContainer, CXTPDockingPaneBaseList& lst, DWORD dwIgnoredOptions)
{
POSITION pos = lst.GetHeadPosition();
while (pos)
{
CXTPDockingPane* pPane = (CXTPDockingPane*)lst.GetNext(pos);
if ((((CXTPDockingPane*)pPane)->GetOptions() & dwIgnoredOptions) == 0)
{
SAFE_CALLPTR(pPane->m_pParentContainer, RemovePane(pPane));
pContainer->_InsertPane(pPane);
}
}
}
BOOL CXTPDockingPaneLayout::_FindTabbedPaneToHide(CXTPDockingPaneAutoHidePanel* pPanel, CXTPDockingPaneBase* pPane)
{
CXTPDockingPaneBaseList lst;
pPane->FindPane(xtpPaneTypeDockingPane, &lst);
if (lst.IsEmpty())
return FALSE;
CXTPDockingPane* pPanePrimary = (CXTPDockingPane*)lst.GetHead();
XTP_DOCKINGPANE_INFO* pInfo = FindPaneInfo(pPanePrimary);
if (!pInfo || pInfo->pDockingHolder == NULL)
return FALSE;
POSITION pos = pPanel->m_lstPanes.GetHeadPosition();
while (pos)
{
CXTPDockingPaneTabbedContainer* pContainer = (CXTPDockingPaneTabbedContainer*)pPanel->m_lstPanes.GetNext(pos);
CXTPDockingPane* pContainerPane = (CXTPDockingPane*)pContainer->GetFirstPane();
if (pContainerPane)
{
XTP_DOCKINGPANE_INFO* pContanerPaneInfo = FindPaneInfo(pContainerPane);
if (pContanerPaneInfo && pContanerPaneInfo->pDockingHolder == pInfo->pDockingHolder)
{
_AddPanesTo(pContainer, lst, xtpPaneNoHideable);
return TRUE;
}
}
}
return FALSE;
}
void CXTPDockingPaneLayout::HidePane(CXTPDockingPaneBase* pPane)
{
ASSERT(!m_bUserLayout);
XTPDockingPaneDirection direction = _GetPaneDirection(pPane);
if (direction < 0 || direction >= 4)
direction = xtpPaneDockLeft;
if (m_wndPanels[direction] == 0)
{
m_wndPanels[direction] = (CXTPDockingPaneAutoHidePanel*)m_pManager->
OnCreatePane(xtpPaneTypeAutoHidePanel, this);
m_wndPanels[direction]->m_direction = direction;
}
if (_FindTabbedPaneToHide(m_wndPanels[direction], pPane))
return;
if (pPane->GetType() == xtpPaneTypeDockingPane)
{
pPane->m_pParentContainer->RemovePane(pPane);
CXTPDockingPaneTabbedContainer* pContainer = (CXTPDockingPaneTabbedContainer*)m_pManager->
OnCreatePane(xtpPaneTypeTabbedContainer, this);
pContainer->Init((CXTPDockingPane*)pPane, m_pManager->GetSite());
pPane = pContainer;
}
else if (pPane->GetType() == xtpPaneTypeTabbedContainer)
{
pPane = ((CXTPDockingPaneBase*)pPane)->Clone(this, 0, xtpPaneNoHideable);
}
m_wndPanels[direction]->_InsertPane(pPane);
}
void CXTPDockingPaneLayout::RepositionMargins(CRect& rect, const CRect& rcClientMargins)
{
int i;
if (rcClientMargins.IsRectNull())
{
for (i = 0; i < 4; i++)
{
SAFE_DELETE(m_wndMargins[i]);
}
return;
}
for (i = 0; i < 4; i++)
{
if (m_wndMargins[i] == 0)
{
m_wndMargins[i] = new CXTPDockingPaneSplitterWnd();
m_wndMargins[i]->Create(m_pManager, i == xtpPaneDockTop || i == xtpPaneDockBottom);
}
}
CRect rcClient(rect);
rcClient.DeflateRect(rcClientMargins);
m_wndMargins[xtpPaneDockLeft]->MoveWindow(CRect(rect.left, rect.top, rcClient.left, rect.bottom));
m_wndMargins[xtpPaneDockRight]->MoveWindow(CRect(rcClient.right , rect.top, rect.right, rect.bottom));
m_wndMargins[xtpPaneDockTop]->MoveWindow(CRect(rcClient.left, rect.top, rcClient.right, rcClient.top));
m_wndMargins[xtpPaneDockBottom]->MoveWindow(CRect(rcClient.left, rcClient.bottom, rcClient.right, rect.bottom));
for (i = 0; i < 4; i++)
{
m_wndMargins[i]->Invalidate(FALSE);
}
rect = rcClient;
}
void CXTPDockingPaneLayout::OnSizeParent(CWnd* pParent, CRect rect, LPVOID lParam)
{
AFX_SIZEPARENTPARAMS* lpLayout = (AFX_SIZEPARENTPARAMS*)lParam;
for (int i = 0; i < 4; i++)
{
SAFE_CALLPTR(m_wndPanels[i], OnSizeParentEx(pParent, rect, lParam));
}
int nMargin = m_pManager->GetClientMargin();
CRect rcClientMargins(nMargin, nMargin, nMargin, nMargin);
if (lpLayout->hDWP != NULL)
{
RepositionMargins(rect, rcClientMargins);
}
else
{
rect.DeflateRect(rcClientMargins);
}
m_pClient->OnSizeParent(pParent, rect, lParam);
m_pTopContainer->OnSizeParent(pParent, rect, lParam);
if (lpLayout->hDWP)
{
CXTPDockingPaneSidePanel::OnSizeParentEx(m_pManager, pParent, lpLayout->rect);
}
}
CXTPDockingPane* CXTPDockingPaneLayout::FindPane(int nID) const
{
POSITION pos = m_lstPanes.GetHeadPosition();
while (pos)
{
XTP_DOCKINGPANE_INFO info = m_lstPanes.GetNext(pos);
CXTPDockingPane* pPane = info.pPane;
if (pPane->GetID() == nID)
return pPane;
}
return NULL;
}
void CXTPDockingPaneLayout::DestroyPane(CXTPDockingPane* pPane)
{
if (pPane == NULL) return;
SAFE_CALLPTR(pPane->m_pParentContainer, RemovePane(pPane));
POSITION pos = m_lstPanes.GetHeadPosition();
while (pos)
{
if (m_lstPanes.GetAt(pos) == pPane)
{
m_lstPanes.RemoveAt(pos);
break;
}
m_lstPanes.GetNext(pos);
}
pos = m_lstStack.GetHeadPosition();
while (pos)
{
if (m_lstStack.GetAt(pos) == pPane)
{
m_lstStack.RemoveAt(pos);
break;
}
m_lstStack.GetNext(pos);
}
((CXTPDockingPane*)pPane)->InternalRelease();
_FreeEmptyPanes();
}
void CXTPDockingPaneLayout::MoveToTail(CXTPDockingPaneBase* pPane)
{
POSITION pos = m_lstStack.GetHeadPosition();
while (pos)
{
if (m_lstStack.GetAt(pos) == pPane)
{
m_lstStack.RemoveAt(pos);
m_lstStack.AddTail(pPane);
return;
}
m_lstStack.GetNext(pos);
}
}