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
00156 void QwtWheel::setTickCnt(int cnt)
00157 {
00158 d_data->tickCnt = qwtLim( cnt, 6, 50 );
00159 update();
00160 }
00161
00166 int QwtWheel::tickCnt() const
00167 {
00168 return d_data->tickCnt;
00169 }
00170
00174 double QwtWheel::mass() const
00175 {
00176 return QwtAbstractSlider::mass();
00177 }
00178
00191 void QwtWheel::setInternalBorder(int w)
00192 {
00193 const int d = qwtMin( width(), height() ) / 3;
00194 w = qwtMin( w, d );
00195 d_data->intBorder = qwtMax( w, 1 );
00196 layoutWheel();
00197 }
00198
00203 int QwtWheel::internalBorder() const
00204 {
00205 return d_data->intBorder;
00206 }
00207
00214 void QwtWheel::drawWheelBackground(QPainter *painter, const QRect &r )
00215 {
00216 painter->save();
00217
00218
00219
00220
00221 #if QT_VERSION < 0x040000
00222 const QColor light = colorGroup().light();
00223 const QColor dark = colorGroup().dark();
00224 #else
00225 const QColor light = palette().color(QPalette::Light);
00226 const QColor dark = palette().color(QPalette::Dark);
00227 #endif
00228
00229 QPen lightPen;
00230 lightPen.setColor(light);
00231 lightPen.setWidth(d_data->intBorder);
00232
00233 QPen darkPen;
00234 darkPen.setColor(dark);
00235 darkPen.setWidth(d_data->intBorder);
00236
00237 setColorArray();
00238
00239
00240
00241
00242
00243 const int nFields = NUM_COLORS * 13 / 10;
00244 const int hiPos = nFields - NUM_COLORS + 1;
00245
00246 if ( orientation() == Qt::Horizontal )
00247 {
00248 const int rx = r.x();
00249 int ry = r.y() + d_data->intBorder;
00250 const int rh = r.height() - 2* d_data->intBorder;
00251 const int rw = r.width();
00252
00253
00254
00255 int x1 = rx;
00256 for (int i = 1; i < nFields; i++ )
00257 {
00258 const int x2 = rx + (rw * i) / nFields;
00259 painter->fillRect(x1, ry, x2-x1 + 1 ,rh,
00260 d_data->colors[qwtAbs(i-hiPos)]);
00261 x1 = x2 + 1;
00262 }
00263 painter->fillRect(x1, ry, rw - (x1 - rx), rh,
00264 d_data->colors[NUM_COLORS - 1]);
00265
00266
00267
00268
00269 painter->setPen(lightPen);
00270 ry = r.y() + d_data->intBorder / 2;
00271 painter->drawLine(r.x(), ry, r.x() + r.width() , ry);
00272
00273 painter->setPen(darkPen);
00274 ry = r.y() + r.height() - (d_data->intBorder - d_data->intBorder / 2);
00275 painter->drawLine(r.x(), ry , r.x() + r.width(), ry);
00276 }
00277 else
00278 {
00279 int rx = r.x() + d_data->intBorder;
00280 const int ry = r.y();
00281 const int rh = r.height();
00282 const int rw = r.width() - 2 * d_data->intBorder;
00283
00284
00285
00286
00287 int y1 = ry;
00288 for ( int i = 1; i < nFields; i++ )
00289 {
00290 const int y2 = ry + (rh * i) / nFields;
00291 painter->fillRect(rx, y1, rw, y2-y1 + 1,
00292 d_data->colors[qwtAbs(i-hiPos)]);
00293 y1 = y2 + 1;
00294 }
00295 painter->fillRect(rx, y1, rw, rh - (y1 - ry),
00296 d_data->colors[NUM_COLORS - 1]);
00297
00298
00299
00300
00301 painter->setPen(lightPen);
00302 rx = r.x() + d_data->intBorder / 2;
00303 painter->drawLine(rx, r.y(), rx, r.y() + r.height());
00304
00305 painter->setPen(darkPen);
00306 rx = r.x() + r.width() - (d_data->intBorder - d_data->intBorder / 2);
00307 painter->drawLine(rx, r.y(), rx , r.y() + r.height());
00308 }
00309
00310 painter->restore();
00311 }
00312
00313
00327 void QwtWheel::setTotalAngle(double angle)
00328 {
00329 if ( angle < 0.0 )
00330 angle = 0.0;
00331
00332 d_data->totalAngle = angle;
00333 update();
00334 }
00335
00340 double QwtWheel::totalAngle() const
00341 {
00342 return d_data->totalAngle;
00343 }
00344
00352 void QwtWheel::setOrientation(Qt::Orientation o)
00353 {
00354 if ( orientation() == o )
00355 return;
00356
00357 #if QT_VERSION >= 0x040000
00358 if ( !testAttribute(Qt::WA_WState_OwnSizePolicy) )
00359 #else
00360 if ( !testWState( WState_OwnSizePolicy ) )
00361 #endif
00362 {
00363 QSizePolicy sp = sizePolicy();
00364 sp.transpose();
00365 setSizePolicy(sp);
00366
00367 #if QT_VERSION >= 0x040000
00368 setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00369 #else
00370 clearWState( WState_OwnSizePolicy );
00371 #endif
00372 }
00373
00374 QwtAbstractSlider::setOrientation(o);
00375 layoutWheel();
00376 }
00377
00388 void QwtWheel::setViewAngle(double angle)
00389 {
00390 d_data->viewAngle = qwtLim( angle, 10.0, 175.0 );
00391 update();
00392 }
00393
00398 double QwtWheel::viewAngle() const
00399 {
00400 return d_data->viewAngle;
00401 }
00402
00408 void QwtWheel::drawWheel( QPainter *painter, const QRect &r )
00409 {
00410
00411
00412
00413 drawWheelBackground( painter, r );
00414
00415 if ( maxValue() == minValue() || d_data->totalAngle == 0.0 )
00416 return;
00417
00418 #if QT_VERSION < 0x040000
00419 const QColor light = colorGroup().light();
00420 const QColor dark = colorGroup().dark();
00421 #else
00422 const QColor light = palette().color(QPalette::Light);
00423 const QColor dark = palette().color(QPalette::Dark);
00424 #endif
00425
00426 const double sign = (minValue() < maxValue()) ? 1.0 : -1.0;
00427 double cnvFactor = qwtAbs(d_data->totalAngle / (maxValue() - minValue()));
00428 const double halfIntv = 0.5 * d_data->viewAngle / cnvFactor;
00429 const double loValue = value() - halfIntv;
00430 const double hiValue = value() + halfIntv;
00431 const double tickWidth = 360.0 / double(d_data->tickCnt) / cnvFactor;
00432 const double sinArc = sin(d_data->viewAngle * M_PI / 360.0);
00433 cnvFactor *= M_PI / 180.0;
00434
00435
00436
00437
00438
00439 if ( orientation() == Qt::Horizontal )
00440 {
00441 const double halfSize = double(r.width()) * 0.5;
00442
00443 int l1 = r.y() + d_data->intBorder;
00444 int l2 = r.y() + r.height() - d_data->intBorder - 1;
00445
00446
00447 if ( d_data->intBorder > 1 )
00448 {
00449 l1 --;
00450 l2 ++;
00451 }
00452
00453 const int maxpos = r.x() + r.width() - 2;
00454 const int minpos = r.x() + 2;
00455
00456
00457
00458
00459 for ( double tickValue = ceil(loValue / tickWidth) * tickWidth;
00460 tickValue < hiValue; tickValue += tickWidth )
00461 {
00462
00463
00464
00465 const int tickPos = r.x() + r.width()
00466 - int( halfSize
00467 * (sinArc + sign * sin((tickValue - value()) * cnvFactor))
00468 / sinArc);
00469
00470
00471
00472 if ( (tickPos <= maxpos) && (tickPos > minpos) )
00473 {
00474 painter->setPen(dark);
00475 painter->drawLine(tickPos -1 , l1, tickPos - 1, l2 );
00476 painter->setPen(light);
00477 painter->drawLine(tickPos, l1, tickPos, l2);
00478 }
00479 }
00480 }
00481 else if ( orientation() == Qt::Vertical )
00482 {
00483 const double halfSize = double(r.height()) * 0.5;
00484
00485 int l1 = r.x() + d_data->intBorder;
00486 int l2 = r.x() + r.width() - d_data->intBorder - 1;
00487
00488 if ( d_data->intBorder > 1 )
00489 {
00490 l1--;
00491 l2++;
00492 }
00493
00494 const int maxpos = r.y() + r.height() - 2;
00495 const int minpos = r.y() + 2;
00496
00497
00498
00499
00500 for ( double tickValue = ceil(loValue / tickWidth) * tickWidth;
00501 tickValue < hiValue; tickValue += tickWidth )
00502 {
00503
00504
00505
00506
00507 const int tickPos = r.y() + int( halfSize *
00508 (sinArc + sign * sin((tickValue - value()) * cnvFactor))
00509 / sinArc);
00510
00511
00512
00513
00514 if ( (tickPos <= maxpos) && (tickPos > minpos) )
00515 {
00516 painter->setPen(dark);
00517 painter->drawLine(l1, tickPos - 1 ,l2, tickPos - 1);
00518 painter->setPen(light);
00519 painter->drawLine(l1, tickPos, l2, tickPos);
00520 }
00521 }
00522 }
00523 }
00524
00525
00527 double QwtWheel::getValue( const QPoint &p )
00528 {
00529
00530
00531 int w, dx;
00532 if ( orientation() == Qt::Vertical )
00533 {
00534 w = d_data->sliderRect.height();
00535 dx = d_data->sliderRect.y() - p.y();
00536 }
00537 else
00538 {
00539 w = d_data->sliderRect.width();
00540 dx = p.x() - d_data->sliderRect.x();
00541 }
00542
00543
00544
00545 const double ang = dx * d_data->viewAngle / w;
00546
00547
00548
00549 const double val = ang * ( maxValue() - minValue() ) / d_data->totalAngle;
00550
00551
00552
00553 return val;
00554 }
00555
00557 void QwtWheel::resizeEvent(QResizeEvent *)
00558 {
00559 layoutWheel( false );
00560 }
00561
00563
00564
00565
00566 void QwtWheel::layoutWheel( bool update_geometry )
00567 {
00568 const QRect r = this->rect();
00569 d_data->sliderRect.setRect(r.x() + d_data->borderWidth, r.y() + d_data->borderWidth,
00570 r.width() - 2*d_data->borderWidth, r.height() - 2*d_data->borderWidth);
00571
00572 if ( update_geometry )
00573 {
00574 updateGeometry();
00575 update();
00576 }
00577 }
00578
00580 void QwtWheel::paintEvent(QPaintEvent *e)
00581 {
00582
00583 const QRect &ur = e->rect();
00584 if ( ur.isValid() )
00585 {
00586 #if QT_VERSION < 0x040000
00587 QwtPaintBuffer paintBuffer(this, ur);
00588 draw(paintBuffer.painter(), ur);
00589 #else
00590 QPainter painter(this);
00591 draw(&painter, ur);
00592 #endif
00593 }
00594 }
00595
00600 void QwtWheel::draw(QPainter *painter, const QRect&)
00601 {
00602 qDrawShadePanel( painter, rect().x(), rect().y(),
00603 rect().width(), rect().height(),
00604 #if QT_VERSION < 0x040000
00605 colorGroup(),
00606 #else
00607 palette(),
00608 #endif
00609 true, d_data->borderWidth );
00610
00611 drawWheel( painter, d_data->sliderRect );
00612
00613 if ( hasFocus() )
00614 QwtPainter::drawFocusRect(painter, this);
00615 }
00616
00618 void QwtWheel::valueChange()
00619 {
00620 QwtAbstractSlider::valueChange();
00621 update();
00622 }
00623
00624
00632 void QwtWheel::getScrollMode( const QPoint &p, int &scrollMode, int &direction)
00633 {
00634 if ( d_data->sliderRect.contains(p) )
00635 scrollMode = ScrMouse;
00636 else
00637 scrollMode = ScrNone;
00638
00639 direction = 0;
00640 }
00641
00648 void QwtWheel::setMass(double val)
00649 {
00650 QwtAbstractSlider::setMass(val);
00651 }
00652
00660 void QwtWheel::setWheelWidth(int w)
00661 {
00662 d_data->wheelWidth = w;
00663 layoutWheel();
00664 }
00665
00669 QSize QwtWheel::sizeHint() const
00670 {
00671 return minimumSizeHint();
00672 }
00673
00678 QSize QwtWheel::minimumSizeHint() const
00679 {
00680 QSize sz( 3*d_data->wheelWidth + 2*d_data->borderWidth,
00681 d_data->wheelWidth + 2*d_data->borderWidth );
00682 if ( orientation() != Qt::Horizontal )
00683 sz.transpose();
00684 return sz;
00685 }
00686
00690 void QwtWheel::paletteChange( const QPalette& )
00691 {
00692 update();
00693 }
00694