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.

389 lines
10 KiB
C++

2 years ago
// XTPChartDiagram2D.cpp
//
// This file is a part of the XTREME TOOLKIT PRO 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 "../../Types/XTPChartTypes.h"
#include "../../XTPChartDefines.h"
#include "../../XTPChartElement.h"
#include <Chart/XTPChartLegendItem.h>
#include "../../XTPChartElementView.h"
#include "../../XTPChartPanel.h"
#include <Chart/XTPChartSeriesPointView.h>
#include "../../XTPChartSeriesView.h"
#include "../../XTPChartSeries.h"
#include "../../XTPChartSeriesPoint.h"
#include "../../XTPChartDiagram.h"
#include "../../XTPChartDiagramView.h"
#include "../../XTPChartTitle.h"
#include "../../XTPChartSeriesStyle.h"
#include "../../XTPChartSeriesLabel.h"
#include "../Axis/XTPChartAxis.h"
#include "../Axis/XTPChartAxisView.h"
#include "XTPChartDiagram2D.h"
#include "XTPChartDiagram2DView.h"
#include "XTPChartDiagram2DPane.h"
#include "XTPChartDiagram2DSeriesView.h"
#include "XTPChartDiagram2DSeriesStyle.h"
#include "XTPChartDiagram2DSeriesLabel.h"
//////////////////////////////////////////////////////////////////////////
// CXTPChartDiagram2DView
CXTPChartDiagram2DView::CXTPChartDiagram2DView(CXTPChartDiagram* pDiagram, CXTPChartElementView* pParent)
: CXTPChartDiagramView(pDiagram, pParent)
{
m_pAxisViews = NULL;
m_pPaneView = NULL;
m_rcLabelPadding.SetRectEmpty();
}
void CXTPChartDiagram2DView::AddAxisView(CXTPChartDeviceContext* pDC, CXTPChartElementView* pParentView, CXTPChartAxis* pAxis)
{
CXTPChartDiagram2DAxisView* pAxisView = (CXTPChartDiagram2DAxisView*)pAxis->CreateView(pDC, pParentView);
pAxisView->CreateView(pDC);
}
CXTPChartAxisView* CXTPChartDiagram2DView::GetAxisView(CXTPChartAxis* pAxis) const
{
for (int i = 0; i < m_pAxisViews->GetCount(); i++)
{
CXTPChartAxisView* pAxisView = (CXTPChartAxisView*)m_pAxisViews->GetAt(i);
if (pAxisView->GetAxis() == pAxis)
return pAxisView;
}
return NULL;
}
void CXTPChartDiagram2DView::UpdateRange(CXTPChartDeviceContext* pDC)
{
int i;
for (i = 0; i < GetSeriesView()->GetCount(); i++)
{
CXTPChartDiagram2DSeriesView* pSeriesView = (CXTPChartDiagram2DSeriesView*)GetSeriesView()->GetAt(i);
pSeriesView->BeforeUpdateRange(pDC);
}
for (i = 0; i < m_pAxisViews->GetCount(); i++)
{
CXTPChartDiagram2DAxisView* pAxisView = (CXTPChartDiagram2DAxisView*)m_pAxisViews->GetAt(i);
for (int j = 0; j < GetSeriesView()->GetCount(); j++)
{
CXTPChartSeriesView* pSeriesView = (CXTPChartSeriesView*)GetSeriesView()->GetAt(j);
if (!pSeriesView->GetSeries()->IsVisible())
continue;
CXTPChartDiagram2DSeriesStyle* pStyle = DYNAMIC_DOWNCAST(CXTPChartDiagram2DSeriesStyle, pSeriesView->GetSeries()->GetStyle());
ASSERT(pStyle);
if (!pStyle)
continue;
BOOL bAxisX = !pAxisView->GetAxis()->IsValuesAxis();
if (pAxisView->GetAxis()->IsSecondary() != (bAxisX ? pStyle->IsSecondaryAxisX() : pStyle->IsSecondaryAxisY()))
continue;
pAxisView->m_arrSeries.Add(pSeriesView);
if (bAxisX)
((CXTPChartDiagram2DSeriesView*)pSeriesView)->m_pAxisViewX = pAxisView;
else
((CXTPChartDiagram2DSeriesView*)pSeriesView)->m_pAxisViewY = pAxisView;
}
}
for (i = 0; i < m_pAxisViews->GetCount(); i++)
{
CXTPChartDiagram2DAxisView* pAxisView = (CXTPChartDiagram2DAxisView*)m_pAxisViews->GetAt(i);
pAxisView->GetAxis()->UpdateRange(pDC, pAxisView);
pAxisView->AddLegendItems();
}
for (i = 0; i < GetSeriesView()->GetCount(); i++)
{
CXTPChartDiagram2DSeriesView* pSeriesView = (CXTPChartDiagram2DSeriesView*)GetSeriesView()->GetAt(i);
pSeriesView->AfterUpdateRange(pDC);
}
}
void CXTPChartDiagram2DView::CheckLabelBounds(const CXTPChartRectF& rcBounds)
{
if (rcBounds.GetTop() < m_rcBounds.top)
{
m_rcLabelPadding.top = max(m_rcLabelPadding.top, m_rcBounds.top - (LONG)rcBounds.GetTop());
}
if (rcBounds.GetRight() > m_rcBounds.right)
{
m_rcLabelPadding.right = max(m_rcLabelPadding.right, (LONG)rcBounds.GetRight() - m_rcBounds.right);
}
if (rcBounds.GetLeft() < m_rcBounds.left)
{
m_rcLabelPadding.left = max(m_rcLabelPadding.left, m_rcBounds.left - (LONG)rcBounds.GetLeft());
}
if (rcBounds.GetBottom() > m_rcBounds.bottom)
{
m_rcLabelPadding.bottom = max(m_rcLabelPadding.bottom, (LONG)rcBounds.GetBottom() - m_rcBounds.bottom);
}
}
void CXTPChartDiagram2DView::CalculateView(CXTPChartDeviceContext* pDC, CRect rcBounds)
{
m_pDiagram->GetTitles()->CalculateView(pDC, rcBounds, m_pTitlesView);
m_rcLabelPadding.SetRectEmpty();
CRect rcDiagramBounds = rcBounds;
for (int nUpdate = 0; nUpdate < 2; nUpdate++)
{
const int AXIS_GAP = 10;
rcBounds = rcDiagramBounds;
rcBounds.DeflateRect(m_rcLabelPadding);
m_rcBounds = rcBounds;
CRect rcInnerBounds(rcBounds);
m_rcLabelPadding.SetRectEmpty();
CRect rcPane(rcBounds);
int i;
((CXTPChartDiagram2D*)m_pDiagram)->UpdateLayout(pDC, this, rcBounds);
CXTPChartDiagram2D* pDiagram = (CXTPChartDiagram2D*)GetDiagram();
for (i = 0; i < m_pAxisViews->GetCount(); i++)
{
CXTPChartDiagram2DAxisView* pAxisView = (CXTPChartDiagram2DAxisView*)m_pAxisViews->GetAt(i);
pAxisView->CalcSize(pDC, rcPane);
if (!pAxisView->GetAxis()->IsVisible())
continue;
if (pAxisView->GetAxis()->IsVertical())
{
if (pAxisView->GetAxis()->GetAlignment() == xtpChartAlignNear)
{
if (rcPane.left != rcBounds.left) rcPane.left += AXIS_GAP;
rcPane.left += pAxisView->GetSize();
}
else
{
if (rcPane.right != rcBounds.right) rcPane.right -= AXIS_GAP;
rcPane.right -= pAxisView->GetSize();
}
}
else
{
if (pAxisView->GetAxis()->GetAlignment() == xtpChartAlignNear)
{
if (rcPane.bottom != rcBounds.bottom) rcPane.bottom -= AXIS_GAP;
rcPane.bottom -= pAxisView->GetSize();
}
else
{
if (rcPane.top != rcBounds.top) rcPane.top += AXIS_GAP;
rcPane.top += pAxisView->GetSize();
}
}
}
for (i = m_pAxisViews->GetCount() - 1; i >= 0; i--)
{
CXTPChartDiagram2DAxisView* pAxisView = (CXTPChartDiagram2DAxisView*)m_pAxisViews->GetAt(i);
int nSize = pAxisView->GetSize();
if (pAxisView->GetAxis()->IsVertical())
{
if (pAxisView->GetAxis()->GetAlignment() == xtpChartAlignNear)
{
if (rcBounds.left != m_rcBounds.left) rcBounds.left += AXIS_GAP;
pAxisView->SetBounds(pDC, CRect(rcBounds.left, rcPane.top, rcBounds.left + nSize, rcPane.bottom));
rcBounds.left += nSize;
}
else
{
if (rcBounds.right != m_rcBounds.right) rcBounds.right -= AXIS_GAP;
pAxisView->SetBounds(pDC, CRect(rcBounds.right - nSize, rcPane.top, rcBounds.right, rcPane.bottom));
rcBounds.right -= nSize;
}
}
else
{
if (pAxisView->GetAxis()->GetAlignment() == xtpChartAlignNear)
{
if (rcBounds.bottom != m_rcBounds.bottom) rcBounds.bottom -= AXIS_GAP;
pAxisView->SetBounds(pDC, CRect(rcPane.left, rcBounds.bottom - nSize, rcPane.right, rcBounds.bottom));
rcBounds.bottom -= nSize;
}
else
{
if (rcBounds.top != m_rcBounds.top) rcBounds.top += AXIS_GAP;
pAxisView->SetBounds(pDC, CRect(rcPane.left, rcBounds.top, rcPane.right, rcBounds.top + nSize));
rcBounds.top += nSize;
}
}
}
m_pPaneView->CalculateView(rcBounds);
if (m_pPaneView->m_rcBounds.Width() < 1 || m_pPaneView->m_rcBounds.Height() < 1)
break;
pDiagram->CalculateSeriesLayout(pDC, this);
for (i = 0; i < m_pLabelsView->GetCount(); i++)
{
CXTPChartDiagram2DSeriesLabelView* pLabelView = (CXTPChartDiagram2DSeriesLabelView*)m_pLabelsView->GetAt(i);
pLabelView->CalculateLayout(pDC);
}
if( m_rcLabelPadding.IsRectNull())
break;
}
}
void CXTPChartDiagram2DView::CreateView(CXTPChartDeviceContext* pDC)
{
CXTPChartDiagramView::CreateView(pDC);
CXTPChartDiagram2D* pDiagram = (CXTPChartDiagram2D*)GetDiagram();
CXTPChartElementView* pPaneView = new CXTPChartElementView(this);
m_pAxisViews = new CXTPChartElementView(this);
AddAxisView(pDC, m_pAxisViews, pDiagram->GetAxisX());
AddAxisView(pDC, m_pAxisViews, pDiagram->GetSecondaryAxisX());
AddAxisView(pDC, m_pAxisViews, pDiagram->GetAxisY());
AddAxisView(pDC, m_pAxisViews, pDiagram->GetSecondaryAxisY());
m_pPaneView = (CXTPChartDiagram2DPaneView*)pDiagram->GetPane()->CreateView(pDC, pPaneView);
m_pSeriesView = m_pPaneView->CreateSeriesView();
m_pLabelsView = new CXTPChartElementView(this);
}
CXTPChartDeviceCommand* CXTPChartDiagram2DView::CreateDeviceCommand(CXTPChartDeviceContext* pDC)
{
if (m_pPaneView->m_rcBounds.Width() < 1 || m_pPaneView->m_rcBounds.Height() < 1)
return NULL;
return CXTPChartDiagramView::CreateDeviceCommand(pDC);
}
void CXTPChartDiagram2DView::OnMouseWheel(UINT /*nFlags*/, short zDelta, CPoint pt)
{
CXTPChartDiagram2D* pDiagram = (CXTPChartDiagram2D*)GetDiagram();
if (!pDiagram->IsAllowZoom())
return;
if (!m_pPaneView->GetBounds().PtInRect(pt))
return;
for (int i = 0; i < m_pAxisViews->GetCount(); i++)
{
CXTPChartDiagram2DAxisView* pAxisView = (CXTPChartDiagram2DAxisView*)m_pAxisViews->GetAt(i);
pAxisView->PerformMouseWheel(zDelta, pt);
}
}
BOOL CXTPChartDiagram2DView::OnSetCursor(CPoint point)
{
if (!m_pPaneView->GetBounds().PtInRect(point))
{
return FALSE;
}
for (int i = 0; i < m_pAxisViews->GetCount(); i++)
{
CXTPChartDiagram2DAxisView* pAxisView = (CXTPChartDiagram2DAxisView*)m_pAxisViews->GetAt(i);
if (pAxisView->IsScollBarVisible())
{
::SetCursor(m_hcurNormalHand);
return TRUE;
}
}
return FALSE;
}
void CXTPChartDiagram2DView::OnLButtonDown(UINT nFlags, CPoint point)
{
CXTPChartDiagram2D* pDiagram = (CXTPChartDiagram2D*)GetDiagram();
if (!pDiagram->IsAllowScroll())
return;
if (m_pPaneView->GetBounds().PtInRect(point))
{
m_pPaneView->OnLButtonDown(nFlags, point);
return;
}
for (int i = 0; i < m_pAxisViews->GetCount(); i++)
{
CXTPChartDiagram2DAxisView* pAxisView = (CXTPChartDiagram2DAxisView*)m_pAxisViews->GetAt(i);
if (pAxisView->GetBounds().PtInRect(point))
{
pAxisView->OnLButtonDown(nFlags, point);
return;
}
}
}