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 
00131 void QwtThermo::paintEvent(QPaintEvent *e)
00132 {
00133     // Use double-buffering
00134     const QRect &ur = e->rect();
00135     if ( ur.isValid() )
00136     {
00137 #if QT_VERSION < 0x040000
00138         QwtPaintBuffer paintBuffer(this, ur);
00139         draw(paintBuffer.painter(), ur);
00140 #else
00141         QPainter painter(this);
00142         draw(&painter, ur);
00143 #endif
00144     }
00145 }
00146 
00148 void QwtThermo::draw(QPainter *p, const QRect& ur)
00149 {
00150     if ( !d_data->thermoRect.contains(ur) )
00151     {
00152         if (d_data->scalePos != None)
00153         {
00154 #if QT_VERSION < 0x040000
00155             scaleDraw()->draw(p, colorGroup());
00156 #else
00157             scaleDraw()->draw(p, palette());
00158 #endif
00159         }
00160 
00161         qDrawShadePanel(p,
00162             d_data->thermoRect.x() - d_data->borderWidth,
00163             d_data->thermoRect.y() - d_data->borderWidth,
00164             d_data->thermoRect.width() + 2*d_data->borderWidth,
00165             d_data->thermoRect.height() + 2*d_data->borderWidth,
00166 #if QT_VERSION < 0x040000
00167             colorGroup(), 
00168 #else
00169             palette(), 
00170 #endif
00171             true, d_data->borderWidth,0);
00172     }
00173     drawThermo(p);
00174 }
00175 
00177 void QwtThermo::resizeEvent(QResizeEvent *)
00178 {
00179     layoutThermo( false );
00180 }
00181 
00188 void QwtThermo::layoutThermo( bool update_geometry )
00189 {
00190     QRect r = rect();
00191     int mbd = 0;
00192     if ( d_data->scalePos != None )
00193     {
00194         int d1, d2;
00195         scaleDraw()->minBorderDist(font(), d1, d2);
00196         mbd = qwtMax(d1, d2);
00197     }
00198 
00199     if ( d_data->orientation == Qt::Horizontal )
00200     {
00201         switch ( d_data->scalePos )
00202         {
00203             case Top:
00204                 d_data->thermoRect.setRect(
00205                     r.x() + mbd + d_data->borderWidth,
00206                     r.y() + r.height()
00207                     - d_data->thermoWidth - 2*d_data->borderWidth,
00208                     r.width() - 2*(d_data->borderWidth + mbd),
00209                     d_data->thermoWidth);
00210                 scaleDraw()->setGeometry(
00211                     d_data->thermoRect.x(),
00212                     d_data->thermoRect.y() - d_data->borderWidth - d_data->scaleDist,
00213                     d_data->thermoRect.width(),
00214                     QwtScaleDraw::Top);
00215                 break;
00216 
00217             case Bottom:
00218             case None: // like Bottom but without scale
00219             default:   // inconsistent orientation and scale position
00220                        // Mapping between values and pixels requires
00221                        // initialization of the scale geometry
00222                 d_data->thermoRect.setRect(
00223                     r.x() + mbd + d_data->borderWidth,
00224                     r.y() + d_data->borderWidth,
00225                     r.width() - 2*(d_data->borderWidth + mbd),
00226                     d_data->thermoWidth);
00227                 scaleDraw()->setGeometry(
00228                     d_data->thermoRect.x(),
00229                     d_data->thermoRect.y() + d_data->thermoRect.height()
00230                     + d_data->borderWidth + d_data->scaleDist,
00231                     d_data->thermoRect.width(),
00232                     QwtScaleDraw::Bottom);
00233                 break;
00234         }
00235         d_data->map.setPaintInterval(d_data->thermoRect.x(),
00236             d_data->thermoRect.x() + d_data->thermoRect.width() - 1);
00237     }
00238     else // Qt::Vertical
00239     {
00240         switch ( d_data->scalePos )
00241         {
00242             case Right:
00243                 d_data->thermoRect.setRect(
00244                     r.x() + d_data->borderWidth,
00245                     r.y() + mbd + d_data->borderWidth,
00246                     d_data->thermoWidth,
00247                     r.height() - 2*(d_data->borderWidth + mbd));
00248                 scaleDraw()->setGeometry(
00249                     d_data->thermoRect.x() + d_data->thermoRect.width()
00250                     + d_data->borderWidth + d_data->scaleDist,
00251                     d_data->thermoRect.y(),
00252                     d_data->thermoRect.height(),
00253                     QwtScaleDraw::Right);
00254                 break;
00255 
00256             case Left:
00257             case None: // like Left but without scale
00258             default:   // inconsistent orientation and scale position
00259                        // Mapping between values and pixels requires
00260                        // initialization of the scale geometry
00261                 d_data->thermoRect.setRect(
00262                     r.x() + r.width() - 2*d_data->borderWidth - d_data->thermoWidth,
00263                     r.y() + mbd + d_data->borderWidth,
00264                     d_data->thermoWidth,
00265                     r.height() - 2*(d_data->borderWidth + mbd));
00266                 scaleDraw()->setGeometry(
00267                     d_data->thermoRect.x() - d_data->scaleDist - d_data->borderWidth,
00268                     d_data->thermoRect.y(),
00269                     d_data->thermoRect.height(),
00270                     QwtScaleDraw::Left);
00271                 break;
00272         }
00273         d_data->map.setPaintInterval(d_data->thermoRect.y() + d_data->thermoRect.height() - 1,
00274             d_data->thermoRect.y());
00275     }
00276     if ( update_geometry )
00277     {
00278         updateGeometry();
00279         update();
00280     }
00281 }
00282 
00299 void QwtThermo::setOrientation(Qt::Orientation o, ScalePos s)
00300 {
00301     if ( o == d_data->orientation )
00302         return;
00303 
00304     switch(o)
00305     {
00306         case Qt::Horizontal:
00307         {
00308             d_data->orientation = Qt::Horizontal;
00309             if ((s == None) || (s == Bottom) || (s == Top))
00310                 d_data->scalePos = s;
00311             else
00312                 d_data->scalePos = None;
00313             break;
00314         }
00315         case Qt::Vertical:
00316         {
00317             d_data->orientation = Qt::Vertical;
00318             if ((s == None) || (s == Left) || (s == Right))
00319                 d_data->scalePos = s;
00320             else
00321                 d_data->scalePos = None;
00322             break;
00323         }
00324     }
00325 
00326 #if QT_VERSION >= 0x040000
00327     if ( !testAttribute(Qt::WA_WState_OwnSizePolicy) )
00328 #else
00329     if ( !testWState( WState_OwnSizePolicy ) )
00330 #endif
00331     {
00332         QSizePolicy sp = sizePolicy();
00333         sp.transpose();
00334         setSizePolicy(sp);
00335 
00336 #if QT_VERSION >= 0x040000
00337         setAttribute(Qt::WA_WState_OwnSizePolicy, false);
00338 #else
00339         clearWState( WState_OwnSizePolicy );
00340 #endif
00341     }
00342 
00343     layoutThermo();
00344 }
00345 
00360 void QwtThermo::setScalePosition(ScalePos s)
00361 {
00362     if ((s == Bottom) || (s == Top))
00363         setOrientation(Qt::Horizontal, s);
00364     else if ((s == Left) || (s == Right))
00365         setOrientation(Qt::Vertical, s);
00366     else
00367         setOrientation(d_data->orientation, None);
00368 }
00369 
00371 QwtThermo::ScalePos QwtThermo::scalePosition() const
00372 {
00373     return d_data->scalePos;
00374 }
00375 
00377 void QwtThermo::fontChange(const QFont &f)
00378 {
00379     QWidget::fontChange( f );
00380     layoutThermo();
00381 }
00382 
00384 void QwtThermo::scaleChange()
00385 {
00386     update();
00387     layoutThermo();
00388 }
00389 
00391 void QwtThermo::drawThermo(QPainter *p)
00392 {
00393     int alarm  = 0, taval = 0;
00394 
00395     QRect fRect;
00396     QRect aRect;
00397     QRect bRect;
00398 
00399     int inverted = ( d_data->maxValue < d_data->minValue );
00400 
00401     //
00402     //  Determine if value exceeds alarm threshold.
00403     //  Note: The alarm value is allowed to lie
00404     //        outside the interval (minValue, maxValue).
00405     //
00406     if (d_data->alarmEnabled)
00407     {
00408         if (inverted)
00409         {
00410             alarm = ((d_data->alarmLevel >= d_data->maxValue)
00411                  && (d_data->alarmLevel <= d_data->minValue)
00412                  && (d_data->value >= d_data->alarmLevel));
00413         
00414         }
00415         else
00416         {
00417             alarm = (( d_data->alarmLevel >= d_data->minValue)
00418                  && (d_data->alarmLevel <= d_data->maxValue)
00419                  && (d_data->value >= d_data->alarmLevel));
00420         }
00421     }
00422 
00423     //
00424     //  transform values
00425     //
00426     int tval = transform(d_data->value);
00427 
00428     if (alarm)
00429        taval = transform(d_data->alarmLevel);
00430 
00431     //
00432     //  calculate recangles
00433     //
00434     if ( d_data->orientation == Qt::Horizontal )
00435     {
00436         if (inverted)
00437         {
00438             bRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00439                   tval - d_data->thermoRect.x(),
00440                   d_data->thermoRect.height());
00441         
00442             if (alarm)
00443             {
00444                 aRect.setRect(tval, d_data->thermoRect.y(),
00445                       taval - tval + 1,
00446                       d_data->thermoRect.height());
00447                 fRect.setRect(taval + 1, d_data->thermoRect.y(),
00448                       d_data->thermoRect.x() + d_data->thermoRect.width() - (taval + 1),
00449                       d_data->thermoRect.height());
00450             }
00451             else
00452             {
00453                 fRect.setRect(tval, d_data->thermoRect.y(),
00454                       d_data->thermoRect.x() + d_data->thermoRect.width() - tval,
00455                       d_data->thermoRect.height());
00456             }
00457         }
00458         else
00459         {
00460             bRect.setRect(tval + 1, d_data->thermoRect.y(),
00461                   d_data->thermoRect.width() - (tval + 1 - d_data->thermoRect.x()),
00462                   d_data->thermoRect.height());
00463         
00464             if (alarm)
00465             {
00466                 aRect.setRect(taval, d_data->thermoRect.y(),
00467                       tval - taval + 1,
00468                       d_data->thermoRect.height());
00469                 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00470                       taval - d_data->thermoRect.x(),
00471                       d_data->thermoRect.height());
00472             }
00473             else
00474             {
00475                 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00476                       tval - d_data->thermoRect.x() + 1,
00477                       d_data->thermoRect.height());
00478             }
00479         
00480         }
00481     }
00482     else // Qt::Vertical
00483     {
00484         if (tval < d_data->thermoRect.y())
00485             tval = d_data->thermoRect.y();
00486         else 
00487         {
00488             if (tval > d_data->thermoRect.y() + d_data->thermoRect.height())
00489                 tval = d_data->thermoRect.y() + d_data->thermoRect.height();
00490         }
00491 
00492         if (inverted)
00493         {
00494             bRect.setRect(d_data->thermoRect.x(), tval + 1,
00495             d_data->thermoRect.width(),
00496             d_data->thermoRect.height() - (tval + 1 - d_data->thermoRect.y()));
00497 
00498             if (alarm)
00499             {
00500                 aRect.setRect(d_data->thermoRect.x(), taval,
00501                     d_data->thermoRect.width(),
00502                     tval - taval + 1);
00503                 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00504                     d_data->thermoRect.width(),
00505                 taval - d_data->thermoRect.y());
00506             }
00507             else
00508             {
00509                 fRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00510                     d_data->thermoRect.width(),
00511                     tval - d_data->thermoRect.y() + 1);
00512             }
00513         }
00514         else
00515         {
00516             bRect.setRect(d_data->thermoRect.x(), d_data->thermoRect.y(),
00517             d_data->thermoRect.width(),
00518             tval - d_data->thermoRect.y());
00519             if (alarm)
00520             {
00521                 aRect.setRect(d_data->thermoRect.x(),tval,
00522                     d_data->thermoRect.width(),
00523                     taval - tval + 1);
00524                 fRect.setRect(d_data->thermoRect.x(),taval + 1,
00525                     d_data->thermoRect.width(),
00526                     d_data->thermoRect.y() + d_data->thermoRect.height() - (taval + 1));
00527             }
00528             else
00529             {
00530                 fRect.setRect(d_data->thermoRect.x(),tval,
00531                     d_data->thermoRect.width(),
00532                 d_data->thermoRect.y() + d_data->thermoRect.height() - tval);
00533             }
00534         }
00535     }
00536 
00537     //
00538     // paint thermometer
00539     //
00540     const QColor bgColor =
00541 #if QT_VERSION < 0x040000
00542         colorGroup().color(QColorGroup::Background);
00543 #else
00544         palette().color(QPalette::Background);
00545 #endif
00546     p->fillRect(bRect, bgColor);
00547 
00548     if (alarm)
00549        p->fillRect(aRect, d_data->alarmBrush);
00550 
00551     p->fillRect(fRect, d_data->fillBrush);
00552 }
00553 
00555 void QwtThermo::setBorderWidth(int w)
00556 {
00557     if ((w >= 0) && (w < (qwtMin(d_data->thermoRect.width(), 
00558         d_data->thermoRect.height()) + d_data->borderWidth) / 2  - 1))
00559     {
00560         d_data->borderWidth = w;
00561         layoutThermo();
00562     }
00563 }
00564 
00566 int QwtThermo::borderWidth() const
00567 {
00568     return d_data->borderWidth;
00569 }
00570 
00577 void QwtThermo::setRange(double vmin, double vmax, bool logarithmic)
00578 {
00579     d_data->minValue = vmin;
00580     d_data->maxValue = vmax;
00581 
00582     if ( logarithmic )
00583         setScaleEngine(new QwtLog10ScaleEngine);
00584     else
00585         setScaleEngine(new QwtLinearScaleEngine);
00586 
00587     /*
00588       There are two different maps, one for the scale, the other
00589       for the values. This is confusing and will be changed
00590       in the future. TODO ...
00591      */
00592 
00593     d_data->map.setTransformation(scaleEngine()->transformation());
00594     d_data->map.setScaleInterval(d_data->minValue, d_data->maxValue);
00595 
00596     if (autoScale())
00597         rescale(d_data->minValue, d_data->maxValue);
00598 
00599     layoutThermo();
00600 }
00601 
00606 void QwtThermo::setFillBrush(const QBrush& b)
00607 {
00608     d_data->fillBrush = b;
00609     update();
00610 }
00611 
00613 const QBrush& QwtThermo::fillBrush() const
00614 {
00615     return d_data->fillBrush;
00616 }
00617 
00622 void QwtThermo::setFillColor(const QColor &c)
00623 {
00624     d_data->fillBrush.setColor(c);
00625     update();
00626 }
00627 
00629 const QColor &QwtThermo::fillColor() const
00630 {
00631     return d_data->fillBrush.color();
00632 }
00633 
00638 void QwtThermo::setAlarmBrush(const QBrush& b)
00639 {
00640     d_data->alarmBrush = b;
00641     update();
00642 }
00643 
00645 const QBrush& QwtThermo::alarmBrush() const
00646 {
00647     return d_data->alarmBrush;
00648 }
00649 
00654 void QwtThermo::setAlarmColor(const QColor &c)
00655 {
00656     d_data->alarmBrush.setColor(c);
00657     update();
00658 }
00659 
00661 const QColor &QwtThermo::alarmColor() const
00662 {
00663     return d_data->alarmBrush.color();
00664 }
00665 
00667 void QwtThermo::setAlarmLevel(double v)
00668 {
00669     d_data->alarmLevel = v;
00670     d_data->alarmEnabled = 1;
00671     update();
00672 }
00673 
00675 double QwtThermo::alarmLevel() const
00676 {
00677     return d_data->alarmLevel;
00678 }
00679 
00681 void QwtThermo::setPipeWidth(int w)
00682 {
00683     if (w > 0)
00684     {
00685         d_data->thermoWidth = w;
00686         layoutThermo();
00687     }
00688 }
00689 
00691 int QwtThermo::pipeWidth() const
00692 {
00693     return d_data->thermoWidth;
00694 }
00695 
00696 
00711 void QwtThermo::setMargin(int)
00712 {
00713 }
00714 
00715 
00720 void QwtThermo::setAlarmEnabled(bool tf)
00721 {
00722     d_data->alarmEnabled = tf;
00723     update();
00724 }
00725 
00727 bool QwtThermo::alarmEnabled() const
00728 {
00729     return d_data->alarmEnabled;
00730 }
00731 
00736 QSize QwtThermo::sizeHint() const
00737 {
00738     return minimumSizeHint();
00739 }
00740 
00746 QSize QwtThermo::minimumSizeHint() const
00747 {
00748     int w = 0, h = 0;
00749 
00750     if ( d_data->scalePos != None )
00751     {
00752         int smw = scaleDraw()->minWidth( QPen(), font() );
00753         int smh = scaleDraw()->minHeight( QPen(), font() );
00754 
00755         if ( d_data->orientation == Qt::Vertical )
00756         {
00757             w = d_data->thermoWidth + smw + 3 * d_data->borderWidth + d_data->scaleDist;
00758             h = smh + 2 * d_data->borderWidth;
00759         }
00760         else
00761         {
00762             w = smw + 2 * d_data->borderWidth;
00763             h = d_data->thermoWidth + smh + 3 * d_data->borderWidth + d_data->scaleDist;
00764         }
00765 
00766     }
00767     else // no scale
00768     {
00769         if ( d_data->orientation == Qt::Vertical )
00770         {
00771             w = d_data->thermoWidth + 2 * d_data->borderWidth;
00772             h = 200 + 2 * d_data->borderWidth;
00773         }
00774         else
00775         {
00776             w = 200 + 2 * d_data->borderWidth;
00777             h = d_data->thermoWidth + 2 * d_data->borderWidth;
00778         }
00779     }
00780     return QSize( w, h );
00781 }
00782 
00783 int QwtThermo::transform(double value) const
00784 {
00785     const double min = qwtMin(d_data->map.s1(), d_data->map.s2());
00786     const double max = qwtMax(d_data->map.s1(), d_data->map.s2());
00787 
00788     if ( value > max )
00789         value = max;
00790     if ( value < min )
00791         value = min;
00792 
00793     return d_data->map.transform(value);
00794 }

Generated on Wed Aug 31 23:02:30 2005 for Qwt User's Guide by  doxygen 1.4.1