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.

549 lines
13 KiB
C++

// XTPReportSubListControl.cpp : implementation of the CXTPReportSubListControl class.
//
// This file is a part of the XTREME REPORTCONTROL MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Common/XTPDrawHelpers.h"
#include "Common/XTPMarkupRender.h"
#include "Common/XTPCustomHeap.h"
#include "Common/XTPSystemHelpers.h"
#include "Common/XTPSmartPtrInternalT.h"
#include "Common/XTPColorManager.h"
#include "XTPReportDefines.h"
#include "XTPReportControl.h"
#include "XTPReportColumn.h"
#include "XTPReportColumns.h"
#include "XTPReportDragDrop.h"
#include "XTPReportSubListControl.h"
#include "XTPReportHeader.h"
#include "XTPReportPaintManager.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CXTPReportSubListControl, CListBox)
/////////////////////////////////////////////////////////////////////////////
// CXTPReportSubListControl
CXTPReportSubListControl::CXTPReportSubListControl()
{
m_pReportCtrl = NULL;
m_pDragWnd = NULL;
m_bSortAscending = FALSE;
m_nDropIndex = 0;
}
CXTPReportSubListControl::~CXTPReportSubListControl()
{
}
BEGIN_MESSAGE_MAP(CXTPReportSubListControl, CListBox)
//{{AFX_MSG_MAP(CXTPReportSubListControl)
ON_WM_ERASEBKGND()
ON_WM_LBUTTONDOWN()
ON_WM_PAINT()
ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CXTPReportSubListControl attributes
BOOL CXTPReportSubListControl::SetReportCtrl(CXTPReportControl* pReportCtrl)
{
if (pReportCtrl == NULL)
return FALSE;
ASSERT_KINDOF(CXTPReportControl, pReportCtrl);
if (m_pReportCtrl != pReportCtrl)
{
ResetContent();
m_pReportCtrl = pReportCtrl;
}
UpdateList();
return TRUE;
}
CXTPReportControl* CXTPReportSubListControl::GetReportCtrl()
{
return m_pReportCtrl;
}
/////////////////////////////////////////////////////////////////////////////
// CXTPReportSubListControl operations
void CXTPReportSubListControl::SortAscending(BOOL bSort)
{
m_bSortAscending = bSort;
if (GetSafeHwnd()) ResetContent();
UpdateList();
}
BOOL CXTPReportSubListControl::UpdateList()
{
if (m_pReportCtrl == NULL)
return FALSE;
if (GetSafeHwnd() == NULL)
return FALSE;
CClientDC dc(this);
CXTPFontDC fnt(&dc, &m_pReportCtrl->GetPaintManager()->m_fontCaption);
int nHeight = dc.GetTextExtent(_T(" "), 1).cy + 5;
if (GetItemHeight(0) != nHeight) SetItemHeight(0, nHeight);
CXTPReportColumns* pColumns = m_pReportCtrl->GetColumns();
int nColumnCount = pColumns->GetCount();
BOOL bChanged = FALSE;
// delete all visible items from the list
for (int i = GetCount() - 1; i >= 0; i--)
{
int nItemIndex = (int)GetItemData(i);
CXTPReportColumn* pColumn = pColumns->Find(nItemIndex);
if (!pColumn || pColumn->IsVisible() || !pColumn->IsShowInFieldChooser())
{
DeleteString(i);
bChanged = TRUE;
}
}
// add the rest of invisible items
for (int nColumn = 0; nColumn < nColumnCount; nColumn++)
{
CXTPReportColumn* pColumn = pColumns->GetAt(nColumn);
if (pColumn && !pColumn->IsVisible() && pColumn->IsShowInFieldChooser()
&& (m_pReportCtrl->m_iIconViewColumn == -1 ? TRUE : (pColumn->GetItemIndex() != m_pReportCtrl->m_iIconViewColumn ? TRUE : FALSE)))
{
int nListItem = FindItemData(pColumn->GetItemIndex());
if (nListItem < 0)
{
int nItem = -1;
if (m_bSortAscending)
{
for (nItem = 0; nItem < GetCount(); nItem++)
{
CString str = GetItemCaption(nItem);
if (str > pColumn->GetCaption())
break;
}
nItem = InsertString(nItem, pColumn->GetCaption());
}
else
{
nItem = AddString(pColumn->GetCaption());
}
if (nItem >= 0)
{
SetItemData(nItem, pColumn->GetItemIndex());
bChanged = TRUE;
}
}
}
}
EnableWindow(GetCount() > 0);
if (bChanged)
Invalidate();
return TRUE;
}
CXTPReportColumn* CXTPReportSubListControl::GetItemColumn(int nIndex)
{
if (!m_pReportCtrl || GetSafeHwnd() == 0)
return NULL;
int nItemData = (int)GetItemData(nIndex);
if (nItemData == -1)
return NULL;
CXTPReportColumn* pColumn = m_pReportCtrl->GetColumns()->Find(nItemData);
return pColumn;
}
CString CXTPReportSubListControl::GetItemCaption(int nIndex)
{
if (!m_pReportCtrl || GetSafeHwnd() == 0)
return _T("");
if (GetStyle() & LBS_HASSTRINGS)
{
CString str;
GetText(nIndex, str);
return str;
}
CXTPReportColumn* pColumn = GetItemColumn(nIndex);
if (pColumn == NULL)
return _T("");
return pColumn->GetCaption();
}
int CXTPReportSubListControl::FindItemData(int nItemData)
{
for (int i = GetCount() - 1; i >= 0; i--)
{
int nItemIndex = (int)GetItemData(i);
if (nItemData == nItemIndex)
return i;
}
return -1;
}
BOOL CXTPReportSubListControl::Include(int /*iSubItem*/)
{
return TRUE;
}
BOOL CXTPReportSubListControl::Disable(int /*iSubItem*/)
{
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CXTPReportSubListControl message handlers
void CXTPReportSubListControl::PreSubclassWindow()
{
CListBox::PreSubclassWindow();
}
void CXTPReportSubListControl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CRect rcItem(lpDrawItemStruct->rcItem);
CXTPReportPaintManager* pPaintManager = m_pReportCtrl ? m_pReportCtrl->GetPaintManager() : NULL;
COLORREF clrBack = pPaintManager ? pPaintManager->m_clrControlBack : ::GetXtremeColor(COLOR_WINDOW);
if (GetCount() > 0 && m_pReportCtrl && pPaintManager)
{
BOOL bDisable = Disable((int)lpDrawItemStruct->itemData);
CXTPFontDC fnt(pDC, &pPaintManager->m_fontCaption);
if (GetExStyle() & WS_EX_STATICEDGE)
{
pDC->Draw3dRect(rcItem, pPaintManager->m_clrHighlightText, pPaintManager->m_clrControlDark);
rcItem.DeflateRect(1, 1);
pDC->FillSolidRect(rcItem, pPaintManager->m_clrControlBack);
rcItem.DeflateRect(1, 1);
}
else
{
pDC->FillSolidRect(rcItem, pPaintManager->m_clrHeaderControl);
pDC->Draw3dRect(rcItem, pPaintManager->m_clrBtnFace, GetXtremeColor(COLOR_3DDKSHADOW));
rcItem.DeflateRect(1, 1);
pDC->Draw3dRect(rcItem, pPaintManager->m_clrControlBack, pPaintManager->m_clrControlDark);
rcItem.DeflateRect(1, 1);
}
pDC->SetBkMode(TRANSPARENT);
CXTPReportColumn* pColumn = GetItemColumn((int)lpDrawItemStruct->itemID);
BOOL bSelected = lpDrawItemStruct->itemState & ODS_SELECTED;
pDC->SetTextColor(pPaintManager->m_clrCaptionText);
if (bSelected)
{
pDC->FillSolidRect(rcItem, GetXtremeColor(COLOR_3DFACE));
pDC->InvertRect(rcItem);
pDC->SetTextColor(bDisable ? ::GetXtremeColor(COLOR_BTNFACE) : ::GetXtremeColor(COLOR_3DHIGHLIGHT));
}
CXTPMarkupUIElement* pMarkupUIElement = pColumn->GetMarkupUIElement();
if (pMarkupUIElement)
{
XTPMarkupSetDefaultFont(XTPMarkupElementContext(pMarkupUIElement),
(HFONT)pDC->GetCurrentFont()->GetSafeHandle(), pDC->GetTextColor());
XTPMarkupMeasureElement(pMarkupUIElement, rcItem.Width(), INT_MAX);
XTPMarkupRenderElement(pMarkupUIElement, pDC->GetSafeHdc(), &rcItem);
}
else
{
if (bDisable && !bSelected)
{
pDC->SetTextColor(::GetXtremeColor(COLOR_3DHIGHLIGHT));
CRect rect = rcItem;
rect.OffsetRect(1, 1);
pDC->DrawText(pColumn->GetCaption(), rect,
DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_END_ELLIPSIS | DT_LEFT);
pDC->SetTextColor(::GetXtremeColor(COLOR_3DSHADOW));
}
pDC->DrawText(pColumn->GetCaption(), rcItem,
DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_END_ELLIPSIS | DT_LEFT);
}
}
else
pDC->FillSolidRect(rcItem, clrBack);
}
BOOL CXTPReportSubListControl::BeginDrag(int nItem)
{
if (GetCount() <= 0)
return FALSE;
int nSubItem = (int)GetItemData(nItem);
if (Disable(nSubItem))
{
return FALSE;
}
GetClientRect(m_rcDragWnd);
m_rcDragWnd.bottom = m_rcDragWnd.top + GetItemHeight(0);
CXTPReportHeader* pHeader = m_pReportCtrl->GetReportHeader();
CXTPReportColumn* pColumn = m_pReportCtrl->GetColumns()->Find(nSubItem);
pHeader->StartDragging(pColumn);
pHeader->m_bDragGroupBox = FALSE;
//pHeader->m_nDragIndex = m_nSubItem;
m_pDragWnd = new CXTPReportHeaderDragWnd;
if (m_pDragWnd)
m_pDragWnd->Create(m_rcDragWnd, pHeader, m_pReportCtrl->GetPaintManager(), pColumn);
m_pReportCtrl->SetMouseMode(xtpReportMouseDraggingColumn);
GetWindowRect(m_rcDropTarget1);
m_rcDropTarget2 = m_pReportCtrl->m_rcHeaderArea;
if (pColumn->IsGroupable())
m_rcDropTarget2.UnionRect(&m_rcDropTarget2, &m_pReportCtrl->m_rcGroupByArea);
m_pReportCtrl->ClientToScreen(m_rcDropTarget2);
m_nDropIndex = -1;
return TRUE;
}
UINT CXTPReportSubListControl::Dragging(CPoint pt)
{
CPoint point = pt;
point.Offset(-(m_rcDragWnd.Width() >> 1), -(m_rcDragWnd.Height() >> 1));
if (m_pDragWnd != NULL)
{
m_pDragWnd->SetWindowPos(&wndTop,
point.x, point.y, 0, 0,
SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
}
if (m_pReportCtrl)
{
CPoint pointCtrl(pt);
m_pReportCtrl->ScreenToClient(&pointCtrl);
m_pReportCtrl->OnMouseMove(0, pointCtrl);
}
if (m_rcDropTarget1.PtInRect(pt))
return DL_MOVECURSOR;
if (m_rcDropTarget2.PtInRect(pt))
return DL_MOVECURSOR;
return DL_STOPCURSOR;
}
void CXTPReportSubListControl::CancelDrag()
{
if (m_pDragWnd != NULL)
{
m_pDragWnd->DestroyWindow();
m_pDragWnd = NULL;
}
CXTPReportHeader* pHeader = m_pReportCtrl->GetReportHeader();
pHeader->SetHotDivider(-1);
m_pReportCtrl->SetMouseMode(xtpReportMouseNothing);
}
void CXTPReportSubListControl::Dropped(CPoint pt)
{
if (m_pDragWnd != NULL)
{
m_pDragWnd->DestroyWindow();
m_pDragWnd = NULL;
}
if (m_pReportCtrl)
{
m_pReportCtrl->ScreenToClient(&pt);
m_pReportCtrl->OnLButtonUp(0, pt);
}
}
void CXTPReportSubListControl::OnPaint()
{
CPaintDC dcPaint(this);
CRect rc;
GetClientRect(rc);
CXTPBufferDC dc(dcPaint, rc);
CXTPReportPaintManager* pPaintManager = m_pReportCtrl ? m_pReportCtrl->GetPaintManager() : NULL;
COLORREF clrBack = pPaintManager ? pPaintManager->m_clrControlBack : GetXtremeColor(COLOR_WINDOW);
dc.FillSolidRect(rc, IsWindowEnabled() ? clrBack : GetXtremeColor(COLOR_BTNFACE));
if (GetCount() > 0 || !pPaintManager)
CWnd::DefWindowProc(WM_PAINT, (WPARAM)dc.m_hDC, 0);
else
{
dc.SetTextColor(GetXtremeColor(COLOR_3DSHADOW));
dc.SetBkMode(TRANSPARENT);
CXTPFontDC fnt(&dc, &pPaintManager->m_fontCaption);
dc.DrawText(pPaintManager->m_strNoFieldsAvailable, rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX);
}
}
LRESULT CXTPReportSubListControl::OnPrintClient(WPARAM wParam, LPARAM lParam)
{
CListBox::DefWindowProc(WM_ERASEBKGND, wParam, 0);
return CListBox::DefWindowProc(WM_PRINTCLIENT, wParam, lParam);
}
BOOL CXTPReportSubListControl::OnEraseBkgnd(CDC* /*pDC*/)
{
return TRUE;
}
void CXTPReportSubListControl::OnLButtonDown(UINT nFlags, CPoint point)
{
SetFocus();
BOOL bOutside = TRUE;
int nItem = ItemFromPoint(point, bOutside);
if (nItem == LB_ERR)
{
CWnd::OnLButtonDown(nFlags, point);
return;
}
SetCurSel(nItem);
ParentNotify_SelChangd();
BOOL bAccept = FALSE;
BOOL bStartDrag = FALSE;
HCURSOR hCursorNo = AfxGetApp()->LoadStandardCursor(IDC_NO), hCursorArrow = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
SetCapture();
while (CWnd::GetCapture() == this)
{
MSG msg;
if (!GetMessage(&msg, NULL, 0, 0))
break;
if (msg.message == WM_MOUSEMOVE)
{
CPoint pt(msg.lParam);
if (point != pt)
{
if (!bStartDrag && abs(point.x - pt.x) + abs(point.y - pt.y) < 3)
continue;
point = pt;
if (!bStartDrag)
{
BeginDrag(nItem);
bStartDrag = TRUE;
}
if (bStartDrag)
{
ClientToScreen(&pt);
UINT nCursor = Dragging(pt);
::SetCursor(nCursor == DL_STOPCURSOR ? hCursorNo : hCursorArrow);
}
}
}
else if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) break;
else if (msg.message == WM_LBUTTONUP)
{
bAccept = TRUE;
break;
}
else ::DispatchMessage(&msg);
}
if (GetCapture() == this)
{
ReleaseCapture();
}
if (bStartDrag)
{
if (bAccept)
{
ClientToScreen(&point);
Dropped(point);
ParentNotify_SelChangd();
}
else
{
CancelDrag();
}
}
}
void CXTPReportSubListControl::ParentNotify_SelChangd()
{
if (GetParent() && (GetStyle() & LBS_NOTIFY))
GetParent()->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_SELCHANGE), (LPARAM)m_hWnd);
}