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