You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1647 lines
38 KiB
C++
1647 lines
38 KiB
C++
// XTPReportRow.cpp : implementation of the CXTPReportRow class.
|
|
//
|
|
// This file is a part of the XTREME REPORTCONTROL MFC class library.
|
|
// (c)1998-2012 Codejock Software, All Rights Reserved.
|
|
//
|
|
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
|
|
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
|
|
// CONSENT OF CODEJOCK SOFTWARE.
|
|
//
|
|
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
|
|
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
|
|
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
|
|
// SINGLE COMPUTER.
|
|
//
|
|
// CONTACT INFORMATION:
|
|
// support@codejock.com
|
|
// http://www.codejock.com
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "Common/Resource.h"
|
|
#include "Common/XTPDrawHelpers.h"
|
|
#include "Common/XTPToolTipContext.h"
|
|
#include "Common/XTPMarkupRender.h"
|
|
#include "Common/XTPSystemHelpers.h"
|
|
#include "Common/XTPResourceManager.h"
|
|
#include "Common/XTPCustomHeap.h"
|
|
#include "Common/XTPSmartPtrInternalT.h"
|
|
#include "Common/XTPColorManager.h"
|
|
|
|
#include "XTPReportDefines.h"
|
|
#include "XTPReportRecordItemRange.h"
|
|
#include "XTPReportRecord.h"
|
|
#include "XTPReportControl.h"
|
|
#include "XTPReportPaintManager.h"
|
|
#include "XTPReportRow.h"
|
|
#include "XTPReportRows.h"
|
|
#include "XTPReportSelectedRows.h"
|
|
#include "XTPReportColumns.h"
|
|
#include "XTPReportColumn.h"
|
|
#include "XTPReportTip.h"
|
|
#include "XTPReportHeader.h"
|
|
#include "XTPReportSection.h"
|
|
#include "XTPReportBorder.h"
|
|
#include "XTPReportRecordItem.h"
|
|
#include "ItemTypes/XTPReportRecordItemPreview.h"
|
|
#include "ItemTypes/XTPReportRecordItemIcon.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
IMPLEMENT_DYNAMIC(CXTPReportRow, CCmdTarget)
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CXTPReportRow
|
|
|
|
CXTPReportRow::CXTPReportRow()
|
|
: m_pParentRows(NULL)
|
|
, m_pParentRow (NULL)
|
|
, m_pRecord (NULL)
|
|
, m_pChilds (NULL)
|
|
, m_pControl (NULL)
|
|
, m_pSection (NULL)
|
|
|
|
, m_nIndex (-1)
|
|
, m_nChildIndex(-1)
|
|
|
|
, m_nGroupLevel (0)
|
|
, m_nRowLevel (0)
|
|
|
|
, m_bVisible (FALSE)
|
|
, m_bExpanded (TRUE)
|
|
, m_bLockExpand(FALSE)
|
|
{
|
|
|
|
|
|
m_rcRow.SetRectEmpty();
|
|
m_rcCollapse.SetRectEmpty();
|
|
m_bHasSelectedChilds = FALSE;
|
|
|
|
m_nPreviewHeight = 0;
|
|
m_nFreeHeight = 0;
|
|
|
|
EnableAutomation();
|
|
}
|
|
|
|
void CXTPReportRow::InitRow(
|
|
CXTPReportControl *pControl,
|
|
CXTPReportSection *pSection,
|
|
CXTPReportRecord *pRecord)
|
|
{
|
|
ASSERT(pRecord || IsGroupRow());
|
|
|
|
m_pControl = pControl;
|
|
m_pSection = pSection;
|
|
|
|
if (m_pControl->m_bFreeHeightMode)
|
|
m_nFreeHeight = m_pControl->m_nDefaultRowFreeHeight;
|
|
|
|
if (pRecord)
|
|
{
|
|
m_pRecord = pRecord;
|
|
m_bExpanded = pRecord->m_bExpanded;
|
|
m_pRecord->InternalAddRef();
|
|
}
|
|
}
|
|
|
|
void CXTPReportRow::InitRow(CXTPReportRow *pRow)
|
|
{
|
|
ASSERT(pRow->m_pRecord);
|
|
ASSERT(pRow->m_pParentRow == NULL);
|
|
|
|
m_pControl = pRow->m_pControl;
|
|
m_pRecord = pRow->m_pRecord;
|
|
m_pSection = pRow->m_pSection;
|
|
|
|
if (NULL != m_pRecord)
|
|
{
|
|
m_pRecord->InternalAddRef();
|
|
}
|
|
|
|
m_rcRow = pRow->m_rcRow;
|
|
m_rcCollapse = pRow->m_rcCollapse;
|
|
m_bVisible = pRow->m_bVisible;
|
|
m_bExpanded = pRow->m_bExpanded;
|
|
m_nIndex = pRow->m_nIndex;
|
|
m_nPreviewHeight = pRow->m_nPreviewHeight;
|
|
m_nRowLevel = pRow->m_nRowLevel;
|
|
m_nGroupLevel = pRow->m_nGroupLevel;
|
|
|
|
if (m_pControl->m_bFreeHeightMode)
|
|
m_nFreeHeight = m_pControl->m_nDefaultRowFreeHeight;
|
|
}
|
|
|
|
|
|
CXTPReportRows* CXTPReportRow::GetChilds(BOOL bCreate)
|
|
{
|
|
if (!m_pChilds && bCreate)
|
|
m_pChilds = new CXTPReportRows();
|
|
|
|
return m_pChilds;
|
|
}
|
|
|
|
|
|
|
|
CXTPReportRow::~CXTPReportRow()
|
|
{
|
|
if (m_pChilds)
|
|
m_pChilds->InternalRelease();
|
|
|
|
if (m_pRecord)
|
|
m_pRecord->InternalRelease();
|
|
}
|
|
|
|
int CXTPReportRow::GetHeight(CDC *pDC, int nWidth)
|
|
{
|
|
ASSERT(m_pControl);
|
|
if (!m_pControl)
|
|
return 0;
|
|
|
|
int nHeight = m_pControl->GetPaintManager()->GetRowHeight(pDC, this, nWidth);
|
|
|
|
if (!IsGroupRow() && !IsItemsVisible())
|
|
{
|
|
nHeight = 0;
|
|
}
|
|
|
|
|
|
m_nPreviewHeight = 0;
|
|
|
|
if (IsPreviewVisible())
|
|
{
|
|
CXTPReportRecordItemPreview *pItem = GetRecord()->GetItemPreview();
|
|
|
|
m_nPreviewHeight = pItem->GetPreviewHeight(pDC, this, nWidth);
|
|
m_nPreviewHeight = m_pControl->GetPaintManager()->GetPreviewItemHeight(pDC, this, nWidth, m_nPreviewHeight);
|
|
}
|
|
|
|
return nHeight + m_nPreviewHeight;
|
|
}
|
|
|
|
|
|
BOOL CXTPReportRow::IsFocused() const
|
|
{
|
|
return m_pSection->GetRows()->GetFocusedRowIndex() == m_nIndex;
|
|
}
|
|
|
|
BOOL CXTPReportRow::IsSelected() const
|
|
{
|
|
return m_pControl->GetSelectedRows()->Contains(this);
|
|
}
|
|
|
|
void CXTPReportRow::SetSelected(BOOL bSelected)
|
|
{
|
|
if (bSelected == IsSelected())
|
|
return;
|
|
|
|
if (bSelected)
|
|
{
|
|
if (!m_pControl->IsMultipleSelection())
|
|
m_pControl->GetSelectedRows()->Clear();
|
|
|
|
m_pControl->GetSelectedRows()->Add(this);
|
|
}
|
|
else
|
|
{
|
|
m_pControl->GetSelectedRows()->Remove(this);
|
|
}
|
|
|
|
m_pControl->RedrawControl();
|
|
}
|
|
|
|
int CXTPReportRow::GetLastChildRow(CXTPReportRows* pChilds) const
|
|
{
|
|
CXTPReportRow* pRow = pChilds->GetAt(pChilds->GetCount() - 1);
|
|
|
|
if (!pRow)
|
|
return -1;
|
|
|
|
if (pRow->HasChildren() && pRow->IsExpanded())
|
|
return GetLastChildRow(pRow->GetChilds());
|
|
|
|
return pRow->GetIndex();
|
|
}
|
|
|
|
void CXTPReportRow::SelectChilds()
|
|
{
|
|
BOOL bM = m_pControl->IsMultipleSelection();
|
|
BOOL bC = HasChildren();
|
|
BOOL bE = IsExpanded();
|
|
if (!(bM && bC && bE && m_nIndex != -1))
|
|
return;
|
|
|
|
m_pControl->BeginUpdate();
|
|
|
|
int nIndexBegin = m_nIndex + 1;
|
|
int nIndexEnd = GetLastChildRow(GetChilds());
|
|
|
|
m_pControl->GetSelectedRows()->AddBlock(nIndexBegin, nIndexEnd);
|
|
|
|
m_pControl->EndUpdate();
|
|
}
|
|
|
|
BOOL CXTPReportRow::IsItemsVisible() const
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL CXTPReportRow::IsPreviewVisible() const
|
|
{
|
|
return !IsGroupRow()
|
|
&& m_pRecord
|
|
&& m_pControl->IsPreviewMode()
|
|
&& !m_pControl->IsIconView()
|
|
&& m_pRecord->GetItemPreview();
|
|
}
|
|
|
|
|
|
void CXTPReportRow::DrawItemGrid(CDC *pDC, CXTPReportColumn *pColumn, CRect rcItem)
|
|
{
|
|
CXTPReportPaintManager *pPaintManager = m_pControl->GetPaintManager();
|
|
|
|
const BOOL bGridVisible = pPaintManager->IsGridVisible(FALSE);
|
|
|
|
rcItem.DeflateRect(0,0,0,1);
|
|
|
|
// Draw horizontal grid
|
|
if (bGridVisible && !IsPreviewVisible())
|
|
{
|
|
pPaintManager->DrawGrid(pDC, xtpReportOrientationHorizontal, rcItem);
|
|
}
|
|
|
|
// Draw vertical grid
|
|
switch(GetType())
|
|
{
|
|
case xtpRowTypeBody:
|
|
{
|
|
pPaintManager->DrawGrid(pDC, xtpReportOrientationVertical, rcItem);
|
|
}
|
|
break;
|
|
|
|
case xtpRowTypeHeader:
|
|
{
|
|
if (pColumn->GetDrawHeaderRowsVGrid())
|
|
{
|
|
pPaintManager->DrawGrid(pDC, xtpReportOrientationVertical, rcItem);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case xtpRowTypeFooter:
|
|
{
|
|
if (pColumn->GetDrawFooterRowsVGrid())
|
|
{
|
|
pPaintManager->DrawGrid(pDC, xtpReportOrientationVertical, rcItem);
|
|
}
|
|
}
|
|
break;
|
|
} // switch
|
|
}
|
|
|
|
|
|
BOOL AdjustClipRect(CDC *pDC, CRect &rcClip)
|
|
{
|
|
if (NULL != pDC && pDC->IsKindOf(RUNTIME_CLASS(CPreviewDC)))
|
|
{
|
|
CPreviewDC *pPreviewDC = DYNAMIC_DOWNCAST(CPreviewDC, pDC);
|
|
|
|
pPreviewDC->PrinterDPtoScreenDP(&rcClip.TopLeft());
|
|
pPreviewDC->PrinterDPtoScreenDP(&rcClip.BottomRight());
|
|
|
|
// Offset the result by the viewport
|
|
// origin of the print preview window
|
|
CPoint ptOrg;
|
|
|
|
// Note: pDC->GetViewportOrg() uses the m_hAttributDC
|
|
::GetViewportOrgEx(pDC->m_hDC, &ptOrg);
|
|
rcClip += ptOrg;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void CXTPReportRow::Draw(CDC *pDC, CRect rcRow, CRect rcClip, int nLeftOffset,
|
|
CXTPReportRecordMergeItems &mergeItems, int nColumnFrom, int nColumnTo)
|
|
{
|
|
// Check preconditions
|
|
ASSERT(NULL != m_pControl);
|
|
|
|
if (NULL == m_pControl)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const BOOL bIsPrinting = pDC->IsPrinting();
|
|
const int nFreezeCount = m_pControl->GetFreezeColumnsCount();
|
|
const int nFreezeIndex = m_pControl->GetFreezeColumnsIndex();
|
|
const int nHeaderIndent = m_pControl->GetHeaderIndent();
|
|
|
|
// Paint Manager
|
|
CXTPReportPaintManager *pPaintManager = m_pControl->GetPaintManager();
|
|
const BOOL bGridVisible = pPaintManager->IsGridVisible(xtpReportOrientationHorizontal);
|
|
|
|
int nIconColumnIndex = -1;
|
|
CXTPReportColumn* pRecNumCol = m_pControl->GetColumns()->Find(m_pControl->m_iColumnForNum);
|
|
if (pRecNumCol)
|
|
nIconColumnIndex = pRecNumCol->GetIndex();
|
|
|
|
m_rcRow = rcRow;
|
|
m_rcRow.left -= nLeftOffset;
|
|
m_rcRow.right -= nLeftOffset;
|
|
|
|
if (nFreezeCount == 0)
|
|
rcRow = m_rcRow;
|
|
|
|
XTP_REPORTRECORDITEM_DRAWARGS drawArgs;
|
|
drawArgs.pDC = pDC;
|
|
drawArgs.pControl = m_pControl;
|
|
drawArgs.pRow = this;
|
|
|
|
CRect rcIndent(nFreezeCount ? rcRow : m_rcRow);
|
|
rcIndent.right = rcIndent.left + nHeaderIndent;
|
|
|
|
CRect rcItem(m_rcRow);
|
|
rcItem.bottom -= m_nPreviewHeight; // Deduct preview item
|
|
|
|
int nFreezeRight = 0;
|
|
|
|
if (nFreezeCount > 0)
|
|
{
|
|
CXTPReportColumn *pColumn = m_pControl->GetColumns()->GetAt(nFreezeIndex);
|
|
nFreezeRight = pColumn->GetRect().right;
|
|
}
|
|
|
|
if (NULL != m_pRecord) // if drawing record, not group
|
|
{
|
|
if (bIsPrinting)
|
|
{
|
|
rcItem.right = rcRow.left;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// Paint record items
|
|
///////////////////////////////////////////////////////////////////////
|
|
CRect rcClipRow; // Clipping rectangle for row
|
|
CRect rcClipItem; // Clipping rectangle for item
|
|
|
|
BOOL bFirstColumn = TRUE;
|
|
|
|
int nColumnPos = -1;
|
|
|
|
for (int nColumn=nColumnFrom; nColumn<nColumnTo; nColumn++)
|
|
{
|
|
CXTPReportColumn *pColumn = m_pControl->GetColumns()->GetAt(nColumn);
|
|
|
|
if (NULL != pColumn && pColumn->IsVisible() && IsItemsVisible())
|
|
{
|
|
++nColumnPos;
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
// Determine item position
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
rcItem.bottom = m_rcRow.bottom;
|
|
rcItem.bottom -= m_nPreviewHeight;
|
|
|
|
if (bIsPrinting) // Printing
|
|
{
|
|
if (pPaintManager->IsColumnWidthWYSIWYG())
|
|
{
|
|
rcItem.left = rcItem.right;
|
|
rcItem.right = rcItem.left + pColumn->GetWidth();
|
|
}
|
|
else
|
|
{
|
|
rcItem.left = rcItem.right;
|
|
rcItem.right = rcItem.left + pColumn->GetPrintWidth(rcRow.Width());
|
|
}
|
|
}
|
|
else // Drawing
|
|
{
|
|
rcItem.left = pColumn->GetRect().left;
|
|
rcItem.right = pColumn->GetRect().right;
|
|
}
|
|
|
|
// Offset first column by header indentation
|
|
if (bFirstColumn)
|
|
{
|
|
bFirstColumn = FALSE;
|
|
rcItem.left += nHeaderIndent;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
/////////////////////////////////////////////////////////////////
|
|
BOOL bDrawFreeze = nColumn<=nFreezeIndex;
|
|
|
|
if (bDrawFreeze)
|
|
{
|
|
// Frozen column
|
|
rcClipRow.SetRect(rcRow.left, rcRow.top, nFreezeRight, rcRow.bottom);
|
|
}
|
|
else
|
|
{
|
|
// Non-frozen column
|
|
rcClipRow.SetRect(nFreezeRight, rcRow.top, rcRow.right, rcRow.bottom);
|
|
}
|
|
|
|
// Determine clipping rectangle
|
|
rcClipItem.IntersectRect(rcItem, rcClip); // Clip section
|
|
rcClipItem.IntersectRect(rcClipItem, rcClipRow); // Clip row
|
|
|
|
// In print preview mode the clipping rectangle needs to be
|
|
// adjusted before creating the clipping region
|
|
//AdjustClipRect(pDC, rcClipItem);
|
|
|
|
|
|
if (!bDrawFreeze && !bIsPrinting && rcItem.right < nFreezeRight)
|
|
{
|
|
// Column is entirely under frozen column, do not draw
|
|
continue;
|
|
}
|
|
|
|
if (!CRect().IntersectRect(rcClip, rcItem) && !bIsPrinting)
|
|
continue;
|
|
|
|
// Create clipping region
|
|
CRgn rgnClipItem;
|
|
if (!bIsPrinting)
|
|
{
|
|
rgnClipItem.CreateRectRgnIndirect(rcClipItem);
|
|
pDC->SelectClipRgn(&rgnClipItem, RGN_COPY);
|
|
}
|
|
|
|
CXTPReportRecordItem *pItem = m_pRecord->GetItem(pColumn);
|
|
|
|
#if 0
|
|
CXTPReportBorder *pBorder = pPaintManager->GetItemBorder(pItem);
|
|
|
|
if (NULL != pBorder)
|
|
{
|
|
pBorder->Draw(pDC, rcItem);
|
|
rcItem = CXTPReportBorder::DeflateRect(rcItem, pBorder);
|
|
}
|
|
#endif
|
|
// Draw row background
|
|
pPaintManager->FillRow(pDC, this, rcItem);
|
|
|
|
// Draw shade background if sorted by this row
|
|
if (pColumn->IsSorted())
|
|
{
|
|
pPaintManager->FillItemShade(pDC, rcItem);
|
|
}
|
|
|
|
if (NULL != pItem)
|
|
{
|
|
// draw item
|
|
drawArgs.pColumn = pColumn;
|
|
drawArgs.rcItem = rcItem;
|
|
drawArgs.nTextAlign = pColumn->GetAlignment();
|
|
drawArgs.pItem = pItem;
|
|
|
|
if (!pItem->IsMerged())
|
|
{
|
|
int nItemTextWidth = pItem->Draw(&drawArgs);
|
|
pColumn->m_nMaxItemWidth = max(pColumn->m_nMaxItemWidth, nItemTextWidth);
|
|
}
|
|
else
|
|
{
|
|
CXTPReportRecordItem *pMergeItem = pItem->GetMergeItem();
|
|
CXTPReportRecordMergeItemId itemId(nColumnPos, nColumn, GetIndex());
|
|
mergeItems[pMergeItem].AddItem(itemId, rcItem);
|
|
}
|
|
}
|
|
else if (m_pControl->IsIconView() && !m_pControl->IsVirtualMode())
|
|
{
|
|
// IconView - non Virtual Mode!
|
|
pItem = new CXTPReportRecordItemIcon();
|
|
drawArgs.pColumn = pColumn;
|
|
drawArgs.rcItem = rcItem;
|
|
CXTPReportColumn* pDataColumn = m_pControl->GetColumns()->GetAt(m_pControl->m_iIconPropNum);
|
|
CXTPReportRecordItem* pDataItem = GetRecord()->GetItem(m_pControl->m_iIconPropNum);
|
|
if (pDataColumn != NULL && pDataItem != NULL)
|
|
{
|
|
pItem->SetCaption(pDataItem->GetCaption(pDataColumn));
|
|
pItem->SetIconIndex(m_pControl->m_iIconNum);
|
|
}
|
|
drawArgs.pItem = pItem;
|
|
pItem->Draw(&drawArgs);
|
|
delete pItem;
|
|
pItem = NULL;
|
|
}
|
|
else if (nIconColumnIndex > -1
|
|
&& !m_pControl->IsIconView()
|
|
&& !m_pControl->IsVirtualMode()) //no Item! (ghost)
|
|
{
|
|
CRect rcIcon = m_pControl->GetColumns()->GetAt(nIconColumnIndex)->GetRect();
|
|
rcIcon.top = m_rcRow.top;
|
|
rcIcon.bottom = m_rcRow.bottom - m_nPreviewHeight;
|
|
rcIcon.left = 0;
|
|
pPaintManager->DrawRowNumber(pDC, rcIcon, this);
|
|
}
|
|
#if 1
|
|
if (pItem && !pItem->IsMerged())
|
|
{
|
|
CRect rcGridItem(rcItem);
|
|
rcGridItem.left--;
|
|
DrawItemGrid(pDC, pColumn, rcGridItem);
|
|
}
|
|
#endif
|
|
// Release clipping
|
|
if (!bIsPrinting)
|
|
{
|
|
pDC->SelectClipRgn(NULL, RGN_COPY);
|
|
rgnClipItem.DeleteObject();
|
|
}
|
|
|
|
if (nColumn == nFreezeIndex)
|
|
{
|
|
pPaintManager->DrawFreezeColsDivider(pDC, rcItem, GetControl(), this);
|
|
}
|
|
}
|
|
} // for (nColumn)
|
|
|
|
if (IsPreviewVisible())
|
|
{
|
|
CRect rcPreviewItem(m_rcRow);
|
|
rcPreviewItem.DeflateRect(nHeaderIndent, rcPreviewItem.Height() - m_nPreviewHeight, 0, 0);
|
|
|
|
drawArgs.rcItem = rcPreviewItem;
|
|
drawArgs.nTextAlign = DT_LEFT;
|
|
drawArgs.pColumn = NULL;
|
|
drawArgs.pItem = m_pRecord->GetItemPreview();
|
|
|
|
// Determine clipping rectangle
|
|
rcClipItem.IntersectRect(rcPreviewItem, rcClip); // Clip section
|
|
rcClipItem.IntersectRect(rcClipItem, rcClipRow); // Clip row
|
|
|
|
CRgn rgnClipItem;
|
|
if (!bIsPrinting)
|
|
{
|
|
rgnClipItem.CreateRectRgnIndirect(rcClipItem);
|
|
pDC->SelectClipRgn(&rgnClipItem, RGN_COPY);
|
|
}
|
|
|
|
drawArgs.pItem->Draw(&drawArgs);
|
|
|
|
// Release clipping
|
|
if (!bIsPrinting)
|
|
{
|
|
pDC->SelectClipRgn(NULL, RGN_COPY);
|
|
rgnClipItem.DeleteObject();
|
|
}
|
|
}
|
|
|
|
if (nHeaderIndent > 0) // draw indent column
|
|
{
|
|
rcIndent.IntersectRect(rcIndent, rcClip);
|
|
pPaintManager->FillIndent(pDC, rcIndent);
|
|
}
|
|
} // (NULL != m_pRecord)
|
|
|
|
CRgn rgnClip;
|
|
if (!bIsPrinting)
|
|
{
|
|
rgnClip.CreateRectRgnIndirect(&rcClip);
|
|
pDC->SelectClipRgn(&rgnClip, RGN_COPY);
|
|
}
|
|
|
|
CRect rcFocus(rcIndent.right, m_rcRow.top, m_rcRow.right, m_rcRow.bottom - (bGridVisible ? 1 : 0));
|
|
|
|
if (!m_pControl->IsIconView() && IsFocused() && m_pControl->HasFocus() && m_pControl->IsRowFocusVisible())
|
|
{
|
|
pPaintManager->DrawFocusedRow(pDC, rcFocus);
|
|
}
|
|
|
|
if (nHeaderIndent > 0 && bGridVisible)
|
|
{
|
|
if (m_nIndex < m_pControl->GetRows()->GetCount() - 1)
|
|
{
|
|
CXTPReportRow *pNextRow = m_pControl->GetRows()->GetAt(m_nIndex+1);
|
|
ASSERT(pNextRow);
|
|
rcFocus.left = rcIndent.left + min(nHeaderIndent, pPaintManager->m_nTreeIndent * pNextRow->GetTreeDepth());
|
|
}
|
|
else
|
|
{
|
|
rcFocus.left = m_rcRow.left;
|
|
}
|
|
pPaintManager->DrawGrid(pDC, xtpReportOrientationHorizontal, rcFocus);
|
|
}
|
|
|
|
if (IsPreviewVisible())
|
|
{
|
|
pPaintManager->DrawGrid(pDC, xtpReportOrientationHorizontal, rcFocus);
|
|
}
|
|
|
|
if (!bIsPrinting)
|
|
{
|
|
pDC->SelectClipRgn(NULL, RGN_COPY);
|
|
rgnClip.DeleteObject();
|
|
}
|
|
}
|
|
|
|
int CXTPReportRow::GetTreeDepth() const
|
|
{
|
|
return m_nRowLevel;
|
|
}
|
|
|
|
INT_PTR CXTPReportRow::OnToolHitTest(CPoint point, TOOLINFO* pTI)
|
|
{
|
|
CRect rcItem;
|
|
CXTPReportRecordItem* pItem = HitTest(point, &rcItem);
|
|
|
|
if (!pItem)
|
|
return -1;
|
|
|
|
|
|
INT_PTR nHit = pItem->OnToolHitTest(point, pTI);
|
|
if (nHit != -1)
|
|
return nHit;
|
|
|
|
nHit = (INT_PTR) pItem;
|
|
CString strTip = pItem->GetTooltip();
|
|
|
|
m_pControl->OnGetToolTipInfo(this, pItem, strTip);
|
|
|
|
if (strTip.IsEmpty() || strTip == _T(" "))
|
|
return -1;
|
|
|
|
if (m_pControl->GetPaintManager()->m_bCleanTooltip)
|
|
{
|
|
//Clean markup
|
|
CString s(strTip), u, v;
|
|
int j = s.Find(_T("<"));
|
|
int k = s.Find(_T(">"));
|
|
while (j > -1 && k > -1)
|
|
{
|
|
u = s.Left(j);
|
|
v = s.Mid(k + 1);
|
|
s = u + v;
|
|
strTip = s;
|
|
j = s.Find(_T("<"));
|
|
k = s.Find(_T(">"));
|
|
}
|
|
}
|
|
|
|
CXTPToolTipContext::FillInToolInfo(pTI, m_pControl->m_hWnd, rcItem, nHit, strTip);
|
|
|
|
return nHit;
|
|
}
|
|
|
|
BOOL CXTPReportRow::OnLButtonDown(XTP_REPORTRECORDITEM_CLICKARGS *pClickArgs)
|
|
{
|
|
if (m_pControl->m_bFreeHeightMode)
|
|
{
|
|
XTPReportMouseMode mouseMode = m_pControl->GetMouseMode();
|
|
if (mouseMode == xtpReportMouseOverRowDivide)
|
|
{
|
|
m_pControl->SetCapture();
|
|
m_pControl->SetMouseMode(xtpReportMouseNothing);
|
|
CPoint point = pClickArgs->ptClient;
|
|
m_pControl->ClientToScreen(&point);
|
|
CRect rcControl = m_pControl->GetReportRectangle();
|
|
CRect rcRow(GetRect());
|
|
rcRow.right = rcControl.right;
|
|
m_pControl->ClientToScreen(&rcRow);
|
|
m_pControl->ClientToScreen(&rcControl);
|
|
|
|
CXTPSplitterTracker tracker(TRUE, m_pControl->m_bDesktopTrackerMode);
|
|
|
|
CRect rcBound(rcRow.left, rcRow.top + m_pControl->m_nDefaultRowFreeHeight, rcRow.right, point.y);
|
|
CRect rcTracker(rcRow.left, point.y - 2, rcRow.right, point.y - 1);
|
|
CRect rcAvail(rcRow.left, rcRow.top + m_pControl->m_nDefaultRowFreeHeight, rcRow.right, rcControl.bottom);
|
|
|
|
if (tracker.Track(m_pControl, rcAvail, rcTracker, point, FALSE))
|
|
{
|
|
m_nFreeHeight = rcTracker.bottom - rcRow.top;
|
|
|
|
if (GetRecord())
|
|
GetRecord()->m_nFreeHeight = m_nFreeHeight;
|
|
|
|
m_pControl->AdjustScrollBars();
|
|
m_pControl->RedrawControl();
|
|
}
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if (pClickArgs->pItem && pClickArgs->pItem->OnLButtonDown(pClickArgs))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return (BOOL) m_pControl->SendMessageToParent(this, pClickArgs->pItem, pClickArgs->pColumn, XTP_NM_REPORT_LBUTTONDOWN, &pClickArgs->ptClient);
|
|
}
|
|
|
|
BOOL CXTPReportRow::OnLButtonUp(XTP_REPORTRECORDITEM_CLICKARGS *pClickArgs)
|
|
{
|
|
if (m_pControl->m_bFreeHeightMode)
|
|
{
|
|
m_pControl->SetMouseMode(xtpReportMouseNothing);
|
|
ReleaseCapture();
|
|
}
|
|
|
|
if (pClickArgs->pItem && pClickArgs->pItem->OnLButtonUp(pClickArgs))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return (BOOL) m_pControl->SendMessageToParent(this, pClickArgs->pItem, pClickArgs->pColumn, XTP_NM_REPORT_LBUTTONUP, &pClickArgs->ptClient);
|
|
}
|
|
|
|
|
|
|
|
BOOL CXTPReportRow::IsLockExpand() const
|
|
{
|
|
BOOL bLockExpand = FALSE;
|
|
|
|
// Locking on control level
|
|
if (m_pControl)
|
|
{
|
|
bLockExpand = bLockExpand || m_pControl->IsLockExpand();
|
|
}
|
|
|
|
// Locking on rows level (not supported)
|
|
if (m_pParentRows)
|
|
{
|
|
//bLockExpand = bLockExpand || m_pParentRows;
|
|
}
|
|
|
|
// Locking on row level
|
|
bLockExpand = bLockExpand || m_bLockExpand;
|
|
|
|
// Locking on record level (not supported)
|
|
if (m_pRecord)
|
|
{
|
|
//bLockExpand = bLockExpand || m_pRecord;
|
|
}
|
|
|
|
return bLockExpand;
|
|
}
|
|
|
|
void CXTPReportRow::OnClick(CPoint ptClicked)
|
|
{
|
|
XTP_REPORTRECORDITEM_CLICKARGS clickArgs;
|
|
clickArgs.pControl = m_pControl;
|
|
clickArgs.pRow = this;
|
|
clickArgs.pColumn = NULL;
|
|
clickArgs.ptClient = ptClicked;
|
|
|
|
// find clicked item
|
|
clickArgs.pItem = HitTest(ptClicked, &clickArgs.rcItem, &clickArgs.pColumn);
|
|
|
|
if (m_pControl->IsVirtualMode())
|
|
{
|
|
if (m_rcCollapse.PtInRect(ptClicked)
|
|
&& clickArgs.pColumn && clickArgs.pColumn->IsTreeColumn()
|
|
&& m_rcCollapse.PtInRect(m_pControl->m_mouseDownState.ptMouse))
|
|
{
|
|
m_pControl->SendMessageToParent(this, NULL, clickArgs.pColumn, XTP_NM_REPORT_ROWEXPANDED, NULL);
|
|
return;
|
|
}
|
|
}
|
|
if (HasChildren() && m_rcCollapse.PtInRect(ptClicked)
|
|
&& clickArgs.pColumn && clickArgs.pColumn->IsTreeColumn()
|
|
&& m_rcCollapse.PtInRect(m_pControl->m_mouseDownState.ptMouse)
|
|
&& !IsLockExpand())
|
|
{
|
|
SetExpanded(!IsExpanded());
|
|
return;
|
|
}
|
|
|
|
// notify item if found
|
|
if (!clickArgs.pItem)
|
|
return;
|
|
|
|
clickArgs.pItem->OnClick(&clickArgs);
|
|
}
|
|
|
|
void CXTPReportRow::OnDblClick(CPoint ptClicked)
|
|
{
|
|
XTP_REPORTRECORDITEM_CLICKARGS clickArgs;
|
|
clickArgs.pControl = m_pControl;
|
|
clickArgs.pRow = this;
|
|
clickArgs.ptClient = ptClicked;
|
|
clickArgs.pColumn = NULL;
|
|
|
|
// find clicked item
|
|
clickArgs.pItem = HitTest(ptClicked, &clickArgs.rcItem, &clickArgs.pColumn);
|
|
|
|
// notify item if found
|
|
if (clickArgs.pItem != NULL)
|
|
{
|
|
clickArgs.pItem->OnDblClick(&clickArgs);
|
|
}
|
|
else
|
|
{
|
|
// just notify parent
|
|
m_pControl->SendMessageToParent(this, NULL, clickArgs.pColumn, NM_DBLCLK, &ptClicked, -1);
|
|
}
|
|
}
|
|
|
|
CRect CXTPReportRow::GetItemRect(CXTPReportRecordItem* pItem)
|
|
{
|
|
if (!IsItemsVisible() || !pItem || !m_pRecord)
|
|
return CRect(0, 0, 0, 0);
|
|
|
|
if (pItem->IsMerged())
|
|
{
|
|
}
|
|
|
|
if (IsPreviewVisible() && pItem == GetRecord()->GetItemPreview())
|
|
{
|
|
return CRect(m_rcRow.left + m_pControl->GetHeaderIndent(),
|
|
m_rcRow.bottom - m_nPreviewHeight, m_rcRow.right, m_rcRow.bottom);
|
|
}
|
|
|
|
CXTPReportColumns* pColumns = m_pControl->GetColumns();
|
|
int nColumnCount = pColumns->GetCount();
|
|
|
|
CRect rcItem(0, m_rcRow.top, 0, m_rcRow.bottom - m_nPreviewHeight);
|
|
|
|
int nFreezeColCount = m_pControl->GetFreezeColumnsCount();
|
|
if (nFreezeColCount > m_pControl->GetColumns()->GetCount() - 1)
|
|
{
|
|
m_pControl->SetFreezeColumnsCount(0);
|
|
nFreezeColCount = 0;
|
|
}
|
|
|
|
int nLeft = nFreezeColCount ? pColumns->GetAt(nFreezeColCount - 1)->GetRect().right : 0;
|
|
|
|
for (int nColumn = 0; nColumn < nColumnCount; nColumn++)
|
|
{
|
|
CXTPReportColumn* pColumn = pColumns->GetAt(nColumn);
|
|
if (pColumn && pColumn->IsVisible())
|
|
{
|
|
if (m_pRecord->GetItem(pColumn) != pItem)
|
|
continue;
|
|
|
|
rcItem.left = pColumn->GetRect().left;
|
|
rcItem.right = pColumn->GetRect().right;
|
|
if (pColumn->GetIndex() >= nFreezeColCount)
|
|
{
|
|
rcItem.left = max(rcItem.left, nLeft);
|
|
rcItem.right = max(rcItem.right, nLeft);
|
|
}
|
|
if (rcItem.Width() <= 0)
|
|
return CRect(0, 0, 0, 0);
|
|
ShiftTreeIndent(rcItem, pColumn);
|
|
return rcItem;
|
|
}
|
|
}
|
|
return CRect(0, 0, 0, 0);
|
|
}
|
|
|
|
void CXTPReportRow::ShiftTreeIndent(CRect& rcItem, CXTPReportColumn* pColumn) const
|
|
{
|
|
if (pColumn->IsTreeColumn())
|
|
{
|
|
int nTreeDepth = GetTreeDepth() - m_nGroupLevel;
|
|
if (nTreeDepth > 0)
|
|
nTreeDepth++;
|
|
rcItem.left += m_pControl->GetIndent(nTreeDepth);
|
|
|
|
CRect rcBitmap(rcItem);
|
|
int nIndent = m_pControl->GetPaintManager()->DrawCollapsedBitmap(NULL, this, rcBitmap).cx;
|
|
rcItem.left += nIndent + 2;
|
|
}
|
|
}
|
|
|
|
CXTPReportRecordItem* CXTPReportRow::HitTest(CPoint ptPoint, CRect* pRectItem, CXTPReportColumn** ppColumn) const
|
|
{
|
|
if (!m_pRecord)
|
|
return NULL;
|
|
|
|
// find record item
|
|
int x = m_rcRow.left + m_pControl->GetHeaderIndent();
|
|
|
|
CXTPReportColumns* pColumns = m_pControl->GetColumns();
|
|
int nColumnCount = pColumns->GetCount();
|
|
|
|
// if hittest for Preview item
|
|
if (IsPreviewVisible())
|
|
{
|
|
CXTPReportRecordItemPreview* pPreviewItem = GetRecord()->GetItemPreview();
|
|
if (pPreviewItem)
|
|
{
|
|
CRect rcItem(x, m_rcRow.bottom - m_nPreviewHeight, m_rcRow.right, m_rcRow.bottom);
|
|
if (rcItem.PtInRect(ptPoint))
|
|
{
|
|
if (pRectItem)
|
|
{
|
|
*pRectItem = rcItem;
|
|
}
|
|
return pPreviewItem;
|
|
}
|
|
}
|
|
}
|
|
|
|
CRect rcItem(0, m_rcRow.top, 0, m_rcRow.bottom - m_nPreviewHeight);
|
|
|
|
if (!IsItemsVisible())
|
|
return NULL;
|
|
|
|
int nFreezeColCount = m_pControl->GetFreezeColumnsCount();
|
|
if (nFreezeColCount > m_pControl->GetColumns()->GetCount() - 1)
|
|
{
|
|
m_pControl->SetFreezeColumnsCount(0);
|
|
nFreezeColCount = 0;
|
|
}
|
|
|
|
int nLeft = nFreezeColCount ? pColumns->GetAt(nFreezeColCount - 1)->GetRect().right : 0;
|
|
|
|
for (int nColumn = 0; nColumn < nColumnCount; nColumn++)
|
|
{
|
|
CXTPReportColumn* pColumn = pColumns->GetAt(nColumn);
|
|
if (pColumn && pColumn->IsVisible())
|
|
{
|
|
rcItem.left = pColumn->GetRect().left;
|
|
rcItem.right = pColumn->GetRect().right;
|
|
if (pColumn->GetIndex() >= nFreezeColCount)
|
|
{
|
|
rcItem.left = max(rcItem.left, nLeft);
|
|
rcItem.right = max(rcItem.right, nLeft);
|
|
}
|
|
if (!rcItem.Width())
|
|
continue;
|
|
|
|
if (rcItem.PtInRect(ptPoint) && ppColumn)
|
|
{
|
|
*ppColumn = pColumn;
|
|
}
|
|
// make tooltip shift if tree view (see also Draw function)
|
|
ShiftTreeIndent(rcItem, pColumn);
|
|
|
|
// check point
|
|
if (rcItem.PtInRect(ptPoint))
|
|
{
|
|
if (pRectItem)
|
|
{
|
|
*pRectItem = rcItem;
|
|
}
|
|
|
|
CXTPReportRecordItem *pItem = m_pRecord->GetItem(pColumn);
|
|
|
|
if (pItem && pItem->IsMerged())
|
|
{
|
|
pItem = pItem->GetMergeItem();
|
|
}
|
|
|
|
return pItem;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void CXTPReportRow::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
if (m_pControl->m_bFreeHeightMode)
|
|
{
|
|
XTPReportMouseMode mouseMode = m_pControl->GetMouseMode();
|
|
if (mouseMode == xtpReportMouseNothing || mouseMode == xtpReportMouseOverRowDivide)
|
|
{
|
|
CRect rc = GetRect();
|
|
if (rc.bottom - point.y > -2 && rc.bottom - point.y < 4)
|
|
{
|
|
if (mouseMode == xtpReportMouseNothing)
|
|
SetCursor(XTPResourceManager()->LoadCursor(XTP_IDC_VSPLITBAR));
|
|
|
|
m_pControl->SetMouseMode(xtpReportMouseOverRowDivide);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
CRect rcItem;
|
|
CXTPReportRecordItem* pItem = HitTest(point, &rcItem);
|
|
if (pItem != NULL)
|
|
pItem->OnMouseMove(nFlags, point, m_pControl);
|
|
}
|
|
|
|
void CXTPReportRow::FillMetrics(CXTPReportColumn* pColumn, CXTPReportRecordItem* pItem, XTP_REPORTRECORDITEM_METRICS* pMetrics)
|
|
{
|
|
m_pControl->m_nLockUpdateCount++;
|
|
XTP_REPORTRECORDITEM_DRAWARGS drawArgs;
|
|
drawArgs.pDC = NULL;
|
|
drawArgs.pColumn = pColumn;
|
|
drawArgs.pControl = m_pControl;
|
|
drawArgs.pRow = this;
|
|
drawArgs.rcItem.SetRectEmpty();
|
|
drawArgs.pItem = pItem;
|
|
drawArgs.nTextAlign = pColumn ? pColumn->GetAlignment() : DT_LEFT;
|
|
GetItemMetrics(&drawArgs, pMetrics);
|
|
m_pControl->m_nLockUpdateCount--;
|
|
}
|
|
|
|
void CXTPReportRow::ShowToolTip(CPoint ptTip, CXTPReportTip* pTipWnd)
|
|
{
|
|
CRect rcItem(0, 0, 0, 0);
|
|
CXTPReportColumn* pColumn = NULL;
|
|
CXTPReportRecordItem* pItem = HitTest(ptTip, &rcItem, &pColumn);
|
|
// show tooltip
|
|
if (!(pItem &&
|
|
(pItem->IsPreviewItem() || !pItem->IsPreviewItem() && pColumn)))
|
|
{
|
|
pTipWnd->m_pItem = NULL;
|
|
pTipWnd->m_nRowIndex = -1;
|
|
return;
|
|
}
|
|
|
|
if (!m_pControl->IsIconView() &&
|
|
!CXTPDrawHelpers::IsTopParentActive(m_pControl->GetSafeHwnd())
|
|
|| m_pControl->GetActiveItem())
|
|
return;
|
|
|
|
if ((pItem != pTipWnd->m_pItem)
|
|
|| (m_nIndex != pTipWnd->m_nRowIndex))
|
|
{
|
|
pTipWnd->m_pItem = pItem;
|
|
pTipWnd->m_nRowIndex = m_nIndex;
|
|
|
|
CString strTip = pItem->GetTooltip();
|
|
m_pControl->OnGetToolTipInfo(this, pItem, strTip);
|
|
|
|
if (!strTip.IsEmpty()
|
|
|| strTip == _T(" ")
|
|
|| pColumn
|
|
&&
|
|
(pColumn->GetAlignment() & DT_WORDBREAK)
|
|
&& !m_pControl->GetPaintManager()->m_bForceShowTooltip)
|
|
return;
|
|
|
|
if (pItem->GetMarkupUIElement() != NULL)
|
|
return;
|
|
|
|
XTP_REPORTRECORDITEM_METRICS* pMetrics = new XTP_REPORTRECORDITEM_METRICS();
|
|
pMetrics->strText = pItem->GetCaption(pColumn);
|
|
FillMetrics(pColumn, pItem, pMetrics);
|
|
|
|
CString strText(pMetrics->strText);
|
|
|
|
strText.TrimRight();
|
|
|
|
if (strText.IsEmpty())
|
|
{
|
|
pMetrics->InternalRelease();
|
|
return;
|
|
}
|
|
|
|
if (m_pControl->GetMarkupContext() && strText[0] == '<' && strText[strText.GetLength() - 1] == '>') // Markup check
|
|
{
|
|
CXTPMarkupUIElement* pElement = XTPMarkupParseText(m_pControl->GetMarkupContext(), strText);
|
|
|
|
if (pElement)
|
|
{
|
|
XTPMarkupReleaseElement(pElement);
|
|
|
|
pMetrics->InternalRelease();
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
if (!pItem->GetFormula().IsEmpty())
|
|
strText = pItem->GetFormula();
|
|
|
|
XTP_REPORTRECORDITEM_ARGS itemArgs;
|
|
itemArgs.pControl = m_pControl;
|
|
itemArgs.pRow = this;
|
|
|
|
pItem->GetCaptionRect(&itemArgs, rcItem);
|
|
|
|
m_pControl->ClientToScreen(&rcItem);
|
|
|
|
if (!pTipWnd->GetSafeHwnd())
|
|
{
|
|
pTipWnd->Create(m_pControl);
|
|
}
|
|
|
|
CWindowDC dc(m_pControl);
|
|
CXTPFontDC font(&dc, pMetrics->pFont);
|
|
CRect rcTooltip(rcItem);
|
|
BOOL bActivate = FALSE;
|
|
pTipWnd->SetTooltipText(strText);
|
|
if (pItem->IsPreviewItem())
|
|
{
|
|
CRect rcCalc(rcTooltip.left, 0, rcTooltip.right, 0);
|
|
dc.DrawText(strText, &rcCalc, DT_WORDBREAK | DT_CALCRECT | DT_NOPREFIX);
|
|
bActivate = (rcCalc.Height() / dc.GetTextExtent(_T(" "), 1).cy) > m_pControl->GetPaintManager()->GetMaxPreviewLines();
|
|
rcTooltip.bottom = rcTooltip.top + rcCalc.Height();
|
|
rcTooltip.right++;
|
|
}
|
|
else if (m_pControl->IsIconView())
|
|
{
|
|
CRect rcCalc;
|
|
rcCalc = m_pControl->GetPaintManager()->CalculateMaxTextRect(&dc,
|
|
pMetrics->strText, &rcItem, TRUE, FALSE, DT_NOPREFIX | DT_WORDBREAK);
|
|
bActivate = ((rcCalc.Width() >= rcItem.Width() - 3)
|
|
|| (rcCalc.Height() >= rcItem.Height() - 3));
|
|
|
|
rcTooltip.bottom = rcTooltip.top + rcCalc.Height() + 5;
|
|
rcTooltip.right = rcTooltip.left + rcCalc.Width() + 5;
|
|
}
|
|
else
|
|
{
|
|
// Calculate tooltip fine rect
|
|
if (pTipWnd->IsMultilineForce())
|
|
{
|
|
CRect rcCalc;
|
|
rcCalc = m_pControl->GetPaintManager()->CalculateMaxTextRect(&dc,
|
|
pMetrics->strText, &rcItem, TRUE, FALSE, DT_NOPREFIX | DT_WORDBREAK);
|
|
bActivate = ((rcCalc.Width() >= rcItem.Width() - 3)
|
|
|| (rcCalc.Height() >= rcItem.Height() - 3));
|
|
|
|
// with small tuning
|
|
rcTooltip.bottom = rcTooltip.top + rcCalc.Height();
|
|
rcTooltip.right = rcTooltip.left + rcCalc.Width() + 15;
|
|
}
|
|
else
|
|
{
|
|
CSize sz = dc.GetTextExtent(strText);
|
|
bActivate = sz.cx > (rcTooltip.Width() - 4);
|
|
}
|
|
}
|
|
if (bActivate || m_pControl->GetPaintManager()->m_bForceShowTooltip)
|
|
{
|
|
rcTooltip.InflateRect(1, 1, 0, 0);
|
|
|
|
if (!m_pControl->GetPaintManager()->IsGridVisible(FALSE))
|
|
rcTooltip.top++;
|
|
|
|
CRect rcHover(m_rcRow);
|
|
m_pControl->ClientToScreen(&rcHover);
|
|
pTipWnd->SetFont(pMetrics->pFont);
|
|
//pTipWnd->SetTooltipText(strText);
|
|
pTipWnd->SetHoverRect(m_pControl->IsIconView() ? rcHover : rcTooltip);
|
|
pTipWnd->SetTooltipRect(rcTooltip);
|
|
pTipWnd->Activate(TRUE, pTipWnd->IsMultilineForce() || pItem->IsPreviewItem() || m_pControl->IsIconView());
|
|
|
|
TRACKMOUSEEVENT tme =
|
|
{
|
|
sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_pControl->GetSafeHwnd(), 0
|
|
};
|
|
_TrackMouseEvent (&tme);
|
|
}
|
|
|
|
pMetrics->InternalRelease();
|
|
}
|
|
}
|
|
|
|
BOOL CXTPReportRow::HasParent(CXTPReportRow* pRow)
|
|
{
|
|
if (m_pParentRow == NULL)
|
|
return FALSE;
|
|
if (pRow == m_pParentRow)
|
|
return TRUE;
|
|
return m_pParentRow->HasParent(pRow);
|
|
}
|
|
|
|
void CXTPReportRow::SetFullExpanded(BOOL bExpanded)
|
|
{
|
|
if (bExpanded != m_bExpanded && HasChildren())
|
|
{
|
|
if (bExpanded)
|
|
{
|
|
m_pControl->_DoExpand(this);
|
|
}
|
|
else
|
|
{
|
|
m_pControl->_DoCollapse(this);
|
|
}
|
|
|
|
if (m_pRecord)
|
|
{
|
|
m_pRecord->m_bExpanded = bExpanded;
|
|
}
|
|
|
|
m_bExpanded = bExpanded;
|
|
|
|
m_pControl->_RefreshIndexes();
|
|
m_pControl->SendMessageToParent(this, NULL, NULL, XTP_NM_REPORT_ROWEXPANDED, NULL);
|
|
|
|
int n = GetChilds()->GetCount();
|
|
for (int i = n - 1; i >= 0; i--)
|
|
{
|
|
CXTPReportRow* pRow = GetChilds()->GetAt(i);
|
|
if (pRow)
|
|
{
|
|
m_pControl->EndUpdate();
|
|
m_pControl->BeginUpdate();
|
|
|
|
pRow->SetExpanded(bExpanded, TRUE);
|
|
m_pControl->_RefreshIndexes();
|
|
m_pControl->SendMessageToParent(pRow, NULL, NULL, XTP_NM_REPORT_ROWEXPANDED, NULL);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_bExpanded = bExpanded;
|
|
}
|
|
}
|
|
|
|
void CXTPReportRow::SetExpanded(BOOL bExpanded, BOOL bRecursive)
|
|
{
|
|
if (bExpanded != m_bExpanded && HasChildren())
|
|
{
|
|
if (bExpanded)
|
|
{
|
|
m_pControl->_DoExpand(this);
|
|
}
|
|
else
|
|
{
|
|
m_pControl->_DoCollapse(this);
|
|
}
|
|
|
|
if (m_pRecord)
|
|
{
|
|
//m_pRecord->m_bExpanded = bExpanded;
|
|
m_pRecord->SetExpanded(bExpanded);
|
|
}
|
|
|
|
m_bExpanded = bExpanded;
|
|
|
|
m_pControl->_RefreshIndexes();
|
|
m_pControl->SendMessageToParent(this, NULL, NULL, XTP_NM_REPORT_ROWEXPANDED, NULL);
|
|
|
|
if (bRecursive)
|
|
{
|
|
int n = GetChilds()->GetCount();
|
|
for (int i = n - 1; i >= 0; i--)
|
|
{
|
|
CXTPReportRow* pRow = GetChilds()->GetAt(i);
|
|
if (pRow)
|
|
{
|
|
m_pControl->EndUpdate();
|
|
m_pControl->BeginUpdate();
|
|
|
|
pRow->SetExpanded(bExpanded, bRecursive);
|
|
m_pControl->_RefreshIndexes();
|
|
m_pControl->SendMessageToParent(pRow, NULL, NULL, XTP_NM_REPORT_ROWEXPANDED, NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_bExpanded = bExpanded;
|
|
}
|
|
}
|
|
|
|
void CXTPReportRow::LockExpand(BOOL bLock)
|
|
{
|
|
m_bLockExpand = bLock;
|
|
}
|
|
|
|
CXTPReportRow* CXTPReportRow::AddChild(CXTPReportRow* pRow)
|
|
{
|
|
GetChilds()->Add(pRow);
|
|
pRow->m_pParentRow = this;
|
|
|
|
return pRow;
|
|
}
|
|
|
|
void CXTPReportRow::OnContextMenu(CPoint ptClick)
|
|
{
|
|
CXTPReportColumn *pColumn = NULL;
|
|
CXTPReportRecordItem *pItem = HitTest(ptClick, NULL, &pColumn);
|
|
|
|
m_pControl->ClientToScreen(&ptClick);
|
|
|
|
// send process notification to the user and wait for the reaction
|
|
m_pControl->SendMessageToParent(this, pItem, pColumn, NM_RCLICK, &ptClick);
|
|
}
|
|
|
|
void CXTPReportRow::GetItemMetrics(
|
|
XTP_REPORTRECORDITEM_DRAWARGS *pDrawArgs,
|
|
XTP_REPORTRECORDITEM_METRICS *pItemMetrics)
|
|
{
|
|
ASSERT(m_pRecord);
|
|
ASSERT(pDrawArgs->pRow == this);
|
|
ASSERT(pDrawArgs->pItem != NULL);
|
|
|
|
if (!m_pRecord || !pDrawArgs->pItem)
|
|
return;
|
|
|
|
CXTPReportPaintManager *pPaintManager = pDrawArgs->pControl->GetPaintManager();
|
|
|
|
pItemMetrics->pFont = &pPaintManager->m_fontText;
|
|
pItemMetrics->clrForeground = pPaintManager->m_clrWindowText;
|
|
pItemMetrics->clrBackground = XTP_REPORT_COLOR_DEFAULT;
|
|
pItemMetrics->nColumnAlignment = pDrawArgs->nTextAlign;
|
|
pItemMetrics->nItemIcon = XTP_REPORT_NOICON;
|
|
|
|
m_pRecord->GetItemMetrics(pDrawArgs, pItemMetrics);
|
|
pDrawArgs->pItem->GetItemMetrics(pDrawArgs, pItemMetrics);
|
|
|
|
m_pControl->GetItemMetrics(pDrawArgs, pItemMetrics);
|
|
pDrawArgs->nTextAlign = pItemMetrics->nColumnAlignment;
|
|
|
|
if (IsSelected()
|
|
&& (pDrawArgs->pDC
|
|
&& !pDrawArgs->pDC->IsPrinting())
|
|
&& !pDrawArgs->pControl->IsIconView())
|
|
{
|
|
if (pDrawArgs->pColumn
|
|
&& IsFocused()
|
|
&& m_pControl->m_pFocusedColumn == pDrawArgs->pColumn)
|
|
return;
|
|
|
|
if (GetControl()->HasFocus())
|
|
{
|
|
pItemMetrics->clrForeground = pPaintManager->m_clrHighlightText;
|
|
pItemMetrics->clrBackground = pPaintManager->m_clrHighlight;
|
|
}
|
|
else if (!pPaintManager->m_bHideSelection)
|
|
{
|
|
pItemMetrics->clrForeground = pPaintManager->m_clrSelectedRowText;
|
|
pItemMetrics->clrBackground = pPaintManager->m_clrSelectedRow;
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL CXTPReportRow::HasChildren() const
|
|
{
|
|
return m_pChilds && m_pChilds->GetCount() > 0;
|
|
}
|
|
|
|
int CXTPReportRow::GetIndex() const
|
|
{
|
|
return m_nIndex;
|
|
}
|
|
|
|
BOOL CXTPReportRow::IsGroupRow() const
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CXTPReportRow::IsExpanded() const
|
|
{
|
|
return m_bExpanded;
|
|
}
|
|
|
|
BOOL CXTPReportRow::IsVisible() const
|
|
{
|
|
return m_bVisible;
|
|
}
|
|
|
|
void CXTPReportRow::SetVisible(BOOL bVisible)
|
|
{
|
|
m_bVisible = bVisible;
|
|
}
|
|
|
|
BOOL CXTPReportRow::IsLastTreeRow() const
|
|
{
|
|
if (!m_pParentRow)
|
|
return FALSE;
|
|
|
|
CXTPReportRows* pRows = m_pParentRow->GetChilds();
|
|
|
|
return pRows->GetCount() > 0 && pRows->GetAt(pRows->GetCount() - 1) == this;
|
|
}
|
|
|
|
void CXTPReportRow::EnsureVisible()
|
|
{
|
|
m_pControl->EnsureVisible(this);
|
|
}
|
|
|
|
CXTPReportRow* CXTPReportRow::GetNextSiblingRow() const
|
|
{
|
|
if (!m_pParentRows)
|
|
return 0;
|
|
|
|
if (m_nChildIndex == -1)
|
|
return 0;
|
|
|
|
ASSERT(m_pParentRows->GetAt(m_nChildIndex) == this);
|
|
|
|
if (m_nChildIndex < m_pParentRows->GetCount() - 1)
|
|
return m_pParentRows->GetAt(m_nChildIndex + 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOL CXTPReportRow::HasMergedItems() const
|
|
{
|
|
BOOL bMerged = FALSE;
|
|
|
|
CXTPReportRecord *pRecord = GetRecord();
|
|
|
|
if (pRecord)
|
|
{
|
|
for (int iItem=0; iItem<pRecord->GetItemCount(); iItem++)
|
|
{
|
|
CXTPReportRecordItem *pItem = pRecord->GetItem(iItem);
|
|
|
|
if (pItem->IsMerged())
|
|
{
|
|
bMerged = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bMerged;
|
|
}
|
|
|
|
XTPReportRowType CXTPReportRow::GetType() const
|
|
{
|
|
XTPReportRowType rowType = xtpRowTypeInvalid;
|
|
|
|
if (NULL != m_pSection)
|
|
{
|
|
rowType = m_pSection->GetRowType();
|
|
}
|
|
|
|
return rowType;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// IAccessible
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
CCmdTarget* CXTPReportRow::GetAccessible()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
HRESULT CXTPReportRow::GetAccessibleParent(IDispatch* FAR* ppdispParent)
|
|
{
|
|
SAFE_MANAGE_STATE(m_pModuleState);
|
|
|
|
*ppdispParent = m_pControl->GetIDispatch(TRUE);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CXTPReportRow::GetAccessibleChildCount(long FAR* pChildCount)
|
|
{
|
|
if (pChildCount == 0)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
*pChildCount = 0;
|
|
|
|
if (m_pRecord)
|
|
{
|
|
*pChildCount = m_pRecord->GetItemCount();
|
|
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CXTPReportRow::GetAccessibleChild(VARIANT varChild, IDispatch* FAR* ppdispChild)
|
|
{
|
|
*ppdispChild = NULL;
|
|
int nChild = GetChildIndex(&varChild);
|
|
|
|
if (nChild <= 0)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*ppdispChild = NULL;
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT CXTPReportRow::GetAccessibleName(VARIANT varChild, BSTR* pszName)
|
|
{
|
|
int nIndex = GetChildIndex(&varChild);
|
|
|
|
if (nIndex == CHILDID_SELF)
|
|
{
|
|
CString strCaption = _T("Report Row");
|
|
*pszName = strCaption.AllocSysString();
|
|
return S_OK;
|
|
}
|
|
|
|
CXTPReportRecordItem* pItem = m_pRecord->GetItem(nIndex - 1);
|
|
if (!pItem)
|
|
return E_INVALIDARG;
|
|
|
|
CString strCaption = pItem->GetCaption(m_pControl->GetColumns()->Find(pItem->GetIndex()));
|
|
*pszName = strCaption.AllocSysString();
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
HRESULT CXTPReportRow::GetAccessibleRole(VARIANT varChild, VARIANT* pvarRole)
|
|
{
|
|
int nIndex = GetChildIndex(&varChild);
|
|
|
|
if (nIndex == CHILDID_SELF)
|
|
{
|
|
pvarRole->vt = VT_I4;
|
|
pvarRole->lVal = ROLE_SYSTEM_ROW;
|
|
|
|
}
|
|
else
|
|
{
|
|
pvarRole->vt = VT_I4;
|
|
pvarRole->lVal = ROLE_SYSTEM_CELL;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CXTPReportRow::GetAccessibleState(VARIANT varChild, VARIANT* pvarState)
|
|
{
|
|
pvarState->vt = VT_I4;
|
|
pvarState->lVal = 0;
|
|
int nChild = GetChildIndex(&varChild);
|
|
|
|
if (nChild == CHILDID_SELF)
|
|
{
|
|
pvarState->lVal = 0;
|
|
|
|
if (IsSelected())
|
|
pvarState->lVal = STATE_SYSTEM_SELECTED;
|
|
}
|
|
else
|
|
{
|
|
CXTPReportRecordItem* pItem = m_pRecord->GetItem(nChild - 1);
|
|
if (pItem)
|
|
{
|
|
CXTPReportColumn* pColumn = m_pControl->GetColumns()->Find(pItem->GetIndex());
|
|
if (pColumn && !pColumn->IsVisible())
|
|
{
|
|
pvarState->lVal = STATE_SYSTEM_INVISIBLE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CXTPReportRow::AccessibleLocation(long* pxLeft, long* pyTop, long* pcxWidth, long* pcyHeight, VARIANT varChild)
|
|
{
|
|
*pxLeft = *pyTop = *pcxWidth = *pcyHeight = 0;
|
|
|
|
CRect rc(0, 0, 0, 0);
|
|
|
|
int nChild = GetChildIndex(&varChild);
|
|
|
|
if (nChild == CHILDID_SELF)
|
|
{
|
|
rc = GetRect();
|
|
m_pControl->ClientToScreen(&rc);
|
|
}
|
|
else
|
|
{
|
|
CXTPReportRecordItem* pItem = m_pRecord->GetItem(nChild - 1);
|
|
if (pItem)
|
|
{
|
|
rc = GetItemRect(pItem);
|
|
m_pControl->ClientToScreen(&rc);
|
|
}
|
|
|
|
}
|
|
|
|
*pxLeft = rc.left;
|
|
*pyTop = rc.top;
|
|
*pcxWidth = rc.Width();
|
|
*pcyHeight = rc.Height();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CXTPReportRow::AccessibleHitTest(long xLeft, long yTop, VARIANT* pvarID)
|
|
{
|
|
if (pvarID == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
pvarID->vt = VT_I4;
|
|
pvarID->lVal = CHILDID_SELF;
|
|
|
|
CPoint pt(xLeft, yTop);
|
|
m_pControl->ScreenToClient(&pt);
|
|
|
|
if (!GetRect().PtInRect(pt))
|
|
return S_FALSE;
|
|
|
|
|
|
CXTPReportRecordItem* pItem = HitTest(pt);
|
|
if (pItem)
|
|
{
|
|
pvarID->lVal = pItem->GetIndex() + 1;
|
|
return S_OK;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
BEGIN_INTERFACE_MAP(CXTPReportRow, CCmdTarget)
|
|
INTERFACE_PART(CXTPReportRow, IID_IAccessible, ExternalAccessible)
|
|
END_INTERFACE_MAP()
|