src/qvgui/qvhistogram.cpp

00001 #include <qstring.h>
00002 #include <qpainter.h>
00003 #include <qwt_plot.h>
00004 #include <qwt_interval_data.h>
00005 #include <qwt_painter.h>
00006 #include <qwt_scale_map.h>
00007 #include <qvgui/qvhistogram.h>
00008 
00009 #ifndef DOXYGEN_IGNORE_THIS
00010 class QVHistogram::PrivateData
00011 {
00012 public:
00013     int attributes;
00014     QwtIntervalData data;
00015     QColor color;
00016     double reference;
00017 };
00018 #endif
00019 
00020 QVHistogram::QVHistogram(const QwtText &title):
00021     QwtPlotItem(title)
00022 {
00023     init();
00024 }
00025 
00026 QVHistogram::QVHistogram(const QString &title):
00027     QwtPlotItem(QwtText(title))
00028 {
00029     init();
00030 }
00031 
00032 QVHistogram::~QVHistogram()
00033 {
00034     delete d_data;
00035 }
00036 
00037 void QVHistogram::init()
00038 {
00039     d_data = new PrivateData();
00040     d_data->reference = 0.0;
00041     d_data->attributes = QVHistogram::Auto;
00042 
00043     setItemAttribute(QwtPlotItem::AutoScale, true);
00044     setItemAttribute(QwtPlotItem::Legend, true);
00045 
00046     setZ(20.0);
00047 }
00048 
00049 void QVHistogram::setBaseline(double reference)
00050 {
00051     if ( d_data->reference != reference )
00052     {
00053         d_data->reference = reference;
00054         itemChanged();
00055     }
00056 }
00057 
00058 double QVHistogram::baseline() const
00059 {
00060     return d_data->reference;
00061 }
00062 
00063 void QVHistogram::setData(const QwtIntervalData &data)
00064 {
00065     d_data->data = data;
00066     itemChanged();
00067 }
00068 
00069 const QwtIntervalData &QVHistogram::data() const
00070 {
00071     return d_data->data;
00072 }
00073 
00074 void QVHistogram::setColor(const QColor &color)
00075 {
00076     if ( d_data->color != color )
00077     {
00078         d_data->color = color;
00079         itemChanged();
00080     }
00081 }
00082 
00083 QColor QVHistogram::color() const
00084 {
00085     return d_data->color;
00086 }
00087 
00088 QwtDoubleRect QVHistogram::boundingRect() const
00089 {
00090     QwtDoubleRect rect = d_data->data.boundingRect();
00091     if ( !rect.isValid() ) 
00092         return rect;
00093 
00094     if ( d_data->attributes & Xfy ) 
00095     {
00096         rect = QwtDoubleRect( rect.y(), rect.x(), 
00097             rect.height(), rect.width() );
00098 
00099         if ( rect.left() > d_data->reference ) 
00100             rect.setLeft( d_data->reference );
00101         else if ( rect.right() < d_data->reference ) 
00102             rect.setRight( d_data->reference );
00103     } 
00104     else 
00105     {
00106         if ( rect.bottom() < d_data->reference ) 
00107             rect.setBottom( d_data->reference );
00108         else if ( rect.top() > d_data->reference ) 
00109             rect.setTop( d_data->reference );
00110     }
00111 
00112     return rect;
00113 }
00114 
00115 
00116 int QVHistogram::rtti() const
00117 {
00118     return QwtPlotItem::Rtti_PlotHistogram;
00119 }
00120 
00121 void QVHistogram::setHistogramAttribute(HistogramAttribute attribute, bool on)
00122 {
00123     if ( bool(d_data->attributes & attribute) == on )
00124         return;
00125 
00126     if ( on )
00127         d_data->attributes |= attribute;
00128     else
00129         d_data->attributes &= ~attribute;
00130 
00131     itemChanged();
00132 }
00133 
00134 bool QVHistogram::testHistogramAttribute(HistogramAttribute attribute) const
00135 {
00136     return d_data->attributes & attribute;
00137 }
00138 
00139 void QVHistogram::draw(QPainter *painter, const QwtScaleMap &xMap, 
00140     const QwtScaleMap &yMap, const QRect &) const
00141 {
00142     const QwtIntervalData &iData = d_data->data;
00143 
00144     painter->setPen(QPen(d_data->color));
00145 
00146     const int x0 = xMap.transform(baseline());
00147     const int y0 = yMap.transform(baseline());
00148 
00149     for ( int i = 0; i < (int)iData.size(); i++ )
00150     {
00151         if ( d_data->attributes & QVHistogram::Xfy )
00152         {
00153             const int x2 = xMap.transform(iData.value(i));
00154             if ( x2 == x0 )
00155                 continue;
00156 
00157             int y1 = yMap.transform( iData.interval(i).minValue());
00158             int y2 = yMap.transform( iData.interval(i).maxValue());
00159             if ( y1 > y2 )
00160                 qSwap(y1, y2);
00161 
00162             if ( i < (int)iData.size() - 2 )
00163             {
00164                 const int yy1 = yMap.transform(iData.interval(i+1).minValue());
00165                 const int yy2 = yMap.transform(iData.interval(i+1).maxValue());
00166 
00167                 if ( y2 == qwtMin(yy1, yy2) )
00168                 {
00169                     const int xx2 = xMap.transform(
00170                         iData.interval(i+1).minValue());
00171                     if ( xx2 != x0 && ( (xx2 < x0 && x2 < x0) ||
00172                                           (xx2 > x0 && x2 > x0) ) )
00173                     {
00174                        // One pixel distance between neighboured bars
00175                        y2++;
00176                     }
00177                 }
00178             }
00179 
00180             drawBar(painter, Qt::Horizontal,
00181                 QRect(x0, y1, x2 - x0, y2 - y1));
00182         }
00183         else
00184         {
00185             const int y2 = yMap.transform(iData.value(i));
00186             if ( y2 == y0 )
00187                 continue;
00188 
00189             int x1 = xMap.transform(iData.interval(i).minValue());
00190             int x2 = xMap.transform(iData.interval(i).maxValue());
00191             if ( x1 > x2 )
00192                 qSwap(x1, x2);
00193 
00194             if ( i < (int)iData.size() - 2 )
00195             {
00196                 const int xx1 = xMap.transform(iData.interval(i+1).minValue());
00197                 const int xx2 = xMap.transform(iData.interval(i+1).maxValue());
00198 
00199                 if ( x2 == qwtMin(xx1, xx2) )
00200                 {
00201                     const int yy2 = yMap.transform(iData.value(i+1));
00202                     if ( yy2 != y0 && ( (yy2 < y0 && y2 < y0) ||
00203                                     (yy2 > y0 && y2 > y0) ) )
00204                     {
00205                         // One pixel distance between neighboured bars
00206                         x2--;
00207                     }
00208                 }
00209             }
00210             drawBar(painter, Qt::Vertical,
00211                 QRect(x1, y0, x2 - x1, y2 - y0) );
00212         }
00213     }
00214 }
00215 
00216 void QVHistogram::drawBar(QPainter *painter,
00217    Qt::Orientation, const QRect& rect) const
00218 {
00219    painter->save();
00220 
00221    const QColor color(painter->pen().color());
00222 #if QT_VERSION >= 0x040000
00223    const QRect r = rect.normalized();
00224 #else
00225    const QRect r = rect.normalize();
00226 #endif
00227 
00228    const int factor = 125;
00229    const QColor light(color.light(factor));
00230    const QColor dark(color.dark(factor));
00231 
00232    painter->setBrush(color);
00233    painter->setPen(Qt::NoPen);
00234    QwtPainter::drawRect(painter, r.x() + 1, r.y() + 1,
00235       r.width() - 2, r.height() - 2);
00236    painter->setBrush(Qt::NoBrush);
00237 
00238    painter->setPen(QPen(light, 2));
00239 #if QT_VERSION >= 0x040000
00240    QwtPainter::drawLine(painter,
00241       r.left() + 1, r.top() + 2, r.right() + 1, r.top() + 2);
00242 #else
00243    QwtPainter::drawLine(painter,
00244       r.left(), r.top() + 2, r.right() + 1, r.top() + 2);
00245 #endif
00246 
00247    painter->setPen(QPen(dark, 2));
00248 #if QT_VERSION >= 0x040000
00249    QwtPainter::drawLine(painter, 
00250       r.left() + 1, r.bottom(), r.right() + 1, r.bottom());
00251 #else
00252    QwtPainter::drawLine(painter, 
00253       r.left(), r.bottom(), r.right() + 1, r.bottom());
00254 #endif
00255 
00256    painter->setPen(QPen(light, 1));
00257 
00258 #if QT_VERSION >= 0x040000
00259    QwtPainter::drawLine(painter, 
00260       r.left(), r.top() + 1, r.left(), r.bottom());
00261    QwtPainter::drawLine(painter,
00262       r.left() + 1, r.top() + 2, r.left() + 1, r.bottom() - 1);
00263 #else
00264    QwtPainter::drawLine(painter, 
00265       r.left(), r.top() + 1, r.left(), r.bottom() + 1);
00266    QwtPainter::drawLine(painter,
00267       r.left() + 1, r.top() + 2, r.left() + 1, r.bottom());
00268 #endif
00269 
00270    painter->setPen(QPen(dark, 1));
00271 
00272 #if QT_VERSION >= 0x040000
00273    QwtPainter::drawLine(painter, 
00274       r.right() + 1, r.top() + 1, r.right() + 1, r.bottom());
00275    QwtPainter::drawLine(painter, 
00276       r.right(), r.top() + 2, r.right(), r.bottom() - 1);
00277 #else
00278    QwtPainter::drawLine(painter, 
00279       r.right() + 1, r.top() + 1, r.right() + 1, r.bottom() + 1);
00280    QwtPainter::drawLine(painter, 
00281       r.right(), r.top() + 2, r.right(), r.bottom());
00282 #endif
00283 
00284    painter->restore();
00285 }

Generated on Thu Jul 17 17:23:28 2008 for QVision by  doxygen 1.5.3