Click here to Skip to main content
15,886,518 members
Articles / Desktop Programming / MFC

Professional User Interface Suite

Rate me:
Please Sign up or sign in to vote.
4.99/5 (174 votes)
13 Jan 200423 min read 1.5M   23.6K   641  
MFC extension library enabling software to be provided with a professional UI
// This is part of the Professional User Interface Suite library.
// Copyright (C) 2001-2004 FOSS Software, Inc.
// All rights reserved.
//
// http://www.prof-uis.com
// http://www.fossware.com
// mailto:foss@fossware.com
//
// This source code can be used, modified and redistributed
// under the terms of the license agreement that is included
// in the Professional User Interface Suite package.
//
// Warranties and Disclaimers:
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND
// INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
// IN NO EVENT WILL FOSS SOFTWARE INC. BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES,
// INCLUDING DAMAGES FOR LOSS OF PROFITS, LOSS OR INACCURACY OF DATA,
// INCURRED BY ANY PERSON FROM SUCH PERSON'S USAGE OF THIS SOFTWARE
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

#include "stdafx.h"

#if (!defined __EXTDOCKBAR_H)
	#include "ExtDockBar.h"
#endif

#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
	#if (!defined __EXT_CONTROLBAR_TABBED_FEATURES_H)
		#include "ExtControlBarTabbedFeatures.h"
	#endif // __EXT_CONTROLBAR_TABBED_FEATURES_H
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)

#if _MFC_VER < 0x700
	#include <../src/AfxImpl.h>
#else
	#include <../src/mfc/AfxImpl.h>
#endif

#if (!defined __EXT_MEMORY_DC_H)
	#include <../Src/ExtMemoryDC.h>
#endif

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	#if (!defined __EXTCUSTOMIZE_H)
		#include <ExtCustomize.h>
	#endif
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

#include <../profuisdll/resource.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////
// CExtDockBar window

IMPLEMENT_DYNCREATE(CExtDockBar, CDockBar);

BEGIN_MESSAGE_MAP(CExtDockBar, CDockBar)
	//{{AFX_MSG_MAP(CExtDockBar)
	//}}AFX_MSG_MAP
	ON_WM_CONTEXTMENU()
	ON_WM_CANCELMODE()
	ON_WM_ERASEBKGND()
	ON_MESSAGE(WM_SIZEPARENT, OnSizeParent)
	ON_WM_NCCALCSIZE()
	ON_WM_NCPAINT()
	ON_WM_DESTROY()
	ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest)
END_MESSAGE_MAP()

bool CExtDockBar::g_bControlBarFixSizePixel = true;
bool CExtDockBar::g_bExtendedRepositioning = false;
bool CExtDockBar::g_bDockBarClassRegistered = false;

CExtDockBar::CExtDockBar(
	UINT nCircleNo // = 0
	)
	: m_nCircleNo( nCircleNo )
	, m_bLockedOptimize( false )
	, m_pDockBarOuter( NULL )
	, m_pDockBarInner( NULL )
	, m_rcLastInvisiblePreCalc( 0, 0, 0, 0 )
	, m_bInDynamicLayoutUpdate( false )
#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
	, m_pWndAutoHideArea( NULL )
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
{
	VERIFY( RegisterDockBarClass() );
}

bool CExtDockBar::RegisterDockBarClass()
{
	if( g_bDockBarClassRegistered )
		return true;

WNDCLASS wndclass;
HINSTANCE hInst = AfxGetInstanceHandle();
	if( ! ::GetClassInfo(
			hInst,
			__EXT_DOCKBAR_CLASS_NAME,
			&wndclass
			)
		)
	{
		// otherwise we need to register a new class
		wndclass.style = CS_GLOBALCLASS;
		wndclass.lpfnWndProc = ::DefWindowProc;
		wndclass.cbClsExtra = wndclass.cbWndExtra = 0;
		wndclass.hInstance = hInst;
		wndclass.hIcon = NULL;
		wndclass.hCursor =
				::LoadCursor(
					NULL, //hInst,
					IDC_ARROW
					)
				;
		ASSERT( wndclass.hCursor != NULL );
		wndclass.hbrBackground = NULL;
		wndclass.lpszMenuName = NULL;
		wndclass.lpszClassName = __EXT_DOCKBAR_CLASS_NAME;
		if( !::AfxRegisterClass( &wndclass ) )
		{
			ASSERT( FALSE );
			//AfxThrowResourceException();
			return false;
		}
	}

	g_bDockBarClassRegistered = true;
	return true;
}

void CExtDockBar::PreSubclassWindow()
{
	CDockBar::PreSubclassWindow();
}

BOOL CExtDockBar::PreCreateWindow(CREATESTRUCT& cs)
{
	if( ( !RegisterDockBarClass() )
		|| ( !CWnd::PreCreateWindow(cs) )
		)
	{
		ASSERT( FALSE );
		return FALSE;
	}
	
	cs.lpszClass = __EXT_DOCKBAR_CLASS_NAME;

	return TRUE;
}

LRESULT CExtDockBar::OnHelpHitTest(WPARAM wParam, LPARAM lParam)
{
	wParam;
	lParam;
	return 0L;
}

#if (!defined __EXT_MFC_NO_CUSTOMIZE)

void CExtDockBar::OnCustomizeModeEnter()
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
	if( _GetCircleNo() > 0 )
		return;
	if( m_pWndAutoHideArea == NULL )
		return;
	ASSERT_VALID( m_pWndAutoHideArea );
	m_pWndAutoHideArea->OnCustomizeModeEnter();
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
}

void CExtDockBar::OnCustomizeModeLeave()
{
	ASSERT_VALID( this );
#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
	if( _GetCircleNo() > 0 )
		return;
	if( m_pWndAutoHideArea == NULL )
		return;
	ASSERT_VALID( m_pWndAutoHideArea );
	m_pWndAutoHideArea->OnCustomizeModeLeave();
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
}

#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

void CExtDockBar::OnCancelMode()
{
	ASSERT_VALID( this );
	CDockBar::OnCancelMode();

BOOL bHelpMode =
		::AfxGetApp()->m_bHelpMode
		|| CExtControlBar::FindHelpMode( this )
		;
	if( !bHelpMode )
		CExtPopupMenuWnd::CancelMenuTracking();
	CWnd::CancelToolTips();
	//ASSERT( !CExtPopupMenuWnd::IsMenuTracking() );
}

CFrameWnd * CExtDockBar::_GetDockingFrameImpl()
{
	ASSERT_VALID( this );
	return
		CExtControlBar::_GetDockingFrameImpl( (CControlBar *)this );
}

#if (!defined __EXT_MFC_NO_CUSTOMIZE)

bool CExtDockBar::_AppendAddRemoveButtonsCustomizeMenu(
	CExtPopupMenuWnd * pPopup,
	CControlBar * pBarEventSrc
	)
{
	ASSERT_VALID( pPopup );
	ASSERT_VALID( pBarEventSrc );
	ASSERT( pBarEventSrc->GetSafeHwnd() != NULL && ::IsWindow(pBarEventSrc->GetSafeHwnd()) );
	if( !pBarEventSrc->IsKindOf(RUNTIME_CLASS(CExtToolControlBar)) )
	{
		ASSERT( FALSE );
		return false;
	}
CExtCustomizeSite * pSite =
		CExtCustomizeSite::GetCustomizeSite( pBarEventSrc->m_hWnd );
	if( pSite == NULL )
		return true;
	if( !pSite->BarIsRegistered((CExtToolControlBar*)pBarEventSrc) )
		return true;
	pSite->BarDefCmdTargetSet((CExtToolControlBar*)pBarEventSrc);
bool bUserBar = false;
	VERIFY(
		pSite->GetToolbarCustomizeInfo(
			(CExtToolControlBar*)pBarEventSrc, NULL, NULL, NULL,
			&bUserBar
			)
		);

CExtCmdItem * pCmdItem =
		g_CmdManager->CmdGetPtr(
			g_CmdManager->ProfileNameFromWnd( pBarEventSrc->m_hWnd ),
			ID_EXT_ADD_REMOVE_BUTTONS
			);
CExtSafeString strAddRemoveButtons;
	if( pCmdItem )
		strAddRemoveButtons = pCmdItem->m_sMenuText;
	if( strAddRemoveButtons.IsEmpty() )
		strAddRemoveButtons = _T("&Add/remove buttons");
	VERIFY(
		pPopup->ItemInsert(
			(UINT)CExtPopupMenuWnd::TYPE_POPUP,
			-1,
			strAddRemoveButtons
			)
		);
CExtPopupMenuWnd::MENUITEMDATA & miARB =
		pPopup->ItemGetInfo( pPopup->ItemGetCount() - 1 );
	miARB.SetChildCombine();
	miARB.SetToolButton();
CExtPopupMenuWnd * pAddRemoveButtons = miARB.GetPopup();
	ASSERT( pAddRemoveButtons != NULL );
	
	VERIFY( pAddRemoveButtons->ItemInsert( ID_EXT_CUSTOMIZE ) );
CExtPopupMenuWnd::MENUITEMDATA & miCustomize =
		pAddRemoveButtons->ItemGetInfo(
			pAddRemoveButtons->ItemGetCount() - 1
			);
	miCustomize.SetForceEnabled();

	if( !bUserBar )
	{
		bool bAddResetBarHere = true;
		if( pBarEventSrc->m_pDockBar != NULL )
		{
			ASSERT_VALID( pBarEventSrc->m_pDockBar );
			MfcControlBarVector_t vBars;
			if( pBarEventSrc->IsFloating() )
				vBars.Add( pBarEventSrc );
			else
			{
				int nPos = pBarEventSrc->m_pDockBar->FindBar( pBarEventSrc );
				ASSERT( nPos >= 0 && nPos < pBarEventSrc->m_pDockBar->m_arrBars.GetSize() );
				for( nPos--; nPos >= 0 && pBarEventSrc->m_pDockBar->m_arrBars[nPos] != NULL; nPos-- );
				nPos++;
				ASSERT( nPos >= 0 && nPos < pBarEventSrc->m_pDockBar->m_arrBars.GetSize() );
				for( ; pBarEventSrc->m_pDockBar->m_arrBars[nPos] != NULL && nPos < pBarEventSrc->m_pDockBar->m_arrBars.GetSize(); nPos++ )
				{
					CControlBar * pBarInRow = (CControlBar *)pBarEventSrc->m_pDockBar->m_arrBars[nPos];
					if( pBarInRow == NULL || __PLACEHODLER_BAR_PTR(pBarInRow) )
						continue;
					ASSERT_VALID( pBarInRow );
					ASSERT_KINDOF( CControlBar, pBarInRow );
					if( !pBarInRow->IsKindOf(RUNTIME_CLASS(CExtToolControlBar)) )
						continue;
					vBars.Add( pBarInRow );
				}
			} // else from if( pBarEventSrc->IsFloating() )
			int nCount = vBars.GetSize();
			ASSERT( nCount >= 1 );
			for( int i = 0; i < nCount; )
			{
				CExtToolControlBar * pBar = (CExtToolControlBar*)vBars[i];
				ASSERT_VALID( pBar );
				ASSERT_KINDOF( CExtToolControlBar, pBar );
				if(		( !pSite->BarIsRegistered(pBar) )
					||	( !pBar->OnCustomizeCanShowHideButtons() )
					)
				{
					vBars.RemoveAt( i );
					nCount--;
					continue;
				}
				bool bUserItem = false;
				VERIFY(
					pSite->GetToolbarCustomizeInfo(
						pBar, NULL, NULL, NULL,
						&bUserItem
						)
					);
				if( bUserItem )
				{
					vBars.RemoveAt( i );
					nCount--;
					continue;
				}
				i++;
			} // for( int i = 0; i < nCount; i++ )
			ASSERT( nCount == vBars.GetSize() );
			if( nCount > 0 )
			{
				bAddResetBarHere = false;
				for( i = 0; i < nCount; i++ )
				{
					CExtToolControlBar * pBar = (CExtToolControlBar*)vBars[i];
					ASSERT_VALID( pBar );
					ASSERT_KINDOF( CExtToolControlBar, pBar );
					CString sBarName;
					pBar->GetWindowText( sBarName );
					VERIFY(
						pAddRemoveButtons->ItemInsert(
							(UINT)CExtPopupMenuWnd::TYPE_POPUP,
							i,
							(LPCTSTR)sBarName
							)
						);
					CExtPopupMenuWnd::MENUITEMDATA & mi = pAddRemoveButtons->ItemGetInfo(i);
					CExtPopupMenuWnd * pFolder = mi.GetPopup();
					ASSERT_VALID( pFolder );
					pBar->OnCustomizeInitShowHideButtonMenu( pFolder );
					ASSERT( pFolder->ItemGetCount() > 0 );
					VERIFY( pFolder->ItemInsert() );
					VERIFY( pFolder->ItemInsert( ID_EXT_RESET_TOOLBAR ) );
					CExtPopupMenuWnd::MENUITEMDATA & miResetToolbar =
						pFolder->ItemGetInfo(
							pFolder->ItemGetCount() - 1
							);
					miResetToolbar.SetForceEnabled();
					miResetToolbar.SetCmdDeliverCb(
						(CExtPopupMenuWnd::MENUITEMDATA::pCbItemClick)
							CExtToolControlBar::stat_CbCmdDeliver
						);
					miResetToolbar.LParamSet( (LPARAM)pBar );
				} // for( i = 0; i < nCount; i++ )
				VERIFY(
					pAddRemoveButtons->ItemInsert(
						(UINT)CExtPopupMenuWnd::TYPE_SEPARATOR,
						i
						)
					);
			} // if( nCount > 0 )
		} // if( pBarEventSrc->m_pDockBar != NULL )
		if( bAddResetBarHere )
		{
			VERIFY( pAddRemoveButtons->ItemInsert( ID_EXT_RESET_TOOLBAR ) );
			CExtPopupMenuWnd::MENUITEMDATA & miResetToolbar =
				pAddRemoveButtons->ItemGetInfo(
					pAddRemoveButtons->ItemGetCount() - 1
					);
			miResetToolbar.SetForceEnabled();
			miResetToolbar.SetCmdDeliverCb(
				(CExtPopupMenuWnd::MENUITEMDATA::pCbItemClick)
					CExtToolControlBar::stat_CbCmdDeliver
				);
			miResetToolbar.LParamSet( (LPARAM)pBarEventSrc );
		} // if( bAddResetBarHere )
	} // if( !bUserBar )
	
	return true;
}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

bool CExtDockBar::_ConstructDockSiteControlBarPopupMenu(
	CFrameWnd * pFrame,
	CExtPopupMenuWnd * pPopup,
	SHORT nHelperNotificationType,
	CControlBar * pBarEventSrc,
	UINT nMsgID, // = WM_NULL
	CObject * pObjectSrc // = NULL
	)
{
	ASSERT_VALID( pFrame );
	ASSERT( pPopup != NULL );

CExtControlBar::POPUP_MENU_EVENT_DATA _pmed(
		nHelperNotificationType,
		pPopup,
		pBarEventSrc,
		CPoint( -1, -1 ),
		nMsgID,
		pObjectSrc
		);
bool bPreNotificationPassed = _pmed.NotifyTarget( false );
	if( !bPreNotificationPassed )
	{
		ExtControlBarVector_t vBars;
		CExtControlBar::_GetFrameControlBars(
			pFrame,
			vBars
			);
		bool bOleInplaceItemActivated =
			CExtControlBar::IsOleIpObjActive( pFrame );

		int nBarsCount = vBars.GetSize();
		CExtControlBar * pPrevBar = NULL;
		for( int i=0; i<nBarsCount; i++ )
		{
			CExtControlBar * pBar = vBars[i];
			ASSERT_VALID( pBar );
			if( pBar->GetSafeHwnd() == NULL
				|| ( ! ::IsWindow(pBar->GetSafeHwnd()) )
				)
				continue;
			// do not include dynamic bars
			if( pBar->IsKindOf( RUNTIME_CLASS(CExtDynControlBar) ) )
				continue;

			// do not include temporary hidden bars
			if( pBar->m_nStateFlags &
					//(CControlBar::delayHide | CControlBar::tempHide)
					CControlBar::tempHide
				)
				continue;
			// do not include some bars when OLE inplace object active
			if( bOleInplaceItemActivated &&
					(pBar->m_dwStyle & CBRS_HIDE_INPLACE)
				)
				continue;

			// do not include bars without caption
			CString sBarText;
			pBar->GetWindowText( sBarText );
			if( sBarText.IsEmpty() )
			{
				// do not include bars without window text to menu
				// ASSERT( FALSE );
				continue;
			}

			if( pPrevBar != NULL
				&&
				pPrevBar->IsFixedDockStyle() != pBar->IsFixedDockStyle()
				)
			{
				VERIFY(
					pPopup->ItemInsert(
						CExtPopupMenuWnd::TYPE_SEPARATOR
						)
					);
			}

			int nBarID = pBar->GetDlgCtrlID();
			ASSERT( CExtCmdManager::IsCommand(nBarID) );
			
			CExtCmdItem _cmd;
			_cmd.m_nCmdID = nBarID;
			_cmd.m_sMenuText = sBarText;
			_cmd.TipsLoad();
			g_CmdManager->CmdSetup(
				g_CmdManager->ProfileNameFromWnd( pFrame->GetSafeHwnd() ),
				_cmd
				);

			if( pBar->OnConstructDockSiteControlBarPopupMenu(pPopup) )
				pPrevBar = pBar;

		} // for( int i=0; i<nBarsCount; i++ )

	} // if( !bPreNotificationPassed )

	// remove double separators
INT nCount = pPopup->ItemGetCount();
	for( INT nItem = 1; nItem < nCount; )
	{
		CExtPopupMenuWnd::MENUITEMDATA & _miiPrev =
			pPopup->ItemGetInfo( nItem - 1 );
		if( !_miiPrev.IsSeparator() )
		{
			nItem++;
			continue;
		}
		CExtPopupMenuWnd::MENUITEMDATA & _miiCurr =
			pPopup->ItemGetInfo( nItem );
		if( !_miiCurr.IsSeparator() )
		{
			nItem++;
			continue;
		}
		pPopup->ItemRemove( nItem );
		nCount--;
	} // for( INT nItem = 1; nItem < nCount; )

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	if(		(!bPreNotificationPassed)
		&&	(	nHelperNotificationType == CExtControlBar::POPUP_MENU_EVENT_DATA::__PMED_CONTROLBAR_CTX
			||	nHelperNotificationType == CExtControlBar::POPUP_MENU_EVENT_DATA::__PMED_CONTROLBAR_NC_CTX
			||	nHelperNotificationType == CExtControlBar::POPUP_MENU_EVENT_DATA::__PMED_DOCKBAR_CTX
			||	nHelperNotificationType == CExtControlBar::POPUP_MENU_EVENT_DATA::__PMED_STATUSBAR_CTX
			||	nHelperNotificationType == CExtControlBar::POPUP_MENU_EVENT_DATA::__PMED_MINIFRAME_NC_CTX
			)
		&&	CExtCustomizeSite::GetCustomizeSite(
				pBarEventSrc->GetSafeHwnd()
				) != NULL
		)
	{ // add customize command
		// add tail separator
		nCount = pPopup->ItemGetCount();
		if( nCount > 0 )
		{
			CExtPopupMenuWnd::MENUITEMDATA & _mii =
				pPopup->ItemGetInfo( nCount - 1 );
			if( !_mii.IsSeparator() )
				pPopup->ItemInsert();
		} // if( nCount > 0 )
		VERIFY( pPopup->ItemInsert( ID_EXT_CUSTOMIZE ) );
		CExtPopupMenuWnd::MENUITEMDATA & mi =
			pPopup->ItemGetInfo(
				pPopup->ItemGetCount() - 1
				);
		mi.SetForceEnabled();
	} // add customize command
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

	_pmed.NotifyTarget( true );

	// remove tail separator
	nCount = pPopup->ItemGetCount();
	if( nCount > 0 )
	{
		CExtPopupMenuWnd::MENUITEMDATA & _mii =
			pPopup->ItemGetInfo( nCount - 1 );
		if( _mii.IsSeparator() )
			pPopup->ItemRemove( nCount - 1 );
	} // if( nCount > 0 )

	return true;
}

void CExtDockBar::OnContextMenu(CWnd* pWnd, CPoint point)
{
	ASSERT_VALID( this );
	pWnd;

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeSite * pSite =
		CExtCustomizeSite::GetCustomizeSite( m_hWnd );
	if(		pSite != NULL
		&&	pSite->IsCustomizeMode()
		)
		return;
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

	if( CExtControlBar::FindHelpMode(this) )
		return;

	// find any control bar
CControlBar * pBar = NULL;
	for( int nPos = 0; nPos < m_arrBars.GetSize(); nPos++ )
	{
		pBar = GetDockedControlBar(nPos);
		if( pBar != NULL )
		{
			ASSERT_VALID( pBar );
			break;
		}
	}
	if( pBar == NULL )
		return;

CFrameWnd * pFrame = _GetDockingFrameImpl();
HWND hWndTrack = pBar->GetOwner()->GetSafeHwnd();
	ASSERT( hWndTrack != NULL && ::IsWindow(hWndTrack) );
CExtPopupMenuWnd * pPopup = new CExtPopupMenuWnd;
	VERIFY( pPopup->CreatePopupMenu(hWndTrack) );

	if(	! _ConstructDockSiteControlBarPopupMenu(
			pFrame,
			pPopup,
			CExtControlBar::POPUP_MENU_EVENT_DATA::__PMED_DOCKBAR_CTX,
			this,
			WM_CONTEXTMENU,
			NULL
			)
		)
	{
		delete pPopup;
		return;
	}
	if( pPopup->ItemGetCount() == 0 )
	{
		delete pPopup;
		return;
	}
	::SetFocus( hWndTrack );
	if( ! pPopup->TrackPopupMenu(
			TPMX_OWNERDRAW_FIXED,
			point.x,
			point.y
			)
		)
	{
		delete pPopup;
	}
}

void CExtDockBar::DoPaint(CDC* pDC)
{
	ASSERT_VALID( this );
	ASSERT_VALID( pDC );
	CExtPaintManager::stat_ExcludeChildAreas(
		pDC->GetSafeHdc(),
		GetSafeHwnd()
		);
CRect rcClient;
	GetClientRect( &rcClient );
CExtMemoryDC dc( pDC, &rcClient );
	ASSERT( dc.GetSafeHdc() != NULL );
	if( dc.GetSafeHdc() != NULL )
		pDC = &dc;
	g_PaintManager->PaintDockBarClientArea(
		*pDC,
		rcClient,
		this
		);
	g_PaintManager->OnPaintSessionComplete( this );
}

BOOL CExtDockBar::OnEraseBkgnd( CDC* pDC )
{
	ASSERT_VALID( this );
	ASSERT_VALID( pDC );
	pDC;
//	CExtPaintManager::stat_ExcludeChildAreas(
//		*pDC,
//		*this
//		);
//	return CDockBar::OnEraseBkgnd(pDC);
	return TRUE;
}

void CExtDockBar::OnDynamicLayoutUpdate()
{
	ASSERT_VALID( this );
	ASSERT_KINDOF( CExtDockBar, this );

	if( m_bLockedOptimize )
		return;

	if( m_bInDynamicLayoutUpdate )
		return;
	m_bInDynamicLayoutUpdate = true;

	ASSERT( m_arrBars.GetSize() >= 1 );
	for( INT nBar = 1; nBar < m_arrBars.GetSize(); nBar++ )
	{
		CExtControlBar * pBar = (CExtControlBar *)
			m_arrBars[ nBar ];
		if( pBar == NULL )
			continue;
		if( __PLACEHODLER_BAR_PTR(pBar) )
			continue;
		ASSERT_VALID( pBar );
		ASSERT_KINDOF( CExtControlBar, pBar );
		if( pBar->IsFixedMode() || pBar->IsFixedDockStyle() )
			continue;
		if( !pBar->IsVisible() )
			continue;
		if( !pBar->IsKindOf(RUNTIME_CLASS(CExtDynControlBar)) )
			continue;
		ASSERT_VALID( ((CExtDynControlBar *)pBar)->m_pWndDynDocker );
		((CExtDynControlBar *)pBar)->m_pWndDynDocker->OnDynamicLayoutUpdate();
	}
	
	RedrawWindow(
		NULL, NULL,
		RDW_INVALIDATE //|RDW_UPDATENOW
			|RDW_ERASE //|RDW_ERASENOW
			|RDW_ALLCHILDREN|RDW_FRAME
		);

	m_bInDynamicLayoutUpdate = false;
}

void CExtDockBar::OnDynamicLayoutOptimize()
{
	if( m_bLockedOptimize )
		return;

	ASSERT( m_arrBars.GetSize() >= 1 );
	for( INT nBar = 1; nBar < m_arrBars.GetSize(); nBar++ )
	{
		CExtControlBar * pBar = (CExtControlBar *)
			m_arrBars[ nBar ];
		if( pBar == NULL )
			continue;
		if( __PLACEHODLER_BAR_PTR(pBar) )
			continue;
		ASSERT_VALID( pBar );
		ASSERT_KINDOF( CExtControlBar, pBar );
		if( pBar->IsFixedMode() || pBar->IsFixedDockStyle() )
			continue;
		if( !pBar->IsVisible() )
			continue;
		if( !pBar->IsKindOf(RUNTIME_CLASS(CExtDynControlBar)) )
			continue;
		ASSERT_VALID( ((CExtDynControlBar *)pBar)->m_pWndDynDocker );
		((CExtDynControlBar *)pBar)->m_pWndDynDocker->OnDynamicLayoutOptimize();
	}
}

CSize CExtDockBar::CalcFixedLayout(
	BOOL bStretch,
	BOOL bHorz
	)
{
	// based on MFC's source of
	// CDockBar::CalcFixedLayout()
	ASSERT_VALID(this);
CSize sizeFixed =
		CControlBar::CalcFixedLayout( bStretch, bHorz );
	// get max size
CSize sizeMax;
	if( !m_rectLayout.IsRectEmpty() )
		sizeMax = m_rectLayout.Size();
	else
	{
		CFrameWnd * pFrame = GetParentFrame();
		CRect rcFrameWindow;
		pFrame->GetClientRect( &rcFrameWindow );
		sizeMax = rcFrameWindow.Size();
	}
	// prepare for layout
AFX_SIZEPARENTPARAMS layout;
	layout.hDWP = m_bLayoutQuery ?
		NULL : ::BeginDeferWindowPos( m_arrBars.GetSize() );

CPoint pt( 0, 0 );
int nWidth = 0;

BOOL bWrapped = FALSE;

	for( int nPos = 0; nPos < m_arrBars.GetSize(); nPos++ )
	{ // layout all the control bars
		CControlBar * pBar = GetDockedControlBar(nPos);
		void * pVoid = m_arrBars[nPos];

		if( pBar != NULL )
		{
			CRect rcBarWin, rcBarClient;
			pBar->GetWindowRect( &rcBarWin );
			pBar->ScreenToClient( & rcBarWin );
			pBar->GetClientRect( &rcBarClient );
			CSize sizeBarMin =
				rcBarWin.Size() - rcBarClient.Size();

			if(	pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar)) )
			{
				if( ! ((CExtControlBar*)pBar)->IsFixedMode() )
				{
					sizeBarMin =
						CSize(
							((CExtControlBar *)pBar)->_CalcDesiredMinHW(),
							((CExtControlBar *)pBar)->_CalcDesiredMinVH()
							);
				} // if( ! ((CExtControlBar*)pBar)->IsFixedMode() )
			} // if(	pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar)) )
			if( pBar->IsVisible() )
			{
				// get ideal rect for bar
				DWORD dwMode = 0;
				if(	(pBar->m_dwStyle & CBRS_SIZE_DYNAMIC)
					&&
					(pBar->m_dwStyle & CBRS_FLOATING)
					)
					dwMode |= LM_HORZ | LM_MRUWIDTH;
				else if(pBar->m_dwStyle & CBRS_ORIENT_HORZ)
					dwMode |= LM_HORZ | LM_HORZDOCK;
				else
					dwMode |=  LM_VERTDOCK;

				CSize sizeBar =
					pBar->CalcDynamicLayout(-1, dwMode);
				CRect rc(pt, sizeBar);

				// get current rect for bar
				CRect rcBar;
				pBar->GetWindowRect( &rcBar );
				ScreenToClient( &rcBar );

				if( bHorz )
				{
					// Offset Calculated Rect out to Actual
					if(	rcBar.left > rc.left
						&& !m_bFloating
						)
						rc.OffsetRect(
							rcBar.left - rc.left,
							0
							);

					// If ControlBar goes off the right, then right justify
					if(	rc.right > sizeMax.cx
						&& !m_bFloating
						)
					{
						int x = rc.Width();
						x = max(sizeMax.cx - x, pt.x);
						rc.OffsetRect(
							x - rc.left,
							0
							);
						if(	rc.right  > sizeMax.cx )
							rc.right -= rc.right - sizeMax.cx;
					}

					// If ControlBar has been wrapped, then left justify
					if( bWrapped )
					{
						bWrapped = FALSE;
						rc.OffsetRect( - rc.left, 0 );

					}
					// If ControlBar is completely invisible, then wrap it
					else if(
						rc.Width() < sizeBarMin.cx
						||
						(rc.left >= sizeMax.cx)
							&& (nPos > 0) && (m_arrBars[nPos - 1] != NULL)
						)
					{
						if(	!pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar))
							||	(
								pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar))
								&&
								((CExtControlBar*)pBar)->IsFixedMode()
								)
							)
						{
							m_arrBars.InsertAt(
								nPos,
								(CObject*)NULL
								);
							pBar = NULL;
							pVoid = NULL;
							bWrapped = TRUE;
						}
					}
					if( !bWrapped )
					{
						if(rc != rcBar)
						{
							if(	!m_bLayoutQuery &&
								!(pBar->m_dwStyle & CBRS_FLOATING)
								)
								pBar->m_pDockContext->
									m_rectMRUDockPos = rc;
							AfxRepositionWindow(
								&layout,
								pBar->m_hWnd,
								&rc
								);
						}
						pt.x = rc.left + sizeBar.cx;
						nWidth = max(nWidth, sizeBar.cy);
					} // if( !bWrapped )
				} // if( bHorz )
				else
				{
					// Offset Calculated Rect out to Actual
					if(	rcBar.top > rc.top
						&& !m_bFloating
						)
						rc.OffsetRect(
							0,
							rcBar.top - rc.top
							);

					// If ControlBar goes off the bottom, then bottom justify
					if(	rc.bottom > sizeMax.cy
						&& !m_bFloating
						)
					{
						int y = rc.Height();
						y = max(sizeMax.cy - y, pt.y);
						rc.OffsetRect(
							0,
							y - rc.top
							);
						if(	rc.bottom  > sizeMax.cy )
							rc.bottom -= rc.bottom - sizeMax.cy;
					}

					// If ControlBar has been wrapped, then top justify
					if( bWrapped )
					{
						bWrapped = FALSE;
						rc.OffsetRect( 0, - rc.top );
					}
					// If ControlBar is completely invisible, then wrap it
					else if(
						rc.Height() < sizeBarMin.cy
						||
						(rc.top >= sizeMax.cy)
							&& (nPos > 0) && (m_arrBars[nPos - 1] != NULL)
						)
					{
						if(	!pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar)) 
							||	(
								pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar))
								&&
								((CExtControlBar*)pBar)->IsFixedMode()
								)
							)
						{
							m_arrBars.InsertAt(
								nPos,
								(CObject*)NULL
								);
							pBar = NULL;
							pVoid = NULL;
							bWrapped = TRUE;
						}
					}

					if( !bWrapped )
					{
						if(rc != rcBar)
						{
							if(	!m_bLayoutQuery
								&& !(pBar->m_dwStyle & CBRS_FLOATING)
								&& pBar->m_pDockContext != NULL
								)
								pBar->m_pDockContext->
									m_rectMRUDockPos = rc;
							AfxRepositionWindow(
								&layout,
								pBar->m_hWnd,
								&rc
								);
						}
						pt.y = rc.top + sizeBar.cy;
						nWidth = max(nWidth, sizeBar.cx);
					} // if( !bWrapped )
				} // else from if( bHorz )
			
//				if( !m_bLayoutQuery && pBar != NULL )
//				{
//					if( pBar->IsKindOf(RUNTIME_CLASS(CExtDynControlBar)) )
//					{
//						ASSERT_VALID( ((CExtDynControlBar *)pBar)->m_pWndDynDocker );
//						((CExtDynControlBar *)pBar)->m_pWndDynDocker->OnDynamicLayoutUpdate();
//					}
//				}

			} // if( pBar->IsVisible() )

			if( !bWrapped )
				// handle any delay/show hide for the bar
				pBar->RecalcDelayShow( &layout );

		} // if( pBar != NULL )
		else
		{
			if( g_bExtendedRepositioning )
			{
				// try to remove wrapping:
				// are we have free space in the end of previous row?
				if( nPos > 0 && nPos != m_arrBars.GetSize()-1 )
				{
					int nPosPrev = nPos-1;
					CControlBar * pPrevBar = NULL;
					do
					{
						pPrevBar = GetDockedControlBar(nPosPrev--);
						if( pPrevBar != NULL
							&& pPrevBar->IsVisible()
							&& (!pPrevBar->IsFloating())
							)
						{
							// get ideal rect for prev bar
							DWORD dwMode = 0;
							if(	(pPrevBar->m_dwStyle & CBRS_SIZE_DYNAMIC)
								&&
								(pPrevBar->m_dwStyle & CBRS_FLOATING)
								)
								dwMode |= LM_HORZ | LM_MRUWIDTH;
							else if(pPrevBar->m_dwStyle & CBRS_ORIENT_HORZ)
								dwMode |= LM_HORZ | LM_HORZDOCK;
							else
								dwMode |=  LM_VERTDOCK;

							CSize sizePrevBar =
								pPrevBar->CalcDynamicLayout(-1, dwMode);

							CRect rcPrev(pt, sizePrevBar);

							if( bHorz )
							{
								if(	rcPrev.right > sizeMax.cx
									&& !m_bFloating
									)
									pPrevBar = NULL;
							}
							else
							{
								if(	rcPrev.bottom > sizeMax.cy
									&& !m_bFloating
									)
									pPrevBar = NULL;
							}
							if( pPrevBar != NULL )
								break;
						}
						pPrevBar = NULL;
					} while( nPosPrev >= 0 );
					if( pPrevBar != NULL )
					{
						m_arrBars.RemoveAt(nPos);
						nPos--;
						continue;
					}
				} // if( nPos > 0 && nPos != m_arrBars.GetSize()-1 )
			} // if( g_bExtendedRepositioning )
		} // else from if( pBar != NULL )

		if( pBar == NULL && pVoid == NULL && nWidth != 0 )
		{
			// end of row because pBar == NULL
			if( bHorz )
			{
				pt.y += nWidth;
				sizeFixed.cx = max(sizeFixed.cx, pt.x);
				sizeFixed.cy = max(sizeFixed.cy, pt.y);
				pt.x = 0;
				sizeFixed.cy--;
			}
			else
			{
				pt.x += nWidth;
				sizeFixed.cx = max(sizeFixed.cx, pt.x);
				sizeFixed.cy = max(sizeFixed.cy, pt.y);
				pt.y = 0;
				sizeFixed.cx--;
			}
			nWidth = 0;
		}
	} // layout all the control bars
	if( !m_bLayoutQuery )
	{
		ASSERT( layout.hDWP != NULL );
		if( layout.hDWP != NULL )
		{
			VERIFY( ::EndDeferWindowPos(layout.hDWP) );
		}
	} // if( !m_bLayoutQuery )

	// adjust size for borders on the dock bar itself
