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

对话框与窗口

开发平台:

Visual C++

  1. // XTPReportRow.cpp : implementation of the CXTPReportRow 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 "Resource.h"
  22. #include "Common/XTPDrawHelpers.h"
  23. #include "Common/XTPToolTipContext.h"
  24. #include "XTPReportRecord.h"
  25. #include "XTPReportControl.h"
  26. #include "XTPReportPaintManager.h"
  27. #include "XTPReportRow.h"
  28. #include "XTPReportColumns.h"
  29. #include "XTPReportColumn.h"
  30. #include "XTPReportRecordItem.h"
  31. #include "XTPReportRecordItemText.h"
  32. #include "XTPReportTip.h"
  33. #include "XTPReportInplaceControls.h"
  34. #include "XTPReportHeader.h"
  35. #ifdef _DEBUG
  36. #define new DEBUG_NEW
  37. #undef THIS_FILE
  38. static char THIS_FILE[] = __FILE__;
  39. #endif
  40. IMPLEMENT_DYNAMIC(CXTPReportRow, CCmdTarget)
  41. /////////////////////////////////////////////////////////////////////////////
  42. // CXTPReportRow
  43. CXTPReportRow::CXTPReportRow()
  44. : m_pParentRow(NULL), m_pRecord(NULL), m_pControl(NULL), m_pParentRows(NULL)
  45. {
  46. m_nGroupLevel = m_nRowLevel = 0;
  47. m_bVisible = FALSE;
  48. m_pChilds = NULL;
  49. m_bExpanded = TRUE;
  50. m_rcRow.SetRectEmpty();
  51. m_rcCollapse.SetRectEmpty();
  52. m_nChildIndex = m_nIndex = -1;
  53. m_nPreviewHeight = 0;
  54. m_nRowType = xtpRowTypeBody;
  55. }
  56. void CXTPReportRow::InitRow(CXTPReportControl* pControl, CXTPReportRecord* pRecord)
  57. {
  58. ASSERT(pRecord || IsGroupRow());
  59. m_pControl = pControl;
  60. if (pRecord)
  61. {
  62. m_pRecord = pRecord;
  63. m_bExpanded = pRecord->m_bExpanded;
  64. m_pRecord->InternalAddRef();
  65. }
  66. }
  67. void CXTPReportRow::InitRow(CXTPReportRow* pRow)
  68. {
  69. ASSERT(pRow->m_pRecord);
  70. ASSERT(pRow->m_pParentRow == NULL);
  71. m_pControl = pRow->m_pControl;
  72. m_pRecord = pRow->m_pRecord;
  73. if (m_pRecord) m_pRecord->InternalAddRef();
  74. m_rcRow = pRow->m_rcRow;
  75. m_nIndex = pRow->m_nIndex;
  76. m_nPreviewHeight = pRow->m_nPreviewHeight;
  77. m_nRowLevel = pRow->m_nRowLevel;
  78. m_nGroupLevel = pRow->m_nGroupLevel;
  79. }
  80. CXTPReportRows* CXTPReportRow::GetChilds()
  81. {
  82. if (!m_pChilds)
  83. {
  84. m_pChilds = new CXTPReportRows();
  85. }
  86. return m_pChilds;
  87. }
  88. CXTPReportRow::~CXTPReportRow()
  89. {
  90. if (m_pChilds)
  91. {
  92. m_pChilds->InternalRelease();
  93. }
  94. if (m_pRecord)
  95. {
  96. m_pRecord->InternalRelease();
  97. }
  98. }
  99. int CXTPReportRow::GetHeight(CDC* pDC, int nWidth)
  100. {
  101. ASSERT(m_pControl);
  102. if (!m_pControl)
  103. return 0;
  104. int nHeight = m_pControl->GetPaintManager()->GetRowHeight(pDC, this, nWidth);
  105. if (!IsGroupRow() && !IsItemsVisible())
  106. nHeight = 0;
  107. if (pDC->IsPrinting())
  108. return nHeight;
  109. m_nPreviewHeight = 0;
  110. if (IsPreviewVisible())
  111. {
  112. CXTPReportRecordItemPreview* pItem = GetRecord()->GetItemPreview();
  113. m_nPreviewHeight = pItem->GetPreviewHeight(pDC, this, m_pControl->GetReportHeader()->GetWidth());
  114. m_nPreviewHeight = m_pControl->GetPaintManager()->GetPreviewItemHeight(pDC, this, m_pControl->GetReportHeader()->GetWidth(), m_nPreviewHeight);
  115. return nHeight + m_nPreviewHeight;
  116. }
  117. return nHeight;
  118. }
  119. BOOL CXTPReportRow::IsFocused() const
  120. {
  121. switch(m_nRowType)
  122. {
  123. case xtpRowTypeBody:
  124. return m_pControl->m_nFocusedRow == m_nIndex;
  125. case xtpRowTypeHeader:
  126. return m_pControl->m_nFocusedHeaderRow == m_nIndex;
  127. case xtpRowTypeFooter:
  128. return m_pControl->m_nFocusedFooterRow == m_nIndex;
  129. }
  130. return FALSE;
  131. }
  132. BOOL CXTPReportRow::IsSelected() const
  133. {
  134. return m_pControl->GetSelectedRows()->Contains(this);
  135. }
  136. void CXTPReportRow::SetSelected(BOOL bSelected)
  137. {
  138. if (bSelected)
  139. {
  140. if (!m_pControl->IsMultipleSelection())
  141. m_pControl->GetSelectedRows()->Clear();
  142. m_pControl->GetSelectedRows()->Add(this);
  143. }
  144. else
  145. {
  146. m_pControl->GetSelectedRows()->Remove(this);
  147. }
  148. m_pControl->RedrawControl();
  149. }
  150. int CXTPReportRow::GetLastChildRow(CXTPReportRows* pChilds) const
  151. {
  152. CXTPReportRow* pRow = pChilds->GetAt(pChilds->GetCount() - 1);
  153. return pRow->HasChildren() && pRow->IsExpanded() ? GetLastChildRow(pRow->GetChilds()) : pRow->GetIndex();
  154. }
  155. void CXTPReportRow::SelectChilds()
  156. {
  157. if (!(m_pControl->IsMultipleSelection() && HasChildren() && IsExpanded() && m_nIndex != -1))
  158. return;
  159. m_pControl->BeginUpdate();
  160. int nIndexBegin = m_nIndex + 1;
  161. int nIndexEnd = GetLastChildRow(GetChilds());
  162. m_pControl->GetSelectedRows()->AddBlock(nIndexBegin, nIndexEnd);
  163. m_pControl->EndUpdate();
  164. }
  165. BOOL CXTPReportRow::IsItemsVisible() const
  166. {
  167. return TRUE;
  168. }
  169. BOOL CXTPReportRow::IsPreviewVisible() const
  170. {
  171. return !IsGroupRow() && m_pRecord && m_pControl->IsPreviewMode() && m_pRecord->GetItemPreview() != NULL;
  172. }
  173. void CXTPReportRow::Draw(CDC* pDC, CRect rcRow, int nLeftOffset)
  174. {
  175. ASSERT(m_pControl);
  176. if (!m_pControl)
  177. return;
  178. BOOL bControlFocused = m_pControl->HasFocus();
  179. int nFreezeCols = m_pControl->m_nFreezeColumnsCount;
  180. CRect rcClipBox = m_pControl->GetReportRectangle();
  181. m_rcRow = rcRow;
  182. m_rcRow.left -= nLeftOffset;
  183. m_rcRow.right -= nLeftOffset;
  184. if (nFreezeCols == 0)
  185. {
  186. rcRow = m_rcRow;
  187. }
  188. XTP_REPORTRECORDITEM_DRAWARGS drawArgs;
  189. drawArgs.pDC = pDC;
  190. drawArgs.pControl = m_pControl;
  191. drawArgs.pRow = this;
  192. int nIndentWidth = m_pControl->GetHeaderIndent();
  193. CXTPReportPaintManager* pPaintManager = m_pControl->GetPaintManager();
  194. CXTPReportColumns arrVisibleColumns(m_pControl);
  195. m_pControl->GetColumns()->GetVisibleColumns(arrVisibleColumns);
  196. int nVisColCount = arrVisibleColumns.GetCount();
  197. nFreezeCols = min(nFreezeCols, nVisColCount);
  198. // paint row background
  199. pPaintManager->FillRow(pDC, this, m_rcRow);
  200. CRect rcItem(m_rcRow.left, m_rcRow.top, m_rcRow.right, m_rcRow.bottom - m_nPreviewHeight);
  201. CRect rcIndent(nFreezeCols ? rcRow : m_rcRow);
  202. rcIndent.right = rcIndent.left + nIndentWidth;
  203. if (m_pRecord) // if drawing record, not group
  204. {
  205. int xMinCol_0 = rcRow.left + nIndentWidth;
  206. // paint record items
  207. for (int nColumn = nVisColCount-1; nColumn >= 0; nColumn--)
  208. {
  209. BOOL bFreezeCol = nColumn < nFreezeCols;
  210. int nColIdx = bFreezeCol ? nFreezeCols - 1 - nColumn : nColumn;
  211. CXTPReportColumn* pColumn = arrVisibleColumns.GetAt(nColIdx);
  212. ASSERT(pColumn && pColumn->IsVisible());
  213. if (pColumn && IsItemsVisible())
  214. {
  215. rcItem.left = pColumn->GetRect().left;
  216. if (nColIdx == 0)
  217. {
  218. rcItem.left = max(xMinCol_0, rcItem.left);
  219. }
  220. rcItem.right = pColumn->GetRect().right;
  221. if (!CRect().IntersectRect(rcClipBox, rcItem))
  222. continue;
  223. if (bFreezeCol)
  224. {
  225. pDC->FillSolidRect(rcItem, pPaintManager->GetControlBackColor(GetControl()));
  226. pPaintManager->FillRow(pDC, this, rcItem);
  227. }
  228. CRect rcGridItem(rcItem);
  229. rcGridItem.left--;
  230. // draw shade background if sorted by this row
  231. if (pColumn->IsSorted())
  232. {
  233. pPaintManager->FillItemShade(pDC, rcItem);
  234. }
  235. CXTPReportRecordItem* pItem = m_pRecord->GetItem(pColumn);
  236. if (pItem)
  237. {
  238. // draw item
  239. drawArgs.pColumn = pColumn;
  240. drawArgs.rcItem = rcItem;
  241. drawArgs.nTextAlign = pColumn->GetAlignment();
  242. drawArgs.pItem = pItem;
  243. // draw item
  244. int nItemTextWidth = pItem->Draw(&drawArgs);
  245. pColumn->m_nMaxItemWidth = max(pColumn->m_nMaxItemWidth, nItemTextWidth);
  246. }
  247. pPaintManager->DrawGrid(pDC, TRUE, rcGridItem);
  248. if (nColIdx == nFreezeCols - 1)
  249. pPaintManager->DrawFreezeColsDivider(pDC, rcGridItem, GetControl(), this);
  250. }
  251. }
  252. if (IsPreviewVisible())
  253. {
  254. CRect rcPreviewItem(m_rcRow);
  255. rcPreviewItem.DeflateRect(nIndentWidth, rcPreviewItem.Height() - m_nPreviewHeight, 0, 0);
  256. drawArgs.rcItem = rcPreviewItem;
  257. drawArgs.nTextAlign = DT_LEFT;
  258. drawArgs.pItem = m_pRecord->GetItemPreview();
  259. drawArgs.pColumn = NULL;
  260. drawArgs.pItem->Draw(&drawArgs);
  261. }
  262. if (nIndentWidth > 0)
  263. {
  264. // draw indent column
  265. pPaintManager->FillIndent(pDC, rcIndent);
  266. }
  267. }
  268. BOOL bGridVisible = pPaintManager->IsGridVisible(FALSE);
  269. //CRect rcFocus(m_rcRow.left + nIndentWidth, m_rcRow.top, m_rcRow.right, m_rcRow.bottom - (bGridVisible ? 1 : 0));
  270. CRect rcFocus(rcIndent.right, m_rcRow.top, m_rcRow.right, m_rcRow.bottom - (bGridVisible ? 1 : 0));
  271. if (IsFocused() && bControlFocused && m_pControl->IsRowFocusVisible())
  272. pPaintManager->DrawFocusedRow(pDC, rcFocus);
  273. if (m_nIndex < m_pControl->GetRows()->GetCount() - 1 && nIndentWidth > 0)
  274. {
  275. CXTPReportRow* pNextRow = m_pControl->GetRows()->GetAt(m_nIndex + 1);
  276. ASSERT(pNextRow);
  277. if (pNextRow) rcFocus.left = rcIndent.left + min(nIndentWidth, pPaintManager->m_nTreeIndent * pNextRow->GetTreeDepth());
  278. }
  279. else
  280. {
  281. rcFocus.left = m_rcRow.left;
  282. }
  283. pPaintManager->DrawGrid(pDC, FALSE, rcFocus);
  284. }
  285. int CXTPReportRow::GetTreeDepth() const
  286. {
  287. return m_nRowLevel;
  288. }
  289. INT_PTR CXTPReportRow::OnToolHitTest(CPoint point, TOOLINFO* pTI)
  290. {
  291. CRect rcItem;
  292. CXTPReportRecordItem* pItem = HitTest(point, &rcItem);
  293. if (!pItem)
  294. return -1;
  295. INT_PTR nHit = (INT_PTR)pItem;
  296. CString strTip = pItem->GetTooltip();
  297. m_pControl->OnGetToolTipInfo(this, pItem, strTip);
  298. if (strTip.IsEmpty() || strTip == _T(" "))
  299. return -1;
  300. CXTPToolTipContext::FillInToolInfo(pTI, m_pControl->m_hWnd, rcItem,
  301. nHit, strTip);
  302. return nHit;
  303. }
  304. BOOL CXTPReportRow::OnLButtonDown(XTP_REPORTRECORDITEM_CLICKARGS* pClickArgs)
  305. {
  306. if(pClickArgs->pItem && pClickArgs->pItem->OnLButtonDown(pClickArgs))
  307. return TRUE;
  308. return (BOOL)m_pControl->SendMessageToParent(this, pClickArgs->pItem, pClickArgs->pColumn, XTP_NM_REPORT_LBUTTONDOWN, &pClickArgs->ptClient);
  309. }
  310. BOOL CXTPReportRow::OnLButtonUp(XTP_REPORTRECORDITEM_CLICKARGS* pClickArgs)
  311. {
  312. if(pClickArgs->pItem)
  313. pClickArgs->pItem->OnLButtonUp(pClickArgs);
  314. return TRUE;
  315. }
  316. void CXTPReportRow::OnClick(CPoint ptClicked)
  317. {
  318. XTP_REPORTRECORDITEM_CLICKARGS clickArgs;
  319. clickArgs.pControl = m_pControl;
  320. clickArgs.pRow = this;
  321. clickArgs.ptClient = ptClicked;
  322. clickArgs.pColumn = NULL;
  323. // find clicked item
  324. clickArgs.pItem = HitTest(ptClicked, &clickArgs.rcItem, &clickArgs.pColumn);
  325. if(m_pControl->IsVirtualMode())
  326. {
  327. if (m_nRowLevel == 0 && m_rcCollapse.PtInRect(ptClicked)
  328. && clickArgs.pColumn && clickArgs.pColumn->IsTreeColumn())
  329. {
  330. m_pControl->SendMessageToParent(this, NULL, NULL, XTP_NM_REPORT_ROWEXPANDED, NULL);
  331. return;
  332. }
  333. }
  334. if (HasChildren() && m_rcCollapse.PtInRect(ptClicked)
  335. && clickArgs.pColumn && clickArgs.pColumn->IsTreeColumn())
  336. {
  337. SetExpanded(!IsExpanded());
  338. return;
  339. }
  340. // notify item if found
  341. if (!clickArgs.pItem)
  342. return;
  343. clickArgs.pItem->OnClick(&clickArgs);
  344. }
  345. void CXTPReportRow::OnDblClick(CPoint ptClicked)
  346. {
  347. XTP_REPORTRECORDITEM_CLICKARGS clickArgs;
  348. clickArgs.pControl = m_pControl;
  349. clickArgs.pRow = this;
  350. clickArgs.ptClient = ptClicked;
  351. clickArgs.pColumn = NULL;
  352. // find clicked item
  353. clickArgs.pItem = HitTest(ptClicked, &clickArgs.rcItem, &clickArgs.pColumn);
  354. // notify item if found
  355. if (clickArgs.pItem != NULL)
  356. {
  357. clickArgs.pItem->OnDblClick(&clickArgs);
  358. }
  359. else
  360. {
  361. // just notify parent
  362. m_pControl->SendMessageToParent(this, NULL, clickArgs.pColumn, NM_DBLCLK, &ptClicked, -1);
  363. }
  364. }
  365. CRect CXTPReportRow::GetItemRect(CXTPReportRecordItem* pItem)
  366. {
  367. if (!IsItemsVisible() || !pItem || !m_pRecord)
  368. return CRect(0, 0, 0, 0);
  369. if (IsPreviewVisible() && pItem == GetRecord()->GetItemPreview())
  370. {
  371. return CRect(m_rcRow.left + m_pControl->GetHeaderIndent(),
  372. m_rcRow.bottom - m_nPreviewHeight, m_rcRow.right, m_rcRow.bottom);
  373. }
  374. CXTPReportColumns* pColumns = m_pControl->GetColumns();
  375. int nColumnCount = pColumns->GetCount();
  376. CRect rcItem(0, m_rcRow.top, 0, m_rcRow.bottom - m_nPreviewHeight);
  377. int nFreezeColCount = m_pControl->GetFreezeColumnsCount();
  378. int nLeft = nFreezeColCount ? pColumns->GetAt(nFreezeColCount - 1)->GetRect().right : 0;
  379. for (int nColumn = 0; nColumn < nColumnCount; nColumn++)
  380. {
  381. CXTPReportColumn* pColumn = pColumns->GetAt(nColumn);
  382. if (pColumn && pColumn->IsVisible())
  383. {
  384. if (m_pRecord->GetItem(pColumn) != pItem)
  385. continue;
  386. rcItem.left = pColumn->GetRect().left;
  387. rcItem.right = pColumn->GetRect().right;
  388. if(pColumn->GetIndex() >= nFreezeColCount)
  389. {
  390. rcItem.left = max(rcItem.left, nLeft);
  391. rcItem.right = max(rcItem.right, nLeft);
  392. }
  393. if(rcItem.Width() <= 0)
  394. return CRect(0, 0, 0, 0);
  395. ShiftTreeIndent(rcItem, pColumn);
  396. return rcItem;
  397. }
  398. }
  399. return CRect(0, 0, 0, 0);
  400. }
  401. void CXTPReportRow::ShiftTreeIndent(CRect& rcItem, CXTPReportColumn* pColumn) const
  402. {
  403. if (pColumn->IsTreeColumn())
  404. {
  405. int nTreeDepth = GetTreeDepth() - m_nGroupLevel;
  406. if (nTreeDepth > 0)
  407. nTreeDepth++;
  408. rcItem.left += m_pControl->GetIndent(nTreeDepth);
  409. CRect rcBitmap(rcItem);
  410. int nIndent = m_pControl->GetPaintManager()->DrawCollapsedBitmap(NULL, this, rcBitmap).cx;
  411. rcItem.left += nIndent + 1;
  412. }
  413. }
  414. CXTPReportRecordItem* CXTPReportRow::HitTest(CPoint ptPoint, CRect* pRectItem, CXTPReportColumn** ppColumn) const
  415. {
  416. if (!m_pRecord)
  417. return NULL;
  418. // find record item
  419. int x = m_rcRow.left + m_pControl->GetHeaderIndent();
  420. CXTPReportColumns* pColumns = m_pControl->GetColumns();
  421. int nColumnCount = pColumns->GetCount();
  422. // if hittes for Preview item
  423. if (IsPreviewVisible())
  424. {
  425. CXTPReportRecordItemPreview* pPreviewItem = GetRecord()->GetItemPreview();
  426. if (pPreviewItem)
  427. {
  428. CRect rcItem(x, m_rcRow.bottom - m_nPreviewHeight, m_rcRow.right, m_rcRow.bottom);
  429. if (rcItem.PtInRect(ptPoint))
  430. {
  431. if (pRectItem)
  432. {
  433. *pRectItem = rcItem;
  434. }
  435. return pPreviewItem;
  436. }
  437. }
  438. }
  439. CRect rcItem(0, m_rcRow.top, 0, m_rcRow.bottom - m_nPreviewHeight);
  440. if (!IsItemsVisible())
  441. return NULL;
  442. int nFreezeColCount = m_pControl->GetFreezeColumnsCount();
  443. int nLeft = nFreezeColCount ? pColumns->GetAt(nFreezeColCount - 1)->GetRect().right : 0;
  444. for (int nColumn = 0; nColumn < nColumnCount; nColumn++)
  445. {
  446. CXTPReportColumn* pColumn = pColumns->GetAt(nColumn);
  447. if (pColumn && pColumn->IsVisible())
  448. {
  449. rcItem.left = pColumn->GetRect().left;
  450. rcItem.right = pColumn->GetRect().right;
  451. if(pColumn->GetIndex() >= nFreezeColCount)
  452. {
  453. rcItem.left = max(rcItem.left, nLeft);
  454. rcItem.right = max(rcItem.right, nLeft);
  455. }
  456. if(!rcItem.Width())
  457. continue;
  458. if (rcItem.PtInRect(ptPoint) && ppColumn)
  459. {
  460. *ppColumn = pColumn;
  461. }
  462. // make tooltip shift if tree view (see also Draw function)
  463. ShiftTreeIndent(rcItem, pColumn);
  464. // check point
  465. if (rcItem.PtInRect(ptPoint))
  466. {
  467. if (pRectItem)
  468. {
  469. *pRectItem = rcItem;
  470. }
  471. return m_pRecord->GetItem(pColumn);
  472. }
  473. }
  474. }
  475. return NULL;
  476. }
  477. void CXTPReportRow::OnMouseMove(UINT nFlags, CPoint point)
  478. {
  479. // find clicked item
  480. CRect rcItem;
  481. CXTPReportRecordItem* pItem = HitTest(point, &rcItem);
  482. // notify item if found
  483. if (pItem != NULL)
  484. {
  485. pItem->OnMouseMove(nFlags, point, m_pControl);
  486. }
  487. }
  488. void CXTPReportRow::FillMetrics(CXTPReportColumn* pColumn, CXTPReportRecordItem* pItem, XTP_REPORTRECORDITEM_METRICS* pMetrics)
  489. {
  490. m_pControl->m_nLockUpdateCount++;
  491. XTP_REPORTRECORDITEM_DRAWARGS drawArgs;
  492. drawArgs.pDC = NULL;
  493. drawArgs.pColumn = pColumn;
  494. drawArgs.pControl = m_pControl;
  495. drawArgs.pRow = this;
  496. drawArgs.rcItem.SetRectEmpty();
  497. drawArgs.pItem = pItem;
  498. drawArgs.nTextAlign = pColumn ? pColumn->GetAlignment() : DT_LEFT;
  499. GetItemMetrics(&drawArgs, pMetrics);
  500. m_pControl->m_nLockUpdateCount--;
  501. }
  502. void CXTPReportRow::ShowToolTip(CPoint ptTip, CXTPReportTip* pTipWnd)
  503. {
  504. CRect rcItem(0, 0, 0, 0);
  505. CXTPReportColumn* pColumn = NULL;
  506. CXTPReportRecordItem* pItem = HitTest(ptTip, &rcItem, &pColumn);
  507. // show tooltip
  508. if (!(pItem && (pItem->IsPreviewItem() || !pItem->IsPreviewItem() && pColumn)))
  509. {
  510. pTipWnd->m_pItem = NULL;
  511. pTipWnd->m_nRowIndex = -1;
  512. return;
  513. }
  514. if (!CXTPDrawHelpers::IsTopParentActive(m_pControl->GetSafeHwnd()) || m_pControl->GetActiveItem())
  515. {
  516. return;
  517. }
  518. if ((pItem != pTipWnd->m_pItem) || (m_nIndex != pTipWnd->m_nRowIndex))
  519. {
  520. pTipWnd->m_pItem = pItem;
  521. pTipWnd->m_nRowIndex = m_nIndex;
  522. CString strTip = pItem->GetTooltip();
  523. m_pControl->OnGetToolTipInfo(this, pItem, strTip);
  524. if (!strTip.IsEmpty() || strTip == _T(" ") || pColumn && (pColumn->GetAlignment() & DT_WORDBREAK))
  525. return;
  526. if (pItem->GetMarkupUIElement() != 0)
  527. return;
  528. XTP_REPORTRECORDITEM_METRICS* pMetrics = new XTP_REPORTRECORDITEM_METRICS();
  529. pMetrics->strText = pItem->GetCaption(pColumn);
  530. FillMetrics(pColumn, pItem, pMetrics);
  531. CString strText(pMetrics->strText);
  532. strText.TrimRight();
  533. if (strText.IsEmpty())
  534. {
  535. pMetrics->InternalRelease();
  536. return;
  537. }
  538. XTP_REPORTRECORDITEM_ARGS itemArgs;
  539. itemArgs.pControl = m_pControl;
  540. itemArgs.pRow = this;
  541. pItem->GetCaptionRect(&itemArgs, rcItem);
  542. m_pControl->ClientToScreen(&rcItem);
  543. if (!pTipWnd->GetSafeHwnd())
  544. {
  545. pTipWnd->Create(m_pControl);
  546. }
  547. CWindowDC dc(m_pControl);
  548. CXTPFontDC font(&dc, pMetrics->pFont);
  549. CRect rcTooltip(rcItem);
  550. BOOL bActivate = FALSE;
  551. if (pItem->IsPreviewItem())
  552. {
  553. CRect rcCalc(rcTooltip.left, 0, rcTooltip.right, 0);
  554. dc.DrawText(strText, rcCalc, DT_WORDBREAK | DT_CALCRECT | DT_NOPREFIX);
  555. bActivate = (rcCalc.Height() / dc.GetTextExtent(_T(" "), 1).cy) > m_pControl->GetPaintManager()->GetMaxPreviewLines();
  556. rcTooltip.bottom = rcTooltip.top + rcCalc.Height();
  557. rcTooltip.right++;
  558. }
  559. else
  560. {
  561. CSize sz = dc.GetTextExtent(strText);
  562. bActivate = sz.cx > (rcTooltip.Width() - 4);
  563. }
  564. if (bActivate)
  565. {
  566. rcTooltip.InflateRect(1, 1, 0, 0);
  567. pTipWnd->SetFont(pMetrics->pFont);
  568. pTipWnd->SetTooltipText(strText);
  569. pTipWnd->SetHoverRect(rcTooltip);
  570. pTipWnd->Activate(TRUE, pItem->IsPreviewItem());
  571. TRACKMOUSEEVENT tme =
  572. {
  573. sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_pControl->GetSafeHwnd(), 0
  574. };
  575. _TrackMouseEvent (&tme);
  576. }
  577. pMetrics->InternalRelease();
  578. }
  579. }
  580. BOOL CXTPReportRow::HasParent(CXTPReportRow* pRow)
  581. {
  582. if (m_pParentRow == NULL)
  583. return FALSE;
  584. if (pRow == m_pParentRow)
  585. return TRUE;
  586. return m_pParentRow->HasParent(pRow);
  587. }
  588. void CXTPReportRow::SetExpanded(BOOL bExpanded)
  589. {
  590. if (bExpanded != m_bExpanded && HasChildren())
  591. {
  592. if (bExpanded)
  593. {
  594. m_pControl->_DoExpand(this);
  595. }
  596. else
  597. {
  598. m_pControl->_DoCollapse(this);
  599. }
  600. if (m_pRecord)
  601. {
  602. m_pRecord->m_bExpanded = bExpanded;
  603. }
  604. m_bExpanded = bExpanded;
  605. m_pControl->_RefreshIndexes();
  606. m_pControl->SendMessageToParent(this, NULL, NULL, XTP_NM_REPORT_ROWEXPANDED, NULL);
  607. }
  608. else
  609. {
  610. m_bExpanded = bExpanded;
  611. }
  612. }
  613. CXTPReportRow* CXTPReportRow::AddChild(CXTPReportRow* pRow)
  614. {
  615. GetChilds()->Add(pRow);
  616. pRow->m_pParentRow = this;
  617. return pRow;
  618. }
  619. void CXTPReportRow::OnContextMenu(CPoint ptClick)
  620. {
  621. CXTPReportColumn* pColumn = NULL;
  622. CXTPReportRecordItem* pItem = HitTest(ptClick, NULL, &pColumn);
  623. m_pControl->ClientToScreen(&ptClick);
  624. // send process notification to the user and wait for the reaction
  625. m_pControl->SendMessageToParent(this, pItem, pColumn, NM_RCLICK, &ptClick);
  626. }
  627. void CXTPReportRow::GetItemMetrics(XTP_REPORTRECORDITEM_DRAWARGS* pDrawArgs, XTP_REPORTRECORDITEM_METRICS* pItemMetrics)
  628. {
  629. ASSERT(m_pRecord);
  630. ASSERT(pDrawArgs->pRow == this);
  631. ASSERT(pDrawArgs->pItem != NULL);
  632. if (!m_pRecord || !pDrawArgs->pItem)
  633. return;
  634. CXTPReportPaintManager* pPaintManager = pDrawArgs->pControl->GetPaintManager();
  635. pItemMetrics->pFont = &pPaintManager->m_fontText;
  636. pItemMetrics->clrForeground = pPaintManager->m_clrWindowText;
  637. pItemMetrics->clrBackground = XTP_REPORT_COLOR_DEFAULT;
  638. pItemMetrics->nColumnAlignment = pDrawArgs->nTextAlign;
  639. pItemMetrics->nItemIcon = XTP_REPORT_NOICON;
  640. m_pRecord->GetItemMetrics(pDrawArgs, pItemMetrics);
  641. pDrawArgs->pItem->GetItemMetrics(pDrawArgs, pItemMetrics);
  642. m_pControl->GetItemMetrics(pDrawArgs, pItemMetrics);
  643. pDrawArgs->nTextAlign = pItemMetrics->nColumnAlignment;
  644. if (IsSelected() && (pDrawArgs->pDC && !pDrawArgs->pDC->IsPrinting()))
  645. {
  646. if (pDrawArgs->pColumn && IsFocused() && m_pControl->m_pFocusedColumn == pDrawArgs->pColumn)
  647. return;
  648. if (GetControl()->HasFocus())
  649. {
  650. pItemMetrics->clrForeground = pPaintManager->m_clrHighlightText;
  651. pItemMetrics->clrBackground = pPaintManager->m_clrHighlight;
  652. }
  653. else if (!pPaintManager->m_bHideSelection)
  654. {
  655. pItemMetrics->clrForeground = pPaintManager->m_clrSelectedRowText;
  656. pItemMetrics->clrBackground = pPaintManager->m_clrSelectedRow;
  657. }
  658. }
  659. }
  660. BOOL CXTPReportRow::HasChildren() const
  661. {
  662. return m_pChilds && m_pChilds->GetCount() > 0;
  663. }
  664. int CXTPReportRow::GetIndex() const
  665. {
  666. return m_nIndex;
  667. }
  668. BOOL CXTPReportRow::IsGroupRow() const
  669. {
  670. return FALSE;
  671. }
  672. BOOL CXTPReportRow::IsExpanded() const
  673. {
  674. return m_bExpanded;
  675. }
  676. BOOL CXTPReportRow::IsLastTreeRow() const
  677. {
  678. if (!m_pParentRow)
  679. return FALSE;
  680. CXTPReportRows* pRows = m_pParentRow->GetChilds();
  681. return pRows->GetCount() > 0 && pRows->GetAt(pRows->GetCount() - 1) == this;
  682. }
  683. void CXTPReportRow::EnsureVisible()
  684. {
  685. m_pControl->EnsureVisible(this);
  686. }
  687. CXTPReportRow* CXTPReportRow::GetNextSiblingRow() const
  688. {
  689. if (!m_pParentRows)
  690. return 0;
  691. if (m_nChildIndex == -1)
  692. return 0;
  693. ASSERT(m_pParentRows->GetAt(m_nChildIndex) == this);
  694. if (m_nChildIndex < m_pParentRows->GetCount() - 1)
  695. return m_pParentRows->GetAt(m_nChildIndex + 1);
  696. return 0;
  697. }
  698. void CXTPReportRow::DrawFixed(CDC* pDC, CRect rcRow, int nLeftOffset, CRect rcArea)
  699. {
  700. ASSERT(m_pControl);
  701. if (!m_pControl)
  702. return;
  703. //  BOOL bControlFocused = m_pControl->HasFocus();
  704. int nFreezeCols = m_pControl->m_nFreezeColumnsCount;
  705. CRect rcClipBox = rcArea ;
  706. m_rcRow = rcRow;
  707. m_rcRow.left -= nLeftOffset;
  708. m_rcRow.right -= nLeftOffset;
  709. if (nFreezeCols == 0)
  710. {
  711. rcRow = m_rcRow;
  712. }
  713. XTP_REPORTRECORDITEM_DRAWARGS drawArgs;
  714. drawArgs.pDC = pDC;
  715. drawArgs.pControl = m_pControl;
  716. drawArgs.pRow = this;
  717. int nIndentWidth = m_pControl->GetHeaderIndent();
  718. CXTPReportPaintManager* pPaintManager = m_pControl->GetPaintManager();
  719. // whether to draw header's last horizontal grid depends on header divider style.
  720. BOOL bDrawLastHeaderGrid = TRUE;
  721. if (GetType() == xtpRowTypeHeader)
  722. {
  723. bDrawLastHeaderGrid = xtpReportFixedRowsDividerNone == (pPaintManager->GetHeaderRowsDividerStyle() & ~xtpReportFixedRowsDividerShade);
  724. }
  725. // whether to draw footer's first horizontal grid depends on footer divider style.
  726. BOOL bDrawFirstFooterGrid = TRUE;
  727. if (GetType() == xtpRowTypeFooter)
  728. {
  729. bDrawFirstFooterGrid = xtpReportFixedRowsDividerNone == (pPaintManager->GetFooterRowsDividerStyle() & ~xtpReportFixedRowsDividerShade);
  730. }
  731. CXTPReportColumns arrVisibleColumns(m_pControl);
  732. m_pControl->GetColumns()->GetVisibleColumns(arrVisibleColumns);
  733. int nVisColCount = arrVisibleColumns.GetCount();
  734. nFreezeCols = min(nFreezeCols, nVisColCount);
  735. // paint row background
  736. pDC->FillSolidRect(m_rcRow, pPaintManager->GetControlBackColor(GetControl()));
  737. CRect rcItem(m_rcRow.left, m_rcRow.top, m_rcRow.right, m_rcRow.bottom - m_nPreviewHeight);
  738. CRect rcIndent(nFreezeCols ? rcRow : m_rcRow);
  739. rcIndent.right = rcIndent.left + nIndentWidth;
  740. if (m_pRecord) // if drawing record, not group
  741. {
  742. int xMinCol_0 = rcRow.left + nIndentWidth;
  743. // paint record items
  744. for (int nColumn = nVisColCount-1; nColumn >= 0; nColumn--)
  745. {
  746. BOOL bFreezeCol = nColumn < nFreezeCols;
  747. int nColIdx = bFreezeCol ? nFreezeCols - 1 - nColumn : nColumn;
  748. CXTPReportColumn* pColumn = arrVisibleColumns.GetAt(nColIdx);
  749. ASSERT(pColumn && pColumn->IsVisible());
  750. if (pColumn && IsItemsVisible())
  751. {
  752. rcItem.left = pColumn->GetRect().left;
  753. if (nColIdx == 0)
  754. {
  755. rcItem.left = max(xMinCol_0, rcItem.left);
  756. }
  757. rcItem.right = pColumn->GetRect().right;
  758. if (!CRect().IntersectRect(rcClipBox, rcItem))
  759. continue;
  760. if (bFreezeCol)
  761. {
  762. pDC->FillSolidRect(rcItem, pPaintManager->GetControlBackColor(GetControl()));
  763. pPaintManager->FillRow(pDC, this, rcItem);
  764. }
  765. CRect rcGridItem(rcItem);
  766. rcGridItem.left--;
  767. // draw shade background if sorted by this row
  768. if (pColumn->IsSorted())
  769. {
  770. pPaintManager->FillItemShade(pDC, rcItem);
  771. }
  772. CXTPReportRecordItem* pItem = m_pRecord->GetItem(pColumn);
  773. if (pItem)
  774. {
  775. // draw item
  776. drawArgs.pColumn = pColumn;
  777. drawArgs.rcItem = rcItem;
  778. drawArgs.nTextAlign = pColumn->GetAlignment();
  779. drawArgs.pItem = pItem;
  780. // draw item
  781. int nItemTextWidth = pItem->Draw(&drawArgs);
  782. pColumn->m_nMaxItemWidth = max(pColumn->m_nMaxItemWidth, nItemTextWidth);
  783. }
  784. // is vertical grid required
  785. if (GetType() == xtpRowTypeHeader)
  786. {
  787. if (pColumn->GetDrawHeaderRowsVGrid())
  788. pPaintManager->DrawGrid(pDC, TRUE, rcGridItem);
  789. }
  790. else
  791. if (GetType() == xtpRowTypeFooter)
  792. {
  793. if (pColumn->GetDrawFooterRowsVGrid())
  794. pPaintManager->DrawGrid(pDC, TRUE, rcGridItem);
  795. }
  796. if (bDrawFirstFooterGrid)
  797. {
  798. // horizontal grid above
  799. CRect rcTop(rcGridItem);
  800. rcTop.bottom = --rcGridItem.top;
  801. pPaintManager->DrawGrid(pDC, FALSE, rcTop);
  802. }
  803. bDrawFirstFooterGrid = TRUE;
  804. if (nColIdx == nFreezeCols - 1)
  805. pPaintManager->DrawFreezeColsDivider(pDC, rcGridItem, GetControl(), this);
  806. }
  807. }
  808. if (nIndentWidth > 0)
  809. {
  810. // draw indent column
  811. pPaintManager->FillIndent(pDC, rcIndent);
  812. }
  813. }
  814. // draw focus
  815. BOOL bControlFocused = m_pControl->HasFocus();
  816. BOOL bGridVisible = pPaintManager->IsGridVisible(FALSE);
  817. CRect rcFocus(rcIndent.right, m_rcRow.top, m_rcRow.right, m_rcRow.bottom - (bGridVisible ? 1 : 0));
  818. if (IsFocused() && bControlFocused && m_pControl->IsRowFocusVisible())
  819. pPaintManager->DrawFocusedRow(pDC, rcFocus);
  820. // last header grid line
  821. if (bDrawLastHeaderGrid)
  822. {
  823. pPaintManager->DrawGrid(pDC, FALSE, rcFocus);
  824. }
  825. }