qwt_plot_legenditem.cpp
Go to the documentation of this file.
1 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2  * Qwt Widget Library
3  * Copyright (C) 1997 Josef Wilgen
4  * Copyright (C) 2002 Uwe Rathmann
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the Qwt License, Version 1.0
8  *****************************************************************************/
9 
10 #include "qwt_plot_legenditem.h"
11 #include "qwt_dyngrid_layout.h"
12 #include "qwt_text.h"
13 #include "qwt_graphic.h"
14 #include "qwt_legend_data.h"
15 #include "qwt_math.h"
16 
17 #include <qlayoutitem.h>
18 #include <qpen.h>
19 #include <qbrush.h>
20 #include <qpainter.h>
21 
22 namespace
23 {
24  class QwtLegendLayoutItem QWT_FINAL: public QLayoutItem
25  {
26  public:
27  QwtLegendLayoutItem( const QwtPlotLegendItem *, const QwtPlotItem * );
28  virtual ~QwtLegendLayoutItem();
29 
30  const QwtPlotItem *plotItem() const;
31 
32  void setData( const QwtLegendData & );
33  const QwtLegendData &data() const;
34 
35  virtual Qt::Orientations expandingDirections() const QWT_OVERRIDE;
36  virtual QRect geometry() const QWT_OVERRIDE;
37  virtual bool hasHeightForWidth() const QWT_OVERRIDE;
38  virtual int heightForWidth( int ) const QWT_OVERRIDE;
39  virtual bool isEmpty() const QWT_OVERRIDE;
40  virtual QSize maximumSize() const QWT_OVERRIDE;
41  virtual int minimumHeightForWidth( int ) const QWT_OVERRIDE;
42  virtual QSize minimumSize() const QWT_OVERRIDE;
43  virtual void setGeometry( const QRect & ) QWT_OVERRIDE;
44  virtual QSize sizeHint() const QWT_OVERRIDE;
45 
46  private:
47 
48  const QwtPlotLegendItem *d_legendItem;
49  const QwtPlotItem *d_plotItem;
50  QwtLegendData d_data;
51 
52  QRect d_rect;
53  };
54 }
55 
56 QwtLegendLayoutItem::QwtLegendLayoutItem(
57  const QwtPlotLegendItem *legendItem, const QwtPlotItem *plotItem ):
58  d_legendItem( legendItem ),
59  d_plotItem( plotItem)
60 {
61 }
62 
63 QwtLegendLayoutItem::~QwtLegendLayoutItem()
64 {
65 }
66 
67 const QwtPlotItem *QwtLegendLayoutItem::plotItem() const
68 {
69  return d_plotItem;
70 }
71 
72 void QwtLegendLayoutItem::setData( const QwtLegendData &data )
73 {
74  d_data = data;
75 }
76 
78 {
79  return d_data;
80 }
81 
82 Qt::Orientations QwtLegendLayoutItem::expandingDirections() const
83 {
84  return Qt::Horizontal;
85 }
86 
87 bool QwtLegendLayoutItem::hasHeightForWidth() const
88 {
89  return !d_data.title().isEmpty();
90 }
91 
92 int QwtLegendLayoutItem::minimumHeightForWidth( int w ) const
93 {
94  return d_legendItem->heightForWidth( d_data, w );
95 }
96 
97 int QwtLegendLayoutItem::heightForWidth( int w ) const
98 {
99  return d_legendItem->heightForWidth( d_data, w );
100 }
101 
102 bool QwtLegendLayoutItem::isEmpty() const
103 {
104  return false;
105 }
106 
107 QSize QwtLegendLayoutItem::maximumSize() const
108 {
109  return QSize( QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX );
110 }
111 
112 QSize QwtLegendLayoutItem::minimumSize() const
113 {
114  return d_legendItem->minimumSize( d_data );
115 }
116 
117 QSize QwtLegendLayoutItem::sizeHint() const
118 {
119  return minimumSize();
120 }
121 
122 void QwtLegendLayoutItem::setGeometry( const QRect &rect )
123 {
124  d_rect = rect;
125 }
126 
127 QRect QwtLegendLayoutItem::geometry() const
128 {
129  return d_rect;
130 }
131 
133 {
134 public:
136  itemMargin( 4 ),
137  itemSpacing( 4 ),
138  borderRadius( 0.0 ),
139  borderPen( Qt::NoPen ),
140  backgroundBrush( Qt::NoBrush ),
141  backgroundMode( QwtPlotLegendItem::LegendBackground ),
142  canvasAlignment( Qt::AlignRight | Qt::AlignBottom )
143  {
144  canvasOffset[ 0 ] = canvasOffset[1] = 10;
145  layout = new QwtDynGridLayout();
146  layout->setMaxColumns( 2 );
147 
148  layout->setSpacing( 0 );
149  layout->setContentsMargins( 0, 0, 0, 0 );
150  }
151 
153  {
154  delete layout;
155  }
156 
157  QFont font;
158  QPen textPen;
161 
162  double borderRadius;
163  QPen borderPen;
166 
167  int canvasOffset[2];
168  Qt::Alignment canvasAlignment;
169 
172 };
173 
176  QwtPlotItem( QwtText( "Legend" ) )
177 {
178  d_data = new PrivateData;
179 
181  setZ( 100.0 );
182 }
183 
186 {
187  clearLegend();
188  delete d_data;
189 }
190 
193 {
195 }
196 
210 void QwtPlotLegendItem::setAlignmentInCanvas( Qt::Alignment alignment )
211 {
212  if ( d_data->canvasAlignment != alignment )
213  {
214  d_data->canvasAlignment = alignment;
215  itemChanged();
216  }
217 }
218 
224 {
225  return d_data->canvasAlignment;
226 }
227 
239 {
240  if ( maxColumns != d_data->layout->maxColumns() )
241  {
242  d_data->layout->setMaxColumns( maxColumns );
243  itemChanged();
244  }
245 }
246 
252 {
253  return d_data->layout->maxColumns();
254 }
255 
265 {
266  margin = qMax( margin, 0 );
267  if ( margin != this->margin() )
268  {
269  d_data->layout->setContentsMargins(
270  margin, margin, margin, margin );
271 
272  itemChanged();
273  }
274 }
275 
281 {
282  int left;
283  d_data->layout->getContentsMargins( &left, NULL, NULL, NULL );
284 
285  return left;
286 }
287 
295 {
296  spacing = qMax( spacing, 0 );
297  if ( spacing != d_data->layout->spacing() )
298  {
299  d_data->layout->setSpacing( spacing );
300  itemChanged();
301  }
302 }
303 
309 {
310  return d_data->layout->spacing();
311 }
312 
320 {
321  margin = qMax( margin, 0 );
322  if ( margin != d_data->itemMargin )
323  {
325 
327  itemChanged();
328  }
329 }
330 
336 {
337  return d_data->itemMargin;
338 }
339 
347 {
348  spacing = qMax( spacing, 0 );
349  if ( spacing != d_data->itemSpacing )
350  {
352 
354  itemChanged();
355  }
356 
357 }
358 
364 {
365  return d_data->itemSpacing;
366 }
367 
374 void QwtPlotLegendItem::setFont( const QFont &font )
375 {
376  if ( font != d_data->font )
377  {
378  d_data->font = font;
379 
381  itemChanged();
382  }
383 }
384 
390 {
391  return d_data->font;
392 }
393 
406  Qt::Orientations orientations, int numPixels )
407 {
408  if ( numPixels < 0 )
409  numPixels = -1;
410 
411  bool isChanged = false;
412 
413  int *offset = d_data->canvasOffset;
414 
415  if ( orientations & Qt::Horizontal )
416  {
417  if ( numPixels != offset[0] )
418  {
419  offset[0] = numPixels;
420  isChanged = true;
421  }
422  }
423 
424  if ( orientations & Qt::Vertical )
425  {
426  if ( numPixels != offset[1] )
427  {
428  offset[1] = numPixels;
429  isChanged = true;
430  }
431  }
432 
433  if ( isChanged )
434  itemChanged();
435 }
436 
445  Qt::Orientation orientation ) const
446 {
447  const int index = ( orientation == Qt::Vertical ) ? 1 : 0;
448  return d_data->canvasOffset[index];
449 }
450 
458 {
459  radius = qwtMaxF( 0.0, radius );
460 
461  if ( radius != d_data->borderRadius )
462  {
463  d_data->borderRadius = radius;
464  itemChanged();
465  }
466 }
467 
473 {
474  return d_data->borderRadius;
475 }
476 
483 void QwtPlotLegendItem::setBorderPen( const QPen &pen )
484 {
485  if ( d_data->borderPen != pen )
486  {
487  d_data->borderPen = pen;
488  itemChanged();
489  }
490 }
491 
497 {
498  return d_data->borderPen;
499 }
500 
509 void QwtPlotLegendItem::setBackgroundBrush( const QBrush &brush )
510 {
511  if ( d_data->backgroundBrush != brush )
512  {
513  d_data->backgroundBrush = brush;
514  itemChanged();
515  }
516 }
517 
523 {
524  return d_data->backgroundBrush;
525 }
526 
538 {
539  if ( mode != d_data->backgroundMode )
540  {
541  d_data->backgroundMode = mode;
542  itemChanged();
543  }
544 }
545 
551 {
552  return d_data->backgroundMode;
553 }
554 
561 void QwtPlotLegendItem::setTextPen( const QPen &pen )
562 {
563  if ( d_data->textPen != pen )
564  {
565  d_data->textPen = pen;
566  itemChanged();
567  }
568 }
569 
575 {
576  return d_data->textPen;
577 }
578 
587 void QwtPlotLegendItem::draw( QPainter *painter,
588  const QwtScaleMap &xMap, const QwtScaleMap &yMap,
589  const QRectF &canvasRect ) const
590 {
591  Q_UNUSED( xMap );
592  Q_UNUSED( yMap );
593 
594  d_data->layout->setGeometry( geometry( canvasRect ) );
595  if ( d_data->layout->geometry().isEmpty() )
596  {
597  // don't draw a legend when having no content
598  return;
599  }
600 
602  drawBackground( painter, d_data->layout->geometry() );
603 
604  for ( int i = 0; i < d_data->layout->count(); i++ )
605  {
606  const QwtLegendLayoutItem *layoutItem =
607  static_cast<QwtLegendLayoutItem *>( d_data->layout->itemAt( i ) );
608 
610  drawBackground( painter, layoutItem->geometry() );
611 
612  painter->save();
613 
614  drawLegendData( painter, layoutItem->plotItem(),
615  layoutItem->data(), layoutItem->geometry() );
616 
617  painter->restore();
618  }
619 }
620 
631  QPainter *painter, const QRectF &rect ) const
632 {
633  painter->save();
634 
635  painter->setPen( d_data->borderPen );
636  painter->setBrush( d_data->backgroundBrush );
637 
638  const double radius = d_data->borderRadius;
639  painter->drawRoundedRect( rect, radius, radius );
640 
641  painter->restore();
642 }
643 
650 QRect QwtPlotLegendItem::geometry( const QRectF &canvasRect ) const
651 {
652  QRect rect;
653  rect.setSize( d_data->layout->sizeHint() );
654 
655  if ( d_data->canvasAlignment & Qt::AlignHCenter )
656  {
657  int x = qRound( canvasRect.center().x() );
658  rect.moveCenter( QPoint( x, rect.center().y() ) );
659  }
660  else if ( d_data->canvasAlignment & Qt::AlignRight )
661  {
662  const int offset = offsetInCanvas( Qt::Horizontal );
663  rect.moveRight( qwtFloor( canvasRect.right() - offset ) );
664  }
665  else
666  {
667  const int offset = offsetInCanvas( Qt::Horizontal );
668  rect.moveLeft( qwtCeil( canvasRect.left() + offset ) );
669  }
670 
671  if ( d_data->canvasAlignment & Qt::AlignVCenter )
672  {
673  int y = qRound( canvasRect.center().y() );
674  rect.moveCenter( QPoint( rect.center().x(), y ) );
675  }
676  else if ( d_data->canvasAlignment & Qt::AlignBottom )
677  {
678  const int offset = offsetInCanvas( Qt::Vertical );
679  rect.moveBottom( qwtFloor( canvasRect.bottom() - offset ) );
680  }
681  else
682  {
683  const int offset = offsetInCanvas( Qt::Vertical );
684  rect.moveTop( qwtCeil( canvasRect.top() + offset ) );
685  }
686 
687  return rect;
688 }
689 
698  const QList<QwtLegendData> &data )
699 {
700  if ( plotItem == NULL )
701  return;
702 
703  QList<QwtLegendLayoutItem *> layoutItems;
704 
706  d_data->map.constFind( plotItem );
707  if ( it != d_data->map.constEnd() )
708  layoutItems = it.value();
709 
710  bool changed = false;
711 
712  if ( data.size() != layoutItems.size() )
713  {
714  changed = true;
715 
716  for ( int i = 0; i < layoutItems.size(); i++ )
717  {
718  d_data->layout->removeItem( layoutItems[i] );
719  delete layoutItems[i];
720  }
721  layoutItems.clear();
722 
723  if ( it != d_data->map.constEnd() )
724  d_data->map.remove( plotItem );
725 
726  if ( !data.isEmpty() )
727  {
728  layoutItems.reserve( data.size() );
729 
730  for ( int i = 0; i < data.size(); i++ )
731  {
732  QwtLegendLayoutItem *layoutItem =
733  new QwtLegendLayoutItem( this, plotItem );
734  d_data->layout->addItem( layoutItem );
735  layoutItems += layoutItem;
736  }
737 
738  d_data->map.insert( plotItem, layoutItems );
739  }
740  }
741 
742  for ( int i = 0; i < data.size(); i++ )
743  {
744  if ( layoutItems[i]->data().values() != data[i].values() )
745  {
746  layoutItems[i]->setData( data[i] );
747  changed = true;
748  }
749  }
750 
751  if ( changed )
752  {
754  itemChanged();
755  }
756 }
757 
760 {
761  if ( !d_data->map.isEmpty() )
762  {
763  d_data->map.clear();
764 
765  for ( int i = d_data->layout->count() - 1; i >= 0; i-- )
766  delete d_data->layout->takeAt( i );
767 
768  itemChanged();
769  }
770 }
771 
780 void QwtPlotLegendItem::drawLegendData( QPainter *painter,
781  const QwtPlotItem *plotItem, const QwtLegendData &data,
782  const QRectF &rect ) const
783 {
784  Q_UNUSED( plotItem );
785 
786  const int m = d_data->itemMargin;
787  const QRectF r = rect.toRect().adjusted( m, m, -m, -m );
788 
789  painter->setClipRect( r, Qt::IntersectClip );
790 
791  int titleOff = 0;
792 
793  const QwtGraphic graphic = data.icon();
794  if ( !graphic.isEmpty() )
795  {
796  QRectF iconRect( r.topLeft(), graphic.defaultSize() );
797 
798  iconRect.moveCenter(
799  QPoint( iconRect.center().x(), rect.center().y() ) );
800 
801  graphic.render( painter, iconRect, Qt::KeepAspectRatio );
802 
803  titleOff += iconRect.width() + d_data->itemSpacing;
804  }
805 
806  const QwtText text = data.title();
807  if ( !text.isEmpty() )
808  {
809  painter->setPen( textPen() );
810  painter->setFont( font() );
811 
812  const QRectF textRect = r.adjusted( titleOff, 0, 0, 0 );
813  text.draw( painter, textRect );
814  }
815 }
816 
824 {
825  QSize size( 2 * d_data->itemMargin, 2 * d_data->itemMargin );
826 
827  if ( !data.isValid() )
828  return size;
829 
830  const QwtGraphic graphic = data.icon();
831  const QwtText text = data.title();
832 
833  int w = 0;
834  int h = 0;
835 
836  if ( !graphic.isNull() )
837  {
838  w = graphic.width();
839  h = graphic.height();
840  }
841 
842  if ( !text.isEmpty() )
843  {
844  const QSizeF sz = text.textSize( font() );
845 
846  w += qwtCeil( sz.width() );
847  h = qMax( h, qwtCeil( sz.height() ) );
848  }
849 
850  if ( graphic.width() > 0 && !text.isEmpty() )
851  w += d_data->itemSpacing;
852 
853  size += QSize( w, h );
854  return size;
855 }
856 
863  const QwtLegendData &data, int width ) const
864 {
865  width -= 2 * d_data->itemMargin;
866 
867  const QwtGraphic graphic = data.icon();
868  const QwtText text = data.title();
869 
870  if ( text.isEmpty() )
871  return graphic.height();
872 
873  if ( graphic.width() > 0 )
874  width -= graphic.width() + d_data->itemSpacing;
875 
876  int h = text.heightForWidth( width, font() );
877  h += 2 * d_data->itemMargin;
878 
879  return qMax( graphic.height(), h );
880 }
881 
887 {
888  return d_data->map.keys();
889 }
890 
896  const QwtPlotItem *plotItem ) const
897 {
898  QList<QwtLegendLayoutItem *> layoutItems;
899 
901  d_data->map.constFind( plotItem );
902  if ( it != d_data->map.constEnd() )
903  layoutItems = it.value();
904 
905  QList<QRect> geometries;
906  geometries.reserve(layoutItems.size());
907 
908  for ( int i = 0; i < layoutItems.size(); i++ )
909  geometries += layoutItems[i]->geometry();
910 
911  return geometries;
912 }
void setSpacing(int)
Set the spacing between the legend items.
BackgroundMode backgroundMode() const
void setBackgroundMode(BackgroundMode)
Set the background mode.
Each item has a background.
virtual QSize minimumSize(const QwtLegendData &) const
The legend has a background.
void render(QPainter *) const
Replay all recorded painter commands.
void setFont(const QFont &)
Definition: qwt_text.cpp:306
QSizeF textSize() const
Definition: qwt_text.cpp:547
BackgroundMode
Background mode.
QMap< const QwtPlotItem *, QList< QwtLegendLayoutItem * > > map
QWT_CONSTEXPR float qwtMaxF(float a, float b)
Definition: qwt_math.h:123
virtual int heightForWidth(const QwtLegendData &, int width) const
lu_byte left
Definition: lparser.c:1228
void setBackgroundBrush(const QBrush &)
Set the background brush.
void setFont(const QFont &)
A class which draws a legend inside the plot canvas.
QSizeF defaultSize() const
Default size.
virtual QRect geometry(const QRectF &canvasRect) const
void draw(QPainter *painter, const QRectF &rect) const
Definition: qwt_text.cpp:592
void clearLegend()
Remove all items from the legend.
Qt::Alignment alignmentInCanvas() const
virtual QLayoutItem * takeAt(int index) QWT_OVERRIDE
virtual void drawBackground(QPainter *, const QRectF &rect) const
void setTextPen(const QPen &)
Set the pen for drawing text labels.
void setMargin(int)
Set the margin around legend items.
void setAlignmentInCanvas(Qt::Alignment)
Set the alignmnet.
int qwtFloor(qreal value)
Definition: qwt_math.h:271
virtual ~QwtPlotLegendItem()
Destructor.
The QwtDynGridLayout class lays out widgets in a grid, adjusting the number of columns and rows to th...
double heightForWidth(double width) const
Definition: qwt_text.cpp:499
QList< const QwtPlotItem * > plotItems() const
virtual void updateLegend(const QwtPlotItem *, const QList< QwtLegendData > &) QWT_OVERRIDE
void setMaxColumns(uint maxColumns)
virtual int rtti() const QWT_OVERRIDE
virtual QSize sizeHint() const QWT_OVERRIDE
QBrush backgroundBrush() const
bool isEmpty() const
Definition: qwt_text.cpp:716
For QwtPlotLegendItem.
Definition: qwt_plot_item.h:86
void setOffsetInCanvas(Qt::Orientations, int numPixels)
Set the distance between the legend and the canvas border.
A class representing a text.
Definition: qwt_text.h:51
virtual QLayoutItem * itemAt(int index) const QWT_OVERRIDE
void setZ(double z)
Set the z value.
QwtGraphic icon() const
virtual void draw(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect) const QWT_OVERRIDE
A paint device for scalable graphics.
Definition: qwt_graphic.h:75
QwtPlotLegendItem::BackgroundMode backgroundMode
A scale map.
Definition: qwt_scale_map.h:26
virtual void itemChanged()
#define QWT_FINAL
Definition: qwt_global.h:57
void setBorderPen(const QPen &)
virtual void addItem(QLayoutItem *) QWT_OVERRIDE
Add an item to the next free position.
double borderRadius() const
int offsetInCanvas(Qt::Orientation) const
QwtText title() const
bool isEmpty() const
bool isValid() const
QwtPlotLegendItem()
Constructor.
Base class for items on the plot canvas.
Definition: qwt_plot_item.h:65
virtual void invalidate() QWT_OVERRIDE
Invalidate all internal caches.
QList< QRect > legendGeometries(const QwtPlotItem *) const
bool isNull() const
void setItemInterest(ItemInterest, bool on=true)
dictionary data
Definition: mqtt_test.py:22
uint maxColumns() const
Return the upper limit for the number of columns.
int qwtCeil(qreal value)
Definition: qwt_math.h:262
virtual bool isEmpty() const QWT_OVERRIDE
virtual void setGeometry(const QRect &) QWT_OVERRIDE
virtual int count() const QWT_OVERRIDE
Attributes of an entry on a legend.
#define QWT_OVERRIDE
Definition: qwt_global.h:53
virtual void drawLegendData(QPainter *, const QwtPlotItem *, const QwtLegendData &, const QRectF &) const
void setMaxColumns(uint)
Limit the number of columns.


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:48:10