CRect rc( 0, 0, 0, 0 );
	CalcInsideRect(rc, bHorz);
	if( (!bStretch || !bHorz) && sizeFixed.cx != 0 )
		sizeFixed.cx +=
			-rc.right + rc.left
			+ g_bControlBarFixSizePixel ? 1 : 0;
	if(	(!bStretch || bHorz) && sizeFixed.cy != 0 )
		sizeFixed.cy +=
			-rc.bottom + rc.top
			+ g_bControlBarFixSizePixel ? 1 : 0;

	if( !m_bLayoutQuery )
		OnDynamicLayoutUpdate();

	return sizeFixed;
}

void CExtDockBar::RemoveAllPlaceHolders(
	bool bSearchPlaceHolder // = true
	)
{
	ASSERT_VALID( this );
INT nCount = m_arrBars.GetSize();
	ASSERT( nCount > 0 );
	ASSERT( m_arrBars[0] == NULL );
MfcControlBarVector_t vPlaceHolders;
	for( INT nBar = 1; nBar < nCount; nBar++ )
	{
		CControlBar * pBar = (CControlBar *) m_arrBars[ nBar ];
		if( pBar == NULL )
			continue;
		if( __PLACEHODLER_BAR_PTR(pBar) )
		{
			vPlaceHolders.Add( pBar );
			continue;
		}
		ASSERT_VALID( pBar );
		ASSERT_KINDOF( CControlBar, pBar );
	}

	nCount = vPlaceHolders.GetSize();
	for( nBar = 0; nBar < nCount; nBar++ )
	{
		CControlBar * pBar = vPlaceHolders[nBar];
		RemovePlaceHolder( pBar, bSearchPlaceHolder );
	}
}

void CExtDockBar::RemovePlaceHolder(
	CControlBar * pBar,
	bool bSearchPlaceHolder, // = true
	bool * p_bRemoved // = NULL
	)
{
	if( p_bRemoved != NULL )
		*p_bRemoved = false;
	// remove remembered docking position
	if( HIWORD(pBar) != 0 )
		pBar = (CControlBar*)_AfxGetDlgCtrlID(pBar->m_hWnd);
int nOldPos = FindBar(pBar);
	if( nOldPos > 0)
	{
		m_arrBars.RemoveAt(nOldPos);

		// remove section indicator (NULL) if nothing else in section
		if(		m_arrBars[nOldPos-1] == NULL
			&&	m_arrBars[nOldPos] == NULL
			)
			m_arrBars.RemoveAt(nOldPos);

		if( p_bRemoved != NULL )
			*p_bRemoved = true;

		return;
	}
	if( !bSearchPlaceHolder )
		return;


	_RemovePlaceHolder(
		m_pDockSite,
		pBar,
		p_bRemoved
		);
}

void CExtDockBar::_RemovePlaceHolder(
	CFrameWnd * pFrame,
	CControlBar * pBar,
	bool * p_bRemoved // = NULL
	)
{
	ASSERT_VALID( pFrame );
	ASSERT( pBar != NULL ); // may be placeholder ID
POSITION pos = pFrame->m_listControlBars.GetHeadPosition();
	for( ; pos != NULL; )
	{
		CControlBar * pTestBar = (CControlBar *)
			pFrame->m_listControlBars.GetNext( pos );
		ASSERT_VALID( pTestBar );
		ASSERT_KINDOF( CControlBar, pTestBar );
		if( !pTestBar->IsDockBar() )
		{
			if( pTestBar->IsKindOf(RUNTIME_CLASS(CExtDynControlBar)) )
			{
				CExtDockDynBar * pDynDocker =
					((CExtDynControlBar*)pTestBar)->
						m_pWndDynDocker;
				ASSERT_VALID( pDynDocker );
				bool bRemoved = false;
				pDynDocker->RemovePlaceHolder(
					pBar,
					false,
					&bRemoved
					);
				if( bRemoved )
				{
					if( p_bRemoved != NULL )
						*p_bRemoved = true;
					return;
				}
			}
			continue;
		}
		ASSERT_KINDOF( CDockBar, pTestBar );
		// dirty, but safe
		bool bRemoved = false;
		((CExtDockBar *)pTestBar)->RemovePlaceHolder(
			pBar,
			false,
			&bRemoved
			);
		if( bRemoved )
		{
			if( p_bRemoved != NULL )
				*p_bRemoved = true;
			return;
		}
	}
}

void CExtDockBar::_SlideDockControlBar(
	CControlBar* pBar,
	LPCRECT lpRect,
	BOOL bMovingEnabled,
	const POINT * ptDesiredMid // = NULL
	)
{
	ASSERT_VALID( this);
	ASSERT_VALID( pBar );
	ASSERT_KINDOF( CControlBar, pBar );

CRect rcBar;
	pBar->GetWindowRect( &rcBar );
	if(	pBar->m_pDockBar == this
		&& (lpRect == NULL || rcBar == *lpRect)
		)
	{
		// already docked and no change in position
		return;
	}

	// set CBRS_FLOAT_MULTI style if docking bar has it
	if(	m_bFloating
		&& (pBar->m_dwDockStyle & CBRS_FLOAT_MULTI)
		)
		m_dwStyle |= CBRS_FLOAT_MULTI;

	m_dwStyle &= ~(CBRS_SIZE_FIXED | CBRS_SIZE_DYNAMIC);
	m_dwStyle |=
		pBar->m_dwStyle & (CBRS_SIZE_FIXED | CBRS_SIZE_DYNAMIC);

	if( !(m_dwStyle & CBRS_FLOAT_MULTI) )
	{
		CString sTitle;
		pBar->GetWindowText( sTitle );
		AfxSetWindowText( m_hWnd, (LPCTSTR)sTitle );
	}

	// align correctly and turn on all borders
DWORD dwStyle = pBar->GetBarStyle();
	dwStyle &= ~(CBRS_ALIGN_ANY);
	dwStyle |=  (m_dwStyle & CBRS_ALIGN_ANY) | CBRS_BORDER_ANY;

	if( m_bFloating )
		dwStyle |= CBRS_FLOATING;
	else
		dwStyle &= ~CBRS_FLOATING;

	pBar->SetBarStyle( dwStyle );

	// hide first if changing to a new docking site to avoid flashing
bool bShow = false;
	if( bMovingEnabled &&
		pBar->m_pDockBar != this && pBar->IsWindowVisible() )
	{
		pBar->SetWindowPos(NULL, 0, 0, 0, 0,
			SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_HIDEWINDOW);
		bShow = true;
	}

int nPos = -1;
	if( lpRect != NULL )
	{
		// insert into appropriate row
		CRect rc( lpRect );
		ScreenToClient( &rc );
		CPoint ptMid(
			(ptDesiredMid == NULL) ?
				rc.left + rc.Width()/2 : ptDesiredMid->x,
			(ptDesiredMid == NULL) ?
				rc.top + rc.Height()/2 : ptDesiredMid->y
			);
		nPos = _InsertByPointImpl( pBar, rc, ptMid );
		ASSERT_VALID( this );
		ASSERT_BAR_LOCATION_IN_ROW( this, pBar );

		// position at requested position
		if( bMovingEnabled )
			pBar->SetWindowPos(
				NULL,
				rc.left, rc.top, rc.Width(), rc.Height(),
				SWP_NOREDRAW|SWP_NOSENDCHANGING
					|SWP_NOZORDER|SWP_NOOWNERZORDER
					|SWP_NOACTIVATE|SWP_NOCOPYBITS
				);
	}
	else
	{
		// always add on current row, then create new one
		m_arrBars.Add(pBar);
		m_arrBars.Add(NULL);
		ASSERT_VALID( this );
		ASSERT_BAR_LOCATION_IN_ROW( this, pBar );

		// align off the edge initially
		if( bMovingEnabled )
			pBar->SetWindowPos(
				NULL,
				-afxData.cxBorder2, -afxData.cyBorder2,
				0, 0,
				SWP_NOREDRAW|SWP_NOSENDCHANGING
					|SWP_NOZORDER|SWP_NOOWNERZORDER
					|SWP_NOACTIVATE|SWP_NOCOPYBITS
					|SWP_NOSIZE
				);
	}

	// attach it to the docking site
	if( pBar->GetParent() != this )
		pBar->SetParent(this);
	if( pBar->m_pDockBar == this )
	{
		//pBar->m_pDockBar->
			RemoveControlBar(
				pBar,
				nPos,
				0,
				false // (!bMovingEnabled) ? true : false
				);
		ASSERT_VALID( this );
	} // if( pBar->m_pDockBar == this )
	else if( pBar->m_pDockBar != NULL )
	{
		ASSERT_KINDOF( CDockBar, pBar->m_pDockBar );
		if( pBar->m_pDockBar->IsKindOf(RUNTIME_CLASS(CExtDockBar)) )
		{
			bool bOptimizeDockBarLayout = false;
			if( !((CExtDockBar *)(pBar->m_pDockBar))->m_bFloating )
				bOptimizeDockBarLayout = true;
			((CExtDockBar *)(pBar->m_pDockBar))->
				RemoveControlBar(
					pBar,
					-1,
					m_bFloating && !pBar->m_pDockBar->m_bFloating,
					false // (!bMovingEnabled) ? true : false
					);
			ASSERT_VALID( this );
			if( bOptimizeDockBarLayout )
				((CExtDockBar *)(pBar->m_pDockBar))->OnDynamicLayoutOptimize();
		}
		else
		{
			pBar->m_pDockBar->
				RemoveControlBar(
					pBar,
//ph//
					0, //-1,
					m_bFloating && !pBar->m_pDockBar->m_bFloating
					);
			ASSERT_VALID( this );
		}
	} // else if( pBar->m_pDockBar != NULL )

	pBar->m_pDockBar = this;
	ASSERT( pBar->m_pDockContext != NULL );
	pBar->m_pDockContext->m_uMRUDockID = GetDlgCtrlID();
	if( lpRect != NULL )
		pBar->m_pDockContext->m_rectMRUDockPos = *lpRect;

	if( bShow )
	{
		ASSERT(!pBar->IsWindowVisible());
		//pBar->SetWindowPos(NULL, 0, 0, 0, 0,
		//	SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW);
		pBar->SetWindowPos(NULL,
			lpRect->left,
			lpRect->top,
			lpRect->right-lpRect->left,
			lpRect->bottom-lpRect->top,
			SWP_NOSIZE/*|SWP_NOMOVE*/|SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW);
	}

	// remove any place holder for pBar in this dockbar
	RemovePlaceHolder( pBar, true );
	ASSERT_VALID( this );

//	// get parent frame for recalc layout
//CFrameWnd* pFrameWnd = GetDockingFrame();
//	pFrameWnd->DelayRecalcLayout();

	_OptimizeCircles();
}

void CExtDockBar::_NewRowDockControlBar(
	CControlBar * pExtBarDocked,
	CControlBar * pExtBarNew,
	bool bLessIndex
	)
{
	ASSERT_VALID( this);
	ASSERT_VALID( pExtBarDocked );
	ASSERT_KINDOF( CControlBar, pExtBarDocked );
	ASSERT_VALID( pExtBarNew );
	ASSERT_KINDOF( CControlBar, pExtBarNew );

CFrameWnd * pNewDockingFrameWnd = pExtBarNew->GetDockingFrame();
INT nNewDockBarGetDockedVisibleCount = -1;
BOOL bNewFloating = pExtBarNew->IsFloating();

BOOL bNewExt = pExtBarNew->IsKindOf( RUNTIME_CLASS(CExtControlBar) );

	if( pExtBarNew->GetParent() != this )
	{
		if( bNewExt )
			((CExtControlBar *)pExtBarNew)->m_bUpdatingChain = true;
		pExtBarNew->SetWindowPos(
			NULL, 0, 0, 0, 0,
			SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE
			|SWP_HIDEWINDOW
			);
		pExtBarNew->SetParent( this );
		if( bNewExt )
			((CExtControlBar *)pExtBarNew)->m_bUpdatingChain = false;
	}

	// align correctly and turn on all borders
DWORD dwStyle = pExtBarNew->GetBarStyle();
	dwStyle &= ~(CBRS_ALIGN_ANY);
	dwStyle |=  (m_dwStyle & CBRS_ALIGN_ANY) | CBRS_BORDER_ANY;

	if( m_bFloating )
		dwStyle |= CBRS_FLOATING;
	else
		dwStyle &= ~CBRS_FLOATING;

	pExtBarNew->SetBarStyle( dwStyle );

INT nCountOfSideBars = m_arrBars.GetSize();
CControlBar * pRemoveBar = NULL;
HWND hWndDockBarOld = NULL;
	if( pExtBarNew->m_pDockBar != this )
	{
		if( pExtBarNew->m_pDockBar != NULL )
		{
			nNewDockBarGetDockedVisibleCount =
				GetDockedVisibleCount();
			ASSERT_VALID( pExtBarNew->m_pDockBar );
			ASSERT_KINDOF( CDockBar, pExtBarNew->m_pDockBar );
			if( pExtBarNew->IsWindowVisible() )
				pExtBarNew->SetWindowPos(
					NULL, 0, 0, 0, 0,
					SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE
					|SWP_HIDEWINDOW
					);
			ASSERT_VALID( pExtBarNew->m_pDockBar );

			if( !pExtBarNew->m_pDockBar->m_bFloating
				&& pExtBarNew->m_pDockBar->IsKindOf(RUNTIME_CLASS(CExtDockBar))
				)
			{
hWndDockBarOld = pExtBarNew->m_pDockBar->GetSafeHwnd();
				((CExtDockBar *)pExtBarNew->m_pDockBar)->RemoveControlBar( pExtBarNew );
// optimized at final state with all circles
//				((CExtDockBar *)pExtBarNew->m_pDockBar)->OnDynamicLayoutOptimize();
			}
			else		
				pExtBarNew->m_pDockBar->RemoveControlBar( pExtBarNew );

			//ASSERT_VALID( pExtBarNew->m_pDockBar ); this may be alredy destroyed floating dockbar
		} // if( pExtBarNew->m_pDockBar != NULL )
	} // if( pExtBarNew->m_pDockBar != this )
	else
	{
		if( pExtBarDocked != pExtBarNew )
		{
			INT nPos = FindBar( pExtBarNew );
			ASSERT( nPos >= 0 && nPos < nCountOfSideBars );
			m_arrBars.RemoveAt( nPos );
			nCountOfSideBars --;
			ASSERT( nCountOfSideBars > 1 );
			if(   (	nCountOfSideBars == nPos
					&& m_arrBars[nPos-1] == NULL )
				||
				  (	nCountOfSideBars > nPos
					&& m_arrBars[nPos-1] == NULL
					&& m_arrBars[nPos] == NULL
					)
				)
			{
				// remove empty row
				m_arrBars.RemoveAt( nPos-1 );
				nCountOfSideBars --;
			}
			ASSERT_VALID( this );
		} // if( pExtBarDocked != pExtBarNew )
		else
			pRemoveBar = pExtBarNew;
	} // else from if( pExtBarNew->m_pDockBar != this )

INT nIdxDockedBar = FindBar( pExtBarDocked );
	ASSERT( nIdxDockedBar >= 0 && nIdxDockedBar < nCountOfSideBars );

INT nIncrement = bLessIndex ? -1 : 1;

	for( INT nIdx = nIdxDockedBar; true; nIdx += nIncrement )
	{
		CControlBar * pBar = (CControlBar *) m_arrBars[ nIdx ];
		if( nIdx == 0
			|| nIdx == (nCountOfSideBars-1)
			|| pBar == NULL
			)
		{
			ASSERT( m_arrBars[0] == NULL );
			m_arrBars.InsertAt( nIdx, pExtBarNew );
			m_arrBars.InsertAt( nIdx, (CControlBar *)NULL );
			ASSERT_VALID( this );
			break;
		}

#ifdef _DEBUG
		if( __PLACEHODLER_BAR_PTR(pBar) )
			continue;
		ASSERT_VALID( pBar );
		ASSERT_KINDOF( CControlBar, pBar );
#endif // _DEBUG

	} // for( INT nIdx = nIdxDockedBar; true; nIdx += nIncrement )

CDockBar * pOldDockBar = pExtBarNew->m_pDockBar;

	pExtBarNew->m_pDockBar = this;
	ASSERT_BAR_LOCATION_IN_ROW( this, pExtBarNew );
	
	ASSERT( pExtBarNew->m_pDockContext != NULL );
	pExtBarNew->m_pDockContext->m_uMRUDockID = GetDlgCtrlID();

	if( pRemoveBar != NULL )
	{
		INT nPos = FindBar( pRemoveBar, nIdx+1 );
		nCountOfSideBars = m_arrBars.GetSize();
		ASSERT( nPos >= 0 && nPos < nCountOfSideBars );
		m_arrBars.RemoveAt( nPos );
		nCountOfSideBars --;
		ASSERT( nCountOfSideBars > 1 );
		if(   (	nCountOfSideBars == nPos
				&& m_arrBars[nPos-1] == NULL )
			||
			  (	nCountOfSideBars > nPos
				&& m_arrBars[nPos-1] == NULL
				&& m_arrBars[nPos] == NULL
				)
			)
		{
			// remove empty row
			m_arrBars.RemoveAt( nPos-1 );
//			nCountOfSideBars --;
		}
		ASSERT_VALID( this );
	}

	if( bNewFloating && nNewDockBarGetDockedVisibleCount == 0 )
	{
		if( pOldDockBar->GetDockedCount() == 0 )
			pNewDockingFrameWnd->DestroyWindow();
		else
			pNewDockingFrameWnd->ShowWindow( SW_HIDE );
	}
//	else
//		pNewDockingFrameWnd->DelayRecalcLayout();

//	ASSERT( !pExtBarNew->IsWindowVisible() );
	pExtBarNew->SetWindowPos(NULL, 0, 0, 0, 0,
		SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE
			|SWP_SHOWWINDOW|SWP_FRAMECHANGED
		);

	OnDynamicLayoutUpdate();
	if( hWndDockBarOld != NULL
		&& hWndDockBarOld != GetSafeHwnd()
		&& ::IsWindow(hWndDockBarOld)
		)
	{
		CWnd * pWndDockBar = FromHandlePermanent( hWndDockBarOld );
		if( pWndDockBar != NULL
			&& pWndDockBar->GetSafeHwnd() == hWndDockBarOld
			)
		{
			ASSERT( pWndDockBar != this );
			ASSERT_KINDOF( CExtDockBar, pWndDockBar );
			((CExtDockBar *)pWndDockBar)->OnDynamicLayoutUpdate();
		}
	}

CFrameWnd * pFrame = GetParentFrame();
	ASSERT_VALID( pFrame );
	if( !pFrame->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)) )
		_OptimizeCircles();
}

void CExtDockBar::_InnerOuterDockControlBar(
	CControlBar * pBar,
	bool bInner
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( pBar );
	ASSERT_KINDOF( CControlBar, pBar );

UINT nOwnID = GetDlgCtrlID();
	ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nOwnID );

bool bDockAtStartIdx = false;
	if( nOwnID == AFX_IDW_DOCKBAR_RIGHT
		|| nOwnID == AFX_IDW_DOCKBAR_BOTTOM
		)
		bDockAtStartIdx = true;
	if( !bInner )
		bDockAtStartIdx = false;

	if( pBar->m_pDockBar == this )
	{
		INT nCountOfBars = m_arrBars.GetSize();
		ASSERT( nCountOfBars > 2 );
		if( m_arrBars[1] == pBar )
			return;
		INT nBarPos = FindBar( pBar );
		ASSERT( nBarPos > 0 && nBarPos < nCountOfBars );
		m_arrBars.RemoveAt( nBarPos );
		nCountOfBars --;
		if( m_arrBars[nBarPos - 1] == NULL
			&& m_arrBars[ nBarPos ] == NULL
			)
		{
			m_arrBars.RemoveAt( nBarPos );
			nCountOfBars --;
		}

		//ASSERT_VALID( this );
		if( bDockAtStartIdx )
		{
			m_arrBars.InsertAt( 1, pBar );
			nCountOfBars++;
			ASSERT( nCountOfBars == m_arrBars.GetSize() );
			if( nCountOfBars < 3 || m_arrBars[2] != NULL )
				m_arrBars.InsertAt( 2, (CControlBar *)NULL );
			ASSERT_VALID( this );
		} // if( bDockAtStartIdx )
		else
		{
			m_arrBars.InsertAt( nCountOfBars, (CControlBar *)NULL );
			m_arrBars.InsertAt( nCountOfBars, pBar );
			ASSERT_VALID( this );
		} // else from if( bDockAtStartIdx )
	} // if( pBar->m_pDockBar == this )
	else
	{
		CFrameWnd * pDockingFrameWnd = pBar->GetDockingFrame();
		INT nDockBarGetDockedVisibleCount = -1;
		BOOL bFloating = pBar->IsFloating();

		ASSERT( pBar->GetParent() != this );
		pBar->SetWindowPos(
			NULL, 0, 0, 0, 0,
			SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE
			|SWP_HIDEWINDOW
			);
		pBar->SetParent( this );

		// align correctly and turn on all borders
		DWORD dwStyle = pBar->GetBarStyle();
		dwStyle &= ~(CBRS_ALIGN_ANY);
		dwStyle |=  (m_dwStyle & CBRS_ALIGN_ANY) | CBRS_BORDER_ANY;

		if( m_bFloating )
			dwStyle |= CBRS_FLOATING;
		else
			dwStyle &= ~CBRS_FLOATING;

		pBar->SetBarStyle( dwStyle );

		ASSERT( pBar->m_pDockBar != this );
		if( pBar->IsWindowVisible() )
			pBar->SetWindowPos(
				NULL, 0, 0, 0, 0,
				SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE
				|SWP_HIDEWINDOW
				);

		if( pBar->m_pDockBar != NULL )
		{
			ASSERT_VALID( pBar->m_pDockBar );
			ASSERT_KINDOF( CDockBar, pBar->m_pDockBar );
			if( !pBar->m_pDockBar->m_bFloating
				&& pBar->m_pDockBar->IsKindOf(RUNTIME_CLASS(CExtDockBar))
				)
			{
				((CExtDockBar *)pBar->m_pDockBar)->RemoveControlBar( pBar );
				((CExtDockBar *)pBar->m_pDockBar)->OnDynamicLayoutOptimize();
			}
			else
				pBar->m_pDockBar->RemoveControlBar( pBar );
			//ASSERT_VALID( pBar->m_pDockBar ); this may be alredy destroyed floating dockbar
		}

		
		//ASSERT_VALID( this );
		INT nCountOfBars = m_arrBars.GetSize();
		ASSERT( nCountOfBars > 0 );
		if( bDockAtStartIdx )
		{
			m_arrBars.InsertAt( 1, pBar );
			nCountOfBars++;
			if( nCountOfBars < 3 || m_arrBars[2] != NULL )
				m_arrBars.InsertAt( 2, (CControlBar *)NULL );
			ASSERT_VALID( this );
		} // if( bDockAtStartIdx )
		else
		{
			m_arrBars.InsertAt( nCountOfBars, (CControlBar *)NULL );
			m_arrBars.InsertAt( nCountOfBars, pBar );

			if(		nCountOfBars > 1 // (+ v.2.23) - fixes initial mutual sizes in row/col problem
			   &&	m_arrBars[nCountOfBars-1] == NULL
			   )
			   m_arrBars.RemoveAt( nCountOfBars-1, 1 );

			ASSERT_VALID( this );
		} // else from if( bDockAtStartIdx )

		CDockBar * pOldDockBar = pBar->m_pDockBar;
		pBar->m_pDockBar = this;
		ASSERT_BAR_LOCATION_IN_ROW( this, pBar );
		
		ASSERT( pBar->m_pDockContext != NULL );
		pBar->m_pDockContext->m_uMRUDockID = GetDlgCtrlID();

		if( bFloating && nDockBarGetDockedVisibleCount == 0 )
		{
			if( pOldDockBar->GetDockedCount() == 0 )
				pDockingFrameWnd->DestroyWindow();
			else
				pDockingFrameWnd->ShowWindow( SW_HIDE );
		}
//		else
//			pDockingFrameWnd->DelayRecalcLayout();

//		ASSERT( !pBar->IsWindowVisible() );
		pBar->SetWindowPos(NULL, 0, 0, 0, 0,
			SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE
				|SWP_SHOWWINDOW|SWP_FRAMECHANGED
			);

		ASSERT_VALID( this );
	} // else from if( pBar->m_pDockBar == this )

	_OptimizeCircles();
}

void CExtDockBar::_LockSequenceOptimization( bool bLock )
{
	ASSERT_VALID( this );
	ASSERT_KINDOF( CExtDockBar, this );
	m_bLockedOptimize = bLock;
}

void CExtDockDynBar::_LockSequenceOptimization( bool bLock )
{
	ASSERT_VALID( this );
	ASSERT_KINDOF( CExtDockDynBar, this );
	m_bLockedOptimize = bLock;
CExtDynControlBar * pDynBar =
		STATIC_DOWNCAST(
			CExtDynControlBar,
			GetParent()
			);
	ASSERT( pDynBar->m_pWndDynDocker == this );
	ASSERT_VALID( pDynBar->m_pDockBar );
	if(  pDynBar->m_pDockBar->IsKindOf(RUNTIME_CLASS(CExtDockBar)) )
		((CExtDockBar *)pDynBar->m_pDockBar)->_LockSequenceOptimization( bLock );
}

void CExtDockBar::DockControlBar(
	CControlBar * pBar,
	LPCRECT lpRect, // = NULL
	bool bSmoothMode // = false
	)
{
	ASSERT_VALID(this);
	ASSERT_VALID(pBar);
	ASSERT_KINDOF(CControlBar, pBar);

CRect rectBar;
	pBar->GetWindowRect( &rectBar );
	if(		pBar->m_pDockBar == this
		&&	(lpRect == NULL || rectBar == *lpRect)
		)
	{
		// already docked and no change in position
		return;
	}

	// set CBRS_FLOAT_MULTI style if docking bar has it
	if( m_bFloating && (pBar->m_dwDockStyle & CBRS_FLOAT_MULTI) )
		m_dwStyle |= CBRS_FLOAT_MULTI;

	m_dwStyle &= ~(CBRS_SIZE_FIXED | CBRS_SIZE_DYNAMIC);
	m_dwStyle |= pBar->m_dwStyle & (CBRS_SIZE_FIXED | CBRS_SIZE_DYNAMIC);

	if( !(m_dwStyle & CBRS_FLOAT_MULTI) )
	{
		CString sTitle;
		pBar->GetWindowText( sTitle );
		AfxSetWindowText( m_hWnd, (LPCTSTR)sTitle );
	}

	// align correctly and turn on all borders
DWORD dwStyle = pBar->GetBarStyle();
	dwStyle &= ~(CBRS_ALIGN_ANY);
	dwStyle |=  (m_dwStyle & CBRS_ALIGN_ANY) | CBRS_BORDER_ANY;

	if( m_bFloating )
		dwStyle |= CBRS_FLOATING;
	else
		dwStyle &= ~CBRS_FLOATING;

	pBar->SetBarStyle(dwStyle);

	// hide first if changing to a new docking site to avoid flashing
BOOL bShow = FALSE;
	if( pBar->m_pDockBar != this && pBar->IsWindowVisible() )
	{
		pBar->SetWindowPos(
			NULL,
			0, 0, 0, 0,
			SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_HIDEWINDOW
			);
		bShow = TRUE;
	}

int nPos = -1;
	if( lpRect != NULL )
	{
		// insert into appropriate row
		CRect rect(lpRect);
		ScreenToClient(&rect);
		CPoint ptMid(rect.left + rect.Width()/2, rect.top + rect.Height()/2);
		//nPos = Insert(pBar, rect, ptMid);
		nPos = CDockBar::Insert(pBar, rect, ptMid);

		ASSERT( nPos > 0 && nPos < (m_arrBars.GetSize()-1) );
		// adjust with the previous full-row-mode neiborhood
		// based on the fixed-style docking algorithm
		CControlBar * pBarNeiborhood =
			(CControlBar *)(m_arrBars[nPos-1]);
		if(		pBarNeiborhood != NULL
			&&	(! (__PLACEHODLER_BAR_PTR(pBarNeiborhood)) )
			)
		{
			ASSERT_VALID( pBarNeiborhood );
			CExtControlBar * pExtBarNeiborhood =
				DYNAMIC_DOWNCAST( CExtControlBar, pBarNeiborhood );
			if(		pExtBarNeiborhood != NULL
				&&	pExtBarNeiborhood->IsFixedDockStyle()
				&&	pExtBarNeiborhood->_GetFullRowMode()
				)
				m_arrBars.InsertAt( nPos++, (CControlBar *)NULL );
		}
		// adjust with the next full-row-mode neiborhood
		// based on the fixed-style docking algorithm
		pBarNeiborhood =
			(CControlBar *)(m_arrBars[nPos+1]);
		if(		pBarNeiborhood != NULL
			&&	(! (__PLACEHODLER_BAR_PTR(pBarNeiborhood)) )
			)
		{
			ASSERT_VALID( pBarNeiborhood );
			CExtControlBar * pExtBarNeiborhood =
				DYNAMIC_DOWNCAST( CExtControlBar, pBarNeiborhood );
			if(		pExtBarNeiborhood != NULL
				&&	pExtBarNeiborhood->IsFixedDockStyle()
				&&	pExtBarNeiborhood->_GetFullRowMode()
				)
				m_arrBars.InsertAt( nPos+1, (CControlBar *)NULL );
		}

		// position at requested position
		pBar->SetWindowPos(NULL, rect.left, rect.top, rect.Width(),
			rect.Height(), SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
	}
	else
	{
		// always add on current row, then create new one
		m_arrBars.Add(pBar);
		m_arrBars.Add(NULL);

		// align off the edge initially
		pBar->SetWindowPos(
			NULL,
			-afxData.cxBorder2, -afxData.cyBorder2, 0, 0,
			SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS
			);
	}

	// attach it to the docking site
	if (pBar->GetParent() != this)
		pBar->SetParent(this);
	if( pBar->m_pDockBar == this )
		//pBar->m_pDockBar->
			RemoveControlBar(pBar, nPos);
	else if( pBar->m_pDockBar != NULL )
	{

		ASSERT_KINDOF( CDockBar, pBar->m_pDockBar );
		if( pBar->m_pDockBar->IsKindOf(RUNTIME_CLASS(CExtDockBar)) )
		{
			bool bOptimizeDockBarLayout = false;
			if( !((CExtDockBar *)(pBar->m_pDockBar))->m_bFloating )
				bOptimizeDockBarLayout = true;
			((CExtDockBar *)(pBar->m_pDockBar))->
				RemoveControlBar(
					pBar,
					-1,
					m_bFloating && !pBar->m_pDockBar->m_bFloating,
					false // (!bMovingEnabled) ? true : false
					);
			ASSERT_VALID( this );
			if( bOptimizeDockBarLayout
				&& !m_bLockedOptimize
				)
				((CExtDockBar *)(pBar->m_pDockBar))->OnDynamicLayoutOptimize();
		}
		else
		{
			pBar->m_pDockBar->
				RemoveControlBar(
					pBar,
//ph//
					0, //-1,
					m_bFloating && !pBar->m_pDockBar->m_bFloating
					);
			ASSERT_VALID( this );
		}
	}
	pBar->m_pDockBar = this;

	if( bShow )
	{
		ASSERT(!pBar->IsWindowVisible());
		pBar->SetWindowPos(
			NULL,
			0, 0, 0, 0,
			SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW
			);
	}
	else if( bSmoothMode && lpRect != NULL )
	{
		CRect rcSmooth( *lpRect );
		ScreenToClient( &rcSmooth );
		pBar->SetWindowPos(
			NULL,
			rcSmooth.left, rcSmooth.top,
			rcSmooth.Width(), rcSmooth.Height(),
			SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSENDCHANGING|SWP_NOREDRAW
			);
	} // else if( bSmoothMode && lpRect != NULL )

	// remove any place holder for pBar in this dockbar
	RemovePlaceHolder( pBar, true );

	ASSERT_VALID( this );
	if( pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar))
		&& ((CExtControlBar*)pBar)->_GetFullRowMode()
		)
	{
		nPos = FindBar( pBar );
		ASSERT( nPos > 0 && nPos < (m_arrBars.GetSize()-1) );
		if( m_arrBars[nPos+1] == NULL )
		{
			if( m_arrBars[nPos-1] != NULL )
			{
				m_arrBars.InsertAt( nPos, (CControlBar *)NULL );
				ASSERT_VALID( this );
			}
		} // if( m_arrBars[nPos+1] == NULL )
		else
		{
			if( m_arrBars[nPos-1] == NULL )
			{
				m_arrBars.InsertAt( nPos+1, (CControlBar *)NULL );
				ASSERT_VALID( this );
			}
			else
			{
				for( int nPos2 = nPos-1; m_arrBars[nPos2] != NULL; nPos2-- );
				ASSERT( nPos2 >= 0 );
				m_arrBars.RemoveAt( nPos );
				m_arrBars.InsertAt( nPos2, pBar );
				m_arrBars.InsertAt( nPos2, (CControlBar *)NULL );
				ASSERT_VALID( this );
			}
		} // else from if( m_arrBars[nPos+1] == NULL )
	}

	// get parent frame for recalc layout
