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

对话框与窗口

开发平台:

Visual C++

  1. // XTPRibbonGroups.cpp: implementation of the CXTPRibbonGroups class.
  2. //
  3. // This file is a part of the XTREME RIBBON 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/XTPImageManager.h"
  22. #include "Common/XTPPropExchange.h"
  23. #include "CommandBars/XTPControl.h"
  24. #include "CommandBars/XTPControlPopup.h"
  25. #include "CommandBars/XTPControls.h"
  26. #include "CommandBars/XTPControlGallery.h"
  27. #include "XTPRibbonGroup.h"
  28. #include "XTPRibbonGroups.h"
  29. #include "XTPRibbonTab.h"
  30. #include "XTPRibbonBar.h"
  31. #include "XTPRibbonTheme.h"
  32. #ifdef _DEBUG
  33. #undef THIS_FILE
  34. static char THIS_FILE[]=__FILE__;
  35. #define new DEBUG_NEW
  36. #endif
  37. //////////////////////////////////////////////////////////////////////
  38. // Construction/Destruction
  39. //////////////////////////////////////////////////////////////////////
  40. CXTPRibbonGroups::CXTPRibbonGroups()
  41. {
  42. m_pParentTab = NULL;
  43. m_nGroupsScrollPos = 0;
  44. }
  45. CXTPRibbonGroups::~CXTPRibbonGroups()
  46. {
  47. RemoveAll();
  48. }
  49. void CXTPRibbonGroups::RemoveAll()
  50. {
  51. for (int nIndex = 0; nIndex < GetCount(); nIndex++)
  52. {
  53. CXTPRibbonGroup* pGroup = GetAt(nIndex);
  54. pGroup->OnGroupRemoved();
  55. pGroup->InternalRelease();
  56. }
  57. m_arrGroups.RemoveAll();
  58. RefreshIndexes();
  59. }
  60. void CXTPRibbonGroups::RefreshIndexes()
  61. {
  62. for (int nIndex = 0; nIndex < GetCount(); nIndex++)
  63. {
  64. CXTPRibbonGroup* pGroup = GetAt(nIndex);
  65. pGroup->m_nIndex = nIndex;
  66. }
  67. }
  68. CXTPRibbonBar* CXTPRibbonGroups::GetRibbonBar() const
  69. {
  70. return m_pParentTab->GetRibbonBar();
  71. }
  72. CXTPRibbonGroup* CXTPRibbonGroups::Add(LPCTSTR lpszCaption, int nId)
  73. {
  74. return InsertAt(GetCount(), lpszCaption, nId);
  75. }
  76. CXTPRibbonGroup* CXTPRibbonGroups::InsertAt(int nIndex, CXTPRibbonGroup* pGroup)
  77. {
  78. pGroup->m_pGroups = this;
  79. pGroup->m_pRibbonBar = m_pParentTab->GetRibbonBar();
  80. pGroup->m_pParent = m_pParentTab->GetParent();
  81. m_arrGroups.InsertAt(nIndex, pGroup);
  82. RefreshIndexes();
  83. pGroup->OnGroupAdded();
  84. return pGroup;
  85. }
  86. CXTPRibbonGroup* CXTPRibbonGroups::InsertAt(int nIndex, LPCTSTR lpszCaption, int nId)
  87. {
  88. CXTPRibbonGroup* pGroup = new CXTPRibbonGroup;
  89. pGroup->SetID(nId);
  90. pGroup->SetCaption(lpszCaption);
  91. InsertAt(nIndex, pGroup);
  92. pGroup->LoadToolBar(nId);
  93. return pGroup;
  94. }
  95. void CXTPRibbonGroups::Remove(int nIndex)
  96. {
  97. if ((nIndex >= 0) && (nIndex < GetCount()))
  98. {
  99. CXTPRibbonGroup* pGroup = GetAt(nIndex);
  100. ASSERT(pGroup);
  101. pGroup->OnGroupRemoved();
  102. m_arrGroups.RemoveAt(nIndex);
  103. pGroup->InternalRelease();
  104. RefreshIndexes();
  105. }
  106. }
  107. CXTPRibbonGroup* CXTPRibbonGroups::HitTest(CPoint point) const
  108. {
  109. for (int nIndex = 0; nIndex < GetCount(); nIndex++)
  110. {
  111. CXTPRibbonGroup* pGroup = GetAt(nIndex);
  112. if (pGroup->IsVisible() && pGroup->GetRect().PtInRect(point))
  113. {
  114. return pGroup;
  115. }
  116. }
  117. return NULL;
  118. }
  119. void CXTPRibbonGroups::Copy(CXTPRibbonGroups* pGroups)
  120. {
  121. RemoveAll();
  122. for (int nIndex = 0; nIndex < pGroups->GetCount(); nIndex++)
  123. {
  124. CXTPRibbonGroup* pGroup = pGroups->GetAt(nIndex);
  125. CXTPRibbonGroup* pClone = (CXTPRibbonGroup*)pGroup->GetRuntimeClass()->CreateObject();
  126. InsertAt(nIndex, pClone);
  127. pClone->Copy(pGroup);
  128. pClone->m_pGroups = this;
  129. }
  130. }
  131. //
  132. struct CXTPRibbonGroup::CONTROLINFO
  133. {
  134. CRect rcControl;
  135. CRect rcRow;
  136. CSize szControl;
  137. BOOL bHide;
  138. BOOL bWrap;
  139. BOOL bBeginGroup;
  140. BOOL bWrapGroup;
  141. XTPButtonStyle buttonStyle;
  142. CXTPControl* pControl;
  143. int nTailWidth;
  144. void EnsureButtonSize(CDC* pDC)
  145. {
  146. if (buttonStyle != pControl->GetStyle())
  147. {
  148. buttonStyle = pControl->GetStyle();
  149. szControl = pControl->GetSize(pDC);
  150. }
  151. }
  152. void Attach(CDC* pDC, CXTPControl* p)
  153. {
  154. pControl = p;
  155. rcRow.SetRectEmpty();
  156. szControl = pControl->GetSize(pDC);
  157. rcControl = pControl->GetRect();
  158. bBeginGroup = pControl->GetBeginGroup();
  159. bWrapGroup = bBeginGroup || (pControl->GetFlags() & xtpFlagWrapRow);
  160. buttonStyle = pControl->GetStyle();
  161. bWrap = bHide = FALSE;
  162. nTailWidth = 0;
  163. }
  164. void Detach()
  165. {
  166. pControl->SetHideWrap(bHide);
  167. pControl->SetRowRect(rcRow);
  168. if (!bHide)
  169. pControl->SetRect(rcControl);
  170. pControl->SetWrap(bWrap);
  171. }
  172. };
  173. struct CXTPRibbonGroup::LAYOUTINFO
  174. {
  175. CONTROLINFO* pControls;
  176. int nControlCount;
  177. int nMinWidth;
  178. int nWidth;
  179. BOOL bOldReduced;
  180. };
  181. BOOL CXTPRibbonGroup::OnExtendSize(int nWidthAvail)
  182. {
  183. int nDataCount = m_pLayoutInfo->nControlCount;
  184. CONTROLINFO* pData = m_pLayoutInfo->pControls;
  185. for (int i = nDataCount - 1; i >= 0; i--)
  186. {
  187. if (pData[i].pControl->GetType() == xtpControlGallery &&
  188. ((CXTPControlGallery*)pData[i].pControl)->IsResizable() & 1)
  189. {
  190. CXTPControlGallery* pGallery = (CXTPControlGallery*)pData[i].pControl;
  191. int cx = pGallery->GetItems() ? pGallery->GetItems()->GetItemSize().cx : 0;
  192. if (cx > 0 && cx <= nWidthAvail)
  193. {
  194. int nCount = pGallery->GetItems()->GetItemCount();
  195. CRect rcBorders = pGallery->GetBorders();
  196. int nMaxWidth = nCount * cx + rcBorders.left + rcBorders.right;
  197. if (pData[i].szControl.cx + cx <= nMaxWidth)
  198. {
  199. pData[i].szControl.cx = min(nMaxWidth,
  200.  pData[i].szControl.cx + int(nWidthAvail / cx) * cx);
  201. return TRUE;
  202. }
  203. }
  204. return FALSE;
  205. }
  206. }
  207. return FALSE;
  208. }
  209. BOOL CXTPRibbonGroup::OnReduceSize(int nLevel, int nWidthAvail)
  210. {
  211. if (m_pLayoutInfo == NULL)
  212. return FALSE;
  213. if (m_pLayoutInfo->nWidth < m_pLayoutInfo->nMinWidth)
  214. {
  215. if (nLevel == 2 && m_pLayoutInfo->nWidth > 16)
  216. {
  217. m_pLayoutInfo->nMinWidth = max(m_pLayoutInfo->nWidth, m_pLayoutInfo->nMinWidth - nWidthAvail);
  218. return TRUE;
  219. }
  220. return FALSE;
  221. }
  222. BOOL bReduced = FALSE;
  223. int nResultHeight = GetRibbonBar()->CalcGroupsHeight() - 2 -
  224. GetRibbonBar()->GetRibbonPaintManager()->GetGroupCaptionHeight() ;
  225. int nButtonSize = GetRibbonBar()->GetButtonSize().cy;
  226. int nControlsPerGroup = int(nResultHeight / nButtonSize);
  227. int nDataCount = m_pLayoutInfo->nControlCount;
  228. CONTROLINFO* pData = m_pLayoutInfo->pControls;
  229. bReduced = FALSE;
  230. int* pButtons = new int[nControlsPerGroup];
  231. if (nLevel == 0 && !m_bControlsGrouping && m_nAllowReduce > nLevel)
  232. {
  233. if (nControlsPerGroup > 1)
  234. {
  235. for (int i = nDataCount - 1; i >= 2; i--)
  236. {
  237. if (pData[i].bWrapGroup)
  238. continue;
  239. int nItems = 0;
  240. for (int j = i; j  >= 0; j--)
  241. {
  242. CONTROLINFO* pControl = &pData[j];
  243. if ((nItems == nControlsPerGroup - 1 || !pControl->bWrapGroup)
  244. && pControl->pControl->m_buttonRibbonStyle == xtpButtonIconAndCaptionBelow
  245. && pControl->pControl->GetType() != xtpControlGallery)
  246. {
  247. pButtons[nItems] = j;
  248. nItems += 1;
  249. }
  250. else
  251. {
  252. break;
  253. }
  254. if (nItems == nControlsPerGroup)
  255. break;
  256. }
  257. if (nItems == nControlsPerGroup)
  258. {
  259. for (int k = 0; k < nItems; k++)
  260. pData[pButtons[k]].pControl->m_buttonRibbonStyle = xtpButtonIconAndCaption;
  261. bReduced = TRUE;
  262. break;
  263. }
  264. }
  265. }
  266. }
  267. if (nLevel == 1 && !m_bControlsGrouping && m_nAllowReduce > nLevel)
  268. {
  269. if (nControlsPerGroup > 1)
  270. {
  271. for (int i = nDataCount - 1; i >= 2; i--)
  272. {
  273. if (pData[i].bWrapGroup)
  274. continue;
  275. int nItems = 0;
  276. BOOL bFound = FALSE;
  277. int j;
  278. for (j = i; j  >= 0; j--)
  279. {
  280. CONTROLINFO* pControl = &pData[j];
  281. if ((nItems == nControlsPerGroup - 1 || !pControl->bWrapGroup)
  282. && pControl->pControl->GetType() != xtpControlGallery)
  283. {
  284. pButtons[nItems] = j;
  285. nItems += 1;
  286. bFound = bFound || pControl->pControl->m_buttonRibbonStyle == xtpButtonIconAndCaptionBelow;
  287. }
  288. else
  289. {
  290. break;
  291. }
  292. if (nItems == nControlsPerGroup)
  293. break;
  294. }
  295. i = j;
  296. if (nItems == nControlsPerGroup && bFound)
  297. {
  298. for (int k = 0; k < nItems; k++)
  299. pData[pButtons[k]].pControl->m_buttonRibbonStyle = xtpButtonIconAndCaption;
  300. bReduced = TRUE;
  301. break;
  302. }
  303. }
  304. }
  305. }
  306. if (nLevel == 1 && m_bControlsGrouping && m_nRowCount == 2 && m_nAllowReduce > nLevel)
  307. {
  308. m_nRowCount = 3;
  309. bReduced = TRUE;
  310. }
  311. if (nLevel == 2 && !bReduced && !m_bControlsGrouping && m_nAllowReduce > nLevel)
  312. {
  313. if (nControlsPerGroup > 1)
  314. {
  315. for (int i = nDataCount - 1; i >= 2; i--)
  316. {
  317. if (pData[i].bWrapGroup)
  318. continue;
  319. int nItems = 0;
  320. int nLeft = 0;
  321. for (int j = i; j  >= 0; j--)
  322. {
  323. CONTROLINFO* pControl = &pData[j];
  324. int nOffset = pControl->rcControl.left;
  325. if (nItems != 0 && (nOffset != nLeft))
  326. break;
  327. if ((nItems == nControlsPerGroup - 1 || !pControl->bWrapGroup)
  328. && pControl->pControl->m_buttonRibbonStyle == xtpButtonIconAndCaption
  329. && pControl->pControl->GetType() != xtpControlGallery)
  330. {
  331. pButtons[nItems] = j;
  332. nItems += 1;
  333. nLeft = nOffset;
  334. }
  335. else
  336. {
  337. break;
  338. }
  339. if (nItems == nControlsPerGroup)
  340. break;
  341. }
  342. if (nItems == nControlsPerGroup && GetCount() > nControlsPerGroup)
  343. {
  344. for (int k = 0; k < nItems; k++)
  345. pData[pButtons[k]].pControl->m_buttonRibbonStyle = xtpButtonIcon;
  346. bReduced = TRUE;
  347. break;
  348. }
  349. }
  350. }
  351. }
  352. if (nLevel == 2 && !bReduced && !m_bControlsGrouping && m_nAllowReduce > nLevel)
  353. {
  354. for (int i = nDataCount - 1; i >= 0; i--)
  355. {
  356. if (pData[i].pControl->GetType() == xtpControlGallery &&
  357. pData[i].pControl->m_buttonRibbonStyle != xtpButtonIconAndCaptionBelow)
  358. {
  359. pData[i].pControl->m_buttonRibbonStyle = xtpButtonIconAndCaptionBelow;
  360. bReduced = TRUE;
  361. break;
  362. }
  363. }
  364. }
  365. delete[] pButtons;
  366. if (nLevel == 3)
  367. {
  368. if (nDataCount > 1 && !m_bReduced && m_nAllowReduce > nLevel)
  369. {
  370. m_bReduced = TRUE;
  371. for (int j = 0; j < nDataCount; j++)
  372. {
  373. CONTROLINFO* pControl = &pData[j];
  374. pControl->bHide = TRUE;
  375. }
  376. bReduced = TRUE;
  377. }
  378. }
  379. return bReduced;
  380. }
  381. void CXTPRibbonGroup::OnBeforeCalcSize(CDC* pDC)
  382. {
  383. CSize szLargeIcon = GetRibbonBar()->GetLargeIconSize(FALSE);
  384. m_pLayoutInfo = new LAYOUTINFO;
  385. m_pLayoutInfo->pControls = NULL;
  386. m_pLayoutInfo->nMinWidth = GetMinimumWidth(pDC);
  387. m_pLayoutInfo->bOldReduced = m_bReduced;
  388. int nVisibleCount = 0;
  389. int j;
  390. for (j = 0; j < GetCount(); j++)
  391. {
  392. CXTPControl* pControl = GetAt(j);
  393. if (pControl->IsVisible(xtpHideWrap))
  394. {
  395. nVisibleCount++;
  396. }
  397. }
  398. m_pLayoutInfo->nControlCount = nVisibleCount;
  399. if (nVisibleCount == 0)
  400. return;
  401. m_pLayoutInfo->pControls = new CONTROLINFO[nVisibleCount];
  402. int k = 0;
  403. for (j = 0; j < GetCount(); j++)
  404. {
  405. CXTPControl* pControl = GetAt(j);
  406. if (pControl->IsVisible(xtpHideWrap))
  407. {
  408. pControl->m_buttonRibbonStyle = xtpButtonAutomatic;
  409. if (!m_bControlsGrouping && pControl->GetStyle() == xtpButtonAutomatic && pControl->GetType() != xtpControlGallery)
  410. {
  411. BOOL bDrawImage = pControl->GetIconId() > 0 ?
  412. pControl->GetImageManager()->IsPrimaryImageExists(pControl->GetIconId(), szLargeIcon.cx) != NULL: FALSE;
  413. pControl->m_buttonRibbonStyle = bDrawImage? xtpButtonIconAndCaptionBelow : xtpButtonIconAndCaption;
  414. }
  415. m_pLayoutInfo->pControls[k].Attach(pDC, pControl);
  416. k++;
  417. }
  418. }
  419. ASSERT(k == nVisibleCount);
  420. m_bReduced = FALSE;
  421. m_nRowCount = 2;
  422. }
  423. void CXTPRibbonGroup::OnAfterCalcSize()
  424. {
  425. if (!m_pLayoutInfo)
  426. return;
  427. for (int i = 0; i < m_pLayoutInfo->nControlCount; i++)
  428. {
  429. if (i == 0)
  430. m_pLayoutInfo->pControls[i].bWrap = TRUE;
  431. m_pLayoutInfo->pControls[i].Detach();
  432. }
  433. if (m_pLayoutInfo->bOldReduced && !m_bReduced)
  434. {
  435. GetRibbonBar()->m_bGroupReducedChanged = TRUE;
  436. }
  437. delete[] m_pLayoutInfo->pControls;
  438. delete m_pLayoutInfo;
  439. }
  440. int CXTPRibbonGroup::_WrapSpecialDynamicSize(int nWidth, BOOL bIncludeTail)
  441. {
  442. int nDataCount = m_pLayoutInfo->nControlCount;
  443. CONTROLINFO* pData = m_pLayoutInfo->pControls;
  444. int nWraps = 0, x = 0;
  445. for (int i = 0; i < nDataCount; i++)
  446. {
  447. CONTROLINFO* pControl = &pData[i];
  448. pControl->bWrap = FALSE;
  449. CSize szControl = pControl->szControl;
  450. BOOL bBeginGroup = pControl->bBeginGroup && i > 0;
  451. BOOL bWrapGroup = pControl->bWrapGroup && i > 0;
  452. if (bWrapGroup && (pControl->pControl->GetFlags() & xtpFlagWrapRow))
  453. {
  454. x = szControl.cx;
  455. pControl->bWrap = TRUE;
  456. nWraps++;
  457. continue;
  458. }
  459. else if (bWrapGroup)
  460. {
  461. if ((bIncludeTail && (x + pControl->nTailWidth >= nWidth))
  462. || (!bIncludeTail && nWraps == 0 && (x + pControl->nTailWidth >= nWidth)))
  463. {
  464. x = szControl.cx;
  465. pControl->bWrap = TRUE;
  466. nWraps++;
  467. continue;
  468. }
  469. }
  470. if (bBeginGroup)
  471. x += 3;
  472. x += szControl.cx;
  473. }
  474. return nWraps;
  475. }
  476. int CXTPRibbonGroup::_GetSizeSpecialDynamicSize()
  477. {
  478. int nTotalWidth = 0, x = 0, y = 0, nRowHeight = 0;
  479. int nDataCount = m_pLayoutInfo->nControlCount;
  480. CONTROLINFO* pData = m_pLayoutInfo->pControls;
  481. for (int i = 0; i < nDataCount; i++)
  482. {
  483. CONTROLINFO* pControl = &pData[i];
  484. CSize szControl = pControl->szControl;
  485. if (pControl->bWrap)
  486. {
  487. x = 0;
  488. y += nRowHeight;
  489. }
  490. else
  491. {
  492. BOOL bBeginGroup = pControl->bBeginGroup && i > 0;
  493. if (bBeginGroup)
  494. x += 3;
  495. }
  496. pControl->rcControl.SetRect(2 + x, y, 2 + x + szControl.cx, y + szControl.cy);
  497. x += szControl.cx;
  498. nRowHeight = max(nRowHeight, szControl.cy);
  499. nTotalWidth = max(nTotalWidth, x);
  500. }
  501. return nTotalWidth + 4;
  502. }
  503. BOOL CXTPRibbonGroup::_FindBestWrapSpecialDynamicSize()
  504. {
  505. int nMax = _GetSizeSpecialDynamicSize();
  506. int nMin = 0, nMid = 0;
  507. int nCurrent = _WrapSpecialDynamicSize(nMin, TRUE);
  508. int nTarget = 2;
  509. if (nCurrent < nTarget)
  510. return FALSE;
  511. if (nCurrent == nTarget)
  512. return TRUE;
  513. while (nMin < nMax)
  514. {
  515. nMid = (nMin + nMax) / 2;
  516. nCurrent = _WrapSpecialDynamicSize(nMid, TRUE);
  517. if (nCurrent <= nTarget)
  518. {
  519. nMax = nMid;
  520. }
  521. else
  522. {
  523. if (nMin == nMid)
  524. {
  525. _WrapSpecialDynamicSize(nMax, TRUE);
  526. break;
  527. }
  528. nMin = nMid;
  529. }
  530. }
  531. return TRUE;
  532. }
  533. int CXTPRibbonGroup::_CalcSpecialDynamicSize(CDC* /*pDC*/)
  534. {
  535. int nResultHeight = GetRibbonBar()->CalcGroupsHeight() - 9 -
  536. GetRibbonBar()->GetRibbonPaintManager()->GetGroupCaptionHeight();
  537. int i;
  538. int nDataCount = m_pLayoutInfo->nControlCount;
  539. CONTROLINFO* pData = m_pLayoutInfo->pControls;
  540. int nTailWidth = 0;
  541. for (i = nDataCount - 1; i >= 0; i--)
  542. {
  543. CONTROLINFO* pControl = &pData[i];
  544. CSize szControl = pControl->szControl;
  545. nTailWidth += szControl.cx;
  546. pControl->nTailWidth = nTailWidth;
  547. if (pControl->bWrapGroup)
  548. {
  549. nTailWidth = 0;
  550. }
  551. }
  552. int nBaseHeight = GetRibbonBar()->GetRibbonPaintManager()->GetEditHeight();
  553. int nRowCount = _WrapSpecialDynamicSize(32000, FALSE) + 1;
  554. int nTotalWidth = 0;
  555. if (nRowCount == 1)
  556. {
  557. nRowCount = 3;
  558. nTotalWidth = _GetSizeSpecialDynamicSize();
  559. BOOL bAllow3Row = nResultHeight >= nBaseHeight * 3;
  560. BOOL bAllow2Row = nResultHeight >= nBaseHeight * 2 ;
  561. if (!bAllow2Row)
  562. {
  563. _WrapSpecialDynamicSize(32000, FALSE);
  564. nRowCount = 1;
  565. }
  566. else
  567. {
  568. if (!(bAllow3Row && m_nRowCount == 3 && _FindBestWrapSpecialDynamicSize()))
  569. {
  570. nRowCount = _WrapSpecialDynamicSize(nTotalWidth / 2, FALSE) + 1;
  571. }
  572. }
  573. }
  574. nTotalWidth = _GetSizeSpecialDynamicSize();
  575. int nOffset = (nResultHeight + 1 - nBaseHeight * nRowCount) / (nRowCount + 1);
  576. int nTotalOffset = nOffset;
  577. int nRow = 0;
  578. for (i = 0; i < nDataCount; i++)
  579. {
  580. CONTROLINFO* pControl = &pData[i];
  581. if (i > 0 && pControl->bWrap)
  582. {
  583. nOffset = (nResultHeight - nBaseHeight * nRowCount - nTotalOffset) / (nRowCount - nRow);
  584. nTotalOffset += nOffset;
  585. nRow++;
  586. }
  587. pControl->rcControl.OffsetRect(0, nTotalOffset);
  588. }
  589. m_pLayoutInfo->nWidth = nTotalWidth;
  590. return max(m_pLayoutInfo->nWidth, m_pLayoutInfo->nMinWidth);
  591. }
  592. int CXTPRibbonGroup::OnCalcDynamicSize(CDC* pDC)
  593. {
  594. if (m_bReduced)
  595. {
  596. CSize szControl = GetControlGroupPopup()->GetSize(pDC);
  597. return m_pLayoutInfo->nWidth = szControl.cx - 5;
  598. }
  599. if (m_bControlsGrouping)
  600. return _CalcSpecialDynamicSize(pDC);
  601. int nResultHeight = GetRibbonBar()->CalcGroupsHeight() - 9 -
  602. GetRibbonBar()->GetRibbonPaintManager()->GetGroupCaptionHeight() ;
  603. CSize sizeResult(0, nResultHeight);
  604. int dyPrev = 0, dxPrev = 0, x = 2;
  605. int nDataCount = m_pLayoutInfo->nControlCount;
  606. CONTROLINFO* pData = m_pLayoutInfo->pControls;
  607. for (int i = 0; i < nDataCount; i++)
  608. {
  609. CONTROLINFO* pControl = &pData[i];
  610. BOOL bFullRow = pControl->pControl->GetStyle() == xtpButtonIconAndCaptionBelow;
  611. pControl->EnsureButtonSize(pDC);
  612. CSize szControl = pControl->szControl;
  613. int dx = szControl.cx;
  614. int dy = szControl.cy;
  615. BOOL bBeginGroup = pControl->bBeginGroup && i > 0;
  616. BOOL bWrapGroup = pControl->bWrapGroup && i > 0;
  617. if (bBeginGroup)
  618. x += 6;
  619. if (i > 0 && !bWrapGroup && !bFullRow && dyPrev + dy <= nResultHeight)
  620. {
  621. pControl->rcControl.SetRect(x, dyPrev, x + dx, dyPrev + dy);
  622. dxPrev = max(dxPrev, dx);
  623. }
  624. else
  625. {
  626. x += dxPrev;
  627. pControl->rcControl.SetRect(x, 0, x + dx, dy);
  628. dxPrev = dx;
  629. }
  630. sizeResult.cx = max(x + dx, sizeResult.cx);
  631. dyPrev = pControl->rcControl.bottom;
  632. }
  633. m_pLayoutInfo->nWidth = sizeResult.cx + 2;
  634. return max(m_pLayoutInfo->nWidth, m_pLayoutInfo->nMinWidth);
  635. }
  636. void CXTPRibbonGroups::_ReduceSmartLayoutToolBar(CDC* pDC, int* pWidth, int nWidth)
  637. {
  638. int nResult = _CalcSmartLayoutToolBar(pWidth);
  639. if (nResult <= nWidth)
  640. {
  641. if (nResult == nWidth)
  642. return;
  643. for (int i = GetCount() - 1; i >= 0; i--)
  644. {
  645. CXTPRibbonGroup* pGroup = GetAt(i);
  646. if (!pGroup->IsVisible())
  647. continue;
  648. if (pGroup->OnExtendSize(nWidth - nResult))
  649. {
  650. pWidth[i] = pGroup->OnCalcDynamicSize(pDC);
  651. break;
  652. }
  653. }
  654. return;
  655. }
  656. BOOL bReduced = FALSE;
  657. do
  658. {
  659. bReduced = FALSE;
  660. for (int nLevel = 0; nLevel < 4; nLevel++)
  661. {
  662. for (int i = GetCount() - 1; i >= 0; i--)
  663. {
  664. CXTPRibbonGroup* pGroup = GetAt(i);
  665. if (!pGroup->IsVisible())
  666. continue;
  667. if (pGroup->OnReduceSize(nLevel, nResult - nWidth))
  668. {
  669. int nGroupWidth = pGroup->OnCalcDynamicSize(pDC);
  670. nResult -= (pWidth[i] - nGroupWidth);
  671. pWidth[i] = nGroupWidth;
  672. bReduced = TRUE;
  673. break;
  674. }
  675. }
  676. if (bReduced)
  677. break;
  678. }
  679. if (bReduced && nResult <= nWidth)
  680. {
  681. return;
  682. }
  683. }
  684. while (bReduced);
  685. }
  686. int CXTPRibbonGroups::_CalcSmartLayoutToolBar(int* pWidth)
  687. {
  688. int nWidth = 0;
  689. for (int i = 0; i < GetCount(); i++)
  690. {
  691. nWidth += pWidth[i];
  692. if (i != GetCount() - 1 && pWidth[i] != 0)
  693. {
  694. nWidth += 7;
  695. }
  696. }
  697. return nWidth;
  698. }
  699. void CXTPRibbonGroup::CenterColumn(int nFirstItem, int nLastItem, int nGroupHeight)
  700. {
  701. int nHeight = 0;
  702. int i;
  703. for (i = nFirstItem; i <= nLastItem; i++)
  704. {
  705. CONTROLINFO* pControl = &m_pLayoutInfo->pControls[i];
  706. if (pControl->bHide)
  707. continue;
  708. nHeight +=pControl->rcControl.Height();
  709. }
  710. if (nHeight >= nGroupHeight)
  711. return;
  712. int nItems = nLastItem - nFirstItem + 1;
  713. int nOffset = (nGroupHeight - nHeight) / (nItems + 1);
  714. for (i = nFirstItem; i <= nLastItem; i++)
  715. {
  716. CONTROLINFO* pControl = &m_pLayoutInfo->pControls[i];
  717. if (pControl->bHide)
  718. continue;
  719. pControl->rcControl.OffsetRect(0, nOffset);
  720. nOffset += nOffset;
  721. }
  722. }
  723. void CXTPRibbonGroup::OnAdjustBorders(int nWidth, CRect rcBorder)
  724. {
  725. CXTPRibbonTheme* pPaintManager = GetRibbonBar()->GetRibbonPaintManager();
  726. int nGroupCaptionHeigh = pPaintManager->GetGroupCaptionHeight();
  727. int nGroupHeight = GetRibbonBar()->CalcGroupsHeight();
  728. int nGroupClientHeight = nGroupHeight - 2 - 3 - 2;
  729. int i;
  730. BOOL bFirstItem = TRUE;
  731. int nFirstItem = 0;
  732. int nColumn = 0;
  733. BOOL bCenterItems = m_bControlsCentering;
  734. if (IsControlsGrouping())
  735. bCenterItems = FALSE;
  736. int nControlCount = m_pLayoutInfo ? m_pLayoutInfo->nControlCount : 0;
  737. int nLeftOffset = 2;
  738. if (m_pLayoutInfo && m_bControlsCentering && m_pLayoutInfo->nWidth < m_pLayoutInfo->nMinWidth && nWidth == m_pLayoutInfo->nMinWidth)
  739. nLeftOffset = 2 + (m_pLayoutInfo->nMinWidth - m_pLayoutInfo->nWidth) / 2;
  740. for (i = 0; i < nControlCount; i++)
  741. {
  742. CONTROLINFO* pControl = &m_pLayoutInfo->pControls[i];
  743. if (pControl->bHide)
  744. continue;
  745. pControl->rcControl.OffsetRect(rcBorder.left + nLeftOffset, rcBorder.top + 2);
  746. pControl->rcRow = CRect(rcBorder.left, rcBorder.top,
  747. rcBorder.left + nWidth, rcBorder.top + nGroupClientHeight - nGroupCaptionHeigh);
  748. if (bCenterItems && !bFirstItem)
  749. {
  750. if (nColumn != pControl->rcControl.left)
  751. {
  752. CenterColumn(nFirstItem, i - 1, nGroupClientHeight - nGroupCaptionHeigh - 3);
  753. nColumn = pControl->rcControl.left;
  754. nFirstItem = i;
  755. }
  756. }
  757. else
  758. {
  759. bFirstItem = FALSE;
  760. nColumn = pControl->rcControl.left;
  761. }
  762. }
  763. if (bCenterItems && nControlCount > 0) CenterColumn(nFirstItem, m_pLayoutInfo->nControlCount - 1, nGroupClientHeight - nGroupCaptionHeigh - 3);
  764. int nBeginGroup = rcBorder.left;
  765. int nEndGroup = nBeginGroup + nWidth + 5;
  766. SetRect(CRect(nBeginGroup, rcBorder.top, nEndGroup,  rcBorder.top + nGroupClientHeight));
  767. }
  768. void CXTPRibbonGroups::CalcDynamicSize(CDC* pDC, int nLength, DWORD /*dwMode*/, const CRect& rcBorder)
  769. {
  770. CXTPRibbonScrollableBar* pScrollableBar = GetScrollableBar(m_pParentTab->GetParent());
  771. int nCount = GetCount();
  772. if (nCount == 0)
  773. {
  774. pScrollableBar->EnableGroupsScroll(FALSE, FALSE);
  775. return;
  776. }
  777. int* pData = new int[nCount];
  778. int i;
  779. for (i = 0; i < nCount; i++)
  780. {
  781. CXTPRibbonGroup* pGroup = GetAt(i);
  782. if (pGroup->IsVisible())
  783. {
  784. pGroup->OnBeforeCalcSize(pDC);
  785. }
  786. }
  787. for (i = 0; i < nCount; i++)
  788. {
  789. CXTPRibbonGroup* pGroup = GetAt(i);
  790. pData[i] = pGroup->IsVisible() ? pGroup->OnCalcDynamicSize(pDC) : 0;
  791. }
  792. int nGroupsLength = nLength - rcBorder.right - rcBorder.left;
  793. _ReduceSmartLayoutToolBar(pDC, pData, nGroupsLength);
  794. CRect rcBorders = rcBorder;
  795. int nTotalWidth = -7;
  796. for (i = 0; i < nCount; i++)
  797. {
  798. CXTPRibbonGroup* pGroup = GetAt(i);
  799. if (pGroup->IsVisible())
  800. {
  801. nTotalWidth += pData[i] + 2 + 5;
  802. }
  803. }
  804. int nScrollPos = pScrollableBar->m_nGroupsScrollPos;
  805. if (nTotalWidth > nGroupsLength)
  806. {
  807. if (nScrollPos > nTotalWidth - nGroupsLength)
  808. {
  809. nScrollPos = nTotalWidth - nGroupsLength;
  810. }
  811. }
  812. else
  813. {
  814. nScrollPos = 0;
  815. }
  816. if (nScrollPos < 0) nScrollPos = 0;
  817. m_nGroupsScrollPos = nScrollPos;
  818. pScrollableBar->EnableGroupsScroll(nScrollPos > 0, nTotalWidth - nGroupsLength - nScrollPos > 0);
  819. rcBorders.left -= nScrollPos;
  820. for (i = 0; i < nCount; i++)
  821. {
  822. CXTPRibbonGroup* pGroup = GetAt(i);
  823. if (pGroup->IsVisible())
  824. {
  825. pGroup->OnAdjustBorders(pData[i], rcBorders);
  826. rcBorders.left += pData[i] + 2 + 5;
  827. }
  828. }
  829. for (i = 0; i < nCount; i++)
  830. {
  831. CXTPRibbonGroup* pGroup = GetAt(i);
  832. if (pGroup->IsVisible())
  833. {
  834. pGroup->OnAfterCalcSize();
  835. }
  836. }
  837. delete[] pData;
  838. }
  839. void CXTPRibbonGroup::DoPropExchange(CXTPPropExchange* pPX)
  840. {
  841. PX_Int(pPX, _T("Id"), m_nId, 0);
  842. PX_Int(pPX, _T("IconId"), m_nIconId, 0);
  843. PX_Bool(pPX, _T("ShowOptionButton"), m_bShowOptionButton, FALSE);
  844. PX_String(pPX, _T("Caption"), m_strCaption, _T(""));
  845. PX_Bool(pPX, _T("ControlsGrouping"), m_bControlsGrouping, FALSE);
  846. PX_Bool(pPX, _T("ControlsCentering"), m_bControlsCentering, FALSE);
  847. PX_Bool(pPX, _T("Visible"), m_bVisible, TRUE);
  848. if (pPX->IsStoring())
  849. {
  850. CXTPPropExchangeSection secControls(pPX->GetSection(_T("Controls")));
  851. long nCount = 0;
  852. int i;
  853. for (i = 0; i < m_arrControls.GetSize(); i++)
  854. {
  855. CXTPControl* pControl = GetAt(i);
  856. if (!pControl->IsTemporary()) nCount++;
  857. }
  858. CXTPPropExchangeEnumeratorPtr pEnumerator(secControls->GetEnumerator(_T("Control")));
  859. POSITION posEnum = pEnumerator->GetPosition(nCount, FALSE);
  860. for (i = 0; i < (int)m_arrControls.GetSize(); i++)
  861. {
  862. CXTPControl* pControl = GetAt(i);
  863. if (!pControl->IsTemporary())
  864. {
  865. CXTPPropExchangeSection secItem(pEnumerator->GetNext(posEnum));
  866. PX_Object(&secItem, pControl, RUNTIME_CLASS(CXTPControl));
  867. }
  868. }
  869. }
  870. else
  871. {
  872. m_pGroups = (CXTPRibbonGroups*)pPX->m_pOwner;
  873. m_pParent = m_pRibbonBar = m_pGroups->GetRibbonBar();
  874. OnGroupAdded();
  875. CXTPPropExchangeSection secControls(pPX->GetSection(_T("Controls")));
  876. CXTPPropExchangeEnumeratorPtr pEnumerator(secControls->GetEnumerator(_T("Control")));
  877. POSITION posEnum = pEnumerator->GetPosition(0, FALSE);
  878. RemoveAll();
  879. while (posEnum)
  880. {
  881. CXTPPropExchangeSection secItem(pEnumerator->GetNext(posEnum));
  882. CXTPControl* pControl = NULL;
  883. PX_Object(&secItem, pControl, RUNTIME_CLASS(CXTPControl));
  884. if (!pControl)
  885. AfxThrowArchiveException(CArchiveException::badClass);
  886. pControl->m_pRibbonGroup = this;
  887. pControl->InternalAddRef();
  888. m_pRibbonBar->GetControls()->InsertAt(pControl, m_pControlGroupOption->GetIndex());
  889. m_arrControls.Add(pControl);
  890. }
  891. }
  892. CXTPPropExchangeSection secControlGroupOption(pPX->GetSection(_T("ControlGroupOption")));
  893. m_pControlGroupOption->DoPropExchange(&secControlGroupOption);
  894. CXTPPropExchangeSection secControlGroupPopup(pPX->GetSection(_T("ControlGroupPopup")));
  895. m_pControlGroupPopup->DoPropExchange(&secControlGroupPopup);
  896. }
  897. void CXTPRibbonGroups::DoPropExchange(CXTPPropExchange* pPX)
  898. {
  899. if (pPX->IsStoring())
  900. {
  901. long nCount = GetCount();
  902. int i;
  903. CXTPPropExchangeEnumeratorPtr pEnumerator(pPX->GetEnumerator(_T("Group")));
  904. POSITION posEnum = pEnumerator->GetPosition(nCount, FALSE);
  905. for (i = 0; i < nCount; i++)
  906. {
  907. CXTPRibbonGroup* pGroup = GetAt(i);
  908. CXTPPropExchangeSection secItem(pEnumerator->GetNext(posEnum));
  909. PX_Object(&secItem, pGroup, RUNTIME_CLASS(CXTPRibbonGroup));
  910. }
  911. }
  912. else
  913. {
  914. CXTPPropExchangeEnumeratorPtr pEnumerator(pPX->GetEnumerator(_T("Group")));
  915. POSITION posEnum = pEnumerator->GetPosition(0, FALSE);
  916. RemoveAll();
  917. while (posEnum)
  918. {
  919. CXTPPropExchangeSection secItem(pEnumerator->GetNext(posEnum));
  920. secItem->m_pOwner = this;
  921. CXTPRibbonGroup* pGroup = NULL;
  922. PX_Object(&secItem, pGroup, RUNTIME_CLASS(CXTPRibbonGroup));
  923. if (!pGroup)
  924. AfxThrowArchiveException(CArchiveException::badClass);
  925. m_arrGroups.Add(pGroup);
  926. RefreshIndexes();
  927. }
  928. }
  929. }