Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "KDChartPolarCoordinatePlane.h"
00024 #include "KDChartPolarCoordinatePlane_p.h"
00025
00026 #include "KDChartPainterSaver_p.h"
00027 #include "KDChartChart.h"
00028 #include "KDChartPaintContext.h"
00029 #include "KDChartAbstractDiagram.h"
00030 #include "KDChartAbstractPolarDiagram.h"
00031 #include "KDChartPolarDiagram.h"
00032
00033 #include <math.h>
00034
00035 #include <QFont>
00036 #include <QList>
00037 #include <QtDebug>
00038 #include <QPainter>
00039 #include <QTimer>
00040
00041 #include <KDABLibFakes>
00042
00043 using namespace KDChart;
00044
00045 #define d d_func()
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 PolarCoordinatePlane::PolarCoordinatePlane ( Chart* parent )
00116 : AbstractCoordinatePlane ( new Private(), parent )
00117 {
00118
00119 }
00120
00121 PolarCoordinatePlane::~PolarCoordinatePlane()
00122 {
00123
00124 }
00125
00126 void PolarCoordinatePlane::init()
00127 {
00128
00129 }
00130
00131 void PolarCoordinatePlane::addDiagram ( AbstractDiagram* diagram )
00132 {
00133 Q_ASSERT_X ( dynamic_cast<AbstractPolarDiagram*> ( diagram ),
00134 "PolarCoordinatePlane::addDiagram", "Only polar"
00135 "diagrams can be added to a polar coordinate plane!" );
00136 AbstractCoordinatePlane::addDiagram ( diagram );
00137 connect ( diagram, SIGNAL ( layoutChanged ( AbstractDiagram* ) ),
00138 SLOT ( slotLayoutChanged ( AbstractDiagram* ) ) );
00139
00140 }
00141
00142 void PolarCoordinatePlane::paint ( QPainter* painter )
00143 {
00144 AbstractDiagramList diags = diagrams();
00145 if ( d->coordinateTransformations.size() == diags.size() )
00146 {
00147 PaintContext ctx;
00148 ctx.setPainter ( painter );
00149 ctx.setCoordinatePlane ( this );
00150 ctx.setRectangle ( geometry() );
00151
00152
00153 const qreal oldZoomX = zoomFactorX();
00154 const qreal oldZoomY = zoomFactorY();
00155 d->newZoomX = oldZoomX;
00156 d->newZoomY = oldZoomY;
00157 for ( int i = 0; i < diags.size(); i++ )
00158 {
00159 d->currentTransformation = & ( d->coordinateTransformations[i] );
00160 qreal zoomX;
00161 qreal zoomY;
00162 PolarDiagram* polarDia = dynamic_cast<PolarDiagram*> ( diags[i] );
00163 if( polarDia ){
00164 polarDia->paint ( &ctx, true, zoomX, zoomY );
00165 d->newZoomX = qMin(d->newZoomX, zoomX);
00166 d->newZoomY = qMin(d->newZoomY, zoomY);
00167 }
00168 }
00169 d->currentTransformation = 0;
00170
00171
00172 if( d->newZoomX != oldZoomX || d->newZoomY != oldZoomY ){
00173
00174 QTimer::singleShot(10, this, SLOT(adjustZoomAndRepaint()));
00175 return;
00176 }
00177
00178
00179
00180
00181 d->currentTransformation = & ( d->coordinateTransformations.first() );
00182
00183 d->grid->drawGrid( &ctx );
00184
00185
00186 for ( int i = 0; i < diags.size(); i++ )
00187 {
00188 d->currentTransformation = & ( d->coordinateTransformations[i] );
00189 PainterSaver painterSaver( painter );
00190 PolarDiagram* polarDia = dynamic_cast<PolarDiagram*> ( diags[i] );
00191 if( polarDia ){
00192 qreal dummy1, dummy2;
00193 polarDia->paint ( &ctx, false, dummy1, dummy2 );
00194 }else{
00195 diags[i]->paint ( &ctx );
00196 }
00197 }
00198 d->currentTransformation = 0;
00199 }
00200 }
00201
00202
00203 void PolarCoordinatePlane::adjustZoomAndRepaint()
00204 {
00205 const qreal newZoom = qMin(d->newZoomX, d->newZoomY);
00206 setZoomFactors(newZoom, newZoom);
00207 update();
00208 }
00209
00210
00211 void PolarCoordinatePlane::resizeEvent ( QResizeEvent* )
00212 {
00213 d->initialResizeEventReceived = true;
00214 layoutDiagrams();
00215 }
00216
00217 void PolarCoordinatePlane::layoutDiagrams()
00218 {
00219
00220
00221
00222
00223
00224
00225 const QRect rect( areaGeometry() );
00226 d->contentRect = QRectF ( 1, 1, rect.width() - 3, rect.height() - 3 );
00227
00228 const ZoomParameters zoom = d->coordinateTransformations.isEmpty() ? ZoomParameters()
00229 : d->coordinateTransformations.front().zoom;
00230
00231 const qreal oldStartPosition = startPosition();
00232 d->coordinateTransformations.clear();
00233 Q_FOREACH( AbstractDiagram* diagram, diagrams() )
00234 {
00235 AbstractPolarDiagram *polarDiagram = dynamic_cast<AbstractPolarDiagram*>( diagram );
00236 Q_ASSERT( polarDiagram );
00237 QPair<QPointF, QPointF> dataBoundariesPair = polarDiagram->dataBoundaries();
00238
00239 const double angleUnit = 360 / polarDiagram->valueTotals();
00240
00241 const double radius = qAbs( dataBoundariesPair.first.y() ) + dataBoundariesPair.second.y();
00242
00243 const double diagramWidth = radius * 2;
00244 const double planeWidth = d->contentRect.width();
00245 const double planeHeight = d->contentRect.height();
00246 const double radiusUnit = qMin( planeWidth, planeHeight ) / diagramWidth;
00247
00248 QPointF coordinateOrigin = QPointF ( planeWidth / 2, planeHeight / 2 );
00249 coordinateOrigin += d->contentRect.topLeft();
00250
00251 CoordinateTransformation diagramTransposition;
00252 diagramTransposition.originTranslation = coordinateOrigin;
00253 diagramTransposition.radiusUnit = radiusUnit;
00254 diagramTransposition.angleUnit = angleUnit;
00255 diagramTransposition.startPosition = oldStartPosition;
00256 diagramTransposition.zoom = zoom;
00257 diagramTransposition.minValue = dataBoundariesPair.first.y() < 0 ? dataBoundariesPair.first.y() : 0.0;
00258 d->coordinateTransformations.append( diagramTransposition );
00259 }
00260 }
00261
00262 const QPointF PolarCoordinatePlane::translate( const QPointF& diagramPoint ) const
00263 {
00264 Q_ASSERT_X ( d->currentTransformation != 0, "PolarCoordinatePlane::translate",
00265 "Only call translate() from within paint()." );
00266 return d->currentTransformation->translate ( diagramPoint );
00267 }
00268
00269 const QPointF PolarCoordinatePlane::translatePolar( const QPointF& diagramPoint ) const
00270 {
00271 Q_ASSERT_X ( d->currentTransformation != 0, "PolarCoordinatePlane::translate",
00272 "Only call translate() from within paint()." );
00273 return d->currentTransformation->translatePolar ( diagramPoint );
00274 }
00275
00276 qreal PolarCoordinatePlane::angleUnit() const
00277 {
00278 Q_ASSERT_X ( d->currentTransformation != 0, "PolarCoordinatePlane::angleUnit",
00279 "Only call angleUnit() from within paint()." );
00280 return d->currentTransformation->angleUnit;
00281 }
00282
00283 qreal PolarCoordinatePlane::radiusUnit() const
00284 {
00285 Q_ASSERT_X ( d->currentTransformation != 0, "PolarCoordinatePlane::radiusUnit",
00286 "Only call radiusUnit() from within paint()." );
00287 return d->currentTransformation->radiusUnit;
00288 }
00289
00290 void PolarCoordinatePlane::slotLayoutChanged ( AbstractDiagram* )
00291 {
00292 if ( d->initialResizeEventReceived ) layoutDiagrams();
00293 }
00294
00295 void PolarCoordinatePlane::setStartPosition( qreal degrees )
00296 {
00297 Q_ASSERT_X ( diagram(), "PolarCoordinatePlane::setStartPosition",
00298 "setStartPosition() needs a diagram to be associated to the plane." );
00299 for( CoordinateTransformationList::iterator it = d->coordinateTransformations.begin();
00300 it != d->coordinateTransformations.end();
00301 ++it )
00302 {
00303 CoordinateTransformation& trans = *it;
00304 trans.startPosition = degrees;
00305 }
00306 }
00307
00308 qreal PolarCoordinatePlane::startPosition() const
00309 {
00310 return d->coordinateTransformations.isEmpty()
00311 ? 0.0
00312 : d->coordinateTransformations.first().startPosition;
00313 }
00314
00315 double PolarCoordinatePlane::zoomFactorX() const
00316 {
00317 return d->coordinateTransformations.isEmpty()
00318 ? 1.0
00319 : d->coordinateTransformations.first().zoom.xFactor;
00320 }
00321
00322 double PolarCoordinatePlane::zoomFactorY() const
00323 {
00324 return d->coordinateTransformations.isEmpty()
00325 ? 1.0
00326 : d->coordinateTransformations.first().zoom.yFactor;
00327 }
00328
00329 void PolarCoordinatePlane::setZoomFactors( double factorX, double factorY )
00330 {
00331 setZoomFactorX( factorX );
00332 setZoomFactorY( factorY );
00333 }
00334
00335 void PolarCoordinatePlane::setZoomFactorX( double factor )
00336 {
00337 for( CoordinateTransformationList::iterator it = d->coordinateTransformations.begin();
00338 it != d->coordinateTransformations.end();
00339 ++it )
00340 {
00341 CoordinateTransformation& trans = *it;
00342 trans.zoom.xFactor = factor;
00343 }
00344 }
00345
00346 void PolarCoordinatePlane::setZoomFactorY( double factor )
00347 {
00348 for( CoordinateTransformationList::iterator it = d->coordinateTransformations.begin();
00349 it != d->coordinateTransformations.end();
00350 ++it )
00351 {
00352 CoordinateTransformation& trans = *it;
00353 trans.zoom.yFactor = factor;
00354 }
00355 }
00356
00357 QPointF PolarCoordinatePlane::zoomCenter() const
00358 {
00359 return d->coordinateTransformations.isEmpty()
00360 ? QPointF( 0.5, 0.5 )
00361 : QPointF( d->coordinateTransformations.first().zoom.xCenter, d->coordinateTransformations.first().zoom.yCenter );
00362 }
00363
00364 void PolarCoordinatePlane::setZoomCenter( const QPointF& center )
00365 {
00366 for( CoordinateTransformationList::iterator it = d->coordinateTransformations.begin();
00367 it != d->coordinateTransformations.end();
00368 ++it )
00369 {
00370 CoordinateTransformation& trans = *it;
00371 trans.zoom.xCenter = center.x();
00372 trans.zoom.yCenter = center.y();
00373 }
00374 }
00375
00376 DataDimensionsList PolarCoordinatePlane::getDataDimensionsList() const
00377 {
00378 DataDimensionsList l;
00379
00380
00381
00382 return l;
00383 }
00384
00385 void KDChart::PolarCoordinatePlane::setGridAttributes(
00386 bool circular,
00387 const GridAttributes& a )
00388 {
00389 if( circular )
00390 d->gridAttributesCircular = a;
00391 else
00392 d->gridAttributesSagittal = a;
00393 setHasOwnGridAttributes( circular, true );
00394 update();
00395 emit propertiesChanged();
00396 }
00397
00398 void KDChart::PolarCoordinatePlane::resetGridAttributes(
00399 bool circular )
00400 {
00401 setHasOwnGridAttributes( circular, false );
00402 update();
00403 }
00404
00405 const GridAttributes KDChart::PolarCoordinatePlane::gridAttributes(
00406 bool circular ) const
00407 {
00408 if( hasOwnGridAttributes( circular ) ){
00409 if( circular )
00410 return d->gridAttributesCircular;
00411 else
00412 return d->gridAttributesSagittal;
00413 }else{
00414 return globalGridAttributes();
00415 }
00416 }
00417
00418 void KDChart::PolarCoordinatePlane::setHasOwnGridAttributes(
00419 bool circular, bool on )
00420 {
00421 if( circular )
00422 d->hasOwnGridAttributesCircular = on;
00423 else
00424 d->hasOwnGridAttributesSagittal = on;
00425 emit propertiesChanged();
00426 }
00427
00428 bool KDChart::PolarCoordinatePlane::hasOwnGridAttributes(
00429 bool circular ) const
00430 {
00431 return
00432 ( circular )
00433 ? d->hasOwnGridAttributesCircular
00434 : d->hasOwnGridAttributesSagittal;
00435 }