CFrameWnd* pFrameWnd = GetDockingFrame();
	pFrameWnd->DelayRecalcLayout();

// OPTFIX:
//	if( !pFrameWnd->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)) )
//		_OptimizeCircles();
}

void CExtDockBar::DrawBorders(CDC* pDC, CRect& rect)
{
	ASSERT_VALID( this );
	ASSERT_VALID( pDC );

CExtPaintManager::PAINTCONTROLBARBORDERSDATA _pcbbd(
		this,
		CExtPaintManager::__CB_OUTER_DOCKBAR,
		m_dwStyle, // |CBRS_BORDER_ANY|CBRS_BORDER_3D
		rect
		);
	g_PaintManager->PaintControlBarBorders( *pDC, _pcbbd );
}

void CExtDockBar::DrawGripper(CDC* pDC, const CRect& rect)
{
	ASSERT_VALID( this );
	pDC,
	rect;
}

LRESULT CExtDockBar::OnSizeParent(WPARAM wParam, LPARAM lParam)
{
	ASSERT_VALID( this );
//	if( CExtControlBar::g_bUpdatingDragState )
//		return 0;

	if( m_bLockedOptimize )
		return 0;

LRESULT lResult =
		CDockBar::OnSizeParent(wParam,lParam);

//	if( _GetCircleNo() == 0 )
//		return lResult;

	if( (m_dwStyle & CBRS_ALIGN_ANY) == 0 )
		return lResult;

UINT nOwnID = GetDlgCtrlID();
	if( nOwnID == AFX_IDW_DOCKBAR_FLOAT )
		return lResult;
	ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nOwnID );

//DWORD dwWndStyle = GetStyle();
//bool bWndVisible = (dwWndStyle & WS_VISIBLE) ? true : false;
//	if( bWndVisible )
//	{
//		if( GetDockedVisibleCount() != 0 )
//			return lResult;
//	}

AFX_SIZEPARENTPARAMS * lpLayout = (AFX_SIZEPARENTPARAMS*)lParam;
	ASSERT( lpLayout != NULL );
//	if( lpLayout->hDWP == NULL )
//		return lResult;

	m_rcLastInvisiblePreCalc = lpLayout->rect;

	switch( nOwnID )
	{
	case AFX_IDW_DOCKBAR_TOP:
//		ASSERT( m_rcLastInvisiblePreCalc.left <= m_rcLastInvisiblePreCalc.right );
		m_rcLastInvisiblePreCalc.bottom = m_rcLastInvisiblePreCalc.top; // + 1;
		break;
	case AFX_IDW_DOCKBAR_BOTTOM:
//		ASSERT( m_rcLastInvisiblePreCalc.left <= m_rcLastInvisiblePreCalc.right );
		m_rcLastInvisiblePreCalc.top = m_rcLastInvisiblePreCalc.bottom; //  - 1;
		break;
	case AFX_IDW_DOCKBAR_LEFT:
//		ASSERT( m_rcLastInvisiblePreCalc.top <= m_rcLastInvisiblePreCalc.bottom );
		m_rcLastInvisiblePreCalc.right = m_rcLastInvisiblePreCalc.left; //  + 1;
		break;
	case AFX_IDW_DOCKBAR_RIGHT:
//		ASSERT( m_rcLastInvisiblePreCalc.top <= m_rcLastInvisiblePreCalc.bottom );
		m_rcLastInvisiblePreCalc.left = m_rcLastInvisiblePreCalc.right; //  - 1;
		break;
#ifdef _DEBUG
	default:
		ASSERT( FALSE );
		break;
#endif // _DEBUG
	} // switch( nOwnID )

//	MoveWindow( &m_rcLastInvisiblePreCalc, FALSE );

CFrameWnd * pFrame = _GetDockingFrameImpl();
	ASSERT_VALID( pFrame );
	ASSERT_KINDOF( CFrameWnd, pFrame );
	ASSERT( !pFrame->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)) );
	pFrame->ClientToScreen( &m_rcLastInvisiblePreCalc );

	return lResult;
}

BOOL CExtDockBar::RemoveControlBar(
	CControlBar * pBar,
	int nPosExclude, // -1
	int nAddPlaceHolder, // = 0
	bool bEnableFrameDelayRecalcLayout // = true
	)
{
//ph//
// temp
	if(	pBar->IsKindOf( RUNTIME_CLASS(CExtControlBar) )
		&& (! ((CExtControlBar*)pBar)->IsFixedDockStyle() )
		)
		nAddPlaceHolder = 0;

	ASSERT_VALID( this );
	ASSERT(
		nAddPlaceHolder == 1
		|| nAddPlaceHolder == 0
		|| nAddPlaceHolder == -1
		);
	ASSERT_VALID( this );
	ASSERT( pBar != NULL );
int nPos = FindBar( pBar, nPosExclude );
	ASSERT( nPos > 0 );

	if( nAddPlaceHolder == 1 )
	{
		m_arrBars[ nPos ] = (void*)
			_AfxGetDlgCtrlID( pBar->m_hWnd );
		// check for already existing place holder
		int nPosOld =
			FindBar(
				(CControlBar *) m_arrBars[ nPos ],
				nPos
				);
		if( nPosOld > 0 )
		{
			m_arrBars.RemoveAt( nPos );
			// remove section indicator (NULL) if nothing
			// else in section
			if( m_arrBars[ nPos - 1 ] == NULL
				&& m_arrBars[ nPos ] == NULL
				)
				m_arrBars.RemoveAt( nPos );
		} // if( nPosOld > 0 )
	} // if( nAddPlaceHolder == 1 )
	else
	{
		m_arrBars.RemoveAt( nPos );
		if( m_arrBars[nPos-1] == NULL
			&& m_arrBars[nPos] == NULL
			)
			m_arrBars.RemoveAt( nPos );

		// Remove any pre-existing place holders.
		if( nAddPlaceHolder != -1 )
			RemovePlaceHolder( pBar, true );
	} // else from if( nAddPlaceHolder == 1 )

	// don't do anything more in the shutdown case!
	if( pBar->m_pDockContext == NULL )
		return FALSE;

	// get parent frame for recalc layout/frame destroy
CFrameWnd * pFrameWnd = GetDockingFrame();
	if( m_bFloating && GetDockedVisibleCount() == 0 )
	{
		if( GetDockedCount() == 0 )
		{
			pFrameWnd->DestroyWindow();
			return TRUE; // Self-Destruct
		}
		else
			pFrameWnd->ShowWindow( SW_HIDE );
	} // if( m_bFloating && GetDockedVisibleCount() == 0 )
	else
	{
#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
		if( IsKindOf(RUNTIME_CLASS(CExtDockDynTabBar)) )
		{
			// TO FIX:

			//CExtDockDynTabBar * pTabbedDocker =
			//	STATIC_DOWNCAST(
			//		CExtDockDynTabBar,
			//		this
			//		);
			//pTabbedDocker->_SyncTabbedChilds(false,true);
			//OnDynamicLayoutUpdate();
			//pFrameWnd->RecalcLayout();

//			HWND hWndOwn = GetSafeHwnd();
//			ASSERT( hWndOwn != NULL );
//			ASSERT( ::IsWindow(hWndOwn) );
//			OnDynamicLayoutOptimize();
//			if( !::IsWindow(hWndOwn) )
//				return TRUE;


			CExtDynTabControlBar * pTabbedBar =
				STATIC_DOWNCAST(
					CExtDynTabControlBar,
					GetParent()
					);
			//pTabbedBar->SyncSwitcher();
			pTabbedBar->OnRepositionSingleChild();
		}
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)

		if( bEnableFrameDelayRecalcLayout )
			pFrameWnd->DelayRecalcLayout();
	} // else from if( m_bFloating && GetDockedVisibleCount() == 0 )

	return TRUE;
}

int CExtDockBar::Insert(
	CControlBar * pBarIns,
	CRect rect,
	CPoint ptMid
	)
{
	return _InsertByPointImpl( pBarIns, rect, ptMid );
}

int CExtDockBar::_InsertByPointImpl(
	CControlBar * pBarIns,
	CRect rect,
	CPoint ptMid
	)
{
	ASSERT_VALID( this );
	ASSERT( pBarIns != NULL );
	
//	ASSERT( pBarIns->m_pDockBar == this );

BOOL bExtBar = pBarIns->IsKindOf(RUNTIME_CLASS(CExtControlBar));
BOOL bExtFixedBar = FALSE;
	if( bExtBar )
		bExtFixedBar =  ((CExtControlBar *)pBarIns)->IsFixedMode();
BOOL bFixedBar = !bExtBar || bExtFixedBar;

INT nPos = 0, nPosInsAfter = -1, nWidth = 0, nTotalWidth = 0;
INT nCountOfSideBars = m_arrBars.GetSize();
BOOL bHorz = m_dwStyle & CBRS_ORIENT_HORZ;

CRect rcDockBarWnd;
	GetWindowRect( &rcDockBarWnd );
	if( rcDockBarWnd.PtInRect(ptMid) )
	{
		for( ; nPos < nCountOfSideBars; nPos++ )
		{
			CControlBar * pBar = GetDockedControlBar( nPos );
			if( pBar != NULL && pBar->IsVisible() )
			{
				CRect rcBar;
				pBar->GetWindowRect( &rcBar );
				//ScreenToClient( &rcBar );
				nWidth =
					max(
						nWidth,
						bHorz ? rcBar.Size().cy : rcBar.Size().cx - 1
						);
				if( bHorz
						? ( rect.left > rcBar.left )
						: ( rect.top  > rcBar.top  )
					)
				{
					//nPosInsAfter = nPos; // orig
					if( bFixedBar )
					{
						if( !pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar)) )
							nPosInsAfter = nPos;
						else if(
							((CExtControlBar *)pBar)->IsFixedMode()
							)
							nPosInsAfter = nPos;
					}
					else
						nPosInsAfter = nPos;
				}
				if( bFixedBar
					&& rcBar.PtInRect( ptMid )
					)
				{
					INT nDistUp = 0, nDistDown = 0;
					if( bHorz )
					{
						nDistUp = ptMid.y - rcBar.top;
						nDistDown = rcBar.bottom - ptMid.y;
					} // if( bHorz )
					else
					{
						nDistUp = ptMid.x - rcBar.left;
						nDistDown = rcBar.right - ptMid.x;
					} // else from if( bHorz )
					bool bNextRow = ( nDistUp < nDistDown ) ? false : true;
					CControlBar * pFirstBar =
						CExtControlBar::_GetFirstControlBarInRow(
							pBar,
							bNextRow
							);
					ASSERT_VALID( pFirstBar );
					nPosInsAfter = FindBar( pFirstBar );
					ASSERT( nPosInsAfter > 0 && nPosInsAfter < nCountOfSideBars );

					if( bNextRow )
					{
						m_arrBars.InsertAt( nPosInsAfter+1, pBarIns );
						m_arrBars.InsertAt( nPosInsAfter+1, (CObject*)NULL );
						ASSERT_VALID( this );
						ASSERT_BAR_LOCATION_IN_ROW( this, pBarIns );
						return nPosInsAfter+2;
					}
					else
					{
						m_arrBars.InsertAt( nPosInsAfter, (CObject*)NULL );
						m_arrBars.InsertAt( nPosInsAfter, pBarIns );
						ASSERT_VALID( this );
						ASSERT_BAR_LOCATION_IN_ROW( this, pBarIns );
						return nPosInsAfter+1;
					}


//					if( !bNextRow )
///						nPosInsAfter --;
//					break;
				}
			} // if( pBar != NULL && pBar->IsVisible() )
			else
			{
				if( pBar != NULL )
					continue;
				// end of row because pBar == NULL
				nTotalWidth += nWidth - afxData.cyBorder2;
				nWidth = 0;
				if( (bHorz ? ptMid.y : ptMid.x) < nTotalWidth )
				{
					if( nPos == 0 ) // first section
					{
						m_arrBars.InsertAt( 1, (CObject*)NULL );
						m_arrBars.InsertAt( 1, pBarIns );
						ASSERT_VALID( this );
						ASSERT_BAR_LOCATION_IN_ROW( this, pBarIns );
						return 1;
					} // if( nPos == 0 )
					else
					{
						if( !bFixedBar )
						{
							m_arrBars.InsertAt( nPos, pBarIns );
							ASSERT_VALID( this );
							ASSERT_BAR_LOCATION_IN_ROW( this, pBarIns );
						}
						//if( nPosInsAfter < 0 || !bFixedBar )
						if( nPosInsAfter < 0 )
							break;

						ASSERT( nPosInsAfter >= 0 && nPosInsAfter <= nCountOfSideBars );
						CControlBar * pBar2 = (CControlBar *)m_arrBars[ nPosInsAfter ];
						if( pBar2 == NULL )
							break;
						if(  __PLACEHODLER_BAR_PTR(pBar2) )
							break;
						CRect rcBar2;
						pBar2->GetWindowRect( &rcBar2 );

						INT nDistUp = 0, nDistDown = 0;
						if( bHorz )
						{
							nDistUp = ptMid.y - rcBar2.top;
							nDistDown = rcBar2.bottom - ptMid.y;
						} // if( bHorz )
						else
						{
							nDistUp = ptMid.x - rcBar2.left;
							nDistDown = rcBar2.right - ptMid.x;
						} // else from if( bHorz )
						bool bNextRow = ( nDistUp < nDistDown ) ? false : true;
						CControlBar * pFirstBar =
							CExtControlBar::_GetFirstControlBarInRow(
								pBar2,
								bNextRow
								);
						ASSERT_VALID( pFirstBar );
						nPosInsAfter = FindBar( pFirstBar );
						ASSERT( nPosInsAfter > 0 && nPosInsAfter < nCountOfSideBars );

						if( bNextRow )
						{
							m_arrBars.InsertAt( nPosInsAfter+1, pBarIns );
							m_arrBars.InsertAt( nPosInsAfter+1, (CObject*)NULL );
							ASSERT_VALID( this );
							ASSERT_BAR_LOCATION_IN_ROW( this, pBarIns );
							return nPosInsAfter+2;
						}
						else
						{
							m_arrBars.InsertAt( nPosInsAfter, (CObject*)NULL );
							m_arrBars.InsertAt( nPosInsAfter, pBarIns );
							ASSERT_VALID( this );
							ASSERT_BAR_LOCATION_IN_ROW( this, pBarIns );
							return nPosInsAfter+1;
						}

					} // else from if( nPos == 0 )
				}
//				nPosInsAfter = nPos;
			} // else from if( pBar != NULL && pBar->IsVisible() )

		} // for( ; nPos < nCountOfSideBars; nPos++ )
	} // if( rcDockBarWnd.PtInRect(ptMid) )

	if( nPosInsAfter < 0 )
	{
		INT nDistUp = 0, nDistDown = 0;
		if( bHorz )
		{
			nDistUp = ptMid.y - rcDockBarWnd.top;
			nDistDown = rcDockBarWnd.bottom - ptMid.y;
		} // if( bHorz )
		else
		{
			nDistUp = ptMid.x - rcDockBarWnd.left;
			nDistDown = rcDockBarWnd.right - ptMid.x;
		} // else from if( bHorz )
		bool bNextRow =
			( abs(nDistUp) < abs(nDistDown) )
			? false : true;
		nPosInsAfter = bNextRow ? (nCountOfSideBars-1) : 1;
	}

	ASSERT( nPosInsAfter < nCountOfSideBars );
	if( nPosInsAfter == nCountOfSideBars-1 )
		m_arrBars.InsertAt( nCountOfSideBars, (CObject*)NULL ); // upper bound NULL

	if( m_arrBars[ nPosInsAfter ] != NULL )
	{
		if( nPosInsAfter+1 < nCountOfSideBars
			&& m_arrBars[nPosInsAfter+1] != NULL
			)
			m_arrBars.InsertAt( nPosInsAfter+1, (CObject*)NULL );
	}

	m_arrBars.InsertAt( nPosInsAfter+1, pBarIns );

	for( nPos = nPosInsAfter; nPos > 0; nPos-- )
	{
		CControlBar * pBar = (CControlBar *)m_arrBars[nPos];
		if( pBar == NULL )
			break;
		if( __PLACEHODLER_BAR_PTR(pBar) )
		{
			pBar = _GetDockingFrameImpl()->GetControlBar( LOWORD( DWORD(pBar) ) );
			if( pBar == NULL )
				continue;
		}
	
		BOOL bPrevFixedCheck = TRUE;
		if( pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar))
			&& !((CExtControlBar *)pBar)->IsFixedMode()
			)
			bPrevFixedCheck = FALSE;
		if( bFixedBar != bPrevFixedCheck )
		{
			m_arrBars.InsertAt( nPosInsAfter+1, (CObject*)NULL );
			nPosInsAfter++;
		}

		break;
	} // for( INT nPos = nPosInsAfter; nPos > 0; nPos-- )
	
//	ASSERT( FindBar(pBarIns) == (nPosInsAfter+1) );
	ASSERT_VALID( this );
	ASSERT_BAR_LOCATION_IN_ROW( this, pBarIns );

	return nPosInsAfter+1;
}

#ifdef _DEBUG

void CExtDockBar::_AssertValid_CheckBarRows() const
{

	ASSERT( this != NULL );
	if( m_hWnd == NULL )
		return;
	if( ! ::IsWindow(m_hWnd) )
		return;

CRect rcMyWnd;
	GetWindowRect( &rcMyWnd );
CSize sizeMyWnd = rcMyWnd.Size();
	if( sizeMyWnd.cx < 40 || sizeMyWnd.cy < 40 )
		return;

INT nCountOfSideBars = m_arrBars.GetSize();
	ASSERT( nCountOfSideBars > 0 );

// first should be NULL
CControlBar * pFirstPosBar = (CControlBar *) m_arrBars[ 0 ];
	ASSERT( pFirstPosBar == NULL );

	if( m_nCircleNo == 0 )
		return;

// walk all rows and verify no empty rows
INT nRowEntryCount = 0; // including placeholders
INT nBar = 1;
	
	if( nCountOfSideBars > 2  )
	{
		for( ; nBar < nCountOfSideBars; nBar++ )
		{
			CControlBar * pBar = (CControlBar *) m_arrBars[ nBar ];
			if( pBar == NULL )
			{
				ASSERT( nRowEntryCount > 0 );
				nRowEntryCount = 0;
				continue;
			}
			nRowEntryCount++;
		} // for( ; nBar < nCountOfSideBars; nBar++ )
	}
}

void CExtDockBar::_AssertValid_FixedBarNotInNonfixedRow(
	CDockBar * pDockBar,
	CControlBar * pBar
	)
{
	// verify bar and its dockbar
	ASSERT_VALID( pBar );
	ASSERT_KINDOF( CControlBar, pBar->m_pDockBar );
	ASSERT( !pBar->IsDockBar() );
	ASSERT( !pBar->IsKindOf(RUNTIME_CLASS(CDockBar)) );
//	ASSERT( !pBar->IsFloating() );
	
//	ASSERT( pBar->m_pDockBar != NULL );
//	ASSERT_VALID( pBar->m_pDockBar );
//	ASSERT_KINDOF( CExtDockBar, pBar->m_pDockBar );
//CExtDockBar * pDockBar = (CExtDockBar *)pBar->m_pDockBar;

	ASSERT_VALID( pDockBar );
	ASSERT_KINDOF( CDockBar, pDockBar );

bool bCheckingFixedBar = true;
	// verify bar is not a kind of resizable bar
	if( pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar)) )
	{
		CExtControlBar * pExtBar = (CExtControlBar *)pBar;
		if( !pExtBar->IsFixedDockStyle() )
			bCheckingFixedBar = false;
	}

INT nCountOfSideBars = pDockBar->m_arrBars.GetSize();
	ASSERT( nCountOfSideBars > 0 );
INT nBarPosInDockBar = pDockBar->FindBar( pBar );
	ASSERT( nBarPosInDockBar > 0 && nBarPosInDockBar < nCountOfSideBars );

	// walk to begin of row
	for( INT nBar = nBarPosInDockBar-1; nBar > 0; nBar-- )
	{
		CControlBar * pBarExamine = (CControlBar *)
			pDockBar->m_arrBars[ nBar ];
		if( pBarExamine == NULL )
			break; // ok
		if( __PLACEHODLER_BAR_PTR(pBarExamine) )
			continue;
		ASSERT_VALID( pBarExamine );
		ASSERT_KINDOF( CControlBar, pBarExamine );
		ASSERT( pBarExamine->m_pDockBar == pDockBar );
		
		bool bFixedBar = true;
		if( pBarExamine->IsKindOf(RUNTIME_CLASS(CExtControlBar)) )
		{
			CExtControlBar * pExtBar = (CExtControlBar *)pBarExamine;
			//ASSERT( pExtBar->IsFixedMode() );
			if( !pExtBar->IsFixedDockStyle() )
				bFixedBar = false;
		}
		ASSERT( bCheckingFixedBar == bFixedBar );
	}
	
	// walk to end of row
	for( nBar = nBarPosInDockBar+1; nBar < nCountOfSideBars; nBar++ )
	{
		CControlBar * pBarExamine = (CControlBar *)
			pDockBar->m_arrBars[ nBar ];
		if( pBarExamine == NULL )
			break; // ok
		if( __PLACEHODLER_BAR_PTR(pBarExamine) )
			continue;
		ASSERT_VALID( pBarExamine );
		ASSERT_KINDOF( CControlBar, pBarExamine );
		ASSERT( pBarExamine->m_pDockBar == pDockBar );

		bool bFixedBar = true;
		if( pBarExamine->IsKindOf(RUNTIME_CLASS(CExtControlBar)) )
		{
			CExtControlBar * pExtBar = (CExtControlBar *)pBarExamine;
			//ASSERT( pExtBar->IsFixedMode() );
			if( !pExtBar->IsFixedDockStyle() )
				bFixedBar = false;
		}
		ASSERT( bCheckingFixedBar == bFixedBar );
	}
	
}

#endif // _DEBUG

void CExtDockBar::OnNcCalcSize(
	BOOL bCalcValidRects,
	NCCALCSIZE_PARAMS * lpncsp
	)
{
	ASSERT_VALID( this );
	bCalcValidRects;
	lpncsp;

#if (defined __DEBUG_PAINTING_AREAS_DOCKBAR__ )

CRect & rcClientLoc =
		reinterpret_cast < CRect & > ( lpncsp->rgrc[0] );
	rcClientLoc.DeflateRect( 0, 0, 1, 1 );

#endif // __DEBUG_PAINTING_AREAS_DOCKBAR__
}

void CExtDockBar::OnNcPaint()
{
	ASSERT_VALID( this );

#if (defined __DEBUG_PAINTING_AREAS_DOCKBAR__ )

CRect rcBarWnd, rcBarClient;
	GetWindowRect( &rcBarWnd );
	GetClientRect( &rcBarClient );
	ClientToScreen( &rcBarClient );
	if( rcBarWnd == rcBarClient )
		return;
CPoint ptDevOffset = -rcBarWnd.TopLeft();
	rcBarWnd.OffsetRect( ptDevOffset );
	rcBarClient.OffsetRect( ptDevOffset );

CWindowDC dcBarWnd( this );
	ASSERT( dcBarWnd.GetSafeHdc() != NULL );
	dcBarWnd.ExcludeClipRect( &rcBarClient );

BOOL bDynamicDockBar = IsKindOf( RUNTIME_CLASS(CExtDockDynBar) );

COLORREF clrDebugMargin = bDynamicDockBar
		? RGB( 255, 255, 0 )
		: RGB( 255, 0, 255 );

	dcBarWnd.FillSolidRect( &rcBarWnd, clrDebugMargin );

#endif // __DEBUG_PAINTING_AREAS_DOCKBAR__
}

CExtDockBar * CExtDockBar::_GetInCircle(
	UINT nDockBarID,
	bool bEnableCreateNew // = true
	)
{
	ASSERT_VALID( this );
UINT nOwnID = GetDlgCtrlID();
	if( nDockBarID == nOwnID )
		return this;
CFrameWnd * pFrame = GetParentFrame();
	ASSERT_VALID( pFrame );
	ASSERT( !pFrame->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)) );
	return
		_GetInCircle(
			pFrame,
			m_nCircleNo,
			nDockBarID,
			bEnableCreateNew
			);
}

CExtDockBar * CExtDockBar::_GetInCircle(
	CFrameWnd * pFrame,
	UINT nCircleNo,
	UINT nDockBarID,
	bool bEnableCreateNew // = true
	)
{
	ASSERT_VALID( pFrame );
POSITION pos = pFrame->m_listControlBars.GetHeadPosition();
	ASSERT( pos != NULL );
	while( pos != NULL )
	{
		CControlBar * pBar = (CControlBar *)
			pFrame->m_listControlBars.GetNext( pos );
		ASSERT_VALID( pBar );
		ASSERT_KINDOF( CControlBar, pBar );
		if( !pBar->IsKindOf(RUNTIME_CLASS(CExtDockBar)) )
			continue;
		UINT nID = pBar->GetDlgCtrlID();
		if( nID != nDockBarID )
			continue;
		UINT nCircleNo2 = ((CExtDockBar *)pBar)->_GetCircleNo();
		if( nCircleNo == nCircleNo2 )
			return ((CExtDockBar *)pBar);
	} // while( pos != NULL )
	if( !bEnableCreateNew )
		return NULL;
	_CreateInnerCircle( pFrame );
CExtDockBar * pDockBar =
		_GetInCircle(
			pFrame,
			nCircleNo,
			nDockBarID,
			bEnableCreateNew
			);
	ASSERT_VALID( pDockBar );
	return pDockBar;
}

UINT CExtDockBar::_CreateInnerCircle()
{
	ASSERT_VALID( this );
	if( _GetDockBarInner() != NULL )
	{
		ASSERT_VALID( _GetDockBarInner() );
		return ( _GetCircleNo() + 1 );
	}
CFrameWnd * pFrame = GetParentFrame();
	ASSERT_VALID( pFrame );
	ASSERT( !pFrame->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)) );
	return _CreateInnerCircle( pFrame );
}

UINT CExtDockBar::_CreateInnerCircle( CFrameWnd * pFrame )
{
	ASSERT_VALID( pFrame );
	ASSERT( !pFrame->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)) );

UINT nCircleNo = 0;
CExtDockBar * vInnerCircle[4] = { NULL, NULL, NULL, NULL };
CExtDockBar * vCreatingCircle[4] = { NULL, NULL, NULL, NULL };

POSITION pos = pFrame->m_listControlBars.GetHeadPosition();
	ASSERT( pos != NULL );
	while( pos != NULL )
	{
		CControlBar * pBar = (CControlBar *)
			pFrame->m_listControlBars.GetNext( pos );
		ASSERT_VALID( pBar );
		ASSERT_KINDOF( CControlBar, pBar );
		if( !pBar->IsKindOf(RUNTIME_CLASS(CExtDockBar)) )
			continue;
		if( pBar->IsKindOf(RUNTIME_CLASS(CExtDockDynBar)) )
			continue;
		UINT nCircleNo2 = ((CExtDockBar *)pBar)->_GetCircleNo();
		if( nCircleNo2 < nCircleNo )
			continue;
		nCircleNo = nCircleNo2;
		UINT nID = pBar->GetDlgCtrlID();
		//if( nID == AFX_IDW_DOCKBAR_FLOAT )
		//	continue;
		ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nID );
		switch( nID )
		{
		case AFX_IDW_DOCKBAR_TOP:
			vInnerCircle[0] = ((CExtDockBar *)pBar);
			break;
		case AFX_IDW_DOCKBAR_BOTTOM:
			vInnerCircle[1] = ((CExtDockBar *)pBar);
			break;
		case AFX_IDW_DOCKBAR_LEFT:
			vInnerCircle[2] = ((CExtDockBar *)pBar);
			break;
		case AFX_IDW_DOCKBAR_RIGHT:
			vInnerCircle[3] = ((CExtDockBar *)pBar);
			break;
#ifdef _DEBUG
		default:
			ASSERT( FALSE );
			break;
#endif // _DEBUG
		} // switch( nID )
	} // while( pos != NULL )

	ASSERT( vInnerCircle[0] != NULL );
	ASSERT( vInnerCircle[1] != NULL );
	ASSERT( vInnerCircle[2] != NULL );
	ASSERT( vInnerCircle[3] != NULL );

#ifdef _DEBUG
	if( vInnerCircle[0]->m_pDockBarInner == NULL )
	{
		ASSERT( vInnerCircle[1]->m_pDockBarInner == NULL );
		ASSERT( vInnerCircle[2]->m_pDockBarInner == NULL );
		ASSERT( vInnerCircle[3]->m_pDockBarInner == NULL );
	}
	else
	{
		ASSERT( vInnerCircle[1]->m_pDockBarInner != NULL );
		ASSERT( vInnerCircle[2]->m_pDockBarInner != NULL );
		ASSERT( vInnerCircle[3]->m_pDockBarInner != NULL );
	}
	if( vInnerCircle[0]->m_pDockBarOuter == NULL )
	{
		ASSERT( vInnerCircle[1]->m_pDockBarOuter == NULL );
		ASSERT( vInnerCircle[2]->m_pDockBarOuter == NULL );
		ASSERT( vInnerCircle[3]->m_pDockBarOuter == NULL );
	}
	else
	{
		ASSERT( vInnerCircle[1]->m_pDockBarOuter != NULL );
		ASSERT( vInnerCircle[2]->m_pDockBarOuter != NULL );
		ASSERT( vInnerCircle[3]->m_pDockBarOuter != NULL );
	}
#endif // _DEBUG

	nCircleNo ++;


	for( INT i = 0; i<4; i++ )
	{
		CExtDockBar * pBar = vInnerCircle[i];
		UINT nID = pBar->GetDlgCtrlID();
		ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nID );
		ASSERT( vCreatingCircle[i] == NULL );
		vCreatingCircle[i] =
			new CExtDockBar( nCircleNo );
static const DWORD dwAlignFlags[4] =
{
	CBRS_ALIGN_TOP,
	CBRS_ALIGN_BOTTOM,
	CBRS_ALIGN_LEFT,
	CBRS_ALIGN_RIGHT
};
		DWORD dwStyle =
			WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN
			|dwAlignFlags[i] // |CBRS_ALIGN_ANY
			;
		VERIFY(
			vCreatingCircle[i]->Create( pFrame, dwStyle, nID )
			);
		ASSERT( pBar->m_pDockBarInner == NULL );
		ASSERT( vCreatingCircle[i]->m_pDockBarInner == NULL );
		ASSERT( vCreatingCircle[i]->m_pDockBarOuter == NULL );
		pBar->m_pDockBarInner = vCreatingCircle[i];
		vCreatingCircle[i]->m_pDockBarOuter = pBar;
		vCreatingCircle[i]->SetBarStyle( pBar->GetBarStyle() );

#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
		vCreatingCircle[i]->m_pWndAutoHideArea =
			pBar->m_pWndAutoHideArea;
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
		
		
		if( (pBar->GetStyle() & WS_VISIBLE) != NULL
			&& pBar->GetDockedVisibleCount() != 0
			)
		{
			pBar->GetWindowRect( &vCreatingCircle[i]->m_rcLastInvisiblePreCalc );
			switch( nID )
			{
			case AFX_IDW_DOCKBAR_TOP:
				ASSERT( vCreatingCircle[i]->m_rcLastInvisiblePreCalc.left <= vCreatingCircle[i]->m_rcLastInvisiblePreCalc.right );
				vCreatingCircle[i]->m_rcLastInvisiblePreCalc.bottom = vCreatingCircle[i]->m_rcLastInvisiblePreCalc.top; // + 1;
				break;
			case AFX_IDW_DOCKBAR_BOTTOM:
				ASSERT( vCreatingCircle[i]->m_rcLastInvisiblePreCalc.left <= vCreatingCircle[i]->m_rcLastInvisiblePreCalc.right );
				vCreatingCircle[i]->m_rcLastInvisiblePreCalc.top = vCreatingCircle[i]->m_rcLastInvisiblePreCalc.bottom; //  - 1;
				break;
			case AFX_IDW_DOCKBAR_LEFT:
				ASSERT( vCreatingCircle[i]->m_rcLastInvisiblePreCalc.top <= vCreatingCircle[i]->m_rcLastInvisiblePreCalc.bottom );
				vCreatingCircle[i]->m_rcLastInvisiblePreCalc.right = vCreatingCircle[i]->m_rcLastInvisiblePreCalc.left; //  + 1;
				break;
			case AFX_IDW_DOCKBAR_RIGHT:
				ASSERT( vCreatingCircle[i]->m_rcLastInvisiblePreCalc.top <= vCreatingCircle[i]->m_rcLastInvisiblePreCalc.bottom );
				vCreatingCircle[i]->m_rcLastInvisiblePreCalc.left = vCreatingCircle[i]->m_rcLastInvisiblePreCalc.right; //  - 1;
				break;
#ifdef _DEBUG
			default:
				ASSERT( FALSE );
				break;
#endif // _DEBUG
			} // switch( nID )
		} // if( (pBar->GetStyle()&WS_VISIBLE) != NULL  .....
		else
			vCreatingCircle[i]->m_rcLastInvisiblePreCalc = pBar->m_rcLastInvisiblePreCalc;

		// reposition created circle in parent HWND list
		switch( nID )
		{
		case AFX_IDW_DOCKBAR_TOP:
			ASSERT( i == 0 );
			ASSERT( vCreatingCircle[i] != NULL );
			ASSERT( vCreatingCircle[i]->GetSafeHwnd() != NULL );
			ASSERT( ::IsWindow( vCreatingCircle[i]->GetSafeHwnd() ) );
			ASSERT( vInnerCircle[3] != NULL );
			ASSERT( vInnerCircle[3]->GetSafeHwnd() != NULL );
			ASSERT( ::IsWindow( vInnerCircle[3]->GetSafeHwnd() ) );
			VERIFY(
				::SetWindowPos(
					vCreatingCircle[i]->GetSafeHwnd(),
					vInnerCircle[3]->GetSafeHwnd(),
					0, 0, 0, 0,
					SWP_NOSIZE|SWP_NOMOVE
						|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOCOPYBITS
						|SWP_NOSENDCHANGING
					)
				);
			break;
		case AFX_IDW_DOCKBAR_BOTTOM:
		case AFX_IDW_DOCKBAR_LEFT:
		case AFX_IDW_DOCKBAR_RIGHT:
			ASSERT( i >= 1 && i <= 3 );
			ASSERT( vCreatingCircle[i] != NULL );
			ASSERT( vCreatingCircle[i]->GetSafeHwnd() != NULL );
			ASSERT( ::IsWindow( vCreatingCircle[i]->GetSafeHwnd() ) );
			ASSERT( vCreatingCircle[i-1] != NULL );
			ASSERT( vCreatingCircle[i-1]->GetSafeHwnd() != NULL );
			ASSERT( ::IsWindow( vCreatingCircle[i-1]->GetSafeHwnd() ) );
			VERIFY(
				::SetWindowPos(
					vCreatingCircle[i]->GetSafeHwnd(),
					vCreatingCircle[i-1]->GetSafeHwnd(),
					0, 0, 0, 0,
					SWP_NOSIZE|SWP_NOMOVE
						|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOCOPYBITS
						|SWP_NOSENDCHANGING
					)
				);
			break;
#ifdef _DEBUG
		default:
			ASSERT( FALSE );
			break;
#endif // _DEBUG
		} // switch( nID )
	
	}

	ASSERT( vInnerCircle[0]->m_pDockBarInner != NULL );
	ASSERT( vInnerCircle[1]->m_pDockBarInner != NULL );
	ASSERT( vInnerCircle[2]->m_pDockBarInner != NULL );
	ASSERT( vInnerCircle[3]->m_pDockBarInner != NULL );
	
