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::_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;
}
void CXTPDockingPaneTabbedContainer::Maximize()
{
	if (!m_pDockingSite || !m_pParentContainer)
		return;

	CXTPDockingPaneBaseList lst;
	((CXTPDockingPaneSplitterContainer*)m_pParentContainer)->FindChildPane(xtpPaneTypeTabbedContainer, &lst);
	POSITION pos = lst.GetHeadPosition();
	while (pos)
	{
		CXTPDockingPaneTabbedContainer* pTabbedContainer = (CXTPDockingPaneTabbedContainer*)lst.GetNext(pos);
		pTabbedContainer->m_bMaximized = pTabbedContainer == this;
	}

	GetDockingPaneManager()->RecalcFrameLayout(this);
}
BOOL CXTPDockingPaneSidePanel::Init(CXTPDockingPaneBase* pBasePane, XTPDockingPaneDirection direction, CRect rc)
{
	CXTPDockingPaneBaseList lstPanes;
	pBasePane->FindPane(xtpPaneTypeDockingPane, &lstPanes);
	if (lstPanes.GetCount() == 0)
		return FALSE;

	m_direction = direction;
	m_rcWindow = rc;
	CreateContainer();

	CXTPDockingPaneTabbedContainer* pContainer = (CXTPDockingPaneTabbedContainer*)GetDockingPaneManager()->
		OnCreatePane(xtpPaneTypeTabbedContainer, m_pLayout);

	BOOL bInit = FALSE;

	POSITION pos = lstPanes.GetHeadPosition();
	while (pos)
	{
		CXTPDockingPane* pPane = (CXTPDockingPane*)lstPanes.GetNext(pos);

		if (pPane->GetContainer())
		{
			pPane->GetContainer()->RemovePane(pPane);
		}

		if (!bInit)
		{
			pContainer->Init((CXTPDockingPane*)pPane, this);
		}
		else
		{
			pContainer->_InsertPane(pPane, FALSE);
		}
		bInit = TRUE;
	}

	_InsertPane(pContainer);

	OnFocusChanged();

	m_nIdleFlags = 0;

	return TRUE;
}
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);

}
BOOL CXTPDockingPaneTabbedContainer::IsPaneMinimized() const
{
	if (m_bMaximized)
		return FALSE;

	if (!m_pParentContainer || m_pParentContainer->GetType() != xtpPaneTypeSplitterContainer)
		return FALSE;

	if (!GetDockingPaneManager()->IsCaptionMaximizeButtonsVisible())
		return FALSE;

	CXTPDockingPaneBaseList lst;
	((CXTPDockingPaneSplitterContainer*)m_pParentContainer)->FindChildPane(xtpPaneTypeTabbedContainer, &lst);
	POSITION pos = lst.GetHeadPosition();
	while (pos)
	{
		CXTPDockingPaneTabbedContainer* pTabbedContainer = (CXTPDockingPaneTabbedContainer*)lst.GetNext(pos);
		if (pTabbedContainer->m_bMaximized)
			return TRUE;
	}
	return FALSE;
}
BOOL CXTPDockingPaneTabbedContainer::IsAllowMaximize() const
{
	if (!m_pParentContainer || m_pParentContainer->GetType() != xtpPaneTypeSplitterContainer)
		return FALSE;

	if (!GetDockingPaneManager()->IsCaptionMaximizeButtonsVisible())
		return FALSE;

	CXTPDockingPaneBaseList lst;
	((CXTPDockingPaneSplitterContainer*)m_pParentContainer)->FindChildPane(xtpPaneTypeTabbedContainer, &lst);

	if (lst.GetCount() < 2)
		return FALSE;

	lst.RemoveAll();
	((CXTPDockingPaneSplitterContainer*)m_pParentContainer)->FindChildPane(xtpPaneTypeClient, &lst);

	if (!lst.IsEmpty())
		return FALSE;


	return TRUE;
}
void CXTPDockingPaneSidePanel::OnCaptionButtonClick(CXTPDockingPaneCaptionButton* pButton)
{
	CXTPDockingPaneManager* pManager = GetDockingPaneManager();

	switch (pButton->GetID())
	{
		case XTP_IDS_DOCKINGPANE_CLOSE:
			{
				CXTPDockingPaneBaseList lstPanes;
				FindPane(xtpPaneTypeDockingPane, &lstPanes);

				POSITION pos = lstPanes.GetTailPosition();
				while (pos)
				{
					CXTPDockingPane* pPane = (CXTPDockingPane*)lstPanes.GetPrev(pos);

					if ((pPane->GetOptions() & xtpPaneNoCloseable) != 0)
						continue;

					pPane->InternalAddRef();

					if (!pManager->NotifyAction(xtpPaneActionClosing, pPane))
					{
						pPane->Close();
						pManager->NotifyAction(xtpPaneActionClosed, pPane);
					}

					pPane->InternalRelease();
				}
			}
			break;

		case XTP_IDS_DOCKINGPANE_AUTOHIDE:
			OnPinButtonClick();
			break;
	}
}
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();
			}
		}
	}
}
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;
}