00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kplotwidget.h"
00022 #include "kplotwidget.moc"
00023
00024 #include <math.h>
00025 #include <kdebug.h>
00026
00027 #include <QtGui/QActionEvent>
00028 #include <QHash>
00029 #include <QPainter>
00030 #include <QPixmap>
00031 #include <QToolTip>
00032 #include <QtAlgorithms>
00033
00034 #include "kplotaxis.h"
00035 #include "kplotpoint.h"
00036 #include "kplotobject.h"
00037
00038 #define XPADDING 20
00039 #define YPADDING 20
00040 #define BIGTICKSIZE 10
00041 #define SMALLTICKSIZE 4
00042 #define TICKOFFSET 0
00043
00044 class KPlotWidget::Private
00045 {
00046 public:
00047 Private( KPlotWidget *qq )
00048 : q( qq ),
00049 cBackground( Qt::black ), cForeground( Qt::white ), cGrid( Qt::gray ),
00050 showGrid( false ), showObjectToolTip( true ), useAntialias( false )
00051 {
00052
00053 KPlotAxis *leftAxis = new KPlotAxis();
00054 leftAxis->setTickLabelsShown( true );
00055 axes.insert( LeftAxis, leftAxis );
00056 KPlotAxis *bottomAxis = new KPlotAxis();
00057 bottomAxis->setTickLabelsShown( true );
00058 axes.insert( BottomAxis, bottomAxis );
00059 KPlotAxis *rightAxis = new KPlotAxis();
00060 axes.insert( RightAxis, rightAxis );
00061 KPlotAxis *topAxis = new KPlotAxis();
00062 axes.insert( TopAxis, topAxis );
00063 }
00064
00065 ~Private()
00066 {
00067 qDeleteAll( objectList );
00068 qDeleteAll( axes );
00069 }
00070
00071 KPlotWidget *q;
00072
00073 void calcDataRectLimits( double x1, double x2, double y1, double y2 );
00082 float rectCost( const QRectF &r ) const;
00083
00084
00085 QColor cBackground, cForeground, cGrid;
00086
00087 bool showGrid : 1;
00088 bool showObjectToolTip : 1;
00089 bool useAntialias : 1;
00090
00091 int leftPadding, rightPadding, topPadding, bottomPadding;
00092
00093 QHash<Axis, KPlotAxis*> axes;
00094
00095 QList<KPlotObject*> objectList;
00096
00097 QRectF dataRect, secondDataRect;
00098
00099 QRect pixRect;
00100
00101 float plotMask[100][100];
00102 double px[100], py[100];
00103 };
00104
00105 KPlotWidget::KPlotWidget( QWidget * parent )
00106 : QFrame( parent ), d( new Private( this ) )
00107 {
00108 setAttribute( Qt::WA_OpaquePaintEvent );
00109 setAttribute( Qt::WA_NoSystemBackground );
00110
00111 d->secondDataRect = QRectF();
00112
00113 d->calcDataRectLimits( 0.0, 1.0, 0.0, 1.0 );
00114
00115 setDefaultPaddings();
00116
00117 setMinimumSize( 150, 150 );
00118 resize( minimumSizeHint() );
00119 }
00120
00121 KPlotWidget::~KPlotWidget()
00122 {
00123 delete d;
00124 }
00125
00126 QSize KPlotWidget::minimumSizeHint() const
00127 {
00128 return QSize( 150, 150 );
00129 }
00130
00131 QSize KPlotWidget::sizeHint() const
00132 {
00133 return size();
00134 }
00135
00136 void KPlotWidget::setLimits( double x1, double x2, double y1, double y2 )
00137 {
00138 d->calcDataRectLimits( x1, x2, y1, y2 );
00139 update();
00140 }
00141
00142 void KPlotWidget::Private::calcDataRectLimits( double x1, double x2, double y1, double y2 )
00143 {
00144 double XA1, XA2, YA1, YA2;
00145 if (x2<x1) { XA1=x2; XA2=x1; }
00146 else { XA1=x1; XA2=x2; }
00147 if ( y2<y1) { YA1=y2; YA2=y1; }
00148 else { YA1=y1; YA2=y2; }
00149
00150 if ( XA2 == XA1 ) {
00151 kWarning() << "x1 and x2 cannot be equal. Setting x2 = x1 + 1.0";
00152 XA2 = XA1 + 1.0;
00153 }
00154 if ( YA2 == YA1 ) {
00155 kWarning() << "y1 and y2 cannot be equal. Setting y2 = y1 + 1.0";
00156 YA2 = YA1 + 1.0;
00157 }
00158 dataRect = QRectF( XA1, YA1, XA2 - XA1, YA2 - YA1 );
00159
00160 q->axis( LeftAxis )->setTickMarks( dataRect.y(), dataRect.height() );
00161 q->axis( BottomAxis )->setTickMarks( dataRect.x(), dataRect.width() );
00162
00163 if ( secondDataRect.isNull() )
00164 {
00165 q->axis( RightAxis )->setTickMarks( dataRect.y(), dataRect.height() );
00166 q->axis( TopAxis )->setTickMarks( dataRect.x(), dataRect.width() );
00167 }
00168 }
00169
00170 void KPlotWidget::setSecondaryLimits( double x1, double x2, double y1, double y2 ) {
00171 double XA1, XA2, YA1, YA2;
00172 if (x2<x1) { XA1=x2; XA2=x1; }
00173 else { XA1=x1; XA2=x2; }
00174 if ( y2<y1) { YA1=y2; YA2=y1; }
00175 else { YA1=y1; YA2=y2; }
00176
00177 if ( XA2 == XA1 ) {
00178 kWarning() << "x1 and x2 cannot be equal. Setting x2 = x1 + 1.0";
00179 XA2 = XA1 + 1.0;
00180 }
00181 if ( YA2 == YA1 ) {
00182 kWarning() << "y1 and y2 cannot be equal. Setting y2 = y1 + 1.0";
00183 YA2 = YA1 + 1.0;
00184 }
00185 d->secondDataRect = QRectF( XA1, YA1, XA2-XA1, YA2-YA1 );
00186
00187 axis(RightAxis)->setTickMarks( d->secondDataRect.y(), d->secondDataRect.height() );
00188 axis(TopAxis)->setTickMarks( d->secondDataRect.x(), d->secondDataRect.width() );
00189
00190 update();
00191 }
00192
00193 void KPlotWidget::clearSecondaryLimits() {
00194 d->secondDataRect = QRectF();
00195 axis(RightAxis)->setTickMarks( d->dataRect.y(), d->dataRect.height() );
00196 axis(TopAxis)->setTickMarks( d->dataRect.x(), d->dataRect.width() );
00197
00198 update();
00199 }
00200
00201 QRectF KPlotWidget::dataRect() const
00202 {
00203 return d->dataRect;
00204 }
00205
00206 QRectF KPlotWidget::secondaryDataRect() const
00207 {
00208 return d->secondDataRect;
00209 }
00210
00211 void KPlotWidget::addPlotObject( KPlotObject *object )
00212 {
00213
00214 if ( !object )
00215 return;
00216 d->objectList.append( object );
00217 update();
00218 }
00219
00220 void KPlotWidget::addPlotObjects( const QList< KPlotObject* >& objects )
00221 {
00222 bool addedsome = false;
00223 foreach ( KPlotObject *o, objects )
00224 {
00225 if ( !o )
00226 continue;
00227
00228 d->objectList.append( o );
00229 addedsome = true;
00230 }
00231 if ( addedsome )
00232 update();
00233 }
00234
00235 QList< KPlotObject* > KPlotWidget::plotObjects() const
00236 {
00237 return d->objectList;
00238 }
00239
00240 void KPlotWidget::removeAllPlotObjects()
00241 {
00242 if ( d->objectList.isEmpty() )
00243 return;
00244
00245 qDeleteAll( d->objectList );
00246 d->objectList.clear();
00247 update();
00248 }
00249
00250 void KPlotWidget::resetPlotMask() {
00251 for (int ix=0; ix<100; ++ix )
00252 for ( int iy=0; iy<100; ++iy )
00253 d->plotMask[ix][iy] = 0.0;
00254 }
00255
00256 void KPlotWidget::resetPlot() {
00257 qDeleteAll( d->objectList );
00258 d->objectList.clear();
00259 clearSecondaryLimits();
00260 d->calcDataRectLimits( 0.0, 1.0, 0.0, 1.0 );
00261 KPlotAxis *a = axis( RightAxis );
00262 a->setLabel( QString() );
00263 a->setTickLabelsShown( false );
00264 a = axis( TopAxis );
00265 a->setLabel( QString() );
00266 a->setTickLabelsShown( false );
00267 axis(KPlotWidget::LeftAxis)->setLabel( QString() );
00268 axis(KPlotWidget::BottomAxis)->setLabel( QString() );
00269 resetPlotMask();
00270 }
00271
00272 void KPlotWidget::replacePlotObject( int i, KPlotObject *o )
00273 {
00274
00275 if ( !o || i < 0 || i >= d->objectList.count() )
00276 return;
00277 d->objectList.replace( i, o );
00278 update();
00279 }
00280
00281 QColor KPlotWidget::backgroundColor() const
00282 {
00283 return d->cBackground;
00284 }
00285
00286 QColor KPlotWidget::foregroundColor() const
00287 {
00288 return d->cForeground;
00289 }
00290
00291 QColor KPlotWidget::gridColor() const
00292 {
00293 return d->cGrid;
00294 }
00295
00296 void KPlotWidget::setBackgroundColor( const QColor &bg ) {
00297 d->cBackground = bg;
00298 update();
00299 }
00300
00301 void KPlotWidget::setForegroundColor( const QColor &fg )
00302 {
00303 d->cForeground = fg;
00304 update();
00305 }
00306
00307 void KPlotWidget::setGridColor( const QColor &gc )
00308 {
00309 d->cGrid = gc;
00310 update();
00311 }
00312
00313 bool KPlotWidget::isGridShown() const
00314 {
00315 return d->showGrid;
00316 }
00317
00318 bool KPlotWidget::isObjectToolTipShown() const
00319 {
00320 return d->showObjectToolTip;
00321 }
00322
00323 bool KPlotWidget::antialiasing() const
00324 {
00325 return d->useAntialias;
00326 }
00327
00328 void KPlotWidget::setAntialiasing( bool b )
00329 {
00330 d->useAntialias = b;
00331 update();
00332 }
00333
00334 void KPlotWidget::setShowGrid( bool show ) {
00335 d->showGrid = show;
00336 update();
00337 }
00338
00339 void KPlotWidget::setObjectToolTipShown( bool show )
00340 {
00341 d->showObjectToolTip = show;
00342 }
00343
00344
00345 KPlotAxis* KPlotWidget::axis( Axis type )
00346 {
00347 QHash<Axis, KPlotAxis*>::Iterator it = d->axes.find( type );
00348 return it != d->axes.end() ? it.value() : 0;
00349 }
00350
00351 const KPlotAxis* KPlotWidget::axis( Axis type ) const
00352 {
00353 QHash<Axis, KPlotAxis*>::ConstIterator it = d->axes.find( type );
00354 return it != d->axes.end() ? it.value() : 0;
00355 }
00356
00357 QRect KPlotWidget::pixRect() const
00358 {
00359 return d->pixRect;
00360 }
00361
00362 QList<KPlotPoint*> KPlotWidget::pointsUnderPoint( const QPoint& p ) const {
00363 QList<KPlotPoint*> pts;
00364 foreach ( KPlotObject *po, d->objectList ) {
00365 foreach ( KPlotPoint *pp, po->points() ) {
00366 if ( ( p - mapToWidget( pp->position() ).toPoint() ).manhattanLength() <= 4 )
00367 pts << pp;
00368 }
00369 }
00370
00371 return pts;
00372 }
00373
00374
00375 bool KPlotWidget::event( QEvent* e ) {
00376 if ( e->type() == QEvent::ToolTip ) {
00377 if ( d->showObjectToolTip )
00378 {
00379 QHelpEvent *he = static_cast<QHelpEvent*>( e );
00380 const QList<KPlotPoint*> pts = pointsUnderPoint( he->pos() - QPoint( leftPadding(), topPadding() ) - contentsRect().topLeft() );
00381 if ( pts.count() > 0 ) {
00382 QToolTip::showText( he->globalPos(), pts.front()->label(), this );
00383 }
00384 }
00385 e->accept();
00386 return true;
00387 }
00388 else
00389 return QFrame::event( e );
00390 }
00391
00392 void KPlotWidget::resizeEvent( QResizeEvent* e ) {
00393 QFrame::resizeEvent( e );
00394 }
00395
00396 void KPlotWidget::setPixRect() {
00397 int newWidth = contentsRect().width() - leftPadding() - rightPadding();
00398 int newHeight = contentsRect().height() - topPadding() - bottomPadding();
00399
00400 d->pixRect = QRect( 0, 0, newWidth, newHeight );
00401 for ( int i=0; i<100; ++i ) {
00402 d->px[i] = double(i*d->pixRect.width())/100.0 + double(d->pixRect.x());
00403 d->py[i] = double(i*d->pixRect.height())/100.0 + double(d->pixRect.y());
00404 }
00405 }
00406
00407 QPointF KPlotWidget::mapToWidget( const QPointF& p ) const
00408 {
00409 float px = d->pixRect.left() + d->pixRect.width() * ( p.x() - d->dataRect.x() ) / d->dataRect.width();
00410 float py = d->pixRect.top() + d->pixRect.height() * ( d->dataRect.y() + d->dataRect.height() - p.y() ) / d->dataRect.height();
00411 return QPointF( px, py );
00412 }
00413
00414 void KPlotWidget::maskRect( const QRectF& r, float value ) {
00415
00416 int ix1 = int( 100.0*(r.x() - d->pixRect.x())/d->pixRect.width() );
00417 int iy1 = int( 100.0*(r.y() - d->pixRect.y())/d->pixRect.height() );
00418 if ( ix1 < 0 ) ix1 = 0;
00419 if ( iy1 < 0 ) iy1 = 0;
00420 int ix2 = int( 100.0*(r.right() - d->pixRect.x())/d->pixRect.width() ) + 2;
00421 int iy2 = int( 100.0*(r.bottom() - d->pixRect.y())/d->pixRect.height() ) + 2;
00422 if ( ix1 > 99 ) ix1 = 99;
00423 if ( iy1 > 99 ) iy1 = 99;
00424
00425 for ( int ix=ix1; ix<ix2; ++ix )
00426 for ( int iy=iy1; iy<iy2; ++iy )
00427 d->plotMask[ix][iy] += value;
00428 }
00429
00430 void KPlotWidget::maskAlongLine( const QPointF &p1, const QPointF &p2, float value ) {
00431
00432 double m = (p2.y() - p1.y())/(p2.x() - p1.x());
00433 double y0 = p1.y() - m*p1.x();
00434
00435
00436
00437 double x1 = p1.x();
00438 double x2 = p2.x();
00439 if ( x1 > x2 ) {
00440 x1 = p2.x();
00441 x2 = p1.x();
00442 }
00443 for ( double x=x1; x<x2; x+=0.01*(x2-x1) ) {
00444 double y = y0 + m*x;
00445 int ix = int( 100.0*( x - d->pixRect.x() )/d->pixRect.width() );
00446 int iy = int( 100.0*( y - d->pixRect.y() )/d->pixRect.height() );
00447
00448 if ( ix >= 0 && ix < 100 && iy >= 0 && iy < 100 )
00449 d->plotMask[ix][iy] += value;
00450
00451 }
00452 }
00453
00454 void KPlotWidget::placeLabel( QPainter *painter, KPlotPoint *pp ) {
00455 int textFlags = Qt::TextSingleLine | Qt::AlignCenter;
00456
00457 float rbest = 100;
00458 float bestCost = 1.0e7;
00459 QPointF pos = mapToWidget( pp->position() );
00460 QRectF bestRect;
00461 int ix0 = int( 100.0*( pos.x() - d->pixRect.x() )/d->pixRect.width() );
00462 int iy0 = int( 100.0*( pos.y() - d->pixRect.y() )/d->pixRect.height() );
00463
00464 QFontMetricsF fm( painter->font(), painter->device() );
00465 int xmin = qMax( ix0 - 20, 0 );
00466 int xmax = qMin( ix0 + 20, 100 );
00467 int ymin = qMax( iy0 - 20, 0 );
00468 int ymax = qMin( iy0 + 20, 100 );
00469 for ( int ix = xmin; ix < xmax; ++ix )
00470 {
00471 for ( int iy = ymin; iy < ymax; ++iy )
00472 {
00473 QRectF labelRect = fm.boundingRect( QRectF( d->px[ix], d->py[iy], 1, 1 ), textFlags, pp->label() );
00474
00475 labelRect.adjust( -2, -2, 2, 2 );
00476
00477 float r = sqrt( (float)(ix-ix0)*(ix-ix0) + (iy-iy0)*(iy-iy0) );
00478 float cost = d->rectCost( labelRect ) + 0.1*r;
00479
00480 if ( cost < bestCost ) {
00481 bestRect = labelRect;
00482 bestCost = cost;
00483 rbest = r;
00484 }
00485 }
00486 }
00487
00488 if ( ! bestRect.isNull() ) {
00489 painter->drawText( bestRect, textFlags, pp->label() );
00490
00491
00492 if ( rbest > 2.0 ) {
00493
00494 painter->setBrush( QBrush() );
00495
00496
00497
00498 painter->drawRoundRect( bestRect );
00499
00500
00501
00502 float xline = bestRect.center().x();
00503 if ( bestRect.left() > pos.x() )
00504 xline = bestRect.left();
00505 if ( bestRect.right() < pos.x() )
00506 xline = bestRect.right();
00507
00508 float yline = bestRect.center().y();
00509 if ( bestRect.top() > pos.y() )
00510 yline = bestRect.top();
00511 if ( bestRect.bottom() < pos.y() )
00512 yline = bestRect.bottom();
00513
00514 painter->drawLine( QPointF( xline, yline ), pos );
00515 }
00516
00517
00518 maskRect( bestRect );
00519 }
00520 }
00521
00522 float KPlotWidget::Private::rectCost( const QRectF &r ) const
00523 {
00524 int ix1 = int( 100.0 * ( r.x() - pixRect.x() ) / pixRect.width() );
00525 int ix2 = int( 100.0 * ( r.right() - pixRect.x() ) / pixRect.width() );
00526 int iy1 = int( 100.0 * ( r.y() - pixRect.y() ) / pixRect.height() );
00527 int iy2 = int( 100.0 * ( r.bottom() - pixRect.y() ) / pixRect.height() );
00528 float cost = 0.0;
00529
00530 for ( int ix=ix1; ix<ix2; ++ix ) {
00531 for ( int iy=iy1; iy<iy2; ++iy ) {
00532 if ( ix >= 0 && ix < 100 && iy >= 0 && iy < 100 ) {
00533 cost += plotMask[ix][iy];
00534 } else {
00535 cost += 100.;
00536 }
00537 }
00538 }
00539
00540 return cost;
00541 }
00542
00543 void KPlotWidget::paintEvent( QPaintEvent *e ) {
00544
00545 QFrame::paintEvent( e );
00546 QPainter p;
00547
00548 p.begin( this );
00549 p.setRenderHint( QPainter::Antialiasing, d->useAntialias );
00550 p.fillRect( rect(), backgroundColor() );
00551 p.translate( leftPadding() + 0.5, topPadding() + 0.5 );
00552
00553 setPixRect();
00554 p.setClipRect( d->pixRect );
00555 p.setClipping( true );
00556
00557 resetPlotMask();
00558
00559 foreach( KPlotObject *po, d->objectList )
00560 po->draw( &p, this );
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 p.setClipping( false );
00579 drawAxes( &p );
00580
00581 p.end();
00582 }
00583
00584 void KPlotWidget::drawAxes( QPainter *p ) {
00585 if ( d->showGrid ) {
00586 p->setPen( gridColor() );
00587
00588
00589
00590 foreach ( double xx, axis(BottomAxis)->majorTickMarks() ) {
00591 double px = d->pixRect.width() * (xx - d->dataRect.x()) / d->dataRect.width();
00592 p->drawLine( QPointF( px, 0.0 ), QPointF( px, double(d->pixRect.height()) ) );
00593 }
00594
00595 foreach( double yy, axis(LeftAxis)->majorTickMarks() ) {
00596 double py = d->pixRect.height() * (yy - d->dataRect.y()) / d->dataRect.height();
00597 p->drawLine( QPointF( 0.0, py ), QPointF( double(d->pixRect.width()), py ) );
00598 }
00599 }
00600
00601 p->setPen( foregroundColor() );
00602 p->setBrush( Qt::NoBrush );
00603
00604
00605 QFont f = p->font();
00606 int s = f.pointSize();
00607 f.setPointSize( s - 2 );
00608 p->setFont( f );
00609
00610
00611 KPlotAxis *a = axis(BottomAxis);
00612 if (a->isVisible()) {
00613
00614 p->drawLine( 0, d->pixRect.height(), d->pixRect.width(), d->pixRect.height() );
00615
00616
00617 foreach( double xx, a->majorTickMarks() ) {
00618 double px = d->pixRect.width() * (xx - d->dataRect.x()) / d->dataRect.width();
00619 if ( px > 0 && px < d->pixRect.width() ) {
00620 p->drawLine( QPointF( px, double(d->pixRect.height() - TICKOFFSET)),
00621 QPointF( px, double(d->pixRect.height() - BIGTICKSIZE - TICKOFFSET)) );
00622
00623
00624 if ( a->areTickLabelsShown() ) {
00625 QRect r( int(px) - BIGTICKSIZE, d->pixRect.height()+BIGTICKSIZE, 2*BIGTICKSIZE, BIGTICKSIZE );
00626 p->drawText( r, Qt::AlignCenter | Qt::TextDontClip, a->tickLabel( xx ) );
00627 }
00628 }
00629 }
00630
00631
00632 foreach ( double xx, a->minorTickMarks() ) {
00633 double px = d->pixRect.width() * (xx - d->dataRect.x()) / d->dataRect.width();
00634 if ( px > 0 && px < d->pixRect.width() ) {
00635 p->drawLine( QPointF( px, double(d->pixRect.height() - TICKOFFSET)),
00636 QPointF( px, double(d->pixRect.height() - SMALLTICKSIZE -TICKOFFSET)) );
00637 }
00638 }
00639
00640
00641 if ( ! a->label().isEmpty() ) {
00642 QRect r( 0, d->pixRect.height() + 2*YPADDING, d->pixRect.width(), YPADDING );
00643 p->drawText( r, Qt::AlignCenter, a->label() );
00644 }
00645 }
00646
00647
00648 a = axis(LeftAxis);
00649 if (a->isVisible()) {
00650
00651 p->drawLine( 0, 0, 0, d->pixRect.height() );
00652
00653
00654 foreach( double yy, a->majorTickMarks() ) {
00655 double py = d->pixRect.height() * ( 1.0 - (yy - d->dataRect.y()) / d->dataRect.height() );
00656 if ( py > 0 && py < d->pixRect.height() ) {
00657 p->drawLine( QPointF( TICKOFFSET, py ), QPointF( double(TICKOFFSET + BIGTICKSIZE), py ) );
00658
00659
00660 if ( a->areTickLabelsShown() ) {
00661 QRect r( -2*BIGTICKSIZE-SMALLTICKSIZE, int(py)-SMALLTICKSIZE, 2*BIGTICKSIZE, 2*SMALLTICKSIZE );
00662 p->drawText( r, Qt::AlignRight | Qt::AlignVCenter | Qt::TextDontClip, a->tickLabel( yy ) );
00663 }
00664 }
00665 }
00666
00667
00668 foreach ( double yy, a->minorTickMarks() ) {
00669 double py = d->pixRect.height() * ( 1.0 - (yy - d->dataRect.y()) / d->dataRect.height() );
00670 if ( py > 0 && py < d->pixRect.height() ) {
00671 p->drawLine( QPointF( TICKOFFSET, py ), QPointF( double(TICKOFFSET + SMALLTICKSIZE), py ) );
00672 }
00673 }
00674
00675
00676 if ( ! a->label().isEmpty() ) {
00677
00678 p->save();
00679
00680
00681 p->translate( -3*XPADDING, d->pixRect.height() );
00682 p->rotate( -90.0 );
00683
00684 QRect r( 0, 0, d->pixRect.height(), XPADDING );
00685 p->drawText( r, Qt::AlignCenter, a->label() );
00686
00687 p->restore();
00688 }
00689 }
00690
00691
00692 double x0 = d->dataRect.x();
00693 double y0 = d->dataRect.y();
00694 double dw = d->dataRect.width();
00695 double dh = d->dataRect.height();
00696 if ( secondaryDataRect().isValid() ) {
00697 x0 = secondaryDataRect().x();
00698 y0 = secondaryDataRect().y();
00699 dw = secondaryDataRect().width();
00700 dh = secondaryDataRect().height();
00701 }
00702
00703
00704 a = axis(TopAxis);
00705 if (a->isVisible()) {
00706
00707 p->drawLine( 0, 0, d->pixRect.width(), 0 );
00708
00709
00710 foreach( double xx, a->majorTickMarks() ) {
00711 double px = d->pixRect.width() * (xx - x0) / dw;
00712 if ( px > 0 && px < d->pixRect.width() ) {
00713 p->drawLine( QPointF( px, TICKOFFSET ), QPointF( px, double(BIGTICKSIZE + TICKOFFSET)) );
00714
00715
00716 if ( a->areTickLabelsShown() ) {
00717 QRect r( int(px) - BIGTICKSIZE, (int)-1.5*BIGTICKSIZE, 2*BIGTICKSIZE, BIGTICKSIZE );
00718 p->drawText( r, Qt::AlignCenter | Qt::TextDontClip, a->tickLabel( xx ) );
00719 }
00720 }
00721 }
00722
00723
00724 foreach ( double xx, a->minorTickMarks() ) {
00725 double px = d->pixRect.width() * (xx - x0) / dw;
00726 if ( px > 0 && px < d->pixRect.width() ) {
00727 p->drawLine( QPointF( px, TICKOFFSET ), QPointF( px, double(SMALLTICKSIZE + TICKOFFSET)) );
00728 }
00729 }
00730
00731
00732 if ( ! a->label().isEmpty() ) {
00733 QRect r( 0, 0 - 3*YPADDING, d->pixRect.width(), YPADDING );
00734 p->drawText( r, Qt::AlignCenter, a->label() );
00735 }
00736 }
00737
00738
00739 a = axis(RightAxis);
00740 if (a->isVisible()) {
00741
00742 p->drawLine( d->pixRect.width(), 0, d->pixRect.width(), d->pixRect.height() );
00743
00744
00745 foreach( double yy, a->majorTickMarks() ) {
00746 double py = d->pixRect.height() * ( 1.0 - (yy - y0) / dh );
00747 if ( py > 0 && py < d->pixRect.height() ) {
00748 p->drawLine( QPointF( double(d->pixRect.width() - TICKOFFSET), py ),
00749 QPointF( double(d->pixRect.width() - TICKOFFSET - BIGTICKSIZE), py ) );
00750
00751
00752 if ( a->areTickLabelsShown() ) {
00753 QRect r( d->pixRect.width() + SMALLTICKSIZE, int(py)-SMALLTICKSIZE, 2*BIGTICKSIZE, 2*SMALLTICKSIZE );
00754 p->drawText( r, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, a->tickLabel( yy ) );
00755 }
00756 }
00757 }
00758
00759
00760 foreach ( double yy, a->minorTickMarks() ) {
00761 double py = d->pixRect.height() * ( 1.0 - (yy - y0) / dh );
00762 if ( py > 0 && py < d->pixRect.height() ) {
00763 p->drawLine( QPointF( double(d->pixRect.width() - 0.0), py ),
00764 QPointF( double(d->pixRect.width() - 0.0 - SMALLTICKSIZE), py ) );
00765 }
00766 }
00767
00768
00769 if ( ! a->label().isEmpty() ) {
00770
00771 p->save();
00772
00773
00774 p->translate( d->pixRect.width() + 2*XPADDING, d->pixRect.height() );
00775 p->rotate( -90.0 );
00776
00777 QRect r( 0, 0, d->pixRect.height(), XPADDING );
00778 p->drawText( r, Qt::AlignCenter, a->label() );
00779
00780 p->restore();
00781 }
00782 }
00783 }
00784
00785 int KPlotWidget::leftPadding() const
00786 {
00787 if ( d->leftPadding >= 0 )
00788 return d->leftPadding;
00789 const KPlotAxis *a = axis( LeftAxis );
00790 if ( a && a->isVisible() && a->areTickLabelsShown() )
00791 {
00792 return !a->label().isEmpty() ? 3 * XPADDING : 2 * XPADDING;
00793 }
00794 return XPADDING;
00795 }
00796
00797 int KPlotWidget::rightPadding() const
00798 {
00799 if ( d->rightPadding >= 0 )
00800 return d->rightPadding;
00801 const KPlotAxis *a = axis( RightAxis );
00802 if ( a && a->isVisible() && a->areTickLabelsShown() )
00803 {
00804 return !a->label().isEmpty() ? 3 * XPADDING : 2 * XPADDING;
00805 }
00806 return XPADDING;
00807 }
00808
00809 int KPlotWidget::topPadding() const
00810 {
00811 if ( d->topPadding >= 0 )
00812 return d->topPadding;
00813 const KPlotAxis *a = axis( TopAxis );
00814 if ( a && a->isVisible() && a->areTickLabelsShown() )
00815 {
00816 return !a->label().isEmpty() ? 3 * YPADDING : 2 * YPADDING;
00817 }
00818 return YPADDING;
00819 }
00820
00821 int KPlotWidget::bottomPadding() const
00822 {
00823 if ( d->bottomPadding >= 0 )
00824 return d->bottomPadding;
00825 const KPlotAxis *a = axis( BottomAxis );
00826 if ( a && a->isVisible() && a->areTickLabelsShown() )
00827 {
00828 return !a->label().isEmpty() ? 3 * YPADDING : 2 * YPADDING;
00829 }
00830 return YPADDING;
00831 }
00832
00833 void KPlotWidget::setLeftPadding( int padding )
00834 {
00835 d->leftPadding = padding;
00836 }
00837
00838 void KPlotWidget::setRightPadding( int padding )
00839 {
00840 d->rightPadding = padding;
00841 }
00842
00843 void KPlotWidget::setTopPadding( int padding )
00844 {
00845 d->topPadding = padding;
00846 }
00847
00848 void KPlotWidget::setBottomPadding( int padding )
00849 {
00850 d->bottomPadding = padding;
00851 }
00852
00853 void KPlotWidget::setDefaultPaddings()
00854 {
00855 d->leftPadding = -1;
00856 d->rightPadding = -1;
00857 d->topPadding = -1;
00858 d->bottomPadding = -1;
00859 }
00860