#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
	if( vInnerCircle[0]->m_pWndAutoHideArea != NULL )
	{
		vInnerCircle[0]->m_pWndAutoHideArea->AdjustOrder();
		vInnerCircle[1]->m_pWndAutoHideArea->AdjustOrder();
		vInnerCircle[2]->m_pWndAutoHideArea->AdjustOrder();
		vInnerCircle[3]->m_pWndAutoHideArea->AdjustOrder();
	}
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)

	ASSERT( nCircleNo > 0 );
	return nCircleNo;
}

void CExtDockBar::_InjectInnerCircle()
{
	ASSERT_VALID( this );
	_InjectCircle( m_nCircleNo + 1 );
}

void CExtDockBar::_InjectCircle( UINT nCircleNo )
{
	ASSERT_VALID( this );
	ASSERT( nCircleNo > 0 );

CFrameWnd * pFrame = GetParentFrame();
	ASSERT_VALID( pFrame );
	ASSERT( !pFrame->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)) );
	_InjectCircle( pFrame, nCircleNo );
}

void CExtDockBar::_InjectCircle( CFrameWnd * pFrame, UINT nCircleNo )
{
	ASSERT_VALID( pFrame );
	ASSERT( nCircleNo > 0 );

CExtDockBar * vCircleOld[4];
	vCircleOld[0] = (CExtDockBar *)pFrame->GetControlBar( AFX_IDW_DOCKBAR_TOP );
	vCircleOld[1] = (CExtDockBar *)pFrame->GetControlBar( AFX_IDW_DOCKBAR_BOTTOM );
	vCircleOld[2] = (CExtDockBar *)pFrame->GetControlBar( AFX_IDW_DOCKBAR_LEFT );
	vCircleOld[3] = (CExtDockBar *)pFrame->GetControlBar( AFX_IDW_DOCKBAR_RIGHT );
bool bEmptyCircleExist = true;
	for( INT nDockSide = 0; nDockSide < 4; nDockSide++ )
	{
		ASSERT_VALID( vCircleOld[nDockSide] );
		ASSERT_KINDOF( CExtDockBar, vCircleOld[nDockSide] );
		ASSERT( vCircleOld[nDockSide]->_GetCircleNo() == 0 );
		vCircleOld[nDockSide] = vCircleOld[nDockSide]->_GetBarByCircleNo( nCircleNo );
		ASSERT_VALID( vCircleOld[nDockSide] );
		ASSERT( vCircleOld[nDockSide]->_GetCircleNo() == nCircleNo );
		if( ! vCircleOld[nDockSide]->_CanBeSafeOptimized() )
			bEmptyCircleExist = false;
	} // for( INT nDockSide = 0; nDockSide < 4; nDockSide++ )
	if( bEmptyCircleExist )
	{
#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
		if( vCircleOld[0]->m_pWndAutoHideArea != NULL )
		{
			vCircleOld[0]->m_pWndAutoHideArea->AdjustOrder();
			vCircleOld[1]->m_pWndAutoHideArea->AdjustOrder();
			vCircleOld[2]->m_pWndAutoHideArea->AdjustOrder();
			vCircleOld[3]->m_pWndAutoHideArea->AdjustOrder();
		}
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
		return;
	}

CExtDockBar * vCircleNew[4] = { NULL, NULL, NULL, NULL };
	for( nDockSide = 0; nDockSide < 4; nDockSide++ )
	{
		ASSERT_VALID( vCircleOld[nDockSide] );
		ASSERT( vCircleOld[nDockSide]->_GetCircleNo() == nCircleNo );

		UINT nID = vCircleOld[nDockSide]->GetDlgCtrlID();
		ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nID );
		vCircleNew[nDockSide] =
			new CExtDockBar( nCircleNo );
		
#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
		vCircleNew[nDockSide]->m_pWndAutoHideArea =
			vCircleOld[nDockSide]->m_pWndAutoHideArea;
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
		
static const DWORD dwAlignFlags[4] =
{
	CBRS_ALIGN_TOP,
	CBRS_ALIGN_BOTTOM,
	CBRS_ALIGN_LEFT,
	CBRS_ALIGN_RIGHT
};
		DWORD dwStyle =
			WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN
			|dwAlignFlags[nDockSide] // |CBRS_ALIGN_ANY
			;
		VERIFY(
			vCircleNew[nDockSide]->Create( pFrame, dwStyle, nID )
			);
		ASSERT( vCircleNew[nDockSide]->m_pDockBarInner == NULL );
		ASSERT( vCircleNew[nDockSide]->m_pDockBarOuter == NULL );
		ASSERT( vCircleOld[nDockSide]->m_pDockBarOuter != NULL );
		ASSERT( vCircleOld[nDockSide]->m_pDockBarOuter->m_pDockBarInner == vCircleOld[nDockSide] );
		
		vCircleOld[nDockSide]->m_pDockBarOuter->m_pDockBarInner = vCircleNew[nDockSide];
		vCircleNew[nDockSide]->m_pDockBarOuter = vCircleOld[nDockSide]->m_pDockBarOuter;
		vCircleOld[nDockSide]->m_pDockBarOuter = vCircleNew[nDockSide];
		vCircleNew[nDockSide]->m_pDockBarInner = vCircleOld[nDockSide];

		vCircleNew[nDockSide]->SetBarStyle(
			vCircleOld[nDockSide]->GetBarStyle()
			);
		if( (vCircleOld[nDockSide]->GetStyle() & WS_VISIBLE) != NULL
			&& vCircleOld[nDockSide]->GetDockedVisibleCount() != 0
			)
		{
			vCircleOld[nDockSide]->GetWindowRect(
				&(vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc)
				);
			switch( nID )
			{
			case AFX_IDW_DOCKBAR_TOP:
				ASSERT( vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.left <= vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.right );
				vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.bottom = vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.top; // + 1;
				break;
			case AFX_IDW_DOCKBAR_BOTTOM:
				ASSERT( vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.left <= vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.right );
				vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.top = vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.bottom; //  - 1;
				break;
			case AFX_IDW_DOCKBAR_LEFT:
				ASSERT( vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.top <= vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.bottom );
				vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.right = vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.left; //  + 1;
				break;
			case AFX_IDW_DOCKBAR_RIGHT:
				ASSERT( vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.top <= vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.bottom );
				vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.left = vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc.right; //  - 1;
				break;
#ifdef _DEBUG
			default:
				ASSERT( FALSE );
				break;
#endif // _DEBUG
			} // switch( nID )
		} // if( (vCircleOld[nDockSide]->GetStyle()&WS_VISIBLE) != NULL  .....
		else
			vCircleNew[nDockSide]->m_rcLastInvisiblePreCalc =
				vCircleOld[nDockSide]->m_rcLastInvisiblePreCalc;
		
		for(	CExtDockBar * pResetNoBar = vCircleOld[nDockSide];
				pResetNoBar != NULL;
				pResetNoBar = pResetNoBar->m_pDockBarInner
				)
			pResetNoBar->m_nCircleNo++;

		switch( nID )
		{
		case AFX_IDW_DOCKBAR_TOP:
			ASSERT( nDockSide == 0 );
			ASSERT( vCircleOld[3]->m_pDockBarOuter != NULL );
			ASSERT( vCircleOld[3]->m_pDockBarOuter->GetSafeHwnd() != NULL );
			ASSERT( ::IsWindow( vCircleOld[3]->m_pDockBarOuter->GetSafeHwnd() ) );

			ASSERT( vCircleNew[nDockSide] != NULL );
			ASSERT( vCircleNew[nDockSide]->GetSafeHwnd() != NULL );
			ASSERT( ::IsWindow( vCircleNew[nDockSide]->GetSafeHwnd() ) );

			VERIFY(
				::SetWindowPos(
					vCircleNew[nDockSide]->GetSafeHwnd(),
					vCircleOld[3]->m_pDockBarOuter->GetSafeHwnd(),
					0, 0, 0, 0,
					SWP_NOSIZE|SWP_NOMOVE
						|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOCOPYBITS
						|SWP_NOSENDCHANGING
					)
				);
			break;
		case AFX_IDW_DOCKBAR_BOTTOM:
		case AFX_IDW_DOCKBAR_LEFT:
		case AFX_IDW_DOCKBAR_RIGHT:
			ASSERT( nDockSide > 0 );
			ASSERT( vCircleNew[nDockSide-1] != NULL );
			ASSERT( vCircleNew[nDockSide-1]->GetSafeHwnd() != NULL );
			ASSERT( ::IsWindow( vCircleNew[nDockSide-1]->GetSafeHwnd() ) );

			ASSERT( vCircleNew[nDockSide] != NULL );
			ASSERT( vCircleNew[nDockSide]->GetSafeHwnd() != NULL );
			ASSERT( ::IsWindow( vCircleNew[nDockSide]->GetSafeHwnd() ) );

			VERIFY(
				::SetWindowPos(
					vCircleNew[nDockSide]->GetSafeHwnd(),
					vCircleNew[nDockSide-1]->GetSafeHwnd(),
					0, 0, 0, 0,
					SWP_NOSIZE|SWP_NOMOVE
						|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOCOPYBITS
						|SWP_NOSENDCHANGING
					)
				);
			break;
#ifdef _DEBUG
		default:
			ASSERT( FALSE );
			break;
#endif // _DEBUG
		} // switch( nID )

//		VERIFY(
//			::SetWindowPos(
//				vCircleNew[nDockSide]->GetSafeHwnd(),
//				vCircleOld[nDockSide]->m_pDockBarOuter->_GetHwndForInjectingAfter(),
//				0, 0, 0, 0,
//				SWP_NOSIZE|SWP_NOMOVE
//					|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOCOPYBITS
//					|SWP_NOSENDCHANGING
//				)
//			);

	} // for( nDockSide = 0; nDockSide < 4; nDockSide++ )
	ASSERT_VALID( vCircleNew[0] );
	ASSERT_VALID( vCircleNew[1] );
	ASSERT_VALID( vCircleNew[2] );
	ASSERT_VALID( vCircleNew[3] );

#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
	if( vCircleNew[0]->m_pWndAutoHideArea != NULL )
	{
		vCircleNew[0]->m_pWndAutoHideArea->AdjustOrder();
		vCircleNew[1]->m_pWndAutoHideArea->AdjustOrder();
		vCircleNew[2]->m_pWndAutoHideArea->AdjustOrder();
		vCircleNew[3]->m_pWndAutoHideArea->AdjustOrder();
	}
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
}

#ifdef _DEBUG

void CExtDockBar::_Assert_HwndIsDockbar(
	HWND hWndDockBar,
	UINT nDockBarID,
	UINT nCircleNo
	)
{
	ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nDockBarID );
	ASSERT( hWndDockBar != NULL );
	ASSERT( ::IsWindow( hWndDockBar ) );
CWnd * pWndDockBar = CWnd::FromHandlePermanent( hWndDockBar );
	ASSERT_VALID( pWndDockBar );
CExtDockBar * pDockBar =
		STATIC_DOWNCAST( CExtDockBar, pWndDockBar );
UINT nRealDockBarID = pDockBar->GetDlgCtrlID();
	ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nRealDockBarID );
	ASSERT( nDockBarID == nRealDockBarID );
UINT nRealCircleNo = pDockBar->_GetCircleNo();
	ASSERT( nRealCircleNo == nCircleNo );
}

#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
void CExtDockBar::_Assert_HwndIsAutoHider(
	HWND hWndAutoHider,
	UINT nAutoHiderID
	)
{
	ASSERT( hWndAutoHider != NULL );
	ASSERT( ::IsWindow( hWndAutoHider ) );
CWnd * pWndAutoHider = CWnd::FromHandlePermanent( hWndAutoHider );
	ASSERT_VALID( pWndAutoHider );
CExtDynAutoHideArea * pAutoHider =
		STATIC_DOWNCAST( CExtDynAutoHideArea, pWndAutoHider );
UINT nRealAutoHiderID = pAutoHider->GetDlgCtrlID();
	ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nRealAutoHiderID );
	ASSERT( nAutoHiderID == nRealAutoHiderID );
}
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)

#endif // _DEBUG

//HWND CExtDockBar::_GetHwndForInjectingAfter()
//{
//	ASSERT_VALID( this );
//HWND hWndOwn = GetSafeHwnd();
//	ASSERT( hWndOwn != NULL );
//	ASSERT( ::IsWindow( hWndOwn ) );
//
//UINT nOwnID = GetDlgCtrlID();
//	ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nOwnID );
//
//HWND hWndAutoHideArea = m_pWndAutoHideArea->GetSafeHwnd();
//UINT nOwnCircleNo =  _GetCircleNo();
//
//HWND hWndInsertAfter =
//		(hWndAutoHideArea != NULL && nOwnCircleNo == 0)
//			? hWndAutoHideArea
//			: hWndOwn
//			;
//	switch( nOwnID )
//	{
//	case AFX_IDW_DOCKBAR_TOP:
//	{
//		// get dockbar in same circle (nOwnCircleNo) - bottom
//		hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//		ASSERT_HWND_IS_DOCKBAR( hWndInsertAfter, AFX_IDW_DOCKBAR_BOTTOM, nOwnCircleNo );
//		// get dockbar in same circle (nOwnCircleNo) - left
//		hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//		ASSERT_HWND_IS_DOCKBAR( hWndInsertAfter, AFX_IDW_DOCKBAR_LEFT, nOwnCircleNo );
//		// get dockbar in same circle (nOwnCircleNo) - right
//		hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//		ASSERT_HWND_IS_DOCKBAR( hWndInsertAfter, AFX_IDW_DOCKBAR_RIGHT, nOwnCircleNo );
//		if( nOwnCircleNo == 0 && hWndAutoHideArea != NULL )
//		{
//			// get autohider - top
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_TOP );
//			// get autohider - bottom
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_BOTTOM );
//			// get autohider - left
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_LEFT );
//			// get autohider - right
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_RIGHT );
//		}
//	}
//	break; // case AFX_IDW_DOCKBAR_TOP
//	case AFX_IDW_DOCKBAR_BOTTOM:
//	{
//		// get dockbar in same circle (nOwnCircleNo) - left
//		hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//		ASSERT_HWND_IS_DOCKBAR( hWndInsertAfter, AFX_IDW_DOCKBAR_LEFT, nOwnCircleNo );
//		// get dockbar in same circle (nOwnCircleNo) - right
//		hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//		ASSERT_HWND_IS_DOCKBAR( hWndInsertAfter, AFX_IDW_DOCKBAR_RIGHT, nOwnCircleNo );
//		if( nOwnCircleNo == 0 && hWndAutoHideArea != NULL )
//		{
//			// get autohider - top
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_TOP );
//			// get autohider - bottom
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_BOTTOM );
//			// get autohider - left
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_LEFT );
//			// get autohider - right
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_RIGHT );
//		}
//		// get dockbar in next circle (nOwnCircleNo+1) - top
//		hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//		ASSERT_HWND_IS_DOCKBAR( hWndInsertAfter, AFX_IDW_DOCKBAR_TOP, (nOwnCircleNo+1) );
//	}
//	break; // case AFX_IDW_DOCKBAR_BOTTOM
//	case AFX_IDW_DOCKBAR_LEFT:
//	{
//		// get dockbar in same circle (nOwnCircleNo) - right
//		hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//		ASSERT_HWND_IS_DOCKBAR( hWndInsertAfter, AFX_IDW_DOCKBAR_RIGHT, nOwnCircleNo );
//		if( nOwnCircleNo == 0 && hWndAutoHideArea != NULL )
//		{
//			// get autohider - top
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_TOP );
//			// get autohider - bottom
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_BOTTOM );
//			// get autohider - left
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_LEFT );
//			// get autohider - right
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_RIGHT );
//		}
//		// get dockbar in next circle (nOwnCircleNo+1) - top
//		hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//		ASSERT_HWND_IS_DOCKBAR( hWndInsertAfter, AFX_IDW_DOCKBAR_TOP, (nOwnCircleNo+1) );
//		// get dockbar in next circle (nOwnCircleNo+1) - bottom
//		hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//		ASSERT_HWND_IS_DOCKBAR( hWndInsertAfter, AFX_IDW_DOCKBAR_BOTTOM, (nOwnCircleNo+1) );
//	}
//	break; // case AFX_IDW_DOCKBAR_LEFT
//	case AFX_IDW_DOCKBAR_RIGHT:
//	{
//		if( nOwnCircleNo == 0 && hWndAutoHideArea != NULL )
//		{
//			// get autohider - top
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_TOP );
//			// get autohider - bottom
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_BOTTOM );
//			// get autohider - left
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_LEFT );
//			// get autohider - right
//			hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//			ASSERT_HWND_IS_AUTOHIDER( hWndInsertAfter, AFX_IDW_DOCKBAR_RIGHT );
//		}
//		// get dockbar in next circle (nOwnCircleNo+1) - top
//		hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//		ASSERT_HWND_IS_DOCKBAR( hWndInsertAfter, AFX_IDW_DOCKBAR_TOP, (nOwnCircleNo+1) );
//		// get dockbar in next circle (nOwnCircleNo+1) - bottom
//		hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//		ASSERT_HWND_IS_DOCKBAR( hWndInsertAfter, AFX_IDW_DOCKBAR_BOTTOM, (nOwnCircleNo+1) );
//		// get dockbar in next circle (nOwnCircleNo+1) - left
//		hWndInsertAfter = ::GetWindow( hWndInsertAfter, GW_HWNDNEXT );
//		ASSERT_HWND_IS_DOCKBAR( hWndInsertAfter, AFX_IDW_DOCKBAR_LEFT, (nOwnCircleNo+1) );
//	}
//	break; // case AFX_IDW_DOCKBAR_RIGHT
//#ifdef _DEBUG
//	default:
//		ASSERT( FALSE );
//		break;
//#endif // _DEBUG
//	} // switch( nOwnID )
//
//
//	ASSERT( hWndInsertAfter != NULL );
//	return hWndInsertAfter;
//}

CExtDockBar * CExtDockBar::_GetBarByCircleNo( UINT nCircleNo )
{
	ASSERT_VALID( this );
	if( nCircleNo == m_nCircleNo )
		return this;
	if( nCircleNo < m_nCircleNo )
	{
		ASSERT( m_nCircleNo > 0 );
		ASSERT( m_pDockBarOuter != NULL );
		return m_pDockBarOuter->_GetBarByCircleNo( nCircleNo );
	}

	if( m_pDockBarInner == NULL )
	{
#ifdef _DEBUG
		UINT nNewCircle =
#endif // _DEBUG
			_CreateInnerCircle();
		ASSERT( nNewCircle == (m_nCircleNo + 1) );
	}
	ASSERT( m_pDockBarInner != NULL );
	ASSERT( m_pDockBarInner->m_nCircleNo == (m_nCircleNo + 1) );
	return m_pDockBarInner->_GetBarByCircleNo( nCircleNo );
}

LRESULT CExtDockBar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	switch( message )
	{
	case WM_CREATE:
		EnableToolTips();
	break;
	case WM_DESTROY:
	case WM_NCDESTROY:
		if( m_pDockBarInner != NULL )
		{
			ASSERT( m_pDockBarInner->m_pDockBarOuter == this );
			m_pDockBarInner->m_pDockBarOuter = NULL;
			m_pDockBarInner = NULL;
		}
		if( m_pDockBarOuter != NULL )
		{
			ASSERT( m_pDockBarOuter->m_pDockBarInner == this );
			m_pDockBarOuter->m_pDockBarInner = NULL;
			m_pDockBarOuter = NULL;
		}
		break;
	} // switch( message )

	return CControlBar::WindowProc(message, wParam, lParam);
}

void CExtDockBar::_OptimizeCircles()
{
	ASSERT_VALID( this );

CFrameWnd * pFrame = GetParentFrame();
	ASSERT_VALID( pFrame );
	ASSERT( !pFrame->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)) );

	if( !m_bLockedOptimize )
		_OptimizeCircles( pFrame );
}

void CExtDockBar::_OptimizeCircles( CFrameWnd * pFrame )
{
	ASSERT_VALID( pFrame );

CExtDockBar * vCircle[4];

	vCircle[0] = (CExtDockBar*)pFrame->GetControlBar( AFX_IDW_DOCKBAR_TOP );
	ASSERT_VALID( vCircle[0] );
	ASSERT_KINDOF( CExtDockBar, vCircle[0] );
	ASSERT( vCircle[0]->_GetCircleNo() == 0 );
	vCircle[1] = (CExtDockBar*)pFrame->GetControlBar( AFX_IDW_DOCKBAR_BOTTOM );
	ASSERT_VALID( vCircle[1] );
	ASSERT_KINDOF( CExtDockBar, vCircle[1] );
	ASSERT( vCircle[1]->_GetCircleNo() == 0 );
	vCircle[2] = (CExtDockBar*)pFrame->GetControlBar( AFX_IDW_DOCKBAR_LEFT );
	ASSERT_VALID( vCircle[2] );
	ASSERT_KINDOF( CExtDockBar, vCircle[2] );
	ASSERT( vCircle[2]->_GetCircleNo() == 0 );
	vCircle[3] = (CExtDockBar*)pFrame->GetControlBar( AFX_IDW_DOCKBAR_RIGHT );
	ASSERT_VALID( vCircle[3] );
	ASSERT_KINDOF( CExtDockBar, vCircle[3] );
	ASSERT( vCircle[3]->_GetCircleNo() == 0 );

	if( vCircle[0]->_GetDockBarInner() == NULL )
		return;
	vCircle[0] = vCircle[0]->_GetDockBarInner();
	ASSERT( vCircle[0] != NULL );
	ASSERT_KINDOF( CExtDockBar, vCircle[0] );
	ASSERT( vCircle[0]->_GetCircleNo() == 1 );
	
	vCircle[1] = vCircle[1]->_GetDockBarInner();
	ASSERT( vCircle[1] != NULL );
	ASSERT_KINDOF( CExtDockBar, vCircle[1] );
	ASSERT( vCircle[1]->_GetCircleNo() == 1 );
	
	vCircle[2] = vCircle[2]->_GetDockBarInner();
	ASSERT( vCircle[2] != NULL );
	ASSERT_KINDOF( CExtDockBar, vCircle[2] );
	ASSERT( vCircle[2]->_GetCircleNo() == 1 );
	
	vCircle[3] = vCircle[3]->_GetDockBarInner();
	ASSERT( vCircle[3] != NULL );
	ASSERT_KINDOF( CExtDockBar, vCircle[3] );
	ASSERT( vCircle[3]->_GetCircleNo() == 1 );

//bool bCreateInnerCircle = true;

UINT nCircleShift = 0;
#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
bool bAutoHidersPassed = false;
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
	while( vCircle[0] != NULL )
	{
		ASSERT( vCircle[0] != NULL );
		ASSERT_KINDOF( CExtDockBar, vCircle[0] );
		ASSERT( vCircle[1] != NULL );
		ASSERT_KINDOF( CExtDockBar, vCircle[1] );
		ASSERT( vCircle[2] != NULL );
		ASSERT_KINDOF( CExtDockBar, vCircle[2] );
		ASSERT( vCircle[3] != NULL );
		ASSERT_KINDOF( CExtDockBar, vCircle[3] );

		ASSERT( vCircle[0]->m_nCircleNo == vCircle[1]->m_nCircleNo );
		ASSERT( vCircle[0]->m_nCircleNo == vCircle[2]->m_nCircleNo );
		ASSERT( vCircle[0]->m_nCircleNo == vCircle[3]->m_nCircleNo );

#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
		if( !bAutoHidersPassed )
		{
			bAutoHidersPassed = true;
			if( vCircle[0]->m_pWndAutoHideArea != NULL )
			{
				vCircle[0]->m_pWndAutoHideArea->AdjustOrder();
				vCircle[1]->m_pWndAutoHideArea->AdjustOrder();
				vCircle[2]->m_pWndAutoHideArea->AdjustOrder();
				vCircle[3]->m_pWndAutoHideArea->AdjustOrder();
			}
		}
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)

		if( nCircleShift != 0 )
		{
			ASSERT( vCircle[0]->m_nCircleNo > nCircleShift );
			vCircle[0]->m_nCircleNo -= nCircleShift;
			vCircle[1]->m_nCircleNo -= nCircleShift;
			vCircle[2]->m_nCircleNo -= nCircleShift;
			vCircle[3]->m_nCircleNo -= nCircleShift;
		}

		CExtDockBar * vCircleOptimize[4];
		
		vCircleOptimize[0] = vCircle[0];
		vCircleOptimize[1] = vCircle[1];
		vCircleOptimize[2] = vCircle[2];
		vCircleOptimize[3] = vCircle[3];

//		bool bLastCircle =
//			( vCircle[0]->_GetDockBarInner() != NULL ) ? true : false;

		vCircle[0] = vCircle[0]->_GetDockBarInner();
		vCircle[1] = vCircle[1]->_GetDockBarInner();
		vCircle[2] = vCircle[2]->_GetDockBarInner();
		vCircle[3] = vCircle[3]->_GetDockBarInner();

		if(		vCircleOptimize[0]->_CanBeSafeOptimized()
			&&	vCircleOptimize[1]->_CanBeSafeOptimized()
			&&	vCircleOptimize[2]->_CanBeSafeOptimized()
			&&	vCircleOptimize[3]->_CanBeSafeOptimized()
			)
		{
//			if( bLastCircle )
//			{
//				bCreateInnerCircle = false;
//				break;
//			}

#ifdef __DEBUG_LOCKING_OPTIMIZATION_ASSERTS__
			ASSERT( !vCircleOptimize[0]->m_bLockedOptimize );
			ASSERT( !vCircleOptimize[1]->m_bLockedOptimize );
			ASSERT( !vCircleOptimize[2]->m_bLockedOptimize );
			ASSERT( !vCircleOptimize[3]->m_bLockedOptimize );
#endif // __DEBUG_LOCKING_OPTIMIZATION_ASSERTS__
			
			vCircleOptimize[0]->_SafeOptimizeInnerOuterChain();
			vCircleOptimize[1]->_SafeOptimizeInnerOuterChain();
			vCircleOptimize[2]->_SafeOptimizeInnerOuterChain();
			vCircleOptimize[3]->_SafeOptimizeInnerOuterChain();
			
			nCircleShift++;
		}
		else
		{
#ifdef __DEBUG_LOCKING_OPTIMIZATION_ASSERTS__
			ASSERT( !vCircleOptimize[0]->m_bLockedOptimize );
			ASSERT( !vCircleOptimize[1]->m_bLockedOptimize );
			ASSERT( !vCircleOptimize[2]->m_bLockedOptimize );
			ASSERT( !vCircleOptimize[3]->m_bLockedOptimize );
#endif // __DEBUG_LOCKING_OPTIMIZATION_ASSERTS__
			
			vCircleOptimize[0]->OnDynamicLayoutOptimize();
			vCircleOptimize[1]->OnDynamicLayoutOptimize();
			vCircleOptimize[2]->OnDynamicLayoutOptimize();
			vCircleOptimize[3]->OnDynamicLayoutOptimize();
		}

	} // while( vCircle[0] != NULL )

//	if( bCreateInnerCircle )
//		_CreateInnerCircle( pFrame );

CArray < HWND, HWND > arrHwndsToDynOptimize;
bool bDeepOptimize = false;

POSITION pos = pFrame->m_listControlBars.GetHeadPosition();
	for( ; pos != NULL; )
	{
		CExtDynControlBar * pBar =
			DYNAMIC_DOWNCAST(
				CExtDynControlBar,
				((CObject *)(pFrame->m_listControlBars.GetNext(pos)))
				);
		if( pBar == NULL )
			continue;
		ASSERT( !pBar->IsFixedMode() );
		HWND hWnd = pBar->m_pWndDynDocker->GetSafeHwnd();
		if( hWnd == NULL
			|| ! ::IsWindow( hWnd )
			)
			continue;
		//if( !pBar->IsFloating() )
		{
			INT nDockedCount =
				pBar->m_pWndDynDocker->GetDockedCount();
			if( nDockedCount > 0 )
				continue;
			bDeepOptimize = true;
		} // if( !pBar->IsFloating() )

		arrHwndsToDynOptimize.Add( hWnd );
	}

	for( INT nHwndIdx = 0; nHwndIdx < arrHwndsToDynOptimize.GetSize(); nHwndIdx++ )
	{
		HWND hWnd = arrHwndsToDynOptimize[ nHwndIdx ];
		ASSERT( hWnd != NULL );
		if( !::IsWindow( hWnd ) )
			continue;
		CWnd * pWndChild = CWnd::FromHandlePermanent( hWnd );
		if( pWndChild == NULL )
			continue;
		CExtDockDynBar * pDockBar =
			DYNAMIC_DOWNCAST(
				CExtDockDynBar,
				pWndChild
				);
		if( pDockBar == NULL )
			continue;
#ifdef __DEBUG_LOCKING_OPTIMIZATION_ASSERTS__
		ASSERT( !pDockBar->m_bLockedOptimize );
#endif // __DEBUG_LOCKING_OPTIMIZATION_ASSERTS__
		pDockBar->OnDynamicLayoutOptimize();
	}

	if( bDeepOptimize )
		_OptimizeCircles( pFrame );
}

void CExtDockBar::_SafeOptimizeInnerOuterChain()
{
	ASSERT( this != NULL );
	ASSERT_KINDOF( CExtDockBar, this );
	ASSERT( GetSafeHwnd() != NULL );
	ASSERT( ::IsWindow(GetSafeHwnd()) );

	if( m_pDockBarInner != NULL )
	{
		ASSERT( m_pDockBarInner->m_pDockBarOuter == this );
		m_pDockBarInner->m_pDockBarOuter = m_pDockBarOuter;
	}
	if( m_pDockBarOuter != NULL )
	{
		ASSERT( m_pDockBarOuter->m_pDockBarInner == this );
		m_pDockBarOuter->m_pDockBarInner = m_pDockBarInner;
	}
	m_pDockBarInner = NULL;
	m_pDockBarOuter = NULL;

CFrameWnd * pFrame = GetParentFrame();
	ASSERT( pFrame != NULL );
	ASSERT( !pFrame->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)) );

POSITION pos = pFrame->m_listControlBars.Find( this );
	ASSERT( pos != NULL );
	pFrame->m_listControlBars.RemoveAt( pos );

BOOL bAutoDelete = m_bAutoDelete;
	DestroyWindow();
	if( !bAutoDelete )
		delete this;
}

bool CExtDockBar::_CanBeSafeOptimized()
{
	ASSERT( this != NULL );
	ASSERT_KINDOF( CExtDockBar, this );
	for( INT nPos = 0; nPos < m_arrBars.GetSize(); nPos++ )
	{
		void * pBar = m_arrBars[ nPos ];
		if( pBar != NULL ) // placeholer or child control bar
			return false;
	}
	return true;
}

#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
CExtDynAutoHideArea * CExtDockBar::_GetAutoHideArea()
{
	return m_pWndAutoHideArea;
}
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)

void CExtDockBar::_HandleDestruction()
{
	m_bLockedOptimize = true;
bool bFirstDestroyed = true;
	for( int nBar = m_arrBars.GetSize() - 1; nBar > 0 ; nBar-- )
	{
		ASSERT( m_arrBars[0] == NULL );
		CExtControlBar * pBar = (CExtControlBar *)
			m_arrBars[ nBar ];
		if( bFirstDestroyed )
		{
			ASSERT( pBar == NULL );
			bFirstDestroyed = false;
			continue;
		}
		if( pBar == NULL )
		{
			m_arrBars.RemoveAt( nBar );
			continue;
		}
		if( __PLACEHODLER_BAR_PTR(pBar) )
		{
			m_arrBars.RemoveAt( nBar );
			continue;
		}
		ASSERT_VALID( pBar );
		ASSERT_KINDOF( CExtControlBar, pBar );
		ASSERT_VALID( pBar->m_pDockSite );
		ASSERT( pBar->m_pDockContext != NULL );
		ASSERT( pBar->m_pDockBar == this );
		pBar->m_bUpdatingChain = true;
		pBar->m_pDockBar = NULL;
		if( pBar->IsKindOf(RUNTIME_CLASS(CExtDynControlBar)) )
		{
			CExtDockDynBar * pDynDocker =
				((CExtDynControlBar*)pBar)->m_pWndDynDocker;
			ASSERT_VALID( pDynDocker );
			pDynDocker->_HandleDestruction();
		}
		ASSERT( pBar->m_bUpdatingChain );
		if( pBar->GetParent() != pBar->m_pDockSite )
			pBar->SetParent( pBar->m_pDockSite );
		pBar->m_bUpdatingChain = false;
		m_arrBars.RemoveAt( nBar );
	}
	m_bLockedOptimize = false;
}

