# qwt_dial_needle.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 <math.h>
    00011 #include <qapplication.h>
    00012 #include <qpainter.h>
    00013 #include "qwt_math.h"
    00014 #include "qwt_painter.h"
    00015 #include "qwt_polygon.h"
    00016 #include "qwt_dial_needle.h"
    00017
    00018 #if QT_VERSION < 0x040000
    00019 typedef QColorGroup QwtPalette;
    00020 #else
    00021 typedef QPalette QwtPalette;
    00022 #endif
    00023
    00025 QwtDialNeedle::QwtDialNeedle():
    00026     d_palette(QApplication::palette())
    00027 {
    00028 }
    00029
    00031 QwtDialNeedle::~QwtDialNeedle()
    00032 {
    00033 }
    00034
    00040 void QwtDialNeedle::setPalette(const QPalette &palette)
    00041 {
    00042     d_palette = palette;
    00043 }
    00044
    00048 const QPalette &QwtDialNeedle::palette() const
    00049 {
    00050     return d_palette;
    00051 }
    00052
    00054 void QwtDialNeedle::drawKnob(QPainter *painter,
    00055     const QPoint &pos, int width, const QBrush &brush, bool sunken)
    00056 {
    00057     painter->save();
    00058
    00059     QRect rect(0, 0, width, width);
    00060     rect.moveCenter(pos);
    00061
    00062     painter->setPen(Qt::NoPen);
    00063     painter->setBrush(brush);
    00064     painter->drawEllipse(rect);
    00065
    00066     painter->setBrush(Qt::NoBrush);
    00067
    00068     const int colorOffset = 20;
    00069
    00070     int startAngle = 45;
    00071     if ( sunken )
    00072         startAngle += 180;
    00073
    00074     QPen pen;
    00075     pen.setWidth(1);
    00076
    00077     pen.setColor(brush.color().dark(100 - colorOffset));
    00078     painter->setPen(pen);
    00079     painter->drawArc(rect, startAngle * 16, 180 * 16);
    00080
    00081     pen.setColor(brush.color().dark(100 + colorOffset));
    00082     painter->setPen(pen);
    00083     painter->drawArc(rect, (startAngle + 180) * 16, 180 * 16);
    00084
    00085     painter->restore();
    00086 }
    00087
    00091 QwtDialSimpleNeedle::QwtDialSimpleNeedle(Style style, bool hasKnob,
    00092         const QColor &mid, const QColor &base):
    00093     d_style(style),
    00094     d_hasKnob(hasKnob),
    00095     d_width(-1)
    00096 {
    00097     QPalette palette;
    00098     for ( int i = 0; i < QPalette::NColorGroups; i++ )
    00099     {
    00100         palette.setColor((QPalette::ColorGroup)i,
    00101             QwtPalette::Mid, mid);
    00102         palette.setColor((QPalette::ColorGroup)i,
    00103             QwtPalette::Base, base);
    00104     }
    00105
    00106     setPalette(palette);
    00107 }
    00108
    00110 void QwtDialSimpleNeedle::setWidth(int width)
    00111 {
    00112     d_width = width;
    00113 }
    00114
    00118 int QwtDialSimpleNeedle::width() const
    00119 {
    00120     return d_width;
    00121 }
    00122
    00132 void QwtDialSimpleNeedle::draw(QPainter *painter, const QPoint &center,
    00133     int length, double direction, QPalette::ColorGroup colorGroup) const
    00134 {
    00135     if ( d_style == Arrow )
    00136     {
    00137         drawArrowNeedle(painter, palette(), colorGroup,
    00138             center, length, d_width, direction, d_hasKnob);
    00139     }
    00140     else
    00141     {
    00142         drawRayNeedle(painter, palette(), colorGroup,
    00143             center, length, d_width, direction, d_hasKnob);
    00144     }
    00145 }
    00146
    00150 void QwtDialSimpleNeedle::drawRayNeedle(QPainter *painter,
    00151     const QPalette &palette, QPalette::ColorGroup colorGroup,
    00152     const QPoint &center, int length, int width, double direction,
    00153     bool hasKnob)
    00154 {
    00155     if ( width <= 0 )
    00156         width = 5;
    00157
    00158     direction *= M_PI / 180.0;
    00159
    00160     painter->save();
    00161
    00162     const QPoint p1(center.x() + 1, center.y() + 2);
    00163     const QPoint p2 = qwtPolar2Pos(p1, length, direction);
    00164
    00165     if ( width == 1 )
    00166     {
    00167         const QColor midColor =
    00168             palette.color(colorGroup, QwtPalette::Mid);
    00169
    00170         painter->setPen(QPen(midColor, 1));
    00171         painter->drawLine(p1, p2);
    00172     }
    00173     else
    00174     {
    00175         QwtPolygon pa(4);
    00176         pa.setPoint(0, qwtPolar2Pos(p1, width / 2, direction + M_PI_2));
    00177         pa.setPoint(1, qwtPolar2Pos(p2, width / 2, direction + M_PI_2));
    00178         pa.setPoint(2, qwtPolar2Pos(p2, width / 2, direction - M_PI_2));
    00179         pa.setPoint(3, qwtPolar2Pos(p1, width / 2, direction - M_PI_2));
    00180
    00181         painter->setPen(Qt::NoPen);
    00182         painter->setBrush(palette.brush(colorGroup, QwtPalette::Mid));
    00183         painter->drawPolygon(pa);
    00184     }
    00185     if ( hasKnob )
    00186     {
    00187         int knobWidth = qwtMax(qRound(width * 0.7), 5);
    00188         if ( knobWidth % 2 == 0 )
    00189             knobWidth++;
    00190
    00191         drawKnob(painter, center, knobWidth,
    00192             palette.brush(colorGroup, QwtPalette::Base),
    00193             false);
    00194     }
    00195
    00196     painter->restore();
    00197 }
    00198
    00202 void QwtDialSimpleNeedle::drawArrowNeedle(QPainter *painter,
    00203     const QPalette &palette, QPalette::ColorGroup colorGroup,
    00204     const QPoint &center, int length, int width,
    00205     double direction, bool hasKnob)
    00206 {
    00207     direction *= M_PI / 180.0;
    00208
    00209     painter->save();
    00210
    00211     if ( width <= 0 )
    00212     {
    00213         width = (int)qwtMax(length * 0.06, 9.0);
    00214         if ( width % 2 == 0 )
    00215             width++;
    00216     }
    00217
    00218     const int peak = 3;
    00219     const QPoint p1(center.x() + 1, center.y() + 1);
    00220     const QPoint p2 = qwtPolar2Pos(p1, length - peak, direction);
    00221     const QPoint p3 = qwtPolar2Pos(p1, length, direction);
    00222
    00223     QwtPolygon pa(5);
    00224     pa.setPoint(0, qwtPolar2Pos(p1, width / 2, direction - M_PI_2));
    00225     pa.setPoint(1, qwtPolar2Pos(p2, 1, direction - M_PI_2));
    00226     pa.setPoint(2, p3);
    00227     pa.setPoint(3, qwtPolar2Pos(p2, 1, direction + M_PI_2));
    00228     pa.setPoint(4, qwtPolar2Pos(p1, width / 2, direction + M_PI_2));
    00229
    00230     painter->setPen(Qt::NoPen);
    00231     painter->setBrush(palette.brush(colorGroup, QwtPalette::Mid));
    00232     painter->drawPolygon(pa);
    00233
    00234     QwtPolygon shadowPa(3);
    00235
    00236     const int colorOffset = 10;
    00237
    00238     int i;
    00239     for ( i = 0; i < 3; i++ )
    00240         shadowPa.setPoint(i, pa[i]);
    00241
    00242     const QColor midColor = palette.color(colorGroup, QwtPalette::Mid);
    00243
    00244     painter->setPen(midColor.dark(100 + colorOffset));
    00245     painter->drawPolyline(shadowPa);
    00246
    00247     for ( i = 0; i < 3; i++ )
    00248         shadowPa.setPoint(i, pa[i + 2]);
    00249
    00250     painter->setPen(midColor.dark(100 - colorOffset));
    00251     painter->drawPolyline(shadowPa);
    00252
    00253     if ( hasKnob )
    00254     {
    00255         drawKnob(painter, center, qRound(width * 1.3),
    00256             palette.brush(colorGroup, QwtPalette::Base),
    00257             false);
    00258     }
    00259
    00260     painter->restore();
    00261 }
    00262
    00264
    00265 QwtCompassMagnetNeedle::QwtCompassMagnetNeedle(Style style,
    00266         const QColor &light, const QColor &dark):
    00267     d_style(style)
    00268 {
    00269     QPalette palette;
    00270     for ( int i = 0; i < QPalette::NColorGroups; i++ )
    00271     {
    00272         palette.setColor((QPalette::ColorGroup)i,
    00273             QwtPalette::Light, light);
    00274         palette.setColor((QPalette::ColorGroup)i,
    00275             QwtPalette::Dark, dark);
    00276         palette.setColor((QPalette::ColorGroup)i,
    00277             QwtPalette::Base, Qt::darkGray);
    00278     }
    00279
    00280     setPalette(palette);
    00281 }
    00282
    00292 void QwtCompassMagnetNeedle::draw(QPainter *painter, const QPoint &center,
    00293     int length, double direction, QPalette::ColorGroup colorGroup) const
    00294 {
    00295     if ( d_style == ThinStyle )
    00296     {
    00297         drawThinNeedle(painter, palette(), colorGroup,
    00298             center, length, direction);
    00299     }
    00300     else
    00301     {
    00302         drawTriangleNeedle(painter, palette(), colorGroup,
    00303             center, length, direction);
    00304     }
    00305 }
    00306
    00317 void QwtCompassMagnetNeedle::drawTriangleNeedle(QPainter *painter,
    00318     const QPalette &palette, QPalette::ColorGroup colorGroup,
    00319     const QPoint &center, int length, double direction)
    00320 {
    00321     const QBrush darkBrush = palette.brush(colorGroup, QwtPalette::Dark);
    00322     const QBrush lightBrush = palette.brush(colorGroup, QwtPalette::Light);
    00323
    00324     QBrush brush;
    00325
    00326     const int width = qRound(length / 3.0);
    00327     const int colorOffset =  10;
    00328
    00329     painter->save();
    00330     painter->setPen(Qt::NoPen);
    00331
    00332     const QPoint arrowCenter(center.x() + 1, center.y() + 1);
    00333
    00334     QwtPolygon pa(3);
    00335     pa.setPoint(0, arrowCenter);
    00336     pa.setPoint(1, qwtDegree2Pos(arrowCenter, length, direction));
    00337
    00338     pa.setPoint(2, qwtDegree2Pos(arrowCenter, width / 2, direction + 90.0));
    00339
    00340     brush = darkBrush;
    00341     brush.setColor(brush.color().dark(100 + colorOffset));
    00342     painter->setBrush(brush);
    00343     painter->drawPolygon(pa);
    00344
    00345     pa.setPoint(2, qwtDegree2Pos(arrowCenter, width / 2, direction - 90.0));
    00346
    00347     brush = darkBrush;
    00348     brush.setColor(brush.color().dark(100 - colorOffset));
    00349     painter->setBrush(brush);
    00350     painter->drawPolygon(pa);
    00351
    00352     // --
    00353
    00354     pa.setPoint(1, qwtDegree2Pos(arrowCenter, length, direction + 180.0));
    00355
    00356     pa.setPoint(2, qwtDegree2Pos(arrowCenter, width / 2, direction + 90.0));
    00357
    00358     brush = lightBrush;
    00359     brush.setColor(brush.color().dark(100 + colorOffset));
    00360     painter->setBrush(brush);
    00361     painter->drawPolygon(pa);
    00362
    00363     pa.setPoint(2, qwtDegree2Pos(arrowCenter, width / 2, direction - 90.0));
    00364
    00365     brush = lightBrush;
    00366     brush.setColor(brush.color().dark(100 - colorOffset));
    00367     painter->setBrush(brush);
    00368     painter->drawPolygon(pa);
    00369
    00370     painter->restore();
    00371 }
    00372
    00383 void QwtCompassMagnetNeedle::drawThinNeedle(QPainter *painter,
    00384     const QPalette &palette, QPalette::ColorGroup colorGroup,
    00385     const QPoint &center, int length, double direction)
    00386 {
    00387     const QBrush darkBrush = palette.brush(colorGroup, QwtPalette::Dark);
    00388     const QBrush lightBrush = palette.brush(colorGroup, QwtPalette::Light);
    00389     const QBrush baseBrush = palette.brush(colorGroup, QwtPalette::Base);
    00390
    00391     const int colorOffset = 10;
    00392     const int width = qwtMax(qRound(length / 6.0), 3);
    00393
    00394     painter->save();
    00395
    00396     const QPoint arrowCenter(center.x() + 1, center.y() + 1);
    00397
    00398     drawPointer(painter, darkBrush, colorOffset,
    00399         arrowCenter, length, width, direction);
    00400     drawPointer(painter, lightBrush, -colorOffset,
    00401         arrowCenter, length, width, direction + 180.0);
    00402
    00403     drawKnob(painter, arrowCenter, width, baseBrush, true);
    00404
    00405     painter->restore();
    00406 }
    00407
    00419 void QwtCompassMagnetNeedle::drawPointer(
    00420     QPainter *painter, const QBrush &brush,
    00421     int colorOffset, const QPoint &center, int length,
    00422     int width, double direction)
    00423 {
    00424     painter->save();
    00425
    00426     const int peak = qwtMax(qRound(length / 10.0), 5);
    00427
    00428     const int knobWidth = width + 8;
    00429     QRect knobRect(0, 0, knobWidth, knobWidth);
    00430     knobRect.moveCenter(center);
    00431
    00432     QwtPolygon pa(5);
    00433
    00434     pa.setPoint(0, qwtDegree2Pos(center, width / 2, direction + 90.0));
    00435     pa.setPoint(1, center);
    00436     pa.setPoint(2, qwtDegree2Pos(pa.point(1), length - peak, direction));
    00437     pa.setPoint(3, qwtDegree2Pos(center, length, direction));
    00438     pa.setPoint(4, qwtDegree2Pos(pa.point(0), length - peak, direction));
    00439
    00440     painter->setPen(Qt::NoPen);
    00441
    00442     QBrush darkBrush = brush;
    00443     darkBrush.setColor(darkBrush.color().dark(100 + colorOffset));
    00444     painter->setBrush(darkBrush);
    00445     painter->drawPolygon(pa);
    00446     painter->drawPie(knobRect, qRound(direction * 16), 90 * 16);
    00447
    00448     pa.setPoint(0, qwtDegree2Pos(center, width / 2, direction - 90.0));
    00449     pa.setPoint(4, qwtDegree2Pos(pa.point(0), length - peak, direction));
    00450
    00451     QBrush lightBrush = brush;
    00452     lightBrush.setColor(lightBrush.color().dark(100 - colorOffset));
    00453     painter->setBrush(lightBrush);
    00454     painter->drawPolygon(pa);
    00455     painter->drawPie(knobRect, qRound(direction * 16), -90 * 16);
    00456
    00457     painter->restore();
    00458 }
    00459
    00467 QwtCompassWindArrow::QwtCompassWindArrow(Style style,
    00468         const QColor &light, const QColor &dark):
    00469     d_style(style)
    00470 {
    00471     QPalette palette;
    00472     for ( int i = 0; i < QPalette::NColorGroups; i++ )
    00473     {
    00474         palette.setColor((QPalette::ColorGroup)i,
    00475             QwtPalette::Light, light);
    00476         palette.setColor((QPalette::ColorGroup)i,
    00477             QwtPalette::Dark, dark);
    00478     }
    00479
    00480     setPalette(palette);
    00481 }
    00482
    00492 void QwtCompassWindArrow::draw(QPainter *painter, const QPoint &center,
    00493     int length, double direction, QPalette::ColorGroup colorGroup) const
    00494 {
    00495     if ( d_style == Style1 )
    00496     {
    00497         drawStyle1Needle(painter, palette(), colorGroup,
    00498             center, length, direction);
    00499     }
    00500     else
    00501     {
    00502         drawStyle2Needle(painter, palette(), colorGroup,
    00503             center, length, direction);
    00504     }
    00505 }
    00506
    00517 void QwtCompassWindArrow::drawStyle1Needle(QPainter *painter,
    00518     const QPalette &palette, QPalette::ColorGroup colorGroup,
    00519     const QPoint &center, int length, double direction)
    00520 {
    00521     const QBrush lightBrush = palette.brush(colorGroup, QwtPalette::Light);
    00522
    00523     const double AR1[] = {0, 0.4, 0.3, 1, 0.8, 1, 0.3, 0.4};
    00524     const double AW1[] = {0, -45, -20, -15, 0, 15, 20, 45};
    00525
    00526     const QPoint arrowCenter(center.x() + 1, center.y() + 1);
    00527
    00528     QwtPolygon pa(8);
    00529     pa.setPoint(0, arrowCenter);
    00530     for (int i=1; i<8; i++)
    00531     {
    00532         const QPoint p = qwtDegree2Pos(center,
    00533             AR1[i] * length, direction + AW1[i]);
    00534         pa.setPoint(i, p);
    00535     }
    00536
    00537     painter->save();
    00538     painter->setPen(Qt::NoPen);
    00539     painter->setBrush(lightBrush);
    00540     painter->drawPolygon(pa);
    00541     painter->restore();
    00542 }
    00543
    00554 void QwtCompassWindArrow::drawStyle2Needle(QPainter *painter,
    00555     const QPalette &palette, QPalette::ColorGroup colorGroup,
    00556     const QPoint &center, int length, double direction)
    00557 {
    00558     const QBrush lightBrush = palette.brush(colorGroup, QwtPalette::Light);
    00559     const QBrush darkBrush = palette.brush(colorGroup, QwtPalette::Dark);
    00560
    00561     painter->save();
    00562     painter->setPen(Qt::NoPen);
    00563
    00564     const double angle = 12.0;
    00565     const double ratio = 0.7;
    00566
    00567     const QPoint arrowCenter(center.x() + 1, center.y() + 1);
    00568
    00569     QwtPolygon pa(3);
    00570
    00571     pa.setPoint(0, center);
    00572     pa.setPoint(2, qwtDegree2Pos(arrowCenter, ratio * length, direction));
    00573
    00574     pa.setPoint(1, qwtDegree2Pos(arrowCenter, length, direction + angle));
    00575     painter->setBrush(darkBrush);
    00576     painter->drawPolygon(pa);
    00577
    00578     pa.setPoint(1, qwtDegree2Pos(arrowCenter, length, direction - angle));
    00579     painter->setBrush(lightBrush);
    00580     painter->drawPolygon(pa);
    00581
    00582     painter->restore();
    00583 }
    00584