00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <iostream>
00011 #include <math.h>
00012 #include <qpainter.h>
00013 #include <qpixmap.h>
00014 #include "qwt_math.h"
00015 #include "qwt_paint_buffer.h"
00016 #include "qwt_painter.h"
00017 #include "qwt_dial_needle.h"
00018 #include "qwt_dial.h"
00019
00020 QwtDialScaleDraw::QwtDialScaleDraw(QwtDial *parent):
00021 d_parent(parent)
00022 {
00023 }
00024
00025 QString QwtDialScaleDraw::label(double value) const
00026 {
00027 if ( d_parent == NULL )
00028 return QwtScaleDraw::label(value);
00029
00030 return d_parent->scaleLabel(value);
00031 }
00032
00044 QwtDial::QwtDial(QWidget* parent, const char* name):
00045 QwtSliderBase(Qt::Horizontal, parent, name,
00046 WRepaintNoErase|WResizeNoErase),
00047 d_visibleBackground(FALSE),
00048 d_frameShadow(Sunken),
00049 d_lineWidth(0),
00050 d_mode(RotateNeedle),
00051 d_wrapping(FALSE),
00052 d_origin(90.0),
00053 d_minScaleArc(0.0),
00054 d_maxScaleArc(0.0),
00055 d_scaleDraw(0),
00056 d_maxMajIntv(36),
00057 d_maxMinIntv(10),
00058 d_scaleStep(0.0),
00059 d_needle(0)
00060 {
00061 setFocusPolicy(QWidget::TabFocus);
00062
00063 QPalette p = palette();
00064 for ( int i = 0; i < QPalette::NColorGroups; i++ )
00065 {
00066 const QPalette::ColorGroup cg = (QPalette::ColorGroup)i;
00067
00068
00069
00070
00071 p.setColor(cg, QColorGroup::Foreground,
00072 p.color(cg, QColorGroup::Base));
00073 }
00074 setPalette(p);
00075
00076 d_scaleDraw = new QwtDialScaleDraw(this);
00077 d_scaleDraw->setGeometry(0, 0, 0, QwtScaleDraw::Round);
00078
00079 setScaleArc(0.0, 360.0);
00080 setRange(0.0, 360.0, 1.0);
00081 }
00082
00084 QwtDial::~QwtDial()
00085 {
00086 delete d_scaleDraw;
00087 delete d_needle;
00088 }
00089
00099 void QwtDial::showBackground(bool show)
00100 {
00101 if ( d_visibleBackground != show )
00102 {
00103 d_visibleBackground = show;
00104
00105 if ( d_visibleBackground )
00106 clearMask();
00107 else
00108 {
00109 const QRect r = boundingRect();
00110
00111 QRegion region(QRect(r.x() - 1, r.y() - 1,
00112 r.width() + 2, r.height() + 2), QRegion::Ellipse);
00113
00114 setMask(region);
00115 }
00116 update();
00117 }
00118 }
00119
00126 bool QwtDial::hasVisibleBackground() const
00127 {
00128 return d_visibleBackground;
00129 }
00130
00137 void QwtDial::setFrameShadow(Shadow shadow)
00138 {
00139 if ( shadow != d_frameShadow )
00140 {
00141 d_frameShadow = shadow;
00142 if ( lineWidth() > 0 )
00143 update();
00144 }
00145 }
00146
00153 QwtDial::Shadow QwtDial::frameShadow() const
00154 {
00155 return d_frameShadow;
00156 }
00157
00164 void QwtDial::setLineWidth(int lineWidth)
00165 {
00166 if ( lineWidth < 0 )
00167 lineWidth = 0;
00168
00169 if ( d_lineWidth != lineWidth )
00170 {
00171 d_lineWidth = lineWidth;
00172 update();
00173 }
00174 }
00175
00181 int QwtDial::lineWidth() const
00182 {
00183 return d_lineWidth;
00184 }
00185
00191 QRect QwtDial::contentsRect() const
00192 {
00193 const int lw = lineWidth();
00194
00195 QRect r = boundingRect();
00196 if ( lw > 0 )
00197 {
00198 r.setRect(r.x() + lw, r.y() + lw,
00199 r.width() - 2 * lw, r.height() - 2 * lw);
00200 }
00201 return r;
00202 }
00203
00209 QRect QwtDial::boundingRect() const
00210 {
00211 const int radius = QMIN(width(), height()) / 2;
00212 const QPoint center = rect().center();
00213
00214 int x = center.x() + width() % 2 - radius;
00215 if ( width() % 2 == 0 )
00216 x++;
00217
00218 int y = center.y() - radius;
00219 if ( height() % 2 == 0 )
00220 y++;
00221
00222 return QRect(x, y, 2 * radius, 2 * radius);
00223 }
00224
00230 QRect QwtDial::scaleContentsRect() const
00231 {
00232 const QPen scalePen(colorGroup().text(), 0, NoPen);
00233
00234 int scaleDist = 0;
00235 if ( d_scaleDraw )
00236 {
00237 scaleDist = QMAX(
00238 d_scaleDraw->maxWidth(scalePen, fontMetrics()),
00239 d_scaleDraw->maxHeight(scalePen, fontMetrics()));
00240 }
00241
00242 const QRect rect = contentsRect();
00243
00244 return QRect(rect.x() + scaleDist, rect.y() + scaleDist,
00245 rect.width() - 2 * scaleDist, rect.height() - 2 * scaleDist);
00246 }
00247
00262 void QwtDial::setMode(Mode mode)
00263 {
00264 if ( mode != d_mode )
00265 {
00266 d_mode = mode;
00267 update();
00268 }
00269 }
00270
00284 QwtDial::Mode QwtDial::mode() const
00285 {
00286 return d_mode;
00287 }
00288
00289 void QwtDial::setWrapping(bool wrapping)
00290 {
00291 d_wrapping = wrapping;
00292 }
00293
00294 bool QwtDial::wrapping() const
00295 {
00296 return d_wrapping;
00297 }
00298
00300 void QwtDial::resizeEvent(QResizeEvent *e)
00301 {
00302 QWidget::resizeEvent(e);
00303
00304 if ( !hasVisibleBackground() )
00305 {
00306 const QRect r = boundingRect();
00307
00308 QRegion region(QRect(r.x() - 1, r.y() - 1,
00309 r.width() + 2, r.height() + 2), QRegion::Ellipse);
00310
00311 setMask(region);
00312 }
00313 }
00314
00316 void QwtDial::paintEvent(QPaintEvent *e)
00317 {
00318 const QRect &ur = e->rect();
00319 if ( ur.isValid() )
00320 {
00321 QwtPaintBuffer paintBuffer(this, ur);
00322
00323 QPainter *painter = paintBuffer.painter();
00324
00325 drawFrame(painter);
00326 drawContents(painter);
00327
00328 #if 0
00329 if ( hasFocus() )
00330 {
00331 QRect focusRect = contentsRect();
00332
00333 const int margin = 2;
00334 focusRect.setRect(focusRect.x() + margin, focusRect.y() + margin,
00335 focusRect.width() - 2 * margin, focusRect.height() - margin);
00336
00337 painter->setBrush(Qt::NoBrush);
00338 painter->setPen(QPen(colorGroup().mid(), 0, Qt::DotLine));
00339 painter->drawEllipse(focusRect);
00340 }
00341 #endif
00342 }
00343 }
00344
00351 void QwtDial::drawFrame(QPainter *painter)
00352 {
00353 const int lw = lineWidth();
00354
00355 QRect r = boundingRect();
00356 r.setRect(r.x() + lw / 2, r.y() + lw / 2,
00357 r.width() - lw, r.height() - lw);
00358
00359 if ( lw > 0 )
00360 {
00361 switch(d_frameShadow)
00362 {
00363 case QFrame::Raised:
00364 QwtPainter::drawRoundFrame(painter, r, lw, FALSE);
00365 break;
00366 case QFrame::Sunken:
00367 QwtPainter::drawRoundFrame(painter, r, lw, TRUE);
00368 break;
00369 default:
00370 {
00371 painter->setPen(QPen(Qt::black, lw));
00372 painter->drawEllipse(r);
00373 }
00374 }
00375 }
00376 }
00377
00390 void QwtDial::drawContents(QPainter *painter) const
00391 {
00392 if ( colorGroup().base() != colorGroup().background() )
00393 {
00394 painter->setPen(NoPen);
00395 painter->setBrush(colorGroup().base());
00396 painter->drawEllipse(contentsRect());
00397 }
00398
00399 QPalette::ColorGroup cg;
00400 if ( isEnabled() )
00401 cg = hasFocus() ? QPalette::Active : QPalette::Inactive;
00402 else
00403 cg = QPalette::Disabled;
00404
00405 const QRect insideScaleRect = scaleContentsRect();
00406 if ( colorGroup().base() != colorGroup().background() )
00407 {
00408 painter->setPen(NoPen);
00409 painter->setBrush(colorGroup().base());
00410 painter->drawEllipse(insideScaleRect);
00411 }
00412
00413 const QPoint center = insideScaleRect.center();
00414 const int radius = insideScaleRect.width() / 2;
00415
00416 #if 0
00417 const int margin = 4;
00418 #endif
00419
00420 if ( colorGroup().foreground() != colorGroup().base() )
00421 {
00422 painter->setPen(NoPen);
00423 painter->setBrush(colorGroup().foreground());
00424 painter->drawEllipse(insideScaleRect);
00425 }
00426
00427 painter->save();
00428 drawScaleContents(painter, center, radius);
00429 painter->restore();
00430
00431 double direction = d_origin;
00432
00433 if (isValid())
00434 {
00435 direction = d_origin + d_minScaleArc;
00436 if ( maxValue() > minValue() && d_maxScaleArc > d_minScaleArc )
00437 {
00438 const double ratio =
00439 (value() - minValue()) / (maxValue() - minValue());
00440 direction += ratio * (d_maxScaleArc - d_minScaleArc);
00441 }
00442
00443 if ( direction >= 360.0 )
00444 direction -= 360.0;
00445 }
00446
00447 double origin = d_origin;
00448 if ( mode() == RotateScale )
00449 {
00450 origin -= direction - d_origin;
00451 direction = d_origin;
00452 }
00453
00454 painter->save();
00455 drawScale(painter, center, radius, origin, d_minScaleArc, d_maxScaleArc);
00456 painter->restore();
00457
00458 if ( isValid() )
00459 {
00460 painter->save();
00461 drawNeedle(painter, center, radius, direction, cg);
00462 painter->restore();
00463 }
00464 }
00465
00475 void QwtDial::drawNeedle(QPainter *painter, const QPoint ¢er,
00476 int radius, double direction, QPalette::ColorGroup cg) const
00477 {
00478 if ( d_needle )
00479 {
00480 direction = 360.0 - direction;
00481 d_needle->draw(painter, center, radius, direction, cg);
00482 }
00483 }
00484
00485 void QwtDial::drawScale(QPainter *painter, const QPoint ¢er,
00486 int radius, double origin, double minArc, double maxArc) const
00487 {
00488 if ( d_scaleDraw == NULL )
00489 return;
00490
00491 origin -= 270.0;
00492
00493 double angle = maxArc - minArc;
00494 if ( angle > 360.0 )
00495 angle = fmod(angle, 360.0);
00496
00497 minArc += origin;
00498 if ( minArc < -360.0 )
00499 minArc = fmod(minArc, 360.0);
00500
00501 maxArc = minArc + angle;
00502 if ( maxArc > 360.0 )
00503 {
00504
00505
00506 minArc -= 360.0;
00507 maxArc -= 360.0;
00508 }
00509
00510 d_scaleDraw->setAngleRange(minArc, maxArc);
00511 d_scaleDraw->setGeometry(center.x() - radius, center.y() - radius,
00512 2 * radius, QwtScaleDraw::Round);
00513
00514 painter->setFont(font());
00515 painter->setPen(colorGroup().text());
00516 d_scaleDraw->draw(painter);
00517 }
00518
00527 void QwtDial::drawScaleContents(QPainter *,
00528 const QPoint &, int) const
00529 {
00530
00531 }
00532
00540 void QwtDial::setNeedle(QwtDialNeedle *needle)
00541 {
00542 if ( needle != d_needle )
00543 {
00544 if ( d_needle )
00545 delete d_needle;
00546
00547 d_needle = needle;
00548 update();
00549 }
00550 }
00551
00557 const QwtDialNeedle *QwtDial::needle() const
00558 {
00559 return d_needle;
00560 }
00561
00567 QwtDialNeedle *QwtDial::needle()
00568 {
00569 return d_needle;
00570 }
00571
00572 void QwtDial::rangeChange()
00573 {
00574 updateScale();
00575 }
00576
00577 void QwtDial::updateScale()
00578 {
00579 if ( d_scaleDraw )
00580 {
00581 d_scaleDraw->setScale(minValue(), maxValue(),
00582 d_maxMajIntv, d_maxMinIntv, d_scaleStep);
00583 }
00584 }
00585
00586 void QwtDial::setScaleDraw(QwtDialScaleDraw *scaleDraw)
00587 {
00588 if ( scaleDraw != d_scaleDraw )
00589 {
00590 if ( d_scaleDraw )
00591 delete d_scaleDraw;
00592
00593 d_scaleDraw = scaleDraw;
00594 updateScale();
00595 update();
00596 }
00597 }
00598
00599 void QwtDial::setScale(int maxMajIntv, int maxMinIntv, double step)
00600 {
00601 d_maxMajIntv = maxMajIntv;
00602 d_maxMinIntv = maxMinIntv;
00603 d_scaleStep = step;
00604
00605 updateScale();
00606 }
00607
00608 QString QwtDial::scaleLabel(double value) const
00609 {
00610 #if 1
00611 if ( value == -0 )
00612 value = 0;
00613 #endif
00614
00615 QString text;
00616 text.sprintf("%g", value);
00617
00618 return text;
00619 }
00620
00621 void QwtDial::setOrigin(double origin)
00622 {
00623 d_origin = origin;
00624 update();
00625 }
00626
00627 double QwtDial::origin() const
00628 {
00629 return d_origin;
00630 }
00631
00632 void QwtDial::setScaleArc(double minArc, double maxArc)
00633 {
00634
00635
00636 if ( minArc != 360.0 && minArc != -360.0 )
00637 minArc = fmod(minArc, 360.0);
00638 if ( maxArc != 360.0 && maxArc != -360.0 )
00639 maxArc = fmod(maxArc, 360.0);
00640
00641 d_minScaleArc = QMIN(minArc, maxArc);
00642 d_maxScaleArc = QMAX(minArc, maxArc);
00643 if ( d_maxScaleArc - d_minScaleArc > 360.0 )
00644 d_maxScaleArc = d_minScaleArc + 360.0;
00645
00646 update();
00647 }
00648
00649 void QwtDial::valueChange()
00650 {
00651 update();
00652 QwtSliderBase::valueChange();
00653 }
00654
00658 QSize QwtDial::sizeHint() const
00659 {
00660 int sh = 0;
00661 if ( d_scaleDraw )
00662 sh = d_scaleDraw->minHeight( QPen(), fontMetrics() );
00663
00664 const int d = 6 * sh + 2 * lineWidth();
00665
00666 return QSize( d, d );
00667 }
00668
00674 QSize QwtDial::minimumSizeHint() const
00675 {
00676 int sh = 0;
00677 if ( d_scaleDraw )
00678 sh = d_scaleDraw->minHeight( QPen(), fontMetrics() );
00679
00680 const int d = 3 * sh + 2 * lineWidth();
00681
00682 return QSize( d, d );
00683 }
00684
00685 static double line2Radians(const QPoint &p1, const QPoint &p2)
00686 {
00687 const QPoint p = p2 - p1;
00688
00689 double angle;
00690 if ( p.x() == 0 )
00691 angle = ( p.y() <= 0 ) ? M_PI_2 : 3 * M_PI_2;
00692 else
00693 {
00694 angle = atan(double(-p.y()) / double(p.x()));
00695 if ( p.x() < 0 )
00696 angle += M_PI;
00697 if ( angle < 0.0 )
00698 angle += 2 * M_PI;
00699 }
00700 return 360.0 - angle * 180.0 / M_PI;
00701 }
00702
00703 double QwtDial::getValue(const QPoint &p)
00704 {
00705 if ( d_maxScaleArc == d_minScaleArc || maxValue() == minValue() )
00706 return minValue();
00707
00708 double dir = line2Radians(rect().center(), p) - d_origin;
00709 if ( dir < 0.0 )
00710 dir += 360.0;
00711
00712 double value;
00713
00714 if ( mode() == RotateScale )
00715 {
00716 value = 360.0 - dir;
00717 }
00718 else
00719 {
00720 const double ratio =
00721 (dir - d_minScaleArc) / (d_maxScaleArc - d_minScaleArc);
00722 value = minValue() + ratio * (maxValue() - minValue());
00723 }
00724
00725 if ( d_scrollMode == ScrMouse )
00726 {
00727 if ( value - d_mouseOffset < 0.0 )
00728 value += 360.0;
00729 if ( value - d_mouseOffset >= 360.0 )
00730 value -= 360.0;
00731 }
00732
00733 return value;
00734 }
00735
00736 void QwtDial::getScrollMode(const QPoint &p, int &scrollMode, int &direction)
00737 {
00738 direction = 0;
00739
00740 const QRegion region(contentsRect(), QRegion::Ellipse);
00741 if ( !region.contains(p) || p == rect().center() )
00742 scrollMode = ScrNone;
00743 else
00744 scrollMode = ScrMouse;
00745 }
00746