void CExtDockBar::OnDestroy()
{
	_HandleDestruction();
	CDockBar::OnDestroy();
}

BOOL CExtDockBar::DestroyWindow()
{
	_HandleDestruction();
	return  CDockBar::DestroyWindow();
}

/////////////////////////////////////////////////////////////////////////
// CExtDockDynBar window

IMPLEMENT_DYNCREATE(CExtDockDynBar, CExtDockBar);

BEGIN_MESSAGE_MAP(CExtDockDynBar, CExtDockBar)
	//{{AFX_MSG_MAP(CExtDockDynBar)
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

CExtDockDynBar::CExtDockDynBar(
	UINT nCircleNo
	)
	: CExtDockBar( nCircleNo )
	, m_bHelperDockSiteModified( false )
{
	m_bAutoDelete = TRUE;
}

/////////////////////////////////////////////////////////////////////////
// CExtDynControlBar window

#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
CExtDynAutoHideArea * CExtDockDynBar::_GetAutoHideArea()
{
CExtControlBar * pExtBar = 
		STATIC_DOWNCAST(
			CExtControlBar,
			GetParent()
			);
	ASSERT( pExtBar->m_pDockBar != NULL );
CExtDockBar * pDockBar =
		DYNAMIC_DOWNCAST(
			CExtDockBar,
			pExtBar->m_pDockBar
			);
	if( pDockBar == NULL )
		return NULL;
	return pDockBar->_GetAutoHideArea();
}
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)

void CExtDockDynBar::VisibleLayoutItem_t::_AssignFromOther(
	const CExtDockDynBar::VisibleLayoutItem_t & other
	)
{
	m_vRow.RemoveAll();
INT nSize = other.m_vRow.GetSize();
	if( nSize == 0 )
	{
		m_vRow.FreeExtra();
		return;
	}
	m_vRow.SetSize( nSize );
	for( INT nBar = 0; nBar < nSize; nBar++ )
	{
		CExtControlBar * pExtBar = other.m_vRow[ nBar ];
		ASSERT( pExtBar != NULL );
		ASSERT( !pExtBar->IsFixedMode() );
#ifdef _DEBUG
		if( __PLACEHODLER_BAR_PTR(pExtBar) )
		{
			ASSERT( FALSE );
		}
#endif // _DEBUG
		m_vRow.SetAt( nBar, pExtBar );
	} // for( INT nBar = 0; nBar < nSize; nBar++ )
}

CExtDockDynBar::VisibleLayoutItem_t::VisibleLayoutItem_t()
	: m_nRowMetric( 0 )
	, m_nRowMinMetric( 0 )
	, m_nRowExtent( 0 )
	, m_nRowMinExtent( 0 )
{
}

CExtDockDynBar::VisibleLayoutItem_t::VisibleLayoutItem_t(
	const CExtDockDynBar::VisibleLayoutItem_t & other
	)
{
	_AssignFromOther( other );
}

CExtDockDynBar::VisibleLayoutItem_t::~VisibleLayoutItem_t()
{
}

CExtDockDynBar::VisibleLayoutItem_t &
	CExtDockDynBar::VisibleLayoutItem_t::operator=(
		const CExtDockDynBar::VisibleLayoutItem_t & other
		)
{
	_AssignFromOther( other );
	return * this;
}

bool CExtDockDynBar::VisibleLayoutItem_t::IsEmpty() const
{
	if( m_vRow.GetSize() == 0 )
		return true;
	return false;
}

bool CExtDockDynBar::VisibleLayoutItem_t::IsRowMinSized() const
{
	ASSERT( m_nRowMetric >= m_nRowMinMetric );
	return (m_nRowMetric == m_nRowMinMetric ) ? true : false;
}


void CExtDockDynBar::VisibleLayout_t::_Clean()
{
INT nSize = m_vRows.GetSize();
	for( INT nRow = 0; nRow < nSize; nRow++ )
	{
		VisibleLayoutItem_t * pVLI = m_vRows.GetAt( nRow );
		ASSERT( pVLI != NULL );
		delete pVLI;
	}
	m_vRows.RemoveAll();
	m_vRows.FreeExtra();
}

CExtDockDynBar::VisibleLayout_t::VisibleLayout_t()
	: m_nTotalMetric( 0 )
	, m_nTotalMinMetric( 0 )
	, m_nTotalMinExtent( 0 )
	, m_nTotalBarsCount( 0 )
{
}

CExtDockDynBar::VisibleLayout_t::~VisibleLayout_t()
{
	_Clean();
}

void CExtDockDynBar::VisibleLayout_t::AddBarPointer(
	CExtControlBar * pExtBar
	)
{
	ASSERT_VALID( pExtBar );
	ASSERT( !pExtBar->IsFixedMode() );
	if( !pExtBar->IsVisible() )
		return;
#ifdef _DEBUG
		if( __PLACEHODLER_BAR_PTR(pExtBar) )
		{
			ASSERT( FALSE );
		}
#endif // _DEBUG

VisibleLayoutItem_t * pVLI = NULL;
INT nRowCount = m_vRows.GetSize();
	if( nRowCount == 0 )
	{
		pVLI = new VisibleLayoutItem_t;
		m_vRows.Add( pVLI );
	}
	else
		pVLI = m_vRows[ nRowCount - 1 ];
	ASSERT( pVLI != NULL );
	pVLI->m_vRow.Add( pExtBar );

	m_nTotalBarsCount++;
}

void CExtDockDynBar::VisibleLayout_t::MakeNewRow()
{
INT nRowCount = m_vRows.GetSize();
	if( nRowCount == 0 )
	{
		VisibleLayoutItem_t * pVLI = new VisibleLayoutItem_t;
		m_vRows.Add( pVLI );
		return;
	}
VisibleLayoutItem_t * pVLI = m_vRows.GetAt( nRowCount - 1 );
	ASSERT( pVLI != NULL );
	if( pVLI->IsEmpty() )
		return;
	pVLI = new VisibleLayoutItem_t;
	m_vRows.Add( pVLI );
}

bool CExtDockDynBar::VisibleLayout_t::IsEmpty() const
{
INT nRowCount = m_vRows.GetSize();
	if( nRowCount == 0 )
		return true;
	if( nRowCount == 1 )
	{
		VisibleLayoutItem_t * pVLI = m_vRows.GetAt( 0 );
		if( pVLI->IsEmpty() )
			return true;
	}
#ifdef _DEBUG
	else
	{
		VisibleLayoutItem_t * pVLI = m_vRows.GetAt( 0 );
		ASSERT( !pVLI->IsEmpty() );
		
	}
#endif // _DEBUG
	return false;
}

void CExtDockDynBar::_VisibleLayoutBuild(
	VisibleLayout_t & _vl
	)
{
	ASSERT_VALID( this );

	ASSERT( _vl.IsEmpty() );

INT nCount = m_arrBars.GetSize();
	ASSERT( nCount > 0 );
	ASSERT( m_arrBars[0] == NULL );

UINT nOwnID = GetDlgCtrlID();
	ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nOwnID );
BOOL bHorz = ( nOwnID == AFX_IDW_DOCKBAR_TOP || nOwnID == AFX_IDW_DOCKBAR_BOTTOM );

	ASSERT( m_arrBars[0] == NULL );

	for( INT nBar = 1; nBar < nCount; nBar++ )
	{
		CExtControlBar * pExtBar = (CExtControlBar *) m_arrBars[nBar];
		if( pExtBar == NULL )
		{
			if( nBar == (nCount-1) )
				break;
			_vl.MakeNewRow();
			continue;
		}
		if( __PLACEHODLER_BAR_PTR(pExtBar) )
			continue;
		ASSERT_VALID( pExtBar );
		ASSERT_KINDOF( CExtControlBar, pExtBar );
		ASSERT( !pExtBar->IsFixedMode() );
		if( !pExtBar->IsVisible() )
			continue;
		_vl.AddBarPointer( pExtBar );
	} // for( INT nBar = 1; nBar < nCount; nBar++ )

INT nRowsCount = _vl.m_vRows.GetSize();
	if( nRowsCount == 0 )
		return;
	for( INT nRow = 0; nRow < nRowsCount; nRow ++ )
	{
		VisibleLayoutItem_t * pVLI = _vl.m_vRows[ nRow ];
		ASSERT( pVLI != NULL );
		INT nRowSize = pVLI->m_vRow.GetSize();
		// TO FIX:
		if( nRowSize == 0 )
			continue;
		ASSERT( nRowSize > 0 );
		CExtControlBar * pExtBar = pVLI->m_vRow[ 0 ];
		ASSERT( pExtBar != NULL );
		
		LONG nMinHW = pExtBar->_CalcDesiredMinHW();
		LONG nMinVH = pExtBar->_CalcDesiredMinVH();
		pVLI->m_nRowMinMetric = bHorz
			? nMinVH
			: nMinHW;
		pVLI->m_nRowMetric = bHorz
			? pExtBar->m_sizeDockedH.cy
			: pExtBar->m_sizeDockedV.cx;
		_vl.m_nTotalMetric += pVLI->m_nRowMetric;

		INT nRowMinMetric = bHorz
			? nMinVH
			: nMinHW;

		INT nRowMinExtent = bHorz
			? nMinHW
			: nMinVH;
		INT nRowExtent = bHorz
			? pExtBar->m_sizeDockedH.cx
			: pExtBar->m_sizeDockedV.cy;
		
		for( nBar = 1; nBar < nRowSize; nBar++ )
		{
			pExtBar = pVLI->m_vRow[ nBar ];
			ASSERT( pExtBar != NULL );
			LONG nMinHW = pExtBar->_CalcDesiredMinHW();
			LONG nMinVH = pExtBar->_CalcDesiredMinVH();
			INT nBarMinMetric = bHorz
				? nMinVH
				: nMinHW;
			nRowMinMetric =
				min( nRowMinMetric, nBarMinMetric );
			nRowMinExtent += bHorz
				? nMinHW
				: nMinVH;
			nRowExtent += bHorz
				? pExtBar->m_sizeDockedH.cx
				: pExtBar->m_sizeDockedV.cy;
		}

		_vl.m_nTotalMinMetric += nRowMinMetric;
		_vl.m_nTotalMinExtent = max( nRowMinExtent, _vl.m_nTotalMinExtent );
		pVLI->m_nRowExtent = nRowExtent;
	} // for( INT nRow = 0; nRow < nRowsCount; nRow ++ )

}

void CExtDockDynBar::_VisibleLayoutAlign(
	VisibleLayout_t & _vl,
	CSize _size
	)
{
	ASSERT_VALID( this );

	ASSERT( !_vl.IsEmpty() );
	ASSERT( _size.cx > 0 && _size.cy > 0 );

CRect rcDockBarReal;
	GetClientRect( &rcDockBarReal );
	_size = rcDockBarReal.Size();
	if( _size.cx <= 0 || _size.cy <= 0 )
		return;

UINT nOwnID = GetDlgCtrlID();
	ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nOwnID );
BOOL bHorz = ( nOwnID == AFX_IDW_DOCKBAR_TOP || nOwnID == AFX_IDW_DOCKBAR_BOTTOM );

INT nRowsCount = _vl.m_vRows.GetSize();
	ASSERT( nRowsCount > 0 );

INT nDesiredMetric = bHorz ? _size.cy : _size.cx;
INT nIncrement = (_vl.m_nTotalMetric < nDesiredMetric) ? 1 : -1;
INT nDiff = abs(_vl.m_nTotalMetric - nDesiredMetric);

	// align direction 1 (row metrics)
bool bResetRowMetrics = true;
	while( nDiff != 0 )
	{
		bResetRowMetrics = false;
		ASSERT( nDiff >= 0 );
		INT nRowsMinSized = 0;
		for( INT nRow = 0; nRow < nRowsCount; nRow ++ )
		{
			VisibleLayoutItem_t * pVLI = _vl.m_vRows[ nRow ];
			ASSERT( pVLI != NULL );
			//ASSERT( !pVLI->IsEmpty() );
			INT nRowSize = pVLI->m_vRow.GetSize();
			// TO FIX:
			if( nRowSize == 0 )
				continue;
			ASSERT( nRowSize > 0 );

			if( nIncrement < 0 && pVLI->IsRowMinSized() )
			{
				nRowsMinSized ++;
				if( nRowsCount == nRowsMinSized )
					break;
				continue;
			}
			pVLI->m_nRowMetric += nIncrement;
			nDiff--;

			for( INT nBar = 0; nBar < nRowSize; nBar++ )
			{
				CExtControlBar * pExtBar = pVLI->m_vRow[ nBar ];
				ASSERT( pExtBar != NULL );
				LONG & nRowMetricRef = bHorz
					? pExtBar->m_sizeDockedH.cy
					: pExtBar->m_sizeDockedV.cx;
				nRowMetricRef += nIncrement;
			} // for( INT nBar = 0; nBar < nRowSize; nBar++ )

			if( nDiff == 0 )
				break;
		} // for( INT nRow = 0; nRow < nRowsCount; nRow ++ )
		if( nRowsCount == nRowsMinSized )
			break;
	} // while( nDiff != 0 )
	if( bResetRowMetrics )
	{
		for( INT nRow = 0; nRow < nRowsCount; nRow ++ )
		{
			VisibleLayoutItem_t * pVLI = _vl.m_vRows[ nRow ];
			ASSERT( pVLI != NULL );
			//ASSERT( !pVLI->IsEmpty() );
			INT nRowSize = pVLI->m_vRow.GetSize();
			// TO FIX:
			if( nRowSize == 0 )
				continue;
			ASSERT( nRowSize > 0 );
			for( INT nBar = 0; nBar < nRowSize; nBar++ )
			{
				CExtControlBar * pExtBar = pVLI->m_vRow[ nBar ];
				ASSERT( pExtBar != NULL );
				LONG & nRowMetricRef = bHorz
					? pExtBar->m_sizeDockedH.cy
					: pExtBar->m_sizeDockedV.cx;
				nRowMetricRef = pVLI->m_nRowMetric;
			} // for( INT nBar = 0; nBar < nRowSize; nBar++ )
		} // for( INT nRow = 0; nRow < nRowsCount; nRow ++ )
	} // if( bResetRowMetrics )

	// align direction 2 (row extents)
	nDesiredMetric = bHorz ? _size.cx : _size.cy;
	for( INT nRow = 0; nRow < nRowsCount; nRow ++ )
	{
		VisibleLayoutItem_t * pVLI = _vl.m_vRows[ nRow ];
		ASSERT( pVLI != NULL );
		//ASSERT( !pVLI->IsEmpty() );
		// TO FIX:
		if( pVLI->IsEmpty() )
			continue;

		INT nIncrement =
			(pVLI->m_nRowExtent < nDesiredMetric) ? 1 : -1;
		INT nDiff = abs( pVLI->m_nRowExtent - nDesiredMetric );

		while( nDiff != 0 )
		{
			ASSERT( nDiff >= 0 );
			INT nRowSize = pVLI->m_vRow.GetSize();
			// TO FIX:
			if( nRowSize == 0 )
				continue;
			ASSERT( nRowSize > 0 );
			INT nBarsMinSized = 0;
			for( INT nBar = 0; nBar < nRowSize; nBar++ )
			{
				CExtControlBar * pExtBar = pVLI->m_vRow[ nBar ];
				ASSERT( pExtBar != NULL );
				LONG & nBarMetricRef = bHorz
					? pExtBar->m_sizeDockedH.cx
					: pExtBar->m_sizeDockedV.cy;

				if( nIncrement < 0 )
				{
					LONG nBarMinMetric = bHorz
						? pExtBar->_CalcDesiredMinHW()
						: pExtBar->_CalcDesiredMinVH();
					ASSERT( nBarMetricRef >= nBarMinMetric );
					if( nBarMetricRef <= nBarMinMetric )
					{
						nBarsMinSized ++;
						if( nBarsMinSized == nRowSize )
							break;
						continue;
					}
				} // if( nIncrement < 0 )

				nBarMetricRef += nIncrement;
				nDiff --;
				if( nDiff == 0 )
					break;
			} // for( INT nBar = 0; nBar < nRowSize; nBar++ )
			if( nBarsMinSized == nRowSize )
				break;
		} // while( nDiff != 0 )
	} // for( INT nRow = 0; nRow < nRowsCount; nRow ++ )

	ASSERT( _vl.m_nTotalBarsCount > 0 );
HANDLE hDWP = ::BeginDeferWindowPos( _vl.m_nTotalBarsCount );
	ASSERT( hDWP != NULL );
	
	// apply new layout
CPoint ptOffs( 0, 0 );	
	for( nRow = 0; nRow < nRowsCount; nRow ++ )
	{
		VisibleLayoutItem_t * pVLI = _vl.m_vRows[ nRow ];
		ASSERT( pVLI != NULL );
		//ASSERT( !pVLI->IsEmpty() );
		INT nRowSize = pVLI->m_vRow.GetSize();
		// TO FIX:
		if( nRowSize == 0 )
			continue;
		ASSERT( nRowSize > 0 );

		INT nRowOffset = 0;
		for( INT nBar = 0; nBar < nRowSize; nBar++ )
		{
			CExtControlBar * pExtBar = pVLI->m_vRow[ nBar ];
			ASSERT( pExtBar != NULL );

			if( nBar == 0 )
				nRowOffset = bHorz
					? pExtBar->m_sizeDockedH.cy
					: pExtBar->m_sizeDockedV.cx;

			CRect rcBar(
				ptOffs,
				bHorz
					? pExtBar->m_sizeDockedH
					: pExtBar->m_sizeDockedV
				);
		
			if( hDWP != NULL )
			{
				hDWP =
					::DeferWindowPos(
						hDWP,
						pExtBar->GetSafeHwnd(),
						NULL,
						rcBar.left, rcBar.top,
						rcBar.Width(), rcBar.Height(),
						SWP_NOZORDER|SWP_NOACTIVATE
						);
				ASSERT( hDWP != NULL );
			}
			if( hDWP == NULL )
				pExtBar->MoveWindow( &rcBar );

			if( bHorz )
				ptOffs.x += pExtBar->m_sizeDockedH.cx;
			else
				ptOffs.y += pExtBar->m_sizeDockedV.cy;

		} // for( INT nBar = 0; nBar < nRowSize; nBar++ )

		if( bHorz )
		{
			ptOffs.x = 0;
			ptOffs.y += nRowOffset;
		}
		else
		{
			ptOffs.x += nRowOffset;
			ptOffs.y = 0;
		}
	} // for( nRow = 0; nRow < nRowsCount; nRow ++ )

	ASSERT( hDWP != NULL );
	if( hDWP != NULL )
		::EndDeferWindowPos( hDWP );
}

IMPLEMENT_DYNCREATE(CExtDynControlBar, CExtControlBar);

BEGIN_MESSAGE_MAP(CExtDynControlBar, CExtControlBar)
	//{{AFX_MSG_MAP(CExtDynControlBar)
	ON_WM_CREATE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

CExtDynControlBar::CExtDynControlBar()
	: m_pWndDynDocker( NULL )
{
	m_bAppearInDockSiteControlBarPopupMenu = false;
	m_bAutoDelete = TRUE;
}

CExtDockDynBar * CExtDynControlBar::OnCreateDynamicDockBarObject()
{
	return ( new CExtDockDynBar( 0 ) );
}

int CExtDynControlBar::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if( CExtControlBar::OnCreate(lpCreateStruct) == -1 )
	{
		ASSERT( FALSE );
		return -1;
	}

UINT nOwnID = GetDlgCtrlID();

#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
	if( IsKindOf( RUNTIME_CLASS(CExtDynTabControlBar) )
		&& nOwnID == AFX_IDW_DOCKBAR_FLOAT
		)
	{
		nOwnID = AFX_IDW_DOCKBAR_TOP;
		SetDlgCtrlID( nOwnID );
	}
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)

	ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nOwnID );

	ASSERT( m_pWndDynDocker == NULL );
	m_pWndDynDocker = OnCreateDynamicDockBarObject();
	ASSERT( m_pWndDynDocker != NULL );
	
CFrameWnd * pParentFrame =
		STATIC_DOWNCAST( CFrameWnd, GetParent() );
	ASSERT_VALID( pParentFrame );
	if( !m_pWndDynDocker->Create(
			pParentFrame,
			WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN
				|CBRS_ALIGN_TOP //|CBRS_ALIGN_ANY
				|CBRS_BORDER_ANY
				,
			nOwnID
			)
		)
	{
		ASSERT( FALSE );
		return -1;
	}
	m_pWndDynDocker->SetParent( this );
	EnableToolTips();
	return 0;
}

bool CExtDynControlBar::IsBarWithGripper(
	bool * pbGripperAtTop, // = NULL
	bool * pbTextOnGripper // = NULL
	) const
{
	ASSERT_VALID( this );
	if( pbGripperAtTop != NULL )
		*pbGripperAtTop = false;
	if( pbTextOnGripper != NULL )
		*pbTextOnGripper = false;
	return false;
}

bool CExtDynControlBar::_CanDockToTabbedContainers(
	CExtControlBar * pDestBar
	) const
{
	ASSERT_VALID( this );
	if( !CExtControlBar::_CanDockToTabbedContainers(pDestBar) )
		return false;
	if( m_pWndDynDocker == NULL )
		return false;
	for( int i = 0; i < m_pWndDynDocker->m_arrBars.GetSize(); i++ )
	{
		CExtControlBar * pBar = (CExtControlBar *)
			m_pWndDynDocker->m_arrBars[i];
		if( pBar == NULL )
			continue;
		if( __PLACEHODLER_BAR_PTR(pBar) )
			continue;
		ASSERT_VALID( pBar );
		ASSERT_KINDOF( CExtControlBar, pBar );
		if( !pBar->_CanDockToTabbedContainers(pDestBar) )
			return false;
	} // for( int i = 0; i < m_pWndDynDocker->m_arrBars.GetSize(); i++ )
	return true;
}

#if (!defined __EXT_MFC_NO_TAB_CONTROLBARS)
CExtDynTabControlBar * CExtDynControlBar::_GetNearestTabbedContainer()
{
	ASSERT_VALID( this );
	return CExtControlBar::_GetNearestTabbedContainer();
}
#endif // (!defined __EXT_MFC_NO_TAB_CONTROLBARS)

CSize CExtDynControlBar::_CalcLayoutMinSize() const
{
	ASSERT_VALID( this );
CExtDockDynBar * pDockBar = 
		STATIC_DOWNCAST( CExtDockDynBar, GetWindow(GW_CHILD) );
	ASSERT_VALID( pDockBar );
	ASSERT_KINDOF( CExtDockDynBar, pDockBar );
CExtDockDynBar::VisibleLayout_t _vl;
	pDockBar->_VisibleLayoutBuild( _vl );
UINT nDockBarID = pDockBar->GetDlgCtrlID();
	ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nDockBarID );
BOOL bHorz = ( nDockBarID == AFX_IDW_DOCKBAR_TOP || nDockBarID == AFX_IDW_DOCKBAR_BOTTOM );
CSize _size(
		bHorz ? _vl.m_nTotalMinMetric : _vl.m_nTotalMinExtent,
		bHorz ? _vl.m_nTotalMinExtent : _vl.m_nTotalMinExtent
		);
	return _size;
}

INT CExtDynControlBar::_CalcDesiredMinHW() const
{
	return _CalcLayoutMinSize().cx;
}

INT CExtDynControlBar::_CalcDesiredMinVH() const
{
	return _CalcLayoutMinSize().cy;
}

CSize CExtDynControlBar::_CalcDesiredMinFloatedSize() const
{
	return _CalcLayoutMinSize();
}

CSize CExtDynControlBar::CalcDynamicLayout(
	int nLength,
	DWORD nMode
	)
{
CSize _size = CExtControlBar::CalcDynamicLayout( nLength, nMode );

	if( m_pDockBar == NULL ) // (+ v.2.23) - shutdown mode
		return _size;

	ASSERT_VALID( m_pDockBar );
	if( ((CExtDockBar *)m_pDockBar)->m_bLayoutQuery )
		return _size;

	if( m_pWndDynDocker->GetSafeHwnd() == NULL )
		return _size;

INT nDockedVisibleCount = m_pWndDynDocker->GetDockedVisibleCount();
	if( nDockedVisibleCount == 0 )
	{
		m_pDockSite->ShowControlBar( this, FALSE, FALSE );
		_size.cx = _size.cy = 0;
	}

CFrameWnd * pParentFrame = GetParentFrame();
	if(	pParentFrame->IsKindOf( RUNTIME_CLASS( CMiniFrameWnd ) ) )
	{
		ASSERT_VALID( m_pWndDynDocker );
		ASSERT( ::IsWindow( m_pWndDynDocker->GetSafeHwnd() ) );
//!!//
//		m_pWndDynDocker->OnDynamicLayoutUpdate();
//		pParentFrame->SetWindowPos(
//			NULL, 0, 0, 0, 0,
//			SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE
//				|SWP_FRAMECHANGED
//			);
//		pParentFrame->SendMessage( WM_NCPAINT );

		ASSERT_VALID( m_pDockBar );
		if(	( ! m_pWndDynDocker->m_bLockedOptimize )
			&& pParentFrame == m_pDockBar->GetParent()
			)
			m_pWndDynDocker->OnDynamicLayoutUpdate();

	} // if( ....
	
	return _size;
}

void CExtDockDynBar::OnDynamicLayoutUpdate()
{
	ASSERT_VALID( this );
	ASSERT_KINDOF( CExtDockDynBar, this );

	if( m_bLockedOptimize )
		return;

	if( m_bInDynamicLayoutUpdate )
		return;
	m_bInDynamicLayoutUpdate = true;

UINT nDockBarID = GetDlgCtrlID();
	ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nDockBarID );
BOOL bHorz = ( nDockBarID == AFX_IDW_DOCKBAR_TOP || nDockBarID == AFX_IDW_DOCKBAR_BOTTOM );
	
	CalcFixedLayout( TRUE, bHorz );

	m_bInDynamicLayoutUpdate = false;

	CExtDockBar::OnDynamicLayoutUpdate();
}

void CExtDockDynBar::OnDynamicLayoutOptimize()
{
	ASSERT_VALID( this );
	ASSERT_VALID( m_pDockSite );

	if( m_bLockedOptimize )
	{
#ifdef _DEBUG
	#ifdef __DEBUG_LOCKING_OPTIMIZATION_ASSERTS__
		INT nDockedCount = GetDockedCount();
		ASSERT( nDockedCount != 0 );
	#endif // __DEBUG_LOCKING_OPTIMIZATION_ASSERTS__
#endif // _DEBUG
		return;
	}

bool bOptimizeChilds = false;
INT nSinglePos = -1;
bool bPlaceHolder = false;
	ASSERT( m_arrBars.GetSize() >= 1 );

INT nDockedCount = GetDockedCount();
	if( nDockedCount != 0 )
	{
		ASSERT( nDockedCount >= 1 );
		for( INT nBar = 1; nBar < m_arrBars.GetSize(); nBar++ )
		{
			CControlBar * pBar = (CControlBar *)m_arrBars[ nBar ];
			if( pBar == NULL )
				continue;
			if( __PLACEHODLER_BAR_PTR(pBar) )
			{
				if( nSinglePos >= 0 && !bPlaceHolder )
				{
					bOptimizeChilds = true;
					break;
				}
				nSinglePos = nBar;
				bPlaceHolder = true;
				continue;
			}
			else
			{
				ASSERT_VALID( pBar );
				ASSERT_KINDOF( CControlBar, pBar );
				if( nSinglePos >= 0 )
				{
					bOptimizeChilds = true;
					break;
				}
				nSinglePos = nBar;
			}
		} // for( INT nBar = 1; nBar < m_arrBars.GetSize(); nBar++ )
	} // if( nDockedCount != 0 )
	
	if( bOptimizeChilds )
	{
		CExtDockBar::OnDynamicLayoutOptimize();
		return;
	}

CFrameWnd * pDockSite = m_pDockSite;
CMiniFrameWnd * pMiniFrame =
		DYNAMIC_DOWNCAST(
			CMiniFrameWnd,
			GetParentFrame()
			);
	if( pMiniFrame != NULL )
		pMiniFrame->DelayRecalcLayout();

CExtDynControlBar * pDynBar =
		STATIC_DOWNCAST( CExtDynControlBar, GetParent() );
	ASSERT_VALID( pDynBar );
	ASSERT( pDockSite == pDynBar->m_pDockSite );

CDockBar * pDockBarParent = 
		STATIC_DOWNCAST( CDockBar, pDynBar->GetParent() );
	ASSERT_VALID( pDockBarParent );
	ASSERT( pDockSite == pDockBarParent->m_pDockSite );

HWND hWndOwn = GetSafeHwnd();

	if( nSinglePos == -1 )
	{ // optimizing empty dynamic docker
//		AfxMessageBox( "Optimizing empty dynamic docker!" );

		pDynBar->m_pDockBar = NULL;
//		pDockSite->RemoveControlBar( pDynBar );
		pDockSite->RemoveControlBar( this );

		ASSERT( pDynBar->m_bAutoDelete );
		HWND hWndDynBar = pDynBar->GetSafeHwnd();
		pDockBarParent->RemoveControlBar( pDynBar );
		if( ::IsWindow(hWndDynBar) )
			pDynBar->DestroyWindow();
		
		if( pMiniFrame == NULL )
			pDockSite->DelayRecalcLayout();
		ASSERT( pDockSite->m_listControlBars.Find(pDynBar) == NULL );

		if( ! (	::IsWindow(hWndOwn) ) )
			return;

		if( pDockBarParent->IsKindOf(RUNTIME_CLASS(CExtDockBar)) )
			((CExtDockBar *)pDockBarParent)->OnDynamicLayoutUpdate();
		return;
	} // optimizing empty dynamic docker

	if( bPlaceHolder )
	{ // optimizing placeholder dynamic docker
////		AfxMessageBox( "Optimizing placeholder dynamic docker!" );
		return;
	} // optimizing placeholder dynamic docker

	// optimizing singlebar dynamic docker
//	AfxMessageBox( "Optimizing singlebar dynamic docker!" );

CExtControlBar * pSingleBar = (CExtControlBar *)m_arrBars[ nSinglePos ];
	ASSERT_VALID( pSingleBar );
	ASSERT_KINDOF( CExtControlBar, pSingleBar );
	ASSERT( !pSingleBar->IsFixedMode() );
CRect wrSingleBar;
	pDynBar->GetWindowRect( &wrSingleBar );
CSize sizeSingleBar = wrSingleBar.Size();

INT nDynPos = pDockBarParent->FindBar( pDynBar );
	ASSERT( nDynPos > 0 );
	pDockBarParent->m_arrBars[ nDynPos ] = pSingleBar;
	pSingleBar->m_pDockBar = pDockBarParent;

	if( pSingleBar->IsKindOf(RUNTIME_CLASS(CExtControlBar))
		&& !((CExtControlBar*)pSingleBar)->IsFixedMode()
		)
	{
		if( pDockBarParent->GetBarStyle() & CBRS_ORIENT_HORZ )
			((CExtControlBar*)pSingleBar)->
				SetInitDesiredSizeHorizontal( sizeSingleBar );
		else
			((CExtControlBar*)pSingleBar)->
				SetInitDesiredSizeVertical( sizeSingleBar );
		DWORD dwStyle = pSingleBar->GetBarStyle();
		dwStyle &= ~(CBRS_ALIGN_ANY);
		dwStyle |=  (pDynBar->m_dwStyle & CBRS_ALIGN_ANY) | CBRS_BORDER_ANY;
		pSingleBar->SetBarStyle( dwStyle );
	}

	m_arrBars.RemoveAll();
	m_arrBars.Add( (CControlBar *)NULL );

	pSingleBar->SetParent( pDockBarParent );
	pSingleBar->m_pDockBar = pDockBarParent;

	pDynBar->m_pDockBar = NULL;
//	pDockSite->RemoveControlBar( pDynBar );
	pDockSite->RemoveControlBar( this );
	ASSERT( pDynBar->m_bAutoDelete );
	pDynBar->DestroyWindow();

/*
//	pSingleBar->m_bUpdatingChain = true;
	pDockBarParent->ScreenToClient( &wrSingleBar );
	pSingleBar->SetWindowPos(
		NULL,
		wrSingleBar.left, wrSingleBar.top,
		sizeSingleBar.cx, sizeSingleBar.cy,
		SWP_NOZORDER|SWP_NOOWNERZORDER
			|SWP_NOACTIVATE
			|SWP_FRAMECHANGED
			//|SWP_NOREDRAW
		);
//	pSingleBar->m_bUpdatingChain = false;
*/

	if( pMiniFrame == NULL )
		pDockSite->DelayRecalcLayout();
	ASSERT( pDockSite->m_listControlBars.Find(pDynBar) == NULL );

	if( pDockBarParent->IsKindOf(RUNTIME_CLASS(CExtDockBar)) )
		((CExtDockBar *)pDockBarParent)->OnDynamicLayoutUpdate();
}

CSize CExtDockDynBar::CalcFixedLayout(
	BOOL bStretch,
	BOOL bHorz
	)
{
	bHorz;

	ASSERT_VALID( this );
	ASSERT( !m_bFloating );

VisibleLayout_t _vl;
	_VisibleLayoutBuild( _vl );

CRect rect;
	GetWindowRect( &rect );
CSize _size = rect.Size();

	if( !_vl.IsEmpty()
		&& bStretch
		&& _size.cx > 0 && _size.cy > 0
		)
	{
		_VisibleLayoutAlign( _vl, _size );
	}

	return _size;
}

