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

qwt_wheel.cpp

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

Generated on Sun Nov 21 11:12:44 2004 for Qwt User's Guide by doxygen 1.3.5