Newer
Older
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_painter.h"
#include "qwt_scale_map.h"
#include "qwt_symbol.h"
#include "qwt_text.h"
#include "qwt_math.h"
class QwtPlotMarker::PrivateData
{
public:
PrivateData():
labelAlignment( Qt::AlignCenter ),
labelOrientation( Qt::Horizontal ),
spacing( 2 ),
symbol( NULL ),
style( QwtPlotMarker::NoLine ),
xValue( 0.0 ),
yValue( 0.0 )
{
Qt::Alignment labelAlignment;
Qt::Orientation labelOrientation;
int spacing;
LineStyle style;
double xValue;
double yValue;
};
//! Sets alignment to Qt::AlignCenter, and style to QwtPlotMarker::NoLine
QwtPlotMarker::QwtPlotMarker( const QString &title ):
QwtPlotItem( QwtText( title ) )
setZ( 30.0 );
}
//! Sets alignment to Qt::AlignCenter, and style to QwtPlotMarker::NoLine
QwtPlotMarker::QwtPlotMarker( const QwtText &title ):
QwtPlotItem( title )
{
d_data = new PrivateData;
setZ( 30.0 );
}
//! Destructor
QwtPlotMarker::~QwtPlotMarker()
{
delete d_data;
}
//! \return QwtPlotItem::Rtti_PlotMarker
int QwtPlotMarker::rtti() const
{
return QwtPlotItem::Rtti_PlotMarker;
}
//! Return Value
double QwtPlotMarker::xValue() const
{
return d_data->xValue;
double QwtPlotMarker::yValue() const
{
return d_data->yValue;
d_data->xValue = x;
d_data->yValue = y;
itemChanged();
\param canvasRect Contents rectangle of the canvas in painter coordinates
void QwtPlotMarker::draw( QPainter *painter,
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
const QRectF &canvasRect ) const
const QPointF pos( xMap.transform( d_data->xValue ),
yMap.transform( d_data->yValue ) );
if ( d_data->symbol &&
( d_data->symbol->style() != QwtSymbol::NoSymbol ) )
{
const QSizeF sz = d_data->symbol->size();
const QRectF clipRect = canvasRect.adjusted(
-sz.width(), -sz.height(), sz.width(), sz.height() );
if ( clipRect.contains( pos ) )
d_data->symbol->drawSymbol( painter, pos );
\param painter Painter
\param canvasRect Contents rectangle of the canvas in painter coordinates
\param pos Position of the marker, translated into widget coordinates
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
\sa drawLabel(), QwtSymbol::drawSymbol()
*/
void QwtPlotMarker::drawLines( QPainter *painter,
const QRectF &canvasRect, const QPointF &pos ) const
{
if ( d_data->style == NoLine )
return;
const bool doAlign = QwtPainter::roundingAlignment( painter );
painter->setPen( d_data->pen );
if ( d_data->style == QwtPlotMarker::HLine ||
d_data->style == QwtPlotMarker::Cross )
{
double y = pos.y();
if ( doAlign )
y = qRound( y );
QwtPainter::drawLine( painter, canvasRect.left(),
y, canvasRect.right() - 1.0, y );
}
if ( d_data->style == QwtPlotMarker::VLine ||
d_data->style == QwtPlotMarker::Cross )
{
double x = pos.x();
if ( doAlign )
x = qRound( x );
QwtPainter::drawLine( painter, x,
canvasRect.top(), x, canvasRect.bottom() - 1.0 );
}
}
/*!
Align and draw the text label of the marker
\param painter Painter
\param canvasRect Contents rectangle of the canvas in painter coordinates
\param pos Position of the marker, translated into widget coordinates
\sa drawLabel(), QwtSymbol::drawSymbol()
*/
void QwtPlotMarker::drawLabel( QPainter *painter,
const QRectF &canvasRect, const QPointF &pos ) const
{
if ( d_data->label.isEmpty() )
return;
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
Qt::Alignment align = d_data->labelAlignment;
QPointF alignPos = pos;
QSizeF symbolOff( 0, 0 );
switch ( d_data->style )
{
case QwtPlotMarker::VLine:
{
// In VLine-style the y-position is pointless and
// the alignment flags are relative to the canvas
if ( d_data->labelAlignment & Qt::AlignTop )
{
alignPos.setY( canvasRect.top() );
align &= ~Qt::AlignTop;
align |= Qt::AlignBottom;
}
else if ( d_data->labelAlignment & Qt::AlignBottom )
{
// In HLine-style the x-position is pointless and
// the alignment flags are relative to the canvas
alignPos.setY( canvasRect.bottom() - 1 );
align &= ~Qt::AlignBottom;
align |= Qt::AlignTop;
}
else
{
alignPos.setY( canvasRect.center().y() );
}
break;
}
case QwtPlotMarker::HLine:
{
if ( d_data->labelAlignment & Qt::AlignLeft )
{
alignPos.setX( canvasRect.left() );
align &= ~Qt::AlignLeft;
align |= Qt::AlignRight;
}
else if ( d_data->labelAlignment & Qt::AlignRight )
{
alignPos.setX( canvasRect.right() - 1 );
align &= ~Qt::AlignRight;
align |= Qt::AlignLeft;
}
{
alignPos.setX( canvasRect.center().x() );
}
break;
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
default:
{
if ( d_data->symbol &&
( d_data->symbol->style() != QwtSymbol::NoSymbol ) )
{
symbolOff = d_data->symbol->size() + QSizeF( 1, 1 );
symbolOff /= 2;
}
}
}
qreal pw2 = d_data->pen.widthF() / 2.0;
if ( pw2 == 0.0 )
pw2 = 0.5;
const int spacing = d_data->spacing;
const qreal xOff = qMax( pw2, symbolOff.width() );
const qreal yOff = qMax( pw2, symbolOff.height() );
const QSizeF textSize = d_data->label.textSize( painter->font() );
if ( align & Qt::AlignLeft )
{
alignPos.rx() -= xOff + spacing;
if ( d_data->labelOrientation == Qt::Vertical )
alignPos.rx() -= textSize.height();
else
alignPos.rx() -= textSize.width();
}
else if ( align & Qt::AlignRight )
{
alignPos.rx() += xOff + spacing;
}
else
{
if ( d_data->labelOrientation == Qt::Vertical )
alignPos.rx() -= textSize.height() / 2;
else
alignPos.rx() -= textSize.width() / 2;
}
if ( align & Qt::AlignTop )
{
alignPos.ry() -= yOff + spacing;
if ( d_data->labelOrientation != Qt::Vertical )
alignPos.ry() -= textSize.height();
}
else if ( align & Qt::AlignBottom )
{
alignPos.ry() += yOff + spacing;
if ( d_data->labelOrientation == Qt::Vertical )
alignPos.ry() += textSize.width();
else
{
if ( d_data->labelOrientation == Qt::Vertical )
alignPos.ry() += textSize.width() / 2;
else
alignPos.ry() -= textSize.height() / 2;
}
painter->translate( alignPos.x(), alignPos.y() );
if ( d_data->labelOrientation == Qt::Vertical )
painter->rotate( -90.0 );
const QRectF textRect( 0, 0, textSize.width(), textSize.height() );
d_data->label.draw( painter, textRect );
if ( style != d_data->style )
{
d_data->style = style;
legendChanged();
itemChanged();
}
}
/*!
\return the line style
QwtPlotMarker::LineStyle QwtPlotMarker::lineStyle() const
{
return d_data->style;
if ( symbol != d_data->symbol )
{
delete d_data->symbol;
d_data->symbol = symbol;
if ( symbol )
setLegendIconSize( symbol->boundingRect().size() );
legendChanged();
itemChanged();
}
}
/*!
\return the symbol
\sa setSymbol(), QwtSymbol
*/
d_data->label = label;
itemChanged();
}
}
/*!
\return the label
\sa setLabel()
*/
QwtText QwtPlotMarker::label() const
{
return d_data->label;
In case of QwtPlotMarker::HLine the alignment is relative to the
y position of the marker, but the horizontal flags correspond to the
canvas rectangle. In case of QwtPlotMarker::VLine the alignment is
relative to the x position of the marker, but the vertical flags
correspond to the canvas rectangle.
In all other styles the alignment is relative to the marker's position.
\param align Alignment.
\sa labelAlignment(), labelOrientation()
void QwtPlotMarker::setLabelAlignment( Qt::Alignment align )
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
if ( align != d_data->labelAlignment )
{
d_data->labelAlignment = align;
itemChanged();
}
}
/*!
\return the label alignment
\sa setLabelAlignment(), setLabelOrientation()
*/
Qt::Alignment QwtPlotMarker::labelAlignment() const
{
return d_data->labelAlignment;
}
/*!
\brief Set the orientation of the label
When orientation is Qt::Vertical the label is rotated by 90.0 degrees
( from bottom to top ).
\param orientation Orientation of the label
\sa labelOrientation(), setLabelAlignment()
*/
void QwtPlotMarker::setLabelOrientation( Qt::Orientation orientation )
{
if ( orientation != d_data->labelOrientation )
{
d_data->labelOrientation = orientation;
itemChanged();
}
}
/*!
\return the label orientation
\sa setLabelOrientation(), labelAlignment()
*/
Qt::Orientation QwtPlotMarker::labelOrientation() const
{
return d_data->labelOrientation;
}
/*!
\brief Set the spacing
When the label is not centered on the marker position, the spacing
is the distance between the position and the label.
\param spacing Spacing
\sa spacing(), setLabelAlignment()
*/
void QwtPlotMarker::setSpacing( int spacing )
{
if ( spacing < 0 )
spacing = 0;
if ( spacing == d_data->spacing )
return d_data->spacing;
}
/*!
Build and assign a line pen
In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it
non cosmetic ( see QPen::isCosmetic() ). This method has been introduced
to hide this incompatibility.
\param color Pen color
\param width Pen width
\param style Pen style
\sa pen(), brush()
*/
void QwtPlotMarker::setLinePen( const QColor &color, qreal width, Qt::PenStyle style )
{
setLinePen( QPen( color, width, style ) );
if ( pen != d_data->pen )
{
d_data->pen = pen;
legendChanged();
itemChanged();
}
}
/*!
\return the line pen
\sa setLinePen()
*/
const QPen &QwtPlotMarker::linePen() const
{
return d_data->pen;
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
/*!
\return Icon representing the marker on the legend
\param index Index of the legend entry
( usually there is only one )
\param size Icon size
\sa setLegendIconSize(), legendData()
*/
QwtGraphic QwtPlotMarker::legendIcon( int index,
const QSizeF &size ) const
{
Q_UNUSED( index );
if ( size.isEmpty() )
return QwtGraphic();
QwtGraphic icon;
icon.setDefaultSize( size );
icon.setRenderHint( QwtGraphic::RenderPensUnscaled, true );
QPainter painter( &icon );
painter.setRenderHint( QPainter::Antialiasing,
testRenderHint( QwtPlotItem::RenderAntialiased ) );
if ( d_data->style != QwtPlotMarker::NoLine )
{
painter.setPen( d_data->pen );
if ( d_data->style == QwtPlotMarker::HLine ||
d_data->style == QwtPlotMarker::Cross )
{
const double y = 0.5 * size.height();
QwtPainter::drawLine( &painter,
0.0, y, size.width(), y );
}
if ( d_data->style == QwtPlotMarker::VLine ||
d_data->style == QwtPlotMarker::Cross )
{
const double x = 0.5 * size.width();
QwtPainter::drawLine( &painter,
x, 0.0, x, size.height() );
}
}
if ( d_data->symbol )
{
const QRect r( 0.0, 0.0, size.width(), size.height() );
d_data->symbol->drawSymbol( &painter, r );
}
return icon;
}