void CExtDockDynBar::CalcOrderedVector(
	ExtControlBarVector_t & vBars
	)
{
	ASSERT_VALID( this );

INT nCount = m_arrBars.GetSize();
	ASSERT( nCount > 0 );
	ASSERT( m_arrBars[0] == NULL );
	for( INT nBar = 1; nBar < nCount; nBar++ )
	{
		CExtControlBar * pBar = (CExtControlBar *) m_arrBars[nBar];
		if( pBar == NULL )
			continue;
		if( __PLACEHODLER_BAR_PTR( pBar ) )
			continue;
		ASSERT_VALID( pBar );
		ASSERT_KINDOF( CExtControlBar, pBar );
		ASSERT( !pBar->IsFixedMode() );
		vBars.Add( pBar );
	} // for( INT nBar = 1; nBar < nCount; nBar++ )
}

void CExtDockDynBar::OnSize(UINT nType, int cx, int cy) 
{
	CExtDockBar::OnSize(nType, cx, cy);
	
	if(		!m_bHelperDockSiteModified
		&&	m_pDockSite != NULL
		)
	{
		POSITION pos = m_pDockSite->m_listControlBars.Find( this );
		if( pos != NULL )
		{
			m_pDockSite->m_listControlBars.RemoveAt( pos );
			m_bHelperDockSiteModified = true;
		}
	}

/*
	if( nType == SIZE_MINIMIZED )
		return;
	if( cx <= 0 || cy <= 0 )
		return;

	OnDynamicLayoutUpdate();
*/

}

/////////////////////////////////////////////////////////////////////////
// CExtDockOuterBar::OuterLayoutItemData

void CExtDockOuterBar::OuterLayoutItemData::_AssignFromOther(
	const CExtDockOuterBar::OuterLayoutItemData & other
	)
{
	m_pBar = other.m_pBar;
	m_bVisible = other.m_bVisible;
	m_sizeCalcDynamic = other.m_sizeCalcDynamic;
	m_sizeBarMin = other.m_sizeBarMin;
	m_rcPreCalc = other.m_rcPreCalc;
	m_rcReal = other.m_rcReal;
}

CExtDockOuterBar::OuterLayoutItemData::OuterLayoutItemData()
	: m_pBar( NULL )
	, m_bVisible( false )
	, m_sizeCalcDynamic( 0, 0 )
	, m_sizeBarMin( 0, 0 )
	, m_rcPreCalc( 0, 0, 0, 0 )
	, m_rcReal( 0, 0, 0, 0 )
{
}

CExtDockOuterBar::OuterLayoutItemData::OuterLayoutItemData(
		CControlBar * pBar,
		BOOL bHorz,
		const SIZE & sizeMax
		)
	: m_pBar( pBar )
	, m_sizeCalcDynamic( 0, 0 )
	, m_sizeBarMin( 0, 0 )
	, m_rcPreCalc( 0, 0, 0, 0 )
	, m_rcReal( 0, 0, 0, 0 )
{
	ASSERT_VALID( m_pBar );
	ASSERT_KINDOF( CControlBar, pBar );
	m_bVisible = pBar->IsVisible() ? true : false;
//	if( m_bVisible
//		&& (pBar->m_nStateFlags & CControlBar::delayHide) != 0
//		)
//		m_bVisible = false;
//	if( (!m_bVisible)
//		&& (pBar->m_nStateFlags & CControlBar::delayShow) != 0
//		)
//		m_bVisible = true;
	if( !m_bVisible )
		return;

//	for _CalcFixedRowLayout
CRect rcBarWin, rcBarClient;
	pBar->GetWindowRect( &rcBarWin );
	pBar->ScreenToClient( & rcBarWin );
	pBar->GetClientRect( &rcBarClient );
	m_sizeBarMin = rcBarWin.Size() - rcBarClient.Size();
	if(	pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar)) )
	{
		m_sizeBarMin +=
			((CExtControlBar *)pBar)->
				_CalcDesiredMinOuterSize( bHorz );
	} // if(	pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar)) )

	// get ideal rect for bar
DWORD dwMode = 0;
	if(	(pBar->m_dwStyle & CBRS_SIZE_DYNAMIC)
		&&
		(pBar->m_dwStyle & CBRS_FLOATING)
		)
		dwMode |= LM_HORZ | LM_MRUWIDTH;
	else if(pBar->m_dwStyle & CBRS_ORIENT_HORZ)
		dwMode |= LM_HORZ | LM_HORZDOCK;
	else
		dwMode |=  LM_VERTDOCK;

	m_sizeCalcDynamic = pBar->CalcDynamicLayout(-1, dwMode);
	if(		pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar))
		&&	((CExtControlBar *)pBar)->_GetFullRowMode()
		)
	{
		if(dwMode & LM_HORZDOCK)
			m_sizeCalcDynamic.cx = sizeMax.cx;
		else if(dwMode & LM_VERTDOCK)
			m_sizeCalcDynamic.cy = sizeMax.cy;
	}
}

/////////////////////////////////////////////////////////////////////////
// CExtDockOuterBar window

IMPLEMENT_DYNCREATE(CExtDockOuterBar, CExtDockBar);

BEGIN_MESSAGE_MAP(CExtDockOuterBar, CExtDockBar)
	//{{AFX_MSG_MAP(CExtDockOuterBar)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
	ON_WM_SYSCOLORCHANGE()
	__EXT_MFC_SAFE_ON_WM_SETTINGCHANGE()
	ON_MESSAGE(WM_DISPLAYCHANGE, OnDisplayChange)
	ON_MESSAGE(__ExtMfc_WM_THEMECHANGED, OnThemeChanged)
END_MESSAGE_MAP()

CExtDockOuterBar::CExtDockOuterBar()
	: CExtDockBar( 0 )
	, m_bInDockSiteDelayedRecalc( false )
	, m_bDockSiteRecalcIsDelayed( false )
{
}

void CExtDockOuterBar::OnSysColorChange() 
{
	CExtDockBar::OnSysColorChange();
	g_PaintManager.OnSysColorChange( this );
	g_CmdManager.OnSysColorChange( this );
}

void CExtDockOuterBar::OnSettingChange(UINT uFlags, __EXT_MFC_SAFE_LPCTSTR lpszSection) 
{
	CExtDockBar::OnSettingChange( uFlags, lpszSection );
	g_PaintManager.OnSettingChange( this, uFlags, lpszSection );
	g_CmdManager.OnSettingChange( this, uFlags, lpszSection );
}

LRESULT CExtDockOuterBar::OnDisplayChange( WPARAM wParam, LPARAM lParam )
{
LRESULT lResult = CExtDockBar::OnDisplayChange( wParam, lParam );
	g_PaintManager.OnDisplayChange( this, (INT)wParam, CPoint(lParam) );
	g_CmdManager.OnDisplayChange( this, (INT)wParam, CPoint(lParam) );
	return lResult;
}

LRESULT CExtDockOuterBar::OnThemeChanged( WPARAM wParam, LPARAM lParam )
{
LRESULT lResult = Default();
	g_PaintManager.OnThemeChanged( this, wParam, lParam );
	g_CmdManager.OnThemeChanged( this, wParam, lParam );
	return lResult;
}

void CExtDockOuterBar::OnDynamicLayoutUpdate()
{
	CExtDockBar::OnDynamicLayoutUpdate();
}

void CExtDockOuterBar::OnDynamicLayoutOptimize()
{
	CExtDockBar::OnDynamicLayoutOptimize();
}

void CExtDockOuterBar::_DelayDockSiteRecalc()
{
	ASSERT_VALID( this );
	if( m_bDockSiteRecalcIsDelayed )
		return;
CExtDockOuterBar * pDocker = this;
	if( GetDlgCtrlID() != AFX_IDW_DOCKBAR_TOP )
	{
		CFrameWnd * pFrame = STATIC_DOWNCAST( CFrameWnd, GetParent() );
		ASSERT_VALID( pFrame );
		CControlBar * pTempBar = pFrame->GetControlBar( AFX_IDW_DOCKBAR_TOP );
		if( pTempBar == NULL )
			pTempBar = pFrame->GetControlBar( AFX_IDW_DOCKBAR_BOTTOM );
		if( pTempBar == NULL )
			pTempBar = pFrame->GetControlBar( AFX_IDW_DOCKBAR_LEFT );
		if( pTempBar == NULL )
			pTempBar = pFrame->GetControlBar( AFX_IDW_DOCKBAR_RIGHT );
		if( pTempBar != NULL )
			pDocker = STATIC_DOWNCAST( CExtDockOuterBar, pTempBar );
	} // if( GetDlgCtrlID() != AFX_IDW_DOCKBAR_TOP )
	pDocker->_DelayDockSiteRecalc_Start();
}

void CExtDockOuterBar::_DelayDockSiteRecalc_Start()
{
	ASSERT_VALID( this );
	if( m_bDockSiteRecalcIsDelayed )
		return;
	m_bDockSiteRecalcIsDelayed = true;
	if( _DelayDockSiteRecalc_Update() )
	{
		KillTimer( 901 );
		m_bDockSiteRecalcIsDelayed = false;
	}
	else
		SetTimer( 901, 1, NULL );
}

bool CExtDockOuterBar::_DelayDockSiteRecalc_Update()
{
	ASSERT_VALID( this );
	if( m_bInDockSiteDelayedRecalc )
		return false;
CExtControlBar::InternalFriendlyFrameWnd * pFrame =
		(CExtControlBar::InternalFriendlyFrameWnd *)
			STATIC_DOWNCAST( CFrameWnd, GetParent() );
	ASSERT_VALID( pFrame );
	if( pFrame->IsInRecalcLayout() )
		return false;
	m_bInDockSiteDelayedRecalc = true;
	pFrame->RecalcLayout();
	m_bInDockSiteDelayedRecalc = false;
	return true;
}

void CExtDockOuterBar::OnTimer(UINT nIDEvent) 
{
	if( nIDEvent == 901 )
	{
		if( _DelayDockSiteRecalc_Update() )
		{
			KillTimer( 901 );
			m_bDockSiteRecalcIsDelayed = false;
		}
		return;
	} // if( nIDEvent == 901 )
	CExtDockBar::OnTimer(nIDEvent);
}

void CExtDockOuterBar::_AffixmentBringToTop( CExtControlBar * pBar )
{
	ASSERT_VALID( this );
	ASSERT_VALID( pBar );
CExtControlBar::InternalAffixmentData * pAffixmentDataSrc =
		pBar->_AffixmentGetOuter();
	ASSERT( pAffixmentDataSrc != NULL );
	ASSERT( FindBar(pBar) >= 0 );
ExtControlBarVector_t vBars;
	pBar->_GetRowExtBars( vBars, false );
int nCount = vBars.GetSize();
	ASSERT( nCount > 0 );
	pAffixmentDataSrc->m_nAffixmentWeight = 1;
///	pAffixmentDataSrc->m_rcAffixment.SetRectEmpty();
	if( nCount == 1 )
		return;
int nResetWeight = m_arrBars.GetSize() * 4;
	for( int nBar = 0; nBar < nCount; )
	{
		CExtControlBar * pBar2 = vBars[nBar];
		ASSERT_VALID( pBar2 );
		if( pBar2 == pBar )
		{
			nBar++;
			continue;
		}
		CExtControlBar::InternalAffixmentData * pAffixmentData2 =
			pBar2->_AffixmentGetOuter();
		if( pAffixmentData2 == NULL )
		{
			vBars.RemoveAt(nBar);
			nCount--;
			continue;
		}
		if( pAffixmentData2->IsEmpty() )
			pAffixmentData2->m_nAffixmentWeight = nResetWeight++;
		else
			pAffixmentData2->m_nAffixmentWeight++;
		nBar++;
	} // for( int nBar = 0; nBar < nCount; )
	if( nCount <= 1 )
		return;
	// reset affixment weights
ExtControlBarVector_t vBars2;
	for( nBar = 0; nBar < nCount; nBar++ )
	{
		CExtControlBar * pBarX = vBars[nBar];
		int nCount2 = vBars2.GetSize();
		if( nCount2 == 0 )
		{
			vBars2.Add( pBarX );
			continue;
		}
		CExtControlBar::InternalAffixmentData * pAffixmentDataX =
			pBarX->_AffixmentGetOuter();
		ASSERT( pAffixmentDataX != NULL );
		int nWeightX = pAffixmentDataX->m_nAffixmentWeight;
		for( int nBar2 = 0; nBar2 < nCount2; nBar2++ )
		{
			CExtControlBar * pBar2 = vBars2[nBar2];
			ASSERT( pBar2 != pBarX );
			CExtControlBar::InternalAffixmentData * pAffixmentData2 =
				pBar2->_AffixmentGetOuter();
			ASSERT( pAffixmentData2 != NULL );
			int nWeight2 = pAffixmentData2->m_nAffixmentWeight;
			ASSERT( nWeight2 != nWeightX );
			if( nWeight2 > nWeightX )
			{
				vBars2.InsertAt( nBar2, pBarX );
				break;
			}
			if( nBar2 == nCount2-1 )
			{
				vBars2.Add( pBarX );
				break;
			}
		} // for( int nBar2 = 0; nBar2 < nCount2; nBar2++ )
	} // for( nBar = 0; nBar < nCount; nBar++ )
	ASSERT( vBars2.GetSize() == nCount );
	ASSERT( vBars2[0]->_AffixmentGetOuter()->m_nAffixmentWeight == 1 );
//	if( nCount == 2 )
//		return;
	for( nBar = 1; nBar < nCount; nBar++ )
	{
		CExtControlBar * pBarX = vBars2[nBar];
		CExtControlBar::InternalAffixmentData * pAffixmentDataX =
			pBarX->_AffixmentGetOuter();
		ASSERT( pAffixmentDataX != NULL );
		pAffixmentDataX->m_nAffixmentWeight = nBar + 1;
	}
}

//#define __DEBUG_CExtDockOuterBar_CompressSubRow_ASSERT_CRITICAL_MINSIZE

bool CExtDockOuterBar::_CompressSubRow(
	CExtDockOuterBar::dockbar_outer_layout_t & dbol,
	int nSubRowStartPos,
	int nSubRowEndPos,
	int nExtentMax,
	bool bHorz,
	bool & bAdjustWithAffixment,
	bool * p_bFullyOccupiedLayout // = NULL
	)
{
	ASSERT_VALID(this);
	ASSERT( dbol.GetSize() > 0 );
	ASSERT( nSubRowStartPos <= nSubRowEndPos );
	ASSERT( 0 <= nSubRowStartPos && nSubRowStartPos < dbol.GetSize() );
	ASSERT( 0 <= nSubRowEndPos   && nSubRowEndPos < dbol.GetSize() );

CArray < CRect, CRect > arrRcPreCalc;
int nPossibleBetween = 0;
//int nPossibleCs = 0;
int nExtentReal = 0;
	for( int nBar = nSubRowStartPos; nBar <= nSubRowEndPos; nBar++ )
	{
		OuterLayoutItemData & olid = dbol.ElementAt( nBar );
		ASSERT_VALID( olid.m_pBar );
		ASSERT_KINDOF( CControlBar, olid.m_pBar );
		ASSERT( olid.m_bVisible );
		CRect rcPreCalc( olid.m_rcPreCalc );
		ASSERT( rcPreCalc.left >= 0 );
		ASSERT( rcPreCalc.top >= 0 );
		ASSERT( rcPreCalc.left <= rcPreCalc.right );
		ASSERT( rcPreCalc.top <= rcPreCalc.bottom );
#ifdef __DEBUG_CExtDockOuterBar_CompressSubRow_ASSERT_CRITICAL_MINSIZE
		ASSERT( rcPreCalc.Width() >= olid.m_sizeBarMin.cx );
		ASSERT( rcPreCalc.Height() >= olid.m_sizeBarMin.cy );
#endif // __DEBUG_CExtDockOuterBar_CompressSubRow_ASSERT_CRITICAL_MINSIZE
		int nBetween = 0;
		if( nBar == nSubRowStartPos )
		{
			nBetween += bHorz
				? rcPreCalc.left
				: rcPreCalc.top
				;
			ASSERT( nBetween >= 0 );
		} // if( nBar == nSubRowStartPos )
		else
		{
			if( bHorz )
			{
				nBetween +=
					rcPreCalc.left
					- arrRcPreCalc.ElementAt(nBar-1-nSubRowStartPos).right
					;
				ASSERT( nBetween >= 0 );
				if( nBar == nSubRowEndPos )
					nBetween += nExtentMax - rcPreCalc.right;
			} // if( bHorz )
			else
			{
				nBetween +=
					rcPreCalc.top
					- arrRcPreCalc.ElementAt(nBar-1-nSubRowStartPos).bottom
					;
				ASSERT( nBetween >= 0 );
				if( nBar == nSubRowEndPos )
					nBetween += nExtentMax - rcPreCalc.bottom;
			} // else from if( bHorz )
		} // else from if( nBar == nSubRowStartPos )
//		int nCsAvail = bHorz
//			? (rcPreCalc.Width() - olid.m_sizeBarMin.cx)
//			: (rcPreCalc.Height() - olid.m_sizeBarMin.cy)
//			;
//		ASSERT( nCsAvail >= 0 );
//		nPossibleCs += nCsAvail;
		nPossibleBetween += nBetween;
		arrRcPreCalc.Add( rcPreCalc );
		nExtentReal += bHorz
			? rcPreCalc.Width()
			: rcPreCalc.Height()
			;
	} // for( int nBar = nSubRowStartPos; nBar <= nSubRowEndPos; nBar++ )

	ASSERT( arrRcPreCalc.GetSize() == (nSubRowEndPos-nSubRowStartPos+1) );

//int nPossible = nPossibleBetween + nPossibleCs;

bool bRetVal = false;
int nCsRow = nExtentReal - nExtentMax /*- nPossibleBetween*/; //nPossibleCs;
	if( nPossibleBetween > 0 )
		nCsRow -= nPossibleBetween;

	if( nPossibleBetween > 0 )
	{
		int nLeftPrev = nExtentMax;
		for( nBar = nSubRowEndPos; nBar >= nSubRowStartPos; nBar-- )
		{
			CRect & rcPreCalc = arrRcPreCalc.ElementAt( nBar-nSubRowStartPos );
			int nShift =
				nLeftPrev
				- (bHorz ? rcPreCalc.right : rcPreCalc.bottom)
				;
			if( nShift < 0 )
				rcPreCalc.OffsetRect(
					bHorz ? nShift : 0,
					bHorz ? 0 : nShift
					);
			nLeftPrev = bHorz
				? rcPreCalc.left
				: rcPreCalc.top
				;
		} // for( nBar = nSubRowEndPos; nBar >= nSubRowStartPos; nBar-- )
		if( nLeftPrev >= 0 )
			bRetVal = true;
//		else
//			nCsRow = -nLeftPrev;
	} // if( nPossibleBetween > 0 )

bool bCompressionPassed = false;
	if( (!bRetVal) && nCsRow >= 0 )
	{
		int nLeftPrev = nExtentMax;
		for( nBar = nSubRowEndPos; nBar >= nSubRowStartPos; nBar-- )
		{
			OuterLayoutItemData & olid = dbol.ElementAt( nBar );
			CRect & rcPreCalc = arrRcPreCalc.ElementAt( nBar-nSubRowStartPos );
			int nCsAvail = bHorz
				? (rcPreCalc.Width() - olid.m_sizeBarMin.cx)
				: (rcPreCalc.Height() - olid.m_sizeBarMin.cy)
				;
			if( nCsAvail < 0 )
				nCsAvail = 0;
			//ASSERT( nCsAvail >= 0 );
			if( nCsAvail > nCsRow )
				nCsAvail = nCsRow;
			bool bAdjust = false;
			if( nCsRow > 0 )
			{
				nCsRow -= nCsAvail;
				ASSERT( nCsRow >= 0 );
				bAdjust = true;
			}
			int nShift =
				nLeftPrev
				- (bHorz ? rcPreCalc.right : rcPreCalc.bottom )
				;
			//ASSERT( nShift >= 0 );
			rcPreCalc.OffsetRect(
				bHorz ? nShift : 0,
				bHorz ? 0 : nShift
				);
			//if( nCsRow > 0 )
			if( bAdjust )
				(bHorz ? rcPreCalc.left : rcPreCalc.top) += nCsAvail;
			nLeftPrev = bHorz ? rcPreCalc.left : rcPreCalc.top;
		} // for( nBar = nSubRowEndPos; nBar >= nSubRowStartPos; nBar-- )
		if( nCsRow == 0 && nLeftPrev >= 0 )
		{
			bRetVal = true;
			if(		nLeftPrev == 0
				&&	(nSubRowStartPos < nSubRowEndPos)
				)
			{ // if compression passed with full row layout with more than 1 bar
				bCompressionPassed = true;
				// re-compress with affixment
				AffixmentOrderVector_t arrAffixmentOrder;
				_CalcAffixmentOrderVector(
					bHorz,
					arrAffixmentOrder,
					dbol,
					false,
					nSubRowStartPos,
					nSubRowEndPos
					);
				ASSERT( arrAffixmentOrder.GetSize() == (nSubRowEndPos-nSubRowStartPos+1) );
				bool bPerformReShift = false;
				// last is not reviewed
				for( int nOrderT = arrAffixmentOrder.GetSize()-1; nOrderT > 0; nOrderT-- )
				{
					int nReviewIdx = arrAffixmentOrder[ nOrderT - 1 ];
					OuterLayoutItemData & olidReview = dbol.ElementAt( nReviewIdx );
					CExtControlBar * pExtBarReview =
						DYNAMIC_DOWNCAST(
							CExtControlBar,
							olidReview.m_pBar
							);
					if( pExtBarReview == NULL )
						continue;
					CExtControlBar::InternalAffixmentData * pAffixmentDataReview =
						pExtBarReview->_AffixmentGetOuter();
					if( pAffixmentDataReview == NULL
						||	pAffixmentDataReview->IsEmpty()
						)
						continue;
					CRect & rcPreCalcReview = arrRcPreCalc.ElementAt( nReviewIdx-nSubRowStartPos );
					int nExtentBarReview = bHorz
						? rcPreCalcReview.Width()
						: rcPreCalcReview.Height()
						;
					int nExtentCompressedAffixmentReview = bHorz
						? pAffixmentDataReview->m_sizeCompressed.cx
						: pAffixmentDataReview->m_sizeCompressed.cy
						;
					if( nExtentCompressedAffixmentReview < nExtentBarReview )
						continue;
					int nCsExt = nExtentCompressedAffixmentReview - nExtentBarReview;
					int nCsSrc = nCsExt;

					for( int nCmpxIdx = arrAffixmentOrder.GetSize(); nCmpxIdx > nOrderT ; nCmpxIdx-- )
					{
						int nCmpxIdxEffective = arrAffixmentOrder[ nCmpxIdx - 1 ];
						OuterLayoutItemData & olidCmpx = dbol.ElementAt( nCmpxIdxEffective );
						CExtControlBar * pExtBarCmpx =
							DYNAMIC_DOWNCAST(
								CExtControlBar,
								olidCmpx.m_pBar
								);
						if( pExtBarCmpx == NULL )
							continue;
						CExtControlBar::InternalAffixmentData * pAffixmentDataCmpx =
							pExtBarCmpx->_AffixmentGetOuter();
						if( pAffixmentDataCmpx == NULL
							||	pAffixmentDataCmpx->IsEmpty()
							)
							continue;
						ASSERT( pAffixmentDataReview->m_nAffixmentWeight <= pAffixmentDataCmpx->m_nAffixmentWeight );
						CRect & rcPreCalcCmpx = arrRcPreCalc.ElementAt( nCmpxIdxEffective-nSubRowStartPos );
						int nCsAvail = bHorz
							? (rcPreCalcCmpx.Width() - olidCmpx.m_sizeBarMin.cx)
							: (rcPreCalcCmpx.Height() - olidCmpx.m_sizeBarMin.cy)
							;
						//ASSERT( nCsAvail >= 0 );
						if( nCsAvail < 0 )
							continue;
						nCsAvail = min( nCsAvail, nCsExt );
						ASSERT( nCsAvail >= 0 );
						if( nCsAvail == 0 )
							continue;
						(bHorz ? rcPreCalcCmpx.right : rcPreCalcCmpx.bottom ) -=
							nCsAvail;
						nCsExt -= nCsAvail;
						bPerformReShift = true;
						ASSERT( nCsExt >= 0 );
						if( nCsExt == 0 )
							break;
					} // for( int nCmpxIdx = arrAffixmentOrder.GetSize(); nCmpxIdx > nOrderT ; nCmpxIdx-- )

					ASSERT( 0 <= nCsExt && nCsExt <= nCsSrc );
					if( nCsExt == nCsSrc )
						continue;

					ASSERT( bPerformReShift );
					(bHorz ? rcPreCalcReview.right : rcPreCalcReview.bottom ) +=
						(nCsSrc - nCsExt);
				} // for( int nOrderT = arrAffixmentOrder.GetSize()-1; nOrderT > 0; nOrderT-- )
				if( bPerformReShift )
				{
					int nRightPrev = 0;
					for( nBar = nSubRowStartPos; nBar <= nSubRowEndPos; nBar++ )
					{
//						OuterLayoutItemData & olid = dbol.ElementAt( nBar );
						CRect & rcPreCalc = arrRcPreCalc.ElementAt( nBar-nSubRowStartPos );
						int nShift =
							nRightPrev
							- (bHorz ? rcPreCalc.left : rcPreCalc.top )
							;
						if( nShift != 0 )
							rcPreCalc.OffsetRect(
								bHorz ? nShift : 0,
								bHorz ? 0 : nShift
								);
						nRightPrev = bHorz ? rcPreCalc.right : rcPreCalc.bottom;
					} // for( nBar = nSubRowStartPos; nBar <= nSubRowEndPos; nBar++ )
				} // if( bPerformReShift )
			} // if compression passed with full row layout with more than 1 bar
		} // if( nCsRow == 0 && nLeftPrev >= 0 )
	} // if( (!bRetVal) && nCsRow >= 0 )

	if( !bRetVal )
	{
		bAdjustWithAffixment = false;
		return false;
	} // if( !bRetVal )

bool bCalcFullyOccupiedLayout = 
		(p_bFullyOccupiedLayout != NULL) ? true : false;
	if(		bCalcFullyOccupiedLayout
		&&	(*p_bFullyOccupiedLayout)
		)
		bCalcFullyOccupiedLayout = false;
	if(		bCalcFullyOccupiedLayout
		&&	nSubRowStartPos > 0
		&&	nSubRowEndPos < (dbol.GetSize() - 1)
		)
		bCalcFullyOccupiedLayout = false;
	if(		bCalcFullyOccupiedLayout
		&&	bCompressionPassed
		)
	{
		bCalcFullyOccupiedLayout = false;
		*p_bFullyOccupiedLayout = true;
	}
int nPosRightPrev = 0;
	for( nBar = nSubRowStartPos; nBar <= nSubRowEndPos; nBar++ )
	{
		OuterLayoutItemData & olid = dbol.ElementAt( nBar );
		olid.m_rcPreCalc = arrRcPreCalc.ElementAt( nBar-nSubRowStartPos );
		ASSERT( olid.m_rcPreCalc.left >= 0 );
		ASSERT( olid.m_rcPreCalc.right >= 0 );
		ASSERT( olid.m_rcPreCalc.left <= olid.m_rcPreCalc.right );
		ASSERT( olid.m_rcPreCalc.top <= olid.m_rcPreCalc.bottom );
#ifdef __DEBUG_CExtDockOuterBar_CompressSubRow_ASSERT_CRITICAL_MINSIZE
		ASSERT( olid.m_rcPreCalc.Width() >= olid.m_sizeBarMin.cx );
		ASSERT( olid.m_rcPreCalc.Height() >= olid.m_sizeBarMin.cy );
#endif // __DEBUG_CExtDockOuterBar_CompressSubRow_ASSERT_CRITICAL_MINSIZE
		if( !bCalcFullyOccupiedLayout )
			continue;
		int nPosLeft = bHorz
			? olid.m_rcPreCalc.left
			: olid.m_rcPreCalc.top
			;
		if( nBar == nSubRowStartPos )
		{
			ASSERT( nPosLeft >= 0 );
			if( nPosLeft > 0 )
			{
				bCalcFullyOccupiedLayout = false;
				continue;
			}
		} // if( nBar == nSubRowStartPos )
		ASSERT( nPosLeft >= nPosRightPrev );
		if( nPosLeft > nPosRightPrev )
		{
			bCalcFullyOccupiedLayout = false;
			continue;
		}
		nPosRightPrev = bHorz
			? olid.m_rcPreCalc.right
			: olid.m_rcPreCalc.bottom
			;
		if( nBar == nSubRowEndPos )
		{
			if( nPosRightPrev < nExtentMax )
			{
				bCalcFullyOccupiedLayout = false;
				continue;
			}
		} // if( nBar == nSubRowEndPos )
	} // for( nBar = nSubRowStartPos; nBar <= nSubRowEndPos; nBar++ )

	if( bCalcFullyOccupiedLayout )
	{
		ASSERT( p_bFullyOccupiedLayout != NULL );
		*p_bFullyOccupiedLayout = true;
	}

	return true;
}

void CExtDockOuterBar::_CalcFixedRowLayout(
	CSize & sizeFixed,
	CSize & sizeMax,
	CPoint & pt,
	BOOL bHorz,
	AFX_SIZEPARENTPARAMS & layout,
	CExtDockOuterBar::dockbar_outer_layout_t & dbol,
	int * p_nSubRowCount, // = NULL
	bool * p_bFullyOccupiedLayout // = NULL
	)
{
	ASSERT_VALID(this);
	if( p_nSubRowCount != NULL )
		*p_nSubRowCount = 1;
	if( p_bFullyOccupiedLayout != NULL )
		*p_bFullyOccupiedLayout = false;
int nCountOfBars = dbol.GetSize();
	ASSERT( nCountOfBars > 0 );

	// pre-process hidden bars
	for( int nBar = 0; nBar < nCountOfBars; )
	{
		OuterLayoutItemData & olid = dbol.ElementAt( nBar );
		ASSERT_VALID( olid.m_pBar );
		ASSERT_KINDOF( CControlBar, olid.m_pBar );
		if( !olid.m_bVisible )
		{
			olid.m_pBar->RecalcDelayShow( &layout );
			dbol.RemoveAt( nBar );
			nCountOfBars--;
			continue;
		}
		olid.m_pBar->GetWindowRect( &olid.m_rcReal );
		ScreenToClient( &olid.m_rcReal );
		nBar++;
	} // for( int nBar = 0; nBar < nCountOfBars; )

	// precalc layout (1), move according to affixement
AffixmentOrderVector_t arrAffixmentOrder;
	_CalcAffixmentOrderVector(
		bHorz ? true : false,
		arrAffixmentOrder,
		dbol,
		true
		);
	ASSERT( arrAffixmentOrder.GetSize() == nCountOfBars );

	// precalc layout (2), split to subrows
int nTotalRowExtent = 0;
int nSubRowStartPos = 0;
bool bAdjustWithAffixment = true;
bool bAlignSubRowAffixmentHW = true;
	for( nBar = 0; nBar < nCountOfBars; nBar++ )
	{
		OuterLayoutItemData & olid = dbol.ElementAt( nBar );
		ASSERT_VALID( olid.m_pBar );
		ASSERT_KINDOF( CControlBar, olid.m_pBar );
		ASSERT( olid.m_bVisible );

		olid.m_rcPreCalc = CRect( pt, olid.m_sizeCalcDynamic );
		if( bHorz )
		{
			if(		olid.m_rcReal.left > olid.m_rcPreCalc.left
				&&	(!m_bFloating)
				)
				olid.m_rcPreCalc.OffsetRect(
					olid.m_rcReal.left - olid.m_rcPreCalc.left,
					0
					);
			int nRest = olid.m_rcPreCalc.right - sizeMax.cx;
///			int nRest = sizeMax.cx - olid.m_rcPreCalc.left + olid.m_sizeBarMin.cx;
			if(		nRest >= 0
				&&	(	!olid.m_pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar))
					||	(	olid.m_pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar))
						&&	((CExtControlBar*)olid.m_pBar)->IsFixedMode()
						)
					)
				)
			{ // trying to make one multi-row or compress it
				if( !_CompressSubRow(
						dbol,
						nSubRowStartPos,
						nBar,
						sizeMax.cx,
						bHorz ? true : false,
						bAdjustWithAffixment,
						p_bFullyOccupiedLayout
						)
					)
				{
					if( p_nSubRowCount != NULL )
						(*p_nSubRowCount)++;
					if( p_bFullyOccupiedLayout != NULL )
						*p_bFullyOccupiedLayout = true;
//					ASSERT( bAlignSubRowAffixmentHW );
					bAlignSubRowAffixmentHW = false;
					_AlignSubRowAffixmentHW(
						bHorz ? true : false,
						dbol,
						nSubRowStartPos,
						nBar
						);
					bAdjustWithAffixment = false;
					nSubRowStartPos = nBar;
					_AdjustByTotalRowExtent(
						nTotalRowExtent,
						sizeFixed,
						pt,
						bHorz
						);
					ASSERT( pt.x == 0 );
					olid.m_rcPreCalc = CRect( pt, olid.m_sizeCalcDynamic );
				}
				else
					bAlignSubRowAffixmentHW = true;
			} // trying to make one multi-row or compress it
			pt.x =
				//olid.m_rcPreCalc.left + olid.m_sizeCalcDynamic.cx
				olid.m_rcPreCalc.right
				;
			nTotalRowExtent = max( nTotalRowExtent, olid.m_sizeCalcDynamic.cy );
		} // if( bHorz )
		else
		{
			// offset calculated rect out to actual
			if(		olid.m_rcReal.top > olid.m_rcPreCalc.top
				&&	(!m_bFloating)
				)
				olid.m_rcPreCalc.OffsetRect(
					0,
					olid.m_rcReal.top - olid.m_rcPreCalc.top
					);
			int nRest = olid.m_rcPreCalc.bottom - sizeMax.cy;
///			int nRest = sizeMax.cy - olid.m_rcPreCalc.top + olid.m_sizeBarMin.cy;
			if(		nRest >= 0
				&&	(	!olid.m_pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar))
					||	(	olid.m_pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar))
						&&	((CExtControlBar*)olid.m_pBar)->IsFixedMode()
						)
					)
				)
			{ // trying to make one multi-row or compress it
				if( !_CompressSubRow(
						dbol,
						nSubRowStartPos,
						nBar,
						sizeMax.cy,
						bHorz ? true : false,
						bAdjustWithAffixment,
						p_bFullyOccupiedLayout
						)
					)
				{
					if( p_nSubRowCount != NULL )
						(*p_nSubRowCount)++;
					if( p_bFullyOccupiedLayout != NULL )
						*p_bFullyOccupiedLayout = true;
//					ASSERT( bAlignSubRowAffixmentHW );
					bAlignSubRowAffixmentHW = false;
					_AlignSubRowAffixmentHW(
						bHorz ? true : false,
						dbol,
						nSubRowStartPos,
						nBar
						);
					bAdjustWithAffixment = false;
					nSubRowStartPos = nBar;
					_AdjustByTotalRowExtent(
						nTotalRowExtent,
						sizeFixed,
						pt,
						bHorz
						);
					ASSERT( pt.y == 0 );
					olid.m_rcPreCalc = CRect( pt, olid.m_sizeCalcDynamic );
				}
				else
					bAlignSubRowAffixmentHW = true;
			} // trying to make one multi-row or compress it
			pt.y =
				//olid.m_rcPreCalc.top + olid.m_sizeCalcDynamic.cy
				olid.m_rcPreCalc.bottom
				;
			nTotalRowExtent = max( nTotalRowExtent, olid.m_sizeCalcDynamic.cx );
		} // else from if( bHorz )

	} // for( nBar = 0; nBar < nCountOfBars; nBar++ )

	if( bAlignSubRowAffixmentHW && (nCountOfBars > 0) )
	{
		ASSERT( nBar <= nCountOfBars );
		if( nBar == nCountOfBars )
			nBar = nCountOfBars - 1;
		ASSERT( nSubRowStartPos <= nBar );
		_AlignSubRowAffixmentHW(
			bHorz ? true : false,
			dbol,
			nSubRowStartPos,
			nBar
			);
	} // if( bAlignSubRowAffixmentHW && (nCountOfBars > 0) )

