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
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
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 }