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

qwt_knob.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 <qpainter.h> 00011 #include <qpalette.h> 00012 #include <qstyle.h> 00013 #include <qevent.h> 00014 #include "qwt_knob.h" 00015 #include "qwt_math.h" 00016 #include "qwt_paint_buffer.h" 00017 00023 QwtKnob::QwtKnob(QWidget* parent, const char *name): 00024 QwtSliderBase(Qt::Horizontal, parent, name, 00025 Qt::WRepaintNoErase|Qt::WResizeNoErase) 00026 { 00027 d_angle = 0.0; 00028 d_oldAngle = 0.0; 00029 d_nTurns = 0.0; 00030 d_borderWidth = 2; 00031 d_borderDist = 4; 00032 d_totalAngle = 270.0; 00033 d_scaleDist = 4; 00034 d_hasScale = 0; 00035 d_symbol = Line; 00036 d_maxScaleTicks = 11; 00037 d_knobWidth = 50; 00038 d_dotWidth = 8; 00039 00040 scaleDraw()->setGeometry( 00041 0, 0, d_knobWidth + 2 * d_scaleDist, QwtScaleDraw::Round ); 00042 setUpdateTime(50); 00043 setTotalAngle( 270.0 ); 00044 recalcAngle(); 00045 setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); 00046 } 00047 00049 QwtKnob::~QwtKnob() 00050 { 00051 } 00052 00057 void QwtKnob::setSymbol(QwtKnob::Symbol s) 00058 { 00059 if ( d_symbol != s ) 00060 { 00061 d_symbol = s; 00062 update(); 00063 } 00064 } 00065 00070 QwtKnob::Symbol QwtKnob::symbol() const 00071 { 00072 return d_symbol; 00073 } 00074 00083 void QwtKnob::setTotalAngle (double angle) 00084 { 00085 if (angle < 10.0) 00086 d_totalAngle = 10.0; 00087 else 00088 d_totalAngle = angle; 00089 scaleDraw()->setAngleRange( -0.5 * d_totalAngle, 0.5 * d_totalAngle); 00090 layoutKnob(); 00091 } 00092 00093 00099 void QwtKnob::drawKnob(QPainter *p, const QRect &r) 00100 { 00101 const int bw2 = d_borderWidth / 2; 00102 00103 QRect aRect(r.x() + bw2, r.y() + bw2, 00104 r.width() - 2 * bw2, r.height() - 2 * bw2); 00105 00106 // 00107 // draw button face 00108 // 00109 p->setBrush(colorGroup().brush(QColorGroup::Button)); 00110 p->drawEllipse(aRect); 00111 00112 // 00113 // draw button shades 00114 // 00115 QPen pn; 00116 pn.setWidth(d_borderWidth); 00117 00118 pn.setColor(colorGroup().light()); 00119 p->setPen(pn); 00120 p->drawArc(aRect, 45*16,180*16); 00121 00122 pn.setColor(colorGroup().dark()); 00123 p->setPen(pn); 00124 p->drawArc(aRect, 225*16,180*16); 00125 00126 // 00127 // draw marker 00128 // 00129 if ( isValid() ) 00130 drawMarker(p, d_angle, colorGroup().buttonText()); 00131 } 00132 00139 void QwtKnob::valueChange() 00140 { 00141 recalcAngle(); 00142 update(); 00143 QwtSliderBase::valueChange(); 00144 } 00145 00152 double QwtKnob::getValue(const QPoint &p) 00153 { 00154 const double dx = double((rect().x() + rect().width() / 2) - p.x() ); 00155 const double dy = double((rect().y() + rect().height() / 2) - p.y() ); 00156 00157 const double arc = atan2(-dx,dy) * 180.0 / M_PI; 00158 00159 double newValue = 0.5 * (minValue() + maxValue()) 00160 + (arc + d_nTurns * 360.0) * (maxValue() - minValue()) 00161 / d_totalAngle; 00162 00163 const double oneTurn = fabs(maxValue() - minValue()) * 360.0 / d_totalAngle; 00164 const double eqValue = value() + d_mouseOffset; 00165 00166 if (fabs(newValue - eqValue) > 0.5 * oneTurn) 00167 { 00168 if (newValue < eqValue) 00169 newValue += oneTurn; 00170 else 00171 newValue -= oneTurn; 00172 } 00173 00174 return newValue; 00175 } 00176 00183 void QwtKnob::getScrollMode(const QPoint &p, int &scrollMode, int &direction) 00184 { 00185 const int r = d_kRect.width() / 2; 00186 00187 const int dx = d_kRect.x() + r - p.x(); 00188 const int dy = d_kRect.y() + r - p.y(); 00189 00190 if ( (dx * dx) + (dy * dy) <= (r * r)) // point is inside the knob 00191 { 00192 scrollMode = ScrMouse; 00193 direction = 0; 00194 } 00195 else // point lies outside 00196 { 00197 scrollMode = ScrTimer; 00198 double arc = atan2(double(-dx),double(dy)) * 180.0 / M_PI; 00199 if ( arc < d_angle) 00200 direction = -1; 00201 else if (arc > d_angle) 00202 direction = 1; 00203 else 00204 direction = 0; 00205 } 00206 } 00207 00208 00214 void QwtKnob::rangeChange() 00215 { 00216 if (!hasUserScale()) 00217 { 00218 scaleDraw()->setScale(minValue(), maxValue(), 00219 scaleMaxMajor(), scaleMaxMinor()); 00220 } 00221 layoutKnob(); 00222 recalcAngle(); 00223 } 00224 00228 void QwtKnob::resizeEvent(QResizeEvent *) 00229 { 00230 layoutKnob( FALSE ); 00231 } 00232 00234 // the current rect and fonts. 00235 // \param update_geometry notify the layout system and call update 00236 // to redraw the scale 00237 void QwtKnob::layoutKnob( bool update_geometry ) 00238 { 00239 const QRect &r = rect(); 00240 00241 const int width = qwtMin(qwtMin(r.height(), r.width()), d_knobWidth); 00242 const int width_2 = width / 2; 00243 00244 d_kRect.setRect(r.x() + r.width() / 2 - width_2, 00245 r.y() + r.height() / 2 - width_2, 00246 width, width); 00247 00248 scaleDraw()->setGeometry(d_kRect.x() - d_scaleDist, 00249 d_kRect.y() - d_scaleDist, 00250 width + 2 * d_scaleDist, QwtScaleDraw::Round ); 00251 00252 if ( update_geometry ) 00253 { 00254 updateGeometry(); 00255 update(); 00256 } 00257 } 00258 00262 void QwtKnob::paintEvent(QPaintEvent *e) 00263 { 00264 const QRect &ur = e->rect(); 00265 if ( ur.isValid() ) 00266 { 00267 QwtPaintBuffer paintBuffer(this, ur); 00268 draw(paintBuffer.painter(), ur); 00269 } 00270 } 00271 00275 void QwtKnob::draw(QPainter *painter, const QRect& ur) 00276 { 00277 if ( !d_kRect.contains( ur ) ) // event from valueChange() 00278 scaleDraw()->draw( painter ); 00279 drawKnob( painter, d_kRect ); 00280 00281 if ( hasFocus() ) 00282 { 00283 QRect r = rect(); 00284 00285 #if QT_VERSION < 300 00286 style().drawFocusRect(painter, r, colorGroup()); 00287 #else 00288 style().drawPrimitive(QStyle::PE_FocusRect, painter, 00289 r, colorGroup()); 00290 #endif 00291 } 00292 00293 } 00294 00301 void QwtKnob::drawMarker(QPainter *p, double arc, const QColor &c) 00302 { 00303 const double rarc = arc * M_PI / 180.0; 00304 const double ca = cos(rarc); 00305 const double sa = - sin(rarc); 00306 00307 int radius = d_kRect.width() / 2 - d_borderWidth; 00308 if (radius < 3) 00309 radius = 3; 00310 00311 const int ym = d_kRect.y() + radius + d_borderWidth; 00312 const int xm = d_kRect.x() + radius + d_borderWidth; 00313 00314 switch (d_symbol) 00315 { 00316 case Dot: 00317 { 00318 p->setBrush(c); 00319 p->setPen(Qt::NoPen); 00320 00321 const double rb = double(qwtMax(radius - 4 - d_dotWidth / 2, 0)); 00322 p->drawEllipse(xm - int(floor (sa * rb + 0.5)) - d_dotWidth / 2, 00323 ym - int(floor (ca * rb + 0.5)) - d_dotWidth / 2, 00324 d_dotWidth, d_dotWidth); 00325 break; 00326 } 00327 case Line: 00328 { 00329 p->setPen(QPen(c, 2)); 00330 00331 const double rb = qwtMax(double((radius - 4) / 3.0), 0.0); 00332 const double re = qwtMax(double(radius - 4), 0.0); 00333 00334 p->drawLine (xm - int (floor (sa * rb + 0.5)), 00335 ym - int (floor (ca * rb + 0.5)), 00336 xm - int (floor (sa * re + 0.5)), 00337 ym - int (floor (ca * re + 0.5))); 00338 00339 break; 00340 } 00341 } 00342 } 00343 00350 void QwtKnob::setKnobWidth(int w) 00351 { 00352 d_knobWidth = qwtMax(w,5); 00353 layoutKnob(); 00354 } 00355 00360 void QwtKnob::setBorderWidth(int bw) 00361 { 00362 d_borderWidth = qwtMax(bw, 0); 00363 layoutKnob(); 00364 } 00365 00370 void QwtKnob::recalcAngle() 00371 { 00372 d_oldAngle = d_angle; 00373 00374 // 00375 // calculate the angle corresponding to the value 00376 // 00377 if (maxValue() == minValue()) 00378 { 00379 d_angle = 0; 00380 d_nTurns = 0; 00381 } 00382 else 00383 { 00384 d_angle = (value() - 0.5 * (minValue() + maxValue())) 00385 / (maxValue() - minValue()) * d_totalAngle; 00386 d_nTurns = floor((d_angle + 180.0) / 360.0); 00387 d_angle = d_angle - d_nTurns * 360.0; 00388 } 00389 } 00390 00391 00396 void QwtKnob::scaleChange() 00397 { 00398 layoutKnob(); 00399 } 00400 00405 void QwtKnob::fontChange(const QFont &f) 00406 { 00407 QwtSliderBase::fontChange( f ); 00408 layoutKnob(); 00409 } 00410 00414 QSize QwtKnob::sizeHint() const 00415 { 00416 return minimumSizeHint(); 00417 } 00418 00424 QSize QwtKnob::minimumSizeHint() const 00425 { 00426 // Add the scale radial thickness to the knobWidth 00427 const int sh = scaleDraw()->minHeight( QPen(), fontMetrics() ); 00428 const int d = 2 * sh + 2 * d_scaleDist + d_knobWidth; 00429 00430 return QSize( d, d ); 00431 } 00432 00433 // Local Variables: 00434 // mode: C++ 00435 // c-file-style: "stroustrup" 00436 // indent-tabs-mode: nil 00437 // End:

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