• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDEUI

kplotwidget.cpp

Go to the documentation of this file.
00001 /*  -*- C++ -*-
00002     This file is part of the KDE libraries
00003     Copyright (C) 2003 Jason Harris <kstars@30doradus.org>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, USA.
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         // create the axes and setting their default properties
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     //Colors
00085     QColor cBackground, cForeground, cGrid;
00086     //draw options
00087     bool showGrid : 1;
00088     bool showObjectToolTip : 1;
00089     bool useAntialias : 1;
00090     //padding
00091     int leftPadding, rightPadding, topPadding, bottomPadding;
00092     // hashmap with the axes we have
00093     QHash<Axis, KPlotAxis*> axes;
00094     // List of KPlotObjects
00095     QList<KPlotObject*> objectList;
00096     // Limits of the plot area in data units
00097     QRectF dataRect, secondDataRect;
00098     // Limits of the plot area in pixel units
00099     QRect pixRect;
00100     // Grid of bools to mask "used" regions of the plot
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(); //default: no secondary data rect
00112     // sets the default limits
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     // skip null pointers
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     // skip null pointers and invalid indexes
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     // PixRect starts at (0,0) because we will translate by leftPadding(), topPadding()
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     //Loop over Mask grid points that are near the target rectangle.
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     //Determine slope and zeropoint of line
00432     double m = (p2.y() - p1.y())/(p2.x() - p1.x());
00433     double y0 = p1.y() - m*p1.x();
00434  
00435     //Make steps along line from p1 to p2, computing the nearest 
00436     //gridpoint position at each point.
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                 //Add some padding to labelRect
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         //Is a line needed to connect the label to the point?
00492         if ( rbest > 2.0 ) {
00493             //Draw a rectangle around the label 
00494             painter->setBrush( QBrush() );
00495             //QPen pen = painter->pen();
00496             //pen.setStyle( Qt::DotLine );
00497             //painter->setPen( pen );
00498             painter->drawRoundRect( bestRect );
00499     
00500             //Now connect the label to the point with a line.
00501             //The line is drawn from the center of the near edge of the rectangle
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         //Mask the label's rectangle so other labels won't overlap it.
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     // let QFrame draw its default stuff (like the frame)
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     //DEBUG_MASK
00563     /*
00564     p.setPen( Qt::magenta );
00565     p.setBrush( Qt::magenta );
00566     for ( int ix=0; ix<100; ++ix ) {
00567         for ( int iy=0; iy<100; ++iy ) {
00568             if ( PlotMask[ix][iy] > 0.0 ) {
00569                 double x = d->pixRect.x() + double(ix*d->pixRect.width())/100.;
00570                 double y = d->pixRect.y() + double(iy*d->pixRect.height())/100.;
00571 
00572                 p.drawRect( QRectF(x-1, y-1, 2, 2 ) );
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         //Grid lines are placed at locations of primary axes' major tickmarks
00589         //vertical grid lines
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         //horizontal grid lines
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     //set small font for tick labels
00605     QFont f = p->font();
00606     int s = f.pointSize();
00607     f.setPointSize( s - 2 );
00608     p->setFont( f );
00609 
00610     /*** BottomAxis ***/
00611     KPlotAxis *a = axis(BottomAxis);
00612     if (a->isVisible()) {
00613         //Draw axis line
00614         p->drawLine( 0, d->pixRect.height(), d->pixRect.width(), d->pixRect.height() );
00615 
00616         // Draw major tickmarks
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                 //Draw ticklabel
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         // Draw minor tickmarks
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         // Draw BottomAxis Label
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     }  //End of BottomAxis
00646 
00647     /*** LeftAxis ***/
00648     a = axis(LeftAxis);
00649     if (a->isVisible()) {
00650         //Draw axis line
00651         p->drawLine( 0, 0, 0, d->pixRect.height() );
00652 
00653         // Draw major tickmarks
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                 //Draw ticklabel
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         // Draw minor tickmarks
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         //Draw LeftAxis Label.  We need to draw the text sideways.
00676         if ( ! a->label().isEmpty() ) {
00677             //store current painter translation/rotation state
00678             p->save();
00679     
00680             //translate coord sys to left corner of axis label rectangle, then rotate 90 degrees.
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() ); //draw the label, now that we are sideways
00686     
00687             p->restore();  //restore translation/rotation state
00688         }
00689     }  //End of LeftAxis
00690 
00691     //Prepare for top and right axes; we may need the secondary data rect
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     /*** TopAxis ***/
00704     a = axis(TopAxis);
00705     if (a->isVisible()) {
00706         //Draw axis line
00707         p->drawLine( 0, 0, d->pixRect.width(), 0 );
00708 
00709         // Draw major tickmarks
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                 //Draw ticklabel
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         // Draw minor tickmarks
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         // Draw TopAxis Label
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     }  //End of TopAxis
00737 
00738     /*** RightAxis ***/
00739     a = axis(RightAxis);
00740     if (a->isVisible()) {
00741         //Draw axis line
00742         p->drawLine( d->pixRect.width(), 0, d->pixRect.width(), d->pixRect.height() );
00743 
00744         // Draw major tickmarks
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                 //Draw ticklabel
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         // Draw minor tickmarks
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         //Draw RightAxis Label.  We need to draw the text sideways.
00769         if ( ! a->label().isEmpty() ) {
00770             //store current painter translation/rotation state
00771             p->save();
00772     
00773             //translate coord sys to left corner of axis label rectangle, then rotate 90 degrees.
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() ); //draw the label, now that we are sideways
00779     
00780             p->restore();  //restore translation/rotation state
00781         }
00782     }  //End of RightAxis
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 

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal