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.

370 lines
8.9 KiB
C++

// XTPReportSections.cpp : implementation of the CXTPReportSections 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/XTPSystemHelpers.h"
#include "Common/XTPImageManager.h"
#include "Common/XTPPropExchange.h"
#include "Common/XTPToolTipContext.h"
#include "Common/XTPResourceManager.h"
#include "Common/XTPMarkupRender.h"
#include "Common/XTPCustomHeap.h"
#include "Common/XTPSmartPtrInternalT.h"
#include "Common/XTPColorManager.h"
#include "XTPReportDefines.h"
#include "XTPReportControl.h"
#include "XTPReportSection.h"
#include "XTPReportSections.h"
#include "XTPReportRecord.h"
#include "XTPReportRecords.h"
#include "XTPReportRows.h"
#include "XTPReportRow.h"
#include "XTPReportPaintManager.h"
CXTPReportSections::CXTPReportSections(CXTPReportControl *pControl)
: m_pControl (pControl)
, m_rcSections(0,0,0,0)
{
Add(new CXTPReportSection(pControl, xtpRowTypeHeader));
Add(new CXTPReportSection(pControl, xtpRowTypeBody));
Add(new CXTPReportSection(pControl, xtpRowTypeFooter));
}
CXTPReportSections::~CXTPReportSections()
{
for (int nSection=0; nSection<GetSize(); nSection++)
{
CXTPReportSection *pSection = GetAt(nSection);
SAFE_DELETE(pSection);
}
RemoveAll();
}
CXTPReportSection *CXTPReportSections::FindSection(CXTPReportRow *pRow) const
{
for (int nSection=0; nSection<GetSize(); nSection++)
{
CXTPReportSection *pSection = GetAt(nSection);
if (pSection->GetRows()->Contains(pRow))
{
return pSection;
}
}
return NULL;
}
BOOL CXTPReportSections::EnsureVisible(CDC *pDC, CXTPReportRow *pRow)
{
// None of the parameters may be null
ASSERT(NULL != pDC);
ASSERT(NULL != pRow);
BOOL bResult = FALSE;
if (NULL != pRow)
{
CXTPReportSection *pSection = pRow->GetSection();
ASSERT(NULL != pSection); // Section must always be valid
if (NULL != pSection)
{
bResult = pSection->EnsureVisible(pDC, pRow);
}
}
return bResult;
}
CXTPReportRow* CXTPReportSections::GetFocusedRow() const
{
CXTPReportRow *pFocusedRow = NULL;
for (int nSection=0; nSection<GetSize(); nSection++)
{
CXTPReportSection *pSection = GetAt(nSection);
pFocusedRow = pSection->GetRows()->GetFocusedRow();
if (NULL != pFocusedRow)
{
return pFocusedRow;
}
}
return NULL;
}
CRect CXTPReportSections::GetRect() const
{
return m_rcSections;
}
CXTPReportSection* CXTPReportSections::HitTest(CPoint pt) const
{
CXTPReportSection *pHitSection = NULL;
for (int nSection=0; nSection<GetSize(); nSection++)
{
CXTPReportSection *pSection = GetAt(nSection);
if (pSection->m_rcSection.PtInRect(pt))
{
ASSERT(NULL == pHitSection); // There can only be one
pHitSection = pSection;
}
}
return pHitSection;
}
void CXTPReportSections::Draw(CDC *pDC)
{
for (int nSection=0; nSection<GetSize(); nSection++)
{
CXTPReportSection *pSection = GetAt(nSection);
if (pSection->IsVisible())
{
pSection->Draw(pDC);
}
}
}
void CXTPReportSections::AdjustLayout(CDC *pDC, CRect rcSections)
{
m_rcSections = rcSections;
CArray<int, int> arrHeightSection;
CArray<int ,int> arrHeightDivider;
arrHeightSection.SetSize(GetSize());
arrHeightDivider.SetSize(GetSize());
int nSection;
//////////////////////////////////////////////////////////////////////////
// Calculate height of sections
//////////////////////////////////////////////////////////////////////////
for (nSection=0; nSection<GetSize(); nSection++)
{
CXTPReportSection *pSection = GetAt(nSection);
int nHeightSection = 0; // Height of the section in pixels
int nHeightDivider = 0; // Height of the divider in pixels
if (pSection->IsVisible())
{
// Divider
XTPReportFixedRowsDividerStyle dividerStyle = pSection->GetDividerStyle();
nHeightDivider = m_pControl->GetPaintManager()->GetSectionDividerHeight(dividerStyle);
// Section
switch (pSection->GetHeightMode())
{
case xtpReportSectionHeightModeFixed:
{
nHeightSection = pSection->GetHeight();
}
break;
case xtpReportSectionHeightModeRelative:
{
double dPercent = rcSections.Height() / 100.0; // Pixels per percent
nHeightSection = static_cast<int>(dPercent * pSection->GetHeight());
}
break;
case xtpReportSectionHeightModeAuto:
case xtpReportSectionHeightModeAutoExpand:
case xtpReportSectionHeightModeAutoShrink:
{
nHeightSection = pSection->GetTotalHeight(pDC);
}
break;
case xtpReportSectionHeightModeExpand:
{
// Remaining height is calculated in the next step
nHeightSection = 0;
}
break;
}
}
arrHeightSection[nSection] = nHeightSection;
arrHeightDivider[nSection] = nHeightDivider;
}
//////////////////////////////////////////////////////////////////////////
// Calculate remaining height
//////////////////////////////////////////////////////////////////////////
int nHeightExpand = rcSections.Height();
for (nSection=0; nSection<GetSize(); nSection++)
{
nHeightExpand -= arrHeightSection[nSection];
nHeightExpand -= arrHeightDivider[nSection];
}
if (nHeightExpand < 0)
{
// Shrink auto shrink section
for (nSection=0; nSection<GetSize(); nSection++)
{
CXTPReportSection *pSection = GetAt(nSection);
if (xtpReportSectionHeightModeAutoShrink == pSection->GetHeightMode())
{
int nHeightSection = arrHeightSection[nSection];
nHeightSection += nHeightExpand; // nHeightExpand is negative
nHeightSection = max(0, nHeightSection);
arrHeightSection[nSection] = nHeightSection;
}
}
}
nHeightExpand = max(0, nHeightExpand);
//////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////
for (nSection=0; nSection<GetSize(); nSection++)
{
CXTPReportSection *pSection = GetAt(nSection);
if (xtpReportSectionHeightModeExpand == pSection->GetHeightMode())
{
arrHeightSection[nSection] = nHeightExpand;
}
}
//////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////
int nTop = rcSections.top;
for (nSection=0; nSection<GetSize(); nSection++)
{
CXTPReportSection *pSection = GetAt(nSection);
// Divider at the top
if (xtpReportSectionDividerStyleNone != pSection->GetDividerStyle() &&
xtpReportSectionDividerPositionTop == pSection->GetDividerPosition())
{
pSection->m_rcDivider.left = rcSections.left;
pSection->m_rcDivider.right = rcSections.right;
pSection->m_rcDivider.top = nTop;
pSection->m_rcDivider.bottom = nTop + arrHeightDivider[nSection];
nTop += arrHeightDivider[nSection];
}
pSection->m_rcSection.left = rcSections.left;
pSection->m_rcSection.right = rcSections.right;
pSection->m_rcSection.top = nTop;
pSection->m_rcSection.bottom = nTop + arrHeightSection[nSection];
nTop += arrHeightSection[nSection];
// Divider at the bottom
if (xtpReportSectionDividerStyleNone != pSection->GetDividerStyle() &&
xtpReportSectionDividerPositionBottom == pSection->GetDividerPosition())
{
pSection->m_rcDivider.left = rcSections.left;
pSection->m_rcDivider.right = rcSections.right;
pSection->m_rcDivider.top = nTop;
pSection->m_rcDivider.bottom = nTop + arrHeightDivider[nSection];
nTop += arrHeightDivider[nSection];
}
}
}
void CXTPReportSections::SetMarkupContext(CXTPMarkupContext *pMarkupContext)
{
// Set markup context for all sections
for (int nSection=0; nSection<GetSize(); nSection++)
{
CXTPReportSection *pSection = GetAt(nSection);
pSection->SetMarkupContext(pMarkupContext);
}
}
void CXTPReportSections::ReSortRows()
{
// Re-sort rows of all sections
for (int nSection=0; nSection<GetSize(); nSection++)
{
CXTPReportSection *pSection = GetAt(nSection);
ASSERT(NULL != pSection);
if (pSection->IsAllowSort())
{
pSection->ReSortRows();
}
}
m_pControl->AdjustIndentation();
m_pControl->AdjustLayout();
m_pControl->RedrawControl();
}
void CXTPReportSections::RefreshIndexes(BOOL bAdjustLayout, BOOL bReverseOrder)
{
// Re-sort rows of all sections
for (int nSection=0; nSection<GetSize(); nSection++)
{
CXTPReportSection *pSection = GetAt(nSection);
ASSERT(NULL != pSection);
pSection->RefreshIndexes(FALSE, bReverseOrder);
}
if (bAdjustLayout)
{
m_pControl->AdjustScrollBars();
}
}