00001
00002
00003
00004
00005
00006
00007
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_painter.h"
00016 #include "qwt_paint_buffer.h"
00017 #include "qwt_wheel.h"
00018
00019 #define NUM_COLORS 30
00020
00021 class QwtWheel::PrivateData
00022 {
00023 public:
00024 PrivateData()
00025 {
00026 viewAngle = 175.0;
00027 totalAngle = 360.0;
00028 tickCnt = 10;
00029 intBorder = 2;
00030 borderWidth = 2;
00031 wheelWidth = 20;
00032 #if QT_VERSION < 0x040000
00033 allocContext = 0;
00034 #endif
00035 };
00036
00037 QRect sliderRect;
00038 double viewAngle;
00039 double totalAngle;
00040 int tickCnt;
00041 int intBorder;
00042 int borderWidth;
00043 int wheelWidth;
00044 #if QT_VERSION < 0x040000
00045 int allocContext;
00046 #endif
00047 QColor colors[NUM_COLORS];
00048 };
00049
00051 QwtWheel::QwtWheel(QWidget *parent):
00052 QwtAbstractSlider(Qt::Horizontal, parent)
00053 {
00054 initWheel();
00055 }
00056
00057 #if QT_VERSION < 0x040000
00058 QwtWheel::QwtWheel(QWidget *parent, const char *name):
00059 QwtAbstractSlider(Qt::Horizontal, parent)
00060 {
00061 setName(name);
00062 initWheel();
00063 }
00064 #endif
00065
00066 void QwtWheel::initWheel()
00067 {
00068 d_data = new PrivateData;
00069
00070 #if QT_VERSION < 0x040000
00071 setWFlags(Qt::WNoAutoErase);
00072 #endif
00073
00074 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
00075
00076 #if QT_VERSION >= 0x040000
00077 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00078 #else
00079 clearWState( WState_OwnSizePolicy );
00080 #endif
00081
00082 setUpdateTime(50);
00083 }
00084
00086 QwtWheel::~QwtWheel()
00087 {
00088 #if QT_VERSION < 0x040000
00089 if ( d_data->allocContext )
00090 QColor::destroyAllocContext( d_data->allocContext );
00091 #endif
00092 delete d_data;
00093 }
00094
00096 void QwtWheel::setColorArray()
00097 {
00098 if ( !d_data->colors )
00099 return;
00100
00101 #if QT_VERSION < 0x040000
00102 const QColor light = colorGroup().light();
00103 const QColor dark = colorGroup().dark();
00104 #else
00105 const QColor light = palette().color(QPalette::Light);
00106 const QColor dark = palette().color(QPalette::Dark);
00107 #endif
00108
00109 if ( !d_data->colors[0].isValid() ||
00110 d_data->colors[0] != light ||
00111 d_data->colors[NUM_COLORS - 1] != dark )
00112 {
00113 #if QT_VERSION < 0x040000
00114 if ( d_data->allocContext )
00115 QColor::destroyAllocContext( d_data->allocContext );
00116
00117 d_data->allocContext = QColor::enterAllocContext();
00118 #endif
00119
00120 d_data->colors[0] = light;
00121 d_data->colors[NUM_COLORS - 1] = dark;
00122
00123 int dh, ds, dv, lh, ls, lv;
00124 #if QT_VERSION < 0x040000
00125 d_data->colors[0].rgb(&lh, &ls, &lv);
00126 d_data->colors[NUM_COLORS - 1].rgb(&dh, &ds, &dv);
00127 #else
00128 d_data->colors[0].getRgb(&lh, &ls, &lv);
00129 d_data->colors[NUM_COLORS - 1].getRgb(&dh, &ds, &dv);
00130 #endif
00131
00132 for ( int i = 1; i < NUM_COLORS - 1; ++i )
00133 {
00134 const double factor = double(i) / double(NUM_COLORS);
00135
00136 d_data->colors[i].setRgb( lh + int( double(dh - lh) * factor ),
00137 ls + int( double(ds - ls) * factor ),
00138 lv + int( double(dv - lv) * factor ));
00139 }
00140 #if QT_VERSION < 0x040000
00141 QColor::leaveAllocContext();
00142 #endif
00143 }
00144 }
00145
00154 void QwtWheel::setTickCnt(int cnt)
00155 {
00156 d_data->tickCnt = qwtLim( cnt, 6, 50 );
00157 update();
00158 }
00159
00160 int QwtWheel::tickCnt() const
00161 {
00162 return d_data->tickCnt;
00163 }
00164
00168 double QwtWheel::mass() const
00169 {
00170 return QwtAbstractSlider::mass();
00171 }
00172
00183 void QwtWheel::setInternalBorder( int w )
00184 {
00185 const int d = qwtMin( width(), height() ) / 3;
00186 w = qwtMin( w, d );
00187 d_data->intBorder = qwtMax( w, 1 );
00188 layoutWheel();
00189 }
00190
00191 int QwtWheel::internalBorder() const
00192 {
00193 return d_data->intBorder;
00194 }
00195
00197 void QwtWheel::drawWheelBackground( QPainter *p, const QRect &r )
00198 {
00199 p->save();
00200
00201
00202
00203
00204 #if QT_VERSION < 0x040000
00205 const QColor light = colorGroup().light();
00206 const QColor dark = colorGroup().dark();
00207 #else
00208 const QColor light = palette().color(QPalette::Light);
00209 const QColor dark = palette().color(QPalette::Dark);
00210 #endif
00211
00212 QPen lightPen;
00213 lightPen.setColor(light);
00214 lightPen.setWidth(d_data->intBorder);
00215
00216 QPen darkPen;
00217 darkPen.setColor(dark);
00218 darkPen.setWidth(d_data->intBorder);
00219
00220 setColorArray();
00221
00222
00223
00224
00225
00226 const int nFields = NUM_COLORS * 13 / 10;
00227 const int hiPos = nFields - NUM_COLORS + 1;
00228
00229 if ( orientation() == Qt::Horizontal )
00230 {
00231 const int rx = r.x();
00232 int ry = r.y() + d_data->intBorder;
00233 const int rh = r.height() - 2* d_data->intBorder;
00234 const int rw = r.width();
00235
00236
00237
00238 int x1 = rx;
00239 for (int i = 1; i < nFields; i++ )
00240 {
00241 const int x2 = rx + (rw * i) / nFields;
00242 p->fillRect(x1, ry, x2-x1 + 1 ,rh, d_data->colors[qwtAbs(i-hiPos)]);
00243 x1 = x2 + 1;
00244 }
00245 p->fillRect(x1, ry, rw - (x1 - rx), rh, d_data->colors[NUM_COLORS - 1]);
00246
00247
00248
00249
00250 p->setPen(lightPen);
00251 ry = r.y() + d_data->intBorder / 2;
00252 p->drawLine(r.x(), ry, r.x() + r.width() , ry);
00253
00254 p->setPen(darkPen);
00255 ry = r.y() + r.height() - (d_data->intBorder - d_data->intBorder / 2);
00256 p->drawLine(r.x(), ry , r.x() + r.width(), ry);
00257 }
00258 else
00259 {
00260 int rx = r.x() + d_data->intBorder;
00261 const int ry = r.y();
00262 const int rh = r.height();
00263 const int rw = r.width() - 2 * d_data->intBorder;
00264
00265
00266
00267
00268 int y1 = ry;
00269 for ( int i = 1; i < nFields; i++ )
00270 {
00271 const int y2 = ry + (rh * i) / nFields;
00272 p->fillRect(rx, y1, rw, y2-y1 + 1, d_data->colors[qwtAbs(i-hiPos)]);
00273 y1 = y2 + 1;
00274 }
00275 p->fillRect(rx, y1, rw, rh - (y1 - ry), d_data->colors[NUM_COLORS - 1]);
00276
00277
00278
00279
00280 p->setPen(lightPen);
00281 rx = r.x() + d_data->intBorder / 2;
00282 p->drawLine(rx, r.y(), rx, r.y() + r.height());
00283
00284 p->setPen(darkPen);
00285 rx = r.x() + r.width() - (d_data->intBorder - d_data->intBorder / 2);
00286 p->drawLine(rx, r.y(), rx , r.y() + r.height());
00287 }
00288
00289 p->restore();
00290 }
00291
00292
00304 void QwtWheel::setTotalAngle(double angle)
00305 {
00306 if ( angle < 0.0 )
00307 angle = 0.0;
00308
00309 d_data->totalAngle = angle;
00310 update();
00311 }
00312
00313 double QwtWheel::totalAngle() const
00314 {
00315 return d_data->totalAngle;
00316 }
00317
00325 void QwtWheel::setOrientation(Qt::Orientation o)
00326 {
00327 if ( orientation() == o )
00328 return;
00329
00330 #if QT_VERSION >= 0x040000
00331 if ( !testAttribute(Qt::WA_WState_OwnSizePolicy) )
00332 #else
00333 if ( !testWState( WState_OwnSizePolicy ) )
00334 #endif
00335 {
00336 QSizePolicy sp = sizePolicy();
00337 sp.transpose();
00338 setSizePolicy(sp);
00339
00340 #if QT_VERSION >= 0x040000
00341 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00342 #else
00343 clearWState( WState_OwnSizePolicy );
00344 #endif
00345 }
00346
00347 QwtAbstractSlider::setOrientation(o);
00348 layoutWheel();
00349 }
00350
00359 void QwtWheel::setViewAngle(double angle)
00360 {
00361 d_data->viewAngle = qwtLim( angle, 10.0, 175.0 );
00362 update();
00363 }
00364
00365 double QwtWheel::viewAngle() const
00366 {
00367 return d_data->viewAngle;
00368 }
00369
00375 void QwtWheel::drawWheel( QPainter *p, const QRect &r )
00376 {
00377
00378
00379
00380 drawWheelBackground( p, r );
00381
00382 if ( maxValue() == minValue() || d_data->totalAngle == 0.0 )
00383 return;
00384
00385 #if QT_VERSION < 0x040000
00386 const QColor light = colorGroup().light();
00387 const QColor dark = colorGroup().dark();
00388 #else
00389 const QColor light = palette().color(QPalette::Light);
00390 const QColor dark = palette().color(QPalette::Dark);
00391 #endif
00392
00393 const double sign = (minValue() < maxValue()) ? 1.0 : -1.0;
00394 double cnvFactor = qwtAbs(d_data->totalAngle / (maxValue() - minValue()));
00395 const double halfIntv = 0.5 * d_data->viewAngle / cnvFactor;
00396 const double loValue = value() - halfIntv;
00397 const double hiValue = value() + halfIntv;
00398 const double tickWidth = 360.0 / double(d_data->tickCnt) / cnvFactor;
00399 const double sinArc = sin(d_data->viewAngle * M_PI / 360.0);
00400 cnvFactor *= M_PI / 180.0;
00401
00402
00403
00404
00405
00406 if ( orientation() == Qt::Horizontal )
00407 {
00408 const double halfSize = double(r.width()) * 0.5;
00409
00410 int l1 = r.y() + d_data->intBorder;
00411 int l2 = r.y() + r.height() - d_data->intBorder - 1;
00412
00413
00414 if ( d_data->intBorder > 1 )
00415 {
00416 l1 --;
00417 l2 ++;
00418 }
00419
00420 const int maxpos = r.x() + r.width() - 2;
00421 const int minpos = r.x() + 2;
00422
00423
00424
00425
00426 for ( double tickValue = ceil(loValue / tickWidth) * tickWidth;
00427 tickValue < hiValue; tickValue += tickWidth )
00428 {
00429
00430
00431
00432 const int tickPos = r.x() + r.width()
00433 - int( halfSize
00434 * (sinArc + sign * sin((tickValue - value()) * cnvFactor))
00435 / sinArc);
00436
00437
00438
00439 if ( (tickPos <= maxpos) && (tickPos > minpos) )
00440 {
00441 p->setPen(dark);
00442 p->drawLine(tickPos -1 , l1, tickPos - 1, l2 );
00443 p->setPen(light);
00444 p->drawLine(tickPos, l1, tickPos, l2);
00445 }
00446 }
00447 }
00448 else if ( orientation() == Qt::Vertical )
00449 {
00450 const double halfSize = double(r.height()) * 0.5;
00451
00452 int l1 = r.x() + d_data->intBorder;
00453 int l2 = r.x() + r.width() - d_data->intBorder - 1;
00454
00455 if ( d_data->intBorder > 1 )
00456 {
00457 l1--;
00458 l2++;
00459 }
00460
00461 const int maxpos = r.y() + r.height() - 2;
00462 const int minpos = r.y() + 2;
00463
00464
00465
00466
00467 for ( double tickValue = ceil(loValue / tickWidth) * tickWidth;
00468 tickValue < hiValue; tickValue += tickWidth )
00469 {
00470
00471
00472
00473
00474 const int tickPos = r.y() + int( halfSize *
00475 (sinArc + sign * sin((tickValue - value()) * cnvFactor))
00476 / sinArc);
00477
00478
00479
00480
00481 if ( (tickPos <= maxpos) && (tickPos > minpos) )
00482 {
00483 p->setPen(dark);
00484 p->drawLine(l1, tickPos - 1 ,l2, tickPos - 1);
00485 p->setPen(light);
00486 p->drawLine(l1, tickPos, l2, tickPos);
00487 }
00488 }
00489 }
00490 }
00491
00492
00494 double QwtWheel::getValue( const QPoint &p )
00495 {
00496
00497
00498 int w, dx;
00499 if ( orientation() == Qt::Vertical )
00500 {
00501 w = d_data->sliderRect.height();
00502 dx = d_data->sliderRect.y() - p.y();
00503 }
00504 else
00505 {
00506 w = d_data->sliderRect.width();
00507 dx = p.x() - d_data->sliderRect.x();
00508 }
00509
00510
00511
00512 const double ang = dx * d_data->viewAngle / w;
00513
00514
00515
00516 const double val = ang * ( maxValue() - minValue() ) / d_data->totalAngle;
00517
00518
00519
00520 return val;
00521 }
00522
00524 void QwtWheel::resizeEvent(QResizeEvent *)
00525 {
00526 layoutWheel( false );
00527 }
00528
00530
00531
00532
00533 void QwtWheel::layoutWheel( bool update_geometry )
00534 {
00535 const QRect r = this->rect();
00536 d_data->sliderRect.setRect(r.x() + d_data->borderWidth, r.y() + d_data->borderWidth,
00537 r.width() - 2*d_data->borderWidth, r.height() - 2*d_data->borderWidth);
00538
00539 if ( update_geometry )
00540 {
00541 updateGeometry();
00542 update();
00543 }
00544 }
00545
00547 void QwtWheel::paintEvent(QPaintEvent *e)
00548 {
00549
00550 const QRect &ur = e->rect();
00551 if ( ur.isValid() )
00552 {
00553 #if QT_VERSION < 0x040000
00554 QwtPaintBuffer paintBuffer(this, ur);
00555 draw(paintBuffer.painter(), ur);
00556 #else
00557 QPainter painter(this);
00558 draw(&painter, ur);
00559 #endif
00560 }
00561 }
00562
00564 void QwtWheel::draw(QPainter *painter, const QRect&)
00565 {
00566 qDrawShadePanel( painter, rect().x(), rect().y(),
00567 rect().width(), rect().height(),
00568 #if QT_VERSION < 0x040000
00569 colorGroup(),
00570 #else
00571 palette(),
00572 #endif
00573 true, d_data->borderWidth );
00574
00575 drawWheel( painter, d_data->sliderRect );
00576
00577 if ( hasFocus() )
00578 QwtPainter::drawFocusRect(painter, this);
00579 }
00580
00582 void QwtWheel::valueChange()
00583 {
00584 QwtAbstractSlider::valueChange();
00585 update();
00586 }
00587
00588
00596 void QwtWheel::getScrollMode( const QPoint &p, int &scrollMode, int &direction)
00597 {
00598 if ( d_data->sliderRect.contains(p) )
00599 scrollMode = ScrMouse;
00600 else
00601 scrollMode = ScrNone;
00602
00603 direction = 0;
00604 }
00605
00612 void QwtWheel::setMass(double val)
00613 {
00614 QwtAbstractSlider::setMass(val);
00615 }
00616
00624 void QwtWheel::setWheelWidth(int w)
00625 {
00626 d_data->wheelWidth = w;
00627 layoutWheel();
00628 }
00629
00633 QSize QwtWheel::sizeHint() const
00634 {
00635 return minimumSizeHint();
00636 }
00637
00642 QSize QwtWheel::minimumSizeHint() const
00643 {
00644 QSize sz( 3*d_data->wheelWidth + 2*d_data->borderWidth,
00645 d_data->wheelWidth + 2*d_data->borderWidth );
00646 if ( orientation() != Qt::Horizontal )
00647 sz.transpose();
00648 return sz;
00649 }
00650
00654 void QwtWheel::paletteChange( const QPalette& )
00655 {
00656 update();
00657 }
00658