qwt_plot_legenditem.cpp
Go to the documentation of this file.
00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 #include "qwt_plot_legenditem.h"
00011 #include "qwt_dyngrid_layout.h"
00012 #include "qwt_scale_map.h"
00013 #include "qwt_painter.h"
00014 #include <qlayoutitem.h>
00015 #include <qpen.h>
00016 #include <qbrush.h>
00017 #include <qpainter.h>
00018 #include <qmath.h>
00019 
00020 class QwtLegendLayoutItem: public QLayoutItem
00021 {
00022 public:
00023     QwtLegendLayoutItem( const QwtPlotLegendItem *, const QwtPlotItem * );
00024     virtual ~QwtLegendLayoutItem();
00025 
00026     const QwtPlotItem *plotItem() const;
00027 
00028     void setData( const QwtLegendData & );
00029     const QwtLegendData &data() const;
00030 
00031     virtual Qt::Orientations expandingDirections() const;
00032     virtual QRect geometry() const;
00033     virtual bool hasHeightForWidth() const;
00034     virtual int heightForWidth( int w ) const;
00035     virtual bool isEmpty() const;
00036     virtual QSize maximumSize() const;
00037     virtual int minimumHeightForWidth( int w ) const;
00038     virtual QSize minimumSize() const;
00039     virtual void setGeometry( const QRect & r );
00040     virtual QSize sizeHint() const;
00041 
00042 private:
00043 
00044     const QwtPlotLegendItem *d_legendItem;
00045     const QwtPlotItem *d_plotItem;
00046     QwtLegendData d_data;
00047 
00048     QRect d_rect;
00049 };
00050 
00051 QwtLegendLayoutItem::QwtLegendLayoutItem( 
00052         const QwtPlotLegendItem *legendItem, const QwtPlotItem *plotItem ):
00053     d_legendItem( legendItem ),
00054     d_plotItem( plotItem)
00055 {
00056 }
00057 
00058 QwtLegendLayoutItem::~QwtLegendLayoutItem()
00059 {
00060 }
00061 
00062 const QwtPlotItem *QwtLegendLayoutItem::plotItem() const
00063 {
00064     return d_plotItem;
00065 }
00066 
00067 void QwtLegendLayoutItem::setData( const QwtLegendData &data )
00068 {
00069     d_data = data;
00070 }
00071 
00072 const QwtLegendData &QwtLegendLayoutItem::data() const
00073 {
00074     return d_data;
00075 }
00076 
00077 Qt::Orientations QwtLegendLayoutItem::expandingDirections() const
00078 {
00079     return Qt::Horizontal;
00080 }
00081 
00082 bool QwtLegendLayoutItem::hasHeightForWidth() const
00083 {
00084     return !d_data.title().isEmpty();
00085 }
00086 
00087 int QwtLegendLayoutItem::minimumHeightForWidth( int w ) const
00088 {
00089     return d_legendItem->heightForWidth( d_data, w );
00090 }
00091 
00092 int QwtLegendLayoutItem::heightForWidth( int w ) const
00093 {
00094     return d_legendItem->heightForWidth( d_data, w );
00095 }
00096 
00097 bool QwtLegendLayoutItem::isEmpty() const
00098 {
00099     return false;
00100 }
00101 
00102 QSize QwtLegendLayoutItem::maximumSize() const
00103 {
00104     return QSize( QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX );
00105 }
00106 
00107 QSize QwtLegendLayoutItem::minimumSize() const
00108 {
00109     return d_legendItem->minimumSize( d_data );
00110 }
00111 
00112 QSize QwtLegendLayoutItem::sizeHint() const
00113 {
00114     return minimumSize();
00115 }
00116 
00117 void QwtLegendLayoutItem::setGeometry( const QRect &rect )
00118 {
00119     d_rect = rect;
00120 }
00121 
00122 QRect QwtLegendLayoutItem::geometry() const
00123 {
00124     return d_rect;
00125 }
00126 
00127 class QwtPlotLegendItem::PrivateData
00128 {
00129 public:
00130     PrivateData():
00131         itemMargin( 4 ),
00132         itemSpacing( 4 ),
00133         borderRadius( 0.0 ),
00134         borderPen( Qt::NoPen ),
00135         backgroundBrush( Qt::NoBrush ),
00136         backgroundMode( QwtPlotLegendItem::LegendBackground ),
00137         borderDistance( 10 ),
00138         alignment( Qt::AlignRight | Qt::AlignBottom )
00139     {
00140         layout = new QwtDynGridLayout();
00141         layout->setMaxColumns( 2 );
00142 
00143         layout->setSpacing( 0 );
00144         layout->setContentsMargins( 0, 0, 0, 0 );
00145     }
00146 
00147     ~PrivateData()
00148     {
00149         delete layout;
00150     }
00151 
00152     QFont font;
00153     QPen textPen;
00154     int itemMargin;
00155     int itemSpacing;
00156 
00157     double borderRadius;
00158     QPen borderPen;
00159     QBrush backgroundBrush;
00160     QwtPlotLegendItem::BackgroundMode backgroundMode;
00161 
00162     int borderDistance;
00163     Qt::Alignment alignment;
00164 
00165     QMap< const QwtPlotItem *, QList<QwtLegendLayoutItem *> > map;
00166     QwtDynGridLayout *layout;
00167 };
00168 
00170 QwtPlotLegendItem::QwtPlotLegendItem():
00171     QwtPlotItem( QwtText( "Legend" ) )
00172 {
00173     d_data = new PrivateData;
00174 
00175     setItemInterest( QwtPlotItem::LegendInterest, true );
00176     setZ( 100.0 );
00177 }
00178 
00180 QwtPlotLegendItem::~QwtPlotLegendItem()
00181 {
00182     clearLegend();
00183     delete d_data;
00184 }
00185 
00187 int QwtPlotLegendItem::rtti() const
00188 {
00189     return QwtPlotItem::Rtti_PlotLegend;
00190 }
00191 
00205 void QwtPlotLegendItem::setAlignment( Qt::Alignment alignment )
00206 {
00207     if ( d_data->alignment != alignment )
00208     {
00209         d_data->alignment = alignment;
00210         itemChanged();
00211     }
00212 }
00213 
00218 Qt::Alignment QwtPlotLegendItem::alignment() const
00219 {
00220     return d_data->alignment;
00221 }
00222 
00233 void QwtPlotLegendItem::setMaxColumns( uint maxColumns )
00234 {
00235     if ( maxColumns != d_data->layout->maxColumns() )
00236     {
00237         d_data->layout->setMaxColumns( maxColumns );
00238         itemChanged();
00239     }
00240 }
00241 
00246 uint QwtPlotLegendItem::maxColumns() const
00247 {
00248     return d_data->layout->maxColumns();
00249 }
00250 
00259 void QwtPlotLegendItem::setMargin( int margin )
00260 {
00261     margin = qMax( margin, 0 );
00262     if ( margin != this->margin() )
00263     {
00264         d_data->layout->setContentsMargins( 
00265             margin, margin, margin, margin );
00266 
00267         itemChanged();
00268     }
00269 }
00270 
00275 int QwtPlotLegendItem::margin() const
00276 {
00277     int left;
00278     d_data->layout->getContentsMargins( &left, NULL, NULL, NULL );
00279 
00280     return left;
00281 }
00282 
00289 void QwtPlotLegendItem::setSpacing( int spacing )
00290 {
00291     spacing = qMax( spacing, 0 );
00292     if ( spacing != d_data->layout->spacing() )
00293     {
00294         d_data->layout->setSpacing( spacing );
00295         itemChanged();
00296     }
00297 }
00298 
00303 int QwtPlotLegendItem::spacing() const
00304 {
00305     return d_data->layout->spacing();
00306 }
00307 
00314 void QwtPlotLegendItem::setItemMargin( int margin )
00315 {
00316     margin = qMax( margin, 0 );
00317     if ( margin != d_data->itemMargin )
00318     {
00319         d_data->itemMargin = margin;
00320 
00321         d_data->layout->invalidate();
00322         itemChanged();
00323     }
00324 }
00325 
00330 int QwtPlotLegendItem::itemMargin() const
00331 {
00332     return d_data->itemMargin;
00333 }
00334 
00341 void QwtPlotLegendItem::setItemSpacing( int spacing )
00342 {
00343     spacing = qMax( spacing, 0 );
00344     if ( spacing != d_data->itemSpacing )
00345     {
00346         d_data->itemSpacing = spacing;
00347 
00348         d_data->layout->invalidate();
00349         itemChanged();
00350     }
00351 
00352 }
00353 
00358 int QwtPlotLegendItem::itemSpacing() const
00359 {
00360     return d_data->itemSpacing;
00361 }
00362 
00369 void QwtPlotLegendItem::setFont( const QFont &font )
00370 {
00371     if ( font != d_data->font )
00372     {
00373         d_data->font = font;
00374 
00375         d_data->layout->invalidate();
00376         itemChanged();
00377     }
00378 }
00379 
00384 QFont QwtPlotLegendItem::font() const
00385 {
00386     return d_data->font;
00387 }
00388 
00397 void QwtPlotLegendItem::setBorderDistance( int distance )
00398 {
00399     if ( distance < 0 )
00400         distance = -1;
00401 
00402     if ( distance != d_data->borderDistance )
00403     {
00404         d_data->borderDistance = distance;
00405         itemChanged();
00406     }
00407 }
00408 
00413 int QwtPlotLegendItem::borderDistance() const
00414 {
00415     return d_data->borderDistance;
00416 }
00417 
00424 void QwtPlotLegendItem::setBorderRadius( double radius )
00425 {
00426     radius = qMax( 0.0, radius );
00427 
00428     if ( radius != d_data->borderRadius )
00429     {
00430         d_data->borderRadius = radius;
00431         itemChanged();
00432     }
00433 }
00434 
00439 double QwtPlotLegendItem::borderRadius() const
00440 {
00441     return d_data->borderRadius;
00442 }
00443 
00450 void QwtPlotLegendItem::setBorderPen( const QPen &pen )
00451 {
00452     if ( d_data->borderPen != pen )
00453     {
00454         d_data->borderPen = pen;
00455         itemChanged();
00456     }
00457 }
00458 
00463 QPen QwtPlotLegendItem::borderPen() const
00464 {
00465     return d_data->borderPen;
00466 }
00467 
00476 void QwtPlotLegendItem::setBackgroundBrush( const QBrush &brush )
00477 {
00478     if ( d_data->backgroundBrush != brush )
00479     {
00480         d_data->backgroundBrush = brush;
00481         itemChanged();
00482     }
00483 }
00484 
00489 QBrush QwtPlotLegendItem::backgroundBrush() const
00490 {
00491     return d_data->backgroundBrush;
00492 }
00493 
00504 void QwtPlotLegendItem::setBackgroundMode( BackgroundMode mode )
00505 {
00506     if ( mode != d_data->backgroundMode )
00507     {
00508         d_data->backgroundMode = mode;
00509         itemChanged();
00510     }
00511 }
00512 
00517 QwtPlotLegendItem::BackgroundMode QwtPlotLegendItem::backgroundMode() const
00518 {
00519     return d_data->backgroundMode;
00520 }
00521 
00528 void QwtPlotLegendItem::setTextPen( const QPen &pen )
00529 {
00530     if ( d_data->textPen != pen )
00531     {
00532         d_data->textPen = pen;
00533         itemChanged();
00534     }
00535 }
00536 
00541 QPen QwtPlotLegendItem::textPen() const
00542 {
00543     return d_data->textPen;
00544 }
00545 
00554 void QwtPlotLegendItem::draw( QPainter *painter,
00555     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00556     const QRectF &canvasRect ) const
00557 {
00558     Q_UNUSED( xMap );
00559     Q_UNUSED( yMap );
00560 
00561     d_data->layout->setGeometry( geometry( canvasRect ) );
00562     if ( d_data->layout->geometry().isEmpty() )
00563     {
00564         // don't draw a legend when having no content
00565         return;
00566     }
00567 
00568     if ( d_data->backgroundMode == QwtPlotLegendItem::LegendBackground )
00569         drawBackground( painter, d_data->layout->geometry() );
00570     
00571     for ( int i = 0; i <  d_data->layout->count(); i++ )
00572     {
00573         const QwtLegendLayoutItem *layoutItem = 
00574             static_cast<QwtLegendLayoutItem *>( d_data->layout->itemAt( i ) );
00575 
00576         if ( d_data->backgroundMode == QwtPlotLegendItem::ItemBackground )
00577             drawBackground( painter, layoutItem->geometry() );
00578 
00579         painter->save();
00580 
00581         drawLegendData( painter, layoutItem->plotItem(),
00582             layoutItem->data(), layoutItem->geometry() );
00583 
00584         painter->restore();
00585     }
00586 }
00587 
00597 void QwtPlotLegendItem::drawBackground( 
00598     QPainter *painter, const QRectF &rect ) const
00599 {
00600     painter->save();
00601 
00602     painter->setPen( d_data->borderPen );
00603     painter->setBrush( d_data->backgroundBrush );
00604     
00605     const double radius = d_data->borderRadius;
00606     painter->drawRoundedRect( rect, radius, radius );
00607     
00608     painter->restore();
00609 }
00610 
00617 QRect QwtPlotLegendItem::geometry( const QRectF &canvasRect ) const
00618 {
00619     QRect rect;
00620     rect.setSize( d_data->layout->sizeHint() );
00621 
00622     int margin = d_data->borderDistance;
00623     if ( d_data->alignment & Qt::AlignHCenter )
00624     {
00625         int x = qRound( canvasRect.center().x() );
00626         rect.moveCenter( QPoint( x, rect.center().y() ) ); 
00627     }
00628     else if ( d_data->alignment & Qt::AlignRight )
00629     {
00630         rect.moveRight( qFloor( canvasRect.right() - margin ) );
00631     }
00632     else 
00633     {
00634         rect.moveLeft( qCeil( canvasRect.left() + margin ) );
00635     }
00636 
00637     if ( d_data->alignment & Qt::AlignVCenter )
00638     {
00639         int y = qRound( canvasRect.center().y() );
00640         rect.moveCenter( QPoint( rect.center().x(), y ) );
00641     }
00642     else if ( d_data->alignment & Qt::AlignBottom )
00643     {
00644         rect.moveBottom( qFloor( canvasRect.bottom() - margin ) );
00645     }
00646     else 
00647     {
00648         rect.moveTop( qCeil( canvasRect.top() + margin ) ); 
00649     }
00650 
00651     return rect;
00652 }
00653 
00661 void QwtPlotLegendItem::updateLegend( const QwtPlotItem *plotItem,
00662         const QList<QwtLegendData> &data )
00663 {
00664     if ( plotItem == NULL )
00665         return;
00666 
00667     QList<QwtLegendLayoutItem *> layoutItems;
00668 
00669     QMap<const QwtPlotItem *, QList<QwtLegendLayoutItem *> >::iterator it = 
00670         d_data->map.find( plotItem );
00671     if ( it != d_data->map.end() )
00672         layoutItems = it.value();
00673 
00674     bool changed = false;
00675 
00676     if ( data.size() != layoutItems.size() )
00677     {
00678         changed = true;
00679 
00680         for ( int i = 0; i < layoutItems.size(); i++ )
00681         {
00682             d_data->layout->removeItem( layoutItems[i] );
00683             delete layoutItems[i];
00684         }
00685         layoutItems.clear();
00686 
00687         if ( it != d_data->map.end() )
00688             d_data->map.remove( plotItem );
00689 
00690         if ( !data.isEmpty() )
00691         {
00692             for ( int i = 0; i < data.size(); i++ )
00693             {
00694                 QwtLegendLayoutItem *layoutItem = 
00695                     new QwtLegendLayoutItem( this, plotItem );
00696                 d_data->layout->addItem( layoutItem );
00697                 layoutItems += layoutItem;
00698             }
00699 
00700             d_data->map.insert( plotItem, layoutItems );
00701         }
00702     }
00703 
00704     for ( int i = 0; i < data.size(); i++ )
00705     {
00706         if ( layoutItems[i]->data().values() != data[i].values() )
00707         {
00708             layoutItems[i]->setData( data[i] );
00709             changed = true;
00710         }
00711     }
00712 
00713     if ( changed )
00714     {
00715         d_data->layout->invalidate();
00716         itemChanged();
00717     }
00718 }
00719 
00721 void QwtPlotLegendItem::clearLegend()
00722 {
00723     if ( !d_data->map.isEmpty() )
00724     {
00725         d_data->map.clear();
00726 
00727         for ( int i = d_data->layout->count() - 1; i >= 0; i-- )
00728             delete d_data->layout->takeAt( i );
00729 
00730         itemChanged();
00731     }
00732 }
00733 
00742 void QwtPlotLegendItem::drawLegendData( QPainter *painter,
00743     const QwtPlotItem *plotItem, const QwtLegendData &data, 
00744     const QRectF &rect ) const
00745 {
00746     Q_UNUSED( plotItem );
00747 
00748     const int m = d_data->itemMargin;
00749     const QRectF r = rect.toRect().adjusted( m, m, -m, -m );
00750 
00751     painter->setClipRect( r, Qt::IntersectClip );
00752 
00753     int titleOff = 0;
00754 
00755     const QwtGraphic graphic = data.icon();
00756     if ( !graphic.isEmpty() )
00757     {
00758         QRectF iconRect( r.topLeft(), graphic.defaultSize() );
00759 
00760         iconRect.moveCenter( 
00761             QPoint( iconRect.center().x(), rect.center().y() ) );
00762 
00763         graphic.render( painter, iconRect, Qt::KeepAspectRatio );
00764 
00765         titleOff += iconRect.width() + d_data->itemSpacing;
00766     }
00767 
00768     const QwtText text = data.title();
00769     if ( !text.isEmpty() )
00770     {
00771         painter->setPen( textPen() );
00772         painter->setFont( font() );
00773 
00774         const QRectF textRect = r.adjusted( titleOff, 0, 0, 0 );
00775         text.draw( painter, textRect );
00776     }
00777 }
00778 
00785 QSize QwtPlotLegendItem::minimumSize( const QwtLegendData &data ) const
00786 {
00787     QSize size( 2 * d_data->itemMargin, 2 * d_data->itemMargin );
00788 
00789     if ( !data.isValid() )
00790         return size;
00791 
00792     const QwtGraphic graphic = data.icon();
00793     const QwtText text = data.title();
00794 
00795     int w = 0;
00796     int h = 0;
00797 
00798     if ( !graphic.isNull() )
00799     {
00800         w = graphic.width();
00801         h = graphic.height();
00802     }
00803 
00804     if ( !text.isEmpty() )
00805     {
00806         const QSizeF sz = text.textSize( font() );
00807 
00808         w += qCeil( sz.width() );
00809         h = qMax( h, qCeil( sz.height() ) );
00810     }
00811 
00812     if ( graphic.width() > 0 && !text.isEmpty() )
00813         w += d_data->itemSpacing;
00814 
00815     size += QSize( w, h );
00816     return size;
00817 }
00818 
00824 int QwtPlotLegendItem::heightForWidth( 
00825     const QwtLegendData &data, int width ) const
00826 {
00827     width -= 2 * d_data->itemMargin;
00828 
00829     const QwtGraphic graphic = data.icon();
00830     const QwtText text = data.title();
00831 
00832     if ( text.isEmpty() )
00833         return graphic.height();
00834 
00835     if ( graphic.width() > 0 )
00836         width -= graphic.width() + d_data->itemSpacing;
00837 
00838     int h = text.heightForWidth( width, font() );
00839     h += 2 * d_data->itemMargin;
00840 
00841     return qMax( graphic.height(), h );
00842 }
00843 
00848 QList< const QwtPlotItem * > QwtPlotLegendItem::plotItems() const
00849 {
00850     return d_data->map.keys();
00851 }
00852 
00857 QList< QRect > QwtPlotLegendItem::legendGeometries( 
00858     const QwtPlotItem *plotItem ) const
00859 {
00860     QList<QwtLegendLayoutItem *> layoutItems;
00861 
00862     QMap<const QwtPlotItem *, QList<QwtLegendLayoutItem *> >::iterator it =
00863         d_data->map.find( plotItem );
00864     if ( it != d_data->map.end() )
00865         layoutItems = it.value();
00866 
00867     QList<QRect> geometries;
00868     for ( int i = 0; i < layoutItems.size(); i++ )
00869         geometries += layoutItems[i]->geometry();
00870 
00871     return geometries;
00872 }


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:56