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

qwt_thermo.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 <qevent.h>
00012 #include <qstyle.h>
00013 #include <qpixmap.h>
00014 #include <qdrawutil.h>
00015 #include "qwt_math.h"
00016 #include "qwt_scale_engine.h"
00017 #include "qwt_scale_draw.h"
00018 #include "qwt_scale_map.h"
00019 #include "qwt_paint_buffer.h"
00020 #include "qwt_thermo.h"
00021 
00022 class QwtThermo::PrivateData
00023 {
00024 public:
00025     PrivateData():
00026         fillBrush(Qt::black),
00027         alarmBrush(Qt::white),
00028         orientation(Qt::Vertical),
00029         scalePos(QwtThermo::Left),
00030         borderWidth(2),
00031         scaleDist(3),
00032         thermoWidth(10),
00033         minValue(0.0),
00034         maxValue(1.0),
00035         value(0.0),
00036         alarmLevel(0.0),
00037         alarmEnabled(false)
00038     {
00039         map.setScaleInterval(minValue, maxValue);
00040     }
00041 
00042     QwtScaleMap map;
00043     QRect thermoRect;
00044     QBrush fillBrush;
00045     QBrush alarmBrush;
00046 
00047     Qt::Orientation orientation;
00048     ScalePos scalePos;
00049     int borderWidth;
00050     int scaleDist;
00051     int thermoWidth;
00052 
00053     double minValue;
00054     double maxValue;
00055     double value;
00056     double alarmLevel;
00057     bool alarmEnabled;
00058 };
00059 
00061 QwtThermo::QwtThermo(QWidget *parent): 
00062     QWidget(parent)
00063 {
00064 #if QT_VERSION < 0x040000
00065     setWFlags(Qt::WNoAutoErase);
00066 #endif
00067     d_data = new PrivateData;
00068     setRange(d_data->minValue, d_data->maxValue, false);
00069 
00070     QSizePolicy policy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
00071     if (d_data->orientation == Qt::Vertical) 
00072         policy.transpose();
00073 
00074     setSizePolicy(policy);
00075     
00076 #if QT_VERSION >= 0x040000
00077     setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00078 #else
00079     clearWState( WState_OwnSizePolicy );
00080 #endif
00081 }
00082 
00084 QwtThermo::~QwtThermo()
00085 {
00086     delete d_data;
00087 }
00088 
00090 void QwtThermo::setMaxValue(double v) 
00091 { 
00092     setRange(d_data->minValue, v); 
00093 }
00094 
00096 double QwtThermo::maxValue() const 
00097 { 
00098     return d_data->maxValue; 
00099 }
00100 
00102 void QwtThermo::setMinValue(double v) 
00103 { 
00104     setRange(v, d_data->maxValue); 
00105 }
00106 
00108 double QwtThermo::minValue() const 
00109 { 
00110     return d_data->minValue; 
00111 }
00112 
00114 void QwtThermo::setValue(double v)
00115 {
00116     if (d_data->value != v)
00117     {
00118         d_data->value = v;
00119         update();
00120     }
00121 }
00122 
00124 double QwtThermo::value() const 
00125 { 
00126     return d_data->value; 
00127 }
00128 
00129 void QwtThermo::setScaleDraw(QwtScaleDraw *scaleDraw)
00130 {
00131     setAbstractScaleDraw(scaleDraw);
00132 }
00133 
00134 const QwtScaleDraw *QwtThermo::scaleDraw() const
00135 {
00136     return (QwtScaleDraw *)abstractScaleDraw();
00137 }
00138 
00139 QwtScaleDraw *QwtThermo::scaleDraw() 
00140 {
00141     return (QwtScaleDraw *)abstractScaleDraw();
00142 }
00143 
00145 void QwtThermo::paintEvent(QPaintEvent *e)
00146 {
00147     // Use double-buffering
00148     const QRect &ur = e->rect();
00149     if ( ur.isValid() )
00150     {
00151 #if QT_VERSION < 0x040000
00152         QwtPaintBuffer paintBuffer(this, ur);
00153         draw(paintBuffer.painter(), ur);
00154 #else
00155         QPainter painter(this);
00156         draw(&painter, ur);
00157 #endif
00158     }
00159 }
00160 
00162 void QwtThermo::draw(QPainter *p, const QRect& ur)
00163 {
00164     if ( !d_data->thermoRect.contains(ur) )
00165     {
00166         if (d_data->scalePos != None)
00167         {
00168 #if QT_VERSION < 0x040000
00169             scaleDraw()->draw(p, colorGroup());
00170 #else
00171             scaleDraw()->draw(p, palette());
00172 #endif
00173         }
00174 
00175         qDrawShadePanel(p,
00176             d_data->thermoRect.x() - d_data->borderWidth,
00177             d_data->thermoRect.y() - d_data->borderWidth,
00178             d_data->thermoRect.width() + 2*d_data->borderWidth,
00179             d_data->thermoRect.height() + 2*d_data->borderWidth,
00180 #if QT_VERSION < 0x040000
00181             colorGroup(), 
00182 #else
00183             palette(), 
00184 #endif
00185             true, d_data->borderWidth,0);
00186     }
00187     drawThermo(p);
00188 }
00189 
00191 void QwtThermo::resizeEvent(QResizeEvent *)
00192 {
00193     layoutThermo( false );
00194 }
00195 
00202 void QwtThermo::layoutThermo( bool update_geometry )
00203 {
00204     QRect r = rect();
00205     int mbd = 0;
00206     if ( d_data->scalePos != None )
00207     {
00208         int d1, d2;
00209         scaleDraw()->getBorderDistHint(font(), d1, d2);
00210         mbd = qwtMax(d1, d2);
00211     }
00212 
00213     if ( d_data->orientation == Qt::Horizontal )
00214     {
00215         switch ( d_data->scalePos )
00216         {
00217             case Top:
00218             {
00219                 d_data->thermoRect.setRect(
00220                     r.x() + mbd + d_data->borderWidth,
00221                     r.y() + r.height()
00222                     - d_data->thermoWidth - 2*d_data->borderWidth,
00223                     r.width() - 2*(d_data->borderWidth + mbd),
00224                     d_data->thermoWidth);
00225                 scaleDraw()->setAlignment(QwtScaleDraw::TopScale);
00226                 scaleDraw()->move( d_data->thermoRect.x(),
00227                     d_data->thermoRect.y() - d_data->borderWidth 
00228                         - d_data->scaleDist);
00229                 scaleDraw()->setLength(d_data->thermoRect.width());
00230                 break;
00231             }
00232 
00233             case Bottom:
00234             case None: // like Bottom but without scale
00235             default:   // inconsistent orientation and scale position
00236                        // Mapping between values and pixels requires
00237                        // initialization of the scale geometry
00238             {
00239                 d_data->thermoRect.setRect(
00240                     r.x() + mbd + d_data->borderWidth,
00241                     r.y() + d_data->borderWidth,
00242                     r.width() - 2*(d_data->borderWidth + mbd),
00243                     d_data->thermoWidth);
00244                 scaleDraw()->setAlignment(QwtScaleDraw::BottomScale);
00245                 scaleDraw()->move(
00246                     d_data->thermoRect.x(),
00247                     d_data->thermoRect.y() + d_data->thermoRect.height()
00248                         + d_data->borderWidth + d_data->scaleDist );
00249                 scaleDraw()->setLength(d_data->thermoRect.width());
00250                 break;
00251             }
00252         }
00253         d_data->map.setPaintInterval(d_data->thermoRect.x(),
00254             d_data->thermoRect.x() + d_data->thermoRect.width() - 1);
00255     }
00256     else // Qt::Vertical
00257     {
00258         switch ( d_data->scalePos )
00259         {
00260             case Right:
00261             {
00262                 d_data->thermoRect.setRect(
00263                     r.x() + d_data->borderWidth,
00264                     r.y() + mbd + d_data->borderWidth,
00265                     d_data->thermoWidth,
00266                     r.height() - 2*(d_data->borderWidth + mbd));
00267                 scaleDraw()->setAlignment(QwtScaleDraw::RightScale);
00268                 scaleDraw()->move(
00269                     d_data->thermoRect.x() + d_data->thermoRect.width()
00270                         + d_data->borderWidth + d_data->scaleDist,
00271                     d_data->thermoRect.y());
00272                 scaleDraw()->setLength(d_data->thermoRect.height());
00273                 break;
00274             }
00275 
00276             case Left:
00277             case None: // like Left but without scale
00278             default:   // inconsistent orientation and scale position
00279                        // Mapping between values and pixels requires
00280                        // initialization of the scale geometry
00281             {
00282                 d_data->thermoRect.setRect(
00283                     r.x() + r.width() - 2*d_data->borderWidth - d_data->thermoWidth,
00284                     r.y() + mbd + d_data->borderWidth,
00285                     d_data->thermoWidth,
00286                     r.height() - 2*(d_data->borderWidth + mbd));
00287                 scaleDraw()->setAlignment(QwtScaleDraw::LeftScale);
00288                 scaleDraw()->move(
00289                     d_data->thermoRect.x() - d_data->scaleDist 
00290                         - d_data->borderWidth,
00291                     d_data->thermoRect.y() );
00292                 scaleDraw()->setLength(d_data->thermoRect.height());
00293                 break;
00294             }
00295         }
00296         d_data->map.setPaintInterval(
00297             d_data->thermoRect.y() + d_data->thermoRect.height() - 1,
00298             d_data->thermoRect.y());
00299     }
00300     if ( update_geometry )
00301     {
00302         updateGeometry();
00303         update();
00304     }
00305 }
00306 
00323 void QwtThermo::setOrientation(Qt::Orientation o, ScalePos s)
00324 {
00325     if ( o == d_data->orientation )
00326         return;
00327 
00328     switch(o)
00329     {
00330         case Qt::Horizontal:
00331         {
00332             d_data->orientation = Qt::Horizontal;
00333             if ((s == None) || (s == Bottom) || (s == Top))
00334                 d_data->scalePos = s;
00335             else
00336                 d_data->scalePos = None;
00337             break;
00338         }
00339         case Qt::Vertical:
00340         {
00341             d_data->orientation = Qt::Vertical;
00342             if ((s == None) || (s == Left) || (s == Right))
00343                 d_data->scalePos = s;
00344             else
00345                 d_data->scalePos = None;
00346             break;
00347         }
00348     }
00349 
00350 #if QT_VERSION >= 0x040000
00351     if ( !testAttribute(Qt::WA_WState_OwnSizePolicy) )
00352 #else
00353     if ( !testWState( WState_OwnSizePolicy ) )
00354 #endif
00355     {
00356         QSizePolicy sp = sizePolicy();
00357         sp.transpose();
00358         setSizePolicy(sp);
00359 
00360 #if QT_VERSION >= 0x040000
00361         setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00362 #else
00363         clearWState( WState_OwnSizePolicy );
00364 #endif
00365     }
00366 
00367     layoutThermo();
00368 }
00369 
00384 void QwtThermo::setScalePosition(ScalePos s)
00385 {
00386     if ((s == Bottom) || (s == Top))
00387         setOrientation(Qt::Horizontal, s);
00388     else if ((s == Left) || (s == Right))
00389         setOrientation(Qt::Vertical, s);
00390     else
00391         setOrientation(d_data->orientation, None);
00392 }
00393 
00395 QwtThermo::ScalePos QwtThermo::scalePosition() const
00396 {
00397     return d_data->scalePos;
00398 }
00399 
00401 void QwtThermo::fontChange(const QFont &f)
00402 {
00403     QWidget::fontChange( f );
00404     layoutThermo();
00405 }
00406 
00408 void QwtThermo::scaleChange()
00409 {
00410     update();
00411     layoutThermo();
00412 }
00413 
00415 void QwtThermo::drawThermo(QPainter *p)
00416 {
00417     int alarm  = 0, taval = 0;
00418 
00419     QRect fRect;
00420     QRect aRect;
00421     QRect bRect;
00422 
00423     int inverted = ( d_data->maxValue < d_data->minValue );
00424 
00425     //
00426     //  Determine if value exceeds alarm threshold.
00427     //  Note: The alarm value is allowed to lie
00428     //        outside the interval (minValue, maxValue).
00429     //
00430     if (d_data->alarmEnabled)
00431     {
00432         if (inverted)
00433         {
00434             alarm = ((d_data->alarmLevel >= d_data->maxValue)
00435                  && (d_data->alarmLevel <= d_data->minValue)
00436                  && (d_data->value >= d_data->alarmLevel));
00437         
00438         }
00439         else
00440         {
00441             alarm = (( d_data->alarmLevel >= d_data->minValue)
00442                  && (d_data->alarmLevel <= d_data->maxValue)
00443                  && (d_data->value >= d_data->alarmLevel));
00444         }
00445     }
00446 
00447     //
00448     //  transform values
00449     //
00450     int tval = transform(d_data->value);
00451 
00452     if (alarm)
00453        taval = transform(d_data->alarmLevel);
00454 
00455     //
00456     //  calculate recangles
00457     //
00458     if ( d_data->orientation == Qt::Horizontal )
00459     {
00460         if (inverted)
00461         {
00462             bRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00463                   tval - d_data->thermoRect.x(),
00464                   d_data->thermoRect.height());
00465         
00466             if (alarm)
00467             {
00468                 aRect.setRect(tval, d_data->thermoRect.y(),
00469                       taval - tval + 1,
00470                       d_data->thermoRect.height());
00471                 fRect.setRect(taval + 1, d_data->thermoRect.y(),
00472                       d_data->thermoRect.x() + d_data->thermoRect.width() - (taval + 1),
00473                       d_data->thermoRect.height());
00474             }
00475             else
00476             {
00477                 fRect.setRect(tval, d_data->thermoRect.y(),
00478                       d_data->thermoRect.x() + d_data->thermoRect.width() - tval,
00479                       d_data->thermoRect.height());
00480             }
00481         }
00482         else
00483         {
00484             bRect.setRect(tval + 1, d_data->thermoRect.y(),
00485                   d_data->thermoRect.width() - (tval + 1 - d_data->thermoRect.x()),
00486                   d_data->thermoRect.height());
00487         
00488             if (alarm)
00489             {
00490                 aRect.setRect(taval, d_data->thermoRect.y(),
00491                       tval - taval + 1,
00492                       d_data->thermoRect.height());
00493                 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00494                       taval - d_data->thermoRect.x(),
00495                       d_data->thermoRect.height());
00496             }
00497             else
00498             {
00499                 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00500                       tval - d_data->thermoRect.x() + 1,
00501                       d_data->thermoRect.height());
00502             }
00503         
00504         }
00505     }
00506     else // Qt::Vertical
00507     {
00508         if (tval < d_data->thermoRect.y())
00509             tval = d_data->thermoRect.y();
00510         else 
00511         {
00512             if (tval > d_data->thermoRect.y() + d_data->thermoRect.height())
00513                 tval = d_data->thermoRect.y() + d_data->thermoRect.height();
00514         }
00515 
00516         if (inverted)
00517         {
00518             bRect.setRect(d_data->thermoRect.x(), tval + 1,
00519             d_data->thermoRect.width(),
00520             d_data->thermoRect.height() - (tval + 1 - d_data->thermoRect.y()));
00521 
00522             if (alarm)
00523             {
00524                 aRect.setRect(d_data->thermoRect.x(), taval,
00525                     d_data->thermoRect.width(),
00526                     tval - taval + 1);
00527                 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00528                     d_data->thermoRect.width(),
00529                 taval - d_data->thermoRect.y());
00530             }
00531             else
00532             {
00533                 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00534                     d_data->thermoRect.width(),
00535                     tval - d_data->thermoRect.y() + 1);
00536             }
00537         }
00538         else
00539         {
00540             bRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00541             d_data->thermoRect.width(),
00542             tval - d_data->thermoRect.y());
00543             if (alarm)
00544             {
00545                 aRect.setRect(d_data->thermoRect.x(),tval,
00546                     d_data->thermoRect.width(),
00547                     taval - tval + 1);
00548                 fRect.setRect(d_data->thermoRect.x(),taval + 1,
00549                     d_data->thermoRect.width(),
00550                     d_data->thermoRect.y() + d_data->thermoRect.height() - (taval + 1));
00551             }
00552             else
00553             {
00554                 fRect.setRect(d_data->thermoRect.x(),tval,
00555                     d_data->thermoRect.width(),
00556                 d_data->thermoRect.y() + d_data->thermoRect.height() - tval);
00557             }
00558         }
00559     }
00560 
00561     //
00562     // paint thermometer
00563     //
00564     const QColor bgColor =
00565 #if QT_VERSION < 0x040000
00566         colorGroup().color(QColorGroup::Background);
00567 #else
00568         palette().color(QPalette::Background);
00569 #endif
00570     p->fillRect(bRect, bgColor);
00571 
00572     if (alarm)
00573        p->fillRect(aRect, d_data->alarmBrush);
00574 
00575     p->fillRect(fRect, d_data->fillBrush);
00576 }
00577 
00579 void QwtThermo::setBorderWidth(int w)
00580 {
00581     if ((w >= 0) && (w < (qwtMin(d_data->thermoRect.width(), 
00582         d_data->thermoRect.height()) + d_data->borderWidth) / 2  - 1))
00583     {
00584         d_data->borderWidth = w;
00585         layoutThermo();
00586     }
00587 }
00588 
00590 int QwtThermo::borderWidth() const
00591 {
00592     return d_data->borderWidth;
00593 }
00594 
00601 void QwtThermo::setRange(double vmin, double vmax, bool logarithmic)
00602 {
00603     d_data->minValue = vmin;
00604     d_data->maxValue = vmax;
00605 
00606     if ( logarithmic )
00607         setScaleEngine(new QwtLog10ScaleEngine);
00608     else
00609         setScaleEngine(new QwtLinearScaleEngine);
00610 
00611     /*
00612       There are two different maps, one for the scale, the other
00613       for the values. This is confusing and will be changed
00614       in the future. TODO ...
00615      */
00616 
00617     d_data->map.setTransformation(scaleEngine()->transformation());
00618     d_data->map.setScaleInterval(d_data->minValue, d_data->maxValue);
00619 
00620     if (autoScale())
00621         rescale(d_data->minValue, d_data->maxValue);
00622 
00623     layoutThermo();
00624 }
00625 
00630 void QwtThermo::setFillBrush(const QBrush& brush)
00631 {
00632     d_data->fillBrush = brush;
00633     update();
00634 }
00635 
00637 const QBrush& QwtThermo::fillBrush() const
00638 {
00639     return d_data->fillBrush;
00640 }
00641 
00646 void QwtThermo::setFillColor(const QColor &c)
00647 {
00648     d_data->fillBrush.setColor(c);
00649     update();
00650 }
00651 
00653 const QColor &QwtThermo::fillColor() const
00654 {
00655     return d_data->fillBrush.color();
00656 }
00657 
00662 void QwtThermo::setAlarmBrush(const QBrush& brush)
00663 {
00664     d_data->alarmBrush = brush;
00665     update();
00666 }
00667 
00669 const QBrush& QwtThermo::alarmBrush() const
00670 {
00671     return d_data->alarmBrush;
00672 }
00673 
00678 void QwtThermo::setAlarmColor(const QColor &c)
00679 {
00680     d_data->alarmBrush.setColor(c);
00681     update();
00682 }
00683 
00685 const QColor &QwtThermo::alarmColor() const
00686 {
00687     return d_data->alarmBrush.color();
00688 }
00689 
00691 void QwtThermo::setAlarmLevel(double v)
00692 {
00693     d_data->alarmLevel = v;
00694     d_data->alarmEnabled = 1;
00695     update();
00696 }
00697 
00699 double QwtThermo::alarmLevel() const
00700 {
00701     return d_data->alarmLevel;
00702 }
00703 
00705 void QwtThermo::setPipeWidth(int w)
00706 {
00707     if (w > 0)
00708     {
00709         d_data->thermoWidth = w;
00710         layoutThermo();
00711     }
00712 }
00713 
00715 int QwtThermo::pipeWidth() const
00716 {
00717     return d_data->thermoWidth;
00718 }
00719 
00720 
00735 void QwtThermo::setMargin(int)
00736 {
00737 }
00738 
00739 
00744 void QwtThermo::setAlarmEnabled(bool tf)
00745 {
00746     d_data->alarmEnabled = tf;
00747     update();
00748 }
00749 
00751 bool QwtThermo::alarmEnabled() const
00752 {
00753     return d_data->alarmEnabled;
00754 }
00755 
00760 QSize QwtThermo::sizeHint() const
00761 {
00762     return minimumSizeHint();
00763 }
00764 
00770 QSize QwtThermo::minimumSizeHint() const
00771 {
00772     int w = 0, h = 0;
00773 
00774     if ( d_data->scalePos != None )
00775     {
00776         const int sdExtent = scaleDraw()->extent( QPen(), font() );
00777         const int sdLength = scaleDraw()->minLength( QPen(), font() );
00778 
00779         w = sdLength;
00780         h = d_data->thermoWidth + sdExtent + 
00781             d_data->borderWidth + d_data->scaleDist;
00782 
00783     }
00784     else // no scale
00785     {
00786         w = 200;
00787         h = d_data->thermoWidth;
00788     }
00789 
00790     if ( d_data->orientation == Qt::Vertical )
00791         qSwap(w, h);
00792 
00793     w += 2 * d_data->borderWidth;
00794     h += 2 * d_data->borderWidth;
00795 
00796     return QSize( w, h );
00797 }
00798 
00799 int QwtThermo::transform(double value) const
00800 {
00801     const double min = qwtMin(d_data->map.s1(), d_data->map.s2());
00802     const double max = qwtMax(d_data->map.s1(), d_data->map.s2());
00803 
00804     if ( value > max )
00805         value = max;
00806     if ( value < min )
00807         value = min;
00808 
00809     return d_data->map.transform(value);
00810 }

Generated on Mon Jan 30 22:16:26 2006 for Qwt User's Guide by  doxygen 1.4.4