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