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

对话框与窗口

开发平台:

Visual C++

  1. // XTPReportRows.cpp : implementation of the CXTPReportRows class.
  2. //
  3. // This file is a part of the XTREME REPORTCONTROL 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/XTPVc50Helpers.h"
  22. #include "XTPReportRow.h"
  23. #include "XTPReportGroupRow.h"
  24. #include "XTPReportRecord.h"
  25. #include "XTPReportRecords.h"
  26. #include "XTPReportRecordItem.h"
  27. #include "XTPReportRecordItemText.h"
  28. #include "XTPReportControl.h"
  29. #include "XTPReportColumns.h"
  30. #include "XTPReportColumn.h"
  31. #include "XTPReportInplaceControls.h"
  32. #include "XTPReportRows.h"
  33. #ifdef _DEBUG
  34. #define new DEBUG_NEW
  35. #undef THIS_FILE
  36. static char THIS_FILE[] = __FILE__;
  37. #endif
  38. //////////////////////////////////////////////////////////////////////////
  39. // CXTPReportRows
  40. CXTPReportRows::CXTPReportRows()
  41. {
  42. m_pVirtualRow = 0;
  43. m_nVirtualRowsCount = 0;
  44. }
  45. CXTPReportRows::~CXTPReportRows()
  46. {
  47. Clear();
  48. }
  49. //////////////////////////////////////////////////////////////////////////
  50. // CXTPReportRows member functions
  51. void CXTPReportRows::Clear(BOOL bResetRow)
  52. {
  53. // array cleanup
  54. for (int nRow = (int)m_arrRows.GetSize() - 1; nRow >= 0; nRow--)
  55. {
  56. CXTPReportRow* pRow = m_arrRows.GetAt(nRow);
  57. if (bResetRow)
  58. {
  59. pRow->m_bVisible = FALSE;
  60. pRow->m_nIndex = -1;
  61. }
  62. pRow->InternalRelease();
  63. }
  64. m_arrRows.RemoveAll();
  65. if (m_pVirtualRow)
  66. {
  67. m_pVirtualRow->InternalRelease();
  68. m_pVirtualRow = 0;
  69. }
  70. }
  71. CXTPReportRow* CXTPReportRows::GetNext(CXTPReportRow* pRow, BOOL bSkipGroupFocus)
  72. {
  73. if (pRow)
  74. {
  75. int index = pRow->GetIndex();
  76. while (index < GetCount() - 1)
  77. {
  78. index++;
  79. pRow = GetAt(index);
  80. if (!bSkipGroupFocus || !pRow->IsGroupRow() || !pRow->IsExpanded())
  81. return pRow;
  82. }
  83. }
  84. else if (GetCount() > 0)
  85. {
  86. return GetAt(0);
  87. }
  88. return pRow;
  89. }
  90. CXTPReportRow* CXTPReportRows::GetPrev(CXTPReportRow* pRow, BOOL bSkipGroupFocus)
  91. {
  92. if (pRow)
  93. {
  94. int index = pRow->GetIndex();
  95. while (index > 0)
  96. {
  97. index--;
  98. pRow = GetAt(index);
  99. if (!bSkipGroupFocus || !pRow->IsGroupRow() || !pRow->IsExpanded())
  100. return pRow;
  101. }
  102. }
  103. else if (GetCount() > 0)
  104. {
  105. return GetAt(0);
  106. }
  107. return pRow;
  108. }
  109. void CXTPReportRows::InsertAt(int nIndex, CXTPReportRow* pRow)
  110. {
  111. m_arrRows.InsertAt(nIndex, pRow);
  112. }
  113. int CXTPReportRows::Add(CXTPReportRow* pRow)
  114. {
  115. int nIndex = (int)m_arrRows.Add(pRow);
  116. pRow->m_nChildIndex = nIndex;
  117. pRow->m_pParentRows = this;
  118. return nIndex;
  119. }
  120. void CXTPReportRows::RemoveAt(int nIndex)
  121. {
  122. m_arrRows.GetAt(nIndex)->InternalRelease();
  123. m_arrRows.RemoveAt(nIndex);
  124. }
  125. int CXTPReportRows::RemoveRow(CXTPReportRow* pRow)
  126. {
  127. for (int i = 0; i < (int)m_arrRows.GetSize(); i++)
  128. {
  129. if (m_arrRows.GetAt(i) == pRow)
  130. {
  131. RemoveAt(i);
  132. return i;
  133. }
  134. }
  135. return -1;
  136. }
  137. void CXTPReportRows::SetVirtualMode(CXTPReportRow* pRow, int nCount)
  138. {
  139. ASSERT(m_pVirtualRow == NULL);
  140. m_pVirtualRow = pRow;
  141. m_nVirtualRowsCount = nCount;
  142. }
  143. int _cdecl CXTPReportRows::CompareRows(const CXTPReportRow** ppRow1, const CXTPReportRow** ppRow2)
  144. {
  145. CXTPReportColumns* pColumns = (**ppRow1).GetControl()->GetColumns();
  146. CXTPReportRecord* pRecord1 = (**ppRow1).GetRecord();
  147. CXTPReportRecord* pRecord2 = (**ppRow2).GetRecord();
  148. ASSERT(pColumns);
  149. ASSERT(pRecord1 && pRecord2 || !pRecord1 && !pRecord2);
  150. if (pRecord1 == pRecord2 && pRecord1)
  151. return 0;
  152. if (!pRecord1 && !pRecord2)
  153. {
  154. // compare groupRows by its first not group child rows
  155. if ((*ppRow1)->HasChildren() && (*ppRow2)->HasChildren())
  156. {
  157. CXTPReportRow* pRow1a = (CXTPReportRow*)(*ppRow1);
  158. CXTPReportRow* pRow2a = (CXTPReportRow*)(*ppRow2);
  159. if (pRow1a->GetChilds() && pRow1a->GetChilds()->GetCount() &&
  160. pRow2a->GetChilds() && pRow2a->GetChilds()->GetCount())
  161. {
  162. pRow1a = pRow1a->GetChilds()->GetAt(0);
  163. pRow2a = pRow2a->GetChilds()->GetAt(0);
  164. return CompareRows((const CXTPReportRow**)&pRow1a, (const CXTPReportRow**)&pRow2a);
  165. }
  166. }
  167. }
  168. if (!pRecord1 || !pRecord2)
  169. {
  170. ASSERT(FALSE);
  171. return 0;
  172. }
  173. for (int nGroupOrder = 0; nGroupOrder < pColumns->GetGroupsOrder()->GetCount(); nGroupOrder++)
  174. {
  175. CXTPReportColumn* pColumn = pColumns->GetGroupsOrder()->GetAt(nGroupOrder);
  176. if (!pColumn->m_bAutoSortWhenGrouped)
  177. continue;
  178. BOOL bIncreasing = pColumn->m_bSortIncreasing;
  179. CXTPReportRecordItem* pItem1 = pRecord1->GetItem(pColumn);
  180. CXTPReportRecordItem* pItem2 = pRecord2->GetItem(pColumn);
  181. if (!pItem1 || !pItem2)
  182. continue;
  183. int nCompareResult = pItem1->CompareGroupCaption(pColumn, pItem2);
  184. if (nCompareResult != 0)
  185. return nCompareResult * (bIncreasing ? 1 : -1);
  186. }
  187. for (int nSortOrder = 0; nSortOrder < pColumns->GetSortOrder()->GetCount(); nSortOrder++)
  188. {
  189. CXTPReportColumn* pColumn = pColumns->GetSortOrder()->GetAt(nSortOrder);
  190. BOOL bIncreasing = pColumn->IsSortedIncreasing();
  191. CXTPReportRecordItem* pItem1 = pRecord1->GetItem(pColumn);
  192. CXTPReportRecordItem* pItem2 = pRecord2->GetItem(pColumn);
  193. if (!pItem1 || !pItem2)
  194. continue;
  195. int nCompareResult = pItem1->Compare(pColumn, pItem2);
  196. if (nCompareResult != 0)
  197. return nCompareResult * (bIncreasing ? 1 : -1);
  198. }
  199. return pRecord1->GetIndex() > pRecord2->GetIndex() ? 1 : -1;
  200. }
  201. int _cdecl CXTPReportRows::CompareRows2(const CXTPReportRow** ppRow1, const CXTPReportRow** ppRow2)
  202. {
  203. CXTPReportColumns* pColumns = (**ppRow1).GetControl()->GetColumns();
  204. CXTPReportRecord* pRecord1 = (**ppRow1).GetRecord();
  205. CXTPReportRecord* pRecord2 = (**ppRow2).GetRecord();
  206. ASSERT(pColumns);
  207. ASSERT(pRecord1 && pRecord2 || !pRecord1 && !pRecord2);
  208. if (pRecord1 == pRecord2 && pRecord1)
  209. return 0;
  210. if (!pRecord1 && !pRecord2)
  211. {
  212. // compare groupRows by its first not group child rows
  213. if ((*ppRow1)->HasChildren() && (*ppRow2)->HasChildren())
  214. {
  215. CXTPReportRow* pRow1a = (CXTPReportRow*)(*ppRow1);
  216. CXTPReportRow* pRow2a = (CXTPReportRow*)(*ppRow2);
  217. if (pRow1a->GetChilds() && pRow1a->GetChilds()->GetCount() &&
  218. pRow2a->GetChilds() && pRow2a->GetChilds()->GetCount())
  219. {
  220. pRow1a = pRow1a->GetChilds()->GetAt(0);
  221. pRow2a = pRow2a->GetChilds()->GetAt(0);
  222. return CompareRows((const CXTPReportRow**)&pRow1a, (const CXTPReportRow**)&pRow2a);
  223. }
  224. }
  225. }
  226. if (!pRecord1 || !pRecord2)
  227. {
  228. ASSERT(FALSE);
  229. return 0;
  230. }
  231. for (int nGroupOrder = 0; nGroupOrder < pColumns->GetGroupsOrder()->GetCount(); nGroupOrder++)
  232. {
  233. CXTPReportColumn* pColumn = pColumns->GetGroupsOrder()->GetAt(nGroupOrder);
  234. if (!pColumn->m_bAutoSortWhenGrouped)
  235. continue;
  236. BOOL bIncreasing = pColumn->m_bSortIncreasing;
  237. CXTPReportRecordItem* pItem1 = pRecord1->GetItem(pColumn);
  238. CXTPReportRecordItem* pItem2 = pRecord2->GetItem(pColumn);
  239. if (!pItem1 || !pItem2)
  240. continue;
  241. int nCompareResult = pItem1->CompareGroupCaption(pColumn, pItem2);
  242. if (nCompareResult != 0)
  243. {
  244. if(nGroupOrder > 0)
  245. nCompareResult = bIncreasing ? -1 : 1;
  246. return nCompareResult * (bIncreasing ? 1 : -1);
  247. }
  248. }
  249. for (int nSortOrder = 0; nSortOrder < pColumns->GetSortOrder()->GetCount(); nSortOrder++)
  250. {
  251. CXTPReportColumn* pColumn = pColumns->GetSortOrder()->GetAt(nSortOrder);
  252. BOOL bIncreasing = pColumn->IsSortedIncreasing();
  253. CXTPReportRecordItem* pItem1 = pRecord1->GetItem(pColumn);
  254. CXTPReportRecordItem* pItem2 = pRecord2->GetItem(pColumn);
  255. if (!pItem1 || !pItem2)
  256. continue;
  257. int nCompareResult = pItem1->Compare(pColumn, pItem2);
  258. if (nCompareResult != 0)
  259. return nCompareResult * (bIncreasing ? 1 : -1);
  260. }
  261. return 0;
  262. }
  263. void CXTPReportRows::SortEx(T_CompareFunc pCompareFunc)
  264. {
  265. typedef int (_cdecl *GENERICCOMPAREFUNC)(const void *, const void*);
  266. qsort(m_arrRows.GetData(), (size_t)m_arrRows.GetSize(), sizeof(CXTPReportRow*), (GENERICCOMPAREFUNC)pCompareFunc);
  267. }
  268. void CXTPReportRows::Sort()
  269. {
  270. SortEx(CompareRows);
  271. }
  272. int CXTPReportRows::GetCount() const
  273. {
  274. if (m_pVirtualRow)
  275. return m_nVirtualRowsCount;
  276. return (int)m_arrRows.GetSize();
  277. }
  278. CXTPReportRow* CXTPReportRows::GetAt(int nIndex) const
  279. {
  280. if (m_pVirtualRow)
  281. {
  282. m_pVirtualRow->m_nIndex = nIndex;
  283. return m_pVirtualRow;
  284. }
  285. return (nIndex >= 0) && (nIndex < GetCount()) ? m_arrRows.GetAt(nIndex) : NULL;
  286. }
  287. CXTPReportRow* CXTPReportRows::Find(CXTPReportRecord* pRecord)
  288. {
  289. for (int i = 0; i < (int)m_arrRows.GetSize(); i++)
  290. {
  291. if (m_arrRows.GetAt(i)->GetRecord() == pRecord)
  292. return m_arrRows.GetAt(i);
  293. }
  294. return 0;
  295. }
  296. CXTPReportRow* CXTPReportRows::FindInTree(CXTPReportRecord* pRecord)
  297. {
  298. for (int i = 0; i < (int)m_arrRows.GetSize(); i++)
  299. {
  300. if (m_arrRows.GetAt(i)->GetRecord() == pRecord)
  301. return m_arrRows.GetAt(i);
  302. if (m_arrRows.GetAt(i)->HasChildren())
  303. {
  304. CXTPReportRow* pRow = m_arrRows.GetAt(i)->GetChilds()->FindInTree(pRecord);
  305. if (pRow)
  306. return pRow;
  307. }
  308. }
  309. return 0;
  310. }
  311. CXTPReportRow* CXTPReportRows::FindInsertionPos(CXTPReportRow* pRow, BOOL& bInsertAfter)
  312. {
  313. CXTPReportRow* pInsertionRowPos = NULL;
  314. bInsertAfter = FALSE;
  315. for(int i = 0; i < (int)m_arrRows.GetSize(); i++)
  316. {
  317. CXTPReportRow* pCurRow = m_arrRows.GetAt(i);
  318. if(pCurRow->IsGroupRow())
  319. {
  320. // compare group caption
  321. CXTPReportRecord* pRecord = pRow->GetRecord();
  322. CXTPReportColumns* pColumns = pRow->GetControl()->GetColumns();
  323. if(!(pRecord && pColumns))
  324. continue;
  325. CXTPReportColumn* pColumn = pColumns->GetGroupsOrder()->GetAt(pCurRow->GetGroupLevel());
  326. CXTPReportRecordItem* pItem = pRecord->GetItem(pColumn);
  327. COleVariant varGroup(pItem ? (LPCTSTR)pItem->GetGroupCaption(pColumn) : _T(""));
  328. COleVariant varGroupRowCaption((LPCTSTR)((CXTPReportGroupRow*)pCurRow)->GetCaption());
  329. ULONG dwFlags = pRecord->GetRecords()->IsCaseSensitive() ? 0 : NORM_IGNORECASE;
  330. LCID lcidnSortLocale = CXTPReportRecordItemVariant::m_nSortLocale;
  331. if (lcidnSortLocale == LOCALE_USER_DEFAULT)
  332. {
  333. lcidnSortLocale = CXTPReportControlLocale::GetActiveLCID();
  334. }
  335. int nCompareResult = VARCMP_S(varGroup, varGroupRowCaption, lcidnSortLocale, dwFlags) - VARCMP_EQ;
  336. if(pColumn->m_bSortIncreasing && nCompareResult > 0 || !pColumn->m_bSortIncreasing && nCompareResult < 0)
  337. continue;
  338. // find in children
  339. if(!pCurRow->GetChilds())
  340. continue;
  341. if(nCompareResult == 0)
  342. pInsertionRowPos = pCurRow->GetChilds()->FindInsertionPos(pRow, bInsertAfter);
  343. if(!pInsertionRowPos)
  344. {
  345. if(nCompareResult != 0)
  346. pInsertionRowPos = pCurRow;
  347. else
  348. {
  349. pInsertionRowPos = pCurRow->GetChilds()->GetAt(pCurRow->GetChilds()->GetCount() - 1);
  350. bInsertAfter = TRUE;
  351. }
  352. }
  353. break;
  354. }
  355. if(CompareRows2((const CXTPReportRow**)&pRow, (const CXTPReportRow**)&pCurRow) <= 0)
  356. {
  357. pInsertionRowPos = pCurRow;
  358. break;
  359. }
  360. }
  361. return pInsertionRowPos;
  362. }
  363. void CXTPReportRows::RefreshChildIndices(BOOL bRunInChildren)
  364. {
  365. for(int nIndex = 0; nIndex < GetCount(); nIndex++)
  366. {
  367. CXTPReportRow* pRow = GetAt(nIndex);
  368. pRow->m_nChildIndex = nIndex;
  369. ASSERT(pRow->m_pParentRows == this);
  370. if(bRunInChildren && pRow->HasChildren() && pRow->GetChilds())
  371. pRow->GetChilds()->RefreshChildIndices(bRunInChildren);
  372. }
  373. }
  374. void CXTPReportRows::SetSize(INT_PTR nNewSize, INT_PTR nGrowBy)
  375. {
  376. int nSize = GetCount();
  377. if (nNewSize < nSize)
  378. {
  379. for (int i = (int)nNewSize; i < nSize; i++)
  380. {
  381. CXTPReportRow* pRow = GetAt(i);
  382. if (pRow)
  383. pRow->InternalRelease();
  384. }
  385. }
  386. m_arrRows.SetSize(nNewSize, nGrowBy);
  387. }
  388. void CXTPReportRows::ReserveSize(INT_PTR nNewSize, INT_PTR nGrowBy)
  389. {
  390. m_arrRows.ReserveSize(nNewSize, nGrowBy);
  391. }
  392. void CXTPReportRows::SetAt(INT_PTR nIndex, CXTPReportRow* pRow)
  393. {
  394. ASSERT(pRow);
  395. ASSERT(nIndex >= 0 && nIndex < GetCount());
  396. if (!pRow || nIndex < 0 || nIndex >= GetCount())
  397. return;
  398. CXTPReportRow* pRow_prev = GetAt((int)nIndex);
  399. if (pRow_prev)
  400. pRow_prev->InternalRelease();
  401. pRow->m_nChildIndex = (int)nIndex;
  402. pRow->m_pParentRows = this;
  403. m_arrRows.SetAt(nIndex, pRow);
  404. }
  405. //////////////////////////////////////////////////////////////////////////
  406. // CXTPReportSelectedRows
  407. CXTPReportSelectedRows::CXTPReportSelectedRows(CXTPReportControl* pControl)
  408. : m_pControl(pControl)
  409. {
  410. m_nRowBlockBegin = -1;
  411. m_nPosSelected = 0;
  412. m_bChanged = FALSE;
  413. m_nRowType = xtpRowTypeBody;
  414. }
  415. void CXTPReportSelectedRows::Clear()
  416. {
  417. if (m_arrSelectedBlocks.GetSize() > 0)
  418. {
  419. m_bChanged = TRUE;
  420. _NotifySelChanging(xtpReportSelectionClear);
  421. }
  422. m_arrSelectedBlocks.RemoveAll();
  423. m_nRowBlockBegin = -1;
  424. m_nRowType = xtpRowTypeBody;
  425. m_pControl->RedrawControl();
  426. }
  427. void CXTPReportSelectedRows::_InsertBlock(int nIndexInsert, int nIndexBegin, int nIndexEnd)
  428. {
  429. SELECTED_BLOCK block;
  430. block.nIndexBegin = nIndexBegin;
  431. block.nIndexEnd = nIndexEnd;
  432. m_arrSelectedBlocks.InsertAt(nIndexInsert, block);
  433. }
  434. void CXTPReportSelectedRows::_OnCollapsed(int nIndex, int nCount)
  435. {
  436. ASSERT(nCount > 0);
  437. for (int i = (int)m_arrSelectedBlocks.GetSize() - 1; i >= 0 ; i--)
  438. {
  439. int& nIndexBegin = m_arrSelectedBlocks[i].nIndexBegin;
  440. int& nIndexEnd = m_arrSelectedBlocks[i].nIndexEnd;
  441. if (nIndexBegin <= nIndex && nIndexEnd > nIndex + 1)
  442. {
  443. nIndexEnd = max(nIndexBegin + 1, nIndexEnd - nCount);
  444. }
  445. else if (nIndexBegin > nIndex + nCount)
  446. {
  447. nIndexBegin -= nCount;
  448. nIndexEnd -= nCount;
  449. }
  450. else if (nIndexEnd < nIndex)
  451. break;
  452. else if (nIndexBegin > nIndex)
  453. {
  454. nIndexBegin = nIndex;
  455. nIndexEnd = max(nIndexBegin + 1, nIndexEnd - nCount);
  456. }
  457. }
  458. }
  459. void CXTPReportSelectedRows::_OnExpanded(int nIndex, int nCount)
  460. {
  461. ASSERT(nCount > 0);
  462. for (int i = (int)m_arrSelectedBlocks.GetSize() - 1; i >= 0 ; i--)
  463. {
  464. int& nIndexBegin = m_arrSelectedBlocks[i].nIndexBegin;
  465. int& nIndexEnd = m_arrSelectedBlocks[i].nIndexEnd;
  466. if (nIndexBegin <= nIndex && nIndexEnd > nIndex + 1)
  467. {
  468. _InsertBlock(i + 1, nIndex + 1 + nCount, nIndexEnd + nCount);
  469. m_arrSelectedBlocks[i].nIndexEnd = nIndex + 1;
  470. }
  471. else if (nIndexBegin > nIndex)
  472. {
  473. nIndexBegin += nCount;
  474. nIndexEnd += nCount;
  475. }
  476. else if (nIndexEnd < nIndex)
  477. break;
  478. }
  479. }
  480. void CXTPReportSelectedRows::AddBlock(int ib, int ie)
  481. {
  482. int i = 0;
  483. int nCount = (int)m_arrSelectedBlocks.GetSize();
  484. if (nCount > 0)
  485. {
  486. int& nIndexEnd = m_arrSelectedBlocks[nCount - 1].nIndexEnd;
  487. if (nIndexEnd == ib)
  488. {
  489. nIndexEnd = ie + 1;
  490. m_pControl->RedrawControl();
  491. return;
  492. }
  493. if (nIndexEnd < ib)
  494. {
  495. i = nCount;
  496. }
  497. }
  498. for (; i < nCount; i++)
  499. {
  500. int& nIndexBegin = m_arrSelectedBlocks[i].nIndexBegin;
  501. int& nIndexEnd = m_arrSelectedBlocks[i].nIndexEnd;
  502. if ((nIndexBegin <= ib) && (nIndexEnd > ie))
  503. {
  504. return;
  505. }
  506. if (nIndexEnd == ib)
  507. {
  508. nIndexEnd = ie + 1;
  509. if (i + 1 < nCount && m_arrSelectedBlocks[i + 1].nIndexBegin == nIndexEnd)
  510. {
  511. nIndexEnd = m_arrSelectedBlocks[i + 1].nIndexEnd;
  512. m_arrSelectedBlocks.RemoveAt(i + 1);
  513. }
  514. m_pControl->RedrawControl();
  515. return;
  516. }
  517. if (nIndexBegin == ie + 1)
  518. {
  519. nIndexBegin = ib;
  520. m_pControl->RedrawControl();
  521. return;
  522. }
  523. if (nIndexBegin > ie)
  524. break;
  525. }
  526. _InsertBlock(i, ib, ie + 1);
  527. m_pControl->RedrawControl();
  528. }
  529. void CXTPReportSelectedRows::Add(CXTPReportRow* pRow)
  530. {
  531. if (!pRow)
  532. return;
  533. _NotifySelChanging(xtpReportSelectionAdd, pRow);
  534. int nIndex = pRow->GetIndex();
  535. if (nIndex != -1)
  536. {
  537. AddBlock(nIndex, nIndex);
  538. }
  539. }
  540. void CXTPReportSelectedRows::Remove(CXTPReportRow* pRow)
  541. {
  542. if (!pRow)
  543. return;
  544. _NotifySelChanging(xtpReportSelectionRemove, pRow);
  545. int nIndex = pRow->GetIndex();
  546. for (int i = 0; i < (int)m_arrSelectedBlocks.GetSize(); i++)
  547. {
  548. int nIndexBegin = m_arrSelectedBlocks[i].nIndexBegin;
  549. int nIndexEnd = m_arrSelectedBlocks[i].nIndexEnd;
  550. if ((nIndexBegin <= nIndex) && (nIndexEnd > nIndex))
  551. {
  552. if (nIndexBegin != nIndex)
  553. {
  554. _InsertBlock(i, nIndexBegin, nIndex);
  555. i++;
  556. }
  557. if (nIndexEnd - 1 != nIndex)
  558. {
  559. _InsertBlock(i + 1, nIndex + 1, nIndexEnd);
  560. }
  561. m_arrSelectedBlocks.RemoveAt(i);
  562. m_pControl->RedrawControl();
  563. return;
  564. }
  565. }
  566. }
  567. void CXTPReportSelectedRows::Select(CXTPReportRow* pRow)
  568. {
  569. if (!pRow)
  570. return;
  571. // If new selected row belongs to the other type - clear previous selection.
  572. if (m_nRowType != pRow->GetType())
  573. Clear();
  574. if (m_arrSelectedBlocks.GetSize() == 1 && m_arrSelectedBlocks[0].nIndexBegin ==
  575. m_arrSelectedBlocks[0].nIndexEnd - 1 && m_arrSelectedBlocks[0].nIndexBegin == pRow->GetIndex())
  576. {
  577. }
  578. else
  579. {
  580. Clear();
  581. Add(pRow);
  582. m_bChanged = TRUE;
  583. m_nRowType = pRow->GetType();
  584. }
  585. }
  586. void CXTPReportSelectedRows::SelectBlock(int nBlockBegin, int nEnd)
  587. {
  588. CXTPReportRows* pRows;
  589. switch(m_nRowType)
  590. {
  591. case xtpRowTypeHeader : pRows = m_pControl->GetHeaderRows(); break;
  592. case xtpRowTypeFooter : pRows = m_pControl->GetFooterRows(); break;
  593. default : pRows = m_pControl->GetRows(); break;
  594. }
  595. ASSERT(nBlockBegin >= 0 && nBlockBegin < pRows->GetCount() && nEnd < pRows->GetCount() );
  596. nBlockBegin = m_nRowBlockBegin != -1 ? m_nRowBlockBegin : nBlockBegin;
  597. int nBegin = nBlockBegin;
  598. if (nBegin == -1 || nEnd == -1)
  599. return;
  600. if (nBegin > nEnd)
  601. {
  602. nBegin = nEnd;
  603. nEnd = nBlockBegin;
  604. }
  605. if (m_arrSelectedBlocks.GetSize() == 1 && m_arrSelectedBlocks[0].nIndexBegin == nBegin &&
  606. m_arrSelectedBlocks[0].nIndexEnd == nEnd + 1)
  607. {
  608. return;
  609. }
  610. XTPReportRowType nRowType = m_nRowType;
  611. Clear();
  612. m_nRowType = nRowType;
  613. if (m_nRowBlockBegin == -1) m_nRowBlockBegin = nBlockBegin;
  614. BOOL bSkipGroupFocus = m_pControl->IsSkipGroupsFocusEnabled();
  615. BOOL bHasGroups = m_pControl->GetColumns()->GetGroupsOrder()->GetCount() != 0;
  616. if (!bHasGroups || !bSkipGroupFocus)
  617. {
  618. _InsertBlock(0, nBegin, nEnd + 1);
  619. }
  620. else
  621. {
  622. for (int i = nBegin; i <= nEnd; i++)
  623. {
  624. CXTPReportRow* pRow = pRows->GetAt(i);
  625. if (!pRow)
  626. continue;
  627. if (!bSkipGroupFocus || !pRow->IsGroupRow() || !pRow->IsExpanded() || (i == nBegin) || (i == nEnd))
  628. {
  629. Add(pRow);
  630. }
  631. }
  632. }
  633. }
  634. BOOL CXTPReportSelectedRows::Contains(const CXTPReportRow* pRow)
  635. {
  636. if (!pRow)
  637. return FALSE;
  638. if (m_nRowType != pRow->GetType())
  639. return FALSE;
  640. int nIndex = pRow->GetIndex();
  641. int nCount = (int)m_arrSelectedBlocks.GetSize();
  642. if (nCount == 0)
  643. return FALSE;
  644. if (m_arrSelectedBlocks[0].nIndexBegin > nIndex)
  645. return FALSE;
  646. if (m_arrSelectedBlocks[nCount - 1].nIndexEnd <= nIndex)
  647. return FALSE;
  648. for (int i = 0; i < nCount; i++)
  649. {
  650. if ((m_arrSelectedBlocks[i].nIndexBegin <= nIndex) &&
  651. (m_arrSelectedBlocks[i].nIndexEnd > nIndex))
  652. {
  653. return TRUE;
  654. }
  655. }
  656. return FALSE;
  657. }
  658. void CXTPReportSelectedRows::Invert(CXTPReportRow* pRow)
  659. {
  660. if(pRow->GetType() != m_nRowType)
  661. return;
  662. if (Contains(pRow))
  663. Remove (pRow);
  664. else Add(pRow);
  665. m_nRowBlockBegin = -1;
  666. m_bChanged = TRUE;
  667. }
  668. int CXTPReportSelectedRows::GetCount()
  669. {
  670. int nCount = 0;
  671. for (int i = 0; i < (int)m_arrSelectedBlocks.GetSize(); i++)
  672. {
  673. nCount += m_arrSelectedBlocks[i].nIndexEnd - m_arrSelectedBlocks[i].nIndexBegin;
  674. }
  675. return nCount;
  676. }
  677. POSITION CXTPReportSelectedRows::GetFirstSelectedRowPosition()
  678. {
  679. if (m_arrSelectedBlocks.GetSize() == 0)
  680. return 0;
  681. m_nPosSelected = 0;
  682. POSITION pos = 0;
  683. pos = (POSITION)(DWORD_PTR)(m_arrSelectedBlocks[0].nIndexBegin + 1);
  684. return pos;
  685. }
  686. CXTPReportRow* CXTPReportSelectedRows::GetNextSelectedRow(POSITION& pos)
  687. {
  688. ASSERT(m_nPosSelected < m_arrSelectedBlocks.GetSize());
  689. int nIndex = (int)(DWORD_PTR)pos - 1;
  690. CXTPReportRow* pRow;
  691. switch(m_nRowType)
  692. {
  693. case xtpRowTypeHeader : pRow = m_pControl->GetHeaderRows()->GetAt(nIndex); break;
  694. case xtpRowTypeFooter : pRow = m_pControl->GetFooterRows()->GetAt(nIndex); break;
  695. default : pRow = m_pControl->GetRows()->GetAt(nIndex); break;
  696. }
  697. if (nIndex < m_arrSelectedBlocks[m_nPosSelected].nIndexEnd - 1)
  698. {
  699. (int)(DWORD_PTR)pos++;
  700. }
  701. else
  702. {
  703. if (m_nPosSelected >= m_arrSelectedBlocks.GetSize() - 1)
  704. {
  705. pos = NULL;
  706. }
  707. else
  708. {
  709. m_nPosSelected++;
  710. pos = (POSITION)(DWORD_PTR)(m_arrSelectedBlocks[m_nPosSelected].nIndexBegin + 1);
  711. }
  712. }
  713. return pRow;
  714. }
  715. CXTPReportRow* CXTPReportSelectedRows::GetAt (int nIndex)
  716. {
  717. for (int i = 0; i < (int)m_arrSelectedBlocks.GetSize(); i++)
  718. {
  719. int nCount = m_arrSelectedBlocks[i].nIndexEnd - m_arrSelectedBlocks[i].nIndexBegin;
  720. if (nCount <= nIndex)
  721. {
  722. nIndex -= nCount;
  723. continue;
  724. }
  725. CXTPReportRow* pRow;
  726. switch(m_nRowType)
  727. {
  728. case xtpRowTypeHeader : pRow = m_pControl->GetHeaderRows()->GetAt(m_arrSelectedBlocks[i].nIndexBegin + nIndex); break;
  729. case xtpRowTypeFooter : pRow = m_pControl->GetFooterRows()->GetAt(m_arrSelectedBlocks[i].nIndexBegin + nIndex); break;
  730. default : pRow = m_pControl->GetRows()->GetAt(m_arrSelectedBlocks[i].nIndexBegin + nIndex); break;
  731. }
  732. return pRow;
  733. }
  734. return 0;
  735. }
  736. void CXTPReportSelectedRows::_NotifySelChanging(XTPReportSelectionChangeType nType, CXTPReportRow* pRow)
  737. {
  738. ASSERT(m_pControl);
  739. if (!m_pControl)
  740. return;
  741. XTP_NM_SELECTION_CHANGING nm;
  742. ::ZeroMemory(&nm, sizeof(nm));
  743. nm.pRow = pRow;
  744. nm.nType = nType;
  745. m_pControl->SendNotifyMessage(XTP_NM_REPORT_SELCHANGING,(NMHDR*)&nm);
  746. }