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_scale_map.h"
13 #include "qwt_painter.h"
14 #include <qlayoutitem.h>
15 #include <qpen.h>
16 #include <qbrush.h>
17 #include <qpainter.h>
18 #include <qmath.h>
19 
20 class QwtLegendLayoutItem: public QLayoutItem
21 {
22 public:
24  virtual ~QwtLegendLayoutItem();
25 
26  const QwtPlotItem *plotItem() const;
27 
28  void setData( const QwtLegendData & );
29  const QwtLegendData &data() const;
30 
31  virtual Qt::Orientations expandingDirections() const;
32  virtual QRect geometry() const;
33  virtual bool hasHeightForWidth() const;
34  virtual int heightForWidth( int w ) const;
35  virtual bool isEmpty() const;
36  virtual QSize maximumSize() const;
37  virtual int minimumHeightForWidth( int w ) const;
38  virtual QSize minimumSize() const;
39  virtual void setGeometry( const QRect & r );
40  virtual QSize sizeHint() const;
41 
42 private:
43 
47 
48  QRect d_rect;
49 };
50 
52  const QwtPlotLegendItem *legendItem, const QwtPlotItem *plotItem ):
53  d_legendItem( legendItem ),
54  d_plotItem( plotItem)
55 {
56 }
57 
59 {
60 }
61 
63 {
64  return d_plotItem;
65 }
66 
68 {
69  d_data = data;
70 }
71 
73 {
74  return d_data;
75 }
76 
78 {
79  return Qt::Horizontal;
80 }
81 
83 {
84  return !d_data.title().isEmpty();
85 }
86 
88 {
89  return d_legendItem->heightForWidth( d_data, w );
90 }
91 
93 {
94  return d_legendItem->heightForWidth( d_data, w );
95 }
96 
98 {
99  return false;
100 }
101 
103 {
104  return QSize( QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX );
105 }
106 
108 {
109  return d_legendItem->minimumSize( d_data );
110 }
111 
113 {
114  return minimumSize();
115 }
116 
117 void QwtLegendLayoutItem::setGeometry( const QRect &rect )
118 {
119  d_rect = rect;
120 }
121 
123 {
124  return d_rect;
125 }
126 
128 {
129 public:
131  itemMargin( 4 ),
132  itemSpacing( 4 ),
133  borderRadius( 0.0 ),
134  borderPen( Qt::NoPen ),
135  backgroundBrush( Qt::NoBrush ),
136  backgroundMode( QwtPlotLegendItem::LegendBackground ),
137  borderDistance( 10 ),
138  alignment( Qt::AlignRight | Qt::AlignBottom )
139  {
140  layout = new QwtDynGridLayout();
141  layout->setMaxColumns( 2 );
142 
143  layout->setSpacing( 0 );
144  layout->setContentsMargins( 0, 0, 0, 0 );
145  }
146 
148  {
149  delete layout;
150  }
151 
152  QFont font;
153  QPen textPen;
156 
157  double borderRadius;
158  QPen borderPen;
161 
163  Qt::Alignment alignment;
164 
165  QMap< const QwtPlotItem *, QList<QwtLegendLayoutItem *> > map;
167 };
168 
171  QwtPlotItem( QwtText( "Legend" ) )
172 {
173  d_data = new PrivateData;
174 
176  setZ( 100.0 );
177 }
178 
181 {
182  clearLegend();
183  delete d_data;
184 }
185 
188 {
190 }
191 
206 {
207  if ( d_data->alignment != alignment )
208  {
210  itemChanged();
211  }
212 }
213 
218 Qt::Alignment QwtPlotLegendItem::alignment() const
219 {
220  return d_data->alignment;
221 }
222 
234 {
235  if ( maxColumns != d_data->layout->maxColumns() )
236  {
237  d_data->layout->setMaxColumns( maxColumns );
238  itemChanged();
239  }
240 }
241 
247 {
248  return d_data->layout->maxColumns();
249 }
250 
260 {
261  margin = qMax( margin, 0 );
262  if ( margin != this->margin() )
263  {
264  d_data->layout->setContentsMargins(
265  margin, margin, margin, margin );
266 
267  itemChanged();
268  }
269 }
270 
276 {
277  int left;
278  d_data->layout->getContentsMargins( &left, NULL, NULL, NULL );
279 
280  return left;
281 }
282 
290 {
291  spacing = qMax( spacing, 0 );
292  if ( spacing != d_data->layout->spacing() )
293  {
294  d_data->layout->setSpacing( spacing );
295  itemChanged();
296  }
297 }
298 
304 {
305  return d_data->layout->spacing();
306 }
307 
315 {
316  margin = qMax( margin, 0 );
317  if ( margin != d_data->itemMargin )
318  {
320 
322  itemChanged();
323  }
324 }
325 
331 {
332  return d_data->itemMargin;
333 }
334 
342 {
343  spacing = qMax( spacing, 0 );
344  if ( spacing != d_data->itemSpacing )
345  {
347 
349  itemChanged();
350  }
351 
352 }
353 
359 {
360  return d_data->itemSpacing;
361 }
362 
369 void QwtPlotLegendItem::setFont( const QFont &font )
370 {
371  if ( font != d_data->font )
372  {
373  d_data->font = font;
374 
376  itemChanged();
377  }
378 }
379 
385 {
386  return d_data->font;
387 }
388 
398 {
399  if ( distance < 0 )
400  distance = -1;
401 
402  if ( distance != d_data->borderDistance )
403  {
404  d_data->borderDistance = distance;
405  itemChanged();
406  }
407 }
408 
414 {
415  return d_data->borderDistance;
416 }
417 
425 {
426  radius = qMax( 0.0, radius );
427 
428  if ( radius != d_data->borderRadius )
429  {
430  d_data->borderRadius = radius;
431  itemChanged();
432  }
433 }
434 
440 {
441  return d_data->borderRadius;
442 }
443 
450 void QwtPlotLegendItem::setBorderPen( const QPen &pen )
451 {
452  if ( d_data->borderPen != pen )
453  {
454  d_data->borderPen = pen;
455  itemChanged();
456  }
457 }
458 
464 {
465  return d_data->borderPen;
466 }
467 
476 void QwtPlotLegendItem::setBackgroundBrush( const QBrush &brush )
477 {
478  if ( d_data->backgroundBrush != brush )
479  {
480  d_data->backgroundBrush = brush;
481  itemChanged();
482  }
483 }
484 
490 {
491  return d_data->backgroundBrush;
492 }
493 
505 {
506  if ( mode != d_data->backgroundMode )
507  {
508  d_data->backgroundMode = mode;
509  itemChanged();
510  }
511 }
512 
518 {
519  return d_data->backgroundMode;
520 }
521 
528 void QwtPlotLegendItem::setTextPen( const QPen &pen )
529 {
530  if ( d_data->textPen != pen )
531  {
532  d_data->textPen = pen;
533  itemChanged();
534  }
535 }
536 
542 {
543  return d_data->textPen;
544 }
545 
554 void QwtPlotLegendItem::draw( QPainter *painter,
555  const QwtScaleMap &xMap, const QwtScaleMap &yMap,
556  const QRectF &canvasRect ) const
557 {
558  Q_UNUSED( xMap );
559  Q_UNUSED( yMap );
560 
561  d_data->layout->setGeometry( geometry( canvasRect ) );
562  if ( d_data->layout->geometry().isEmpty() )
563  {
564  // don't draw a legend when having no content
565  return;
566  }
567 
569  drawBackground( painter, d_data->layout->geometry() );
570 
571  for ( int i = 0; i < d_data->layout->count(); i++ )
572  {
573  const QwtLegendLayoutItem *layoutItem =
574  static_cast<QwtLegendLayoutItem *>( d_data->layout->itemAt( i ) );
575 
577  drawBackground( painter, layoutItem->geometry() );
578 
579  painter->save();
580 
581  drawLegendData( painter, layoutItem->plotItem(),
582  layoutItem->data(), layoutItem->geometry() );
583 
584  painter->restore();
585  }
586 }
587 
598  QPainter *painter, const QRectF &rect ) const
599 {
600  painter->save();
601 
602  painter->setPen( d_data->borderPen );
603  painter->setBrush( d_data->backgroundBrush );
604 
605  const double radius = d_data->borderRadius;
606  painter->drawRoundedRect( rect, radius, radius );
607 
608  painter->restore();
609 }
610 
617 QRect QwtPlotLegendItem::geometry( const QRectF &canvasRect ) const
618 {
619  QRect rect;
620  rect.setSize( d_data->layout->sizeHint() );
621 
623  if ( d_data->alignment & Qt::AlignHCenter )
624  {
625  int x = qRound( canvasRect.center().x() );
626  rect.moveCenter( QPoint( x, rect.center().y() ) );
627  }
628  else if ( d_data->alignment & Qt::AlignRight )
629  {
630  rect.moveRight( qFloor( canvasRect.right() - margin ) );
631  }
632  else
633  {
634  rect.moveLeft( qCeil( canvasRect.left() + margin ) );
635  }
636 
637  if ( d_data->alignment & Qt::AlignVCenter )
638  {
639  int y = qRound( canvasRect.center().y() );
640  rect.moveCenter( QPoint( rect.center().x(), y ) );
641  }
642  else if ( d_data->alignment & Qt::AlignBottom )
643  {
644  rect.moveBottom( qFloor( canvasRect.bottom() - margin ) );
645  }
646  else
647  {
648  rect.moveTop( qCeil( canvasRect.top() + margin ) );
649  }
650 
651  return rect;
652 }
653 
662  const QList<QwtLegendData> &data )
663 {
664  if ( plotItem == NULL )
665  return;
666 
667  QList<QwtLegendLayoutItem *> layoutItems;
668 
669  QMap<const QwtPlotItem *, QList<QwtLegendLayoutItem *> >::const_iterator it =
670  d_data->map.constFind( plotItem );
671  if ( it != d_data->map.constEnd() )
672  layoutItems = it.value();
673 
674  bool changed = false;
675 
676  if ( data.size() != layoutItems.size() )
677  {
678  changed = true;
679 
680  for ( int i = 0; i < layoutItems.size(); i++ )
681  {
682  d_data->layout->removeItem( layoutItems[i] );
683  delete layoutItems[i];
684  }
685  layoutItems.clear();
686 
687  if ( it != d_data->map.end() )
688  d_data->map.remove( plotItem );
689 
690  if ( !data.isEmpty() )
691  {
692 #if QT_VERSION >= 0x040700
693  layoutItems.reserve( data.size() );
694 #endif
695  for ( int i = 0; i < data.size(); i++ )
696  {
697  QwtLegendLayoutItem *layoutItem =
698  new QwtLegendLayoutItem( this, plotItem );
699  d_data->layout->addItem( layoutItem );
700  layoutItems += layoutItem;
701  }
702 
703  d_data->map.insert( plotItem, layoutItems );
704  }
705  }
706 
707  for ( int i = 0; i < data.size(); i++ )
708  {
709  if ( layoutItems[i]->data().values() != data[i].values() )
710  {
711  layoutItems[i]->setData( data[i] );
712  changed = true;
713  }
714  }
715 
716  if ( changed )
717  {
719  itemChanged();
720  }
721 }
722 
725 {
726  if ( !d_data->map.isEmpty() )
727  {
728  d_data->map.clear();
729 
730  for ( int i = d_data->layout->count() - 1; i >= 0; i-- )
731  delete d_data->layout->takeAt( i );
732 
733  itemChanged();
734  }
735 }
736 
745 void QwtPlotLegendItem::drawLegendData( QPainter *painter,
746  const QwtPlotItem *plotItem, const QwtLegendData &data,
747  const QRectF &rect ) const
748 {
749  Q_UNUSED( plotItem );
750 
751  const int m = d_data->itemMargin;
752  const QRectF r = rect.toRect().adjusted( m, m, -m, -m );
753 
754  painter->setClipRect( r, Qt::IntersectClip );
755 
756  int titleOff = 0;
757 
758  const QwtGraphic graphic = data.icon();
759  if ( !graphic.isEmpty() )
760  {
761  QRectF iconRect( r.topLeft(), graphic.defaultSize() );
762 
763  iconRect.moveCenter(
764  QPoint( iconRect.center().x(), rect.center().y() ) );
765 
766  graphic.render( painter, iconRect, Qt::KeepAspectRatio );
767 
768  titleOff += iconRect.width() + d_data->itemSpacing;
769  }
770 
771  const QwtText text = data.title();
772  if ( !text.isEmpty() )
773  {
774  painter->setPen( textPen() );
775  painter->setFont( font() );
776 
777  const QRectF textRect = r.adjusted( titleOff, 0, 0, 0 );
778  text.draw( painter, textRect );
779  }
780 }
781 
789 {
790  QSize size( 2 * d_data->itemMargin, 2 * d_data->itemMargin );
791 
792  if ( !data.isValid() )
793  return size;
794 
795  const QwtGraphic graphic = data.icon();
796  const QwtText text = data.title();
797 
798  int w = 0;
799  int h = 0;
800 
801  if ( !graphic.isNull() )
802  {
803  w = graphic.width();
804  h = graphic.height();
805  }
806 
807  if ( !text.isEmpty() )
808  {
809  const QSizeF sz = text.textSize( font() );
810 
811  w += qCeil( sz.width() );
812  h = qMax( h, qCeil( sz.height() ) );
813  }
814 
815  if ( graphic.width() > 0 && !text.isEmpty() )
816  w += d_data->itemSpacing;
817 
818  size += QSize( w, h );
819  return size;
820 }
821 
828  const QwtLegendData &data, int width ) const
829 {
830  width -= 2 * d_data->itemMargin;
831 
832  const QwtGraphic graphic = data.icon();
833  const QwtText text = data.title();
834 
835  if ( text.isEmpty() )
836  return graphic.height();
837 
838  if ( graphic.width() > 0 )
839  width -= graphic.width() + d_data->itemSpacing;
840 
841  int h = text.heightForWidth( width, font() );
842  h += 2 * d_data->itemMargin;
843 
844  return qMax( graphic.height(), h );
845 }
846 
851 QList< const QwtPlotItem * > QwtPlotLegendItem::plotItems() const
852 {
853  return d_data->map.keys();
854 }
855 
861  const QwtPlotItem *plotItem ) const
862 {
863  QList<QwtLegendLayoutItem *> layoutItems;
864 
865  QMap<const QwtPlotItem *, QList<QwtLegendLayoutItem *> >::const_iterator it =
866  d_data->map.constFind( plotItem );
867  if ( it != d_data->map.constEnd() )
868  layoutItems = it.value();
869 
870  QList<QRect> geometries;
871 #if QT_VERSION >= 0x040700
872  geometries.reserve(layoutItems.size());
873 #endif
874 
875  for ( int i = 0; i < layoutItems.size(); i++ )
876  geometries += layoutItems[i]->geometry();
877 
878  return geometries;
879 }
void setSpacing(int)
Set the spacing between the legend items.
const QwtPlotItem * plotItem() const
virtual QSize maximumSize() const
BackgroundMode backgroundMode() const
void setBackgroundMode(BackgroundMode)
Set the background mode.
Each item has a background.
virtual bool isEmpty() const
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:296
virtual void setGeometry(const QRect &rect)
virtual int rtti() const
BackgroundMode
Background mode.
QMap< const QwtPlotItem *, QList< QwtLegendLayoutItem * > > map
virtual void addItem(QLayoutItem *)
Add an item to the next free position.
virtual void updateLegend(const QwtPlotItem *, const QList< QwtLegendData > &)
void setBackgroundBrush(const QBrush &)
Set the background brush.
virtual QRect geometry() const
void setData(const QwtLegendData &)
void setFont(const QFont &)
A class which draws a legend inside the plot canvas.
QSizeF defaultSize() const
Default size.
virtual void drawLegendData(QPainter *painter, const QwtPlotItem *, const QwtLegendData &, const QRectF &) const
virtual QRect geometry(const QRectF &canvasRect) const
void draw(QPainter *painter, const QRectF &rect) const
Definition: qwt_text.cpp:560
virtual void invalidate()
Invalidate all internal caches.
void clearLegend()
Remove all items from the legend.
virtual void draw(QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &rect) const
virtual void drawBackground(QPainter *, const QRectF &rect) const
virtual bool isEmpty() const
void setTextPen(const QPen &)
Set the pen for drawing text labels.
void setMargin(int)
Set the margin around legend items.
TFSIMD_FORCE_INLINE const tfScalar & y() const
virtual QSize sizeHint() const
const QwtPlotItem * d_plotItem
void setMaxColumns(uint maxCols)
virtual int heightForWidth(const QwtLegendData &, int w) const
virtual int count() const
virtual ~QwtPlotLegendItem()
Destructor.
virtual QLayoutItem * itemAt(int index) const
The QwtDynGridLayout class lays out widgets in a grid, adjusting the number of columns and rows to th...
virtual Qt::Orientations expandingDirections() const
void setAlignment(Qt::Alignment)
Set the alignmnet.
QList< const QwtPlotItem * > plotItems() const
QSizeF textSize(const QFont &=QFont()) const
Definition: qwt_text.cpp:526
virtual QSize minimumSize() const
QBrush backgroundBrush() const
bool isEmpty() const
Definition: qwt_text.h:213
For QwtPlotLegendItem.
Definition: qwt_plot_item.h:85
void setBorderDistance(int numPixels)
Set the margin between the legend and the canvas border.
A class representing a text.
Definition: qwt_text.h:51
void setZ(double z)
Set the z value.
const QwtPlotLegendItem * d_legendItem
QwtGraphic icon() const
A paint device for scalable graphics.
Definition: qwt_graphic.h:74
TFSIMD_FORCE_INLINE const tfScalar & x() const
QwtPlotLegendItem::BackgroundMode backgroundMode
A scale map.
Definition: qwt_scale_map.h:30
virtual void itemChanged()
void setBorderPen(const QPen &)
double borderRadius() const
uintptr_t size
TFSIMD_FORCE_INLINE const tfScalar & w() const
virtual bool hasHeightForWidth() const
virtual int minimumHeightForWidth(int w) const
QwtText title() const
virtual void setGeometry(const QRect &r)
QwtLegendLayoutItem(const QwtPlotLegendItem *, const QwtPlotItem *)
bool isEmpty() const
const QwtLegendData & data() const
bool isValid() const
QwtPlotLegendItem()
Constructor.
Base class for items on the plot canvas.
Definition: qwt_plot_item.h:64
QList< QRect > legendGeometries(const QwtPlotItem *) const
virtual int heightForWidth(int w) const
bool isNull() const
void setItemInterest(ItemInterest, bool on=true)
int i
uint maxColumns() const
Return the upper limit for the number of columns.
Qt::Alignment alignment() const
double heightForWidth(double width, const QFont &=QFont()) const
Definition: qwt_text.cpp:490
Attributes of an entry on a legend.
virtual QLayoutItem * takeAt(int index)
virtual QSize sizeHint() const
void setMaxColumns(uint)
Limit the number of columns.


plotjuggler
Author(s): Davide Faconti
autogenerated on Sat Jul 6 2019 03:44:17