]> SALOME platform Git repositories - modules/gui.git/blob - src/Plot2d/Plot2d_PlotItems.cxx
Salome HOME
0022773: [CEA 1314] Plot2d : The titles of the devices no visible after validating...
[modules/gui.git] / src / Plot2d / Plot2d_PlotItems.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : Plot2d_PlotItems.cxx
23 //  Author : Natalia ERMOLAEVA, Open CASCADE S.A.S. (natalia.donis@opencascade.com)
24
25 #include "Plot2d_PlotItems.h"
26 #include "Plot2d_Object.h"
27 #include "Plot2d_ViewFrame.h"
28
29 #include <QPainter>
30 #include <QPalette>
31 #include <QLayout>
32 #include <QLine>
33 #include <QVariant>
34 #include <QStyleOption>
35 #include <QPaintEvent>
36 #include <qwt_plot.h>
37 #include <qwt_painter.h>
38 #include <qwt_scale_map.h>
39 #include <qwt_legend.h>
40 #include <qwt_legend_label.h>
41 #include <qwt_plot_dict.h>
42
43 const int SPACING = 10;
44 const int SYMBOL_SIZE = 13;
45
46 const char* yAxisLeft[] = {
47   "12 12 2 1",
48   "  c None",
49   ". c #000000",
50   "            ",
51   "   .        ",
52   "  ...       ",
53   " . . .      ",
54   "   .        ",
55   "   .        ",
56   "   .    .   ",
57   "   .     .  ",
58   "   ........ ",
59   "         .  ",
60   "        .   ",
61   "            "};
62
63 const char* yAxisRight[] = {
64   "12 12 2 1",
65   "  c None",
66   ". c #000000",
67   "            ",
68   "        .   ",
69   "       ...  ",
70   "      . . . ",
71   "        .   ",
72   "        .   ",
73   "   .    .   ",
74   "  .     .   ",
75   " ........   ",
76   "  .         ",
77   "   .        ",
78   "            "};
79
80 /*!
81   Constructor of Plot2d_QwtLegendLabel
82 */
83 Plot2d_QwtLegendLabel::Plot2d_QwtLegendLabel( QWidget* parent ) :
84   QwtLegendLabel( parent ),
85   myYAxisIdentifierMode( IM_None ),
86   myIsSelected(false),
87   mySymbol( new QwtSymbol() ),
88   mySymbolType(0),
89   myPen( QPen() )
90 {
91   myYAxisLeftIcon = yAxisLeft;
92   myYAxisRightIcon = yAxisRight;
93   int anIconWidth = qMax( myYAxisLeftIcon.width(), myYAxisRightIcon.width() );
94   setSpacing( SPACING );
95
96   mySpacingCollapsed = spacing();
97   mySpacingExpanded = anIconWidth + mySpacingCollapsed;
98 }
99
100 /*!
101   Destructor of Plot2d_QwtLegendLabel
102 */
103 Plot2d_QwtLegendLabel::~Plot2d_QwtLegendLabel()
104 {
105 }
106
107 /*!
108   Set Y axis identifier displaying mode
109 */
110 void Plot2d_QwtLegendLabel::setYAxisIdentifierMode( const int theMode )
111 {
112   myYAxisIdentifierMode = theMode;
113   setSpacing( theMode == IM_None ? mySpacingCollapsed : mySpacingExpanded );
114 }
115
116 /*!
117   Paint the identifier to a given rect.
118   \param painter Painter
119   \param rect Rect where to paint
120 */
121 void Plot2d_QwtLegendLabel::drawIdentifier( QPainter* painter, const QRect& rect )
122 {
123   if ( rect.isEmpty() )
124     return;
125
126   if( myPen.style() != Qt::NoPen ) {
127     painter->save();
128     painter->setPen(myPen);
129     QwtPainter::drawLine( painter, rect.left() - 2, rect.center().y() + mySymbolType * 4,
130                                    rect.right() + 2, rect.center().y() + mySymbolType * 4 );
131     painter->restore();
132   }
133   if ( mySymbol->style() != QwtSymbol::NoSymbol )
134   {
135     QRect symbolRect;
136     symbolRect.setSize( QSize( SYMBOL_SIZE, SYMBOL_SIZE ) );
137     symbolRect.moveCenter( QPoint( rect.center().x(), rect.center().y() - mySymbolType * 4 ) );
138     painter->save();
139     painter->setBrush( mySymbol->brush() );
140     painter->setPen( mySymbol->pen() );
141     mySymbol->drawSymbol( painter, symbolRect );
142     painter->restore();
143   }
144   if( myYAxisIdentifierMode != IM_None ) {
145     QPixmap aPixmap( myYAxisIdentifierMode == IM_Left ? yAxisLeft : yAxisRight );
146     painter->save();
147     painter->drawPixmap( rect.topRight() + QPoint( mySpacingExpanded/2, mySpacingExpanded/2 ), aPixmap );
148     painter->restore();
149   }
150 }
151
152 /*!
153   Update highliting on the item.
154 */
155 void Plot2d_QwtLegendLabel::updateHighlit() {
156   QwtText txt = text();
157   if( isSelected() ) {
158     QColor highlightColor = Plot2d_Object::selectionColor();
159     if( highlightColor != txt.backgroundBrush().color() ) {
160       txt.setBackgroundBrush( highlightColor  );
161       setText(txt);
162     }
163   }
164   else if( this->parent() ) {
165     if(QWidget* parent = qobject_cast<QWidget*>( this->parent()->parent() ) ) {
166       QPalette aPal = parent->palette();
167       if( aPal.color( QPalette::Background) != txt.backgroundBrush().color() ) {
168         txt.setBackgroundBrush( aPal.color( QPalette::Background ) );
169         setText( txt );
170       }
171     }
172   }
173 }
174
175 /*!
176   Sets selected property.
177 */
178 void Plot2d_QwtLegendLabel::setSelected(const bool on) {
179   myIsSelected = on;
180 }
181
182 /*!
183   Gets selected property.
184 */
185 bool Plot2d_QwtLegendLabel::isSelected() const {
186   return myIsSelected;
187 }
188
189
190 /*
191   Draw text of the item.
192 */
193 void  Plot2d_QwtLegendLabel::drawText( QPainter * painter, const QRectF &rect ) {
194   painter->setPen( isSelected() ? Plot2d_Object::highlightedLegendTextColor() :
195                    getColorFromPalette( QPalette::Text) );
196
197   QwtTextLabel::drawText( painter, rect );
198 }
199
200 /*!
201   Sets symbol.
202 */
203 void Plot2d_QwtLegendLabel::setSymbol( const QwtSymbol* theSymbol )
204 {
205   mySymbol = new QwtSymbol( theSymbol->style(), theSymbol->brush(),
206                             theSymbol->pen(), theSymbol->size() );
207 }
208
209 /*!
210   Sets symbol type 0(marker on line) or 1(marker above line).
211 */
212 void Plot2d_QwtLegendLabel::setSymbolType( const int theType )
213 {
214   mySymbolType = theType;
215 }
216
217 /*!
218   Sets pen.
219 */
220 void Plot2d_QwtLegendLabel::setPen (const QPen& thePen )
221 {
222   myPen = thePen;
223 }
224
225 /*!
226   Redefined method paintEvent of QwtLegendLabel
227 */
228 void Plot2d_QwtLegendLabel::paintEvent( QPaintEvent *e )
229 {
230   const QRect cr = contentsRect();
231
232   int ButtonFrame = 6;
233   QPainter painter( this );
234   painter.setClipRegion( e->region() );
235
236   if ( isDown() )
237   {
238     qDrawWinButton( &painter, 0, 0, width(), height(),
239                     palette(), true );
240   }
241
242   painter.save();
243   painter.setClipRect( cr );
244
245   drawContents( &painter );
246
247   QRect iconRect = cr;
248   if ( !icon().isNull() )
249   {
250     if ( itemMode() != QwtLegendData::ReadOnly )
251       iconRect.setX( iconRect.x() + ButtonFrame );
252       iconRect.setSize( QSize( icon().size().width() + spacing() ,
253                                    icon().size().height() + spacing() ) );
254       iconRect.moveCenter( QPoint( iconRect.center().x(), cr.center().y() ) );
255   }
256
257   drawIdentifier( &painter, iconRect );
258
259   painter.restore();
260 }
261
262 /*
263   Get color from the legend pallete by 'role' flag.
264 */
265 QColor Plot2d_QwtLegendLabel::getColorFromPalette(QPalette::ColorRole role) {
266   QWidget* pw = parentWidget();
267   QColor  col = palette().color( role );
268   while( pw ) {
269     if ( qobject_cast<QwtLegend*>( pw ) ) {
270       col = pw->palette().color(role );
271       break;
272     }
273     pw = pw->parentWidget();
274   }
275   return col;
276 }
277 /*
278  * Internal class to store deviation data on the curve.
279  */
280 class Plot2d_QwtPlotCurve::Plot2d_DeviationData {
281 public:
282   Plot2d_DeviationData(const double *min, const double *max,const QList<int>& idx)
283   {
284     foreach(int index,idx) {
285       myMin[index] = min[index];
286       myMax[index] = max[index];
287     }
288   }
289   ~Plot2d_DeviationData(){}
290
291   size_t size() const
292   {
293     return qwtMin(myMin.size(), myMax.size());
294   }
295   bool values(size_t i, double &min, double &max) {
296     if(myMin.contains(i) && myMax.contains(i)) {
297       min = myMin[i];
298       max = myMax[i];
299       return true;
300     }
301     return false;
302   }
303 private:
304   QMap<int,double> myMin;
305   QMap<int,double> myMax;
306 };
307
308
309 /*!
310   Constructor of Plot2d_QwtPlotCurve
311 */
312 Plot2d_QwtPlotCurve::Plot2d_QwtPlotCurve( const QString& title,
313                                           QwtPlot::Axis yAxis /*const int index*/ ) :
314   Plot2d_SelectableItem(),
315   QwtPlotCurve( title ),
316   myYAxis( yAxis ),
317   myYAxisIdentifierEnabled( false ),
318   myDeviationData(0)
319 {
320 }
321
322 /*!
323   Destructor of Plot2d_QwtPlotCurve
324 */
325 Plot2d_QwtPlotCurve::~Plot2d_QwtPlotCurve()
326 {
327   clearDeviationData();
328 }
329
330 /*!
331   Enable / disable Y axis identifier
332 */
333 void Plot2d_QwtPlotCurve::setYAxisIdentifierEnabled( const bool on )
334 {
335   myYAxisIdentifierEnabled = on;
336 }
337
338 /*!
339   Redefined method, which updates legend of the curve
340 */
341 void Plot2d_QwtPlotCurve::updateLegend( const QwtPlotItem* thePlotItem,
342                                         const QList<QwtLegendData>& theLegendData )
343 {
344   if ( !thePlotItem || !thePlotItem->plot() )
345     return;
346
347   if ( !testItemAttribute( QwtPlotItem::Legend ) )
348     return;
349
350   QwtPlotCurve::updateLegend( thePlotItem, theLegendData );
351
352   const QVariant itemInfo = thePlotItem->plot()->itemToInfo( const_cast< QwtPlotItem *>( thePlotItem ) );  
353   if( QwtLegend* legend = dynamic_cast<QwtLegend*>( thePlotItem->plot()->legend() ) ) {
354     if( QWidget* widget = legend->legendWidget( itemInfo ) ) {
355       QwtLegendLabel* label = dynamic_cast<QwtLegendLabel*>( widget );
356       if( Plot2d_QwtLegendLabel* anItem = (Plot2d_QwtLegendLabel*)label ) {
357         int aMode = Plot2d_QwtLegendLabel::IM_None;
358         if( myYAxisIdentifierEnabled )
359           aMode = myYAxis == QwtPlot::yRight ?
360             Plot2d_QwtLegendLabel::IM_Right :
361             Plot2d_QwtLegendLabel::IM_Left;
362         anItem->setYAxisIdentifierMode( aMode );
363         
364         anItem->setSymbol( legendSymbol() );
365         if( Plot2d_Plot2d* plot = dynamic_cast<Plot2d_Plot2d*>( thePlotItem->plot() ) )
366           anItem->setSymbolType( plot->getLegendSymbolType() );
367         anItem->setPen( legendPen() );
368         
369         anItem->setSelected( isSelected() );
370         anItem->updateHighlit();
371         anItem->repaint();
372       }
373     }
374   }
375 }
376
377 /*!
378   Redefined method, which updates and calls QwtPlot::autoRefresh() for the parent plot
379 */
380 void Plot2d_QwtPlotCurve::itemChanged()
381 {
382   if ( plot() )
383     updateLegend( this, legendData() );
384
385   QwtPlotItem::itemChanged();
386 }
387
388 /*!
389   Redefined method, which draw a set of points of a curve.
390 */
391 void Plot2d_QwtPlotCurve::drawSeries( QPainter *painter,
392                                       const QwtScaleMap &xMap,
393                                       const QwtScaleMap &yMap,
394                                       const QRectF &canvasRect,
395                                       int from, int to) const
396 {
397   if (to < 0)
398     to = dataSize() - 1;
399   QwtPlotCurve::drawSeries(painter, xMap, yMap, canvasRect, from, to);
400
401   //draw deviation data
402   if(hasDeviationData()) {
403     painter->save();
404     int lineW = deviationMarkerLineWidth();
405     int tickSz = deviationMarkerTickSize() + qRound(lineW/2);
406     double min, max, xi, yi;
407     int xp, ytop, ybtm, tickl, tickr;
408     QColor c = isSelected() ? Plot2d_Object::selectionColor() : deviationMarkerColor();
409     QPen p = QPen(c, lineW, Qt::SolidLine);
410     painter->setPen(p);
411     for (int i = from; i <= to; i++) {
412       if(!myDeviationData->values(i,min,max)) continue;
413       const QPointF sample = data()->sample( i );
414       xi = sample.x();
415       yi = sample.y();
416       xp = xMap.transform(xi);
417       ytop = yMap.transform(yi + max);
418       ybtm = yMap.transform(yi - min);
419       tickl = xp - tickSz;
420       tickr = xp + tickSz;
421       painter->drawLine(tickl,ytop,tickr,ytop);
422       painter->drawLine(xp,ytop,xp,ybtm);
423       painter->drawLine(tickl,ybtm,tickr,ybtm);
424     }
425           painter->restore();
426   }
427 }
428
429 /*!
430  * Return color of the deviation marker.
431  */
432 QColor Plot2d_QwtPlotCurve::deviationMarkerColor() const {
433   QColor c(0, 0, 127);
434   if(plot()) {
435     QVariant var = plot()->property(PLOT2D_DEVIATION_COLOR);
436     if(var.isValid())
437       c = var.value<QColor>();
438   }
439   return c;
440 }
441 /*!
442  * Return line width of the deviation marker.
443  */
444 int Plot2d_QwtPlotCurve::deviationMarkerLineWidth() const {
445   int lw = 1;
446   if(plot()) {
447     QVariant var = plot()->property(PLOT2D_DEVIATION_LW);
448     if(var.isValid())
449       lw = var.toInt();
450   }
451   return lw;
452 }
453
454 /*!
455  * Return tick size of the deviation marker.
456  */
457 int Plot2d_QwtPlotCurve::deviationMarkerTickSize() const {
458   int ts = 2;
459   if(plot()) {
460     QVariant var = plot()->property(PLOT2D_DEVIATION_TS);
461     if(var.isValid())
462       ts = var.toInt();
463   }
464   return ts;
465 }
466
467 /*!
468  * Sets deviation data for the plot item.
469  */
470 void Plot2d_QwtPlotCurve::setDeviationData(const double* min, const double* max,const QList<int> &idx) {
471   clearDeviationData();
472   myDeviationData = new Plot2d_DeviationData(min,max,idx);
473 }
474
475 /*!
476  * Return true if deviation is assigned to the plot item,
477    false otherwise.
478  */
479 bool Plot2d_QwtPlotCurve::hasDeviationData() const {
480   return myDeviationData != 0;
481 }
482
483 /*!
484  * Remove deviation data from the plot item.
485  */
486 void Plot2d_QwtPlotCurve::clearDeviationData()
487 {
488   if(myDeviationData)
489     delete myDeviationData;
490   myDeviationData = 0;
491 }
492
493
494
495 /*!
496   Constructor.
497 */
498 Plot2d_SelectableItem::Plot2d_SelectableItem():
499   myIsSelected(false),
500   myLegendSymbol( new QwtSymbol() ),
501   myLegendPen( QPen() )
502 {
503 }
504
505 /*!
506   Destructor.
507 */
508 Plot2d_SelectableItem::~Plot2d_SelectableItem()
509 {
510 }
511
512 /*!
513   Sets selected property.
514 */
515 void Plot2d_SelectableItem::setSelected( const bool on) {
516   myIsSelected = on;
517 }
518
519 /*!
520   Return selected property.
521 */
522 bool Plot2d_SelectableItem::isSelected() const {
523   return myIsSelected;
524 }
525
526 /*!
527   Sets legend pen property.
528 */
529 void Plot2d_SelectableItem::setLegendPen( const QPen & p) {
530   myLegendPen = p;
531 }
532
533 /*!
534   Return legend pen property.
535 */
536 QPen Plot2d_SelectableItem::legendPen() const {
537   return myLegendPen;
538 }
539
540 /*!
541   Sets legend symbol property.
542 */
543 void Plot2d_SelectableItem::setLegendSymbol( const QwtSymbol* s ) {
544   myLegendSymbol->setStyle( s->style() );
545   myLegendSymbol->setBrush( s->brush() );
546   myLegendSymbol->setPen( s->pen() );
547   myLegendSymbol->setSize( s->size() );
548 }
549
550 /*!
551   Sets legend symbol property.
552 */
553 QwtSymbol* Plot2d_SelectableItem::legendSymbol() const {
554   return new QwtSymbol( myLegendSymbol->style(), myLegendSymbol->brush(),
555                         myLegendSymbol->pen(), myLegendSymbol->size() );
556 }
557
558 /*!
559   Constructor
560 */
561 Plot2d_HistogramQwtItem::Plot2d_HistogramQwtItem( const QwtText& theTitle )
562 : QwtPlotItem( theTitle )
563 {
564   init();
565 }
566
567 /*!
568   Constructor
569 */
570 Plot2d_HistogramQwtItem::Plot2d_HistogramQwtItem( const QString& theTitle )
571 : QwtPlotItem( QwtText( theTitle ) )
572 {
573   init();
574 }
575
576 /*!
577   Destructor
578 */
579 Plot2d_HistogramQwtItem::~Plot2d_HistogramQwtItem()
580 {
581 }
582
583 /*!
584   Initialization of object
585 */
586 void Plot2d_HistogramQwtItem::init()
587 {
588   myReference = 0.0;
589   myAttributes = Plot2d_HistogramQwtItem::Auto;
590
591   setItemAttribute( QwtPlotItem::AutoScale, true );
592   setItemAttribute( QwtPlotItem::Legend,    true );
593
594   setZ( 20.0 );
595 }
596
597 /*!
598   Sets base line to object
599   @param theRef
600 */
601 void Plot2d_HistogramQwtItem::setBaseline( double theRef )
602 {
603   if ( myReference != theRef ) {
604     myReference = theRef;
605     itemChanged();
606   }
607 }
608
609 /*!
610   Returns base line of object
611 */
612 double Plot2d_HistogramQwtItem::baseline() const
613 {
614   return myReference;
615 }
616
617 /*!
618   Sets data to object
619 */
620 void Plot2d_HistogramQwtItem::setData( const QwtIntervalSeriesData& theData )
621 {
622   myData.setSamples( theData.samples() );
623   itemChanged();
624 }
625
626 /*!
627   Returns data from object
628 */
629 const QwtIntervalSeriesData& Plot2d_HistogramQwtItem::data() const
630 {
631   return myData;
632 }
633
634 /*!
635   Sets color to object
636 */
637 void Plot2d_HistogramQwtItem::setColor( const QColor& theColor )
638 {
639   if ( myColor != theColor ) {
640     myColor = theColor;
641     itemChanged();
642   }
643 }
644
645 /*!
646   Returns color from object
647 */
648 QColor Plot2d_HistogramQwtItem::color() const
649 {
650   return myColor;
651 }
652
653 /*!
654   Returns bounding rect of object
655 */
656 QwtDoubleRect Plot2d_HistogramQwtItem::boundingRect() const
657 {
658   QwtDoubleRect aRect = myData.boundingRect();
659   if ( !aRect.isValid() )
660       return aRect;
661
662   if ( myAttributes & Xfy ) {
663     aRect = QwtDoubleRect( aRect.y(), aRect.x(),
664                            aRect.height(), aRect.width() );
665     if ( aRect.left() > myReference )
666       aRect.setLeft( myReference );
667     else if ( aRect.right() < myReference )
668       aRect.setRight( myReference );
669   }
670   else {
671     if ( aRect.bottom() < myReference )
672       aRect.setBottom( myReference );
673     else if ( aRect.top() > myReference )
674       aRect.setTop( myReference );
675   }
676   return aRect;
677 }
678
679 /*!
680   Returns type of plot object
681 */
682 int Plot2d_HistogramQwtItem::rtti() const
683 {
684   return QwtPlotItem::Rtti_PlotHistogram;
685 }
686
687 /*!
688   Sets histogram attributes
689 */
690 void Plot2d_HistogramQwtItem::setHistogramAttribute( HistogramAttribute theAttr,
691                                                      bool isOn )
692 {
693   if ( testHistogramAttribute( theAttr ) != isOn ) {
694     if ( isOn )
695       myAttributes |= theAttr;
696     else
697       myAttributes &= ~theAttr;
698
699     itemChanged();
700   }
701 }
702
703 /*!
704   Tests histogram attributes
705 */
706 bool Plot2d_HistogramQwtItem::testHistogramAttribute( HistogramAttribute theAttr ) const
707 {
708   return myAttributes & theAttr;
709 }
710
711 /*!
712   Draws histogram object
713 */
714 void Plot2d_HistogramQwtItem::draw( QPainter* thePainter,
715                                     const QwtScaleMap& theXMap,
716                                     const QwtScaleMap& theYMap,
717                                     const QRectF& ) const
718 {
719   thePainter->setPen( QPen( myColor ) );
720
721   const int x0 = theXMap.transform( baseline() );
722   const int y0 = theYMap.transform( baseline() );
723
724   for ( int i = 0; i < (int)myData.size(); i++ ) {
725     if ( myAttributes & Plot2d_HistogramQwtItem::Xfy ) {
726       const int x2 = theXMap.transform( myData.sample(i).value );
727       if ( x2 == x0 )
728         continue;
729       int y1 = theYMap.transform( myData.sample( i ).interval.minValue() );
730       int y2 = theYMap.transform( myData.sample( i ).interval.maxValue() );
731       if ( y1 > y2 )
732         qSwap( y1, y2 );
733
734       if ( i < (int)myData.size() - 2 ) {
735         const int yy1 = theYMap.transform( myData.sample(i+1).interval.minValue() );
736         const int yy2 = theYMap.transform( myData.sample(i+1).interval.maxValue() );
737         if ( y2 == qwtMin( yy1, yy2 ) ) {
738           const int xx2 = theXMap.transform( myData.sample(i+1).interval.minValue() );
739           if ( xx2 != x0 && ( ( xx2 < x0 && x2 < x0 ) ||
740                               ( xx2 > x0 && x2 > x0 ) ) ) {
741             // One pixel distance between neighboured bars
742             y2++;
743           }
744         }
745       }
746       drawBar( thePainter, Qt::Horizontal, QRect( x0, y1, x2 - x0, y2 - y1 ) );
747     }
748     else {
749       const int y2 = theYMap.transform( myData.sample( i ).value );
750       if ( y2 == y0 )
751         continue;
752       int x1 = theXMap.transform( myData.sample( i ).interval.minValue() );
753       int x2 = theXMap.transform( myData.sample( i ).interval.maxValue() );
754       if ( x1 > x2 )
755         qSwap( x1, x2 );
756
757       if ( i < (int)myData.size() - 2 ) {
758         const int xx1 = theXMap.transform( myData.sample(i+1).interval.minValue() );
759         const int xx2 = theXMap.transform( myData.sample(i+1).interval.maxValue() );
760         if ( x2 == qwtMin( xx1, xx2 ) ) {
761           const int yy2 = theYMap.transform( myData.sample(i+1).value );
762           if ( yy2 != y0 && ( ( yy2 < y0 && y2 < y0 ) ||
763                               ( yy2 > y0 && y2 > y0 ) ) ) {
764             // One pixel distance between neighboured bars
765             x2--;
766           }
767         }
768       }
769       drawBar( thePainter, Qt::Vertical, QRect( x1, y0, x2 - x1, y2 - y0 ) );
770     }
771   }
772 }
773
774 /*!
775   Draws single bar of histogram
776 */
777 void Plot2d_HistogramQwtItem::drawBar( QPainter* thePainter,
778                                        Qt::Orientation,
779                                        const QRect& theRect ) const
780 {
781   thePainter->save();
782
783   const QColor color( thePainter->pen().color() );
784   QRect r = theRect.normalized();
785
786   const int factor = 125;
787   const QColor light( color.light( factor ) );
788   const QColor dark( color.dark( factor ) );
789
790   thePainter->setBrush( color );
791   thePainter->setPen( Qt::NoPen );
792   QwtPainter::drawRect( thePainter, r.x() + 1, r.y() + 1,
793                         r.width() - 2, r.height() - 2 );
794   thePainter->setBrush( Qt::NoBrush );
795
796   thePainter->setPen( QPen( light, 2 ) );
797   QwtPainter::drawLine( thePainter, r.left() + 1, r.top() + 2,
798                         r.right() + 1, r.top() + 2 );
799
800   thePainter->setPen( QPen( dark, 2 ) );
801   QwtPainter::drawLine( thePainter, r.left() + 1, r.bottom(),
802                         r.right() + 1, r.bottom() );
803   thePainter->setPen( QPen( light, 1 ) );
804
805   QwtPainter::drawLine( thePainter, r.left(), r.top() + 1,
806                         r.left(), r.bottom() );
807   QwtPainter::drawLine( thePainter, r.left() + 1, r.top() + 2,
808                          r.left() + 1, r.bottom() - 1 );
809   thePainter->setPen( QPen( dark, 1 ) );
810
811   QwtPainter::drawLine( thePainter, r.right() + 1, r.top() + 1,
812                         r.right() + 1, r.bottom() );
813   QwtPainter::drawLine(thePainter, r.right(), r.top() + 2,
814                         r.right(), r.bottom() - 1 );
815   thePainter->restore();
816 }
817
818 /*!
819   Constructor
820 */
821 Plot2d_HistogramItem::Plot2d_HistogramItem( const QwtText& theTitle )
822 : Plot2d_HistogramQwtItem( theTitle ),
823   Plot2d_SelectableItem(),
824   myCrossed( true )
825 {
826 }
827
828 /*!
829   Constructor
830 */
831 Plot2d_HistogramItem::Plot2d_HistogramItem( const QString& theTitle )
832 : Plot2d_HistogramQwtItem( theTitle ),
833   myCrossed( true )
834 {
835 }
836
837 /*!
838   Destructor
839 */
840 Plot2d_HistogramItem::~Plot2d_HistogramItem()
841 {
842 }
843
844 /*!
845   Get histogram bar items
846 */
847 QList<QRect> Plot2d_HistogramItem::getBars() const
848 {
849   return myBarItems;
850 }
851
852 /*!
853   Set to legend item symbol with color of item
854 */
855 void Plot2d_HistogramItem::updateLegend( QwtPlotItem* thePlotItem,
856                                          QList<QwtLegendData>& theLegendData )
857 {
858   if ( !thePlotItem || !thePlotItem->plot() )
859     return;
860
861   Plot2d_HistogramQwtItem::updateLegend( thePlotItem, theLegendData );
862
863   const QVariant itemInfo = thePlotItem->plot()->itemToInfo( const_cast< QwtPlotItem *>( thePlotItem ) );
864   QwtLegend *legend = dynamic_cast<QwtLegend *>( thePlotItem->plot()->legend() );
865   QWidget* widget = legend->legendWidget( itemInfo );
866
867   if ( !widget || !widget->inherits( "QwtLegendItem" ) )
868     return;
869
870   QwtLegendLabel* label = dynamic_cast<QwtLegendLabel*>( widget );
871   if( Plot2d_QwtLegendLabel* anItem = (Plot2d_QwtLegendLabel*)( label ) ) {
872     QFontMetrics aFMetrics( anItem->font() );
873     int aSize = aFMetrics.height();
874     QwtSymbol* aSymbol = new QwtSymbol( QwtSymbol::Rect, QBrush( legendPen().color() ),
875                                         QPen( legendPen().color() ), QSize( aSize, aSize ) );
876     anItem->setSymbol( aSymbol );
877     if( Plot2d_Plot2d* plot = dynamic_cast<Plot2d_Plot2d*>( thePlotItem->plot() ) )
878       anItem->setSymbolType( plot->getLegendSymbolType() );
879     anItem->setSelected( isSelected() );
880     anItem->updateHighlit();
881     anItem->update();
882     anItem->repaint();
883   }
884 }
885
886 /*!
887   Draws histogram object
888 */
889 void Plot2d_HistogramItem::draw( QPainter* thePainter,
890                                  const QwtScaleMap& theXMap,
891                                  const QwtScaleMap& theYMap,
892                                  const QRectF& ) const
893 {
894   // nds: clear list of bar items
895   Plot2d_HistogramItem* anItem = (Plot2d_HistogramItem*)this;
896   anItem->myBarItems.clear();
897
898   thePainter->setPen( QPen( color() ) );
899   const int x0 = theXMap.transform( baseline() );
900   const int y0 = theYMap.transform( baseline() );
901
902   const QwtIntervalSeriesData& iData = data();
903
904   for ( int i = 0; i < (int)iData.size(); i++ ) {
905     if ( testHistogramAttribute( Plot2d_HistogramItem::Xfy ) ) {
906       const int x2 = theXMap.transform( iData.sample(i).value );
907       if ( x2 == x0 )
908         continue;
909       int y1 = theYMap.transform( iData.sample(i).interval.minValue() );
910       int y2 = theYMap.transform( iData.sample(i).interval.maxValue() );
911       if ( y1 > y2 )
912         qSwap( y1, y2 );
913
914       if ( i < (int)iData.size() - 2 ) {
915         const int yy1 = theYMap.transform( iData.sample(i+1).interval.minValue() );
916         const int yy2 = theYMap.transform( iData.sample(i+1).interval.maxValue() );
917         if ( y2 == qwtMin( yy1, yy2 ) ) {
918           const int xx2 = theXMap.transform( iData.sample(i+1).interval.minValue() );
919           if ( xx2 != x0 && ( ( xx2 < x0 && x2 < x0 ) ||
920                               ( xx2 > x0 && x2 > x0 ) ) ) {
921             // One pixel distance between neighboured bars
922             y2++;
923           }
924         }
925       }
926       // nds: draw rect with the other lower rects
927       QRect aRect( x0, y1, x2 - x0, y2 - y1 );
928       drawRectAndLowers( thePainter, Qt::Horizontal, aRect );
929       anItem->myBarItems.append( aRect );
930     }
931     else {
932       const int y2 = theYMap.transform( iData.sample(i).value );
933       if ( y2 == y0 )
934         continue;
935       int x1 = theXMap.transform( iData.sample(i).interval.minValue() );
936       int x2 = theXMap.transform( iData.sample(i).interval.maxValue() );
937       if ( x1 > x2 )
938         qSwap( x1, x2 );
939
940       if ( i < (int)iData.size() - 2 ) {
941         const int xx1 = theXMap.transform( iData.sample(i+1).interval.minValue() );
942         const int xx2 = theXMap.transform( iData.sample(i+1).interval.maxValue() );
943         if ( x2 == qwtMin( xx1, xx2 ) ) {
944           const int yy2 = theYMap.transform( iData.sample(i+1).value );
945           if ( yy2 != y0 && ( ( yy2 < y0 && y2 < y0 ) ||
946                               ( yy2 > y0 && y2 > y0 ) ) ) {
947             // One pixel distance between neighboured bars
948             x2--;
949           }
950         }
951       }
952       // nds: draw rect with the other lower rects
953       QRect aRect(x1, y0, x2 - x1, y2 - y0 );
954       drawRectAndLowers( thePainter, Qt::Vertical, aRect );
955       anItem->myBarItems.append( aRect );
956     }
957   }
958 }
959
960 /*!
961   Set/clear "cross items" option
962 */
963 void Plot2d_HistogramItem::setCrossItems( bool theCross )
964 {
965   myCrossed = theCross;
966 }
967
968 /*!
969   Get "cross items" option
970 */
971 bool Plot2d_HistogramItem::isCrossItems() const
972 {
973   return myCrossed;
974 }
975
976 /*!
977   Draws bar of histogram and on it bars of histograms with lower height.
978 */
979 void Plot2d_HistogramItem::drawRectAndLowers( QPainter* thePainter,
980                                               Qt::Orientation theOr,
981                                               const QRect& theRect ) const
982 {
983   QRect aRect = theRect;
984   // theRect has inversed coordinates on Y axis.
985   // The top of the rect is bottom in standard QRect coordinates,
986   // and it bottom is the top.
987   if ( myCrossed )//&& theOr == Qt::Horizontal )
988     aRect.setTop( getCrossedTop( theRect ) );
989
990   drawBar( thePainter, Qt::Horizontal, aRect );
991 }
992
993 /*!
994   Returns top value of the given rect in the context of other bars.
995
996   It's necessary to remember, that \a theRect has inverted coordinate Y.
997 */
998 int Plot2d_HistogramItem::getCrossedTop( const QRect& theRect ) const
999 {
1000   int aRes = theRect.top();
1001   QwtPlot* aPlot = plot();
1002   // int aHeight = theRect.height();
1003   if ( aPlot ) {
1004     QwtPlotItemList anItems = aPlot->itemList();
1005     QwtPlotItemIterator anIt = anItems.begin(), aLast = anItems.end();
1006     Plot2d_HistogramItem* anItem;
1007     QList<QRect> aRects;
1008     for ( ; anIt != aLast; anIt++ ) {
1009       if ( !((*anIt)->rtti() == QwtPlotItem::Rtti_PlotHistogram) )
1010         continue;
1011       anItem = dynamic_cast<Plot2d_HistogramItem*>( *anIt );
1012       if( !anItem || anItem == this )
1013         continue;
1014       aRects.clear();
1015       aRects = anItem->getBars();
1016       for ( int i = 0, aSize = aRects.size(); i < aSize; i++ ) {
1017         if ( qMax( theRect.x(), aRects[i].x() ) <=
1018              qMin( theRect.left(), aRects[i].left() ) ) {
1019           if ( theRect.bottom() < aRects[i].bottom() )
1020             if ( aRects[i].bottom() < aRes )
1021               aRes = aRects[i].bottom();
1022         }
1023       }
1024     }
1025   }
1026   return aRes;
1027 }
1028
1029 Plot2d_QwtLegend::Plot2d_QwtLegend( QWidget *parent ):
1030 QwtLegend( parent )
1031 {
1032   setAutoFillBackground(true);
1033 }
1034
1035 Plot2d_QwtLegend::~Plot2d_QwtLegend()
1036 {
1037 }
1038
1039 /*!
1040   Redefined method, which create a widget to be inserted into the legend.
1041 */
1042 QWidget *Plot2d_QwtLegend::createWidget( const QwtLegendData &data ) const
1043 {
1044   Q_UNUSED( data );
1045
1046   Plot2d_QwtLegendLabel *label = new Plot2d_QwtLegendLabel();
1047   label->setItemMode( defaultItemMode() );
1048
1049   connect( label, SIGNAL( clicked() ), SLOT( itemClicked() ) );
1050   connect( label, SIGNAL( checked( bool ) ), SLOT( itemChecked( bool ) ) );
1051
1052   return label;
1053 }