00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "KDChartAbstractCoordinatePlane.h"
00027 #include "KDChartAbstractCoordinatePlane_p.h"
00028
00029 #include <QGridLayout>
00030 #include <QRubberBand>
00031 #include <QMouseEvent>
00032
00033 #include "KDChartChart.h"
00034 #include "KDChartGridAttributes.h"
00035
00036 #include <KDABLibFakes>
00037
00038
00039 using namespace KDChart;
00040
00041 #define d d_func()
00042
00043 AbstractCoordinatePlane::Private::Private()
00044 : AbstractArea::Private()
00045 , parent( 0 )
00046 , grid( 0 )
00047 , referenceCoordinatePlane( 0 )
00048 , enableRubberBandZooming( false )
00049 , rubberBand( 0 )
00050 {
00051
00052 }
00053
00054
00055 AbstractCoordinatePlane::AbstractCoordinatePlane ( KDChart::Chart* parent )
00056 : AbstractArea ( new Private() )
00057 {
00058 d->parent = parent;
00059 d->init();
00060 }
00061
00062 AbstractCoordinatePlane::~AbstractCoordinatePlane()
00063 {
00064 emit destroyedCoordinatePlane( this );
00065 }
00066
00067 void AbstractCoordinatePlane::init()
00068 {
00069 d->initialize();
00070 connect( this, SIGNAL(internal_geometryChanged( QRect, QRect )),
00071 this, SIGNAL(geometryChanged( QRect, QRect )),
00072 Qt::QueuedConnection );
00073 }
00074
00075 void AbstractCoordinatePlane::addDiagram ( AbstractDiagram* diagram )
00076 {
00077
00078 diagram->hide();
00079
00080 d->diagrams.append( diagram );
00081 diagram->setParent( d->parent );
00082 diagram->setCoordinatePlane( this );
00083 layoutDiagrams();
00084 layoutPlanes();
00085 connect( diagram, SIGNAL( modelsChanged() ), this, SLOT( layoutPlanes() ) );
00086 update();
00087 }
00088
00089
00090 void AbstractCoordinatePlane::replaceDiagram ( AbstractDiagram* diagram, AbstractDiagram* oldDiagram_ )
00091 {
00092 if( diagram && oldDiagram_ != diagram ){
00093 AbstractDiagram* oldDiagram = oldDiagram_;
00094 if( d->diagrams.count() ){
00095 if( ! oldDiagram ){
00096 oldDiagram = d->diagrams.first();
00097 if( oldDiagram == diagram )
00098 return;
00099 }
00100 takeDiagram( oldDiagram );
00101 }
00102 delete oldDiagram;
00103 addDiagram( diagram );
00104 layoutDiagrams();
00105 layoutPlanes();
00106 update();
00107 }
00108 }
00109
00110
00111 void AbstractCoordinatePlane::takeDiagram ( AbstractDiagram* diagram )
00112 {
00113 const int idx = d->diagrams.indexOf( diagram );
00114 if( idx != -1 ){
00115 d->diagrams.removeAt( idx );
00116 diagram->setParent( 0 );
00117 diagram->setCoordinatePlane( 0 );
00118 disconnect( diagram, SIGNAL( modelsChanged() ), this, SLOT( layoutPlanes() ) );
00119 layoutDiagrams();
00120 update();
00121 }
00122 }
00123
00124
00125 AbstractDiagram* AbstractCoordinatePlane::diagram()
00126 {
00127 if ( d->diagrams.isEmpty() )
00128 {
00129 return 0;
00130 } else {
00131 return d->diagrams.first();
00132 }
00133 }
00134
00135 AbstractDiagramList AbstractCoordinatePlane::diagrams()
00136 {
00137 return d->diagrams;
00138 }
00139
00140 ConstAbstractDiagramList AbstractCoordinatePlane::diagrams() const
00141 {
00142 ConstAbstractDiagramList list;
00143 #ifndef QT_NO_STL
00144 qCopy( d->diagrams.begin(), d->diagrams.end(), std::back_inserter( list ) );
00145 #else
00146 Q_FOREACH( AbstractDiagram * a, d->diagrams )
00147 list.push_back( a );
00148 #endif
00149 return list;
00150 }
00151
00152 QSize KDChart::AbstractCoordinatePlane::minimumSizeHint() const
00153 {
00154 return QSize( 200, 200 );
00155 }
00156
00157
00158 QSizePolicy KDChart::AbstractCoordinatePlane::sizePolicy() const
00159 {
00160 return QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
00161 }
00162
00163 void KDChart::AbstractCoordinatePlane::setGlobalGridAttributes( const GridAttributes& a )
00164 {
00165 d->gridAttributes = a;
00166 update();
00167 }
00168
00169 GridAttributes KDChart::AbstractCoordinatePlane::globalGridAttributes() const
00170 {
00171 return d->gridAttributes;
00172 }
00173
00174 KDChart::DataDimensionsList KDChart::AbstractCoordinatePlane::gridDimensionsList()
00175 {
00176
00177
00178
00179 return d->grid->updateData( this );
00180 }
00181
00182 void KDChart::AbstractCoordinatePlane::setGridNeedsRecalculate()
00183 {
00184 d->grid->setNeedRecalculate();
00185 }
00186
00187 void KDChart::AbstractCoordinatePlane::setReferenceCoordinatePlane( AbstractCoordinatePlane * plane )
00188 {
00189 d->referenceCoordinatePlane = plane;
00190 }
00191
00192 AbstractCoordinatePlane * KDChart::AbstractCoordinatePlane::referenceCoordinatePlane( ) const
00193 {
00194 return d->referenceCoordinatePlane;
00195 }
00196
00197 void KDChart::AbstractCoordinatePlane::setParent( KDChart::Chart* parent )
00198 {
00199 d->parent = parent;
00200 }
00201
00202 const KDChart::Chart* KDChart::AbstractCoordinatePlane::parent() const
00203 {
00204 return d->parent;
00205 }
00206
00207 KDChart::Chart* KDChart::AbstractCoordinatePlane::parent()
00208 {
00209 return d->parent;
00210 }
00211
00212
00213 bool KDChart::AbstractCoordinatePlane::isEmpty() const
00214 {
00215 return false;
00216
00217
00218 }
00219
00220 Qt::Orientations KDChart::AbstractCoordinatePlane::expandingDirections() const
00221 {
00222 return Qt::Vertical | Qt::Horizontal;
00223 }
00224
00225 QSize KDChart::AbstractCoordinatePlane::maximumSize() const
00226 {
00227
00228
00229 return QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX);
00230 }
00231
00232 QSize KDChart::AbstractCoordinatePlane::minimumSize() const
00233 {
00234 return QSize(60, 60);
00235 }
00236
00237 QSize KDChart::AbstractCoordinatePlane::sizeHint() const
00238 {
00239
00240
00241 return maximumSize();
00242 }
00243
00244 void KDChart::AbstractCoordinatePlane::setGeometry( const QRect& r )
00245 {
00246
00247 if( d->geometry != r ){
00248
00249
00250
00251 emit internal_geometryChanged( d->geometry, r );
00252
00253 d->geometry = r;
00254
00255
00256
00257 }
00258 }
00259
00260 QRect KDChart::AbstractCoordinatePlane::geometry() const
00261 {
00262 return d->geometry;
00263 }
00264
00265 void KDChart::AbstractCoordinatePlane::update()
00266 {
00267
00268 emit needUpdate();
00269 }
00270
00271 void KDChart::AbstractCoordinatePlane::relayout()
00272 {
00273
00274 emit needRelayout();
00275 }
00276
00277 void KDChart::AbstractCoordinatePlane::layoutPlanes()
00278 {
00279
00280 emit needLayoutPlanes();
00281 }
00282
00283 void KDChart::AbstractCoordinatePlane::setRubberBandZoomingEnabled( bool enable )
00284 {
00285 d->enableRubberBandZooming = enable;
00286
00287 if( !enable && d->rubberBand != 0 )
00288 {
00289 delete d->rubberBand;
00290 d->rubberBand = 0;
00291 }
00292 }
00293
00294 bool KDChart::AbstractCoordinatePlane::isRubberBandZoomingEnabled() const
00295 {
00296 return d->enableRubberBandZooming;
00297 }
00298
00299 void KDChart::AbstractCoordinatePlane::mousePressEvent( QMouseEvent* event )
00300 {
00301 if( event->button() == Qt::LeftButton )
00302 {
00303 if( d->enableRubberBandZooming && d->rubberBand == 0 )
00304 d->rubberBand = new QRubberBand( QRubberBand::Rectangle, qobject_cast< QWidget* >( parent() ) );
00305
00306 if( d->rubberBand != 0 )
00307 {
00308 d->rubberBandOrigin = event->pos();
00309 d->rubberBand->setGeometry( QRect( event->pos(), QSize() ) );
00310 d->rubberBand->show();
00311
00312 event->accept();
00313 }
00314 }
00315 else if( event->button() == Qt::RightButton )
00316 {
00317 if( d->enableRubberBandZooming && !d->rubberBandZoomConfigHistory.isEmpty() )
00318 {
00319
00320 ZoomParameters config = d->rubberBandZoomConfigHistory.pop();
00321 setZoomFactorX( config.xFactor );
00322 setZoomFactorY( config.yFactor );
00323 setZoomCenter( config.center() );
00324
00325 QWidget* const p = qobject_cast< QWidget* >( parent() );
00326 if( p != 0 )
00327 p->update();
00328
00329 event->accept();
00330 }
00331 }
00332
00333 KDAB_FOREACH( AbstractDiagram * a, d->diagrams )
00334 {
00335 a->mousePressEvent( event );
00336 }
00337 }
00338
00339 void KDChart::AbstractCoordinatePlane::mouseDoubleClickEvent( QMouseEvent* event )
00340 {
00341 if( event->button() == Qt::RightButton )
00342 {
00343
00344
00345 mousePressEvent( event );
00346 }
00347 KDAB_FOREACH( AbstractDiagram * a, d->diagrams )
00348 {
00349 a->mouseDoubleClickEvent( event );
00350 }
00351 }
00352
00353 void KDChart::AbstractCoordinatePlane::mouseReleaseEvent( QMouseEvent* event )
00354 {
00355 if( d->rubberBand != 0 )
00356 {
00357
00358 d->rubberBandZoomConfigHistory.push( ZoomParameters( zoomFactorX(), zoomFactorY(), zoomCenter() ) );
00359
00360
00361 const double rubberWidth = static_cast< double >( d->rubberBand->width() );
00362 const double rubberHeight = static_cast< double >( d->rubberBand->height() );
00363
00364 if( rubberWidth > 0.0 && rubberHeight > 0.0 )
00365 {
00366
00367 const double rubberCenterX = static_cast< double >( d->rubberBand->geometry().center().x() - geometry().x() );
00368 const double rubberCenterY = static_cast< double >( d->rubberBand->geometry().center().y() - geometry().y() );
00369
00370
00371 const double myWidth = static_cast< double >( geometry().width() );
00372 const double myHeight = static_cast< double >( geometry().height() );
00373
00374
00375 const double newCenterX = rubberCenterX / myWidth / zoomFactorX() + zoomCenter().x() - 0.5 / zoomFactorX();
00376 const double newCenterY = rubberCenterY / myHeight / zoomFactorY() + zoomCenter().y() - 0.5 / zoomFactorY();
00377
00378
00379 const double newZoomFactorX = zoomFactorX() * myWidth / rubberWidth;
00380 const double newZoomFactorY = zoomFactorY() * myHeight / rubberHeight;
00381
00382
00383 const QPointF newZoomCenter( newCenterX, newCenterY );
00384
00385 setZoomFactorX( newZoomFactorX );
00386 setZoomFactorY( newZoomFactorY );
00387 setZoomCenter( newZoomCenter );
00388 }
00389
00390 d->rubberBand->parentWidget()->update();
00391 delete d->rubberBand;
00392 d->rubberBand = 0;
00393
00394 event->accept();
00395 }
00396
00397 KDAB_FOREACH( AbstractDiagram * a, d->diagrams )
00398 {
00399 a->mouseReleaseEvent( event );
00400 }
00401 }
00402
00403 void KDChart::AbstractCoordinatePlane::mouseMoveEvent( QMouseEvent* event )
00404 {
00405 if( d->rubberBand != 0 )
00406 {
00407 const QRect normalized = QRect( d->rubberBandOrigin, event->pos() ).normalized();
00408 d->rubberBand->setGeometry( normalized & geometry() );
00409
00410 event->accept();
00411 }
00412
00413 KDAB_FOREACH( AbstractDiagram * a, d->diagrams )
00414 {
00415 a->mouseMoveEvent( event );
00416 }
00417 }
00418
00419 #if QT_VERSION < 0x040400 || defined(Q_COMPILER_MANGLES_RETURN_TYPE)
00420 const
00421 #endif
00422 bool KDChart::AbstractCoordinatePlane::isVisiblePoint( const QPointF& point ) const
00423 {
00424 return d->isVisiblePoint( this, point );
00425 }
00426
00427 AbstractCoordinatePlane* KDChart::AbstractCoordinatePlane::sharedAxisMasterPlane( QPainter* p )
00428 {
00429 Q_UNUSED( p );
00430 return this;
00431 }
00432
00433 #if !defined(QT_NO_DEBUG_STREAM)
00434 #include "KDChartEnums.h"
00435
00436 QDebug KDChart::operator<<( QDebug stream, const DataDimension& r )
00437 {
00438 stream << "DataDimension("
00439 << " start=" << r.start
00440 << " end=" << r.end
00441 << " sequence=" << KDChartEnums::granularitySequenceToString( r.sequence )
00442 << " isCalculated=" << r.isCalculated
00443 << " calcMode=" << ( r.calcMode == AbstractCoordinatePlane::Logarithmic ? "Logarithmic" : "Linear" )
00444 << " stepWidth=" << r.stepWidth
00445 << " subStepWidth=" << r.subStepWidth
00446 << " )";
00447 return stream;
00448 }
00449 #endif
00450
00451 #undef d