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.

1347 lines
38 KiB
C++

// XTPChartAxisView.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 <math.h>
#include "../../Types/XTPChartTypes.h"
#include "Common/Base/Types/XTPPoint3.h"
#include "../../XTPChartDefines.h"
#include "../../XTPChartElement.h"
#include <Chart/XTPChartLegendItem.h>
#include "../../XTPChartElementView.h"
#include "../../XTPChartPanel.h"
#include "../../XTPChartContentView.h"
#include "../../XTPChartLegend.h"
#include <Chart/XTPChartLegendView.h>
#include "../../XTPChartDiagram.h"
#include "../Diagram2D/XTPChartDiagram2D.h"
#include "XTPChartAxis.h"
#include "XTPChartAxisView.h"
#include "XTPChartAxisRange.h"
#include "XTPChartAxisLabel.h"
#include "XTPChartAxisGridLines.h"
#include "XTPChartAxisTickMarks.h"
#include "XTPChartAxisTitle.h"
#include "XTPChartAxisConstantLines.h"
#include "XTPChartAxisStrips.h"
#include "XTPChartAxisCustomLabels.h"
#include "XTPChartScaleTypeMap.h"
#include "../../Drawing/XTPChartDeviceCommand.h"
#include "../../Drawing/XTPChartLineDeviceCommand.h"
#include "../../Drawing/XTPChartRectangleDeviceCommand.h"
#include "../../Utils/XTPChartTextPainter.h"
#include <Common/XTPMathUtils.h>
#include "../../Appearance/XTPChartLineStyle.h"
#include "../../Appearance/XTPChartFillStyle.h"
#define SCROLLBARSIZE 10
//////////////////////////////////////////////////////////////////////////
// CXTPChartAxisView
CXTPChartAxisView::CXTPChartAxisView(CXTPChartAxis* pAxis, CXTPChartElementView* pParentView)
: CXTPChartElementView(pParentView)
{
m_dGridSpacing = 1;
m_pAxis = pAxis;
}
CXTPChartAxisView::~CXTPChartAxisView()
{
}
//////////////////////////////////////////////////////////////////////////
// CXTPChartDiagram2DAxisView
CXTPChartDiagram2DAxisView::CXTPChartDiagram2DAxisView(CXTPChartAxis* pAxis, CXTPChartElementView* pParentView)
: CXTPChartAxisView(pAxis, pParentView)
{
ASSERT(m_pContainer);
m_nSize = 0;
m_ptOldPosition = CPoint(0, 0);
m_rcBounds.SetRectEmpty();
}
CXTPChartDiagram2DAxisView::~CXTPChartDiagram2DAxisView()
{
}
double CXTPChartAxisView::ValueToAxis(double dValue) const
{
if (!m_pAxis->IsLogarithmic())
return dValue;
if (fabs(dValue) < CXTPMathUtils::m_dEPS)
return 0;
if (dValue < 0)
return 0;
return log(dValue) / log(m_pAxis->GetLogarithmicBase());
}
double CXTPChartAxisView::AxisToValue(double dValue) const
{
if (!m_pAxis->IsLogarithmic())
return dValue;
return pow(m_pAxis->GetLogarithmicBase(), dValue);
}
double CXTPChartAxisView::GetRangeMinValue() const
{
return m_pAxis->GetRange()->GetMinValue();
}
double CXTPChartAxisView::GetRangeMaxValue() const
{
return m_pAxis->GetRange()->GetMaxValue();
}
double CXTPChartAxisView::GetViewRangeMinValue() const
{
return max(m_pAxis->GetRange()->GetViewMinValue(), GetRangeMinValue());
}
double CXTPChartAxisView::GetViewRangeMaxValue() const
{
return min(m_pAxis->GetRange()->GetViewMaxValue(), GetRangeMaxValue());
}
double CXTPChartAxisView::GetAxisRangeMinValue() const
{
return ValueToAxis(GetViewRangeMinValue());
}
double CXTPChartAxisView::GetAxisRangeMaxValue() const
{
return ValueToAxis(GetViewRangeMaxValue());
}
CXTPChartDeviceCommand* CXTPChartDiagram2DAxisView::CreateInterlacedDeviceCommand(CXTPChartDeviceContext* pDC, CRect rcPane)
{
UNREFERENCED_PARAMETER(pDC);
if (!m_pAxis->IsInterlaced())
return NULL;
if (m_arrTicks.GetSize() < 1)
return NULL;
CXTPChartDeviceCommand* pCommands = new CXTPChartDeviceCommand();
BOOL bVertical = IsVertical();
BOOL bReversed = m_pAxis->IsReversed();
int nLeft = bVertical ? (bReversed ? m_rcBounds.top : m_rcBounds.bottom) : (bReversed ? m_rcBounds.right : m_rcBounds.left);
int i = 0;
double dMark;
double dGridSpacing = GetGridSpacing();
int nCount = int((m_arrTicks[0].m_dValue - GetRangeMinValue()) / dGridSpacing);
if ((nCount & 1) == 1)
{
dMark = m_arrTicks[0].m_dValue;
nLeft = (int)ValueToPoint(dMark);
i = 1;
}
while (i <= m_arrTicks.GetSize())
{
int nRight;
if (i >= m_arrTicks.GetSize())
{
nRight = bVertical ? (!bReversed ? m_rcBounds.top : m_rcBounds.bottom) : (!bReversed ? m_rcBounds.right : m_rcBounds.left);
}
else
{
dMark = m_arrTicks[i].m_dValue;
nRight = (int)ValueToPoint(dMark);
}
i++;
CXTPChartRectF rc = bVertical ? CXTPChartRectF((float)rcPane.left, (float)nRight, (float)rcPane.Width(), (float)nLeft - nRight) :
CXTPChartRectF((float)nLeft, (float)rcPane.top, (float)nRight - nLeft, (float)rcPane.Height());
if (rc.Width < 0) rc.X += rc.Width, rc.Width = -rc.Width;
if (rc.Height < 0) rc.Y += rc.Height, rc.Height = -rc.Height;
pCommands->AddChildCommand(m_pAxis->GetInterlacedFillStyle()->CreateDeviceCommand(rc,
m_pAxis->GetActualInterlacedColor(), m_pAxis->GetActualInterlacedColor2()));
if (i >= m_arrTicks.GetSize())
break;
dMark = m_arrTicks[i].m_dValue;
nLeft = (int)ValueToPoint(dMark);
i++;
}
return pCommands;
}
CXTPChartDeviceCommand* CXTPChartDiagram2DAxisView::CreateStripsDeviceCommand(CXTPChartDeviceContext* pDC, CRect rcPane)
{
UNREFERENCED_PARAMETER(pDC);
CXTPChartAxisStrips* pStrips = m_pAxis->GetStrips();
if (pStrips->GetCount() == 0)
return NULL;
CXTPChartDeviceCommand* pCommands = new CXTPChartDeviceCommand();
BOOL bVertical = IsVertical();
for (int i = 0; i < pStrips->GetCount(); i++)
{
CXTPChartAxisStrip* pStrip = pStrips->GetAt(i);
if (!pStrip->IsVisible())
continue;
double dMarkLeft = !pStrip->GetAxisMinValue().IsEmpty() ? m_pAxis->GetScaleTypeMap()->ValueToInternal(pStrip->GetAxisMinValue()) :
pStrip->GetAxisMinValueInternal();
double dMarkRight = !pStrip->GetAxisMaxValue().IsEmpty() ? m_pAxis->GetScaleTypeMap()->ValueToInternal(pStrip->GetAxisMaxValue()) :
pStrip->GetAxisMaxValueInternal();
int nLeft = (int)ValueToPoint(dMarkLeft);
int nRight = (int)ValueToPoint(dMarkRight);
CXTPChartRectF rc;
if (bVertical)
{
rc = CXTPChartRectF((float)rcPane.left, (float)nRight, (float)rcPane.Width(), (float)nLeft - nRight);
}
else
{
rc = CXTPChartRectF((float)nLeft, (float)rcPane.top, (float)nRight - nLeft, (float)rcPane.Height());
}
rc.Normalize();
pCommands->AddChildCommand(pStrip->GetFillStyle()->CreateDeviceCommand(rc, pStrip->GetActualColor(), pStrip->GetActualColor2()));
}
return pCommands;
}
CXTPChartDeviceCommand* CXTPChartDiagram2DAxisView::CreateConstantLinesDeviceCommand(CXTPChartDeviceContext* pDC, CRect rcPane, BOOL bBehind)
{
CXTPChartAxisConstantLines* pConstantLines = m_pAxis->GetConstantLines();
if (pConstantLines->GetCount() == 0)
return NULL;
CXTPChartDeviceCommand* pCommands = new CXTPChartDeviceCommand();
BOOL bVertical = IsVertical();
for (int i = 0; i < pConstantLines->GetCount(); i++)
{
CXTPChartAxisConstantLine* pConstantLine = pConstantLines->GetAt(i);
if (!pConstantLine->IsVisible())
continue;
if (pConstantLine->IsShowBehind() != bBehind)
continue;
double dMark = !pConstantLine->GetAxisValue().IsEmpty() ? m_pAxis->GetScaleTypeMap()->ValueToInternal(pConstantLine->GetAxisValue()) :
pConstantLine->GetAxisValueInternal();
int nLeft = (int)ValueToPoint(dMark);
if (bVertical)
{
pCommands->AddChildCommand(pConstantLine->GetLineStyle()->CreateDeviceCommand(CXTPPoint3d(rcPane.left, nLeft),
CXTPPoint3d(rcPane.right, nLeft), pConstantLine->GetActualColor()));
}
else
{
pCommands->AddChildCommand(pConstantLine->GetLineStyle()->CreateDeviceCommand(CXTPPoint3d(nLeft, rcPane.top),
CXTPPoint3d(nLeft, rcPane.bottom), pConstantLine->GetActualColor()));
}
CXTPChartString strText = pConstantLine->GetText();
if (bVertical)
{
CXTPChartTextPainter painter(pDC, strText, pConstantLine);
int x = pConstantLine->GetAlignment() == xtpChartAlignNear ? rcPane.left + 2 :
pConstantLine->GetAlignment() == xtpChartAlignFar ? rcPane.right - 2 - (int)painter.GetSize().Width :
(rcPane.left + rcPane.right - (int)painter.GetSize().Width) / 2;
painter.SetLocation(CXTPPoint2i(x, pConstantLine->IsTextBelow() ? nLeft + 2 : nLeft - (int)painter.GetSize().Height));
pCommands->AddChildCommand(painter.CreateDeviceCommand(pDC, pConstantLine->GetActualTextColor()));
}
else
{
CXTPChartRotatedTextPainterNearLine painter(pDC, strText, pConstantLine, CPoint(0, 0), TRUE ? xtpChartTextNearRight : xtpChartTextNearTop, 90);
int y = pConstantLine->GetAlignment() == xtpChartAlignNear ? rcPane.bottom - (int)painter.GetSize().Width / 2 :
pConstantLine->GetAlignment() == xtpChartAlignFar ? rcPane.top + (int)painter.GetSize().Width / 2 : (rcPane.top + rcPane.bottom) / 2;
painter.SetBasePoint(CPoint(pConstantLine->IsTextBelow() ? nLeft + 2 - (int)painter.GetSize().Height : nLeft + 2, y));
pCommands->AddChildCommand(painter.CreateDeviceCommand(pDC, pConstantLine->GetActualTextColor()));
}
}
return pCommands;
}
CXTPChartDeviceCommand* CXTPChartDiagram2DAxisView::CreateGridLinesDeviceCommand(CXTPChartDeviceContext* pDC, CRect rcPane)
{
UNREFERENCED_PARAMETER(pDC);
CXTPChartAxisGridLines* pGridLines = m_pAxis->GetGridLines();
if (!pGridLines->IsVisible())
return NULL;
CXTPChartDeviceCommand* pCommands = new CXTPChartDeviceCommand();
CXTPChartColor clrGridLines = pGridLines->GetColor();
CXTPChartColor clrMinorGridLines = pGridLines->GetMinorColor();
BOOL bMinorVisible = pGridLines->IsMinorVisible();
BOOL bVertical = IsVertical();
for (int i = 0; i < m_arrTicks.GetSize(); i++)
{
int nLeft = (int)ValueToPoint(m_arrTicks[i].m_dValue);
if (bVertical)
{
pCommands->AddChildCommand(pGridLines->GetLineStyle()->CreateDeviceCommand(CXTPPoint3d(rcPane.left, nLeft),
CXTPPoint3d(rcPane.right, nLeft), clrGridLines));
}
else
{
pCommands->AddChildCommand(pGridLines->GetLineStyle()->CreateDeviceCommand(CXTPPoint3d(nLeft, rcPane.top),
CXTPPoint3d(nLeft, rcPane.bottom), clrGridLines));
}
}
if (bMinorVisible)
{
for (int i = 0; i < m_arrMinorTicks.GetSize(); i++)
{
int nLeft = (int)ValueToPoint(m_arrMinorTicks[i]);
if (bVertical)
{
pCommands->AddChildCommand(pGridLines->GetMinorLineStyle()->CreateDeviceCommand(CXTPPoint3d(rcPane.left, nLeft),
CXTPPoint3d(rcPane.right, nLeft), clrMinorGridLines));
}
else
{
pCommands->AddChildCommand(pGridLines->GetMinorLineStyle()->CreateDeviceCommand(CXTPPoint3d(nLeft, rcPane.top),
CXTPPoint3d(nLeft, rcPane.bottom), clrMinorGridLines));
}
}
}
return pCommands;
}
double CXTPChartDiagram2DAxisView::GetScale() const
{
double dMinValue = GetAxisRangeMinValue();
double dMaxValue = GetAxisRangeMaxValue();
if (IsVertical())
{
return (m_rcBounds.Height()) / (dMaxValue - dMinValue);
}
else
{
return (m_rcBounds.Width()) / (dMaxValue - dMinValue);
}
}
double CXTPChartDiagram2DAxisView::DistanceToPoint(double x) const
{
double dMinValue = GetAxisRangeMinValue();
double dMaxValue = GetAxisRangeMaxValue();
if (IsVertical())
{
return x / (dMaxValue - dMinValue) * (m_rcBounds.Height());
}
else
{
return x / (dMaxValue - dMinValue) * (m_rcBounds.Width());
}
}
double CXTPChartDiagram2DAxisView::PointToValue(int nPoint) const
{
double dMinValue = GetAxisRangeMinValue();
double dMaxValue = GetAxisRangeMaxValue();
BOOL bRevered = m_pAxis->IsReversed();
double dValue;
if (bRevered)
{
if (IsVertical())
{
dValue = dMinValue + (double)(nPoint - m_rcBounds.top) * (dMaxValue - dMinValue) / m_rcBounds.Height();
}
else
{
dValue = dMinValue + (double)(m_rcBounds.right - nPoint) * (dMaxValue - dMinValue) / m_rcBounds.Width();
}
}
else
{
if (IsVertical())
{
dValue = dMinValue + (double)(m_rcBounds.bottom - nPoint) * (dMaxValue - dMinValue) / m_rcBounds.Height() ;
}
else
{
dValue = dMinValue + (double)(nPoint - m_rcBounds.left) * (dMaxValue - dMinValue) / m_rcBounds.Width();
}
}
return AxisToValue(dValue);
}
double CXTPChartDiagram2DAxisView::ValueToPoint(double x) const
{
double dMinValue = GetAxisRangeMinValue();
double dMaxValue = GetAxisRangeMaxValue();
x = ValueToAxis(x);
BOOL bRevered = m_pAxis->IsReversed();
double dValue;
if (bRevered)
{
if (IsVertical())
{
dValue = m_rcBounds.top + (x - dMinValue) / (dMaxValue - dMinValue) * (m_rcBounds.Height());
}
else
{
dValue = m_rcBounds.right - (x - dMinValue) / (dMaxValue - dMinValue) * (m_rcBounds.Width());
}
}
else
{
if (IsVertical())
{
dValue = m_rcBounds.bottom - (x - dMinValue) / (dMaxValue - dMinValue) * (m_rcBounds.Height());
}
else
{
dValue = m_rcBounds.left + (x - dMinValue) / (dMaxValue - dMinValue) * (m_rcBounds.Width());
}
}
return CXTPMathUtils::Round(dValue);
}
CXTPChartDeviceCommand* CXTPChartDiagram2DAxisView::CreateTickMarksDeviceCommand(CXTPChartDeviceContext* pDC)
{
UNREFERENCED_PARAMETER(pDC);
CXTPChartDeviceCommand* pCommands = new CXTPChartHitTestElementCommand(m_pAxis, m_rcBounds);
CXTPChartAxisTickMarks* pTickMarks = m_pAxis->GetTickMarks();
if (!pTickMarks->IsVisible())
return pCommands;
int nScrollBarSize = IsScollBarVisible() ? SCROLLBARSIZE : 0;
CXTPChartColor clrAxis = m_pAxis->GetActualColor();
int nLength = pTickMarks->GetLength();
int nThickness = pTickMarks->GetThickness();
BOOL bMinorVisible = pTickMarks->IsMinorVisible();
BOOL bVertical = IsVertical();
BOOL bCross = pTickMarks->IsCrossAxis();
int nAxisThickness = m_pAxis->GetThickness() - 1 + nScrollBarSize;
int nExtraLength = bCross ? nLength + nAxisThickness : 0;
for (int i = 0; i < m_arrTicks.GetSize(); i++)
{
int nLeft = (int)ValueToPoint(m_arrTicks[i].m_dValue);
if (bVertical)
{
if (m_pAxis->GetAlignment() == xtpChartAxisNear)
pCommands->AddChildCommand(new CXTPChartSolidLineDeviceCommand(CXTPPoint3d(m_rcBounds.right - nAxisThickness - nLength, nLeft),
CXTPPoint3d(m_rcBounds.right - nAxisThickness + nExtraLength, nLeft), clrAxis, nThickness));
else
pCommands->AddChildCommand(new CXTPChartSolidLineDeviceCommand(CXTPPoint3d(m_rcBounds.left + nAxisThickness - nExtraLength, nLeft),
CXTPPoint3d(m_rcBounds.left + nAxisThickness + nLength, nLeft), clrAxis, nThickness));
}
else
{
if (m_pAxis->GetAlignment() == xtpChartAxisNear)
pCommands->AddChildCommand(new CXTPChartSolidLineDeviceCommand(CXTPPoint3d(nLeft, m_rcBounds.top + nAxisThickness - nExtraLength),
CXTPPoint3d(nLeft, m_rcBounds.top + nAxisThickness + nLength), clrAxis, nThickness));
else
pCommands->AddChildCommand(new CXTPChartSolidLineDeviceCommand(CXTPPoint3d(nLeft, m_rcBounds.bottom - nAxisThickness - nLength),
CXTPPoint3d(nLeft, m_rcBounds.bottom - nAxisThickness + nExtraLength), clrAxis, nThickness));
}
}
if (bMinorVisible)
{
nLength = pTickMarks->GetMinorLength();
int nExtraLength = bCross ? nLength + nAxisThickness : 0;
int nMinorThickness = pTickMarks->GetMinorThickness();
for (int i = 0; i < m_arrMinorTicks.GetSize(); i++)
{
int nLeft = (int)ValueToPoint(m_arrMinorTicks[i]);
if (bVertical)
{
if (m_pAxis->GetAlignment() == xtpChartAxisNear)
pCommands->AddChildCommand(new CXTPChartSolidLineDeviceCommand(CXTPPoint3d(m_rcBounds.right - nAxisThickness - nLength, nLeft),
CXTPPoint3d(m_rcBounds.right - nAxisThickness + nExtraLength, nLeft), clrAxis, nMinorThickness));
else
pCommands->AddChildCommand(new CXTPChartSolidLineDeviceCommand(CXTPPoint3d(m_rcBounds.left + nAxisThickness - nExtraLength, nLeft),
CXTPPoint3d(m_rcBounds.left + nAxisThickness + nLength, nLeft), clrAxis, nMinorThickness));
}
else
{
if (m_pAxis->GetAlignment() == xtpChartAxisNear)
pCommands->AddChildCommand(new CXTPChartSolidLineDeviceCommand(CXTPPoint3d(nLeft, m_rcBounds.top + nAxisThickness - nExtraLength),
CXTPPoint3d(nLeft, m_rcBounds.top + nAxisThickness + nLength), clrAxis, nMinorThickness));
else
pCommands->AddChildCommand(new CXTPChartSolidLineDeviceCommand(CXTPPoint3d(nLeft, m_rcBounds.bottom - nAxisThickness - nLength),
CXTPPoint3d(nLeft, m_rcBounds.bottom - nAxisThickness + nExtraLength), clrAxis, nMinorThickness));
}
}
}
return pCommands;
}
CXTPChartDeviceCommand* CXTPChartDiagram2DAxisView::CreateLabelsDeviceCommand(CXTPChartDeviceContext* pDC)
{
if (!m_pAxis->GetLabel()->IsVisible())
return NULL;
CXTPChartDeviceCommand* pLabelsCommand = new CXTPChartHitTestElementCommand(m_pAxis->GetLabel(), m_rcBounds);
CXTPChartColor clrAxis = m_pAxis->GetActualColor();
BOOL bVertical = IsVertical();
int nAngle = m_pAxis->GetLabel()->GetAngle();
BOOL bNear = m_pAxis->GetAlignment() == xtpChartAxisNear;
int nOffset = m_pAxis->GetThickness() + (m_pAxis->GetTickMarks()->IsVisible() ? m_pAxis->GetTickMarks()->GetLength() : 0)
+ (IsScollBarVisible() ? SCROLLBARSIZE : 0);
for (int i = 0; i < m_arrTicks.GetSize(); i++)
{
int nLeft = (int)ValueToPoint(m_arrTicks[i].m_dValue);
CXTPChartString s = m_arrTicks[i].m_strLabel;
if (bVertical)
{
CXTPChartRotatedTextPainterNearLine painter(pDC, s, m_pAxis->GetLabel(), CPoint(bNear ? m_rcBounds.right - nOffset : m_rcBounds.left + nOffset, nLeft), bNear ? xtpChartTextNearLeft : xtpChartTextNearRight, (float)nAngle);
pLabelsCommand->AddChildCommand(painter.CreateDeviceCommand(pDC, m_pAxis->GetLabel()->GetActualTextColor()));
}
else
{
CXTPChartRotatedTextPainterNearLine painter(pDC, s, m_pAxis->GetLabel(), CPoint(nLeft, bNear ? m_rcBounds.top + nOffset : m_rcBounds.bottom - nOffset), bNear ? xtpChartTextNearBottom : xtpChartTextNearTop, (float)nAngle);
pLabelsCommand->AddChildCommand(painter.CreateDeviceCommand(pDC, m_pAxis->GetLabel()->GetActualTextColor()));
}
}
return pLabelsCommand;
}
void CXTPChartDiagram2DAxisView::OnLButtonDown(UINT /*nFlags*/, CPoint point)
{
CXTPChartContainer* pContainer = m_pContainer;
ASSERT (pContainer);
if (m_rcScrollBar.GetLeft() > point.x || m_rcScrollBar.GetRight() < point.x)
return;
if (m_rcScrollBar.GetTop() > point.y || m_rcScrollBar.GetBottom() < point.y)
return;
m_pContainer->SetCapture(this);
m_ptOldPosition = point;
if (IsVertical())
{
double top = m_rcThumb.GetTop();
double bottom = m_rcThumb.GetBottom();
if (point.y < top || point.y > bottom)
{
double dy = !m_pAxis->IsReversed() ? (m_rcScrollBar.GetBottom() - point.y) : (point.y - m_rcScrollBar.GetTop());
double pos = dy * (ValueToAxis(GetRangeMaxValue()) - ValueToAxis(GetRangeMinValue()))
/ m_rcScrollBar.Height + ValueToAxis(GetRangeMinValue());
double delta = -(GetAxisRangeMinValue() - (pos - (GetAxisRangeMaxValue() - GetAxisRangeMinValue()) / 2));
if (GetAxisRangeMaxValue() + delta > ValueToAxis(GetRangeMaxValue()))
delta = ValueToAxis(GetRangeMaxValue()) - GetAxisRangeMaxValue();
if (GetAxisRangeMinValue() + delta < ValueToAxis(GetRangeMinValue()))
delta = ValueToAxis(GetRangeMinValue()) - GetAxisRangeMinValue();
m_pAxis->GetRange()->SetViewMaxValue(AxisToValue(GetAxisRangeMaxValue() + delta));
m_pAxis->GetRange()->SetViewMinValue(AxisToValue(GetAxisRangeMinValue() + delta));
}
}
else
{
double left = m_rcThumb.GetLeft();
double right = m_rcThumb.GetRight();
if (point.x < left || point.x > right)
{
double dx = !m_pAxis->IsReversed() ? (point.x - m_rcScrollBar.GetLeft()) : (m_rcScrollBar.GetRight() - point.x);
double pos = dx * (ValueToAxis(GetRangeMaxValue()) - ValueToAxis(GetRangeMinValue()))
/ m_rcScrollBar.Width + ValueToAxis(GetRangeMinValue());
double delta = -(GetAxisRangeMinValue() - (pos - (GetAxisRangeMaxValue() - GetAxisRangeMinValue()) / 2));
if (GetAxisRangeMaxValue() + delta > ValueToAxis(GetRangeMaxValue()))
delta = ValueToAxis(GetRangeMaxValue()) - GetAxisRangeMaxValue();
if (GetAxisRangeMinValue() + delta < ValueToAxis(GetRangeMinValue()))
delta = ValueToAxis(GetRangeMinValue()) - GetAxisRangeMinValue();
m_pAxis->GetRange()->SetViewMaxValue(AxisToValue(GetAxisRangeMaxValue() + delta));
m_pAxis->GetRange()->SetViewMinValue(AxisToValue(GetAxisRangeMinValue() + delta));
}
}
}
void CXTPChartDiagram2DAxisView::OnMouseMove(UINT /*nFlags*/, CPoint point)
{
int dx = point.x - m_ptOldPosition.x;
int dy = point.y - m_ptOldPosition.y;
m_ptOldPosition = point;
CXTPChartContainer* pContainer = m_pContainer;
ASSERT (pContainer);
m_pAxis->GetRange()->SetViewAutoRange(FALSE);
double dMinValue = ValueToAxis(GetRangeMinValue());
double dMaxValue = ValueToAxis(GetRangeMaxValue());
double dScale = 0;
if (IsVertical())
{
dScale = (m_rcBounds.Height()) / (dMaxValue - dMinValue);
}
else
{
dScale = (m_rcBounds.Width()) / (dMaxValue - dMinValue);
}
double delta = 1.0 / dScale;
if (IsVertical())
delta *= -dy;
else
delta *= dx;
if (m_pAxis->IsReversed())
delta *= -1;
if (GetAxisRangeMaxValue() + delta > dMaxValue)
delta = dMaxValue - GetAxisRangeMaxValue();
if (GetAxisRangeMinValue() + delta < dMinValue)
delta = dMinValue - GetAxisRangeMinValue();
m_pAxis->GetRange()->SetViewMaxValue(AxisToValue(GetAxisRangeMaxValue() + delta));
m_pAxis->GetRange()->SetViewMinValue(AxisToValue(GetAxisRangeMinValue() + delta));
}
void CXTPChartDiagram2DAxisView::PerformPaneDragging(int dx, int dy)
{
CXTPChartContainer* pContainer = m_pContainer;
ASSERT (pContainer);
m_pAxis->GetRange()->SetViewAutoRange(FALSE);
double delta = 1.0 / GetScale();
if (IsVertical())
delta *= dy;
else
delta *= -dx;
if (m_pAxis->IsReversed())
delta *= -1;
double dMinValue = ValueToAxis(GetRangeMinValue());
double dMaxValue = ValueToAxis(GetRangeMaxValue());
if (GetAxisRangeMaxValue() + delta > dMaxValue)
delta = dMaxValue - GetAxisRangeMaxValue();
if (GetAxisRangeMinValue() + delta < dMinValue)
delta = dMinValue - GetAxisRangeMinValue();
m_pAxis->GetRange()->SetViewMaxValue(AxisToValue(GetAxisRangeMaxValue() + delta));
m_pAxis->GetRange()->SetViewMinValue(AxisToValue(GetAxisRangeMinValue() + delta));
}
void CXTPChartDiagram2DAxisView::PerformMouseWheel(short zDelta, CPoint /*pt*/)
{
CXTPChartContainer* pContainer = m_pContainer;
ASSERT (pContainer);
if (!m_pAxis->IsAllowZoom())
return;
CXTPChartAxisRange* pRange = m_pAxis->GetRange();
pRange->SetViewAutoRange(FALSE);
double dRange = (GetAxisRangeMaxValue() - GetAxisRangeMinValue());
double delta = dRange / 10;
if (zDelta >= 0)
delta = -delta;
if (dRange - 2 * delta < pRange->GetZoomLimit())
{
delta = (dRange - pRange->GetZoomLimit()) / 2;
}
pRange->SetViewMaxValue(min(GetRangeMaxValue(), AxisToValue(GetAxisRangeMaxValue() - delta)));
pRange->SetViewMinValue(max(GetRangeMinValue(), AxisToValue(GetAxisRangeMinValue() + delta)));
}
CXTPChartDeviceCommand* CXTPChartDiagram2DAxisView::CreateScrollBarDeviceCommand(CXTPChartDeviceContext* /*pDC*/)
{
m_rcScrollBar = CXTPChartRectF(0, 0, 0, 0);
if (!IsScollBarVisible())
return NULL;
CXTPChartDeviceCommand* pCommand = new CXTPChartDeviceCommand();
CRect rcBounds = m_rcBounds;
int nSize = SCROLLBARSIZE;
if (IsVertical())
{
if (m_pAxis->GetAlignment() == xtpChartAxisNear)
{
rcBounds.left = rcBounds.right - nSize;
}
else
{
rcBounds.right = rcBounds.left + nSize;
}
}
else
{
if (m_pAxis->GetAlignment() == xtpChartAxisNear)
{
rcBounds.bottom = rcBounds.top + nSize;
}
else
{
rcBounds.top = rcBounds.bottom - nSize;
}
}
CXTPChartColor clrAxis = m_pAxis->GetActualColor();
pCommand->AddChildCommand(new CXTPChartSolidRectangleDeviceCommand(rcBounds, CXTPChartColor::White));
pCommand->AddChildCommand(new CXTPChartBoundedRectangleDeviceCommand(rcBounds, clrAxis, 1));
CXTPChartRectF rcScrollBar(rcBounds);
rcScrollBar.DeflateRect(1.5f, 1.5f, 1.5f, 1.5f);
double dRangeMaxValue = ValueToAxis(GetRangeMaxValue());
double dRangeMinValue = ValueToAxis(GetRangeMinValue());
double minValue = (GetAxisRangeMinValue() - dRangeMinValue) / (dRangeMaxValue - dRangeMinValue);
double maxValue = (GetAxisRangeMaxValue() - dRangeMinValue) / (dRangeMaxValue - dRangeMinValue);
const int MIN_BUTTON_SIZE = 15;
CXTPChartRectF rcThumb(rcScrollBar);
if (IsVertical())
{
double top, bottom;
if (!m_pAxis->IsReversed())
{
bottom = rcThumb.GetBottom() - rcThumb.Height * minValue;
top = rcThumb.GetBottom() - rcThumb.Height * maxValue;
}
else
{
top = rcThumb.GetTop() + rcThumb.Height * minValue;
bottom = rcThumb.GetTop() + rcThumb.Height * maxValue;
}
if (bottom - top < MIN_BUTTON_SIZE)
{
bottom = top + MIN_BUTTON_SIZE;
if (bottom > rcScrollBar.GetBottom())
{
bottom = rcScrollBar.GetBottom();
top = bottom - MIN_BUTTON_SIZE;
}
if (top < rcScrollBar.GetTop())
top = rcScrollBar.GetTop();
}
rcThumb.Y = (float)top;
rcThumb.Height = (float)(bottom - top);
}
else
{
double left, right;
if (!m_pAxis->IsReversed())
{
left = rcThumb.GetLeft() + rcThumb.Width * minValue;
right = rcThumb.GetLeft() + rcThumb.Width * maxValue;
}
else
{
right = rcThumb.GetRight() - rcThumb.Width * minValue;
left = rcThumb.GetRight() - rcThumb.Width * maxValue;
}
if (right - left < MIN_BUTTON_SIZE)
{
right = left + MIN_BUTTON_SIZE;
if (right > rcScrollBar.GetRight())
{
right = rcScrollBar.GetRight();
left = right - MIN_BUTTON_SIZE;
}
if (left < rcScrollBar.GetLeft())
left = rcScrollBar.GetLeft();
}
rcThumb.X = (float)left;
rcThumb.Width = (float)(right - left);
}
m_rcScrollBar = rcScrollBar;
m_rcThumb = rcThumb;
pCommand->AddChildCommand(new CXTPChartSolidRectangleDeviceCommand(rcThumb, clrAxis));
if (IsVertical())
{
if (rcThumb.Height > 10)
{
CXTPChartPointF pt = rcThumb.GetCenter();
pCommand->AddChildCommand(new CXTPChartSolidLineDeviceCommand(
CXTPPoint3d(pt.X - 1, pt.Y), CXTPPoint3d(pt.X + 1, pt.Y), CXTPChartColor::White, 1));
pCommand->AddChildCommand(new CXTPChartSolidLineDeviceCommand(
CXTPPoint3d(pt.X - 1, pt.Y - 2), CXTPPoint3d(pt.X + 1, pt.Y - 2), CXTPChartColor::White, 1));
pCommand->AddChildCommand(new CXTPChartSolidLineDeviceCommand(
CXTPPoint3d(pt.X - 1, pt.Y + 2), CXTPPoint3d(pt.X + 1, pt.Y + 2), CXTPChartColor::White, 1));
}
}
else
{
if (rcThumb.Width > 10)
{
CXTPChartPointF pt = rcThumb.GetCenter();
pCommand->AddChildCommand(new CXTPChartSolidLineDeviceCommand(
CXTPPoint3d(pt.X, pt.Y - 1), CXTPPoint3d(pt.X, pt.Y + 1), CXTPChartColor::White, 1));
pCommand->AddChildCommand(new CXTPChartSolidLineDeviceCommand(
CXTPPoint3d(pt.X - 2, pt.Y - 1), CXTPPoint3d(pt.X - 2, pt.Y + 1), CXTPChartColor::White, 1));
pCommand->AddChildCommand(new CXTPChartSolidLineDeviceCommand(
CXTPPoint3d(pt.X + 2, pt.Y - 1), CXTPPoint3d(pt.X + 2, pt.Y + 1), CXTPChartColor::White, 1));
}
}
return pCommand;
}
CXTPChartDeviceCommand* CXTPChartDiagram2DAxisView::CreateTitleDeviceCommand(CXTPChartDeviceContext* pDC)
{
CXTPChartAxisTitle* pTitle = GetAxis()->GetTitle();
if (!pTitle->IsVisible())
return NULL;
CXTPChartString strText = pTitle->GetText();
CXTPChartDeviceCommand* pCommand = new CXTPChartHitTestElementCommand(pTitle, m_rcBounds);
if (IsVertical())
{
if (m_pAxis->GetAlignment() == xtpChartAxisNear)
{
CXTPChartRotatedTextPainterNearLine painter(pDC, pTitle->GetText(), pTitle,
CPoint(m_rcBounds.left, m_rcBounds.CenterPoint().y), xtpChartTextNearRight, 270);
pCommand->AddChildCommand(painter.CreateDeviceCommand(pDC, pTitle->GetActualTextColor()));
}
else
{
CXTPChartRotatedTextPainterNearLine painter(pDC, pTitle->GetText(), pTitle,
CPoint(m_rcBounds.right, m_rcBounds.CenterPoint().y), xtpChartTextNearLeft, 90);
pCommand->AddChildCommand(painter.CreateDeviceCommand(pDC, pTitle->GetActualTextColor()));
}
}
else
{
if (m_pAxis->GetAlignment() == xtpChartAxisNear)
{
if (pTitle->GetAlignment() == xtpChartAlignCenter)
{
CXTPChartRotatedTextPainterNearLine painter(pDC, pTitle->GetText(), pTitle,
CPoint(m_rcBounds.CenterPoint().x, m_rcBounds.bottom + 3), xtpChartTextNearTop, 0);
pCommand->AddChildCommand(painter.CreateDeviceCommand(pDC, pTitle->GetActualTextColor()));
}
else
{
CXTPChartTextPainter painter(pDC, pTitle->GetText(), pTitle);
painter.SetLocation(CXTPChartPointF(pTitle->GetAlignment() == xtpChartAlignNear ? m_rcBounds.left :
m_rcBounds.right - painter.GetSize().Width, m_rcBounds.bottom + 3 - painter.GetSize().Height));
pCommand->AddChildCommand(painter.CreateDeviceCommand(pDC, pTitle->GetActualTextColor()));
}
}
else
{
CXTPChartRotatedTextPainterNearLine painter(pDC, pTitle->GetText(), pTitle,
CPoint(m_rcBounds.CenterPoint().x, m_rcBounds.top), xtpChartTextNearBottom, 0);
pCommand->AddChildCommand(painter.CreateDeviceCommand(pDC, pTitle->GetActualTextColor()));
}
}
return pCommand;
}
BOOL CXTPChartDiagram2DAxisView::IsScollBarVisible() const
{
if (m_pAxis->GetRange()->IsViewAutoRange())
return FALSE;
if (fabs(GetViewRangeMinValue() - GetRangeMinValue()) < CXTPMathUtils::m_dEPS &&
fabs(GetViewRangeMaxValue() - GetRangeMaxValue()) < CXTPMathUtils::m_dEPS)
return FALSE;
CXTPChartDiagram2D* pDiagram = DYNAMIC_DOWNCAST(CXTPChartDiagram2D, m_pAxis->GetDiagram());
if (!pDiagram)
return FALSE;
return pDiagram->IsAllowScroll();
}
CXTPChartDeviceCommand* CXTPChartDiagram2DAxisView::CreateDeviceCommand(CXTPChartDeviceContext* pDC)
{
CXTPChartDeviceCommand* pAxisCommand = new CXTPChartDeviceCommand();
CXTPChartColor clrAxis = m_pAxis->GetActualColor();
int nScrollBarSize = IsScollBarVisible() ? SCROLLBARSIZE : 0;
int nThickness = m_pAxis->GetThickness();
if (m_pAxis->IsVisible())
{
if (IsVertical())
{
float fPosition = m_pAxis->GetAlignment() == xtpChartAxisNear ? m_rcBounds.right - nScrollBarSize - nThickness / 2.0f + 0.5f : m_rcBounds.left + nScrollBarSize + nThickness / 2.0f - 0.5f;
pAxisCommand->AddChildCommand(new CXTPChartSolidLineDeviceCommand(CXTPPoint3d(fPosition, (float)m_rcBounds.top),
CXTPPoint3d(fPosition, m_rcBounds.bottom + 0.5f), clrAxis, m_pAxis->GetThickness()));
}
else
{
float fPosition = m_pAxis->GetAlignment() == xtpChartAxisNear ? m_rcBounds.top + nScrollBarSize + nThickness / 2.0f - 0.5f : m_rcBounds.bottom - nThickness / 2.0f + 0.5f - nScrollBarSize;
pAxisCommand->AddChildCommand(new CXTPChartSolidLineDeviceCommand(CXTPPoint3d(m_rcBounds.left, fPosition),
CXTPPoint3d(m_rcBounds.right + 0.5f, fPosition), clrAxis, nThickness));
}
pAxisCommand->AddChildCommand(CreateTickMarksDeviceCommand(pDC));
pAxisCommand->AddChildCommand(CreateLabelsDeviceCommand(pDC));
pAxisCommand->AddChildCommand(CreateTitleDeviceCommand(pDC));
pAxisCommand->AddChildCommand(CreateScrollBarDeviceCommand(pDC));
}
return pAxisCommand;
}
double CXTPChartAxisView::CalculateGridSpacing(double nAxisRangeDelta, double nScreenDelta, double nGridSpacingFactor)
{
if (m_pAxis->GetScaleType() == xtpChartScaleQualitative)
return 1.0;
double multipliers[] = { 1, 2, 3, 5 };
if (nScreenDelta <= 0)
return 1;
double deltaCoef = nGridSpacingFactor * nAxisRangeDelta / nScreenDelta;
if (deltaCoef < CXTPMathUtils::m_dEPS)
return 1;
if (deltaCoef > 1.0)
{
for (double factor = 1;; factor *= 10)
{
for (int i = 0; i < 4; i++) {
double result = multipliers[i] * factor;
if (deltaCoef <= result)
return result;
}
}
}
else
{
double result = 1;
if (m_pAxis->GetScaleType() == xtpChartScaleDateTime)
return result;
for (double factor = 0.1;; factor /= 10)
{
for (int i = 4 - 1; i >= 0; i--) {
double newResult = multipliers[i] * factor;
if (deltaCoef > newResult)
return result;
result = newResult;
}
}
}
}
void CXTPChartDiagram2DAxisView::SetBounds(CXTPChartDeviceContext* pDC, CRect rcBounds)
{
UNREFERENCED_PARAMETER(pDC);
m_rcBounds = rcBounds;
}
void CXTPChartDiagram2DAxisView::CreateTickMarks(CXTPChartDeviceContext* pDC, CRect rcDiagram)
{
UNREFERENCED_PARAMETER(pDC);
UNREFERENCED_PARAMETER(rcDiagram);
m_arrTicks.RemoveAll();
m_arrMinorTicks.RemoveAll();
double dViewMinValue = GetViewRangeMinValue();
double dViewMaxValue = GetViewRangeMaxValue();
double dAxisMinValue = GetAxisRangeMinValue();
double dAxisMaxValue = GetAxisRangeMaxValue();
double dGridSpacing = GetGridSpacing();
BOOL bVertical = IsVertical();
BOOL bNear = m_pAxis->GetAlignment() == xtpChartAxisNear;
int nAngle = m_pAxis->GetLabel()->GetAngle();
if (m_pAxis->GetCustomLabels()->GetCount() > 0)
{
CXTPChartAxisCustomLabels* pCustomLabels = m_pAxis->GetCustomLabels();
int nCount = pCustomLabels->GetCount();
for (int i = 0; i < nCount; i++)
{
CXTPChartAxisCustomLabel* pLabel = pCustomLabels->GetAt(i);
CXTPChartAxisViewTick tick;
tick.m_dValue = !pLabel->GetAxisValue().IsEmpty() ? m_pAxis->GetScaleTypeMap()->ValueToInternal(pLabel->GetAxisValue()) :
pLabel->GetAxisValueInternal();
if (tick.m_dValue >= dViewMinValue && tick.m_dValue <= dViewMaxValue)
{
tick.m_strLabel = pLabel->GetText();
CXTPChartRotatedTextPainterNearLine painter(pDC, tick.m_strLabel, m_pAxis->GetLabel(),
CPoint(0, 0), bVertical ? (bNear ? xtpChartTextNearLeft : xtpChartTextNearRight) :
(bNear ? xtpChartTextNearBottom : xtpChartTextNearTop), (float)nAngle);
tick.m_szLabel = painter.GetSize();
tick.m_szBounds = painter.GetRoundedBounds().Size();
m_arrTicks.Add(tick);
}
}
}
else
{
if (dAxisMinValue < -CXTPMathUtils::m_dEPS)
dAxisMinValue += -CXTPMathUtils::m_dEPS;
double dMark = ((int)(dAxisMinValue / dGridSpacing)) * dGridSpacing;
if (dMark < dAxisMinValue)
dMark += dGridSpacing;
while (dMark < dAxisMaxValue + CXTPMathUtils::m_dEPS)
{
CXTPChartAxisViewTick tick;
tick.m_dValue = AxisToValue(dMark);
tick.m_strLabel = m_pAxis->GetScaleTypeMap()->InternalToValue(m_pAxis->GetLabel()->GetFormat(), tick.m_dValue);
CXTPChartRotatedTextPainterNearLine painter(pDC, tick.m_strLabel, m_pAxis->GetLabel(),
CPoint(0, 0), bVertical ? (bNear ? xtpChartTextNearLeft : xtpChartTextNearRight) :
(bNear ? xtpChartTextNearBottom : xtpChartTextNearTop), (float)nAngle);
tick.m_szLabel = painter.GetSize();
tick.m_szBounds = painter.GetRoundedBounds().Size();
m_arrTicks.Add(tick);
dMark += dGridSpacing;
}
int nMinorCount = m_pAxis->GetMinorCount();
if (m_arrTicks.GetSize() > 0 && nMinorCount > 0)
{
double cur, prev;
for (int i = 0; i <= m_arrTicks.GetSize(); i++)
{
if (m_pAxis->IsLogarithmic())
{
cur = i == m_arrTicks.GetSize() ? m_arrTicks[i - 1].m_dValue * m_pAxis->GetLogarithmicBase() :
m_arrTicks[i].m_dValue;
prev = i == 0 ? m_arrTicks[0].m_dValue / m_pAxis->GetLogarithmicBase() : m_arrTicks[i - 1].m_dValue;
}
else
{
cur = i == m_arrTicks.GetSize() ? m_arrTicks[i - 1].m_dValue + dGridSpacing : m_arrTicks[i].m_dValue;
prev = i == 0 ? cur - dGridSpacing : m_arrTicks[i - 1].m_dValue;
}
for (int j = 0; j < nMinorCount; j++)
{
double dValue = prev + (cur - prev) * (j + 1) / (nMinorCount + 1);
if (dValue >= dViewMinValue && dValue <= dViewMaxValue)
{
m_arrMinorTicks.Add(dValue);
}
}
}
}
}
}
void CXTPChartDiagram2DAxisView::CalcSize(CXTPChartDeviceContext* pDC, CRect rcDiagram)
{
CXTPChartAxis* pAxis = GetAxis();
double dScreenLength = IsVertical() ? rcDiagram.Height() : rcDiagram.Width();
if (dScreenLength < 1)
{
m_nSize = 0;
return;
}
if (pAxis->GetGridSpacingAuto())
{
double dRangeDelta = GetAxisRangeMaxValue() - GetAxisRangeMinValue();
m_dGridSpacing = CalculateGridSpacing(dRangeDelta, dScreenLength, IsVertical() ? 30 : 50);
if (pAxis->IsLogarithmic())
m_dGridSpacing = max(1, m_dGridSpacing);
}
else
{
m_dGridSpacing = pAxis->GetGridSpacing();
}
pAxis->m_dGridSpacing = m_dGridSpacing;
CreateTickMarks(pDC, rcDiagram);
if (!pAxis->IsVisible())
{
m_nSize = 0;
return;
}
BOOL bVertical = IsVertical();
m_nSize = pAxis->GetThickness();
if (pAxis->GetTickMarks()->IsVisible())
{
m_nSize += pAxis->GetTickMarks()->GetLength();
}
if (IsScollBarVisible())
{
m_nSize += SCROLLBARSIZE;
}
if (pAxis->GetLabel()->IsVisible())
{
int nLabelSize = 0;
for (int i = 0; i < m_arrTicks.GetSize(); i++)
{
CSize szBounds = m_arrTicks[i].m_szBounds;
nLabelSize = max(nLabelSize, bVertical ? szBounds.cx : szBounds.cy);
}
m_nSize += nLabelSize;
}
if (pAxis->GetTitle()->IsVisible())
{
CXTPChartAxisTitle* pTitle = GetAxis()->GetTitle();
CXTPChartString strText = pTitle->GetText();
BOOL bNear = m_pAxis->GetAlignment() == xtpChartAxisNear;
CXTPChartRotatedTextPainterNearLine painter(pDC, pTitle->GetText(), pTitle,
CPoint(0, 0), IsVertical() ? (bNear ? xtpChartTextNearRight : xtpChartTextNearLeft) :
(bNear ? xtpChartTextNearTop : xtpChartTextNearBottom), (float)(IsVertical() ? (bNear ? 270 : 90) : 0));
CSize szTitle = painter.GetRoundedBounds().Size();
m_nSize += bVertical ? szTitle.cx : szTitle.cy;
}
}
BOOL CXTPChartDiagram2DAxisView::IsVertical() const
{
return m_pAxis->IsVertical();
}
void CXTPChartDiagram2DAxisView::CreateView(CXTPChartDeviceContext* pDC)
{
UNREFERENCED_PARAMETER(pDC);
}
void CXTPChartAxisView::AddLegendItems()
{
CXTPChartElementView* pParentView = m_pParentView;
while (pParentView->GetParentView() != NULL)
pParentView = pParentView->GetParentView();
CXTPChartContentView* pContentView = (CXTPChartContentView*)pParentView;
if (pContentView->GetLegendView())
{
CXTPChartAxisConstantLines* pConstantLines = m_pAxis->GetConstantLines();
int i;
for (i = 0; i < pConstantLines->GetCount(); i++)
{
CXTPChartAxisConstantLine* pConstantLine = pConstantLines->GetAt(i);
if (!pConstantLine->IsVisible() || !pConstantLine->IsLegendVisible())
continue;
pContentView->GetLegendView()->AddItem(pConstantLine);
}
CXTPChartAxisStrips* pStrips = m_pAxis->GetStrips();
for (i = 0; i < pStrips->GetCount(); i++)
{
CXTPChartAxisStrip* pStrip = pStrips->GetAt(i);
if (!pStrip->IsVisible() || !pStrip->IsLegendVisible())
continue;
pContentView->GetLegendView()->AddItem(pStrip);
}
}
}