/* DEBUG **
*********************************************
*********************************************
int nPosLastTest = 0;
	for( nBar = 0; bAdjustWithAffixment && nBar < nCountOfBars; nBar++ )
	{
		OuterLayoutItemData & olid = dbol.ElementAt( nBar );
		ASSERT_VALID( olid.m_pBar );
		ASSERT_KINDOF( CControlBar, olid.m_pBar );
		ASSERT( olid.m_bVisible );
		int nPosCurrTest = bHorz
			? olid.m_rcPreCalc.left
			: olid.m_rcPreCalc.top
			;
		ASSERT( nPosLastTest <= nPosCurrTest );
		if( nPosLastTest < nPosCurrTest )
			break;
		nPosLastTest = bHorz
			? olid.m_rcPreCalc.right
			: olid.m_rcPreCalc.bottom
			;
	} // for( nBar = 0; bAdjustWithAffixment && nBar < nCountOfBars; nBar++ )
int bMaxTest = bHorz ? sizeMax.cx : sizeMax.cy;
	if( nBar == nCountOfBars
		&& nPosLastTest >= bMaxTest
		)
		bAdjustWithAffixment = false;
*********************************************
*********************************************
** DEBUG */

	if( bAdjustWithAffixment )
	{
		// pre adjust affixment
		for( int nOrder = nCountOfBars; nOrder > 0; nOrder-- )
		{
			int nBarAtOrder = arrAffixmentOrder[nOrder-1];
			ASSERT( 0 <= nBarAtOrder && nBarAtOrder < nCountOfBars );
			OuterLayoutItemData & olid = dbol.ElementAt( nBarAtOrder );
			ASSERT_VALID( olid.m_pBar );
			ASSERT_KINDOF( CControlBar, olid.m_pBar );
			ASSERT( olid.m_bVisible );
			CExtControlBar * pExtBar =
				DYNAMIC_DOWNCAST(
					CExtControlBar,
					olid.m_pBar
					);
			if( pExtBar == NULL )
				continue;
			CExtControlBar::InternalAffixmentData * pAffixmentData =
					pExtBar->_AffixmentGetOuter();
//			if( pAffixmentData == NULL )
//				continue;
//			ASSERT( !pAffixmentData->IsEmpty() );
//			ASSERT( !pAffixmentData->m_rcAffixment.IsRectEmpty() );
//			if( olid.m_rcPreCalc == pAffixmentData->m_rcAffixment )
//				continue;
			if(		pAffixmentData == NULL
				||	pAffixmentData->IsEmpty()
				||	pAffixmentData->m_rcAffixment.IsRectEmpty()
				||	olid.m_rcPreCalc == pAffixmentData->m_rcAffixment
				)
				continue;
			_PreAdjustWithAffixment(
				bHorz ? true : false,
				dbol,
				olid,
				nBarAtOrder,
				pAffixmentData,
				bHorz ? sizeMax.cx : sizeMax.cy
				);
		} // for( int nOrder = nCountOfBars; nOrder > 0; nOrder-- )
		// post adjust affixment
		for( nOrder = nCountOfBars; nOrder > 0; nOrder-- )
		{
			int nBarAtOrder = arrAffixmentOrder[nOrder-1];
			ASSERT( 0 <= nBarAtOrder && nBarAtOrder < nCountOfBars );
			OuterLayoutItemData & olid = dbol.ElementAt( nBarAtOrder );
			ASSERT_VALID( olid.m_pBar );
			ASSERT_KINDOF( CControlBar, olid.m_pBar );
			ASSERT( olid.m_bVisible );
			CExtControlBar * pExtBar =
				DYNAMIC_DOWNCAST(
					CExtControlBar,
					olid.m_pBar
					);
			if( pExtBar == NULL )
				continue;
			CExtControlBar::InternalAffixmentData * pAffixmentData =
					pExtBar->_AffixmentGetOuter();
//			if( pAffixmentData == NULL )
//				continue;
//			ASSERT( !pAffixmentData->IsEmpty() );
//			ASSERT( !pAffixmentData->m_rcAffixment.IsRectEmpty() );
//			if( olid.m_rcPreCalc == pAffixmentData->m_rcAffixment )
//				continue;
			if(		pAffixmentData == NULL
				||	pAffixmentData->IsEmpty()
				||	pAffixmentData->m_rcAffixment.IsRectEmpty()
				||	olid.m_rcPreCalc == pAffixmentData->m_rcAffixment
				)
				continue;
			_PostAdjustWithAffixment(
				bHorz ? true : false,
				dbol,
				olid,
				nBarAtOrder,
				pAffixmentData,
				bHorz ? sizeMax.cx : sizeMax.cy
				);
		} // for( int nOrder = nCountOfBars; nOrder > 0; nOrder-- )
	} // if( bAdjustWithAffixment )

	// verify for minimal layouts
	for( nBar = 0; nBar < nCountOfBars; nBar++ )
	{
		OuterLayoutItemData & olid = dbol.ElementAt( nBar );
		ASSERT_VALID( olid.m_pBar );
		ASSERT_KINDOF( CControlBar, olid.m_pBar );
		ASSERT( olid.m_bVisible );
		if( bHorz )
		{
			int nRest = sizeMax.cx - olid.m_rcPreCalc.right;
			if( nRest >= 0 )
				continue;
			olid.m_rcPreCalc.right = sizeMax.cx;
			if( olid.m_rcPreCalc.Width() < olid.m_sizeBarMin.cx )
				olid.m_rcPreCalc.right = olid.m_rcPreCalc.left + olid.m_sizeBarMin.cx;
		} // if( bHorz )
		else
		{
			int nRest = sizeMax.cy - olid.m_rcPreCalc.bottom;
			if( nRest >= 0 )
				continue;
			olid.m_rcPreCalc.bottom = sizeMax.cy;
			if( olid.m_rcPreCalc.Height() < olid.m_sizeBarMin.cy )
				olid.m_rcPreCalc.bottom = olid.m_rcPreCalc.top + olid.m_sizeBarMin.cy;
		} // else from if( bHorz )
	}

	// apply layout
	if( !m_bLayoutQuery )
	{
		for( nBar = 0; nBar < nCountOfBars; nBar++ )
		{
			OuterLayoutItemData & olid = dbol.ElementAt( nBar );
			ASSERT_VALID( olid.m_pBar );
			ASSERT_KINDOF( CControlBar, olid.m_pBar );
			ASSERT( olid.m_bVisible );
			if( olid.m_rcPreCalc == olid.m_rcReal )
				continue;
			if( (olid.m_pBar->m_dwStyle & CBRS_FLOATING) == 0 )
				olid.m_pBar->m_pDockContext->
					m_rectMRUDockPos = olid.m_rcPreCalc;
			AfxRepositionWindow(
				&layout,
				olid.m_pBar->m_hWnd,
				&olid.m_rcPreCalc
				);
		} // for( nBar = 0; nBar < nCountOfBars; nBar++ )
	} // if( !m_bLayoutQuery )

	_AdjustByTotalRowExtent(
		nTotalRowExtent,
		sizeFixed,
		pt,
		bHorz
		);
}

void CExtDockOuterBar::_PreAdjustWithAffixment(
	bool bHorz,
	CExtDockOuterBar::dockbar_outer_layout_t & dbol,
	CExtDockOuterBar::OuterLayoutItemData & olidAdjustedSrc,
	int nBarAdjustedSrc,
	CExtControlBar::InternalAffixmentData * pAffixmentDataAdjustedSrc,
	int nExtentMax
	)
{
	if( nExtentMax <= 0 )
		return;
int nCountOfBars = dbol.GetSize();
	ASSERT( 0 <= nBarAdjustedSrc && nBarAdjustedSrc < nCountOfBars );
	ASSERT( dbol.ElementAt(nBarAdjustedSrc).m_pBar == olidAdjustedSrc.m_pBar );
	ASSERT( pAffixmentDataAdjustedSrc != NULL );
	ASSERT( !pAffixmentDataAdjustedSrc->IsEmpty() );
int nPosAffixment = bHorz
		? pAffixmentDataAdjustedSrc->m_rcAffixment.left
		: pAffixmentDataAdjustedSrc->m_rcAffixment.top
		;
int nPosPreCalc = bHorz
		? olidAdjustedSrc.m_rcPreCalc.left
		: olidAdjustedSrc.m_rcPreCalc.top
		;
int nAdjustShift = nPosAffixment - nPosPreCalc;
	if( nAdjustShift == 0 )
		return;
//	TRACE3(
//		"     Bar 0x%08X      weight = %d      nAdjustShift = %d\n",
//		long(olidAdjustedSrc.m_pBar),
//		pAffixmentDataAdjustedSrc->m_nAffixmentWeight,
//		nAdjustShift
//		);
	_ShiftSubRowWithAffixment(
		bHorz,
		dbol,
		( nAdjustShift > 0 )
			? nBarAdjustedSrc
			: 0
			,
		( nAdjustShift > 0 )
			? (nCountOfBars - 1)
			: nBarAdjustedSrc
			,
		nAdjustShift,
		nExtentMax
		);
}

void CExtDockOuterBar::_PostAdjustWithAffixment(
	bool bHorz,
	CExtDockOuterBar::dockbar_outer_layout_t & dbol,
	CExtDockOuterBar::OuterLayoutItemData & olidAdjustedSrc,
	int nBarAdjustedSrc,
	CExtControlBar::InternalAffixmentData * pAffixmentDataAdjustedSrc,
	int nExtentMax
	)
{
	if( nExtentMax <= 0 )
		return;
int nCountOfBars = dbol.GetSize();
	ASSERT( 0 <= nBarAdjustedSrc && nBarAdjustedSrc < nCountOfBars );
	ASSERT( dbol.ElementAt(nBarAdjustedSrc).m_pBar == olidAdjustedSrc.m_pBar );
	ASSERT( pAffixmentDataAdjustedSrc != NULL );
	ASSERT( !pAffixmentDataAdjustedSrc->IsEmpty() );

int nPosAffixment = bHorz
		? pAffixmentDataAdjustedSrc->m_rcAffixment.left
		: pAffixmentDataAdjustedSrc->m_rcAffixment.top
		;
int nPosPreCalc = bHorz
		? olidAdjustedSrc.m_rcPreCalc.left
		: olidAdjustedSrc.m_rcPreCalc.top
		;
int nPosPossibleToFix = nPosPreCalc;
int nAdjustShift = nPosAffixment - nPosPreCalc;
	if( nAdjustShift == 0 )
		return;
	if( nAdjustShift < 0 )
	{
		if( nBarAdjustedSrc == 0 )
		{
			nPosPossibleToFix =
				max( nPosPossibleToFix, 0 );
		} // if( nBarAdjustedSrc == 0 )
		else
		{
			OuterLayoutItemData & olid2 = dbol.ElementAt( nBarAdjustedSrc-1 );
			ASSERT_VALID( olid2.m_pBar );
			ASSERT_KINDOF( CControlBar, olid2.m_pBar );
			ASSERT( olid2.m_bVisible );
			nPosPossibleToFix = bHorz
				? olid2.m_rcPreCalc.right
				: olid2.m_rcPreCalc.bottom
				;
		} // else from if( nBarAdjustedSrc == 0 )
		int nPossibleShift = nPosPossibleToFix - nPosPreCalc;
		nAdjustShift = max( nAdjustShift, nPossibleShift );
	} // if( nAdjustShift < 0 )
	else
	{
		nPosPreCalc += bHorz
			? olidAdjustedSrc.m_rcPreCalc.Width()
			: olidAdjustedSrc.m_rcPreCalc.Height()
			;
		nPosPossibleToFix = nPosPreCalc;
		if( nBarAdjustedSrc == (nCountOfBars-1) )
		{
			nPosPossibleToFix =
				min( nPosPossibleToFix, nExtentMax );
		} // if( nBarAdjustedSrc == (nCountOfBars-1) )
		else
		{
			OuterLayoutItemData & olid2 = dbol.ElementAt( nBarAdjustedSrc+1 );
			ASSERT_VALID( olid2.m_pBar );
			ASSERT_KINDOF( CControlBar, olid2.m_pBar );
			ASSERT( olid2.m_bVisible );
			nPosPossibleToFix = bHorz
				? olid2.m_rcPreCalc.left
				: olid2.m_rcPreCalc.top
				;
		} // else from if( nBarAdjustedSrc == (nCountOfBars-1) )
		int nPossibleShift = nPosPossibleToFix - nPosPreCalc;
		nAdjustShift = min( nAdjustShift, nPossibleShift );
	} // else from if( nAdjustShift < 0 )
	if( nAdjustShift == 0 )
		return;
	olidAdjustedSrc.m_rcPreCalc.OffsetRect(
		bHorz ? nAdjustShift : 0,
		bHorz ? 0 : nAdjustShift
		);
}

int CExtDockOuterBar::_ShiftSubRowWithAffixment(
	bool bHorz,
	CExtDockOuterBar::dockbar_outer_layout_t & dbol,
	int nReviewStart,
	int nReviewEnd,
	int nAdjustShift,
	int nExtentMax
	)
{
	ASSERT( dbol.GetSize() > 0 );
	ASSERT( 0 <= nReviewStart && nReviewStart < dbol.GetSize() );
	ASSERT( 0 <= nReviewEnd && nReviewEnd < dbol.GetSize() );
	ASSERT( nReviewStart <= nReviewEnd );
	ASSERT( nAdjustShift != 0 );
	ASSERT( nExtentMax > 0 );

	if( nReviewStart == nReviewEnd )
	{
		OuterLayoutItemData & olid = dbol.ElementAt( nReviewStart );
		ASSERT_VALID( olid.m_pBar );
		ASSERT_KINDOF( CControlBar, olid.m_pBar );
		ASSERT( olid.m_bVisible );
		int nPosPreCalc = bHorz
			? olid.m_rcPreCalc.left
			: olid.m_rcPreCalc.top
			;
		ASSERT( nPosPreCalc >= 0 );
		if( nAdjustShift > 0 )
		{
			ASSERT( nReviewStart == dbol.GetSize()-1 );
			nPosPreCalc += bHorz
				? olid.m_rcPreCalc.Width()
				: olid.m_rcPreCalc.Height()
				;
			ASSERT( nPosPreCalc >= 0 );
			ASSERT( nPosPreCalc <= nExtentMax );
			if( nPosPreCalc == nExtentMax )
				return 0;
			int nRest = nExtentMax - nPosPreCalc;
			ASSERT( nRest >= 0 );
			nAdjustShift = min( nAdjustShift, nRest );
			ASSERT( nAdjustShift >= 0 );
		} // if( nAdjustShift > 0 )
		else
		{
			ASSERT( nReviewStart == 0 );
//			if( nPosPreCalc == 0 )
//				return 0;
//if( nPosPreCalc < 0 )
//	return 0;
			nAdjustShift = max( (-nPosPreCalc), nAdjustShift );
			ASSERT( nAdjustShift <= 0 );
		} // else from if( nAdjustShift > 0 )
		olid.m_rcPreCalc.OffsetRect(
			bHorz ? nAdjustShift : 0,
			bHorz ? 0 : nAdjustShift
			);
		ASSERT( olid.m_rcPreCalc.left >= 0 );
		ASSERT( olid.m_rcPreCalc.top >= 0 );
		return nAdjustShift;
	} // if( nReviewStart == nReviewEnd )

	if( nAdjustShift > 0 )
	{
		OuterLayoutItemData & olid1 = dbol.ElementAt( nReviewStart );
		ASSERT_VALID( olid1.m_pBar );
		ASSERT_KINDOF( CControlBar, olid1.m_pBar );
		ASSERT( olid1.m_bVisible );
		ASSERT( olid1.m_rcPreCalc.left >= 0 );
		ASSERT( olid1.m_rcPreCalc.top >= 0 );
		int nPosPreCalc1 = bHorz
			? olid1.m_rcPreCalc.right // (olid1.m_rcPreCalc.left + olid1.m_rcPreCalc.Width())
			: olid1.m_rcPreCalc.bottom // (olid1.m_rcPreCalc.top + olid1.m_rcPreCalc.Height())
			;
		ASSERT( nPosPreCalc1 >= 0 );
		OuterLayoutItemData & olid2 = dbol.ElementAt( nReviewStart + 1 );
		ASSERT_VALID( olid2.m_pBar );
		ASSERT_KINDOF( CControlBar, olid2.m_pBar );
		ASSERT( olid2.m_bVisible );
		ASSERT( olid2.m_rcPreCalc.left >= 0 );
		ASSERT( olid2.m_rcPreCalc.top >= 0 );
		int nPosPreCalc2 = bHorz
			? olid2.m_rcPreCalc.left
			: olid2.m_rcPreCalc.top
			;
		ASSERT( nPosPreCalc2 >= 0 );
		int nDist = nPosPreCalc2 - nPosPreCalc1;
		ASSERT( nDist >= 0 );
		nDist = min( nAdjustShift, nDist );
		ASSERT( nDist <= nAdjustShift );
		if( nDist == nAdjustShift )
		{
			olid1.m_rcPreCalc.OffsetRect(
				bHorz ? nAdjustShift : 0,
				bHorz ? 0 : nAdjustShift
				);
			ASSERT( olid1.m_rcPreCalc.left >= 0 );
			ASSERT( olid1.m_rcPreCalc.top >= 0 );
			return nAdjustShift;
		}
		int nSpaceToCompress = nAdjustShift - nDist;
		ASSERT( nSpaceToCompress > 0 );
		int nSpaceReallyCompressed =
			_ShiftSubRowWithAffixment(
				bHorz,
				dbol,
				nReviewStart + 1,
				nReviewEnd,
				nSpaceToCompress,
				nExtentMax
				);
		ASSERT( nSpaceReallyCompressed >= 0 );
		ASSERT( nSpaceReallyCompressed <= nSpaceToCompress );
/*?????*/		nAdjustShift = nSpaceReallyCompressed + nDist;
		olid1.m_rcPreCalc.OffsetRect(
			bHorz ? nAdjustShift : 0,
			bHorz ? 0 : nAdjustShift
			);
		ASSERT( olid1.m_rcPreCalc.left >= 0 );
		ASSERT( olid1.m_rcPreCalc.top >= 0 );
	} // if( nAdjustShift > 0 )
	else
	{
		OuterLayoutItemData & olid1 = dbol.ElementAt( nReviewEnd );
		ASSERT_VALID( olid1.m_pBar );
		ASSERT_KINDOF( CControlBar, olid1.m_pBar );
		ASSERT( olid1.m_bVisible );
		ASSERT( olid1.m_rcPreCalc.left >= 0 );
		ASSERT( olid1.m_rcPreCalc.top >= 0 );
		int nPosPreCalc1 = bHorz
			? olid1.m_rcPreCalc.left
			: olid1.m_rcPreCalc.top
			;
		ASSERT( nPosPreCalc1 >= 0 );
		OuterLayoutItemData & olid2 = dbol.ElementAt( nReviewEnd - 1 );
		ASSERT_VALID( olid2.m_pBar );
		ASSERT_KINDOF( CControlBar, olid2.m_pBar );
		ASSERT( olid2.m_bVisible );
		ASSERT( olid2.m_rcPreCalc.left >= 0 );
		ASSERT( olid2.m_rcPreCalc.top >= 0 );
		int nPosPreCalc2 = bHorz
			? olid2.m_rcPreCalc.right // (olid2.m_rcPreCalc.left + olid2.m_rcPreCalc.Width())
			: olid2.m_rcPreCalc.bottom // (olid2.m_rcPreCalc.top + olid2.m_rcPreCalc.Height())
			;
		ASSERT( nPosPreCalc2 >= 0 );
		int nDist = nPosPreCalc2 - nPosPreCalc1;
		ASSERT( nDist <= 0 );
		nDist = max( nAdjustShift, nDist );
		ASSERT( nDist >= nAdjustShift );
		if( nDist == nAdjustShift )
		{
			olid1.m_rcPreCalc.OffsetRect(
				bHorz ? nAdjustShift : 0,
				bHorz ? 0 : nAdjustShift
				);
			ASSERT( olid1.m_rcPreCalc.left >= 0 );
			ASSERT( olid1.m_rcPreCalc.top >= 0 );
			return nAdjustShift;
		}
		int nSpaceToCompress = nAdjustShift - nDist;
		ASSERT( nSpaceToCompress < 0 );
		int nSpaceReallyCompressed =
			_ShiftSubRowWithAffixment(
				bHorz,
				dbol,
				nReviewStart,
				nReviewEnd - 1,
				nSpaceToCompress,
				nExtentMax
				);
		ASSERT( nSpaceReallyCompressed <= 0 );
		ASSERT( nSpaceReallyCompressed >= nSpaceToCompress );
/*?????*/		nAdjustShift = nSpaceReallyCompressed + nDist;
		olid1.m_rcPreCalc.OffsetRect(
			bHorz ? nAdjustShift : 0,
			bHorz ? 0 : nAdjustShift
			);
		ASSERT( olid2.m_rcPreCalc.left >= 0 );
		ASSERT( olid2.m_rcPreCalc.top >= 0 );
	} // else from if( nAdjustShift > 0 )

	return nAdjustShift;
}

void CExtDockOuterBar::_AdjustByTotalRowExtent(
	int & nTotalRowExtent,
	CSize & sizeFixed,
	CPoint & pt,
	BOOL bHorz
	)
{
	if( nTotalRowExtent == 0 )
		return;
	if( bHorz )
	{
		pt.y += nTotalRowExtent;
		sizeFixed.cx = max(sizeFixed.cx, pt.x);
		sizeFixed.cy = max(sizeFixed.cy, pt.y);
		pt.x = 0;
		sizeFixed.cy--;
	} // if( bHorz )
	else
	{
		pt.x += nTotalRowExtent;
		sizeFixed.cx = max(sizeFixed.cx, pt.x);
		sizeFixed.cy = max(sizeFixed.cy, pt.y);
		pt.y = 0;
		sizeFixed.cx--;
	} // else from if( bHorz )
	nTotalRowExtent = 0;
}

CSize CExtDockOuterBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
	ASSERT_VALID(this);
CSize sizeFixed =
		CControlBar::CalcFixedLayout( bStretch, bHorz );
CSize sizeMax;
	if( !m_rectLayout.IsRectEmpty() )
		sizeMax = m_rectLayout.Size();
	else
	{
		CFrameWnd * pFrame = GetParentFrame();
		CRect rcFrameWindow;
		pFrame->GetClientRect( &rcFrameWindow );
		sizeMax = rcFrameWindow.Size();
	}

CPoint pt( 0, 0 );
int nCountOfBars = m_arrBars.GetSize();
AFX_SIZEPARENTPARAMS layout;
	layout.hDWP =
		m_bLayoutQuery
			? NULL
			: ( ::BeginDeferWindowPos(nCountOfBars) )
			;
dockbar_outer_layout_t dbol;
	for( int nBar = 0; nBar < nCountOfBars; nBar++ )
	{
		CControlBar * pBar = (CControlBar *)m_arrBars[nBar];
		if(		pBar != NULL
			&&	(!(__PLACEHODLER_BAR_PTR(pBar)))
			)
		{
			ASSERT_VALID( pBar );
			ASSERT_KINDOF( CControlBar, pBar );
			dbol.Add(
				OuterLayoutItemData(
					pBar,
					bHorz,
					sizeMax
					)
				);
		} // if( pBar != NULL && ...
		if( pBar == NULL || nBar == (nCountOfBars-1) )
		{
			if( dbol.GetSize() == 0 )
				continue;
			_CalcFixedRowLayout(
				sizeFixed,
				sizeMax,
				pt,
				bHorz,
				layout,
				dbol
				);
			dbol.RemoveAll();
		} // if( pBar == NULL || nBar == (nCountOfBars-1) )
	} // for( int nBar = 0; nBar < nCountOfBars; nBar++ )
	ASSERT( dbol.GetSize() == 0 );

	if( !m_bLayoutQuery )
	{
		ASSERT( layout.hDWP != NULL );
		if( layout.hDWP != NULL )
		{
			VERIFY( ::EndDeferWindowPos(layout.hDWP) );
		}
	} // if( !m_bLayoutQuery )

	// adjust size for borders on the dock bar itself
CRect rc( 0, 0, 0, 0 );
	CalcInsideRect(rc, bHorz);
	if( (!bStretch || !bHorz) && sizeFixed.cx != 0 )
		sizeFixed.cx +=
			-rc.right + rc.left
			+ g_bControlBarFixSizePixel ? 1 : 0;
	if(	(!bStretch || bHorz) && sizeFixed.cy != 0 )
		sizeFixed.cy +=
			-rc.bottom + rc.top
			+ g_bControlBarFixSizePixel ? 1 : 0;

	if( !m_bLayoutQuery )
		OnDynamicLayoutUpdate();
	return sizeFixed;
}

void CExtDockOuterBar::_RedockInRow(
	CExtControlBar * pBarSlide,
	int nShiftDesired,
	bool * p_bInplaceResizing // = NULL
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( pBarSlide );
	ASSERT( this == pBarSlide->GetParent() );
	if( p_bInplaceResizing != NULL )
		*p_bInplaceResizing = false;
	if( nShiftDesired == 0 )
		return;
int nCountOfBars = m_arrBars.GetSize();
	ASSERT( nCountOfBars > 1 );
int nSlideBarPos = FindBar( pBarSlide );
	ASSERT( 0 < nSlideBarPos && nSlideBarPos < nCountOfBars );
CControlBar * pFirstBar =
		pBarSlide->_GetFirstControlBarInRow(
			pBarSlide,
			false,
			false,
			false
			);
	ASSERT_VALID( pFirstBar );
int nFirstBarPos = FindBar( pFirstBar );
	ASSERT( 0 < nFirstBarPos && nFirstBarPos < nCountOfBars );
	ASSERT( nFirstBarPos <= nSlideBarPos );

UINT nDockBarID = GetDlgCtrlID();
	ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nDockBarID );
BOOL bHorz = 
		(	nDockBarID == AFX_IDW_DOCKBAR_TOP
		||	nDockBarID == AFX_IDW_DOCKBAR_BOTTOM )
		? TRUE : FALSE;

CRect rcSlideBarWnd;
	pBarSlide->GetWindowRect( &rcSlideBarWnd );
	ScreenToClient( &rcSlideBarWnd );

CSize sizeMax, sizeFakeFixed( 0, 0 );
	if( !m_rectLayout.IsRectEmpty() )
		sizeMax = m_rectLayout.Size();
	else
	{
		CFrameWnd * pFrame = GetParentFrame();
		CRect rcFrameWindow;
		pFrame->GetClientRect( &rcFrameWindow );
		sizeMax = rcFrameWindow.Size();
	}

CPoint pt( 0, 0 );
	if( bHorz )
		pt.y = rcSlideBarWnd.top;
	else
		pt.x = rcSlideBarWnd.left;

CExtControlBar::InternalAffixmentData * pAffixmentData =
		pBarSlide->_AffixmentGetOuter();
	if( pAffixmentData != NULL )
	{
		ASSERT( !pAffixmentData->IsEmpty() );
		if( pAffixmentData->m_rcAffixment.IsRectEmpty() )
		{
			pBarSlide->GetWindowRect( &pAffixmentData->m_rcAffixment );
			ScreenToClient( &pAffixmentData->m_rcAffixment );
		}
		pAffixmentData->m_rcAffixment.OffsetRect(
			bHorz ? nShiftDesired : 0,
			bHorz ? 0 : nShiftDesired
			);
		if( bHorz )
		{
			if( pAffixmentData->m_rcAffixment.right >= sizeMax.cx )
				pAffixmentData->m_rcAffixment.OffsetRect(
					sizeMax.cx - pAffixmentData->m_rcAffixment.right,
					0
					);
			if( pAffixmentData->m_rcAffixment.left < 0 )
				pAffixmentData->m_rcAffixment.OffsetRect(
					- pAffixmentData->m_rcAffixment.left,
					0
					);
		} // if( bHorz )
		else
		{
			if( pAffixmentData->m_rcAffixment.bottom >= sizeMax.cy )
				pAffixmentData->m_rcAffixment.OffsetRect(
					0,
					sizeMax.cy - pAffixmentData->m_rcAffixment.bottom
					);
			if( pAffixmentData->m_rcAffixment.top < 0 )
				pAffixmentData->m_rcAffixment.OffsetRect(
					0,
					- pAffixmentData->m_rcAffixment.top
					);
		} // else from if( bHorz )
	}

dockbar_outer_layout_t dbol;
	for( int nBar = nFirstBarPos; nBar < nCountOfBars; nBar++ )
	{
		CControlBar * pBar = (CControlBar *)m_arrBars[nBar];
		if(		pBar != NULL
			&&	(!(__PLACEHODLER_BAR_PTR(pBar)))
			)
		{
			ASSERT_VALID( pBar );
			ASSERT_KINDOF( CControlBar, pBar );
			OuterLayoutItemData olid(
				pBar,
				bHorz,
				sizeMax
				);
			if( pBar == pBarSlide )
			{
				if( pAffixmentData == NULL )
					olid.m_rcPreCalc.OffsetRect(
						bHorz ? nShiftDesired : 0,
						bHorz ? 0 : nShiftDesired
						);
			} // if( pBar == pBarSlide )
			dbol.Add( olid );
		} // if( pBar != NULL && ...
		if( pBar == NULL || nBar == (nCountOfBars-1) )
			break;
	} // for( int nBar = nFirstBarPos; nBar < nCountOfBars; nBar++ )

	ASSERT( dbol.GetSize() != 0 );

int nSubRowCount = 0;
bool bFullyOccupiedLayout = false;
BOOL bLayoutQueryOld = m_bLayoutQuery;
CSize sizeFakeFixedOld( sizeFakeFixed ), sizeMaxOld( sizeMax );
CPoint ptOld( pt );
AFX_SIZEPARENTPARAMS layout;
	layout.hDWP = NULL;
	_CalcFixedRowLayout(
		sizeFakeFixed,
		sizeMax,
		pt,
		bHorz,
		layout,
		dbol,
		&nSubRowCount,
		&bFullyOccupiedLayout
		);
	m_bLayoutQuery = bLayoutQueryOld;
	ASSERT( nSubRowCount >= 1 );
	if( m_bLayoutQuery )
		return;

	ASSERT( (nCountOfBars - nFirstBarPos) > 0 );

	sizeFakeFixed = sizeFakeFixedOld;
	sizeMax = sizeMaxOld;
	pt = ptOld;
	nCountOfBars = dbol.GetSize();
	ASSERT( nCountOfBars > 0 );
	layout.hDWP =
		::BeginDeferWindowPos(nCountOfBars);

