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_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
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
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
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
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
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
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
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
00278
00279 drawWheelBackground( p, r );
00280
00281
00282
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
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
00303
00304 for ( double tickValue = ceil(loValue / tickWidth) * tickWidth;
00305 tickValue < hiValue; tickValue += tickWidth )
00306 {
00307
00308
00309
00310 const int tickPos = r.x() + r.width()
00311 - int( halfSize
00312 * (sinArc + sign * sin((tickValue - value()) * cnvFactor))
00313 / sinArc);
00314
00315
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
00344
00345 for ( double tickValue = ceil(loValue / tickWidth) * tickWidth;
00346 tickValue < hiValue; tickValue += tickWidth )
00347 {
00348
00349
00350
00351
00352 const int tickPos = r.y() + int( halfSize *
00353 (sinArc + sign * sin((tickValue - value()) * cnvFactor))
00354 / sinArc);
00355
00356
00357
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
00375
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
00389
00390 const double ang = dx * d_viewAngle / w;
00391
00392
00393
00394 const double val = ang * ( maxValue() - minValue() ) / d_totalAngle;
00395
00396
00397
00398 return val;
00399 }
00400
00402 void QwtWheel::resizeEvent(QResizeEvent *)
00403 {
00404 layoutWheel( FALSE );
00405 }
00406
00408
00409
00410
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
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
00442
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