1
/****************************************************************************
2
** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved.
4
** This file is part of the KD Chart library.
6
** Licensees holding valid commercial KD Chart licenses may use this file in
7
** accordance with the KD Chart Commercial License Agreement provided with
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 and version 3 as published by the
13
** Free Software Foundation and appearing in the file LICENSE.GPL included.
15
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18
** Contact info@kdab.com if any conditions of this licensing are not
21
**********************************************************************/
23
#include "KDChartTernaryCoordinatePlane.h"
24
#include "KDChartTernaryCoordinatePlane_p.h"
29
#include "KDChartPaintContext.h"
30
#include "KDChartPainterSaver_p.h"
31
#include "KDChartTernaryAxis.h"
32
#include "KDChartAbstractTernaryDiagram.h"
34
#include "TernaryConstants.h"
36
using namespace KDChart;
40
TernaryCoordinatePlane::Private::Private()
41
: AbstractCoordinatePlane::Private()
45
TernaryCoordinatePlane::TernaryCoordinatePlane( Chart* parent )
46
: AbstractCoordinatePlane( new Private(), parent )
50
TernaryCoordinatePlane::~TernaryCoordinatePlane()
54
void TernaryCoordinatePlane::init()
58
void TernaryCoordinatePlane::addDiagram( AbstractDiagram* diagram )
60
Q_ASSERT_X ( dynamic_cast<AbstractTernaryDiagram*>( diagram ),
61
"TernaryCoordinatePlane::addDiagram", "Only ternary "
62
"diagrams can be added to a ternary coordinate plane!" );
63
AbstractCoordinatePlane::addDiagram ( diagram );
64
// connect ( diagram, SIGNAL ( layoutChanged ( AbstractDiagram* ) ),
65
// SLOT ( slotLayoutChanged ( AbstractDiagram* ) ) );
66
// connect( diagram, SIGNAL( propertiesChanged() ),this, SIGNAL( propertiesChanged() ) );
69
void TernaryCoordinatePlane::layoutDiagrams()
70
{ // this is our "resize event":
71
// all diagrams always take the same space, nothing to be done here
72
// the "inner" margin (adjustments to diagram coordinates)
73
QRectF diagramNativeRectangle ( QPointF( 0.0, 0.0 ),
74
QSizeF( TriangleWidth, TriangleHeight ) );
75
QPair<QSizeF, QSizeF> margins = grid()->requiredMargins();
76
d->diagramRect = areaGeometry();
77
diagramNativeRectangle.adjust
78
(-margins.first.width(), -margins.first.height(),
79
margins.second.width(), margins.second.height() );
81
// the "outer" margin (distance between diagram contents and area,
82
// determined by axis label overlap
84
QSizeF topleft( 0.0, 0.0 );
85
QSizeF bottomRight( 0.0, 0.0 );
86
Q_FOREACH( AbstractDiagram* abstractDiagram, diagrams() ) {
87
AbstractTernaryDiagram* diagram =
88
qobject_cast<AbstractTernaryDiagram*>( abstractDiagram );
90
Q_FOREACH( TernaryAxis* axis, diagram->axes() ) {
91
QPair<QSizeF, QSizeF> margin = axis->requiredMargins();
92
topleft = topleft.expandedTo( margin.first );
93
bottomRight = bottomRight.expandedTo( margin.second );
96
d->diagramRectContainer =
97
d->diagramRect.adjusted( topleft.width(),
100
-bottomRight.height() );
103
// now calculate isometric projection, x and y widget coordinate
104
// units, and location of (0.0, 0.0) in diagram coordinates
105
QPointF zeroZeroPoint = d->diagramRectContainer.bottomLeft();
106
double w = d->diagramRectContainer.width();
107
double h = d->diagramRectContainer.height();
111
if ( TriangleHeight * w > h ) {
113
usableWidth = h / diagramNativeRectangle.height();
115
zeroZeroPoint.setX( zeroZeroPoint.x() + ( w - usableWidth ) / 2 );
119
usableHeight = diagramNativeRectangle.height() * w;
120
zeroZeroPoint.setY( zeroZeroPoint.y() - ( h - usableHeight ) / 2 );
122
// the rectangle has 1 as it's width, and TriangleHeight as it's
123
// height - so this is how we translate that to widget coordinates:
124
d->xUnit = usableWidth / diagramNativeRectangle.width(); // only because we normalize the values to [0..1]
125
d->yUnit = -usableHeight / diagramNativeRectangle.height();
127
// now move zeroZeroPoint so that it does not include the tick marks
129
double descent = diagramNativeRectangle.height() - TriangleHeight;
130
double rightShift = -diagramNativeRectangle.x();
131
zeroZeroPoint += QPointF( rightShift * d->xUnit, descent * d->yUnit );
134
d->diagramRect.setBottomLeft( zeroZeroPoint );
135
d->diagramRect.setTopRight( QPointF( usableWidth, -usableHeight ) + zeroZeroPoint );
138
const QPointF TernaryCoordinatePlane::translate( const QPointF& point ) const
140
return QPointF( d->diagramRect.bottomLeft().x() + point.x() * d->xUnit,
141
d->diagramRect.bottomLeft().y() + point.y() * d->yUnit );
144
QSize TernaryCoordinatePlane::minimumSizeHint() const
150
QSizePolicy TernaryCoordinatePlane::sizePolicy() const
152
return QSizePolicy( QSizePolicy::MinimumExpanding,
153
QSizePolicy::MinimumExpanding );
156
void TernaryCoordinatePlane::paint( QPainter* painter )
158
PainterSaver s( painter );
159
// FIXME: this is not a good location for that:
160
painter->setRenderHint(QPainter::Antialiasing, true );
162
// painter->setPen( QColor( "gold" ) );
163
// painter->setBrush( QColor( "gold" ) );
164
// painter->drawRect( d->diagramRectContainer );
166
AbstractDiagramList diags = diagrams();
167
if ( !diags.isEmpty() )
170
ctx.setPainter ( painter );
171
ctx.setCoordinatePlane ( this );
172
const QRectF drawArea( areaGeometry() );
173
ctx.setRectangle ( drawArea );
175
// enabling clipping so that we're not drawing outside
176
// QRect clipRect = drawArea.toRect().adjusted( -1, -1, 1, 1 );
177
// QRegion clipRegion( clipRect );
178
// painter->setClipRegion( clipRegion );
180
// paint the coordinate system rulers:
181
Q_ASSERT( d->grid != 0 );
182
d->grid->drawGrid( &ctx );
184
// paint the diagrams:
185
for ( int i = 0; i < diags.size(); i++ )
187
PainterSaver diagramPainterSaver( painter );
188
diags[i]->paint ( &ctx );
193
DataDimensionsList TernaryCoordinatePlane::getDataDimensionsList() const
195
return DataDimensionsList();
198
TernaryGrid* TernaryCoordinatePlane::grid() const
200
TernaryGrid* ternaryGrid = static_cast<TernaryGrid*>( d->grid );
201
Q_ASSERT( dynamic_cast<TernaryGrid*>( d->grid ) );