XTPDockingPaneSplitterContainer.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:23k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTPDockingPaneSplitterContainer.cpp : implementation of the CXTPDockingPaneSplitterContainer class.
  2. //
  3. // This file is a part of the XTREME DOCKINGPANE MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "Common/Resource.h"
  22. #include "Common/XTPDrawHelpers.h"
  23. #include "Common/XTPColorManager.h"
  24. #include "Common/XTPResourceManager.h"
  25. #include "XTPDockingPaneBase.h"
  26. #include "XTPDockingPaneLayout.h"
  27. #include "XTPDockingPaneManager.h"
  28. #include "XTPDockingPaneSplitterContainer.h"
  29. #include "XTPDockingPanePaintManager.h"
  30. #ifdef _DEBUG
  31. #define new DEBUG_NEW
  32. #undef THIS_FILE
  33. static char THIS_FILE[] = __FILE__;
  34. #endif
  35. CXTPDockingPaneSplitterWnd::CXTPDockingPaneSplitterWnd()
  36. {
  37. m_hCursor = 0;
  38. m_pFirst = 0;
  39. m_pSecond = 0;
  40. m_pContainer = 0;
  41. m_pManager = 0;
  42. m_bHoriz = FALSE;
  43. }
  44. void CXTPDockingPaneSplitterWnd::Create(CXTPDockingPaneManager* pManager, BOOL bHoriz)
  45. {
  46. m_bHoriz = bHoriz;
  47. m_pManager = pManager;
  48. CWnd::Create(_T("XTPDockingPaneSplitter"), _T("Splitter"), WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, CRect(0, 0, 0, 0), pManager->GetSite(), 0);
  49. }
  50. void CXTPDockingPaneSplitterWnd::Create(CXTPDockingPaneSplitterContainer* pContainer, CXTPDockingPaneBase* pFirst, CXTPDockingPaneBase* pSecond)
  51. {
  52. m_pFirst = pFirst;
  53. m_pSecond = pSecond;
  54. m_pContainer = pContainer;
  55. m_bHoriz = !m_pContainer->IsHoriz();
  56. m_pManager = m_pContainer->GetDockingPaneManager();
  57. m_hCursor = XTPResourceManager()->LoadCursor(pContainer->m_bHoriz ? XTP_IDC_HSPLITBAR :  XTP_IDC_VSPLITBAR);
  58. CWnd::Create(_T("XTPDockingPaneSplitter"), _T("Splitter"), WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, CRect(0, 0, 0, 0), pContainer->GetDockingSite(), 0);
  59. }
  60. CXTPDockingPaneSplitterWnd::~CXTPDockingPaneSplitterWnd()
  61. {
  62. if (m_hWnd) DestroyWindow();
  63. }
  64. BEGIN_MESSAGE_MAP(CXTPDockingPaneSplitterWnd, CWnd)
  65. ON_WM_PAINT()
  66. ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
  67. ON_WM_LBUTTONDOWN()
  68. ON_WM_ERASEBKGND()
  69. ON_WM_SETCURSOR()
  70. END_MESSAGE_MAP()
  71. BOOL CXTPDockingPaneSplitterWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  72. {
  73. if (m_pContainer == 0)
  74. return CWnd::OnSetCursor(pWnd, nHitTest, message);
  75. if (GetDockingPaneManager()->IsSplittersLocked())
  76. return CWnd::OnSetCursor(pWnd, nHitTest, message);
  77. CRect rcAvail, rcUnion;
  78. if (!GetAvailableRect(rcAvail, rcUnion))
  79. return CWnd::OnSetCursor(pWnd, nHitTest, message);
  80. ::SetCursor(m_hCursor);
  81. return TRUE;
  82. }
  83. void CXTPDockingPaneSplitterWnd::OnPaint()
  84. {
  85. CPaintDC dc(this);
  86. if (m_pManager)
  87. m_pManager->GetPaintManager()->DrawSplitter(&dc, this);
  88. }
  89. LRESULT CXTPDockingPaneSplitterWnd::OnPrintClient(WPARAM wParam, LPARAM /*lParam*/)
  90. {
  91. CDC* pDC = CDC::FromHandle((HDC)wParam);
  92. if (pDC && m_pManager)
  93. {
  94. m_pManager->GetPaintManager()->DrawSplitter(pDC, this);
  95. }
  96. return TRUE;
  97. }
  98. BOOL CXTPDockingPaneSplitterWnd::OnEraseBkgnd(CDC* /*pDC*/)
  99. {
  100. return TRUE;
  101. }
  102. BOOL CXTPDockingPaneSplitterWnd::IsHorizontal() const
  103. {
  104. return m_bHoriz;
  105. }
  106. void CXTPDockingPaneSplitterWnd::Reposition(CRect rc, CRect rcAvail)
  107. {
  108. int nSplitterSize = m_pContainer->GetDockingPaneManager()->GetPaintManager()->m_nSplitterSize;
  109. int nSplitterIndent = m_pContainer->GetDockingPaneManager()->GetPaintManager()->m_nSplitterIndent;
  110. if (m_pContainer->m_bHoriz)
  111. {
  112. double d = double(rc.left + nSplitterIndent - rcAvail.left) / rcAvail.Width();
  113. int nSum = m_pFirst->m_szDocking.cx + m_pSecond->m_szDocking.cx + nSplitterSize;
  114. m_pFirst->m_szDocking.cx = GetExStyle() & WS_EX_LAYOUTRTL ? nSum - int(d * nSum) - nSplitterSize : int(d * nSum);
  115. m_pSecond->m_szDocking.cx = nSum - m_pFirst->m_szDocking.cx - nSplitterSize;
  116. }
  117. else
  118. {
  119. double d = double(rc.top + nSplitterIndent - rcAvail.top) / rcAvail.Height();
  120. int nSum = m_pFirst->m_szDocking.cy + m_pSecond->m_szDocking.cy + nSplitterSize;
  121. m_pFirst->m_szDocking.cy = int(d * nSum);
  122. m_pSecond->m_szDocking.cy = nSum - m_pFirst->m_szDocking.cy - nSplitterSize;
  123. }
  124. }
  125. void CXTPDockingPaneSplitterContainer::NormalizeDockingSize()
  126. {
  127. if (m_bHoriz) m_szDocking.cx = m_rcWindow.Width();
  128. else m_szDocking.cy = m_rcWindow.Height();
  129. POSITION pos = GetHeadPosition();
  130. while (pos)
  131. {
  132. CXTPDockingPaneBase* pPane = GetNext(pos);
  133. if (!pPane->IsEmpty())
  134. {
  135. if (m_bHoriz) pPane->m_szDocking.cx = pPane->m_rcWindow.Width();
  136. else pPane->m_szDocking.cy = pPane->m_rcWindow.Height();
  137. }
  138. }
  139. }
  140. BOOL CXTPDockingPaneSplitterWnd::GetAvailableRect(CRect& rcAvail, CRect& rcUnion)
  141. {
  142. CXTPDockingPaneManager* pManager = GetDockingPaneManager();
  143. if (!pManager)
  144. return FALSE;
  145. int nSplitterSize = pManager->GetPaintManager()->m_nSplitterSize;
  146. BOOL bHoriz = m_pContainer->m_bHoriz;
  147. ASSERT(m_pFirst && m_pSecond);
  148. if (!m_pFirst || !m_pSecond)
  149. return FALSE;
  150. CRect rcFirst = m_pFirst->GetPaneWindowRect();
  151. CRect rcSecond = m_pSecond->GetPaneWindowRect();
  152. MINMAXINFO mmiFirst, mmiSecond;
  153. m_pFirst->GetMinMaxInfo(&mmiFirst);
  154. m_pSecond->GetMinMaxInfo(&mmiSecond);
  155. rcAvail.UnionRect(rcFirst, rcSecond);
  156. rcUnion = rcAvail;
  157. int nGap = pManager->m_nSplitterGap;
  158. if (bHoriz)
  159. {
  160. rcAvail.DeflateRect(max(mmiFirst.ptMinTrackSize.x, nGap), 0,
  161. max(mmiSecond.ptMinTrackSize.x + nSplitterSize, nGap), 0);
  162. if (rcUnion.Width() > mmiFirst.ptMaxTrackSize.x)
  163. rcAvail.right = min(rcAvail.right, rcUnion.left + mmiFirst.ptMaxTrackSize.x);
  164. if (rcUnion.Width() > mmiSecond.ptMaxTrackSize.x)
  165. rcAvail.left = max(rcAvail.left, rcUnion.right - mmiSecond.ptMaxTrackSize.x - nSplitterSize);
  166. if (rcAvail.left >= rcAvail.right)
  167. return FALSE;
  168. }
  169. else
  170. {
  171. rcAvail.DeflateRect(0, max(mmiFirst.ptMinTrackSize.y, nGap),
  172. 0, max(mmiSecond.ptMinTrackSize.y + nSplitterSize, nGap));
  173. if (rcUnion.Height() > mmiFirst.ptMaxTrackSize.y)
  174. rcAvail.bottom = min(rcAvail.bottom, rcUnion.top + mmiFirst.ptMaxTrackSize.y);
  175. if (rcUnion.Height() > mmiSecond.ptMaxTrackSize.y)
  176. rcAvail.top = max(rcAvail.top, rcUnion.bottom - mmiSecond.ptMaxTrackSize.y - nSplitterSize);
  177. if (rcAvail.top >= rcAvail.bottom)
  178. return FALSE;
  179. }
  180. return TRUE;
  181. }
  182. void CXTPDockingPaneSplitterWnd::OnLButtonDown(UINT /*nFlags*/, CPoint point)
  183. {
  184. if (m_pContainer == 0)
  185. return;
  186. CXTPDockingPaneManager* pManager = GetDockingPaneManager();
  187. if (pManager->IsSplittersLocked())
  188. return;
  189. CXTPWindowRect rc(this);
  190. CRect rcAvail, rcUnion;
  191. if (!GetAvailableRect(rcAvail, rcUnion))
  192. return;
  193. if (m_pContainer->OnAction(xtpPaneActionSplitterResizing))
  194. return;
  195. m_pContainer->NormalizeDockingSize();
  196. BOOL bHoriz = m_pContainer->m_bHoriz;
  197. //point = rc.TopLeft();
  198. ClientToScreen(&point);
  199. if (pManager->IsSplitterTrackerUsed())
  200. {
  201. CXTPSplitterTracker tracker;
  202. BOOL bAccept = tracker.Track(this, rcAvail, rc, point, bHoriz);
  203. if (bAccept)
  204. {
  205. Reposition(rc, rcUnion);
  206. pManager->RecalcFrameLayout(m_pContainer, TRUE);
  207. }
  208. }
  209. else
  210. {
  211. CPoint ptOffset = bHoriz ? CPoint(rc.left - point.x, 0) :
  212. CPoint(0, rc.top - point.y);
  213. SetCapture();
  214. while (CWnd::GetCapture() == this)
  215. {
  216. MSG msg;
  217. while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE))
  218. {
  219. if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT))
  220. return;
  221. DispatchMessage(&msg);
  222. }
  223. if (!GetMessage(&msg, NULL, 0, 0))
  224. break;
  225. if (msg.message == WM_MOUSEMOVE)
  226. {
  227. point = CPoint(msg.lParam);
  228. ClientToScreen(&point);
  229. point += ptOffset;
  230. point.x = max(min(point.x, rcAvail.right), rcAvail.left);
  231. point.y = max(min(point.y, rcAvail.bottom), rcAvail.top);
  232. if (bHoriz)
  233. {
  234. if (rc.left == point.x)
  235. continue;
  236. rc.OffsetRect(point.x - rc.left, 0);
  237. }
  238. else
  239. {
  240. if (rc.top == point.y)
  241. continue;
  242. rc.OffsetRect(0, point.y - rc.top);
  243. }
  244. Reposition(rc, rcUnion);
  245. pManager->RecalcFrameLayout(m_pContainer);
  246. }
  247. else if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) break;
  248. else if (msg.message == WM_LBUTTONUP) break;
  249. else ::DispatchMessage(&msg);
  250. }
  251. if (CWnd::GetCapture() == this) ReleaseCapture();
  252. }
  253. m_pContainer->OnAction(xtpPaneActionSplitterResized);
  254. }
  255. CXTPDockingPaneManager* CXTPDockingPaneSplitterWnd::GetDockingPaneManager() const
  256. {
  257. return m_pManager;
  258. }
  259. CXTPDockingPaneSplitterContainer::CXTPDockingPaneSplitterContainer(CXTPDockingPaneLayout* pLayout)
  260. : CXTPDockingPaneBaseContainer(xtpPaneTypeSplitterContainer, pLayout)
  261. {
  262. m_bRecalcLayout = FALSE;
  263. m_bHoriz = FALSE;
  264. }
  265. void CXTPDockingPaneSplitterContainer::Init(CXTPDockingPaneBase* pPane, BOOL bHoriz, CWnd* pFrame)
  266. {
  267. ASSERT(pPane);
  268. if (!pPane)
  269. return;
  270. m_bHoriz = bHoriz;
  271. m_pDockingSite = pFrame;
  272. _InsertPane(pPane);
  273. m_szDocking = pPane->m_szDocking;
  274. }
  275. void CXTPDockingPaneSplitterContainer::_UpdateSplitters()
  276. {
  277. if (m_bRecalcLayout)
  278. return;
  279. if (m_pLayout->IsUserLayout())
  280. return;
  281. while (!m_lstSpliters.IsEmpty())
  282. {
  283. delete m_lstSpliters.RemoveTail();
  284. }
  285. if (m_lstPanes.GetCount() > 1)
  286. {
  287. POSITION posPane = GetHeadPosition();
  288. CXTPDockingPaneBase* pFirstPane = NULL;
  289. // Finding first nonempty pane
  290. while (posPane)
  291. {
  292. pFirstPane = GetNext(posPane);
  293. if (!pFirstPane->IsEmpty())
  294. break;
  295. }
  296. // Splitting
  297. while (posPane)
  298. {
  299. CXTPDockingPaneBase* pSecondPane = GetNext(posPane);
  300. if (pSecondPane->IsEmpty())
  301. continue;
  302. CXTPDockingPaneSplitterWnd* pSplitter = OnCreateSplitter();
  303. pSplitter->Create(this, pFirstPane, pSecondPane);
  304. m_lstSpliters.AddTail(pSplitter);
  305. pFirstPane = pSecondPane;
  306. }
  307. }
  308. }
  309. CXTPDockingPaneSplitterWnd* CXTPDockingPaneSplitterContainer::OnCreateSplitter()
  310. {
  311. return new CXTPDockingPaneSplitterWnd();
  312. }
  313. void CXTPDockingPaneSplitterContainer::_Replace(CXTPDockingPaneBase* pPane, CXTPDockingPaneBase* pReplace)
  314. {
  315. ASSERT(pPane && pReplace);
  316. POSITION pos = m_lstPanes.Find(pPane);
  317. ASSERT(pos);
  318. m_lstPanes.InsertAfter(pos, pReplace);
  319. m_lstPanes.RemoveAt(pos);
  320. pReplace->m_pParentContainer = this;
  321. _UpdateSplitters();
  322. if (m_pParentContainer)
  323. {
  324. m_pParentContainer->OnChildContainerChanged(this);
  325. }
  326. }
  327. void CXTPDockingPaneSplitterContainer::_InsertPane(CXTPDockingPaneBase* pPane, CXTPDockingPaneBase* pNeighbour, BOOL bAfter)
  328. {
  329. POSITION pos = pNeighbour ? m_lstPanes.Find(pNeighbour) : NULL;
  330. if (bAfter)
  331. {
  332. if (pos == NULL) pos = m_lstPanes.GetTailPosition();
  333. m_lstPanes.InsertAfter(pos, pPane);
  334. }
  335. else
  336. {
  337. if (pos == NULL) pos = GetHeadPosition();
  338. m_lstPanes.InsertBefore(pos, pPane);
  339. }
  340. pPane->m_pParentContainer = this;
  341. pPane->SetDockingSite(GetDockingSite());
  342. GetDockingPaneManager()->RecalcFrameLayout(this, TRUE);
  343. _UpdateSplitters();
  344. if (m_pParentContainer)
  345. {
  346. m_pParentContainer->OnChildContainerChanged(this);
  347. }
  348. pPane->OnParentContainerChanged(this);
  349. }
  350. void CXTPDockingPaneSplitterContainer::RemovePane(CXTPDockingPaneBase* pPane)
  351. {
  352. POSITION pos = m_lstPanes.Find(pPane);
  353. ASSERT(pos);
  354. m_lstPanes.RemoveAt(pos);
  355. _UpdateSplitters();
  356. GetDockingPaneManager()->RecalcFrameLayout(this, TRUE);
  357. if (m_pParentContainer)
  358. {
  359. m_pParentContainer->OnChildContainerChanged(this);
  360. }
  361. if (m_lstPanes.IsEmpty())
  362. {
  363. m_pParentContainer->RemovePane(this);
  364. }
  365. pPane->m_pParentContainer = NULL;
  366. }
  367. void CXTPDockingPaneSplitterContainer::OnChildContainerChanged(CXTPDockingPaneBase* pContainer)
  368. {
  369. if (m_pParentContainer)
  370. {
  371. m_pParentContainer->OnChildContainerChanged(pContainer);
  372. }
  373. _UpdateSplitters();
  374. GetDockingPaneManager()->RecalcFrameLayout(this, TRUE);
  375. }
  376. void CXTPDockingPaneSplitterContainer::OnParentContainerChanged(CXTPDockingPaneBase* pContainer)
  377. {
  378. m_pDockingSite = pContainer->m_pDockingSite;
  379. _UpdateSplitters();
  380. POSITION pos = GetHeadPosition();
  381. while (pos)
  382. {
  383. GetNext(pos)->OnParentContainerChanged(pContainer);
  384. }
  385. }
  386. CXTPDockingPaneSplitterContainer::~CXTPDockingPaneSplitterContainer()
  387. {
  388. while (!m_lstSpliters.IsEmpty())
  389. {
  390. delete m_lstSpliters.RemoveTail();
  391. }
  392. }
  393. void CXTPDockingPaneSplitterContainer::OnSizeParent(CWnd* pParent, CRect rect, LPVOID lParam)
  394. {
  395. int nSplitterSize = GetDockingPaneManager()->GetPaintManager()->m_nSplitterSize;
  396. int nSplitterIndent = GetDockingPaneManager()->GetPaintManager()->m_nSplitterIndent;
  397. CXTPDockingPaneBase* pClient = GetDockingPaneManager()->GetClientPane();
  398. AFX_SIZEPARENTPARAMS* lpLayout = (AFX_SIZEPARENTPARAMS*)lParam;
  399. m_pDockingSite = pParent;
  400. m_rcWindow = rect;
  401. BOOL bClientPane = !GetDockingPaneManager()->m_bHideClient;
  402. // getting list of nonempty panes
  403. CXTPDockingPaneBaseList lst;
  404. POSITION pos = GetHeadPosition();
  405. while (pos)
  406. {
  407. CXTPDockingPaneBase* pPane = GetNext(pos);
  408. if (!pPane->IsEmpty())
  409. lst.AddTail(pPane);
  410. if (!bClientPane && pPane->ContainPane(pClient))
  411. bClientPane = TRUE;
  412. }
  413. if (!lst.IsEmpty() && bClientPane && GetDockingPaneManager()->m_bHideClient)
  414. {
  415. pClient->OnSizeParent(pParent, CXTPEmptyRect(), lParam);
  416. }
  417. if (lst.GetCount() == 0)
  418. return;
  419. if (lst.GetCount() == 1)
  420. {
  421. lst.GetHead()->OnSizeParent(pParent, rect, lParam);
  422. return;
  423. }
  424. if (m_bRecalcLayout)
  425. return;
  426. m_bRecalcLayout = TRUE;
  427. //ASSERT(m_lstSpliters.GetCount() == lst.GetCount() - 1);
  428. int nTotalLength = 0;
  429. int nLengthAvail = 0;
  430. _AdjustPanesLength(GetDockingPaneManager(), lst, rect, m_bHoriz, TRUE, nTotalLength, nLengthAvail);
  431. pos = lst.GetHeadPosition();
  432. POSITION posSplitter = m_lstSpliters.GetHeadPosition();
  433. CRect rcPane(rect);
  434. while (pos)
  435. {
  436. CXTPDockingPaneBase* pPane = lst.GetNext(pos);
  437. int nLength = -pPane->m_nLength;
  438. if (pPane->m_nLength > 0)
  439. {
  440. nLength = nTotalLength == 0 ? 0 : int((nLengthAvail * pPane->m_nLength) / nTotalLength);
  441. nTotalLength -= pPane->m_nLength;
  442. nLengthAvail = max(nLengthAvail - nLength, 0);
  443. }
  444. CRect rcSplitter;
  445. if (m_bHoriz)
  446. {
  447. rcPane.right = pos == NULL ? rect.right : rcPane.left + nLength;
  448. rcSplitter.SetRect(rcPane.right - nSplitterIndent, rect.top, rcPane.right + nSplitterSize + nSplitterIndent, rect.bottom);
  449. }
  450. else
  451. {
  452. rcPane.bottom = pos == NULL ? rect.bottom : rcPane.top + nLength;
  453. rcSplitter.SetRect(rect.left, rcPane.bottom - nSplitterIndent, rect.right, rcPane.bottom + nSplitterSize + nSplitterIndent);
  454. }
  455. if (lpLayout->hDWP != NULL && posSplitter)
  456. {
  457. CXTPDockingPaneSplitterWnd* pSplitter = m_lstSpliters.GetNext(posSplitter);
  458. if (pSplitter)
  459. {
  460. rcSplitter.IntersectRect(rcSplitter, rect);
  461. pSplitter->SetWindowPos(&CWnd::wndBottom, rcSplitter.left, rcSplitter.top, rcSplitter.Width(), rcSplitter.Height(), 0);
  462. pSplitter->Invalidate(FALSE);
  463. }
  464. }
  465. pPane->OnSizeParent(pParent, rcPane, lParam);
  466. if (m_bHoriz)
  467. {
  468. rcPane.left = rcPane.right + nSplitterSize;
  469. }
  470. else
  471. {
  472. rcPane.top = rcPane.bottom + nSplitterSize;
  473. }
  474. }
  475. m_bRecalcLayout = FALSE;
  476. }
  477. void CXTPDockingPaneSplitterContainer::FindChildPane(XTPDockingPaneType type, CXTPDockingPaneBaseList* pList) const
  478. {
  479. POSITION pos = GetHeadPosition();
  480. while (pos)
  481. {
  482. CXTPDockingPaneBase* pPane = GetNext(pos);
  483. if (pPane->GetType() == type && !pPane->IsEmpty())
  484. {
  485. pList->AddTail(pPane);
  486. }
  487. }
  488. }
  489. void CXTPDockingPaneSplitterContainer::Copy(CXTPDockingPaneBase* pCloneBase, CXTPPaneToPaneMap* pMap, DWORD /*dwIgnoredOptions*/)
  490. {
  491. CXTPDockingPaneSplitterContainer* pClone = (CXTPDockingPaneSplitterContainer*)pCloneBase;
  492. ASSERT(pClone);
  493. if (!pClone)
  494. return;
  495. m_bHoriz = pClone->m_bHoriz;
  496. m_pDockingSite = GetDockingPaneManager()->GetSite();
  497. POSITION pos = pClone->GetHeadPosition();
  498. while (pos)
  499. {
  500. CXTPDockingPaneBase* pPane = (CXTPDockingPaneBase*)pClone->GetNext(pos);
  501. if (!pPane->IsEmpty() || pMap)
  502. {
  503. _InsertPane(pPane->Clone(m_pLayout, pMap));
  504. }
  505. }
  506. m_szDocking = pClone->m_szDocking;
  507. m_rcWindow = pClone->m_rcWindow;
  508. }
  509. BOOL CXTPDockingPaneSplitterContainer::_Before(const CXTPDockingPaneBase* pPane, POSITION pos) const
  510. {
  511. POSITION p = GetHeadPosition();
  512. while (p)
  513. {
  514. if (p == pos) return FALSE;
  515. CXTPDockingPaneBase* pBase = GetNext(p);
  516. if (pBase == pPane) return TRUE;
  517. }
  518. ASSERT(FALSE);
  519. return FALSE;
  520. }
  521. void CXTPDockingPaneSplitterContainer::_AdjustPanesLength(CXTPDockingPaneManager* pManager, CXTPDockingPaneBaseList& lst, CRect rect, BOOL bHoriz, BOOL bApply, int& nTotalLength, int& nLengthAvail)
  522. {
  523. nTotalLength = 0;
  524. nLengthAvail = 0;
  525. CXTPDockingPaneBase* pClientPane = NULL;
  526. CXTPDockingPaneBase* pClient = pManager->GetClientPane();
  527. int nSplitterSize = pManager->GetPaintManager()->m_nSplitterSize;
  528. POSITION pos = lst.GetHeadPosition();
  529. while (pos)
  530. {
  531. CXTPDockingPaneBase* pPane = lst.GetNext(pos);
  532. pPane->m_nLength = bHoriz ? pPane->m_szDocking.cx : pPane->m_szDocking.cy;
  533. MINMAXINFO mmi;
  534. pPane->GetMinMaxInfo(&mmi);
  535. pPane->m_nLength = max(GetMinSize(&mmi, bHoriz), min(GetMaxSize(&mmi, bHoriz), pPane->m_nLength));
  536. if (pClientPane == NULL && pPane->ContainPane(pClient))
  537. {
  538. if (!pManager->m_bHideClient || pPane->m_szDocking == CSize(0, 0))
  539. {
  540. pClientPane = pPane;
  541. if (bApply) pClientPane->m_szDocking = CSize(0, 0);
  542. pClientPane->m_nLength = 0;
  543. }
  544. }
  545. nTotalLength += pPane->m_nLength;
  546. }
  547. nLengthAvail = (bHoriz ? rect.Width() : rect.Height()) - (nSplitterSize * ((int)lst.GetCount() - 1));
  548. if (pClientPane && nTotalLength < nLengthAvail)
  549. {
  550. pClientPane->m_nLength = nLengthAvail - nTotalLength;
  551. if (bApply)
  552. {
  553. if (bHoriz) pClientPane->m_szDocking.cx = pClientPane->m_nLength;
  554. else pClientPane->m_szDocking.cy = pClientPane->m_nLength;
  555. }
  556. nTotalLength = nLengthAvail;
  557. }
  558. if (nLengthAvail > 0)
  559. {
  560. pos = lst.GetHeadPosition();
  561. while (pos)
  562. {
  563. CXTPDockingPaneBase* pPane = lst.GetNext(pos);
  564. if ((pPane->m_nLength < 0) || (nTotalLength == 0))
  565. continue;
  566. MINMAXINFO mmi;
  567. pPane->GetMinMaxInfo(&mmi);
  568. int nLength = pPane->m_nLength;
  569. if (nLengthAvail * nLength / nTotalLength < GetMinSize(&mmi, bHoriz))
  570. pPane->m_nLength = -GetMinSize(&mmi, bHoriz);
  571. else if (nLengthAvail * nLength / nTotalLength > GetMaxSize(&mmi, bHoriz))
  572. pPane->m_nLength = -GetMaxSize(&mmi, bHoriz);
  573. if (pPane->m_nLength < 0)
  574. {
  575. nLengthAvail += pPane->m_nLength;
  576. nTotalLength -= nLength;
  577. if (nLengthAvail < 0)
  578. {
  579. pPane->m_nLength -= nLengthAvail;
  580. nLengthAvail = 0;
  581. break;
  582. }
  583. pos = lst.GetHeadPosition();
  584. }
  585. }
  586. }
  587. }
  588. CRect CXTPDockingPaneSplitterContainer::_CalculateResultDockingRect(BOOL bHoriz, CXTPDockingPaneBaseList& lst, CRect rect, CXTPDockingPaneBase* pPaneI)
  589. {
  590. CXTPDockingPaneManager* pManager = pPaneI->GetDockingPaneManager();
  591. int nSplitterSize = pManager->GetPaintManager()->m_nSplitterSize;
  592. int nTotalLength = 0;
  593. int nLengthAvail = 0;
  594. _AdjustPanesLength(pManager, lst, rect, bHoriz, FALSE, nTotalLength, nLengthAvail);
  595. POSITION pos = lst.GetHeadPosition();
  596. CRect rcPane(rect);
  597. while (pos)
  598. {
  599. CXTPDockingPaneBase* pPane = lst.GetNext(pos);
  600. int nLength = -pPane->m_nLength;
  601. if (pPane->m_nLength > 0)
  602. {
  603. nLength = nTotalLength == 0 ? 0 : int((nLengthAvail * pPane->m_nLength) / nTotalLength);
  604. nTotalLength -= pPane->m_nLength;
  605. nLengthAvail = max(nLengthAvail - nLength, 0);
  606. }
  607. if (bHoriz)
  608. {
  609. rcPane.right = pos == NULL ? rect.right : rcPane.left + nLength;
  610. if (pPaneI == pPane)
  611. break;
  612. rcPane.left = rcPane.right + nSplitterSize;
  613. }
  614. else
  615. {
  616. rcPane.bottom = pos == NULL ? rect.bottom : rcPane.top + nLength;
  617. if (pPaneI == pPane)
  618. break;
  619. rcPane.top = rcPane.bottom + nSplitterSize;
  620. }
  621. }
  622. return rcPane;
  623. }
  624. CRect CXTPDockingPaneSplitterContainer::_CalculateResultDockingRectSelf(CXTPDockingPaneBase* pPaneI, XTPDockingPaneDirection direction, CXTPDockingPaneBase* pNeighbour)
  625. {
  626. direction = GetDockingPaneManager()->GetRTLDirection(direction);
  627. ASSERT(pNeighbour);
  628. BOOL bAfter = (direction == xtpPaneDockRight || direction == xtpPaneDockBottom);
  629. // getting list of nonempty panes
  630. CXTPDockingPaneBaseList lst;
  631. POSITION posPanes = GetHeadPosition();
  632. while (posPanes)
  633. {
  634. CXTPDockingPaneBase* pPane = GetNext(posPanes);
  635. if (pPane->IsEmpty() || (pPane == pPaneI))
  636. continue;
  637. POSITION pos = lst.AddTail(pPane);
  638. if (pPane == pNeighbour)
  639. {
  640. if (bAfter)
  641. lst.InsertAfter(pos, pPaneI);
  642. else
  643. lst.InsertBefore(pos, pPaneI);
  644. }
  645. }
  646. CRect rcResult = _CalculateResultDockingRect(m_bHoriz, lst, m_rcWindow, pPaneI);
  647. m_pDockingSite->ClientToScreen(rcResult);
  648. return rcResult;
  649. }
  650. CRect CXTPDockingPaneSplitterContainer::_CalculateResultDockingRectChild(CXTPDockingPaneBase* pSplitter, CXTPDockingPaneBase* pPane, XTPDockingPaneDirection direction)
  651. {
  652. BOOL bAfter = (direction == xtpPaneDockRight || direction == xtpPaneDockBottom);
  653. BOOL bHoriz = (direction == xtpPaneDockLeft || direction == xtpPaneDockRight);
  654. CXTPDockingPaneBaseList lst;
  655. lst.AddTail(pSplitter);
  656. if (bAfter)
  657. lst.AddTail(pPane);
  658. else
  659. lst.AddHead(pPane);
  660. CRect rect = pSplitter->GetPaneWindowRect();
  661. return _CalculateResultDockingRect(bHoriz, lst, rect, pPane);
  662. }
  663. void CXTPDockingPaneSplitterContainer::DeletePane()
  664. {
  665. InternalRelease();
  666. }
  667. void CXTPDockingPaneSplitterContainer::GetMinMaxInfo(LPMINMAXINFO pMinMaxInfo) const
  668. {
  669. CXTPDockingPaneBase::GetMinMaxInfo(pMinMaxInfo);
  670. int nCount = 0;
  671. POSITION pos = GetHeadPosition();
  672. while (pos)
  673. {
  674. CXTPDockingPaneBase* pPane = GetNext(pos);
  675. if (pPane->IsEmpty())
  676. continue;
  677. nCount++;
  678. MINMAXINFO info;
  679. pPane->GetMinMaxInfo(&info);
  680. if (nCount == 1)
  681. {
  682. *pMinMaxInfo = info;
  683. }
  684. else
  685. {
  686. GetMinSize(pMinMaxInfo, m_bHoriz) += GetMinSize(&info, m_bHoriz);
  687. GetMaxSize(pMinMaxInfo, m_bHoriz) += GetMaxSize(&info, m_bHoriz);
  688. GetMinSize(pMinMaxInfo, !m_bHoriz) = max(GetMinSize(pMinMaxInfo, !m_bHoriz), GetMinSize(&info, !m_bHoriz));
  689. GetMaxSize(pMinMaxInfo, !m_bHoriz) = min(GetMaxSize(pMinMaxInfo, !m_bHoriz), GetMaxSize(&info, !m_bHoriz));
  690. }
  691. }
  692. if (nCount > 0)
  693. {
  694. GetMinSize(pMinMaxInfo, m_bHoriz) += GetPaintManager()->m_nSplitterSize * (nCount - 1);
  695. GetMaxSize(pMinMaxInfo, m_bHoriz) += GetPaintManager()->m_nSplitterSize * (nCount - 1);
  696. }
  697. }