00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_plot_marker.h"
00011 #include "qwt_painter.h"
00012 #include "qwt_scale_map.h"
00013 #include "qwt_symbol.h"
00014 #include "qwt_text.h"
00015 #include "qwt_math.h"
00016 #include <qpainter.h>
00017
00018 class QwtPlotMarker::PrivateData
00019 {
00020 public:
00021 PrivateData():
00022 labelAlignment( Qt::AlignCenter ),
00023 labelOrientation( Qt::Horizontal ),
00024 spacing( 2 ),
00025 symbol( NULL ),
00026 style( QwtPlotMarker::NoLine ),
00027 xValue( 0.0 ),
00028 yValue( 0.0 )
00029 {
00030 }
00031
00032 ~PrivateData()
00033 {
00034 delete symbol;
00035 }
00036
00037 QwtText label;
00038 Qt::Alignment labelAlignment;
00039 Qt::Orientation labelOrientation;
00040 int spacing;
00041
00042 QPen pen;
00043 const QwtSymbol *symbol;
00044 LineStyle style;
00045
00046 double xValue;
00047 double yValue;
00048 };
00049
00051 QwtPlotMarker::QwtPlotMarker( const QString &title ):
00052 QwtPlotItem( QwtText( title ) )
00053 {
00054 d_data = new PrivateData;
00055 setZ( 30.0 );
00056 }
00057
00059 QwtPlotMarker::QwtPlotMarker( const QwtText &title ):
00060 QwtPlotItem( title )
00061 {
00062 d_data = new PrivateData;
00063 setZ( 30.0 );
00064 }
00065
00067 QwtPlotMarker::~QwtPlotMarker()
00068 {
00069 delete d_data;
00070 }
00071
00073 int QwtPlotMarker::rtti() const
00074 {
00075 return QwtPlotItem::Rtti_PlotMarker;
00076 }
00077
00079 QPointF QwtPlotMarker::value() const
00080 {
00081 return QPointF( d_data->xValue, d_data->yValue );
00082 }
00083
00085 double QwtPlotMarker::xValue() const
00086 {
00087 return d_data->xValue;
00088 }
00089
00091 double QwtPlotMarker::yValue() const
00092 {
00093 return d_data->yValue;
00094 }
00095
00097 void QwtPlotMarker::setValue( const QPointF& pos )
00098 {
00099 setValue( pos.x(), pos.y() );
00100 }
00101
00103 void QwtPlotMarker::setValue( double x, double y )
00104 {
00105 if ( x != d_data->xValue || y != d_data->yValue )
00106 {
00107 d_data->xValue = x;
00108 d_data->yValue = y;
00109 itemChanged();
00110 }
00111 }
00112
00114 void QwtPlotMarker::setXValue( double x )
00115 {
00116 setValue( x, d_data->yValue );
00117 }
00118
00120 void QwtPlotMarker::setYValue( double y )
00121 {
00122 setValue( d_data->xValue, y );
00123 }
00124
00133 void QwtPlotMarker::draw( QPainter *painter,
00134 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00135 const QRectF &canvasRect ) const
00136 {
00137 const QPointF pos( xMap.transform( d_data->xValue ),
00138 yMap.transform( d_data->yValue ) );
00139
00140 drawLines( painter, canvasRect, pos );
00141 drawSymbol( painter, canvasRect, pos );
00142 drawLabel( painter, canvasRect, pos );
00143 }
00144
00154 void QwtPlotMarker::drawLines( QPainter *painter,
00155 const QRectF &canvasRect, const QPointF &pos ) const
00156 {
00157 if ( d_data->style == NoLine )
00158 return;
00159
00160 const bool doAlign = QwtPainter::roundingAlignment( painter );
00161
00162 painter->setPen( d_data->pen );
00163 if ( d_data->style == QwtPlotMarker::HLine ||
00164 d_data->style == QwtPlotMarker::Cross )
00165 {
00166 double y = pos.y();
00167 if ( doAlign )
00168 y = qRound( y );
00169
00170 QwtPainter::drawLine( painter, canvasRect.left(),
00171 y, canvasRect.right() - 1.0, y );
00172 }
00173 if ( d_data->style == QwtPlotMarker::VLine ||
00174 d_data->style == QwtPlotMarker::Cross )
00175 {
00176 double x = pos.x();
00177 if ( doAlign )
00178 x = qRound( x );
00179
00180 QwtPainter::drawLine( painter, x,
00181 canvasRect.top(), x, canvasRect.bottom() - 1.0 );
00182 }
00183 }
00184
00194 void QwtPlotMarker::drawSymbol( QPainter *painter,
00195 const QRectF &canvasRect, const QPointF &pos ) const
00196 {
00197 if ( d_data->symbol == NULL )
00198 return;
00199
00200 const QwtSymbol &symbol = *d_data->symbol;
00201
00202 if ( symbol.style() != QwtSymbol::NoSymbol )
00203 {
00204 const QSizeF sz = symbol.size();
00205
00206 const QRectF clipRect = canvasRect.adjusted(
00207 -sz.width(), -sz.height(), sz.width(), sz.height() );
00208
00209 if ( clipRect.contains( pos ) )
00210 symbol.drawSymbol( painter, pos );
00211 }
00212 }
00213
00223 void QwtPlotMarker::drawLabel( QPainter *painter,
00224 const QRectF &canvasRect, const QPointF &pos ) const
00225 {
00226 if ( d_data->label.isEmpty() )
00227 return;
00228
00229 Qt::Alignment align = d_data->labelAlignment;
00230 QPointF alignPos = pos;
00231
00232 QSizeF symbolOff( 0, 0 );
00233
00234 switch ( d_data->style )
00235 {
00236 case QwtPlotMarker::VLine:
00237 {
00238
00239
00240
00241 if ( d_data->labelAlignment & Qt::AlignTop )
00242 {
00243 alignPos.setY( canvasRect.top() );
00244 align &= ~Qt::AlignTop;
00245 align |= Qt::AlignBottom;
00246 }
00247 else if ( d_data->labelAlignment & Qt::AlignBottom )
00248 {
00249
00250
00251
00252 alignPos.setY( canvasRect.bottom() - 1 );
00253 align &= ~Qt::AlignBottom;
00254 align |= Qt::AlignTop;
00255 }
00256 else
00257 {
00258 alignPos.setY( canvasRect.center().y() );
00259 }
00260 break;
00261 }
00262 case QwtPlotMarker::HLine:
00263 {
00264 if ( d_data->labelAlignment & Qt::AlignLeft )
00265 {
00266 alignPos.setX( canvasRect.left() );
00267 align &= ~Qt::AlignLeft;
00268 align |= Qt::AlignRight;
00269 }
00270 else if ( d_data->labelAlignment & Qt::AlignRight )
00271 {
00272 alignPos.setX( canvasRect.right() - 1 );
00273 align &= ~Qt::AlignRight;
00274 align |= Qt::AlignLeft;
00275 }
00276 else
00277 {
00278 alignPos.setX( canvasRect.center().x() );
00279 }
00280 break;
00281 }
00282 default:
00283 {
00284 if ( d_data->symbol &&
00285 ( d_data->symbol->style() != QwtSymbol::NoSymbol ) )
00286 {
00287 symbolOff = d_data->symbol->size() + QSizeF( 1, 1 );
00288 symbolOff /= 2;
00289 }
00290 }
00291 }
00292
00293 qreal pw2 = d_data->pen.widthF() / 2.0;
00294 if ( pw2 == 0.0 )
00295 pw2 = 0.5;
00296
00297 const int spacing = d_data->spacing;
00298
00299 const qreal xOff = qMax( pw2, symbolOff.width() );
00300 const qreal yOff = qMax( pw2, symbolOff.height() );
00301
00302 const QSizeF textSize = d_data->label.textSize( painter->font() );
00303
00304 if ( align & Qt::AlignLeft )
00305 {
00306 alignPos.rx() -= xOff + spacing;
00307 if ( d_data->labelOrientation == Qt::Vertical )
00308 alignPos.rx() -= textSize.height();
00309 else
00310 alignPos.rx() -= textSize.width();
00311 }
00312 else if ( align & Qt::AlignRight )
00313 {
00314 alignPos.rx() += xOff + spacing;
00315 }
00316 else
00317 {
00318 if ( d_data->labelOrientation == Qt::Vertical )
00319 alignPos.rx() -= textSize.height() / 2;
00320 else
00321 alignPos.rx() -= textSize.width() / 2;
00322 }
00323
00324 if ( align & Qt::AlignTop )
00325 {
00326 alignPos.ry() -= yOff + spacing;
00327 if ( d_data->labelOrientation != Qt::Vertical )
00328 alignPos.ry() -= textSize.height();
00329 }
00330 else if ( align & Qt::AlignBottom )
00331 {
00332 alignPos.ry() += yOff + spacing;
00333 if ( d_data->labelOrientation == Qt::Vertical )
00334 alignPos.ry() += textSize.width();
00335 }
00336 else
00337 {
00338 if ( d_data->labelOrientation == Qt::Vertical )
00339 alignPos.ry() += textSize.width() / 2;
00340 else
00341 alignPos.ry() -= textSize.height() / 2;
00342 }
00343
00344 painter->translate( alignPos.x(), alignPos.y() );
00345 if ( d_data->labelOrientation == Qt::Vertical )
00346 painter->rotate( -90.0 );
00347
00348 const QRectF textRect( 0, 0, textSize.width(), textSize.height() );
00349 d_data->label.draw( painter, textRect );
00350 }
00351
00357 void QwtPlotMarker::setLineStyle( LineStyle style )
00358 {
00359 if ( style != d_data->style )
00360 {
00361 d_data->style = style;
00362
00363 legendChanged();
00364 itemChanged();
00365 }
00366 }
00367
00372 QwtPlotMarker::LineStyle QwtPlotMarker::lineStyle() const
00373 {
00374 return d_data->style;
00375 }
00376
00382 void QwtPlotMarker::setSymbol( const QwtSymbol *symbol )
00383 {
00384 if ( symbol != d_data->symbol )
00385 {
00386 delete d_data->symbol;
00387 d_data->symbol = symbol;
00388
00389 if ( symbol )
00390 setLegendIconSize( symbol->boundingRect().size() );
00391
00392 legendChanged();
00393 itemChanged();
00394 }
00395 }
00396
00401 const QwtSymbol *QwtPlotMarker::symbol() const
00402 {
00403 return d_data->symbol;
00404 }
00405
00411 void QwtPlotMarker::setLabel( const QwtText& label )
00412 {
00413 if ( label != d_data->label )
00414 {
00415 d_data->label = label;
00416 itemChanged();
00417 }
00418 }
00419
00424 QwtText QwtPlotMarker::label() const
00425 {
00426 return d_data->label;
00427 }
00428
00443 void QwtPlotMarker::setLabelAlignment( Qt::Alignment align )
00444 {
00445 if ( align != d_data->labelAlignment )
00446 {
00447 d_data->labelAlignment = align;
00448 itemChanged();
00449 }
00450 }
00451
00456 Qt::Alignment QwtPlotMarker::labelAlignment() const
00457 {
00458 return d_data->labelAlignment;
00459 }
00460
00471 void QwtPlotMarker::setLabelOrientation( Qt::Orientation orientation )
00472 {
00473 if ( orientation != d_data->labelOrientation )
00474 {
00475 d_data->labelOrientation = orientation;
00476 itemChanged();
00477 }
00478 }
00479
00484 Qt::Orientation QwtPlotMarker::labelOrientation() const
00485 {
00486 return d_data->labelOrientation;
00487 }
00488
00498 void QwtPlotMarker::setSpacing( int spacing )
00499 {
00500 if ( spacing < 0 )
00501 spacing = 0;
00502
00503 if ( spacing == d_data->spacing )
00504 return;
00505
00506 d_data->spacing = spacing;
00507 itemChanged();
00508 }
00509
00514 int QwtPlotMarker::spacing() const
00515 {
00516 return d_data->spacing;
00517 }
00518
00532 void QwtPlotMarker::setLinePen( const QColor &color, qreal width, Qt::PenStyle style )
00533 {
00534 setLinePen( QPen( color, width, style ) );
00535 }
00536
00543 void QwtPlotMarker::setLinePen( const QPen &pen )
00544 {
00545 if ( pen != d_data->pen )
00546 {
00547 d_data->pen = pen;
00548
00549 legendChanged();
00550 itemChanged();
00551 }
00552 }
00553
00558 const QPen &QwtPlotMarker::linePen() const
00559 {
00560 return d_data->pen;
00561 }
00562
00563 QRectF QwtPlotMarker::boundingRect() const
00564 {
00565 return QRectF( d_data->xValue, d_data->yValue, 0.0, 0.0 );
00566 }
00567
00577 QwtGraphic QwtPlotMarker::legendIcon( int index,
00578 const QSizeF &size ) const
00579 {
00580 Q_UNUSED( index );
00581
00582 if ( size.isEmpty() )
00583 return QwtGraphic();
00584
00585 QwtGraphic icon;
00586 icon.setDefaultSize( size );
00587 icon.setRenderHint( QwtGraphic::RenderPensUnscaled, true );
00588
00589 QPainter painter( &icon );
00590 painter.setRenderHint( QPainter::Antialiasing,
00591 testRenderHint( QwtPlotItem::RenderAntialiased ) );
00592
00593 if ( d_data->style != QwtPlotMarker::NoLine )
00594 {
00595 painter.setPen( d_data->pen );
00596
00597 if ( d_data->style == QwtPlotMarker::HLine ||
00598 d_data->style == QwtPlotMarker::Cross )
00599 {
00600 const double y = 0.5 * size.height();
00601
00602 QwtPainter::drawLine( &painter,
00603 0.0, y, size.width(), y );
00604 }
00605
00606 if ( d_data->style == QwtPlotMarker::VLine ||
00607 d_data->style == QwtPlotMarker::Cross )
00608 {
00609 const double x = 0.5 * size.width();
00610
00611 QwtPainter::drawLine( &painter,
00612 x, 0.0, x, size.height() );
00613 }
00614 }
00615
00616 if ( d_data->symbol )
00617 {
00618 const QRect r( 0.0, 0.0, size.width(), size.height() );
00619 d_data->symbol->drawSymbol( &painter, r );
00620 }
00621
00622 return icon;
00623 }
00624