Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

KDChartCartesianCoordinatePlane.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002  ** Copyright (C) 2006 Klarälvdalens Datakonsult AB.  All rights reserved.
00003  **
00004  ** This file is part of the KD Chart library.
00005  **
00006  ** This file may be distributed and/or modified under the terms of the
00007  ** GNU General Public License version 2 as published by the Free Software
00008  ** Foundation and appearing in the file LICENSE.GPL included in the
00009  ** packaging of this file.
00010  **
00011  ** Licensees holding valid commercial KD Chart licenses may use this file in
00012  ** accordance with the KD Chart Commercial License Agreement provided with
00013  ** the Software.
00014  **
00015  ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016  ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017  **
00018  ** See http://www.kdab.net/kdchart for
00019  **   information about KDChart Commercial License Agreements.
00020  **
00021  ** Contact info@kdab.net if any conditions of this
00022  ** licensing are not clear to you.
00023  **
00024  **********************************************************************/
00025 
00026 #include <QFont>
00027 #include <QList>
00028 #include <QtDebug>
00029 #include <QPainter>
00030 #include <QApplication>
00031 
00032 #include "KDChartAbstractDiagram.h"
00033 #include "KDChartAbstractCartesianDiagram.h"
00034 #include "KDChartCartesianCoordinatePlane.h"
00035 #include "KDChartCartesianCoordinatePlane_p.h"
00036 #include "CartesianCoordinateTransformation.h"
00037 #include "KDChartGridAttributes.h"
00038 #include "KDChartPaintContext.h"
00039 #include "KDChartPainterSaver_p.h"
00040 
00041 #include <KDABLibFakes>
00042 
00043 
00044 using namespace KDChart;
00045 
00046 #define d d_func()
00047 
00048 CartesianCoordinatePlane::Private::Private()
00049     : AbstractCoordinatePlane::Private()
00050     , bPaintIsRunning( false )
00051     , hasOwnGridAttributesHorizontal ( false )
00052     , hasOwnGridAttributesVertical ( false )
00053     // old: , initialResizeEventReceived ( false )
00054     , isometricScaling ( false )
00055     , horizontalMin(0)
00056     , horizontalMax(0)
00057     , verticalMin(0)
00058     , verticalMax(0)
00059     , autoAdjustHorizontalRangeToData(67)
00060     , autoAdjustVerticalRangeToData(  67)
00061     , autoAdjustGridToZoom( true )
00062 {
00063     // this bloc left empty intentionally
00064 }
00065 
00066 
00067 CartesianCoordinatePlane::CartesianCoordinatePlane ( Chart* parent )
00068     : AbstractCoordinatePlane ( new Private(), parent )
00069 {
00070     // this bloc left empty intentionally
00071 }
00072 
00073 CartesianCoordinatePlane::~CartesianCoordinatePlane()
00074 {
00075     // this bloc left empty intentionally
00076 }
00077 
00078 void CartesianCoordinatePlane::init()
00079 {
00080     // this bloc left empty intentionally
00081 }
00082 
00083 
00084 void CartesianCoordinatePlane::addDiagram ( AbstractDiagram* diagram )
00085 {
00086     Q_ASSERT_X ( dynamic_cast<AbstractCartesianDiagram*> ( diagram ),
00087                  "CartesianCoordinatePlane::addDiagram", "Only cartesian "
00088                  "diagrams can be added to a cartesian coordinate plane!" );
00089     AbstractCoordinatePlane::addDiagram ( diagram );
00090     connect ( diagram,  SIGNAL ( layoutChanged ( AbstractDiagram* ) ),
00091               SLOT ( slotLayoutChanged ( AbstractDiagram* ) ) );
00092 
00093     connect( diagram, SIGNAL( propertiesChanged() ),this, SIGNAL( propertiesChanged() ) );
00094 }
00095 
00096 
00097 void CartesianCoordinatePlane::paint ( QPainter* painter )
00098 {
00099     // prevent recursive call:
00100     //qDebug("attempt plane::paint()");
00101     if( d->bPaintIsRunning ){
00102         return;
00103     }
00104     d->bPaintIsRunning = true;
00105 
00106     //qDebug() << "start plane::paint()";
00107 
00108     AbstractDiagramList diags = diagrams();
00109     if ( !diags.isEmpty() )
00110     {
00111         PaintContext ctx;
00112         ctx.setPainter ( painter );
00113         ctx.setCoordinatePlane ( this );
00114         const QRectF drawArea( drawingArea() );
00115         ctx.setRectangle ( drawArea );
00116 
00117         // enabling clipping so that we're not drawing outside
00118         PainterSaver painterSaver( painter );
00119         QRect clipRect = drawArea.toRect().adjusted( -1, -1, 1, 1 );
00120         QRegion clipRegion( clipRect );
00121         painter->setClipRegion( clipRegion );
00122 
00123         // paint the coordinate system rulers:
00124         d->grid->drawGrid( &ctx );
00125 
00126         // paint the diagrams:
00127         for ( int i = 0; i < diags.size(); i++ )
00128         {
00129 //qDebug("  start diags[i]->paint ( &ctx );");
00130             PainterSaver diagramPainterSaver( painter );
00131             diags[i]->paint ( &ctx );
00132 //qDebug("  done: diags[i]->paint ( &ctx );");
00133         }
00134 
00135         //for debugging:
00136         //    painter->drawRect( drawArea.adjusted(4,4,-4,-4) );
00137         //    painter->drawRect( drawArea.adjusted(2,2,-2,-2) );
00138         //    painter->drawRect( drawArea );
00139     }
00140     d->bPaintIsRunning = false;
00141     //qDebug("done: plane::paint()");
00142 }
00143 
00144 
00145 void CartesianCoordinatePlane::slotLayoutChanged ( AbstractDiagram* )
00146 {
00147     // old: if ( d->initialResizeEventReceived )
00148     layoutDiagrams();
00149 }
00150 
00151 QRectF CartesianCoordinatePlane::getRawDataBoundingRectFromDiagrams() const
00152 {
00153     // determine unit of the rectangles of all involved diagrams:
00154     qreal minX, maxX, minY, maxY;
00155     bool bStarting = true;
00156     Q_FOREACH( const AbstractDiagram* diagram, diagrams() )
00157     {
00158         QPair<QPointF, QPointF> dataBoundariesPair = diagram->dataBoundaries();
00159         //qDebug() << "CartesianCoordinatePlane::getRawDataBoundingRectFromDiagrams()\ngets diagram->dataBoundaries: " << dataBoundariesPair.first << dataBoundariesPair.second;
00160         if ( bStarting || dataBoundariesPair.first.x()  < minX ) minX = dataBoundariesPair.first.x();
00161         if ( bStarting || dataBoundariesPair.first.y()  < minY ) minY = dataBoundariesPair.first.y();
00162         if ( bStarting || dataBoundariesPair.second.x() > maxX ) maxX = dataBoundariesPair.second.x();
00163         if ( bStarting || dataBoundariesPair.second.y() > maxY ) maxY = dataBoundariesPair.second.y();
00164         bStarting = false;
00165     }
00166     //qDebug() << "CartesianCoordinatePlane::getRawDataBoundingRectFromDiagrams()\nreturns data boundaries: " << QRectF( QPointF(minX, minY), QSizeF(maxX - minX, maxY - minY) );
00167     QRectF dataBoundingRect;
00168     dataBoundingRect.setBottomLeft( QPointF(minX, minY) );
00169     dataBoundingRect.setTopRight(   QPointF(maxX, maxY) );
00170     return dataBoundingRect;
00171 }
00172 
00173 
00174 QRectF CartesianCoordinatePlane::adjustedToMaxEmptyInnerPercentage(
00175         const QRectF& r, unsigned int percentX, unsigned int percentY ) const
00176 {
00177     QRectF erg( r );
00178     if( percentX < 100 || percentX == 1000 ) {
00179         const bool isPositive = (r.left() >= 0);
00180         if( (r.right() >= 0) == isPositive ){
00181             const qreal innerBound =
00182                     isPositive ? qMin(r.left(), r.right()) : qMax(r.left(), r.right());
00183             const qreal outerBound =
00184                     isPositive ? qMax(r.left(), r.right()) : qMin(r.left(), r.right());
00185             if( innerBound / outerBound * 100 <= percentX )
00186             {
00187                 if( isPositive )
00188                     erg.setLeft( 0.0 );
00189                 else
00190                     erg.setRight( 0.0 );
00191             }
00192         }
00193     }
00194     if( percentY < 100 || percentY == 1000 ) {
00195         const bool isPositive = (r.bottom() >= 0);
00196         if( (r.top() >= 0) == isPositive ){
00197             const qreal innerBound =
00198                     isPositive ? qMin(r.top(), r.bottom()) : qMax(r.top(), r.bottom());
00199             const qreal outerBound =
00200                     isPositive ? qMax(r.top(), r.bottom()) : qMin(r.top(), r.bottom());
00201             if( innerBound / outerBound * 100 <= percentY )
00202             {
00203                 if( isPositive )
00204                     erg.setBottom( 0.0 );
00205                 else
00206                     erg.setTop( 0.0 );
00207             }
00208         }
00209     }
00210     return erg;
00211 }
00212 
00213 
00214 QRectF CartesianCoordinatePlane::calculateRawDataBoundingRect() const
00215 {
00216     // are manually set ranges to be applied?
00217     const bool bAutoAdjustHorizontalRange = (d->autoAdjustHorizontalRangeToData < 100);
00218     const bool bAutoAdjustVerticalRange   = (d->autoAdjustVerticalRangeToData   < 100);
00219 
00220     const bool bHardHorizontalRange = (d->horizontalMin != d->horizontalMax) && ! bAutoAdjustHorizontalRange;
00221     const bool bHardVerticalRange   = (d->verticalMin   != d->verticalMax)   && ! bAutoAdjustVerticalRange;
00222     QRectF dataBoundingRect;
00223 
00224     // if custom boundaries are set on the plane, use them
00225     if ( bHardHorizontalRange && bHardVerticalRange ) {
00226         dataBoundingRect.setLeft(   d->horizontalMin );
00227         dataBoundingRect.setRight(  d->horizontalMax );
00228         dataBoundingRect.setBottom( d->verticalMin );
00229         dataBoundingRect.setTop(    d->verticalMax );
00230     }else{
00231         // determine unit of the rectangles of all involved diagrams:
00232         dataBoundingRect = getRawDataBoundingRectFromDiagrams();
00233         if ( bHardHorizontalRange ) {
00234             dataBoundingRect.setLeft(  d->horizontalMin );
00235             dataBoundingRect.setRight( d->horizontalMax );
00236         }
00237         if ( bHardVerticalRange ) {
00238             dataBoundingRect.setBottom( d->verticalMin );
00239             dataBoundingRect.setTop(    d->verticalMax );
00240         }
00241     }
00242     // recalculate the bounds, if automatic adjusting of ranges is desired AND
00243     //                         both bounds are at the same side of the zero line
00244     dataBoundingRect = adjustedToMaxEmptyInnerPercentage(
00245             dataBoundingRect, d->autoAdjustHorizontalRangeToData, d->autoAdjustVerticalRangeToData );
00246     if( bAutoAdjustHorizontalRange ){
00247         const_cast<CartesianCoordinatePlane::Private *>(d)->horizontalMin = dataBoundingRect.left();
00248         const_cast<CartesianCoordinatePlane::Private *>(d)->horizontalMax = dataBoundingRect.right();
00249     }
00250     if( bAutoAdjustVerticalRange ){
00251         const_cast<CartesianCoordinatePlane*>(this)->d->verticalMin = dataBoundingRect.bottom();
00252         const_cast<CartesianCoordinatePlane*>(this)->d->verticalMax = dataBoundingRect.top();
00253     }
00254     //qDebug() << "CartesianCoordinatePlane::calculateRawDataBoundingRect()\nreturns data boundaries: " << dataBoundingRect;
00255     return dataBoundingRect;
00256 }
00257 
00258 
00259 DataDimensionsList CartesianCoordinatePlane::getDataDimensionsList() const
00260 {
00261 
00262     DataDimensionsList l;
00263     const AbstractCartesianDiagram* dgr
00264         = diagrams().isEmpty() ? 0 : dynamic_cast<const AbstractCartesianDiagram*> (diagrams().first() );
00265 
00266     if( dgr ){
00267         const QRectF r( calculateRawDataBoundingRect() );
00268         // note:
00269         // We do *not* access d->gridAttributesHorizontal here, but
00270         // we use the getter function, to get the global attrs, if no
00271         // special ones have been set for the respective orientation.
00272         const GridAttributes gaH( gridAttributes( Qt::Horizontal ) );
00273         const GridAttributes gaV( gridAttributes( Qt::Vertical ) );
00274         // append the first dimension: for Abscissa axes
00275         l.append(
00276             DataDimension(
00277                 r.left(), r.right(),
00278                 dgr->datasetDimension() > 1,
00279                 axesCalcModeX(),
00280                 gaH.gridGranularitySequence(),
00281                 gaH.gridStepWidth(),
00282                 gaH.gridSubStepWidth() ) );
00283         // append the second dimension: for Ordinate axes
00284         if( dgr->percentMode() )
00285             l.append(
00286                 DataDimension(
00287                     // always return 0-100 when in percentMode
00288                     0.0, 100.0,
00289                     true,
00290                     axesCalcModeY(),
00291                     KDChartEnums::GranularitySequence_10_20,
00292                     10.0 ) );
00293         else
00294             l.append(
00295                 DataDimension(
00296                     r.bottom(), r.top(),
00297                     true,
00298                     axesCalcModeY(),
00299                     gaV.gridGranularitySequence(),
00300                     gaV.gridStepWidth(),
00301                     gaV.gridSubStepWidth() ) );
00302     }else{
00303         l.append( DataDimension() ); // This gets us the default 1..0 / 1..0 grid
00304         l.append( DataDimension() ); // shown, if there is no diagram on this plane.
00305     }
00306     return l;
00307 }
00308 
00309 QRectF CartesianCoordinatePlane::drawingArea() const
00310 {
00311     const QRect rect( areaGeometry() );
00312     return QRectF ( rect.left()+1, rect.top()+1, rect.width() - 3, rect.height() - 3 );
00313 }
00314 
00315 
00316 void CartesianCoordinatePlane::layoutDiagrams()
00317 {
00318     //qDebug("KDChart::CartesianCoordinatePlane::layoutDiagrams() called");
00319     if ( diagrams().isEmpty() )
00320     {   // FIXME evaluate what can still be prepared
00321         // FIXME decide default dimension if no diagrams are present (to make empty planes useable)
00322     }
00323     // the rectangle the diagrams cover in the *plane*:
00324     // (Why -3? We save 1px on each side for the antialiased drawing, and
00325     // respect the way QPainter calculates the width of a painted rect (the
00326     // size is the rectangle size plus the pen width). This way, most clipping
00327     // for regular pens should be avoided. When pens with a penWidth or larger
00328     // than 1 are used, this may not be sufficient.
00329     const QRectF drawArea( drawingArea() );
00330     //qDebug() << "drawingArea() returns" << drawArea;
00331 
00332     const DataDimensionsList dimensions( gridDimensionsList() );
00333     // test for programming errors: critical
00334     Q_ASSERT_X ( dimensions.count() == 2, "CartesianCoordinatePlane::layoutDiagrams",
00335                  "Error: gridDimensionsList() did not return exactly two dimensions." );
00336     const DataDimension dimX = dimensions.first();
00337     const DataDimension dimY = dimensions.last();
00338     const qreal distX = dimX.distance();
00339     const qreal distY = dimY.distance();
00340     //qDebug() << distX << distY;
00341     const QPointF pt(qMin(dimX.start, dimX.end), qMax(dimY.start, dimY.end));
00342     const QSizeF siz( qAbs(distX), -qAbs(distY) );
00343     const QRectF dataBoundingRect( pt, siz );
00344     //qDebug() << "dataBoundingRect" << dataBoundingRect;
00345 
00346     // calculate the remaining rectangle, and use it as the diagram area:
00347     QRectF diagramArea = drawArea;
00348     diagramArea.setTopLeft ( QPointF ( drawArea.left(), drawArea.top() ) );
00349     diagramArea.setBottomRight ( QPointF ( drawArea.right(), drawArea.bottom() ) );
00350 
00351     // determine coordinate transformation:
00352     QPointF diagramTopLeft = dataBoundingRect.topLeft();
00353     double diagramWidth = dataBoundingRect.width();
00354     double diagramHeight = dataBoundingRect.height();
00355     double planeWidth = diagramArea.width();
00356     double planeHeight = diagramArea.height();
00357     double scaleX;
00358     double scaleY;
00359 
00360     double diagramXUnitInCoordinatePlane;
00361     double diagramYUnitInCoordinatePlane;
00362 
00363     diagramXUnitInCoordinatePlane = diagramWidth != 0 ? planeWidth / diagramWidth : 1;
00364     diagramYUnitInCoordinatePlane = diagramHeight != 0 ? planeHeight / diagramHeight : 1;
00365     // calculate isometric scaling factor to maxscale the diagram into
00366     // the coordinate system:
00367     if ( d->isometricScaling )
00368     {
00369         double scale = qMin ( qAbs ( diagramXUnitInCoordinatePlane ),
00370                               qAbs ( diagramYUnitInCoordinatePlane ) );
00371 
00372         scaleX = qAbs( scale / diagramXUnitInCoordinatePlane );
00373         scaleY = qAbs( scale / diagramYUnitInCoordinatePlane );
00374     } else {
00375         scaleX = 1.0;
00376         scaleY = 1.0;
00377     }
00378 
00379     // calculate diagram origin in plane coordinates:
00380     QPointF coordinateOrigin = QPointF (
00381             diagramTopLeft.x() * -diagramXUnitInCoordinatePlane,
00382     diagramTopLeft.y() * -diagramYUnitInCoordinatePlane );
00383     coordinateOrigin += diagramArea.topLeft();
00384 
00385     d->coordinateTransformation.originTranslation = coordinateOrigin;
00386 
00387     d->coordinateTransformation.diagramRect = dataBoundingRect;
00388 
00389     d->coordinateTransformation.unitVectorX = diagramXUnitInCoordinatePlane;
00390     d->coordinateTransformation.unitVectorY = diagramYUnitInCoordinatePlane;
00391 
00392     d->coordinateTransformation.isoScaleX = scaleX;
00393     d->coordinateTransformation.isoScaleY = scaleY;
00394 
00395     //      adapt diagram area to effect of isometric scaling:
00396     diagramArea.setTopLeft( translate ( dataBoundingRect.topLeft() ) );
00397     diagramArea.setBottomRight ( translate ( dataBoundingRect.bottomRight() ) );
00398 
00399     //qDebug("KDChart::CartesianCoordinatePlane::layoutDiagrams() done,\ncalling update() now:");
00400     update();
00401 }
00402 
00403 
00404 const QPointF CartesianCoordinatePlane::translate( const QPointF& diagramPoint ) const
00405 {
00406     // Note: We do not test if the point lays inside of the data area,
00407     //       but we just apply the transformation calculations to the point.
00408     //       This allows for basic calculations done by the user, see e.g.
00409     //       the file  examples/Lines/BubbleChart/mainwindow.cpp
00410     return  d->coordinateTransformation.translate ( diagramPoint );
00411 }
00412 
00413 const QPointF CartesianCoordinatePlane::translateBack( const QPointF& screenPoint ) const
00414 {
00415     return  d->coordinateTransformation.translateBack ( screenPoint );
00416 }
00417 
00418 void CartesianCoordinatePlane::setIsometricScaling ( bool onOff )
00419 {
00420     if ( d->isometricScaling != onOff )
00421     {
00422         d->isometricScaling = onOff;
00423         layoutDiagrams();
00424         emit propertiesChanged();
00425     }
00426 }
00427 
00428 bool CartesianCoordinatePlane::doesIsometricScaling () const
00429 {
00430     return d->isometricScaling;
00431 }
00432 
00433 bool CartesianCoordinatePlane::doneSetZoomFactorX( double factor )
00434 {
00435     bool bDone = ( d->coordinateTransformation.zoom.xFactor != factor );
00436     if( bDone ){
00437         d->coordinateTransformation.zoom.xFactor = factor;
00438         if( d->autoAdjustGridToZoom )
00439             d->grid->setNeedRecalculate();
00440     }
00441     return bDone;
00442 }
00443 
00444 bool CartesianCoordinatePlane::doneSetZoomFactorY( double factor )
00445 {
00446     bool bDone = ( d->coordinateTransformation.zoom.yFactor != factor );
00447     if( bDone ){
00448         d->coordinateTransformation.zoom.yFactor = factor;
00449         if( d->autoAdjustGridToZoom )
00450             d->grid->setNeedRecalculate();
00451     }
00452     return bDone;
00453 }
00454 
00455 bool CartesianCoordinatePlane::doneSetZoomCenter( QPointF point )
00456 {
00457     bool bDone = ( d->coordinateTransformation.zoom.center() != point );
00458     if( bDone ){
00459         d->coordinateTransformation.zoom.setCenter( point );
00460         if( d->autoAdjustGridToZoom )
00461             d->grid->setNeedRecalculate();
00462     }
00463     return bDone;
00464 }
00465 
00466 void CartesianCoordinatePlane::setZoomFactorX( double factor )
00467 {
00468     if( doneSetZoomFactorX( factor ) ){
00469         emit propertiesChanged();
00470     }
00471 }
00472 
00473 void CartesianCoordinatePlane::setZoomFactorY( double factor )
00474 {
00475     if( doneSetZoomFactorY( factor ) ){
00476         emit propertiesChanged();
00477     }
00478 }
00479 
00480 void CartesianCoordinatePlane::setZoomCenter( QPointF point )
00481 {
00482     if( doneSetZoomCenter( point ) ){
00483         emit propertiesChanged();
00484     }
00485 }
00486 
00487 QPointF CartesianCoordinatePlane::zoomCenter() const
00488 {
00489     return d->coordinateTransformation.zoom.center();
00490 }
00491 
00492 double CartesianCoordinatePlane::zoomFactorX() const
00493 {
00494     return d->coordinateTransformation.zoom.xFactor;
00495 }
00496 
00497 double CartesianCoordinatePlane::zoomFactorY() const
00498 {
00499     return d->coordinateTransformation.zoom.yFactor;
00500 }
00501 
00502 
00503 CartesianCoordinatePlane::AxesCalcMode CartesianCoordinatePlane::axesCalcModeY() const
00504 {
00505     return d->coordinateTransformation.axesCalcModeY;
00506 }
00507 
00508 CartesianCoordinatePlane::AxesCalcMode CartesianCoordinatePlane::axesCalcModeX() const
00509 {
00510     return d->coordinateTransformation.axesCalcModeX;
00511 }
00512 
00513 void CartesianCoordinatePlane::setAxesCalcModes( AxesCalcMode mode )
00514 {
00515     if( d->coordinateTransformation.axesCalcModeY != mode ||
00516         d->coordinateTransformation.axesCalcModeX != mode ){
00517         d->coordinateTransformation.axesCalcModeY = mode;
00518         d->coordinateTransformation.axesCalcModeX = mode;
00519         emit propertiesChanged();
00520     }
00521 }
00522 
00523 void CartesianCoordinatePlane::setAxesCalcModeY( AxesCalcMode mode )
00524 {
00525     if( d->coordinateTransformation.axesCalcModeY != mode ){
00526         d->coordinateTransformation.axesCalcModeY = mode;
00527         emit propertiesChanged();
00528     }
00529 }
00530 
00531 void CartesianCoordinatePlane::setAxesCalcModeX( AxesCalcMode mode )
00532 {
00533     if( d->coordinateTransformation.axesCalcModeX != mode ){
00534         d->coordinateTransformation.axesCalcModeX = mode;
00535         emit propertiesChanged();
00536     }
00537 }
00538 
00539 void KDChart::CartesianCoordinatePlane::setHorizontalRange( const QPair< qreal, qreal > & range )
00540 {
00541     if ( d->horizontalMin != range.first || d->horizontalMax != range.second ) {
00542         d->autoAdjustHorizontalRangeToData = 100;
00543         d->horizontalMin = range.first;
00544         d->horizontalMax = range.second;
00545         layoutDiagrams();
00546         emit propertiesChanged();
00547     }
00548 }
00549 
00550 void KDChart::CartesianCoordinatePlane::setVerticalRange( const QPair< qreal, qreal > & range )
00551 {
00552 
00553     if ( d->verticalMin != range.first || d->verticalMax != range.second ) {
00554         d->autoAdjustVerticalRangeToData = 100;
00555         d->verticalMin = range.first;
00556         d->verticalMax = range.second;
00557         layoutDiagrams();
00558         emit propertiesChanged();
00559     }
00560 }
00561 
00562 QPair< qreal, qreal > KDChart::CartesianCoordinatePlane::horizontalRange( ) const
00563 {
00564     return QPair<qreal, qreal>( d->horizontalMin, d->horizontalMax );
00565 }
00566 
00567 QPair< qreal, qreal > KDChart::CartesianCoordinatePlane::verticalRange( ) const
00568 {
00569     return QPair<qreal, qreal>( d->verticalMin, d->verticalMax );
00570 }
00571 
00572 void CartesianCoordinatePlane::adjustRangesToData()
00573 {
00574     const QRectF dataBoundingRect( getRawDataBoundingRectFromDiagrams() );
00575     d->horizontalMin = dataBoundingRect.left();
00576     d->horizontalMax = dataBoundingRect.right();
00577     d->verticalMin = dataBoundingRect.top();
00578     d->verticalMax = dataBoundingRect.bottom();
00579     layoutDiagrams();
00580     emit propertiesChanged();
00581 }
00582 
00583 void CartesianCoordinatePlane::adjustHorizontalRangeToData()
00584 {
00585     const QRectF dataBoundingRect( getRawDataBoundingRectFromDiagrams() );
00586     d->horizontalMin = dataBoundingRect.left();
00587     d->horizontalMax = dataBoundingRect.right();
00588     layoutDiagrams();
00589     emit propertiesChanged();
00590 }
00591 
00592 void CartesianCoordinatePlane::adjustVerticalRangeToData()
00593 {
00594     const QRectF dataBoundingRect( getRawDataBoundingRectFromDiagrams() );
00595     d->verticalMin = dataBoundingRect.bottom();
00596     d->verticalMax = dataBoundingRect.top();
00597     layoutDiagrams();
00598     emit propertiesChanged();
00599 }
00600 
00601 void CartesianCoordinatePlane::setAutoAdjustHorizontalRangeToData( unsigned int percentEmpty )
00602 {
00603     d->autoAdjustHorizontalRangeToData = percentEmpty;
00604     d->horizontalMin = 0.0;
00605     d->horizontalMax = 0.0;
00606     layoutDiagrams();
00607     emit propertiesChanged();
00608 }
00609 
00610 void CartesianCoordinatePlane::setAutoAdjustVerticalRangeToData( unsigned int percentEmpty )
00611 {
00612     d->autoAdjustVerticalRangeToData = percentEmpty;
00613     d->verticalMin = 0.0;
00614     d->verticalMax = 0.0;
00615     layoutDiagrams();
00616     emit propertiesChanged();
00617 }
00618 
00619 unsigned int CartesianCoordinatePlane::autoAdjustHorizontalRangeToData() const
00620 {
00621     return d->autoAdjustHorizontalRangeToData;
00622 }
00623 
00624 unsigned int CartesianCoordinatePlane::autoAdjustVerticalRangeToData() const
00625 {
00626     return d->autoAdjustVerticalRangeToData;
00627 }
00628 
00629 
00630 void KDChart::CartesianCoordinatePlane::setGridAttributes(
00631     Qt::Orientation orientation,
00632     const GridAttributes& a )
00633 {
00634     if( orientation == Qt::Horizontal )
00635         d->gridAttributesHorizontal = a;
00636     else
00637         d->gridAttributesVertical = a;
00638     setHasOwnGridAttributes( orientation, true );
00639     update();
00640     emit propertiesChanged();
00641 }
00642 
00643 void KDChart::CartesianCoordinatePlane::resetGridAttributes(
00644     Qt::Orientation orientation )
00645 {
00646     setHasOwnGridAttributes( orientation, false );
00647     update();
00648 }
00649 
00650 const GridAttributes KDChart::CartesianCoordinatePlane::gridAttributes(
00651     Qt::Orientation orientation ) const
00652 {
00653     if( hasOwnGridAttributes( orientation ) ){
00654         if( orientation == Qt::Horizontal )
00655             return d->gridAttributesHorizontal;
00656         else
00657             return d->gridAttributesVertical;
00658     }else{
00659         return globalGridAttributes();
00660     }
00661 }
00662 
00663 void KDChart::CartesianCoordinatePlane::setHasOwnGridAttributes(
00664     Qt::Orientation orientation, bool on )
00665 {
00666     if( orientation == Qt::Horizontal )
00667         d->hasOwnGridAttributesHorizontal = on;
00668     else
00669         d->hasOwnGridAttributesVertical = on;
00670     emit propertiesChanged();
00671 }
00672 
00673 bool KDChart::CartesianCoordinatePlane::hasOwnGridAttributes(
00674     Qt::Orientation orientation ) const
00675 {
00676     return
00677         ( orientation == Qt::Horizontal )
00678         ? d->hasOwnGridAttributesHorizontal
00679         : d->hasOwnGridAttributesVertical;
00680 }
00681 
00682 void KDChart::CartesianCoordinatePlane::setAutoAdjustGridToZoom( bool autoAdjust )
00683 {
00684     if( d->autoAdjustGridToZoom != autoAdjust ){
00685         d->autoAdjustGridToZoom = autoAdjust;
00686         d->grid->setNeedRecalculate();
00687         emit propertiesChanged();
00688     }
00689 }
00690 
00691 const bool KDChart::CartesianCoordinatePlane::autoAdjustGridToZoom() const
00692 {
00693     return d->autoAdjustGridToZoom;
00694 }
00695 

Generated on Thu May 10 11:06:25 2007 for KD Chart 2 by doxygen 1.3.6