Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
HistogramItem.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 
51 #ifdef WITH_QWT
52 
53 #include <qwt_plot.h>
54 
55 #if QWT_VERSION < 0x060000
56 #include <qstring.h>
57 #include <qpainter.h>
58 
59 #include <qwt_interval_data.h>
60 #include <qwt_painter.h>
61 #include <qwt_scale_map.h>
62 #include "HistogramItem.hh"
63 
64 class HistogramItem::PrivateData
65 {
66 public:
67  int attributes;
68  QwtIntervalData data;
69  std::vector< QColor > colors_;
70  double reference;
71 };
72 
73 HistogramItem::HistogramItem(const QwtText &title):
74  QwtPlotItem(title)
75 {
76  init();
77 }
78 
79 HistogramItem::HistogramItem(const QString &title):
80  QwtPlotItem(QwtText(title))
81 {
82  init();
83 }
84 
86 {
87  delete d_data;
88 }
89 
90 void HistogramItem::init()
91 {
92  d_data = new PrivateData();
93  d_data->reference = 0.0;
94  d_data->attributes = HistogramItem::Auto;
95 
96  setItemAttribute(QwtPlotItem::AutoScale, true);
97  setItemAttribute(QwtPlotItem::Legend, true);
98 
99  setZ(20.0);
100 }
101 
102 void HistogramItem::setBaseline(double reference)
103 {
104  if ( d_data->reference != reference )
105  {
106  d_data->reference = reference;
107  itemChanged();
108  }
109 }
110 
111 double HistogramItem::baseline() const
112 {
113  return d_data->reference;
114 }
115 
116 void HistogramItem::setData(const QwtIntervalData &data)
117 {
118  d_data->data = data;
119  itemChanged();
120 }
121 
122 const QwtIntervalData &HistogramItem::data() const
123 {
124  return d_data->data;
125 }
126 
127 void HistogramItem::setColors( std::vector< QColor >& _colors)
128 {
129  d_data->colors_ = _colors;
130  itemChanged();
131 }
132 
133 QColor HistogramItem::color(uint i) const
134 {
135  if ( i < d_data->colors_.size() )
136  return d_data->colors_[i];
137  else
138  return Qt::darkBlue;
139 }
140 
141 QwtDoubleRect HistogramItem::boundingRect() const
142 {
143  QwtDoubleRect rect = d_data->data.boundingRect();
144  if ( !rect.isValid() )
145  return rect;
146 
147  if ( d_data->attributes & Xfy )
148  {
149  rect = QwtDoubleRect( rect.y(), rect.x(), rect.height(), rect.width() );
150 
151  if ( rect.left() > d_data->reference )
152  rect.setLeft( d_data->reference );
153  else if ( rect.right() < d_data->reference )
154  rect.setRight( d_data->reference );
155  }
156  else
157  {
158  if ( rect.bottom() < d_data->reference )
159  rect.setBottom( d_data->reference );
160  else if ( rect.top() > d_data->reference )
161  rect.setTop( d_data->reference );
162  }
163 
164  return rect;
165 }
166 
167 
168 int HistogramItem::rtti() const
169 {
170  return QwtPlotItem::Rtti_PlotHistogram;
171 }
172 
173 void HistogramItem::setHistogramAttribute(HistogramAttribute attribute, bool on)
174 {
175  if ( bool(d_data->attributes & attribute) == on )
176  return;
177 
178  if ( on )
179  d_data->attributes |= attribute;
180  else
181  d_data->attributes &= ~attribute;
182 
183  itemChanged();
184 }
185 
186 bool HistogramItem::testHistogramAttribute(HistogramAttribute attribute) const
187 {
188  return d_data->attributes & attribute;
189 }
190 
191 void HistogramItem::draw(QPainter *painter, const QwtScaleMap &xMap,
192  const QwtScaleMap &yMap, const QRect &) const
193 {
194  const QwtIntervalData &iData = d_data->data;
195 
196  const int x0 = xMap.transform(baseline());
197  const int y0 = yMap.transform(baseline());
198 
199  for ( int i = 0; i < (int)iData.size(); i++ )
200  {
201  if ( d_data->attributes & HistogramItem::Xfy )
202  {
203  const int x2 = xMap.transform(iData.value(i));
204  if ( x2 == x0 )
205  continue;
206 
207  int y1 = yMap.transform( iData.interval(i).minValue());
208  int y2 = yMap.transform( iData.interval(i).maxValue());
209  if ( y1 > y2 )
210  qSwap(y1, y2);
211 
212  if ( i < (int)iData.size() - 2 )
213  {
214  const int yy1 = yMap.transform(iData.interval(i+1).minValue());
215  const int yy2 = yMap.transform(iData.interval(i+1).maxValue());
216 
217  if ( y2 == qwtMin(yy1, yy2) )
218  {
219  const int xx2 = xMap.transform(
220  iData.interval(i+1).minValue());
221  if ( xx2 != x0 && ( (xx2 < x0 && x2 < x0) ||
222  (xx2 > x0 && x2 > x0) ) )
223  {
224  // One pixel distance between neighboured bars
225  y2++;
226  }
227  }
228  }
229 
230  painter->setPen( QPen( color(i) ) );
231 
232  drawBar(painter, Qt::Horizontal,
233  QRect(x0, y1, x2 - x0, y2 - y1));
234  }
235  else
236  {
237  const int y2 = yMap.transform(iData.value(i));
238  if ( y2 == y0 )
239  continue;
240 
241  int x1 = xMap.transform(iData.interval(i).minValue());
242  int x2 = xMap.transform(iData.interval(i).maxValue());
243  if ( x1 > x2 )
244  qSwap(x1, x2);
245 
246  if ( i < (int)iData.size() - 2 )
247  {
248  const int xx1 = xMap.transform(iData.interval(i+1).minValue());
249  const int xx2 = xMap.transform(iData.interval(i+1).maxValue());
250 
251  if ( x2 == qwtMin(xx1, xx2) )
252  {
253  const int yy2 = yMap.transform(iData.value(i+1));
254  if ( yy2 != y0 && ( (yy2 < y0 && y2 < y0) || (yy2 > y0 && y2 > y0) ) )
255  {
256  // One pixel distance between neighboured bars
257  x2--;
258  }
259  }
260  }
261 
262  painter->setPen( QPen( color(i) ) );
263 
264  drawBar(painter, Qt::Vertical,
265  QRect(x1, y0, x2 - x1, y2 - y0) );
266  }
267  }
268 }
269 
270 void HistogramItem::drawBar(QPainter *painter,
271  Qt::Orientation, const QRect& rect) const
272 {
273  painter->save();
274 
275  const QColor color(painter->pen().color());
276  const QRect r = rect.normalized();
277 
278 
279  const int factor = 125;
280  const QColor light(color.light(factor));
281  const QColor dark(color.dark(factor));
282 
283  painter->setBrush(color);
284  painter->setPen(Qt::NoPen);
285  QwtPainter::drawRect(painter, r.x() + 1, r.y() + 1,
286  r.width() - 2, r.height() - 2);
287  painter->setBrush(Qt::NoBrush);
288 
289  painter->setPen(QPen(light, 2));
290 
291  QwtPainter::drawLine(painter,
292  r.left() + 1, r.top() + 2, r.right() + 1, r.top() + 2);
293 
294  painter->setPen(QPen(dark, 2));
295 
296  QwtPainter::drawLine(painter,
297  r.left() + 1, r.bottom(), r.right() + 1, r.bottom());
298 
299  painter->setPen(QPen(light, 1));
300 
301  QwtPainter::drawLine(painter,
302  r.left(), r.top() + 1, r.left(), r.bottom());
303  QwtPainter::drawLine(painter,
304  r.left() + 1, r.top() + 2, r.left() + 1, r.bottom() - 1);
305 
306 
307  painter->setPen(QPen(dark, 1));
308 
309  QwtPainter::drawLine(painter,
310  r.right() + 1, r.top() + 1, r.right() + 1, r.bottom());
311  QwtPainter::drawLine(painter,
312  r.right(), r.top() + 2, r.right(), r.bottom() - 1);
313 
314  painter->restore();
315 }
316 
317 #endif // QWT 5
318 
319 #endif // WITH_QWT
HistogramItem(const QString &title=QString::null)
Constructor.
virtual ~HistogramItem()
Destructor.
void setColors(std::vector< QColor > &_colors)
Set colors.
virtual QwtDoubleRect boundingRect() const
Function hat will return the datas bounding rectangle (for rendering)
void setData(const QwtIntervalData &data)
set data to render
virtual void draw(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRect &) const
The actual draw function, drawing the bars inside the plot widget.
virtual void drawBar(QPainter *, Qt::Orientation o, const QRect &) const
Draws a single bar.