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

qwt_wheel.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 #include <qdrawutil.h>
00011 #include <qpixmap.h>
00012 #include <qpainter.h>
00013 #include <qstyle.h>
00014 #include "qwt_math.h"
00015 #include "qwt_paint_buffer.h"
00016 #include "qwt_wheel.h"
00017 
00018 
00020 QwtWheel::QwtWheel(QWidget *parent, const char *name): 
00021     QwtSliderBase(Qt::Horizontal, parent, name, WRepaintNoErase|WResizeNoErase )
00022 {
00023     d_viewAngle = 175.0;
00024     d_totalAngle = 360.0;
00025     d_tickCnt = 10;
00026     d_intBorder = 2;
00027     d_borderWidth = 2;
00028     d_colorCnt = 30;
00029     d_wheelWidth = 20;
00030     d_allocContext = 0;
00031     d_colors = new QColor[d_colorCnt];
00032     setUpdateTime(50);
00033 }
00034 
00036 QwtWheel::~QwtWheel()  
00037 {
00038     if ( d_allocContext )
00039         QColor::destroyAllocContext( d_allocContext );
00040     delete[] d_colors;
00041 }
00042 
00044 void QwtWheel::setColorArray()
00045 {
00046     if ( !d_colors ) 
00047         return;
00048 
00049     QColorGroup g = colorGroup();
00050 
00051     if ( !d_colors[0].isValid() ||
00052         d_colors[0] != g.light() ||
00053         d_colors[d_colorCnt - 1] != g.dark() )
00054     {
00055         if ( d_allocContext )
00056             QColor::destroyAllocContext( d_allocContext );
00057 
00058         d_allocContext = QColor::enterAllocContext();
00059 
00060         d_colors[0] = g.light();
00061         d_colors[d_colorCnt - 1] = g.dark();
00062 
00063         int dh, ds, dv, lh, ls, lv;
00064         d_colors[0].rgb(&lh, &ls, &lv);
00065         d_colors[d_colorCnt - 1].rgb(&dh, &ds, &dv);
00066 
00067         for ( int i = 1; i < d_colorCnt - 1; ++i )
00068         {
00069             const double factor = double(i) / double(d_colorCnt);
00070 
00071             d_colors[i].setRgb( lh + int( double(dh - lh) * factor ),
00072                       ls + int( double(ds - ls) * factor ),
00073                       lv + int( double(dv - lv) * factor ));
00074         }
00075         QColor::leaveAllocContext();
00076     }
00077 }
00078 
00087 void QwtWheel::setTickCnt(int cnt)
00088 {
00089     d_tickCnt = qwtLim( cnt, 6, 50 );
00090     update();
00091 }
00092 
00096 double QwtWheel::mass() const
00097 {
00098     return QwtSliderBase::mass();
00099 }
00100 
00101 
00102 
00113 void QwtWheel::setInternalBorder( int w )
00114 {
00115     const int d = qwtMin( width(), height() ) / 3;
00116     w = qwtMin( w, d );
00117     d_intBorder = qwtMax( w, 1 );
00118     layoutWheel();
00119 }
00120 
00122 void QwtWheel::drawWheelBackground( QPainter *p, const QRect &r )
00123 {
00124     p->save();
00125 
00126     //
00127     // initialize pens
00128     //
00129     const QColorGroup g = colorGroup();
00130 
00131     QPen lightPen;
00132     lightPen.setColor(g.light());
00133     lightPen.setWidth(d_intBorder);
00134 
00135     QPen darkPen;
00136     darkPen.setColor(g.dark());
00137     darkPen.setWidth(d_intBorder);
00138 
00139     setColorArray();
00140 
00141     //
00142     // initialize auxiliary variables
00143     //
00144 
00145     const int nFields = d_colorCnt * 13 / 10;
00146     const int hiPos = nFields - d_colorCnt + 1;
00147 
00148     if ( orientation() == Qt::Horizontal )
00149     {
00150         const int rx = r.x();
00151         int ry = r.y() + d_intBorder;
00152         const int rh = r.height() - 2* d_intBorder;
00153         const int rw = r.width();
00154         //
00155         //  draw shaded background
00156         //
00157         int x1 = rx;
00158         for (int i = 1; i < nFields; i++ )
00159         {
00160             const int x2 = rx + (rw * i) / nFields;
00161             p->fillRect(x1, ry, x2-x1 + 1 ,rh, d_colors[qwtAbs(i-hiPos)]);
00162             x1 = x2 + 1;
00163         }
00164         p->fillRect(x1, ry, rw - (x1 - rx), rh, d_colors[d_colorCnt - 1]);
00165 
00166         //
00167         // draw internal border
00168         //
00169         p->setPen(lightPen);
00170         ry = r.y() + d_intBorder / 2;
00171         p->drawLine(r.x(), ry, r.x() + r.width() , ry);
00172 
00173         p->setPen(darkPen);
00174         ry = r.y() + r.height() - (d_intBorder - d_intBorder / 2);
00175         p->drawLine(r.x(), ry , r.x() + r.width(), ry);
00176     }
00177     else // Qt::Vertical
00178     {
00179         int rx = r.x() + d_intBorder;
00180         const int ry = r.y();
00181         const int rh = r.height();
00182         const int rw = r.width() - 2 * d_intBorder;
00183 
00184         //
00185         // draw shaded background
00186         //
00187         int y1 = ry;
00188         for ( int i = 1; i < nFields; i++ )
00189         {
00190             const int y2 = ry + (rh * i) / nFields;
00191             p->fillRect(rx, y1, rw, y2-y1 + 1, d_colors[qwtAbs(i-hiPos)]);
00192             y1 = y2 + 1;
00193         }
00194         p->fillRect(rx, y1, rw, rh - (y1 - ry), d_colors[d_colorCnt - 1]);
00195 
00196         //
00197         //  draw internal borders
00198         //
00199         p->setPen(lightPen);
00200         rx = r.x() + d_intBorder / 2;
00201         p->drawLine(rx, r.y(), rx, r.y() + r.height());
00202 
00203         p->setPen(darkPen);
00204         rx = r.x() + r.width() - (d_intBorder - d_intBorder / 2);
00205         p->drawLine(rx, r.y(), rx , r.y() + r.height());
00206     }
00207 
00208     p->restore();
00209 }
00210 
00211 
00223 void QwtWheel::setTotalAngle(double angle)
00224 {
00225     d_totalAngle = qwtLim( angle, 10.0, 3600.0 );
00226     update();
00227 }
00228 
00236 void QwtWheel::setOrientation(Qt::Orientation o)
00237 {
00238     if ( orientation() != o )
00239     {
00240         QwtSliderBase::setOrientation(o);
00241         layoutWheel();
00242     }
00243 }
00244 
00253 void QwtWheel::setViewAngle(double angle)
00254 {
00255     d_viewAngle = qwtLim( angle, 10.0, 175.0 );
00256     update();
00257 }
00258 
00264 void QwtWheel::drawWheel( QPainter *p, const QRect &r )
00265 {
00266     const double sign = (minValue() < maxValue()) ? 1.0 : -1.0;
00267     double cnvFactor = qwtAbs(d_totalAngle / (maxValue() - minValue()));
00268     const double halfIntv = 0.5 * d_viewAngle / cnvFactor;
00269     const double loValue = value() - halfIntv;
00270     const double hiValue = value() + halfIntv;
00271     const double tickWidth = 360.0 / double(d_tickCnt) / cnvFactor;
00272     const double sinArc = sin(d_viewAngle * M_PI / 360.0);
00273     cnvFactor *= M_PI / 180.0;
00274 
00275     //
00276     // draw background gradient
00277     //
00278     drawWheelBackground( p, r );
00279 
00280     //
00281     // draw grooves
00282     //
00283     if ( orientation() == Qt::Horizontal )
00284     {
00285         const double halfSize = double(r.width()) * 0.5;
00286 
00287         int l1 = r.y() + d_intBorder;
00288         int l2 = r.y() + r.height() - d_intBorder - 1;
00289 
00290         // draw one point over the border if border > 1
00291         if ( d_intBorder > 1 )
00292         {
00293             l1 --;
00294             l2 ++;
00295         }
00296 
00297         const int maxpos = r.x() + r.width() - 2;
00298         const int minpos = r.x() + 2;
00299 
00300         //
00301         // draw tick marks
00302         //
00303         for ( double tickValue = ceil(loValue / tickWidth) * tickWidth;
00304             tickValue < hiValue; tickValue += tickWidth )
00305         {
00306             //
00307             //  calculate position
00308             //
00309             const int tickPos = r.x() + r.width()
00310                 - int( halfSize
00311                     * (sinArc + sign *  sin((tickValue - value()) * cnvFactor))
00312                     / sinArc);
00313             //
00314             // draw vertical line
00315             //
00316             if ( (tickPos <= maxpos) && (tickPos > minpos) )
00317             {
00318                 p->setPen(colorGroup().dark());
00319                 p->drawLine(tickPos -1 , l1, tickPos - 1,  l2 );  
00320                 p->setPen(colorGroup().light());
00321                 p->drawLine(tickPos, l1, tickPos, l2);  
00322             }
00323         }
00324     }
00325     else if ( orientation() == Qt::Vertical )
00326     {
00327         const double halfSize = double(r.height()) * 0.5;
00328 
00329         int l1 = r.x() + d_intBorder;
00330         int l2 = r.x() + r.width() - d_intBorder - 1;
00331 
00332         if ( d_intBorder > 1 )
00333         {
00334             l1--;
00335             l2++;
00336         }
00337 
00338         const int maxpos = r.y() + r.height() - 2;
00339         const int minpos = r.y() + 2;
00340 
00341         //
00342         // draw tick marks
00343         //
00344         for ( double tickValue = ceil(loValue / tickWidth) * tickWidth;
00345             tickValue < hiValue; tickValue += tickWidth )
00346         {
00347 
00348             //
00349             // calculate position
00350             //
00351             const int tickPos = r.y() + int( halfSize *
00352                 (sinArc + sign * sin((tickValue - value()) * cnvFactor))
00353                 / sinArc);
00354 
00355             //
00356             //  draw horizontal line
00357             //
00358             if ( (tickPos <= maxpos) && (tickPos > minpos) )
00359             {
00360                 p->setPen(colorGroup().dark());
00361                 p->drawLine(l1, tickPos - 1 ,l2, tickPos - 1);  
00362                 p->setPen(colorGroup().light());
00363                 p->drawLine(l1, tickPos, l2, tickPos);  
00364             }
00365         }
00366     }
00367 }
00368 
00369 
00371 double QwtWheel::getValue( const QPoint &p )
00372 {
00373     // The reference position is arbitrary, but the
00374     // sign of the offset is important
00375     int w, dx;
00376     if ( orientation() == Qt::Vertical )
00377     {
00378         w = d_sliderRect.height();
00379         dx = d_sliderRect.y() - p.y();
00380     }
00381     else
00382     {
00383         w = d_sliderRect.width();
00384         dx = p.x() - d_sliderRect.x();
00385     }
00386 
00387     // w pixels is an arc of viewAngle degrees,
00388     // so we convert change in pixels to change in angle
00389     const double ang = dx * d_viewAngle / w;
00390 
00391     // value range maps to totalAngle degrees,
00392     // so convert the change in angle to a change in value
00393     const double val = ang * ( maxValue() - minValue() ) / d_totalAngle;
00394 
00395     // Note, range clamping and rasterizing to step is automatically
00396     // handled by QwtSliderBase, so we simply return the change in value
00397     return val;
00398 }
00399 
00401 void QwtWheel::resizeEvent(QResizeEvent *)
00402 {
00403     layoutWheel( FALSE );
00404 }
00405 
00407 //  the current rect and fonts.
00408 //  \param update_geometry  notify the layout system and call update
00409 //         to redraw the scale
00410 void QwtWheel::layoutWheel( bool update_geometry )
00411 {
00412     const QRect r = this->rect();
00413     d_sliderRect.setRect(r.x() + d_borderWidth, r.y() + d_borderWidth,
00414         r.width() - 2*d_borderWidth, r.height() - 2*d_borderWidth);
00415 
00416     if ( update_geometry )
00417     {
00418         updateGeometry();
00419         update();
00420     }
00421 }
00422 
00424 void QwtWheel::paintEvent(QPaintEvent *e)
00425 {
00426     // Use double-buffering
00427     const QRect &ur = e->rect();
00428     if ( ur.isValid() )
00429     {
00430         QwtPaintBuffer paintBuffer(this, ur);
00431         draw(paintBuffer.painter(), ur);
00432     }
00433 }
00434 
00436 void QwtWheel::draw(QPainter *painter, const QRect&)
00437 {
00438     QColorGroup cg = colorGroup();
00439 
00440     // Rather than maintain a separate color group
00441     // for the outer frame, use our parent's cg
00442     QWidget *parent = parentWidget();
00443     if ( parent )
00444         cg = parent->colorGroup();
00445 
00446     qDrawShadePanel( painter, rect().x(), rect().y(),
00447         rect().width(), rect().height(),
00448         cg, TRUE, d_borderWidth );
00449 
00450     drawWheel( painter, d_sliderRect );
00451 
00452     if ( hasFocus() )
00453     {
00454         QRect r = rect();
00455     
00456 #if QT_VERSION < 300
00457         style().drawFocusRect(painter, r, colorGroup());
00458 #else
00459         style().drawPrimitive(QStyle::PE_FocusRect, painter,
00460             r, colorGroup());
00461 #endif
00462     }
00463 }
00464 
00466 void QwtWheel::valueChange()
00467 {
00468     QwtSliderBase::valueChange();
00469     update();
00470 }
00471 
00472 
00480 void QwtWheel::getScrollMode( const QPoint &p, int &scrollMode, int &direction)
00481 {
00482     if ( d_sliderRect.contains(p) )
00483         scrollMode = ScrMouse;
00484     else
00485         scrollMode = ScrNone;
00486 
00487     direction = 0;
00488 }
00489 
00496 void QwtWheel::setMass(double val)
00497 {
00498     QwtSliderBase::setMass(val);
00499 }
00500 
00508 void QwtWheel::setWheelWidth(int w)
00509 {
00510     d_wheelWidth = w;
00511     layoutWheel();
00512 }
00513 
00519 QSizePolicy QwtWheel::sizePolicy() const
00520 {
00521     QSizePolicy sp;
00522     if ( orientation() == Qt::Horizontal )
00523     {
00524         sp.setHorData( QSizePolicy::Preferred );
00525         sp.setVerData( QSizePolicy::Fixed );
00526     }
00527     else
00528     {
00529         sp.setHorData( QSizePolicy::Fixed );
00530         sp.setVerData( QSizePolicy::Preferred );
00531     }
00532     return sp;
00533 }
00534 
00538 QSize QwtWheel::sizeHint() const
00539 {
00540     return minimumSizeHint();
00541 }
00542 
00547 QSize QwtWheel::minimumSizeHint() const
00548 {
00549     QSize sz( 3*d_wheelWidth + 2*d_borderWidth,
00550     d_wheelWidth + 2*d_borderWidth );
00551     if ( orientation() != Qt::Horizontal )
00552         sz.transpose();
00553     return sz;
00554 }
00555 
00559 void QwtWheel::paletteChange( const QPalette& )
00560 {
00561     update();
00562 }
00563 

Generated on Fri Nov 7 14:11:46 2003 for Qwt Developer's Guide by doxygen 1.3.2