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++
1347 lines
38 KiB
C++
2 years ago
|
// 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);
|
||
|
}
|
||
|
}
|
||
|
}
|