DragonNest/Third/XTToolkitPro/Source/ReportControl/XTPReportHeader.cpp
2024-12-19 09:48:26 +08:00

1636 lines
39 KiB
C++

// XTPReportHeader.cpp : implementation of the CXTPReportHeader class.
//
// This file is a part of the XTREME REPORTCONTROL MFC class library.
// (c)1998-2008 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 "Resource.h"
#include "Common/Resource.h"
#include "Common/XTPDrawHelpers.h"
#include "Common/XTPPropExchange.h"
#include "Common/XTPToolTipContext.h"
#include "Common/XTPResourceManager.h"
#include "XTPReportColumn.h"
#include "XTPReportColumns.h"
#include "XTPReportRecordItem.h"
#include "XTPReportControl.h"
#include "XTPReportPaintManager.h"
#include "XTPReportSubListControl.h"
#include "XTPReportFilterEditControl.h"
#include "XTPReportDragDrop.h"
#include "XTPReportInplaceControls.h"
#include "XTPReportHeader.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CXTPReportHeader
int CXTPReportHeader::s_nMinAutoScrollStep = 3;
BOOL CXTPReportHeader::s_bShowItemsInGroupsPXDefault = TRUE;
BOOL CXTPReportHeader::s_bSendContextMenuForWholeHeaderArea = FALSE;
CXTPReportHeader::CXTPReportHeader(CXTPReportControl* pControl, CXTPReportColumns* pColumns)
: m_pColumns(pColumns), m_pControl(pControl)
{
m_nResizeCaptureRange = 3;
m_pSubList = NULL;
m_pFilterEdit = NULL;
m_dragMode = dragNothing;
m_nDropIndex = -1;
m_rcHeader.SetRect(0, 0, 0, 0);
m_pDropWnd = NULL;
m_pDragWnd = NULL;
m_pHotTrackingColumn = NULL;
m_bAllowColumnResize = TRUE;
m_bAllowColumnRemove = TRUE;
m_bAllowColumnReorder = TRUE;
m_bAllowColumnSort = TRUE;
m_pDragColumn = NULL;
m_hResizeCursor = XTPResourceManager()->LoadCursor(XTP_IDC_VRESIZE);
m_hDontDropCursor = XTPResourceManager()->LoadCursor(XTP_IDC_REPORT_NODROP);
m_bShowItemsInGroups = FALSE;
m_bDragHeader = m_bDragGroupBox = FALSE;
m_nIndentLevel = 0;
m_bAutoColumnSizing = TRUE;
m_nHeaderWidth = 0;
}
CXTPReportHeader::~CXTPReportHeader()
{
DestroyDropWnd();
if (m_pDragWnd)
m_pDragWnd->DestroyWindow();
}
CXTPReportPaintManager* CXTPReportHeader::GetPaintManager() const
{
return m_pControl->GetPaintManager();
}
void CXTPReportHeader::Draw(CDC* pDC, CRect rcHeader, int nLeftOffset)
{
int nFreezeCols = GetControl()->m_nFreezeColumnsCount;
rcHeader.OffsetRect(-nLeftOffset, 0);
m_rcHeader = rcHeader;
// draw background
CXTPClientRect rcHeaderClientArea(m_pControl);
rcHeaderClientArea.top = rcHeader.top;
rcHeaderClientArea.bottom = rcHeader.bottom;
GetPaintManager()->FillHeaderControl(pDC, rcHeaderClientArea);
int x = rcHeader.left;
// draw items
int nColumnsCount = m_pColumns->GetCount(), nColumn;
for (nColumn = 0; nColumn < nColumnsCount; nColumn++)
{
CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
if (pColumn && pColumn->IsVisible())
{
CRect rcItem(x, rcHeader.top, x + pColumn->GetWidth(), rcHeader.bottom);
pColumn->m_rcColumn = rcItem;
if (rcItem.Height() > 0 && CRect().IntersectRect(rcHeaderClientArea, rcItem))
{
GetPaintManager()->DrawColumn(pDC, pColumn, this, rcItem);
}
x += rcItem.Width();
pColumn->m_nMaxItemWidth = 0;
}
}
int xFreeze = 0;
// draw freeze items
for (nColumn = 0; nFreezeCols > 0 && nColumn < nColumnsCount; nColumn++)
{
CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
if (pColumn && pColumn->IsVisible())
{
CRect rcItem(xFreeze, rcHeader.top, xFreeze + pColumn->GetWidth(), rcHeader.bottom);
pColumn->m_rcColumn = rcItem;
if (rcItem.Height() > 0 && CRect().IntersectRect(rcHeaderClientArea, rcItem))
{
GetPaintManager()->FillHeaderControl(pDC, pColumn->m_rcColumn);
GetPaintManager()->DrawColumn(pDC, pColumn, this, rcItem);
if (nFreezeCols == 1 &&
(GetPaintManager()->GetFreezeColsDividerStyle() & xtpReportFreezeColsDividerHeader))
GetPaintManager()->DrawFreezeColsDivider(pDC, rcItem, GetControl());
}
xFreeze += rcItem.Width();
nFreezeCols--;
}
}
// draw empty column to fill free header area
if (x < rcHeaderClientArea.right)
{
CRect rcEmptyColumn = rcHeaderClientArea;
rcEmptyColumn.left = x;
rcEmptyColumn.right += 10;
CXTPReportColumn colEmpty(0, _T(""), rcEmptyColumn.Width(), FALSE,
XTP_REPORT_NOICON, FALSE, TRUE);
ASSERT(m_pColumns);
colEmpty.m_pColumns = m_pColumns;
GetPaintManager()->DrawColumn(pDC, &colEmpty, this, rcEmptyColumn);
}
}
void CXTPReportHeader::CancelMouseMode()
{
if (m_pControl->GetMouseMode() != xtpReportMouseNothing)
{
m_pControl->SetMouseMode(xtpReportMouseNothing);
m_pDragColumn = NULL;
SetHotDivider(-1);
// Drag wnd cleanup
if (m_pDragWnd != NULL)
{
m_pDragWnd->DestroyWindow();
m_pDragWnd = NULL;
}
if (CWnd::GetCapture() == m_pControl)
ReleaseCapture();
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
m_bDragGroupBox = FALSE;
m_bDragHeader = FALSE;
m_pControl->RedrawControl();
}
}
void CXTPReportHeader::SetAutoColumnSizing(BOOL bAutoColumnSizing)
{
m_bAutoColumnSizing = bAutoColumnSizing;
m_pControl->m_nLeftOffset = 0;
if (m_bAutoColumnSizing && m_pControl->m_hWnd)
{
m_pControl->EnableScrollBarCtrl(SB_HORZ, FALSE);
}
AdjustColumnsWidth(m_pControl->m_rcHeaderArea.Width());
m_pControl->RedrawControl();
}
void CXTPReportHeader::OnColumnsChanged(BOOL bGroupOrderChanged)
{
AdjustColumnsWidth(m_pControl->m_rcHeaderArea.Width());
if (!GetPaintManager()->IsFixedRowHeight())
m_pControl->AdjustScrollBars();
m_pControl->UpdateSubList();
m_pControl->RedrawControl();
m_pControl->SendNotifyMessage(XTP_NM_REPORT_COLUMNORDERCHANGED);
if(bGroupOrderChanged)
m_pControl->SendNotifyMessage(XTP_NM_REPORT_GROUPORDERCHANGED);
}
void CXTPReportHeader::TrackColumn(CXTPReportColumn* pColumn, CPoint point)
{
CXTPClientRect rcControl(m_pControl);
m_pControl->ClientToScreen(&point);
CRect rcColumn(pColumn->GetRect());
rcColumn.bottom = rcControl.bottom;
m_pControl->ClientToScreen(&rcColumn);
int nBottomMax = rcColumn.bottom;
int nLeftMin = 0;
CDC* pDC = m_pControl->GetDC();
if (pDC)
{
CRect rcVisible;
UINT uRes = pDC->GetBoundsRect(&rcVisible, 0);
m_pControl->ReleaseDC(pDC);
pDC = NULL;
if ((uRes & DCB_SET) == DCB_SET)
{
m_pControl->ClientToScreen(&rcVisible);
nBottomMax = min(rcVisible.bottom, nBottomMax);
nLeftMin = rcVisible.left;
}
}
int nMaxAvailWidth = GetMaxAvailWidth(pColumn);
int nMinWidth = pColumn->GetMinWidth();
CRect rcAvail(rcColumn.left + nMinWidth, rcColumn.top,
rcColumn.left + nMaxAvailWidth, nBottomMax);
CRect rcTracker(rcColumn.right, rcColumn.top, rcColumn.right + 1, nBottomMax);
CRect rcBound(rcColumn.left - 1, rcColumn.top, rcColumn.left, nBottomMax);
BOOL bLayoutRTL = m_pControl->GetExStyle() & WS_EX_LAYOUTRTL;
if (bLayoutRTL)
{
rcAvail.SetRect(rcColumn.left - nMaxAvailWidth, rcColumn.top,
rcColumn.right - nMinWidth, nBottomMax);
}
CXTPSplitterTracker tracker(TRUE);
CRect rcBoundX = bLayoutRTL ? rcTracker : rcBound;
if (!bLayoutRTL && rcBoundX.left > nLeftMin ||
bLayoutRTL && rcBoundX.left < nLeftMin)
{
tracker.SetBoundRect(rcBoundX);
}
if (tracker.Track(m_pControl, rcAvail, bLayoutRTL ? rcBound : rcTracker, point, TRUE))
{
ResizeColumn(pColumn, rcTracker.left - rcBound.right);
m_pControl->RedrawControl();
}
}
void CXTPReportHeader::OnLButtonDblClk(CPoint ptClick)
{
if (m_pControl->GetMouseMode() == xtpReportMouseOverColumnDivide)
{
CPoint ptLeftColumn(ptClick);
ptLeftColumn.x -= m_nResizeCaptureRange + 1;
CXTPReportColumn* pColumn = HitTest(ptLeftColumn);
if (pColumn != NULL)
{
BestFit(pColumn);
}
}
}
void CXTPReportHeader::OnLButtonDown(CPoint ptClick)
{
m_pControl->SetCapture();
if (m_pControl->GetMouseMode() == xtpReportMouseOverColumnDivide)
{
CXTPReportColumn* pColumn = MouseOverColumnResizeArea(ptClick);
if (pColumn != NULL && pColumn->IsResizable() && m_bAllowColumnResize)
{
if (!m_bAutoColumnSizing || (!IsLastResizebleColumn(pColumn) && !IsLastVisibleColumn(pColumn)))
{
m_pControl->SetMouseMode(xtpReportMouseNothing);
TrackColumn(pColumn, ptClick);
return;
}
}
}
if (m_pControl->GetMouseMode() == xtpReportMouseNothing)
{
BOOL bDragHeader = FALSE;
CXTPReportColumn* pColumn = NULL;
if (m_rcHeader.PtInRect(ptClick))
{
int nColumn = HitTestHeaderColumnIndex(ptClick);
pColumn = m_pColumns->GetAt(nColumn);
bDragHeader = TRUE;
}
else if (m_rcGroupBy.PtInRect(ptClick))
{
int nColumn = FindGroupByColumn(ptClick, TRUE);
pColumn = m_pColumns->GetGroupsOrder()->GetAt(nColumn);
}
if (pColumn != NULL)
{
StartDragging(pColumn, bDragHeader);
m_ptMouse = ptClick;
m_pControl->SetMouseMode(xtpReportMousePrepareDragColumn);
m_pControl->RedrawControl();
}
}
}
void CXTPReportHeader::AdjustColumnsWidth(int nTotalWidth, int nFirstIndex)
{
if (m_bAutoColumnSizing)
{
int nColumnsWidth = 0;
CXTPReportColumn* pLastAutoColumn = NULL;
int nColumn;
for (nColumn = nFirstIndex; nColumn < m_pColumns->GetCount(); nColumn++)
{
CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
if (!pColumn->IsVisible())
continue;
if (pColumn->m_bAutoSize)
{
pLastAutoColumn = pColumn;
nColumnsWidth += pColumn->m_nColumnAutoWidth;
}
else
{
nTotalWidth -= pColumn->GetWidth();
}
}
if (pLastAutoColumn && nTotalWidth > 0)
{
for (nColumn = nFirstIndex; nColumn < m_pColumns->GetCount(); nColumn++)
{
CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
if (!pColumn->IsVisible())
continue;
if (pColumn->m_bAutoSize)
{
if (pColumn == pLastAutoColumn)
{
pColumn->m_nColumnStaticWidth = max(nTotalWidth, pColumn->GetMinWidth());
if(pColumn->m_nColumnStaticWidth != pColumn->m_nColumnAutoWidth)
{
XTP_NM_REPORTCOLUMNRESIZE nmData;
nmData.pColumn = pColumn;
nmData.nPrevWidth = pColumn->m_nColumnAutoWidth;
nmData.nNewWidth = pColumn->m_nColumnStaticWidth;
m_pControl->SendNotifyMessage(XTP_NM_REPORT_COLUMNWIDTHCHANGED, (NMHDR*)&nmData);
}
}
else
{
nColumnsWidth = max(1, nColumnsWidth);
pColumn->m_nColumnStaticWidth =
max(int(pColumn->m_nColumnAutoWidth * nTotalWidth / nColumnsWidth), pColumn->GetMinWidth());
if(pColumn->m_nColumnStaticWidth != pColumn->m_nColumnAutoWidth)
{
XTP_NM_REPORTCOLUMNRESIZE nmData;
nmData.pColumn = pColumn;
nmData.nPrevWidth = pColumn->m_nColumnAutoWidth;
nmData.nNewWidth = pColumn->m_nColumnStaticWidth;
m_pControl->SendNotifyMessage(XTP_NM_REPORT_COLUMNWIDTHCHANGED, (NMHDR*)&nmData);
}
nTotalWidth -= pColumn->m_nColumnStaticWidth;
nColumnsWidth -= pColumn->m_nColumnAutoWidth;
}
}
}
}
m_nHeaderWidth = m_pControl->m_rcHeaderArea.Width();
}
else
{
m_nHeaderWidth = 0;
for (int nColumn = 0; nColumn < m_pColumns->GetCount(); nColumn++)
{
CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
if (pColumn && pColumn->IsVisible())
m_nHeaderWidth += pColumn->GetWidth();
}
if (m_nHeaderWidth == 0)
{
m_nHeaderWidth = nTotalWidth;
}
m_pControl->AdjustScrollBars();
}
XTP_NM_REPORTCOLUMNRESIZE nmData;
ZeroMemory(&nmData, sizeof(nmData));
m_pControl->SendNotifyMessage(XTP_NM_REPORT_COLUMNWIDTHCHANGED, (NMHDR*)&nmData);
}
void CXTPReportHeader::ResizeColumn(CXTPReportColumn* pColumnResize, int nWidth)
{
int nResizeIndex = 0;
int nColumn;
int nTotalWidth = 0;
ASSERT(pColumnResize->IsResizable());
for (nColumn = 0; nColumn < m_pColumns->GetCount(); nColumn++)
{
CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
if (!pColumn->IsVisible())
continue;
if (nResizeIndex > 0)
nTotalWidth += pColumn->m_nColumnStaticWidth;
if (pColumnResize == pColumn)
{
int nDelta = pColumn->GetWidth() - nWidth;
nResizeIndex = nColumn + 1;
nTotalWidth = - nWidth + pColumn->GetWidth();
pColumn->m_nColumnStaticWidth = nWidth;
if (m_bAutoColumnSizing)
{
// if next column is "last resizeble" but not "auto size" column - resize it too.
CXTPReportColumn* pColNext = CXTPReportHeader::GetNextVisibleColumn(nColumn, 1);
if (pColNext && !pColNext->IsAutoSize() && pColNext->IsResizable() &&
IsLastResizebleColumn(pColNext))
{
pColNext->m_nColumnStaticWidth += nDelta;
if(pColNext->m_nColumnStaticWidth != pColNext->m_nColumnAutoWidth)
{
XTP_NM_REPORTCOLUMNRESIZE nmData;
nmData.pColumn = pColNext;
nmData.nPrevWidth = pColNext->m_nColumnAutoWidth;
nmData.nNewWidth = pColNext->m_nColumnStaticWidth;
m_pControl->SendNotifyMessage(XTP_NM_REPORT_COLUMNWIDTHCHANGED, (NMHDR*)&nmData);
}
}
}
}
if(pColumn->m_nColumnStaticWidth != pColumn->m_nColumnAutoWidth)
{
XTP_NM_REPORTCOLUMNRESIZE nmData;
nmData.pColumn = pColumn;
nmData.nPrevWidth = pColumn->m_nColumnAutoWidth;
nmData.nNewWidth = pColumn->m_nColumnStaticWidth;
m_pControl->SendNotifyMessage(XTP_NM_REPORT_COLUMNWIDTHCHANGED, (NMHDR*)&nmData);
}
pColumn->m_nColumnAutoWidth = pColumn->m_nColumnStaticWidth;
}
AdjustColumnsWidth(nTotalWidth, nResizeIndex);
for (nColumn = 0; nColumn < m_pColumns->GetCount(); nColumn++)
{
CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
pColumn->m_nColumnAutoWidth = pColumn->m_nColumnStaticWidth;
}
AdjustColumnsWidth(m_rcHeader.Width());
if (!GetPaintManager()->IsFixedRowHeight())
m_pControl->AdjustScrollBars();
}
void CXTPReportHeader::OnLButtonUp(UINT nFlags, CPoint ptClick)
{
XTPReportMouseMode mouseMode = m_pControl->GetMouseMode();
m_pControl->SetMouseMode(xtpReportMouseNothing);
ReleaseCapture();
if (mouseMode == xtpReportMouseDraggingColumn)
{
// End dragging column
CXTPReportColumn* pDragColumn = m_pDragColumn;
ASSERT(pDragColumn);
if (!pDragColumn)
return;
BOOL bGroupOrderChanged = FALSE;
// Drop column - change position
if (m_dragMode == dragOutTarget || m_dragMode == dragFieldChooser)
{
if (m_bAllowColumnRemove && pDragColumn->m_bAllowRemove)
{
if (m_bDragHeader)
{
XTP_TRACE(_T("Removing column\n"));
pDragColumn->SetVisible(FALSE);
}
else if (m_bDragGroupBox)
{
m_pColumns->GetGroupsOrder()->Remove(pDragColumn);
bGroupOrderChanged = TRUE;
m_pControl->Populate();
}
}
}
else if (((m_dragMode & dragInTarget) != 0) && m_nDropIndex >= 0)
{
XTP_TRACE(_T("Changing column position to %d\n"), m_nDropIndex);
CXTPClientRect rcClient(m_pControl);
CRect rcHeaderFull = m_rcHeader;
rcHeaderFull.right = rcClient.right;
if (rcHeaderFull.PtInRect(ptClick))
{
int nDragIndex = m_pColumns->IndexOf(pDragColumn);
pDragColumn->SetVisible();
m_pColumns->ChangeColumnOrder(m_nDropIndex, nDragIndex);
if (m_bDragGroupBox && ((nFlags & MK_CONTROL) == 0))
{
m_pColumns->GetGroupsOrder()->Remove(pDragColumn);
bGroupOrderChanged = TRUE;
m_pControl->Populate();
}
}
else if (m_rcGroupBy.PtInRect(ptClick))
{
// set grouping by
m_pColumns->GetGroupsOrder()->InsertAt(m_nDropIndex, pDragColumn);
bGroupOrderChanged = TRUE;
if (m_bDragHeader && ((nFlags & MK_CONTROL) == 0))
{
pDragColumn->SetVisible(FALSE);
}
m_pControl->Populate();
}
}
m_dragMode = dragNothing;
OnColumnsChanged(bGroupOrderChanged);
SetHotDivider(-1);
m_pDragColumn = NULL;
// Drag wnd cleanup
if (m_pDragWnd != NULL)
{
m_pDragWnd->DestroyWindow();
m_pDragWnd = NULL;
}
m_bDragHeader = m_bDragGroupBox = FALSE;
return; // Stop message processing
}
if (m_pDragColumn && m_pDragColumn == HitTest(ptClick))
{
m_pControl->SendMessageToParent(NULL, NULL, m_pDragColumn, NM_CLICK, &ptClick);
}
// End holding left mouse button - change sort order for the column
if (mouseMode == xtpReportMousePrepareDragColumn)
{
if (!m_pDragColumn)
return;
CXTPReportColumn* pColumn = m_pDragColumn;
m_pDragColumn = NULL;
// change sort order
if (pColumn->IsSortable() && m_bAllowColumnSort)
{
BOOL bGroupOrderChanged = FALSE;
// do not reset sort order if clicked on the column header from the Group By area
if (m_bDragHeader)
{
CXTPReportColumnOrder* pColumnOrder = m_bShowItemsInGroups && pColumn->IsGroupable() ?
m_pColumns->GetGroupsOrder(): m_pColumns->GetSortOrder();
BOOL bColumnFound = pColumnOrder->IndexOf(pColumn) >= 0;
if (GetKeyState(VK_SHIFT) >= 0)
{
if (m_bShowItemsInGroups && !IsAllowColumnRemove())
{
for (int i = 0; i < pColumnOrder->GetCount(); i++)
{
pColumnOrder->GetAt(i)->SetVisible();
}
}
pColumnOrder->Clear();
pColumnOrder->Add(pColumn);
bGroupOrderChanged = m_bShowItemsInGroups;
}
else if (!bColumnFound)
{
pColumnOrder->Add(pColumn);
bGroupOrderChanged = m_bShowItemsInGroups;
}
if (bColumnFound)
{
pColumn->m_bSortIncreasing = !pColumn->m_bSortIncreasing;
}
}
else
{
pColumn->m_bSortIncreasing = !pColumn->m_bSortIncreasing;
}
m_pControl->SendNotifyMessage(XTP_NM_REPORT_PRESORTORDERCHANGED);
if (bGroupOrderChanged)
m_pControl->Populate();
else
m_pControl->ReSortRows();
m_pControl->SendNotifyMessage(XTP_NM_REPORT_SORTORDERCHANGED);
if (bGroupOrderChanged)
{
OnColumnsChanged(bGroupOrderChanged);
}
}
else
{
// redraw
m_pControl->RedrawControl();
}
m_bDragHeader = m_bDragGroupBox = FALSE;
}
}
CXTPReportColumn* CXTPReportHeader::HitTest(CPoint ptPoint) const
{
int nIndex = HitTestHeaderColumnIndex(ptPoint);
if (nIndex < 0 || m_pColumns == NULL)
return NULL;
return m_pColumns->GetAt(nIndex);
}
int CXTPReportHeader::HitTestHeaderColumnIndex(CPoint ptPoint) const
{
if (!m_pControl->m_rcHeaderArea.PtInRect(ptPoint))
return -1;
int x = m_rcHeader.left;
int nFreezeCols = GetControl()->m_nFreezeColumnsCount;
// enumerate items
int nColumnCount = m_pColumns->GetCount();
for (int nColumn = 0; nColumn < nColumnCount; nColumn++)
{
CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
if (pColumn && pColumn->IsVisible())
{
x += pColumn->GetWidth();
if (ptPoint.x < x - (nFreezeCols > 0 ? m_rcHeader.left : 0))
{
return nColumn;
}
nFreezeCols--;
}
}
return -1;
}
int CXTPReportHeader::GetFulColScrollInfo(CXTPReportColumn*& rpPrev, CXTPReportColumn*& rpCurr, CXTPReportColumn*& rpNext,
int& rnScrollPos, int& rnScrollMax) const
{
int x = m_rcHeader.left;
int nLBorderX = 0;
rnScrollPos = -1;
rnScrollMax = 0;
rpPrev = rpCurr = rpNext = NULL;
BOOL bFind = FALSE;
int nFreezeCols = GetControl()->m_nFreezeColumnsCount;
// enumerate items
int nColumnCount = m_pColumns->GetCount();
for (int nColumn = 0; nColumn < nColumnCount; nColumn++)
{
CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
if (pColumn && pColumn->IsVisible())
{
if (nFreezeCols <= 0)
rnScrollMax++;
if (!bFind)
{
if (nFreezeCols <= 0)
rnScrollPos++;
rpPrev = rpCurr;
rpCurr = pColumn;
x += pColumn->GetWidth();
if (nFreezeCols > 0)
{
nLBorderX += pColumn->GetWidth();
nFreezeCols--;
}
else
{
if (nLBorderX + 1 < x)
{
bFind = TRUE;
}
}
}
else if (!rpNext)
{
rpNext = pColumn;
}
}
}
return nLBorderX;
}
CXTPReportColumn* CXTPReportHeader::MouseOverColumnResizeArea(CPoint ptPoint)
{
if (ptPoint.y >= m_rcHeader.bottom ||
ptPoint.y <= m_rcHeader.top)
{
return NULL;
}
// enumerate columns
int nVisColCount = m_pColumns->GetVisibleColumnsCount() - (m_bAutoColumnSizing ? 1 : 0);
int nFreezeCols = min(GetControl()->m_nFreezeColumnsCount, nVisColCount);
int xMaxFreezeR = 0;
for (int nColumn = 0; nColumn < nVisColCount; nColumn++)
{
BOOL bFreezeCol = nColumn < nFreezeCols;
int nColIdx = bFreezeCol ? nColumn : nVisColCount + nFreezeCols - 1 - nColumn;
CXTPReportColumn* pColumn = m_pColumns->GetVisibleAt(nColIdx);
ASSERT(pColumn->IsVisible());
if (!pColumn->IsResizable())
continue;
int xBorderR = pColumn->GetRect().right;
if (bFreezeCol)
{
xMaxFreezeR = max(xMaxFreezeR, xBorderR);
}
else if (xBorderR <= xMaxFreezeR)
{
return NULL;
}
if (abs(ptPoint.x - xBorderR) <= m_nResizeCaptureRange)
{
if (!m_bAutoColumnSizing ||
(!IsLastResizebleColumn(pColumn) && !IsLastVisibleColumn(pColumn)))
{
return pColumn;
}
}
}
return NULL;
}
int CXTPReportHeader::FindHeaderColumn(CPoint ptPoint) const
{
// Find column in header
CXTPClientRect rcClient(m_pControl);
CRect rcLastEmptyCol = m_rcHeader;
rcLastEmptyCol.left = m_rcHeader.right;
rcLastEmptyCol.right = rcClient.right;
int nCount = m_pColumns->GetCount();
int nVisColCount = m_pColumns->GetVisibleColumnsCount();
if (rcLastEmptyCol.PtInRect(ptPoint))
{
return nCount;
}
if (!m_pControl->m_rcHeaderArea.PtInRect(ptPoint))
return -1;
int nFreezeCols = min(GetControl()->m_nFreezeColumnsCount, nVisColCount);
int xMaxFreezeR = 0;
for (int nColumn = 0; nColumn < nVisColCount; nColumn++)
{
BOOL bFreezeCol = nColumn < nFreezeCols;
int nColIdx = bFreezeCol ? nColumn : nVisColCount + nFreezeCols - 1 - nColumn;
BOOL bLastFreezeCol = nColumn + 1 == nFreezeCols;
CXTPReportColumn* pColumn = m_pColumns->GetVisibleAt(nColIdx);
ASSERT(pColumn->IsVisible());
int xBorderR = pColumn->GetRect().right;
if (bFreezeCol)
{
xMaxFreezeR = max(xMaxFreezeR, xBorderR);
}
else if (xBorderR <= xMaxFreezeR)
{
return -1;
}
CRect rcTest0 = pColumn->GetRect();
if (!bFreezeCol)
{
rcTest0.left = max(xMaxFreezeR, rcTest0.left);
}
CRect rcTest1 = rcTest0;
if (rcTest0.left != pColumn->GetRect().left)
{
rcTest0.SetRect(0, 0, 0, 0);
}
else if (rcTest0.right > rcClient.right)
{
rcTest1.SetRect(0, 0, 0, 0);
}
else
{
rcTest0.right -= rcTest0.Width()/2;
rcTest1.left += rcTest0.Width()/2;
}
if (rcTest0.PtInRect(ptPoint))
{
return pColumn->GetIndex();
}
if (rcTest1.PtInRect(ptPoint))
{
if (bLastFreezeCol && GetControl()->m_nLeftOffset != 0)
{
return pColumn->GetIndex();
}
else
{
return pColumn->GetIndex() + 1;
}
}
}
return 0;
}
int CXTPReportHeader::FindGroupByColumn(CPoint ptPoint, BOOL bExactSearch) const
{
// Find column in Group By area
if (m_rcGroupBy.PtInRect(ptPoint))
{
CXTPReportPaintManager* pPaintManager = GetPaintManager();
int nHeaderHeight = pPaintManager->GetHeaderHeight();
if (bExactSearch)
{
int x = m_rcGroupBy.left + 9;
int y = m_rcGroupBy.top + 7;
//int nTargetColumn = -1;
CXTPReportColumn* pColumn = NULL;
// draw items
int nColumnsCount = m_pColumns->GetGroupsOrder()->GetCount();
for (int nColumn = 0; nColumn < nColumnsCount; nColumn++)
{
pColumn = m_pColumns->GetGroupsOrder()->GetAt(nColumn);
if (pColumn)
{
CRect rcItem(x, y, x + pColumn->m_rcGroupBy.Width(), y + nHeaderHeight - 3);
if (rcItem.PtInRect(ptPoint))
return nColumn;
// next column
x = rcItem.right + 5;
y = rcItem.top + rcItem.Height() / 2;
}
}
return nColumnsCount;
}
else
{
int xLeft = m_rcGroupBy.left + 9;
int xRight;
//int nTargetColumn = -1;
CXTPReportColumn* pColumn = NULL;
// draw items
int nColumnsCount = m_pColumns->GetGroupsOrder()->GetCount();
for (int nColumn = 0; nColumn < nColumnsCount; nColumn++)
{
pColumn = m_pColumns->GetGroupsOrder()->GetAt(nColumn);
if (pColumn)
{
xRight = xLeft + pColumn->m_rcGroupBy.Width();
if (ptPoint.x <= xRight)
{
if (ptPoint.x <= (xLeft + xRight) / 2)
return nColumn;
return nColumn + 1;
}
// next column
xLeft = xRight + 5;
}
}
return nColumnsCount;
}
}
return -1;
}
void CXTPReportHeader::DestroyDropWnd()
{
if (m_pDropWnd != NULL)
{
m_pDropWnd->DestroyWindow();
m_pDropWnd = NULL;
}
}
int CXTPReportHeader::SetHotDivider(int nIndex, BOOL bHeader)
{
m_nDropIndex = nIndex;
if (nIndex < 0)
{
DestroyDropWnd();
return nIndex;
}
CXTPReportPaintManager* pPaintManager = GetPaintManager();
int nHeaderHeight = pPaintManager->GetHeaderHeight();
// compare hot divider left and right columns with dragging column
// and do not show hot divider near dragging column
CXTPReportColumn* pDraggingColumn = GetDraggingColumn();
CPoint pt;
if (bHeader)
{
if (pDraggingColumn)
{
// find column following hot divider column
CXTPReportColumn* pLeftColumn = NULL;
CXTPReportColumn* pRightColumn = NULL;
int nTotalColumnCount = m_pColumns->GetCount();
// find left visible column
for (int nLeftColumnIndex = nIndex - 1; nLeftColumnIndex >= 0; nLeftColumnIndex--)
{
if (nLeftColumnIndex < nTotalColumnCount)
{
pLeftColumn = m_pColumns->GetAt(nLeftColumnIndex);
if (pLeftColumn->IsVisible())
break;
pLeftColumn = NULL;
}
}
// find right visible column
for (int nRightColumnIndex = nIndex; nRightColumnIndex < nTotalColumnCount; nRightColumnIndex++)
{
pRightColumn = m_pColumns->GetAt(nRightColumnIndex);
if (pRightColumn->IsVisible())
break;
pRightColumn = NULL;
}
// compare
if ((pDraggingColumn == pLeftColumn) || (pDraggingColumn == pRightColumn))
{
DestroyDropWnd();
return -1;
}
}
pt.y = m_rcHeader.CenterPoint().y;
pt.x = m_rcHeader.left;
if (nIndex < m_pColumns->GetCount())
{
CXTPReportColumn* pColumnL = m_pColumns->GetAt(nIndex);
if (pColumnL->IsVisible())
{
pt.x = pColumnL->GetRect().left;
}
else
{
if (nIndex > 0 && m_pColumns->GetAt(nIndex-1))
{
CXTPReportColumn* pColumnR = m_pColumns->GetAt(nIndex-1);
ASSERT(pColumnR->IsVisible());
pt.x = pColumnR->GetRect().right;
}
}
}
else
{
pt.x = m_rcHeader.right;
}
if (pt.x < 0)
{
DestroyDropWnd();
return -1;
}
}
else
{
int nDraggingIndex = m_pColumns->GetGroupsOrder()->IndexOf(pDraggingColumn);
if (nDraggingIndex != -1 && (nDraggingIndex == nIndex || nDraggingIndex == nIndex - 1))
{
DestroyDropWnd();
return -1;
}
pt.x = m_rcGroupBy.left + 9;
pt.y = m_rcGroupBy.top + 6 + nHeaderHeight / 2;
int nColumnCount = m_pColumns->GetGroupsOrder()->GetCount();
int nLastColumn = min(nColumnCount, nIndex);
for (int nColumn = 0; nColumn < nLastColumn; nColumn++)
{
CXTPReportColumn* pColumn = m_pColumns->GetGroupsOrder()->GetAt(nColumn);
if (pColumn)
{
pt.x += pColumn->m_rcGroupBy.Width();
if (nColumn < nColumnCount - 1)
{
pt.x += 5;
pt.y += (nHeaderHeight - 3) / 2 ;
}
}
}
}
if (m_pDropWnd == NULL)
{
m_pDropWnd = new CXTPReportHeaderDropWnd(pPaintManager->m_clrHotDivider);
if (m_pDropWnd)
m_pDropWnd->Create(nHeaderHeight);
}
if (m_pDropWnd)
{
m_pControl->ClientToScreen(&pt);
m_pDropWnd->SetWindowPos(pt.x, pt.y);
}
return nIndex;
}
int CXTPReportHeader::GetMaxAvailWidth(CXTPReportColumn* pColumnCheck)
{
int nTotalWidth = m_pControl->m_rcHeaderArea.Width();
if (!m_bAutoColumnSizing)
return 32000;
int nWidth = 0;
for (int i = 0; i < m_pColumns->GetCount(); i++)
{
CXTPReportColumn* pColumn = m_pColumns->GetAt(i);
if (!pColumn->IsVisible())
continue;
if (nWidth > 0)
{
nWidth -= pColumn->GetMinWidth();
}
if (pColumn == pColumnCheck)
{
nWidth = nTotalWidth - pColumnCheck->GetRect().left;
}
}
return nWidth;
}
CXTPReportColumn* CXTPReportHeader::GetHotTrackingColumn() const
{
return m_pDragColumn && IsDragHeader() ? m_pDragColumn : m_pHotTrackingColumn;
}
void CXTPReportHeader::SetHotTrackingColumn(CXTPReportColumn* pColumn)
{
if (!GetPaintManager()->IsColumHotTrackingEnabled())
pColumn = NULL;
if (m_pHotTrackingColumn != pColumn)
{
m_pHotTrackingColumn = pColumn;
m_pControl->RedrawControl();
if (!CWnd::GetCapture())
{
TRACKMOUSEEVENT tme =
{
sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_pControl->GetSafeHwnd(), 0
};
_TrackMouseEvent (&tme);
}
}
}
void CXTPReportHeader::OnMouseMove(UINT /*nFlags*/, CPoint point)
{
XTPReportMouseMode mouseMode = m_pControl->GetMouseMode();
SetHotTrackingColumn(HitTest(point));
if (m_bAllowColumnResize && (mouseMode == xtpReportMouseNothing || mouseMode == xtpReportMouseOverColumnDivide)
&& MouseOverColumnResizeArea(point))
{
if (mouseMode == xtpReportMouseNothing)
SetCursor(m_hResizeCursor);
m_pControl->SetMouseMode(xtpReportMouseOverColumnDivide);
return;
}
if (mouseMode == xtpReportMousePrepareDragColumn)
{
CXTPReportColumn* pColumn = GetDraggingColumn();
if (!pColumn)
return;
if (!m_bAllowColumnReorder && (!m_bAllowColumnRemove || !pColumn->m_bAllowRemove) && !m_pControl->IsGroupByVisible())
return;
if (abs (point.x - m_ptMouse.x) + abs (point.y - m_ptMouse.y) < 4)
return;
if (!(pColumn->IsAllowDragging() && pColumn->GetIndex() >= m_pControl->GetDisableReorderColumnsCount()))
{
m_pDragColumn = NULL;
m_pControl->SetMouseMode(xtpReportMouseNothing);
m_pControl->RedrawControl();
}
else
{
m_pControl->SetMouseMode(xtpReportMouseDraggingColumn);
m_dragMode = m_bDragHeader ? dragInHeader : dragInGroupBox;
// set dragging cursor
ASSERT(m_pDragWnd == NULL);
m_pDragWnd = new CXTPReportHeaderDragWnd();
CRect rcItem(pColumn->GetRect());
if (!m_bDragHeader)
{
// set sizes as drawing external
rcItem.right = rcItem.left + pColumn->m_rcGroupBy.Width();
}
m_pControl->ClientToScreen(&rcItem);
m_pDragWnd->Create(rcItem, this, GetPaintManager(), pColumn);
return;
}
}
if (mouseMode == xtpReportMouseDraggingColumn)
{
if (!m_pDragColumn)
return;
CPoint ptScreen = point;
m_pControl->ClientToScreen(&ptScreen);
if (m_pDragWnd)
{
CRect rcWnd;
m_pDragWnd->GetWindowRect(&rcWnd);
CPoint pt(ptScreen);
pt.Offset(-(rcWnd.Width() >> 1), -(rcWnd.Height() >> 1));
m_pDragWnd->SetWindowPos(&CWnd::wndTop,
pt.x, pt.y, 0, 0,
SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
}
if (m_pSubList && m_pSubList->GetSafeHwnd() && m_pSubList->IsWindowVisible() &&
CXTPWindowRect(m_pSubList).PtInRect(ptScreen))
{
if (m_dragMode == dragFieldChooser)
return;
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
SetHotDivider(-1);
m_dragMode = dragFieldChooser;
return;
}
CXTPClientRect rcClient(m_pControl);
CRect rcDropTarget(m_rcHeader);
if (m_pDragColumn->IsGroupable())
rcDropTarget.UnionRect(m_rcHeader, m_rcGroupBy);
rcDropTarget.right = rcClient.right;
if (rcDropTarget.PtInRect(point))
{
CRect rcHeaderFull = m_rcHeader;
rcHeaderFull.right = rcClient.right;
BOOL bHeaderPoint = rcHeaderFull.PtInRect(point);
// change dropping place
int nDropPos = bHeaderPoint ? FindHeaderColumn(point) : FindGroupByColumn(point);
if (bHeaderPoint && !(m_bAllowColumnReorder && nDropPos > (m_pControl->GetDisableReorderColumnsCount() - 1))/* && m_bDragHeader*/)
nDropPos = -1;
XTP_TRACE(_T("nDropPos = %i, m_nDropIndex = %i\n"), nDropPos, m_nDropIndex);
ReportDraggingMode dragMode = bHeaderPoint ? dragInHeader : dragInGroupBox;
// dropping will change order
if ((m_dragMode & dragInTarget) == 0)
{
// Change drag mode
XTP_TRACE(_T("Switch IN\n"));
XTP_TRACE(_T("point = %d %d\t"), point.x, point.y);
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
}
// redraw control with new arrows if dropping place changed
//if (nDropPos != m_nDropIndex || m_dragMode != dragMode)
{
SetHotDivider(nDropPos, bHeaderPoint);
}
m_dragMode = dragMode;
}
else
{
// dropping will remove the column
if (m_dragMode != dragOutTarget)
{
// change drag mode
XTP_TRACE(_T("Switch OUT\n"));
XTP_TRACE(_T("point = %d %d\t"), point.x, point.y);
if (m_bAllowColumnRemove && m_pDragColumn->m_bAllowRemove)
{
SetCursor(m_hDontDropCursor);
}
SetHotDivider(-1);
m_dragMode = dragOutTarget;
}
}
return;
}
if (mouseMode != xtpReportMouseNothing)
{
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
m_pControl->SetMouseMode(xtpReportMouseNothing);
return;
}
}
void CXTPReportHeader::StartDragging(CXTPReportColumn* pColumn, BOOL bHeader)
{
ASSERT(pColumn);
m_pDragColumn = pColumn;
m_bDragHeader = bHeader;
m_bDragGroupBox = !bHeader;
m_nDropIndex = -1;
}
CXTPReportColumn* CXTPReportHeader::GetDraggingColumn() const
{
return m_pDragColumn;
}
BOOL CXTPReportHeader::SetSubListCtrl(CXTPReportSubListControl* pSubList)
{
m_pSubList = pSubList;
if (!pSubList)
return FALSE;
m_pSubList->SetReportCtrl(m_pControl);
return TRUE;
}
BOOL CXTPReportHeader::SetFilterEditCtrl(CXTPReportFilterEditControl* pFilterEdit)
{
if (!pFilterEdit)
return FALSE;
m_pFilterEdit = pFilterEdit;
m_pFilterEdit->SetReportCtrl(m_pControl);
return TRUE;
}
void CXTPReportHeader::OnContextMenu(CPoint ptClick)
{
CPoint ptClient(ptClick);
if (!m_pControl || !m_pControl->m_rcHeaderArea.PtInRect(ptClient))
return;
if (m_pControl->GetMouseMode() == xtpReportMouseNothing)
{
// mark the column as clicked at by the dragging
CXTPReportColumn* pColumn = HitTest(ptClient);
if (pColumn || s_bSendContextMenuForWholeHeaderArea)
{
m_pControl->ClientToScreen(&ptClick);
// send process notification to the user and wait for the reaction
m_pControl->SendMessageToParent(NULL, NULL, pColumn, XTP_NM_REPORT_HEADER_RCLICK, &ptClick);
m_pControl->RedrawControl();
}
}
}
void CXTPReportHeader::DrawFooter(CDC* pDC, CRect& rcFooter, int nLeftOffset)
{
UNREFERENCED_PARAMETER(nLeftOffset);
// draw background
GetPaintManager()->FillFooter(pDC, rcFooter);
// draw items
int nVisColCount = m_pColumns->GetVisibleColumnsCount();
int nFreezeCols = min(GetControl()->m_nFreezeColumnsCount, nVisColCount);
for (int nColumn = nVisColCount-1; nColumn >= 0; nColumn--)
{
BOOL bFreezeCol = nColumn < nFreezeCols;
int nColIdx = bFreezeCol ? nFreezeCols - 1 - nColumn : nColumn;
CXTPReportColumn* pColumn = m_pColumns->GetVisibleAt(nColIdx);
ASSERT(pColumn && pColumn->IsVisible());
if (pColumn)
{
CRect rcItem = pColumn->GetRect();
rcItem.top = rcFooter.top;
rcItem.bottom = rcFooter.bottom;
if (rcItem.Height() > 0)
{
if (bFreezeCol)
{
GetPaintManager()->FillFooter(pDC, rcItem);
}
GetPaintManager()->DrawColumnFooter(pDC, pColumn, this, rcItem);
}
}
}
}
void CXTPReportHeader::DrawGroupByControl(CDC* pDC, CRect& rcGroupBy)
{
m_rcGroupBy = rcGroupBy;
if (rcGroupBy.Height() <= 0)
return;
CXTPReportPaintManager* pPaintManager = GetPaintManager();
pPaintManager->FillGroupByControl(pDC, rcGroupBy);
CXTPFontDC font(pDC, &pPaintManager->m_fontCaption);
int x = m_rcGroupBy.left + 9;
int y = m_rcGroupBy.top + 7;
int nHeaderHeight = pPaintManager->GetHeaderHeight();
// draw items
int nColumnsCount = m_pColumns->GetGroupsOrder()->GetCount();
for (int nColumn = 0; nColumn < nColumnsCount; nColumn++)
{
CXTPReportColumn* pColumn = m_pColumns->GetGroupsOrder()->GetAt(nColumn);
if (pColumn /*&& pColumn->IsVisible()*/)
{
CRect rcItem(x, y, x + pColumn->GetCaptionWidth(pDC) + 50, y + nHeaderHeight - 3);
pColumn->m_rcGroupBy = rcItem;
// draw background
GetPaintManager()->FillHeaderControl(pDC, rcItem);
// draw column
GetPaintManager()->DrawColumn(pDC, pColumn, this, rcItem, TRUE);
// next column
x = rcItem.right + 5;
y = rcItem.top + rcItem.Height() / 2;
// draw connector
if (nColumn < nColumnsCount - 1)
GetPaintManager()->DrawConnector(pDC, CPoint(rcItem.right - 5, rcItem.bottom), CPoint(x, rcItem.bottom + 4));
}
}
// draw default dragging text if no items there
if (nColumnsCount == 0)
{
CRect rcItem(x, y, x, y + nHeaderHeight - 3);
GetPaintManager()->DrawNoGroupByText(pDC, rcItem);
}
}
int CXTPReportHeader::GetGroupByHeight() const
{
CXTPReportPaintManager* pPaintManager = GetPaintManager();
int nColumnsCount = m_pColumns->GetGroupsOrder()->GetCount();
int nHeaderHeight = pPaintManager->GetHeaderHeight();
int nHeight = 8 + ((nHeaderHeight - 3) / 2) * (nColumnsCount + 1) + 7;
if (!nColumnsCount)
nHeight += (nHeaderHeight - 3) / 2;
return nHeight;
}
void CXTPReportHeader::BestFit(CXTPReportColumn* pColumn)
{
if (pColumn->IsResizable() && m_bAllowColumnResize)
if (!m_bAutoColumnSizing || (!IsLastResizebleColumn(pColumn) && !IsLastVisibleColumn(pColumn)))
{
int nMaxAvailWidth = GetMaxAvailWidth(pColumn);
int nMinWidth = pColumn->GetMinWidth();
int nMaxItemWidth = min(pColumn->GetBestFitWidth(), nMaxAvailWidth);
if (nMaxItemWidth > nMinWidth)
{
ResizeColumn(pColumn, nMaxItemWidth);
m_pControl->RedrawControl();
}
}
}
BOOL CXTPReportHeader::IsLastVisibleColumn(CXTPReportColumn* pColumn) const
{
int nColumnCount = m_pColumns->GetCount();
for (int nColumn = m_pColumns->IndexOf(pColumn) + 1; nColumn < nColumnCount; nColumn++)
{
CXTPReportColumn* pCol = m_pColumns->GetAt(nColumn);
if (pCol && pCol->IsVisible())
return FALSE;
}
return TRUE;
}
BOOL CXTPReportHeader::IsLastResizebleColumn(CXTPReportColumn* pColumn) const
{
int nColumnCount = m_pColumns->GetCount();
for (int nColumn = m_pColumns->IndexOf(pColumn) + 1; nColumn < nColumnCount; nColumn++)
{
CXTPReportColumn* pCol = m_pColumns->GetAt(nColumn);
if (pCol && pCol->IsVisible() && pCol->IsResizable())
return FALSE;
}
return TRUE;
}
void CXTPReportHeader::ShowItemsInGroups(BOOL bShowInGroups)
{
m_bShowItemsInGroups = bShowInGroups;
if (m_bShowItemsInGroups)
{
m_pColumns->GetGroupsOrder()->Clear();
if (m_pColumns->GetSortOrder()->GetCount() > 0)
{
m_pColumns->GetGroupsOrder()->Add(m_pColumns->GetSortOrder()->GetAt(0));
m_pColumns->GetSortOrder()->Clear();
}
m_pControl->Populate();
OnColumnsChanged(TRUE);
}
}
CXTPReportColumn* CXTPReportHeader::GetNextVisibleColumn(int nIndex, int nDirection)
{
if (nDirection == 1)
{
int nColumnCount = m_pColumns->GetCount();
for (int nColumn = nIndex + 1; nColumn < nColumnCount; nColumn++)
{
CXTPReportColumn* pCol = m_pColumns->GetAt(nColumn);
if (pCol && pCol->IsVisible())
return pCol;
}
}
if (nDirection == -1)
{
for (int nColumn = nIndex - 1; nColumn >= 0; nColumn--)
{
CXTPReportColumn* pCol = m_pColumns->GetAt(nColumn);
if (pCol && pCol->IsVisible())
return pCol;
}
}
return NULL;
}
INT_PTR CXTPReportHeader::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
{
CXTPReportColumn* pColumn = HitTest(point);
if (!pColumn)
return -1;
INT_PTR nHit = (INT_PTR)pColumn;
CString strTip = pColumn->GetTooltip();
if (strTip.IsEmpty())
{
CXTPReportPaintManager* pPaintManager = GetPaintManager();
strTip = pColumn->GetCaption();
if (pColumn->IsSortable() && m_bAllowColumnSort)
{
strTip = pPaintManager->m_strSortBy + strTip;
}
}
if (strTip.GetLength() == 0)
return -1;
CXTPToolTipContext::FillInToolInfo(pTI, m_pControl->m_hWnd, pColumn->GetRect(),
nHit, strTip);
return nHit;
}
void CXTPReportHeader::DoPropExchange(CXTPPropExchange* pPX)
{
PX_Bool(pPX, _T("AllowColumnRemove"), m_bAllowColumnRemove, TRUE);
PX_Bool(pPX, _T("AllowColumnResize"), m_bAllowColumnResize, TRUE);
PX_Bool(pPX, _T("AllowColumnReorder"), m_bAllowColumnReorder, TRUE);
PX_Bool(pPX, _T("AllowColumnSort"), m_bAllowColumnSort, TRUE);
PX_Bool(pPX, _T("AutoColumnSizing"), m_bAutoColumnSizing, TRUE);
PX_Bool(pPX, _T("ShowItemsInGroups"), m_bShowItemsInGroups, s_bShowItemsInGroupsPXDefault);
}