// reasonable row shift offset
const int nRsOffset = 1; //2;

	if( nCountOfBars > 1 && pAffixmentData != NULL )
	{
		int nSlideBarIdxInArray = -1;
		for( nBar = 0; nBar < nCountOfBars; nBar++ )
		{
			OuterLayoutItemData & olid = dbol.ElementAt( nBar );
			ASSERT_VALID( olid.m_pBar );
			ASSERT_KINDOF( CControlBar, olid.m_pBar );
			ASSERT( olid.m_bVisible );
			if( olid.m_pBar == pBarSlide )
			{
				ASSERT( nSlideBarIdxInArray < 0 );
				nSlideBarIdxInArray = nBar;
				break;
			}
		} // for( nBar = 0; nBar < nCountOfBars; nBar++ )
		ASSERT( 0 <= nSlideBarIdxInArray && nSlideBarIdxInArray < nCountOfBars );
		OuterLayoutItemData & olid =
			dbol.ElementAt( nSlideBarIdxInArray );
		ASSERT_VALID( olid.m_pBar );
		ASSERT_KINDOF( CControlBar, olid.m_pBar );
		ASSERT( olid.m_bVisible );

		bool bTrySwapping = bFullyOccupiedLayout; // true; (+ v.2.22)
		bool bUpAffxOnSwapping = true;
		if(		bFullyOccupiedLayout
			&&	(nSubRowCount == 1)
			)
		{ // if can analyze resizing in row
			ASSERT( pAffixmentData != NULL );
			if( nSlideBarIdxInArray > 0 )
			{ // do resizing pre-affixment, do not resize first in row
				CSize sizeBarCalc = olid.m_rcPreCalc.Size();
				if( nShiftDesired > 0 )
				{
					//ASSERT( (!bHorz) || sizeBarCalc.cx >= olid.m_sizeBarMin.cx );
					//ASSERT( ( bHorz) || sizeBarCalc.cy >= olid.m_sizeBarMin.cy );
					int nExtentPossibleByBar = bHorz
						? (sizeBarCalc.cx - olid.m_sizeBarMin.cx)
						: (sizeBarCalc.cy - olid.m_sizeBarMin.cy)
						;
					nExtentPossibleByBar =
						min( nExtentPossibleByBar, nShiftDesired );
					if( nExtentPossibleByBar > 0 )
					{
						bTrySwapping = false;
						if( pAffixmentData->m_nAffixmentWeight != 1 )
							_AffixmentBringToTop( pBarSlide );
						if( bHorz )
						{
							int nNewAffixment = sizeBarCalc.cx - nExtentPossibleByBar;
							if( nNewAffixment > olid.m_sizeCalcDynamic.cx )
								nNewAffixment = olid.m_sizeCalcDynamic.cx;
							if( pAffixmentData->m_sizeCompressed.cx != nNewAffixment )
								pAffixmentData->m_sizeCompressed.cx = nNewAffixment;
							else
								bTrySwapping = true;
						} // if( bHorz )
						else
						{
							int nNewAffixment = sizeBarCalc.cy - nExtentPossibleByBar;
							if( nNewAffixment > olid.m_sizeCalcDynamic.cy )
								nNewAffixment = olid.m_sizeCalcDynamic.cy;
							if( pAffixmentData->m_sizeCompressed.cy != nNewAffixment )
								pAffixmentData->m_sizeCompressed.cy = nNewAffixment;
							else
								bTrySwapping = true;
						} // else from if( bHorz )
					} // if( nExtentPossibleByBar > 0 )
				} // if( nShiftDesired > 0 )
				else
				{
					//ASSERT( (!bHorz) || sizeBarCalc.cx >= olid.m_sizeBarMin.cx );
					//ASSERT( ( bHorz) || sizeBarCalc.cy >= olid.m_sizeBarMin.cy );
					int nExtentPossibleByBar = bHorz
						? (olid.m_sizeCalcDynamic.cx - sizeBarCalc.cx)
						: (olid.m_sizeCalcDynamic.cy - sizeBarCalc.cy)
						;
					nExtentPossibleByBar =
						min( nExtentPossibleByBar, (-nShiftDesired) );
					ASSERT( nExtentPossibleByBar >= 0 );
					if( nExtentPossibleByBar > 0 )
					{
						bTrySwapping = false;
						if( pAffixmentData->m_nAffixmentWeight != 1 )
							_AffixmentBringToTop( pBarSlide );
						if( bHorz )
						{
							int nNewAffixment = sizeBarCalc.cx + nExtentPossibleByBar;
							if( nNewAffixment > olid.m_sizeCalcDynamic.cx )
								nNewAffixment = olid.m_sizeCalcDynamic.cx;
							if( pAffixmentData->m_sizeCompressed.cx != nNewAffixment )
								pAffixmentData->m_sizeCompressed.cx = nNewAffixment;
							else
								bTrySwapping = true;
						}
						else
						{
							int nNewAffixment = sizeBarCalc.cy + nExtentPossibleByBar;
							if( nNewAffixment > olid.m_sizeCalcDynamic.cy )
								nNewAffixment = olid.m_sizeCalcDynamic.cy;
							if( pAffixmentData->m_sizeCompressed.cy != nNewAffixment )
								pAffixmentData->m_sizeCompressed.cy = nNewAffixment;
							else
								bTrySwapping = true;
						}
					} // if( nExtentPossibleByBar > 0 )
				} // else from if( nShiftDesired > 0 )
			} // do resizing pre-affixment, do not resize first in row
			else
				bUpAffxOnSwapping = false;
		}  // if can analyze resizing in row
		else if( (!bTrySwapping) && (nSubRowCount == 1) )
		{ // analyze left/right free space between bars is available (+ v.2.22)
			ASSERT( !bFullyOccupiedLayout );
			ASSERT( 0 <= nSlideBarIdxInArray && nSlideBarIdxInArray < nCountOfBars );
			int nStartBar = nSlideBarIdxInArray + 1;
			int nEndBar = nCountOfBars - 1;
			if( nShiftDesired < 0 )
			{
				nStartBar = 0;
				nEndBar = nSlideBarIdxInArray;
			}
			for( int nBarXSP = nStartBar; nBarXSP <= nEndBar; nBarXSP++ )
			{
				OuterLayoutItemData & olid = dbol.ElementAt( nBarXSP );
				ASSERT_VALID( olid.m_pBar );
				ASSERT_KINDOF( CControlBar, olid.m_pBar );
				ASSERT( olid.m_bVisible );
				int nFreeBefore = 0;
				CRect rcBarLocal( olid.m_rcReal );
				if( nBarXSP == 0 )
					nFreeBefore = bHorz ? rcBarLocal.left : rcBarLocal.top;
				else
				{
					OuterLayoutItemData & olidPrev = dbol.ElementAt( nBarXSP-1 );
					ASSERT_VALID( olidPrev.m_pBar );
					ASSERT_KINDOF( CControlBar, olidPrev.m_pBar );
					ASSERT( olidPrev.m_bVisible );
					CRect rcBarLocalPrev( olidPrev.m_rcReal );
					nFreeBefore = bHorz
						? (rcBarLocal.left - rcBarLocalPrev.right)
						: (rcBarLocal.top - rcBarLocalPrev.bottom)
						;
				} // else from if( nBarXSP == 0 )
				if( nFreeBefore < 0 )
					nFreeBefore = 0;
				if( nShiftDesired < 0 && nFreeBefore == 0 )
				{
					if( nBarXSP == nEndBar )
					{
						bTrySwapping = true;
						break;
					}
					continue;
				} // if( nShiftDesired < 0  )
				if( nShiftDesired > 0 && nFreeBefore > 0 )
					break; // no swapping to right/bottom (have some space to slide)
				if( nBarXSP == nEndBar && nShiftDesired > 0 )
				{
					CRect rcThisDocker;
					GetClientRect( &rcThisDocker );
					ASSERT( rcThisDocker.left == 0 && rcThisDocker.top == 0 );
					if( rcThisDocker.right <= 0 || rcThisDocker.bottom <= 0 )
						break; // empty space for anything
					int nFreeAfter = bHorz
						? (rcThisDocker.right - rcBarLocal.right)
						: (rcThisDocker.bottom - rcBarLocal.bottom)
						;
					if( nFreeAfter <= 0 )
					{
						bTrySwapping = true;
						break;
					}
				} // if( nBarXSP == nEndBar && nShiftDesired > 0 )
			} // for( int nBarXSP = nStartBar; nBarXSP <= nEndBar; nBarXSP++ )
		} // analyze left/right free space between bars is available (+ v.2.22)

		if( bTrySwapping )
		{
			if( bUpAffxOnSwapping )
				_AffixmentBringToTop( pBarSlide );
			pAffixmentData->m_rcAffixment = olid.m_rcPreCalc;
			
			if( nShiftDesired > 0 )
			{
				if( nSlideBarIdxInArray != (nCountOfBars-1) )
				{
					OuterLayoutItemData & olid2 =
						dbol.ElementAt( nSlideBarIdxInArray + 1 );
					ASSERT_VALID( olid2.m_pBar );
					ASSERT_KINDOF( CControlBar, olid2.m_pBar );
					ASSERT( olid2.m_bVisible );
					CExtControlBar * pExtBar2 =
						DYNAMIC_DOWNCAST(
							CExtControlBar,
							olid2.m_pBar
							);
					if( pExtBar2 != NULL )
					{
						CExtControlBar::InternalAffixmentData * pAffixmentData2 =
								pExtBar2->_AffixmentGetOuter();
						if( pAffixmentData2 != NULL )
						{
							int nPosAffx2 = bHorz
								? pAffixmentData2->m_rcAffixment.left
								: pAffixmentData2->m_rcAffixment.top
								;
							int nPosReal2 = bHorz
								? olid2.m_rcPreCalc.left
								: olid2.m_rcPreCalc.top
								;
							int n1stExtent = bHorz
								? olid.m_rcPreCalc.Width()
								: olid.m_rcPreCalc.Height()
								;
//							nPosReal2 += nRsOffset;
//							nPosReal2 += nShiftDesired;
							if( (nPosReal2 - n1stExtent) > nPosAffx2 )
								_SwapInRowWithAffixment(
									dbol,
									nSlideBarIdxInArray,
									nSlideBarIdxInArray + 1
									);
							else
							{
								int nPosReal = bHorz
									? olid.m_rcPreCalc.left
									: olid.m_rcPreCalc.top
									;
								int n2ndExtent = bHorz
									? olid2.m_rcPreCalc.Width()
									: olid2.m_rcPreCalc.Height()
									;
								if(		( (nPosReal2+n2ndExtent)
										- (nPosReal+n1stExtent)
										- nShiftDesired
										- nRsOffset
										)
										<= 0
									)
									_SwapInRowWithAffixment(
										dbol,
										nSlideBarIdxInArray,
										nSlideBarIdxInArray + 1
										);
							}
						} // if( pAffixmentData2 != NULL )
					} // if( pExtBar2 != NULL )
				} // if( nSlideBarIdxInArray != (nCountOfBars-1) )
			} // if( nShiftDesired > 0 )
			else
			{
				if( nSlideBarIdxInArray != 0 )
				{
					OuterLayoutItemData & olid2 =
						dbol.ElementAt( nSlideBarIdxInArray - 1 );
					ASSERT_VALID( olid2.m_pBar );
					ASSERT_KINDOF( CControlBar, olid2.m_pBar );
					ASSERT( olid2.m_bVisible );
					CExtControlBar * pExtBar2 =
						DYNAMIC_DOWNCAST(
							CExtControlBar,
							olid2.m_pBar
							);
					if( pExtBar2 != NULL )
					{
						CExtControlBar::InternalAffixmentData * pAffixmentData2 =
								pExtBar2->_AffixmentGetOuter();
						if( pAffixmentData2 != NULL )
						{
							int nPosReal = bHorz
								? olid.m_rcPreCalc.left
								: olid.m_rcPreCalc.top
								;
							int nPosAffx2 = bHorz
								? pAffixmentData2->m_rcAffixment.left
								: pAffixmentData2->m_rcAffixment.top
								;
//							nPosReal -= nRsOffset;
//							nPosReal += nShiftDesired;
							if(	nPosReal <= nPosAffx2 )
								_SwapInRowWithAffixment(
									dbol,
									nSlideBarIdxInArray - 1,
									nSlideBarIdxInArray
									);
							else
							{
								int nPosReal2 = bHorz
									? olid2.m_rcPreCalc.left
									: olid2.m_rcPreCalc.top
									;
//								int n1stExtent = bHorz
//									? olid.m_rcPreCalc.Width()
//									: olid.m_rcPreCalc.Height()
//									;
//								int n2ndExtent = bHorz
//									? olid2.m_rcPreCalc.Width()
//									: olid2.m_rcPreCalc.Height()
//									;
								if(		( (nPosReal /*+n1stExtent*/ )
										- (nPosReal2 /*+n2ndExtent*/ )
										+ nShiftDesired
										- nRsOffset
										)
										<= 0
									)
									_SwapInRowWithAffixment(
										dbol,
										nSlideBarIdxInArray - 1,
										nSlideBarIdxInArray
										);
							}
						} // if( pAffixmentData2 != NULL )
					} // if( pExtBar2 != NULL )
				} // if( nSlideBarIdxInArray != 0 )
			} // else from if( nShiftDesired > 0 )
		} // if( bTrySwapping )
		else
		{
			if( p_bInplaceResizing != NULL )
				*p_bInplaceResizing = bFullyOccupiedLayout; //true; (+ v.2.22)
		} // else from if( bTrySwapping )
	} // if( nCountOfBars > 1 && pAffixmentData != NULL )

	_CalcFixedRowLayout(
		sizeFakeFixed,
		sizeMax,
		pt,
		bHorz,
		layout,
		dbol
		);
	ASSERT( layout.hDWP != NULL );
	if( layout.hDWP != NULL )
	{
		VERIFY( ::EndDeferWindowPos(layout.hDWP) );
	}

	for( nBar = 0; nBar < dbol.GetSize(); nBar++ )
	{
		OuterLayoutItemData & olid =
			dbol.ElementAt( nBar );
		ASSERT_VALID( olid.m_pBar );
		ASSERT_KINDOF( CControlBar, olid.m_pBar );
		if( !olid.m_bVisible )
			continue;
		CExtControlBar * pExtBar =
			DYNAMIC_DOWNCAST( CExtControlBar, olid.m_pBar );
		if( pExtBar == NULL )
			continue;
		pExtBar->RedrawWindow(
			NULL, NULL,
			RDW_INVALIDATE|RDW_UPDATENOW
				|RDW_ERASE|RDW_ERASENOW
				|RDW_ALLCHILDREN|RDW_NOFRAME
			);
	} // for( nBar = 0; nBar < dbol.GetSize(); nBar++ )
}

void CExtDockOuterBar::_SwapInRowWithAffixment(
	CExtDockOuterBar::dockbar_outer_layout_t & dbol,
	int nIdxLess,
	int nIdxGreater
	)
{
	ASSERT( dbol.GetSize() > 1 );
	ASSERT( 0 <= nIdxLess && nIdxLess <= dbol.GetSize() );
	ASSERT( 0 <= nIdxGreater && nIdxGreater <= dbol.GetSize() );
	ASSERT( (nIdxLess+1) == nIdxGreater );

OuterLayoutItemData & olid1 = dbol.ElementAt( nIdxLess );
	ASSERT_VALID( olid1.m_pBar );
	ASSERT_KINDOF( CControlBar, olid1.m_pBar );
	ASSERT( olid1.m_bVisible );
CControlBar * pBar1 = olid1.m_pBar;
int nPosInternal1 = FindBar( pBar1 );
	ASSERT( 0 < nPosInternal1 && nPosInternal1 < m_arrBars.GetSize() );

OuterLayoutItemData & olid2 = dbol.ElementAt( nIdxGreater );
	ASSERT_VALID( olid2.m_pBar );
	ASSERT_KINDOF( CControlBar, olid2.m_pBar );
	ASSERT( olid2.m_bVisible );
CControlBar * pBar2 = olid2.m_pBar;
int nPosInternal2 = FindBar( pBar2 );
	ASSERT( 0 < nPosInternal2 && nPosInternal2 < m_arrBars.GetSize() );

	ASSERT( pBar1 != pBar2 );
	ASSERT( nPosInternal1 != nPosInternal2 );

	m_arrBars[ nPosInternal1 ] = pBar2;
	m_arrBars[ nPosInternal2 ] = pBar1;

OuterLayoutItemData olid = dbol.ElementAt( nIdxGreater );
	dbol.RemoveAt( nIdxGreater );
	dbol.InsertAt( nIdxLess, olid );
}

bool CExtDockOuterBar::_ReDockToNewRow(
	CControlBar * pBarSlide,
	MfcControlBarVector_t & vRow,
	int nShiftDesired
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( pBarSlide );
	ASSERT( pBarSlide->m_pDockBar == this );
	ASSERT( pBarSlide->IsVisible() );
int nCountOfBars = vRow.GetSize();
	ASSERT( nCountOfBars > 0 );

UINT nDockBarID = GetDlgCtrlID();
	ASSERT_DOCKBAR_DLGCTRLID_DOCKED( nDockBarID );
bool bHorz = 
		(	nDockBarID == AFX_IDW_DOCKBAR_TOP
		||	nDockBarID == AFX_IDW_DOCKBAR_BOTTOM )
		? TRUE : FALSE;

CRect rcBarSlide, rcBarSlideOrg, rcBarInsertBefore;
	pBarSlide->GetWindowRect( &rcBarSlide );
	ScreenToClient( &rcBarSlide );
	rcBarSlideOrg = rcBarSlide;
int nExtentBarSlideMinPossible = 0;
	if( pBarSlide->IsKindOf(RUNTIME_CLASS(CExtControlBar)) )	
	{
		CSize sizeBarSlideMinPossible =
			((CExtControlBar*)pBarSlide)->_CalcDesiredMinOuterSize(
				bHorz ? TRUE : FALSE );
		nExtentBarSlideMinPossible = bHorz
			? sizeBarSlideMinPossible.cx
			: sizeBarSlideMinPossible.cy
			;
	} // if( pBarSlide->IsKindOf(RUNTIME_CLASS(CExtControlBar)) )	
	else
	{
		CRect rcBar;
		pBarSlide->GetWindowRect( &rcBar );
		nExtentBarSlideMinPossible = bHorz
			? rcBar.Width()
			: rcBar.Height()
			;
	} // else from if( pBarSlide->IsKindOf(RUNTIME_CLASS(CExtControlBar)) )	
int nExtentRowMinPossible = 0;
	for( int nBar = 0; nBar < nCountOfBars; nBar++ )
	{
		CControlBar * pBar = vRow[nBar];
		ASSERT_VALID( pBar );
		ASSERT_KINDOF( CControlBar, pBar );
		ASSERT( pBar->IsVisible() );
		ASSERT( pBar != pBarSlide );
		int nExtentBarMinPossible = 0;
		if( pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar)) )	
		{
			CSize sizeBarMinPossible =
				((CExtControlBar*)pBar)->_CalcDesiredMinOuterSize(
					bHorz ? TRUE : FALSE );
			nExtentBarMinPossible = bHorz
				? sizeBarMinPossible.cx
				: sizeBarMinPossible.cy
				;
		} // if( pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar)) )	
		else
		{
			CRect rcBar;
			pBar->GetWindowRect( &rcBar );
			nExtentBarMinPossible = bHorz
				? rcBar.Width()
				: rcBar.Height()
				;
		} // else from if( pBar->IsKindOf(RUNTIME_CLASS(CExtControlBar)) )	
		nExtentRowMinPossible += nExtentBarMinPossible;
	} // for( int nBar = 0; nBar < nCountOfBars; nBar++ )

CRect rcThisDockerClient;
	GetClientRect( &rcThisDockerClient );
int nMaxExtent = bHorz
		? rcThisDockerClient.Width()
		: rcThisDockerClient.Height()
		;
int nExtentRest = nMaxExtent - nExtentRowMinPossible;
	if( nExtentRest < nExtentBarSlideMinPossible )
		return false;

int nSlidePosStart = bHorz
		? rcBarSlide.left
		: rcBarSlide.top
		;
	nSlidePosStart += nShiftDesired;
	if( nSlidePosStart < 0 )
	{
		nShiftDesired += nSlidePosStart;
		nSlidePosStart = 0;
	}
CControlBar * pBarInsertBefore = NULL;
bool bAppendMode = false;
	for( nBar = 0; nBar < nCountOfBars; nBar++ )
	{
		CControlBar * pBar = vRow[nBar];
		ASSERT_VALID( pBar );
		ASSERT_KINDOF( CControlBar, pBar );
		ASSERT( pBar->IsVisible() );
		CRect rcBar;
		pBar->GetWindowRect( &rcBar );
		ScreenToClient( &rcBar );
		int nBarInRowPosStart = bHorz
			? rcBar.left
			: rcBar.top
			;
		if( nSlidePosStart <= nBarInRowPosStart )
		{
			rcBarInsertBefore = rcBar;
			pBarInsertBefore = pBar;
		} // if( nSlidePosStart <= nBarInRowPosStart )
		else
		{
			int nBarInRowPosEnd = bHorz
				? rcBar.right
				: rcBar.bottom
				;
			if( nSlidePosStart <= nBarInRowPosEnd )
			{
				int nBarInRowPosMid =
					(nBarInRowPosEnd + nBarInRowPosStart) / 2;
				if( nSlidePosStart <= nBarInRowPosMid )
				{
					rcBarInsertBefore = rcBar;
					pBarInsertBefore = pBar;
					break;
				}
				bAppendMode = true;
				break;
			} // if( nSlidePosStart <= nBarInRowPosEnd )
			else
			{
				if( pBarInsertBefore != NULL )
					break;
				bAppendMode = true;
			} // else from if( nSlidePosStart <= nBarInRowPosEnd )
		} // else from if( nSlidePosStart <= nBarInRowPosStart )
	} // for( nBar = 0; nBar < nCountOfBars; nBar++ )

	if(		pBarInsertBefore == NULL
		&&	(!bAppendMode)
		)
		return false;

int nBarPos = FindBar( pBarSlide );
	ASSERT( 0 < nBarPos && nBarPos < m_arrBars.GetSize() );
	if(		m_arrBars[nBarPos-1] == NULL
		&&	m_arrBars[nBarPos+1] == NULL
		)
		m_arrBars.RemoveAt( nBarPos+1 );
	m_arrBars.RemoveAt( nBarPos );

	if( pBarInsertBefore != NULL )
	{
		if( bHorz )
		{
			rcBarSlide.OffsetRect(
				nShiftDesired,
				rcBarInsertBefore.top - rcBarSlide.top
				);
			if( rcBarInsertBefore.left < rcBarSlide.left )
				rcBarSlide.OffsetRect(
					rcBarInsertBefore.left - rcBarSlide.left,
					0
					);
		} // if( bHorz )
		else
		{
			rcBarSlide.OffsetRect(
				rcBarInsertBefore.left - rcBarSlide.left,
				nShiftDesired
				);
			if( rcBarInsertBefore.top < rcBarSlide.top )
				rcBarSlide.OffsetRect(
					0,
					rcBarInsertBefore.top - rcBarSlide.top
					);
		} // else from if( bHorz )
		nBarPos = FindBar( pBarInsertBefore );
		ASSERT( 0 < nBarPos && nBarPos < m_arrBars.GetSize() );
		m_arrBars.InsertAt( nBarPos, pBarSlide );
		ASSERT_VALID( this );
	} // if( pBarInsertBefore != NULL )
	else
	{
		ASSERT( bAppendMode );
		pBarInsertBefore = vRow[nCountOfBars-1];
		ASSERT_VALID( pBarInsertBefore );
		ASSERT_KINDOF( CControlBar, pBarInsertBefore );
		ASSERT( pBarInsertBefore->IsVisible() );
		pBarInsertBefore->GetWindowRect( &rcBarInsertBefore );
		ScreenToClient( &rcBarInsertBefore );
		if( bHorz )
		{
			rcBarSlide.OffsetRect(
				nShiftDesired,
				rcBarInsertBefore.top - rcBarSlide.top
				);
			if( rcBarSlide.left < rcBarInsertBefore.right )
				rcBarSlide.OffsetRect(
					rcBarInsertBefore.right - rcBarSlide.left,
					0
					);
		} // if( bHorz )
		else
		{
			rcBarSlide.OffsetRect(
				rcBarInsertBefore.left - rcBarSlide.left,
				nShiftDesired
				);
			if( rcBarSlide.top < rcBarInsertBefore.bottom )
				rcBarSlide.OffsetRect(
					0,
					rcBarInsertBefore.bottom - rcBarSlide.top
					);
		} // else from if( bHorz )
		nBarPos = FindBar( pBarInsertBefore );
		ASSERT( 0 < nBarPos && nBarPos < m_arrBars.GetSize() );
		m_arrBars.InsertAt( nBarPos+1, pBarSlide );
		ASSERT_VALID( this );
	} // else from if( pBarInsertBefore != NULL )

	if( rcBarSlideOrg != rcBarSlide )
		pBarSlide->SetWindowPos(
			NULL,
			rcBarSlide.left, rcBarSlide.top,
			rcBarSlide.Width(), rcBarSlide.Height(),
			SWP_NOZORDER|SWP_NOACTIVATE
				|SWP_NOSENDCHANGING
				|SWP_NOREDRAW|SWP_NOCOPYBITS
			);

	return true;
}

void CExtDockOuterBar::_AlignSubRowAffixmentHW(
	bool bHorz,
	CExtDockOuterBar::dockbar_outer_layout_t & dbol,
	int nSubRowStartPos,
	int nSubRowEndPos
	)
{
	ASSERT_VALID(this);
	ASSERT( dbol.GetSize() > 0 );
	ASSERT( nSubRowStartPos <= nSubRowEndPos );
	ASSERT( 0 <= nSubRowStartPos && nSubRowStartPos < dbol.GetSize() );
	ASSERT( 0 <= nSubRowEndPos   && nSubRowEndPos < dbol.GetSize() );
	if( nSubRowStartPos == nSubRowEndPos )
		return;

int nIdxToAlignFirst = -1;
int nIdxToAlignLast = -1;
int nTotalAffixmentExtentHW = -1;
	for( int nBar = nSubRowStartPos; nBar <= nSubRowEndPos; nBar++ )
	{
		OuterLayoutItemData & olid = dbol.ElementAt( nBar );
		ASSERT_VALID( olid.m_pBar );
		ASSERT_KINDOF( CControlBar, olid.m_pBar );
		ASSERT( olid.m_bVisible );
		CExtControlBar * pExtBar =
			DYNAMIC_DOWNCAST(
				CExtControlBar,
				olid.m_pBar
				);
		if( pExtBar == NULL )
			continue;
		if( !pExtBar->_AffixmentIsAlignedHW() )
			continue;
		ASSERT( pExtBar->_AffixmentGetOuter() != NULL );
		int nBarAffixmentExtentHW = bHorz
			? olid.m_rcPreCalc.Height()
			: olid.m_rcPreCalc.Width()
			;
		nTotalAffixmentExtentHW =
			max( nTotalAffixmentExtentHW, nBarAffixmentExtentHW );
		if( nIdxToAlignFirst < 0 )
		{
			ASSERT( nIdxToAlignLast < 0 );
			nIdxToAlignFirst = nIdxToAlignLast = nBar;
			continue;
		}
		ASSERT( nIdxToAlignFirst >= nSubRowStartPos );
		ASSERT( nIdxToAlignFirst <= nIdxToAlignLast );
		nIdxToAlignLast = nBar;
	} // for( int nBar = nSubRowStartPos; nBar <= nSubRowEndPos; nBar++ )
	ASSERT( nIdxToAlignFirst <= nIdxToAlignLast );
	if(		nTotalAffixmentExtentHW < 0
		||	nIdxToAlignFirst == nIdxToAlignLast
		)
		return;
	ASSERT( nSubRowStartPos <= nIdxToAlignFirst && nIdxToAlignFirst <= nSubRowEndPos );
	ASSERT( nSubRowStartPos <= nIdxToAlignLast  && nIdxToAlignLast  <= nSubRowEndPos );
	for( nBar = nIdxToAlignFirst; nBar <= nIdxToAlignLast; nBar++ )
	{
		OuterLayoutItemData & olid = dbol.ElementAt( nBar );
		ASSERT_VALID( olid.m_pBar );
		ASSERT_KINDOF( CControlBar, olid.m_pBar );
		ASSERT( olid.m_bVisible );
		CExtControlBar * pExtBar =
			DYNAMIC_DOWNCAST(
				CExtControlBar,
				olid.m_pBar
				);
		if( pExtBar == NULL )
			continue;
		if( !pExtBar->_AffixmentIsAlignedHW() )
			continue;
		ASSERT( pExtBar->_AffixmentGetOuter() != NULL );
		CRect & rcPreCalc = olid.m_rcPreCalc;
		if( bHorz )
			rcPreCalc.bottom = rcPreCalc.top + nTotalAffixmentExtentHW;
		else
			rcPreCalc.right = rcPreCalc.left + nTotalAffixmentExtentHW;
	} // for( nBar = nIdxToAlignFirst; nBar <= nIdxToAlignLast; nBar++ )
}

void CExtDockOuterBar::_CalcAffixmentOrderVector(
	bool bHorz,
	AffixmentOrderVector_t & arrAffixmentOrder,
	CExtDockOuterBar::dockbar_outer_layout_t & dbol,
	bool bResetAffixmentDataIfNeeded, // = false
	int nSubRowStartPos, // = 0
	int nSubRowEndPos // = -1
	)
{
	ASSERT_VALID(this);
	if( arrAffixmentOrder.GetSize() > 0 )
		arrAffixmentOrder.RemoveAll();
	if( dbol.GetSize() == 0 )
		return;
	ASSERT( 0 <= nSubRowStartPos && nSubRowStartPos < dbol.GetSize() );
	if( nSubRowEndPos < 0 )
		nSubRowEndPos = dbol.GetSize() - 1;
	ASSERT( 0 <= nSubRowEndPos   && nSubRowEndPos < dbol.GetSize() );
	ASSERT( nSubRowStartPos <= nSubRowEndPos );
int nResetAffixmentWeight =
		dbol.GetSize() + nSubRowStartPos + 1;
	for( int nBar = nSubRowStartPos; nBar <= nSubRowEndPos; nBar++ )
	{
		OuterLayoutItemData & olid = dbol.ElementAt( nBar );
		ASSERT_VALID( olid.m_pBar );
		ASSERT_KINDOF( CControlBar, olid.m_pBar );
		ASSERT( olid.m_bVisible );
		CExtControlBar * pExtBar =
			DYNAMIC_DOWNCAST(
				CExtControlBar,
				olid.m_pBar
				);
		if( pExtBar == NULL )
		{
			arrAffixmentOrder.Add( nBar );
			continue;
		}
		CExtControlBar::InternalAffixmentData * pAffixmentData =
				pExtBar->_AffixmentGetOuter();
		if( pAffixmentData == NULL )
		{
			arrAffixmentOrder.Add( nBar );
			continue;
		}
		if( pAffixmentData->IsEmpty() )
		{
			if( bResetAffixmentDataIfNeeded )
				pAffixmentData->m_nAffixmentWeight = nResetAffixmentWeight++;
			else
			{
				arrAffixmentOrder.Add( nBar );
				continue;
			} // else from if( bResetAffixmentDataIfNeeded )
		} // if( pAffixmentData->IsEmpty() )
		if( pAffixmentData->m_rcAffixment.IsRectEmpty() )
		{
			if( bResetAffixmentDataIfNeeded )
				pAffixmentData->m_rcAffixment = olid.m_rcReal;
			else
			{
				arrAffixmentOrder.Add( nBar );
				continue;
			} // else from if( bResetAffixmentDataIfNeeded )
		} // if( pAffixmentData->m_rcAffixment.IsRectEmpty() )
		if( bResetAffixmentDataIfNeeded )
		{
			if( bHorz )
			{
				if( pAffixmentData->m_sizeCompressed.cx == 0 )
					pAffixmentData->m_sizeCompressed.cx =
						olid.m_rcReal.Width();
				if( pAffixmentData->m_sizeCompressed.cx > olid.m_sizeCalcDynamic.cx )
					pAffixmentData->m_sizeCompressed.cx = olid.m_sizeCalcDynamic.cx;
			} // if( bHorz )
			else
			{
				if( pAffixmentData->m_sizeCompressed.cy == 0 )
					pAffixmentData->m_sizeCompressed.cy =
						olid.m_rcReal.Height();
				if( pAffixmentData->m_sizeCompressed.cy > olid.m_sizeCalcDynamic.cy )
					pAffixmentData->m_sizeCompressed.cy = olid.m_sizeCalcDynamic.cy;
			} // else from if( bHorz )
		} // if( bResetAffixmentDataIfNeeded )
		if( arrAffixmentOrder.GetSize() == 0 )
		{
			arrAffixmentOrder.Add( nBar );
			continue;
		}
		int nReviewCount = nBar - nSubRowStartPos;
		ASSERT( nReviewCount > 0 );
		ASSERT( arrAffixmentOrder.GetSize() == nReviewCount );
		for( int nOrder = 0; nOrder < nReviewCount; nOrder++ )
		{
			int nBarAtOrder = arrAffixmentOrder[nOrder];
			ASSERT( nBarAtOrder < nBar );
			OuterLayoutItemData & olid2 = dbol.ElementAt( nBarAtOrder );
			ASSERT_VALID( olid2.m_pBar );
			ASSERT( olid.m_pBar != olid2.m_pBar );
			ASSERT_KINDOF( CControlBar, olid2.m_pBar );
			ASSERT( olid2.m_bVisible );

			CExtControlBar * pExtBar2 =
				DYNAMIC_DOWNCAST(
					CExtControlBar,
					olid2.m_pBar
					);
			if( pExtBar2 == NULL )
			{
				arrAffixmentOrder.InsertAt( nOrder, nBar );
				break;
			}
			CExtControlBar::InternalAffixmentData * pAffixmentData2 =
					pExtBar2->_AffixmentGetOuter();
			if( pAffixmentData2 == NULL )
			{
				arrAffixmentOrder.InsertAt( nOrder, nBar );
				break;
			}
			ASSERT( !pAffixmentData2->IsEmpty() );
// 	TO FIX: affixment recalc afrer tooggling docked/floating state
//			ASSERT(
//				pAffixmentData2->m_nAffixmentWeight
//					!= pAffixmentData->m_nAffixmentWeight
//				);
			if(	pAffixmentData2->m_nAffixmentWeight
					> pAffixmentData->m_nAffixmentWeight
				)
			{
				arrAffixmentOrder.InsertAt( nOrder, nBar );
				break;
			}
			if( nOrder == (nReviewCount - 1) )
			{
				arrAffixmentOrder.Add( nBar );
				break;
			}
		} // for( int nOrder = 0; nOrder < nReviewCount; nOrder++ )
		ASSERT( arrAffixmentOrder.GetSize() == (nReviewCount + 1) );
	} // for( int nBar = nSubRowStartPos; nBar <= nSubRowEndPos; nBar++ )
	ASSERT( arrAffixmentOrder.GetSize() == (nSubRowEndPos-nSubRowStartPos+1) );
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect Foss Software Inc
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions