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.
2064 lines
51 KiB
C++
2064 lines
51 KiB
C++
// XTPReportHeader.cpp : implementation of the CXTPReportHeader 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 "Resource.h"
|
|
#include "Common/Resource.h"
|
|
|
|
#include "Common/XTPDrawHelpers.h"
|
|
#include "Common/XTPPropExchange.h"
|
|
#include "Common/XTPToolTipContext.h"
|
|
#include "Common/XTPResourceManager.h"
|
|
#include "Common/XTPSystemHelpers.h"
|
|
#include "Common/XTPCustomHeap.h"
|
|
#include "Common/XTPSmartPtrInternalT.h"
|
|
#include "Common/XTPColorManager.h"
|
|
|
|
#include "XTPReportDefines.h"
|
|
#include "XTPReportColumn.h"
|
|
#include "XTPReportColumns.h"
|
|
#include "XTPReportControl.h"
|
|
#include "XTPReportPaintManager.h"
|
|
#include "XTPReportSubListControl.h"
|
|
#include "XTPReportFilterEditControl.h"
|
|
#include "XTPReportDragDrop.h"
|
|
#include "XTPReportHeader.h"
|
|
#include "XTPReportRow.h"
|
|
#include "XTPReportRows.h"
|
|
#include "XTPReportSelectedRows.h"
|
|
#include "XTPReportRecord.h"
|
|
#include "XTPReportRecords.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_nVisIndex = -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_bHideColumnAfterGroupBoxDrop = TRUE;
|
|
m_nForceLayoutAdjustment = 0;
|
|
|
|
m_bLastColumnExpand = FALSE;
|
|
m_bLastColumnExpandKeep = FALSE;
|
|
|
|
// Release 13.1
|
|
m_pDragColumn = NULL;
|
|
m_pResizeColumn = 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;
|
|
|
|
m_nMaxColumnWidth = 0;
|
|
|
|
EnableAutomation();
|
|
}
|
|
|
|
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 HeaderWidth = rcHeader.Width();
|
|
int HeaderHeight = rcHeader.Height();
|
|
int nFreezeCols = GetControl()->GetFreezeColumnsCount();
|
|
|
|
rcHeader.OffsetRect(-nLeftOffset, 0);
|
|
m_rcHeader = rcHeader;
|
|
|
|
// draw background
|
|
CXTPClientRect rcHeaderClientArea(m_pControl);
|
|
rcHeaderClientArea.top = rcHeader.top;
|
|
rcHeaderClientArea.bottom = rcHeader.bottom;
|
|
|
|
if (!m_pControl->IsHeaderVisible() && m_pControl->IsGroupByVisible())
|
|
{
|
|
rcHeaderClientArea.top--; //fix for Office2003 - Office2007 Column Style
|
|
}
|
|
|
|
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 (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 (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);
|
|
}
|
|
|
|
if (GetPaintManager()->IsColumnWidthWYSIWYG() && !pDC->IsPrinting() && GetPaintManager()->IsShowWYSIWYGMarkers())
|
|
{
|
|
int PageWidth = GetPaintManager()->GetPrintPageWidth();
|
|
|
|
if (PageWidth > 0 && PageWidth <= HeaderWidth && HeaderWidth > 1)
|
|
{
|
|
for (int st = 1; st <= HeaderWidth / PageWidth; st++)
|
|
{
|
|
CRect rc;
|
|
if (m_bShowItemsInGroups || GetControl()->IsGroupByVisible())
|
|
rc = CRect(PageWidth * st, HeaderHeight, PageWidth * st + 2, 3 * HeaderHeight);//group row mode
|
|
else
|
|
rc = CRect(PageWidth * st, 0, PageWidth * st + 2, HeaderHeight); //non-group row mode
|
|
pDC->Draw3dRect(rc, RGB(255,0,0), RGB(255,0,0));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CXTPReportHeader::CancelMouseMode()
|
|
{
|
|
if (m_pControl->GetMouseMode() != xtpReportMouseNothing)
|
|
{
|
|
m_pControl->SetMouseMode(xtpReportMouseNothing);
|
|
|
|
m_pDragColumn = NULL;
|
|
m_pResizeColumn = 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_pControl->m_nScrollOffsetH = 0;
|
|
m_bAutoColumnSizing = bAutoColumnSizing;
|
|
|
|
if (bAutoColumnSizing && m_pControl->m_hWnd)
|
|
m_pControl->EnableScrollBarCtrl(SB_HORZ, FALSE);
|
|
|
|
AdjustColumnsWidth(m_pControl->m_rcHeaderArea.Width());
|
|
m_pControl->RedrawControl();
|
|
}
|
|
|
|
void CXTPReportHeader::OnColumnsChanged(int nReason, CXTPReportColumn* pColumn)
|
|
{
|
|
if (m_pControl->IsFullColumnScrolling()
|
|
&& pColumn
|
|
&& m_pControl->GetScrollPos(SB_HORZ) > (pColumn->IsVisible() ? pColumn->GetVisibleIndex() : pColumn->GetOldVisibleIndex()))
|
|
{
|
|
if (nReason & xtpReportColumnShown)
|
|
m_rcHeader.left -= pColumn->GetWidth();
|
|
else if (nReason & xtpReportColumnHidden)
|
|
m_rcHeader.left += pColumn->GetWidth();
|
|
AdjustColumnsWidth(m_pControl->m_rcHeaderArea.Width());
|
|
m_pControl->OnHScroll(SB_THUMBTRACK, m_pControl->GetScrollPos(SB_HORZ), NULL);
|
|
}
|
|
else
|
|
{
|
|
AdjustColumnsWidth(m_pControl->m_rcHeaderArea.Width());
|
|
//if (!GetPaintManager()->IsFixedRowHeight())
|
|
// m_pControl->AdjustScrollBars();
|
|
}
|
|
m_pControl->UpdateSubList();
|
|
m_pControl->RedrawControl();
|
|
|
|
XTP_NM_REPORTCOLUMNORDERCHANGED nmData;
|
|
nmData.pColumn = pColumn;
|
|
nmData.nReason = nReason;
|
|
|
|
if (nReason & xtpReportColumnGroupOrderChanged)
|
|
m_pControl->SendNotifyMessage(XTP_NM_REPORT_GROUPORDERCHANGED, (NMHDR*) &nmData);
|
|
m_pControl->SendNotifyMessage(XTP_NM_REPORT_COLUMNORDERCHANGED, (NMHDR*) &nmData);
|
|
}
|
|
|
|
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);
|
|
|
|
if (m_nMaxColumnWidth > 0)
|
|
{
|
|
if (pColumn != m_pColumns->GetLastVisibleColumn())
|
|
nMaxAvailWidth = min(nMaxAvailWidth, m_nMaxColumnWidth);
|
|
}
|
|
|
|
// uncomment this line in condition if you need set
|
|
// maximum width constraint dependence on column
|
|
// autosize option, then client code must be following:
|
|
//
|
|
// m_wndReportCtrl.GetColumns()->GetAt(0)->SetAutoSize(FALSE); // first need cancel column autosize
|
|
// m_wndReportCtrl.GetColumns()->GetAt(0)->SetMaxWidth(100); // and then set maximum width
|
|
|
|
if (pColumn->GetMaxWidth()/* > 0 && !pColumn->IsAutoSize()*/)
|
|
nMaxAvailWidth = pColumn->GetMaxWidth();
|
|
|
|
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, m_pControl->m_bDesktopTrackerMode);
|
|
|
|
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 (nTotalWidth == 0)
|
|
return;
|
|
|
|
if (m_bAutoColumnSizing)
|
|
{
|
|
int nColumnsWidth = 0;
|
|
int nTotalColumnsWidth = 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();
|
|
nTotalColumnsWidth += pColumn->GetWidth();
|
|
}
|
|
}
|
|
|
|
if (pLastAutoColumn && nTotalWidth > 0)
|
|
{
|
|
m_nForceLayoutAdjustment = 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();
|
|
|
|
CXTPReportColumn* p_Column = NULL;
|
|
int TotalMinWidth = 0;
|
|
for (int nCol = nFirstIndex; nCol < m_pColumns->GetCount(); nCol++)
|
|
{
|
|
CXTPReportColumn* pColumn = m_pColumns->GetAt(nCol);
|
|
if (pColumn)
|
|
{
|
|
if (!pColumn->IsVisible())
|
|
continue;
|
|
p_Column = pColumn;
|
|
|
|
if (!m_pControl->m_bIconColumnIndexNotValid)
|
|
TotalMinWidth += pColumn->GetWidth();
|
|
}
|
|
}
|
|
m_nForceLayoutAdjustment = max(TotalMinWidth - m_nHeaderWidth, 0);
|
|
|
|
if (TotalMinWidth > m_nHeaderWidth)
|
|
m_nHeaderWidth = TotalMinWidth;
|
|
}
|
|
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();
|
|
}
|
|
|
|
void CXTPReportHeader::ResizeColumn(CXTPReportColumn* pColumnResize, int nWidth)
|
|
{
|
|
int nResizeIndex = 0;
|
|
int nColumn;
|
|
int nTotalWidth = 0;
|
|
m_pResizeColumn = pColumnResize;
|
|
|
|
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
|
|
// if special flag m_pControl->GetPaintManager()->IsLastColumnWidthWYSIWYG() not used.
|
|
CXTPReportColumn* pColNext = CXTPReportHeader::GetNextVisibleColumn(nColumn, 1);
|
|
|
|
if (pColNext && !pColNext->IsAutoSize()
|
|
&& !m_pControl->GetPaintManager()->IsLastColumnWidthWYSIWYG()
|
|
&& 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());
|
|
|
|
m_pControl->AdjustScrollBars();
|
|
|
|
m_pResizeColumn = NULL;
|
|
}
|
|
|
|
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
|
|
BOOL bFCS = m_pControl->IsFullColumnScrolling(); //<<>>
|
|
//if (pDragColumn->GetIndex() > 0)
|
|
if (pDragColumn->GetVisibleIndex() > 0)
|
|
m_pControl->SetFullColumnScrolling(FALSE);
|
|
|
|
m_pColumns->GetGroupsOrder()->InsertAt(m_nDropIndex, pDragColumn);
|
|
bGroupOrderChanged = TRUE;
|
|
|
|
if ((m_bHideColumnAfterGroupBoxDrop && m_bDragHeader && ((nFlags & MK_CONTROL) == 0)) ||
|
|
(!m_bHideColumnAfterGroupBoxDrop && m_bDragHeader && ((nFlags & MK_CONTROL) == MK_CONTROL)))
|
|
{
|
|
pDragColumn->SetVisible(FALSE);
|
|
}
|
|
m_pControl->Populate();
|
|
|
|
m_pControl->SetFullColumnScrolling(bFCS); //<<>>
|
|
}
|
|
}
|
|
int nReason = bGroupOrderChanged ? xtpReportColumnGroupOrderChanged : xtpReportColumnOrderChanged;
|
|
if (m_dragMode == dragFieldChooser)
|
|
nReason |= xtpReportColumnAddedToFieldChooser;
|
|
else if (m_dragMode == dragInHeader && !m_bDragHeader)
|
|
nReason |= xtpReportColumnRemovedFromFieldChooser;
|
|
if (bGroupOrderChanged && m_bDragGroupBox)
|
|
nReason |= xtpReportColumnRemovedFromGroupby;
|
|
else if (bGroupOrderChanged && m_dragMode == dragInGroupBox)
|
|
nReason |= xtpReportColumnAddedToGroupby;
|
|
m_dragMode = dragNothing;
|
|
OnColumnsChanged(nReason, pDragColumn);
|
|
|
|
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))
|
|
{
|
|
if (m_pDragColumn->IsPlusMinus())
|
|
{
|
|
CXTPReportColumns* pColumns = m_pControl->GetColumns();
|
|
CRect rcPlusMinus = m_pDragColumn->GetRect();
|
|
BOOL bAction = (rcPlusMinus.right - ptClick.x <= 15); //click on Plus-Minus glyph only [13 + 2 pixels]
|
|
if (bAction && pColumns != NULL)
|
|
{
|
|
BOOL bExp = m_pDragColumn->IsExpanded();
|
|
m_pDragColumn->SetExpanded(!bExp);
|
|
|
|
m_bDragHeader = FALSE;
|
|
m_dragMode = dragNothing;
|
|
|
|
m_pControl->SendMessageToParent(NULL, NULL, m_pDragColumn, XTP_NM_REPORT_PLUSMINUSCLICK, &ptClick);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
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;
|
|
}
|
|
|
|
CUIntArray m_arPreSel;
|
|
if (m_pControl->m_bKeepSelectionAfterSort)
|
|
{
|
|
CXTPReportSelectedRows* pSelectedRows = m_pControl->GetSelectedRows();
|
|
if (pSelectedRows)
|
|
{
|
|
int n = pSelectedRows->GetCount();
|
|
for (int i = 0; i < n; i++)
|
|
{
|
|
CXTPReportRow* pRow = pSelectedRows->GetAt(i);
|
|
if (pRow)
|
|
{
|
|
CXTPReportRecord* pRec = pRow->GetRecord();
|
|
if (pRec)
|
|
m_arPreSel.Add(pRec->GetIndex());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_pControl->SendNotifyMessage(XTP_NM_REPORT_PRESORTORDERCHANGED);
|
|
|
|
if (bGroupOrderChanged)
|
|
m_pControl->Populate();
|
|
else
|
|
m_pControl->ReSortRows();
|
|
|
|
if (m_pControl->m_bKeepSelectionAfterSort)
|
|
{
|
|
CXTPReportRows* pRows = m_pControl->GetRows();
|
|
CXTPReportRecords* pRecords = m_pControl->GetRecords();
|
|
if (m_arPreSel.GetSize() > 0)
|
|
{
|
|
for (int i = 0; i < m_arPreSel.GetSize(); i++)
|
|
{
|
|
int j = m_arPreSel.GetAt(i);
|
|
CXTPReportRecord* pRec = pRecords->GetAt(j);
|
|
if (pRec)
|
|
{
|
|
CXTPReportRow* pRow = pRows->FindInTree(pRec);
|
|
if (pRow)
|
|
pRow->SetSelected(TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_pControl->SendNotifyMessage(XTP_NM_REPORT_SORTORDERCHANGED);
|
|
|
|
if (bGroupOrderChanged)
|
|
{
|
|
OnColumnsChanged(xtpReportColumnGroupOrderChanged | xtpReportColumnAddedToGroupby | xtpReportColumnRemovedFromGroupby, pColumn);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
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()->GetFreezeColumnsCount();
|
|
|
|
// 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;
|
|
}
|
|
|
|
//NEED TO REVIEW THIS CODE
|
|
int CXTPReportHeader::GetFullColScrollInfo(
|
|
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()->GetFreezeColumnsCount();
|
|
|
|
// 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()->GetFreezeColumnsCount(), 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()->GetFreezeColumnsCount(), 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_nScrollOffsetH != 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(m_pControl, 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();
|
|
|
|
CXTPReportColumn* pCol = HitTest(point);
|
|
|
|
SetHotTrackingColumn(pCol);
|
|
|
|
if (pCol != NULL && pCol->IsPlusMinus())
|
|
{
|
|
CRect rcPlusMinus = pCol->GetRect();
|
|
if (rcPlusMinus.right - point.x <= 20 && rcPlusMinus.right - point.x > 15)
|
|
{
|
|
CXTPToolTipContext* pTipContext = m_pControl->GetToolTipContext();
|
|
if (pTipContext)
|
|
pTipContext->CancelToolTips();
|
|
}
|
|
}
|
|
|
|
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);
|
|
m_nVisIndex = pColumn->GetVisibleIndex();
|
|
// Release 13.1
|
|
//TRACE(_T("OnMouseMove m_nVisIndex=%d\n"), m_nVisIndex);
|
|
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 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 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;
|
|
}
|
|
|
|
CXTPReportColumn* CXTPReportHeader::GetResizingColumn() const
|
|
{
|
|
return m_pResizeColumn;
|
|
}
|
|
|
|
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()->GetFreezeColumnsCount(), 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* pPM = GetPaintManager();
|
|
if (pPM == NULL) return;
|
|
|
|
pPM->FillGroupByControl(pDC, rcGroupBy);
|
|
|
|
CXTPFontDC font(pDC, &pPM->m_fontCaption);
|
|
|
|
int x = m_rcGroupBy.left + 9;
|
|
int y = m_rcGroupBy.top + 7;
|
|
|
|
int nHeaderHeight = pPM->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
|
|
pPM->FillHeaderControl(pDC, rcItem);
|
|
// draw column
|
|
pPM->DrawColumn(pDC, pColumn, this, rcItem, TRUE);
|
|
// next column
|
|
x = rcItem.right + 5;
|
|
y = rcItem.top + rcItem.Height() / 2;
|
|
// draw connector
|
|
if (nColumn < nColumnsCount - 1)
|
|
pPM->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 - 4);
|
|
pPM->DrawNoGroupByText(pDC, rcItem);
|
|
}
|
|
}
|
|
|
|
int CXTPReportHeader::GetGroupByHeight() const
|
|
{
|
|
CXTPReportPaintManager* pPaintManager = GetPaintManager();
|
|
|
|
int nColumnsCount = m_pColumns->GetGroupsOrder()->GetCount();
|
|
int nHeaderHeight = pPaintManager->GetHeaderHeight();
|
|
int nHeight = 15 + ((nHeaderHeight - 3) / 2) * (nColumnsCount + 1);
|
|
if (nColumnsCount == 0)
|
|
nHeight += (nHeaderHeight - 3) / 2;
|
|
return nHeight;
|
|
}
|
|
|
|
void CXTPReportHeader::BestFit(CXTPReportColumn* pColumn)
|
|
{
|
|
if (pColumn->IsResizable() && m_bAllowColumnResize)
|
|
{
|
|
if (!m_bAutoColumnSizing
|
|
|| (!GetControl()->m_bStrictBestFit && !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)
|
|
{
|
|
if (m_bShowItemsInGroups == bShowInGroups)
|
|
return;
|
|
|
|
m_bShowItemsInGroups = bShowInGroups;
|
|
|
|
if (m_bShowItemsInGroups)
|
|
{
|
|
int nColumnCount = m_pColumns->GetGroupsOrder()->GetCount();
|
|
|
|
for (int nColumn = 0; nColumn < nColumnCount; nColumn++)
|
|
{
|
|
CXTPReportColumn* pCol = m_pColumns->GetGroupsOrder()->GetAt(nColumn);
|
|
|
|
if (pCol && !pCol->IsVisible())
|
|
pCol->SetVisible(TRUE);
|
|
}
|
|
|
|
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(xtpReportColumnGroupOrderChanged, NULL);
|
|
}
|
|
}
|
|
|
|
CXTPReportColumn* CXTPReportHeader::GetNextVisibleColumn(int nIndex, int nDirection)
|
|
{
|
|
if (xtpReportColumnDirectionRight == nDirection)
|
|
{
|
|
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 (xtpReportColumnDirectionLeft == nDirection)
|
|
{
|
|
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();
|
|
CXTPReportPaintManager* pPaintManager = GetPaintManager();
|
|
|
|
if (strTip.IsEmpty())
|
|
{
|
|
strTip = pColumn->GetCaption();
|
|
|
|
if (pColumn->IsSortable() && m_bAllowColumnSort && pPaintManager != NULL)
|
|
{
|
|
if (m_pControl->m_iIconViewColumn > -1
|
|
&& pColumn->GetColumns()->Find(m_pControl->m_iIconViewColumn) == pColumn)
|
|
{
|
|
if (pPaintManager->m_bRecOrRowNum)// flag for Record (TRUE) or Row (FALSE) number
|
|
strTip = _T("Rec") + strTip;
|
|
else
|
|
strTip = _T("Row") + strTip;
|
|
}
|
|
else
|
|
{
|
|
if (pColumn->HasSortTriangle())
|
|
{
|
|
strTip = pPaintManager->m_strSortBy + strTip;
|
|
if (pColumn->IsSortedDecreasing())
|
|
strTip += pPaintManager->m_strDecreasing;
|
|
else
|
|
strTip += pPaintManager->m_strIncreasing;
|
|
}
|
|
}
|
|
}
|
|
if (pColumn->GetMarkupUIElement())
|
|
return -1;
|
|
}
|
|
BOOL bAction(FALSE);
|
|
if (pColumn->IsPlusMinus())
|
|
{
|
|
CRect rcPlusMinus = pColumn->GetRect();
|
|
bAction = (rcPlusMinus.right - point.x <= 15); //click on Plus-Minus glyph only [13 + 2 pixels]
|
|
}
|
|
if (bAction && pPaintManager != NULL)
|
|
{
|
|
if (pColumn->IsExpanded())
|
|
strTip.Format(_T("%s"), pPaintManager->m_strExpand);
|
|
else
|
|
strTip.Format(_T("%s"), pPaintManager->m_strCollapse);
|
|
}
|
|
|
|
if (strTip.GetLength() == 0)
|
|
return -1;
|
|
|
|
if (pPaintManager != NULL && pPaintManager->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, pColumn->GetRect(), nHit, strTip);
|
|
return nHit;
|
|
}
|
|
|
|
void CXTPReportHeader::SetLastColumnExpand(BOOL bLastColumnExpand, BOOL bLastColumnExpandKeep)
|
|
{
|
|
if (m_pColumns != NULL &&
|
|
m_pColumns->GetLastVisibleColumn() != NULL)
|
|
{
|
|
SetAutoColumnSizing(FALSE);
|
|
|
|
m_bLastColumnExpand = bLastColumnExpand;
|
|
m_bLastColumnExpandKeep = bLastColumnExpandKeep;
|
|
if (bLastColumnExpand)
|
|
{
|
|
int nColumnsCount = m_pColumns->GetCount(), nColumn;
|
|
for (nColumn = 0; nColumn < nColumnsCount; nColumn++)
|
|
{
|
|
CXTPReportColumn* pColumn = m_pColumns->GetAt(nColumn);
|
|
if (pColumn && pColumn->IsVisible())
|
|
{
|
|
pColumn->SetAutoSize(FALSE);
|
|
}
|
|
}
|
|
m_pColumns->GetLastVisibleColumn()->SetAutoSize(TRUE);
|
|
}
|
|
|
|
SetAutoColumnSizing(TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
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);
|
|
}
|
|
|
|
BEGIN_INTERFACE_MAP(CXTPReportHeader, CCmdTarget)
|
|
INTERFACE_PART(CXTPReportHeader, IID_IAccessible, ExternalAccessible)
|
|
END_INTERFACE_MAP()
|
|
|
|
CCmdTarget* CXTPReportHeader::GetAccessible()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
HRESULT CXTPReportHeader::GetAccessibleParent(IDispatch* FAR* ppdispParent)
|
|
{
|
|
SAFE_MANAGE_STATE(m_pModuleState);
|
|
|
|
*ppdispParent = m_pControl->GetIDispatch(TRUE);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CXTPReportHeader::GetAccessibleChildCount(long FAR* pChildCount)
|
|
{
|
|
if (pChildCount == 0)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*pChildCount = m_pColumns->GetCount();
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CXTPReportHeader::GetAccessibleChild(VARIANT varChild, IDispatch* FAR* ppdispChild)
|
|
{
|
|
*ppdispChild = NULL;
|
|
int nChild = GetChildIndex(&varChild);
|
|
|
|
if (nChild <= 0)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*ppdispChild = NULL;
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT CXTPReportHeader::GetAccessibleName(VARIANT varChild, BSTR* pszName)
|
|
{
|
|
int nIndex = GetChildIndex(&varChild);
|
|
|
|
if (nIndex == CHILDID_SELF)
|
|
{
|
|
CString strCaption = _T("Report Header");
|
|
*pszName = strCaption.AllocSysString();
|
|
return S_OK;
|
|
}
|
|
|
|
CXTPReportColumn* pColumn = m_pColumns->GetAt(nIndex - 1);
|
|
if (!pColumn)
|
|
return E_INVALIDARG;
|
|
|
|
CString strCaption = pColumn->GetCaption();
|
|
*pszName = strCaption.AllocSysString();
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CXTPReportHeader::GetAccessibleRole(VARIANT /*varChild*/, VARIANT* pvarRole)
|
|
{
|
|
pvarRole->vt = VT_I4;
|
|
pvarRole->lVal = ROLE_SYSTEM_COLUMNHEADER;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CXTPReportHeader::GetAccessibleState(VARIANT varChild, VARIANT* pvarState)
|
|
{
|
|
pvarState->vt = VT_I4;
|
|
pvarState->lVal = 0;
|
|
int nChild = GetChildIndex(&varChild);
|
|
|
|
if (nChild == CHILDID_SELF)
|
|
{
|
|
pvarState->lVal = 0;
|
|
}
|
|
else
|
|
{
|
|
CXTPReportColumn* pColumn = m_pColumns->GetAt(nChild - 1);
|
|
if (pColumn)
|
|
{
|
|
if (!pColumn->IsVisible())
|
|
pvarState->lVal |= STATE_SYSTEM_INVISIBLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CXTPReportHeader::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 = m_pControl->m_rcHeaderArea;
|
|
m_pControl->ClientToScreen(&rc);
|
|
}
|
|
else
|
|
{
|
|
CXTPReportColumn* pColumn = m_pColumns->GetAt(nChild - 1);
|
|
if (pColumn)
|
|
{
|
|
rc = pColumn->GetRect();
|
|
m_pControl->ClientToScreen(&rc);
|
|
}
|
|
}
|
|
|
|
*pxLeft = rc.left;
|
|
*pyTop = rc.top;
|
|
*pcxWidth = rc.Width();
|
|
*pcyHeight = rc.Height();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CXTPReportHeader::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 (!m_pControl->m_rcHeaderArea.PtInRect(pt))
|
|
return S_FALSE;
|
|
|
|
|
|
CXTPReportColumn* pColumn = HitTest(pt);
|
|
if (pColumn)
|
|
{
|
|
pvarID->lVal = pColumn->GetIndex() + 1;
|
|
return S_OK;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|