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 d_data = new PrivateData;
00055
00056 #if QT_VERSION < 0x040000
00057 setWFlags(Qt::WNoAutoErase);
00058 #endif
00059
00060 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
00061
00062 #if QT_VERSION >= 0x040000
00063 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00064 #else
00065 clearWState( WState_OwnSizePolicy );
00066 #endif
00067
00068 setUpdateTime(50);
00069 }
00070
00072 QwtWheel::~QwtWheel()
00073 {
00074 #if QT_VERSION < 0x040000
00075 if ( d_data->allocContext )
00076 QColor::destroyAllocContext( d_data->allocContext );
00077 #endif
00078 delete d_data;
00079 }
00080
00082 void QwtWheel::setColorArray()
00083 {
00084 if ( !d_data->colors )
00085 return;
00086
00087 #if QT_VERSION < 0x040000
00088 const QColor light = colorGroup().light();
00089 const QColor dark = colorGroup().dark();
00090 #else
00091 const QColor light = palette().color(QPalette::Light);
00092 const QColor dark = palette().color(QPalette::Dark);
00093 #endif
00094
00095 if ( !d_data->colors[0].isValid() ||
00096 d_data->colors[0] != light ||
00097 d_data->colors[NUM_COLORS - 1] != dark )
00098 {
00099 #if QT_VERSION < 0x040000
00100 if ( d_data->allocContext )
00101 QColor::destroyAllocContext( d_data->allocContext );
00102
00103 d_data->allocContext = QColor::enterAllocContext();
00104 #endif
00105
00106 d_data->colors[0] = light;
00107 d_data->colors[NUM_COLORS - 1] = dark;
00108
00109 int dh, ds, dv, lh, ls, lv;
00110 #if QT_VERSION < 0x040000
00111 d_data->colors[0].rgb(&lh, &ls, &lv);
00112 d_data->colors[NUM_COLORS - 1].rgb(&dh, &ds, &dv);
00113 #else
00114 d_data->colors[0].getRgb(&lh, &ls, &lv);
00115 d_data->colors[NUM_COLORS - 1].getRgb(&dh, &ds, &dv);
00116 #endif
00117
00118 for ( int i = 1; i < NUM_COLORS - 1; ++i )
00119 {
00120 const double factor = double(i) / double(NUM_COLORS);
00121
00122 d_data->colors[i].setRgb( lh + int( double(dh - lh) * factor ),
00123 ls + int( double(ds - ls) * factor ),
00124 lv + int( double(dv - lv) * factor ));
00125 }
00126 #if QT_VERSION < 0x040000
00127 QColor::leaveAllocContext();
00128 #endif
00129 }
00130 }
00131
00140 void QwtWheel::setTickCnt(int cnt)
00141 {
00142 d_data->tickCnt = qwtLim( cnt, 6, 50 );
00143 update();
00144 }
00145
00146 int QwtWheel::tickCnt() const
00147 {
00148 return d_data->tickCnt;
00149 }
00150
00154 double QwtWheel::mass() const
00155 {
00156 return QwtAbstractSlider::mass();
00157 }
00158
00169 void QwtWheel::setInternalBorder( int w )
00170 {
00171 const int d = qwtMin( width(), height() ) / 3;
00172 w = qwtMin( w, d );
00173 d_data->intBorder = qwtMax( w, 1 );
00174 layoutWheel();
00175 }
00176
00177 int QwtWheel::internalBorder() const
00178 {
00179 return d_data->intBorder;
00180 }
00181
00183 void QwtWheel::drawWheelBackground( QPainter *p, const QRect &r )
00184 {
00185 p->save();
00186
00187
00188
00189
00190 #if QT_VERSION < 0x040000
00191 const QColor light = colorGroup().light();
00192 const QColor dark = colorGroup().dark();
00193 #else
00194 const QColor light = palette().color(QPalette::Light);
00195 const QColor dark = palette().color(QPalette::Dark);
00196 #endif
00197
00198 QPen lightPen;
00199 lightPen.setColor(light);
00200 lightPen.setWidth(d_data->intBorder);
00201
00202 QPen darkPen;
00203 darkPen.setColor(dark);
00204 darkPen.setWidth(d_data->intBorder);
00205
00206 setColorArray();
00207
00208
00209
00210
00211
00212 const int nFields = NUM_COLORS * 13 / 10;
00213 const int hiPos = nFields - NUM_COLORS + 1;
00214
00215 if ( orientation() == Qt::Horizontal )
00216 {
00217 const int rx = r.x();
00218 int ry = r.y() + d_data->intBorder;
00219 const int rh = r.height() - 2* d_data->intBorder;
00220 const int rw = r.width();
00221
00222
00223
00224 int x1 = rx;
00225 for (int i = 1; i < nFields; i++ )
00226 {
00227 const int x2 = rx + (rw * i) / nFields;
00228 p->fillRect(x1, ry, x2-x1 + 1 ,rh, d_data->colors[qwtAbs(i-hiPos)]);
00229 x1 = x2 + 1;
00230 }
00231 p->fillRect(x1, ry, rw - (x1 - rx), rh, d_data->colors[NUM_COLORS - 1]);
00232
00233
00234
00235
00236 p->setPen(lightPen);
00237 ry = r.y() + d_data->intBorder / 2;
00238 p->drawLine(r.x(), ry, r.x() + r.width() , ry);
00239
00240 p->setPen(darkPen);
00241 ry = r.y() + r.height() - (d_data->intBorder - d_data->intBorder / 2);
00242 p->drawLine(r.x(), ry , r.x() + r.width(), ry);
00243 }
00244 else
00245 {
00246 int rx = r.x() + d_data->intBorder;
00247 const int ry = r.y();
00248 const int rh = r.height();
00249 const int rw = r.width() - 2 * d_data->intBorder;
00250
00251
00252
00253
00254 int y1 = ry;
00255 for ( int i = 1; i < nFields; i++ )
00256 {
00257 const int y2 = ry + (rh * i) / nFields;
00258 p->fillRect(rx, y1, rw, y2-y1 + 1, d_data->colors[qwtAbs(i-hiPos)]);
00259 y1 = y2 + 1;
00260 }
00261 p->fillRect(rx, y1, rw, rh - (y1 - ry), d_data->colors[NUM_COLORS - 1]);
00262
00263
00264
00265
00266 p->setPen(lightPen);
00267 rx = r.x() + d_data->intBorder / 2;
00268 p->drawLine(rx, r.y(), rx, r.y() + r.height());
00269
00270 p->setPen(darkPen);
00271 rx = r.x() + r.width() - (d_data->intBorder - d_data->intBorder / 2);
00272 p->drawLine(rx, r.y(), rx , r.y() + r.height());
00273 }
00274
00275 p->restore();
00276 }
00277
00278
00290 void QwtWheel::setTotalAngle(double angle)
00291 {
00292 d_data->totalAngle = qwtLim( angle, 10.0, 3600.0 );
00293 update();
00294 }
00295
00296 double QwtWheel::totalAngle() const
00297 {
00298 return d_data->totalAngle;
00299 }
00300
00308 void QwtWheel::setOrientation(Qt::Orientation o)
00309 {
00310 if ( orientation() == o )
00311 return;
00312
00313 #if QT_VERSION >= 0x040000
00314 if ( !testAttribute(Qt::WA_WState_OwnSizePolicy) )
00315 #else
00316 if ( !testWState( WState_OwnSizePolicy ) )
00317 #endif
00318 {
00319 QSizePolicy sp = sizePolicy();
00320 sp.transpose();
00321 setSizePolicy(sp);
00322
00323 #if QT_VERSION >= 0x040000
00324 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00325 #else
00326 clearWState( WState_OwnSizePolicy );
00327 #endif
00328 }
00329
00330 QwtAbstractSlider::setOrientation(o);
00331 layoutWheel();
00332 }
00333
00342 void QwtWheel::setViewAngle(double angle)
00343 {
00344 d_data->viewAngle = qwtLim( angle, 10.0, 175.0 );
00345 update();
00346 }
00347
00348 double QwtWheel::viewAngle() const
00349 {
00350 return d_data->viewAngle;
00351 }
00352
00358 void QwtWheel::drawWheel( QPainter *p, const QRect &r )
00359 {
00360 #if QT_VERSION < 0x040000
00361 const QColor light = colorGroup().light();
00362 const QColor dark = colorGroup().dark();
00363 #else
00364 const QColor light = palette().color(QPalette::Light);
00365 const QColor dark = palette().color(QPalette::Dark);
00366 #endif
00367
00368 const double sign = (minValue() < maxValue()) ? 1.0 : -1.0;
00369 double cnvFactor = qwtAbs(d_data->totalAngle / (maxValue() - minValue()));
00370 const double halfIntv = 0.5 * d_data->viewAngle / cnvFactor;
00371 const double loValue = value() - halfIntv;
00372 const double hiValue = value() + halfIntv;
00373 const double tickWidth = 360.0 / double(d_data->tickCnt) / cnvFactor;
00374 const double sinArc = sin(d_data->viewAngle * M_PI / 360.0);
00375 cnvFactor *= M_PI / 180.0;
00376
00377
00378
00379
00380 drawWheelBackground( p, r );
00381
00382
00383
00384
00385 if ( orientation() == Qt::Horizontal )
00386 {
00387 const double halfSize = double(r.width()) * 0.5;
00388
00389 int l1 = r.y() + d_data->intBorder;
00390 int l2 = r.y() + r.height() - d_data->intBorder - 1;
00391
00392
00393 if ( d_data->intBorder > 1 )
00394 {
00395 l1 --;
00396 l2 ++;
00397 }
00398
00399 const int maxpos = r.x() + r.width() - 2;
00400 const int minpos = r.x() + 2;
00401
00402
00403
00404
00405 for ( double tickValue = ceil(loValue / tickWidth) * tickWidth;
00406 tickValue < hiValue; tickValue += tickWidth )
00407 {
00408
00409
00410
00411 const int tickPos = r.x() + r.width()
00412 - int( halfSize
00413 * (sinArc + sign * sin((tickValue - value()) * cnvFactor))
00414 / sinArc);
00415
00416
00417
00418 if ( (tickPos <= maxpos) && (tickPos > minpos) )
00419 {
00420 p->setPen(dark);
00421 p->drawLine(tickPos -1 , l1, tickPos - 1, l2 );
00422 p->setPen(light);
00423 p->drawLine(tickPos, l1, tickPos, l2);
00424 }
00425 }
00426 }
00427 else if ( orientation() == Qt::Vertical )
00428 {
00429 const double halfSize = double(r.height()) * 0.5;
00430
00431 int l1 = r.x() + d_data->intBorder;
00432 int l2 = r.x() + r.width() - d_data->intBorder - 1;
00433
00434 if ( d_data->intBorder > 1 )
00435 {
00436 l1--;
00437 l2++;
00438 }
00439
00440 const int maxpos = r.y() + r.height() - 2;
00441 const int minpos = r.y() + 2;
00442
00443
00444
00445
00446 for ( double tickValue = ceil(loValue / tickWidth) * tickWidth;
00447 tickValue < hiValue; tickValue += tickWidth )
00448 {
00449
00450
00451
00452
00453 const int tickPos = r.y() + int( halfSize *
00454 (sinArc + sign * sin((tickValue - value()) * cnvFactor))
00455 / sinArc);
00456
00457
00458
00459
00460 if ( (tickPos <= maxpos) && (tickPos > minpos) )
00461 {
00462 p->setPen(dark);
00463 p->drawLine(l1, tickPos - 1 ,l2, tickPos - 1);
00464 p->setPen(light);
00465 p->drawLine(l1, tickPos, l2, tickPos);
00466 }
00467 }
00468 }
00469 }
00470
00471
00473 double QwtWheel::getValue( const QPoint &p )
00474 {
00475
00476
00477 int w, dx;
00478 if ( orientation() == Qt::Vertical )
00479 {
00480 w = d_data->sliderRect.height();
00481 dx = d_data->sliderRect.y() - p.y();
00482 }
00483 else
00484 {
00485 w = d_data->sliderRect.width();
00486 dx = p.x() - d_data->sliderRect.x();
00487 }
00488
00489
00490
00491 const double ang = dx * d_data->viewAngle / w;
00492
00493
00494
00495 const double val = ang * ( maxValue() - minValue() ) / d_data->totalAngle;
00496
00497
00498
00499 return val;
00500 }
00501
00503 void QwtWheel::resizeEvent(QResizeEvent *)
00504 {
00505 layoutWheel( false );
00506 }
00507
00509
00510
00511
00512 void QwtWheel::layoutWheel( bool update_geometry )
00513 {
00514 const QRect r = this->rect();
00515 d_data->sliderRect.setRect(r.x() + d_data->borderWidth, r.y() + d_data->borderWidth,
00516 r.width() - 2*d_data->borderWidth, r.height() - 2*d_data->borderWidth);
00517
00518 if ( update_geometry )
00519 {
00520 updateGeometry();
00521 update();
00522 }
00523 }
00524
00526 void QwtWheel::paintEvent(QPaintEvent *e)
00527 {
00528
00529 const QRect &ur = e->rect();
00530 if ( ur.isValid() )
00531 {
00532 #if QT_VERSION < 0x040000
00533 QwtPaintBuffer paintBuffer(this, ur);
00534 draw(paintBuffer.painter(), ur);
00535 #else
00536 QPainter painter(this);
00537 draw(&painter, ur);
00538 #endif
00539 }
00540 }
00541
00543 void QwtWheel::draw(QPainter *painter, const QRect&)
00544 {
00545 qDrawShadePanel( painter, rect().x(), rect().y(),
00546 rect().width(), rect().height(),
00547 #if QT_VERSION < 0x040000
00548 colorGroup(),
00549 #else
00550 palette(),
00551 #endif
00552 true, d_data->borderWidth );
00553
00554 drawWheel( painter, d_data->sliderRect );
00555
00556 if ( hasFocus() )
00557 QwtPainter::drawFocusRect(painter, this);
00558 }
00559
00561 void QwtWheel::valueChange()
00562 {
00563 QwtAbstractSlider::valueChange();
00564 update();
00565 }
00566
00567
00575 void QwtWheel::getScrollMode( const QPoint &p, int &scrollMode, int &direction)
00576 {
00577 if ( d_data->sliderRect.contains(p) )
00578 scrollMode = ScrMouse;
00579 else
00580 scrollMode = ScrNone;
00581
00582 direction = 0;
00583 }
00584
00591 void QwtWheel::setMass(double val)
00592 {
00593 QwtAbstractSlider::setMass(val);
00594 }
00595
00603 void QwtWheel::setWheelWidth(int w)
00604 {
00605 d_data->wheelWidth = w;
00606 layoutWheel();
00607 }
00608
00612 QSize QwtWheel::sizeHint() const
00613 {
00614 return minimumSizeHint();
00615 }
00616
00621 QSize QwtWheel::minimumSizeHint() const
00622 {
00623 QSize sz( 3*d_data->wheelWidth + 2*d_data->borderWidth,
00624 d_data->wheelWidth + 2*d_data->borderWidth );
00625 if ( orientation() != Qt::Horizontal )
00626 sz.transpose();
00627 return sz;
00628 }
00629
00633 void QwtWheel::paletteChange( const QPalette& )
00634 {
00635 update();
00636 }
00637