Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

qwt_wheel.cpp

00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** 00002 * Qwt Widget Library 00003 * Copyright (C) 1997 Josef Wilgen 00004 * Copyright (C) 2002 Uwe Rathmann 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the Qwt License, Version 1.0 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 // initialize pens 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 // initialize auxiliary variables 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 // draw shaded background 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 // draw internal border 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 // Qt::Vertical 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 // draw shaded background 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 // draw internal borders 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 // draw background gradient 00278 // 00279 drawWheelBackground( p, r ); 00280 00281 // 00282 // draw grooves 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 // draw one point over the border if border > 1 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 // draw tick marks 00303 // 00304 for ( double tickValue = ceil(loValue / tickWidth) * tickWidth; 00305 tickValue < hiValue; tickValue += tickWidth ) 00306 { 00307 // 00308 // calculate position 00309 // 00310 const int tickPos = r.x() + r.width() 00311 - int( halfSize 00312 * (sinArc + sign * sin((tickValue - value()) * cnvFactor)) 00313 / sinArc); 00314 // 00315 // draw vertical line 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 // draw tick marks 00344 // 00345 for ( double tickValue = ceil(loValue / tickWidth) * tickWidth; 00346 tickValue < hiValue; tickValue += tickWidth ) 00347 { 00348 00349 // 00350 // calculate position 00351 // 00352 const int tickPos = r.y() + int( halfSize * 00353 (sinArc + sign * sin((tickValue - value()) * cnvFactor)) 00354 / sinArc); 00355 00356 // 00357 // draw horizontal line 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 // The reference position is arbitrary, but the 00375 // sign of the offset is important 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 // w pixels is an arc of viewAngle degrees, 00389 // so we convert change in pixels to change in angle 00390 const double ang = dx * d_viewAngle / w; 00391 00392 // value range maps to totalAngle degrees, 00393 // so convert the change in angle to a change in value 00394 const double val = ang * ( maxValue() - minValue() ) / d_totalAngle; 00395 00396 // Note, range clamping and rasterizing to step is automatically 00397 // handled by QwtSliderBase, so we simply return the change in value 00398 return val; 00399 } 00400 00402 void QwtWheel::resizeEvent(QResizeEvent *) 00403 { 00404 layoutWheel( FALSE ); 00405 } 00406 00408 // the current rect and fonts. 00409 // \param update_geometry notify the layout system and call update 00410 // to redraw the scale 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 // Use double-buffering 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 // Rather than maintain a separate color group 00442 // for the outer frame, use our parent's cg 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

Generated on Tue Nov 16 21:12:21 2004 for Qwt User's Guide by doxygen 1.3.8