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.
694 lines
21 KiB
C++
694 lines
21 KiB
C++
// XTPChartPieSeriesLabel.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 "Common/XTPPropExchange.h"
|
|
|
|
#include "../../Types/XTPChartTypes.h"
|
|
#include "Common/Base/Types/XTPPoint3.h"
|
|
#include "../../Types/XTPChartPie.h"
|
|
|
|
#include "../../XTPChartDefines.h"
|
|
#include "../../XTPChartElement.h"
|
|
#include <Chart/XTPChartLegendItem.h>
|
|
#include "../../XTPChartElementView.h"
|
|
#include "../../XTPChartSeriesLabel.h"
|
|
#include "../../XTPChartSeriesStyle.h"
|
|
#include "../../XTPChartSeriesView.h"
|
|
#include "../../XTPChartPanel.h"
|
|
#include "../../XTPChartDiagram.h"
|
|
#include <Chart/XTPChartSeriesPointView.h>
|
|
|
|
#include "../../Appearance/XTPChartFillStyle.h"
|
|
#include "../../Appearance/XTPChartBorder.h"
|
|
|
|
#include "../../Drawing/XTPChartDeviceCommand.h"
|
|
#include "../../Drawing/XTPChartTransformationDeviceCommand.h"
|
|
#include "../../Drawing/XTPChartLineDeviceCommand.h"
|
|
|
|
#include <Common/XTPMathUtils.h>
|
|
#include "../../Utils/XTPChartTextPainter.h"
|
|
|
|
#include "XTPChartPieDiagram.h"
|
|
#include "XTPChartPieSeriesLabel.h"
|
|
#include "XTPChartPieSeriesStyle.h"
|
|
#include "XTPChartPieSeriesPointView.h"
|
|
#include "XTPChartPieSeriesView.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CXTPChartPieSeriesLabel
|
|
|
|
IMPLEMENT_SERIAL(CXTPChartPieSeriesLabel, CXTPChartSeriesLabel, VERSIONABLE_SCHEMA | _XTP_SCHEMA_CURRENT)
|
|
|
|
CXTPChartPieSeriesLabel::CXTPChartPieSeriesLabel()
|
|
{
|
|
m_nPosition = xtpChartPieLabelOutside;
|
|
}
|
|
|
|
CXTPChartPieSeriesLabel::~CXTPChartPieSeriesLabel()
|
|
{
|
|
}
|
|
|
|
CXTPChartPieSeriesStyleBase* CXTPChartPieSeriesLabel::GetStyle() const
|
|
{
|
|
return (CXTPChartPieSeriesStyleBase*)m_pOwner;
|
|
}
|
|
|
|
void CXTPChartPieSeriesLabel::DoPropExchange(CXTPPropExchange* pPX)
|
|
{
|
|
CXTPChartSeriesLabel::DoPropExchange(pPX);
|
|
|
|
PX_Enum(pPX, _T("Position"), m_nPosition, xtpChartPieLabelOutside);
|
|
}
|
|
|
|
CXTPChartPieSeriesLabelsView::CXTPChartPieSeriesLabelsView(CXTPChartElementView* pParentView)
|
|
: CXTPChartElementView(pParentView)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CView;
|
|
|
|
class CXTPChartPieSeriesLabelView : public CXTPChartSeriesLabelView
|
|
{
|
|
public:
|
|
CXTPChartPieSeriesLabelView(CXTPChartSeriesLabel* pLabel, CXTPChartSeriesPointView* pPointView, CXTPChartElementView* pParentView);
|
|
|
|
public:
|
|
XTPChartPieLabelPosition GetPosition() const;
|
|
|
|
protected:
|
|
virtual void CalculateLayout(CXTPChartDeviceContext* pDC);
|
|
virtual CXTPChartDeviceCommand* CreateDeviceCommand(CXTPChartDeviceContext* pDC);
|
|
|
|
CXTPChartDeviceCommand* CreateConnectorDeviceCommand(CXTPChartDeviceContext* pDC);
|
|
|
|
protected:
|
|
CXTPChartRectF m_rcBounds;
|
|
CXTPChartPointF m_ptStartPoint;
|
|
double m_dLineAngle;
|
|
|
|
|
|
friend class CXTPChartPieSeriesLabelsView;
|
|
};
|
|
|
|
|
|
CXTPChartDeviceCommand* CXTPChartPieSeriesLabelsView::CreateDeviceCommand(CXTPChartDeviceContext* pDC)
|
|
{
|
|
CXTPChartDeviceCommand* pDrawingType = new CXTPChartDeviceCommand();
|
|
|
|
int i;
|
|
for (i = 0; i < m_arrChildren.GetSize(); i++)
|
|
{
|
|
CXTPChartPieSeriesLabelView* pChildView =(CXTPChartPieSeriesLabelView*)m_arrChildren[i];
|
|
pDrawingType->AddChildCommand(pChildView->CreateConnectorDeviceCommand(pDC));
|
|
}
|
|
|
|
for (i = 0; i < m_arrChildren.GetSize(); i++)
|
|
{
|
|
CXTPChartPieSeriesLabelView* pChildView =(CXTPChartPieSeriesLabelView*)m_arrChildren[i];
|
|
pDrawingType->AddChildCommand(pChildView->CreateDeviceCommand(pDC));
|
|
}
|
|
|
|
|
|
return pDrawingType;
|
|
}
|
|
|
|
void CXTPChartPieSeriesLabelsView::ResolveOverlappingColumn(CArray<CXTPChartPieSeriesLabelView*, CXTPChartPieSeriesLabelView*>& arrColumn)
|
|
{
|
|
if (arrColumn.GetSize() < 2)
|
|
return;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < arrColumn.GetSize(); i++)
|
|
{
|
|
double& lineAngle = arrColumn[i]->m_dLineAngle;
|
|
|
|
if (lineAngle >= CXTPMathUtils::m_dPI / 2 && lineAngle <= 3 * CXTPMathUtils::m_dPI / 2)
|
|
{
|
|
|
|
}
|
|
else
|
|
{
|
|
if (lineAngle > 3 * CXTPMathUtils::m_dPI / 2)
|
|
lineAngle -= CXTPMathUtils::m_dPI * 2;
|
|
lineAngle = -lineAngle;
|
|
}
|
|
}
|
|
|
|
// Yeah, bubble sort, but we're not waiting more than 20 labels here.
|
|
for (i = 0; i < arrColumn.GetSize(); i++)
|
|
{
|
|
for (int j = 0; j < i; j++)
|
|
{
|
|
if (arrColumn[i]->m_dLineAngle < arrColumn[j]->m_dLineAngle)
|
|
{
|
|
CXTPChartPieSeriesLabelView* p = arrColumn[i];
|
|
arrColumn[i] = arrColumn[j];
|
|
arrColumn[j] = p;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
CXTPChartPieSeriesView* pSeriesView = (CXTPChartPieSeriesView*)arrColumn[0]->GetPointView()->GetSeriesView();
|
|
CRect rcBounds = pSeriesView->GetBounds();
|
|
|
|
|
|
for (i = (int)arrColumn.GetSize() - 2; i >= 0; i--)
|
|
{
|
|
CXTPChartRectF& rcBounds = arrColumn[i]->m_rcBounds;
|
|
|
|
if (arrColumn[i]->m_ptStartPoint.Y < rcBounds.GetCenter().Y)
|
|
continue;
|
|
|
|
if (rcBounds.GetBottom() + 2 > arrColumn[i + 1]->m_rcBounds.GetTop())
|
|
{
|
|
rcBounds.Y = arrColumn[i + 1]->m_rcBounds.GetTop() - 2 - rcBounds.Height;
|
|
}
|
|
}
|
|
|
|
if (arrColumn[0]->m_rcBounds.GetTop() < rcBounds.top)
|
|
arrColumn[0]->m_rcBounds.Y = (float)rcBounds.top;
|
|
|
|
|
|
for (i = 1; i < arrColumn.GetSize(); i++)
|
|
{
|
|
CXTPChartRectF& rcBounds = arrColumn[i]->m_rcBounds;
|
|
|
|
if (rcBounds.GetTop() < arrColumn[i - 1]->m_rcBounds.GetBottom() + 2)
|
|
{
|
|
rcBounds.Y = arrColumn[i - 1]->m_rcBounds.GetBottom() + 2;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void CXTPChartPieSeriesLabelsView::ResolveOverlapping()
|
|
{
|
|
if (m_arrChildren.GetSize() == 0)
|
|
return;
|
|
|
|
if (((CXTPChartPieSeriesLabelView*)GetAt(0))->GetPosition() != xtpChartPieLabelTwoColumns)
|
|
return;
|
|
|
|
|
|
CXTPChartPieSeriesView* pSeriesView = (CXTPChartPieSeriesView*)((CXTPChartPieSeriesLabelView*)GetAt(0))->GetPointView()->GetSeriesView();
|
|
CXTPChartRectF rcInnerBounds = pSeriesView->GetInnerBounds();
|
|
int nCenter = (int)rcInnerBounds.GetCenter().X;
|
|
|
|
|
|
CArray<CXTPChartPieSeriesLabelView*, CXTPChartPieSeriesLabelView*> arrColumn;
|
|
int i;
|
|
|
|
|
|
for (i = 0; i < m_arrChildren.GetSize(); i++)
|
|
{
|
|
CXTPChartPieSeriesLabelView* pView = (CXTPChartPieSeriesLabelView*)m_arrChildren[i];
|
|
if (pView->m_rcBounds.GetLeft() > nCenter)
|
|
{
|
|
arrColumn.Add(pView);
|
|
}
|
|
}
|
|
ResolveOverlappingColumn(arrColumn);
|
|
|
|
arrColumn.RemoveAll();
|
|
|
|
|
|
for (i = 0; i < m_arrChildren.GetSize(); i++)
|
|
{
|
|
CXTPChartPieSeriesLabelView* pView = (CXTPChartPieSeriesLabelView*)m_arrChildren[i];
|
|
if (!(pView->m_rcBounds.GetLeft() > nCenter))
|
|
{
|
|
arrColumn.Add(pView);
|
|
}
|
|
}
|
|
|
|
ResolveOverlappingColumn(arrColumn);
|
|
}
|
|
|
|
CXTPChartPieSeriesLabelView::CXTPChartPieSeriesLabelView(CXTPChartSeriesLabel* pLabel, CXTPChartSeriesPointView* pPointView, CXTPChartElementView* pParentView)
|
|
: CXTPChartSeriesLabelView(pLabel, pPointView, pParentView)
|
|
{
|
|
|
|
}
|
|
|
|
void CXTPChartPieSeriesLabelView::CalculateLayout(CXTPChartDeviceContext* pDC)
|
|
{
|
|
UNREFERENCED_PARAMETER(pDC);
|
|
|
|
XTPChartPieLabelPosition position = GetPosition();
|
|
|
|
if (position != xtpChartPieLabelTwoColumns) // Smart labels implemented for TwoColumns mode only.
|
|
return;
|
|
|
|
double lineAngle;
|
|
|
|
int borderThickness = m_pLabel->GetBorder()->GetThickness();
|
|
|
|
CXTPChartRectF realBounds(((CXTPChartPieSeriesPointView*)m_pPointView)->GetPie()->GetBounds());
|
|
|
|
if (realBounds.Width < 1 || realBounds.Height < 1)
|
|
return;
|
|
|
|
CXTPChartPointF anchorPoint = ((CXTPChartPieSeriesLabel*)m_pLabel)->CalculateAnchorPointAndAngles((CXTPChartPieSeriesPointView*)m_pPointView,
|
|
borderThickness, lineAngle);
|
|
|
|
|
|
CXTPChartString text(m_pLabel->GetPointLabel(m_pPointView->GetPoint()));
|
|
if (text.IsEmpty() || text == _T(" "))
|
|
return;
|
|
|
|
if (position == xtpChartPieLabelInside)
|
|
{
|
|
|
|
}
|
|
else if (position == xtpChartPieLabelRadial)
|
|
{
|
|
|
|
}
|
|
|
|
else if (position == xtpChartPieLabelOutside)
|
|
{
|
|
|
|
}
|
|
else if (position == xtpChartPieLabelTwoColumns)
|
|
{
|
|
CXTPChartPieSeriesView* pSeriesView = (CXTPChartPieSeriesView*)m_pPointView->GetSeriesView();
|
|
CXTPChartRectF rcInnerBounds = pSeriesView->GetInnerBounds();
|
|
|
|
|
|
CXTPChartTextPainter painter(pDC, text, m_pLabel);
|
|
CXTPChartSizeF size = painter.GetSize();
|
|
|
|
CXTPChartPointF startPoint(anchorPoint);
|
|
|
|
CXTPChartPointF finishPoint(anchorPoint.X + (float)(cos(lineAngle) * m_pLabel->GetLineLength()),
|
|
anchorPoint.Y - (float)(sin(lineAngle) * m_pLabel->GetLineLength()));
|
|
|
|
CXTPChartPointF finishPoint2;
|
|
|
|
CXTPChartRectF bounds(0, 0, (float)floor(size.Width + 2 * borderThickness), (float)floor(size.Height + 2 * borderThickness));
|
|
|
|
bounds.Y = (float)(int)(finishPoint.Y - bounds.Height / 2);
|
|
|
|
if (lineAngle < 0) lineAngle += 2 * CXTPMathUtils::m_dPI;
|
|
|
|
if (lineAngle >= CXTPMathUtils::m_dPI / 2 && lineAngle <= 3 * CXTPMathUtils::m_dPI / 2)
|
|
{
|
|
bounds.X = (float)(int)(rcInnerBounds.GetLeft() - pSeriesView->GetMaxLabelWidth());
|
|
finishPoint2 = CXTPChartPointF(bounds.GetRight(), finishPoint.Y);
|
|
|
|
if (finishPoint.X < finishPoint2.X)
|
|
finishPoint = finishPoint2;
|
|
}
|
|
else
|
|
{
|
|
bounds.X = (float)(int)(rcInnerBounds.GetRight() + pSeriesView->GetMaxLabelWidth() - bounds.Width);
|
|
finishPoint2 = CXTPChartPointF(bounds.X, finishPoint.Y);
|
|
|
|
if (finishPoint.X > finishPoint2.X)
|
|
finishPoint = finishPoint2;
|
|
}
|
|
m_rcBounds = bounds;
|
|
m_ptStartPoint = startPoint;
|
|
m_dLineAngle = lineAngle;
|
|
}
|
|
|
|
}
|
|
|
|
BOOL CXTPChartPieSeriesLabel::IsInside() const
|
|
{
|
|
XTPChartPieLabelPosition position = GetPosition();
|
|
return position == xtpChartPieLabelInside || position == xtpChartPieLabelRadial;
|
|
|
|
}
|
|
|
|
XTPChartPieLabelPosition CXTPChartPieSeriesLabelView::GetPosition() const
|
|
{
|
|
return ((CXTPChartPieSeriesLabel*)m_pLabel)->GetPosition();
|
|
}
|
|
|
|
|
|
CXTPChartPointF CXTPChartPieSeriesLabel::CalculateAnchorPointAndAngles(CXTPChartPieSeriesPointView* pPointView,
|
|
int borderThickness, double& lineAngle)
|
|
{
|
|
UNREFERENCED_PARAMETER(borderThickness);
|
|
lineAngle = pPointView->GetPie()->GetHalfAngle();
|
|
|
|
int nHolePercent = pPointView->GetPie()->GetHolePercent();
|
|
|
|
if (nHolePercent > 0 && IsInside())
|
|
{
|
|
double fraction = nHolePercent / 100.0;
|
|
double width = pPointView->GetPie()->GetBounds().Width / 2.0;
|
|
double height = pPointView->GetPie()->GetBounds().Height / 2.0;
|
|
double minWidth = width * fraction;
|
|
double minHeight = height * fraction;
|
|
if (minWidth <= 0.0 || minHeight <= 0.0)
|
|
return CXTPChartPointF(0, 0);
|
|
|
|
double startAngle = pPointView->GetPie()->GetStartAngle();
|
|
double halfAngle = pPointView->GetPie()->GetHalfAngle();
|
|
CXTPPoint3d center = pPointView->GetPie()->CalculateCenter(pPointView->GetBasePoint());
|
|
CXTPChartEllipse maxEllipse(center, width, height);
|
|
CXTPChartEllipse minEllipse(center, minWidth, minHeight);
|
|
CXTPChartPie maxPie(startAngle, halfAngle, maxEllipse, 0, 0);
|
|
CXTPChartPie minPie(startAngle, halfAngle, minEllipse, 0, 0);
|
|
return CXTPChartPointF((maxPie.GetFinishPoint().X + minPie.GetFinishPoint().X) / 2.0f, (maxPie.GetFinishPoint().Y + minPie.GetFinishPoint().Y) / 2.0f);
|
|
|
|
}
|
|
|
|
CXTPChartRectF realBounds(pPointView->GetPie()->GetBounds());
|
|
|
|
CXTPChartEllipse actualEllipse(pPointView->GetPie()->CalculateCenter(pPointView->GetBasePoint()), realBounds.Width / 2, realBounds.Height / 2);
|
|
CXTPChartPie actualPie(pPointView->GetPie()->GetStartAngle(), pPointView->GetPie()->GetHalfAngle(), actualEllipse, 0, 0);
|
|
|
|
if (!IsInside())
|
|
{
|
|
return actualPie.GetFinishPoint();
|
|
}
|
|
|
|
if (pPointView->m_dValue == 1)
|
|
{
|
|
lineAngle = 0;
|
|
return actualPie.GetCenterPoint();
|
|
}
|
|
|
|
return CXTPChartPointF((actualPie.GetCenterPoint().X + actualPie.GetFinishPoint().X) / 2.0f, (actualPie.GetCenterPoint().Y + actualPie.GetFinishPoint().Y) / 2.0f);
|
|
}
|
|
|
|
CXTPChartDeviceCommand* CXTPChartPieSeriesLabelView::CreateConnectorDeviceCommand(CXTPChartDeviceContext* pDC)
|
|
{
|
|
XTPChartPieLabelPosition position = GetPosition();
|
|
|
|
if (position == xtpChartPieLabelInside || position == xtpChartPieLabelRadial)
|
|
return NULL;
|
|
|
|
CXTPChartDeviceCommand* pCommand = new CXTPChartDeviceCommand();
|
|
|
|
double lineAngle;
|
|
|
|
int borderThickness = m_pLabel->GetBorder()->GetThickness();
|
|
|
|
CXTPChartRectF realBounds(((CXTPChartPieSeriesPointView*)m_pPointView)->GetPie()->GetBounds());
|
|
|
|
if (realBounds.Width < 1 || realBounds.Height < 1)
|
|
return pCommand;
|
|
|
|
CXTPChartPointF anchorPoint = ((CXTPChartPieSeriesLabel*)m_pLabel)->CalculateAnchorPointAndAngles((CXTPChartPieSeriesPointView*)m_pPointView,
|
|
borderThickness, lineAngle);
|
|
|
|
|
|
CXTPChartString text(m_pLabel->GetPointLabel(m_pPointView->GetPoint()));
|
|
if (text.IsEmpty() || text == _T(" "))
|
|
return pCommand;
|
|
|
|
CXTPChartColor clrTextColor = GetActualTextColor();
|
|
|
|
if (position == xtpChartPieLabelOutside)
|
|
{
|
|
CXTPChartTextPainter painter(pDC, text, m_pLabel);
|
|
CXTPChartSizeF size = painter.GetSize();
|
|
|
|
CXTPChartPointF startPoint(anchorPoint);
|
|
CXTPChartPointF finishPoint(anchorPoint.X + (float)(cos(lineAngle) * m_pLabel->GetLineLength()),
|
|
anchorPoint.Y - (float)(sin(lineAngle) * m_pLabel->GetLineLength()));
|
|
|
|
CXTPChartRectF innerBounds;
|
|
CXTPChartRectF bounds = CXTPChartSeriesLabelConnectorPainterBase::CalcBorderBoundsForTangentDrawing(finishPoint, lineAngle, size, borderThickness, innerBounds);
|
|
bounds.Round();
|
|
innerBounds.Round();
|
|
|
|
if (m_pLabel->GetShowLines())
|
|
{
|
|
CXTPChartColor clrConnectorColor = GetActualConnectorColor();
|
|
|
|
CXTPChartSeriesLabelLineConnectorPainter linePainter(startPoint, finishPoint, lineAngle, bounds);
|
|
pCommand->AddChildCommand(linePainter.CreateDeviceCommand(pDC, m_pLabel, clrConnectorColor));
|
|
}
|
|
}
|
|
else if (position == xtpChartPieLabelTwoColumns)
|
|
{
|
|
CXTPChartRectF bounds = m_rcBounds;
|
|
|
|
if (m_pLabel->GetShowLines())
|
|
{
|
|
CXTPChartPointF startPoint(anchorPoint);
|
|
CXTPChartPointF finishPoint;
|
|
CXTPChartPointF breakPoint;
|
|
|
|
breakPoint.Y = finishPoint.Y = bounds.GetCenter().Y;
|
|
|
|
double sn = sin(lineAngle);
|
|
|
|
if (m_rcBounds.GetLeft() >= anchorPoint.X)
|
|
{
|
|
breakPoint.X = finishPoint.X = bounds.GetLeft();
|
|
|
|
if (CXTPMathUtils::Compare(sn, 0, 0.1) != 0)
|
|
{
|
|
double lineLength = (startPoint.Y - finishPoint.Y) / sn;
|
|
|
|
breakPoint.X = startPoint.X + (float)(cos(lineAngle) * lineLength);
|
|
|
|
if (breakPoint.X > finishPoint.X || breakPoint.X < startPoint.X)
|
|
breakPoint.X = finishPoint.X;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
breakPoint.X = finishPoint.X = bounds.GetRight();
|
|
|
|
if (CXTPMathUtils::Compare(sn, 0, 0.1) != 0)
|
|
{
|
|
double lineLength = (startPoint.Y - finishPoint.Y) / sn;
|
|
|
|
breakPoint.X = startPoint.X + (float)(cos(lineAngle) * lineLength);
|
|
|
|
if (breakPoint.X < finishPoint.X || breakPoint.X > startPoint.X)
|
|
breakPoint.X = finishPoint.X;
|
|
}
|
|
|
|
}
|
|
|
|
CXTPChartColor clrConnectorColor = GetActualConnectorColor();
|
|
|
|
CXTPChartDeviceCommand* pContaier = new CXTPChartPolygonAntialiasingDeviceCommand();
|
|
pContaier->AddChildCommand(new CXTPChartSolidLineDeviceCommand(startPoint, breakPoint, clrConnectorColor, 1));
|
|
pContaier->AddChildCommand(new CXTPChartSolidLineDeviceCommand(breakPoint, finishPoint, clrConnectorColor, 1));
|
|
|
|
pCommand->AddChildCommand(pContaier);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
return pCommand;
|
|
}
|
|
|
|
CXTPChartDeviceCommand* CXTPChartPieSeriesLabelView::CreateDeviceCommand(CXTPChartDeviceContext* pDC)
|
|
{
|
|
|
|
CXTPChartDeviceCommand* pCommand = new CXTPChartHitTestElementCommand(m_pLabel);
|
|
|
|
double lineAngle;
|
|
|
|
int borderThickness = m_pLabel->GetBorder()->GetThickness();
|
|
|
|
CXTPChartRectF realBounds(((CXTPChartPieSeriesPointView*)m_pPointView)->GetPie()->GetBounds());
|
|
|
|
if (realBounds.Width < 1 || realBounds.Height < 1)
|
|
return pCommand;
|
|
|
|
CXTPChartPointF anchorPoint = ((CXTPChartPieSeriesLabel*)m_pLabel)->CalculateAnchorPointAndAngles((CXTPChartPieSeriesPointView*)m_pPointView,
|
|
borderThickness, lineAngle);
|
|
|
|
XTPChartPieLabelPosition position = GetPosition();
|
|
|
|
CXTPChartString text(m_pLabel->GetPointLabel(m_pPointView->GetPoint()));
|
|
if (text.IsEmpty() || text == _T(" "))
|
|
return pCommand;
|
|
|
|
CXTPChartColor clrTextColor = GetActualTextColor();
|
|
|
|
if (position == xtpChartPieLabelInside)
|
|
{
|
|
CXTPChartTextPainter painter(pDC, text, m_pLabel);
|
|
CXTPChartSizeF size = painter.GetSize();
|
|
|
|
CXTPChartRectF bounds(0, 0, size.Width + 2 * borderThickness, size.Height + 2 * borderThickness);
|
|
bounds.Offset(anchorPoint.X - bounds.Width / 2, anchorPoint.Y - bounds.Height / 2);
|
|
bounds.Round();
|
|
|
|
CXTPChartRectF innerBounds = bounds;
|
|
innerBounds.Inflate((float)-borderThickness, (float)-borderThickness);
|
|
|
|
CXTPChartPointF labelPoint = innerBounds.GetLocation();
|
|
|
|
CXTPChartColor clrBackColor = m_pLabel->GetActualBackColor();
|
|
pCommand->AddChildCommand(m_pLabel->GetFillStyle()->CreateDeviceCommand(bounds, clrBackColor, clrBackColor));
|
|
|
|
painter.SetLocation(labelPoint);
|
|
|
|
pCommand->AddChildCommand(painter.CreateDeviceCommand(pDC, clrTextColor));
|
|
|
|
if (borderThickness)
|
|
{
|
|
CXTPChartColor clrBorderColor = GetActualBorderColor();
|
|
|
|
pCommand->AddChildCommand(m_pLabel->GetBorder()->CreateDeviceCommand(bounds, clrBorderColor));
|
|
}
|
|
}
|
|
else if (position == xtpChartPieLabelRadial)
|
|
{
|
|
CXTPChartTextPainter painter(pDC, text, m_pLabel);
|
|
CXTPChartSizeF size = painter.GetSize();
|
|
|
|
CXTPChartRectF bounds(0, 0, size.Width + 2 * borderThickness, size.Height + 2 * borderThickness);
|
|
bounds.Offset(- bounds.Width / 2, - bounds.Height / 2);
|
|
bounds.Round();
|
|
|
|
CXTPChartRectF innerBounds = bounds;
|
|
innerBounds.Inflate((float)-borderThickness, (float)-borderThickness);
|
|
|
|
float fAngle = (float)(-(int)CXTPMathUtils::Radian2Degree(lineAngle) + 90);
|
|
fAngle = (float)CXTPMathUtils::NormalizeDegree(fAngle);
|
|
|
|
fAngle = fAngle <= 180 ? fAngle - 90 : fAngle + 90;
|
|
|
|
CXTPChartDeviceCommand* pStateGraphicsCommand = pCommand->AddChildCommand(new CXTPChartSaveStateDeviceCommand());
|
|
pStateGraphicsCommand = pStateGraphicsCommand->AddChildCommand(new CXTPChartTranslateDeviceCommand(anchorPoint.X, anchorPoint.Y, 0));
|
|
pStateGraphicsCommand = pStateGraphicsCommand->AddChildCommand(new CXTPChartRotateDeviceCommand(fAngle));
|
|
pStateGraphicsCommand = pStateGraphicsCommand->AddChildCommand(new CXTPChartPolygonAntialiasingDeviceCommand(TRUE));
|
|
|
|
CXTPChartPointF labelPoint = innerBounds.GetLocation();
|
|
|
|
CXTPChartColor clrBackColor = m_pLabel->GetActualBackColor();
|
|
pStateGraphicsCommand->AddChildCommand(m_pLabel->GetFillStyle()->CreateDeviceCommand(bounds, clrBackColor, clrBackColor));
|
|
|
|
painter.SetLocation(labelPoint);
|
|
|
|
pStateGraphicsCommand->AddChildCommand(painter.CreateDeviceCommand(pDC, clrTextColor));
|
|
|
|
if (borderThickness)
|
|
{
|
|
CXTPChartColor clrBorderColor = GetActualBorderColor();
|
|
|
|
pStateGraphicsCommand->AddChildCommand(m_pLabel->GetBorder()->CreateDeviceCommand(bounds, clrBorderColor));
|
|
}
|
|
}
|
|
|
|
else if (position == xtpChartPieLabelOutside)
|
|
{
|
|
CXTPChartTextPainter painter(pDC, text, m_pLabel);
|
|
CXTPChartSizeF size = painter.GetSize();
|
|
|
|
CXTPChartPointF startPoint(anchorPoint);
|
|
CXTPChartPointF finishPoint(anchorPoint.X + (float)(cos(lineAngle) * m_pLabel->GetLineLength()),
|
|
anchorPoint.Y - (float)(sin(lineAngle) * m_pLabel->GetLineLength()));
|
|
|
|
CXTPChartRectF innerBounds;
|
|
CXTPChartRectF bounds = CXTPChartSeriesLabelConnectorPainterBase::CalcBorderBoundsForTangentDrawing(finishPoint, lineAngle, size, borderThickness, innerBounds);
|
|
bounds.Round();
|
|
innerBounds.Round();
|
|
|
|
|
|
CXTPChartPointF labelPoint = innerBounds.GetLocation();
|
|
|
|
CXTPChartColor clrBackColor = m_pLabel->GetActualBackColor();
|
|
pCommand->AddChildCommand(m_pLabel->GetFillStyle()->CreateDeviceCommand(bounds, clrBackColor, clrBackColor));
|
|
|
|
painter.SetLocation(labelPoint);
|
|
pCommand->AddChildCommand(painter.CreateDeviceCommand(pDC, clrTextColor));
|
|
|
|
|
|
if (borderThickness)
|
|
{
|
|
CXTPChartColor clrBorderColor = GetActualBorderColor();
|
|
|
|
pCommand->AddChildCommand(m_pLabel->GetBorder()->CreateInnerBorderDeviceCommand(bounds, clrBorderColor));
|
|
}
|
|
|
|
}
|
|
else if (position == xtpChartPieLabelTwoColumns)
|
|
{
|
|
CXTPChartRectF bounds = m_rcBounds;
|
|
|
|
CXTPChartTextPainter painter(pDC, text, m_pLabel);
|
|
painter.SetLocation(bounds.GetLocation());
|
|
|
|
CXTPChartColor clrBackColor = m_pLabel->GetActualBackColor();
|
|
pCommand->AddChildCommand(m_pLabel->GetFillStyle()->CreateDeviceCommand(bounds, clrBackColor, clrBackColor));
|
|
|
|
pCommand->AddChildCommand(painter.CreateDeviceCommand(pDC, clrTextColor));
|
|
|
|
|
|
if (borderThickness)
|
|
{
|
|
CXTPChartColor clrBorderColor = GetActualBorderColor();
|
|
|
|
pCommand->AddChildCommand(m_pLabel->GetBorder()->CreateInnerBorderDeviceCommand(bounds, clrBorderColor));
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return pCommand;
|
|
}
|
|
|
|
|
|
CXTPChartElementView* CXTPChartPieSeriesLabel::CreateView(CXTPChartDeviceContext* pDC, CXTPChartSeriesPointView* pPointView, CXTPChartElementView* pParentView)
|
|
{
|
|
UNREFERENCED_PARAMETER(pDC);
|
|
return new CXTPChartPieSeriesLabelView(this, pPointView, pParentView);
|
|
}
|
|
|
|
|
|
#ifdef _XTP_ACTIVEX
|
|
|
|
BEGIN_DISPATCH_MAP(CXTPChartPieSeriesLabel, CXTPChartSeriesLabel)
|
|
DISP_PROPERTY_NOTIFY_ID(CXTPChartPieSeriesLabel, "Position", 106, m_nPosition, OleChartChanged, VT_I4)
|
|
END_DISPATCH_MAP()
|
|
|
|
|
|
// {CDFBCC77-27BF-4cb1-9ABF-4558D9835223}
|
|
static const GUID IID_IChartPieSeriesLabel =
|
|
{ 0xcdfbcc77, 0x27bf, 0x4cb1, { 0x9a, 0xbf, 0x45, 0x58, 0xd9, 0x83, 0x52, 0x23 } };
|
|
|
|
BEGIN_INTERFACE_MAP(CXTPChartPieSeriesLabel, CXTPChartSeriesLabel)
|
|
INTERFACE_PART(CXTPChartPieSeriesLabel, IID_IChartPieSeriesLabel, Dispatch)
|
|
END_INTERFACE_MAP()
|
|
|
|
IMPLEMENT_OLETYPELIB_EX(CXTPChartPieSeriesLabel, IID_IChartPieSeriesLabel)
|
|
|
|
|
|
#endif
|