地面站终端 App
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

611 lines
0 B

15 years ago
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
15 years ago
* 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_plot_marker.h"
15 years ago
#include "qwt_painter.h"
#include "qwt_scale_map.h"
#include "qwt_symbol.h"
#include "qwt_text.h"
#include "qwt_math.h"
#include <qpainter.h>
15 years ago
class QwtPlotMarker::PrivateData
{
public:
PrivateData():
labelAlignment( Qt::AlignCenter ),
labelOrientation( Qt::Horizontal ),
spacing( 2 ),
symbol( NULL ),
style( QwtPlotMarker::NoLine ),
xValue( 0.0 ),
yValue( 0.0 )
{
15 years ago
}
~PrivateData()
{
15 years ago
delete symbol;
}
QwtText label;
Qt::Alignment labelAlignment;
Qt::Orientation labelOrientation;
int spacing;
15 years ago
QPen pen;
const QwtSymbol *symbol;
15 years ago
LineStyle style;
double xValue;
double yValue;
};
//! Sets alignment to Qt::AlignCenter, and style to QwtPlotMarker::NoLine
QwtPlotMarker::QwtPlotMarker( const QString &title ):
QwtPlotItem( QwtText( title ) )
15 years ago
{
d_data = new PrivateData;
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 );
15 years ago
}
//! Destructor
QwtPlotMarker::~QwtPlotMarker()
{
delete d_data;
}
//! \return QwtPlotItem::Rtti_PlotMarker
int QwtPlotMarker::rtti() const
{
return QwtPlotItem::Rtti_PlotMarker;
}
//! Return Value
QPointF QwtPlotMarker::value() const
15 years ago
{
return QPointF( d_data->xValue, d_data->yValue );
15 years ago
}
//! Return x Value
double QwtPlotMarker::xValue() const
{
return d_data->xValue;
15 years ago
}
//! Return y Value
double QwtPlotMarker::yValue() const
{
return d_data->yValue;
15 years ago
}
//! Set Value
void QwtPlotMarker::setValue( const QPointF& pos )
15 years ago
{
setValue( pos.x(), pos.y() );
15 years ago
}
//! Set Value
void QwtPlotMarker::setValue( double x, double y )
15 years ago
{
if ( x != d_data->xValue || y != d_data->yValue )
{
d_data->xValue = x;
d_data->yValue = y;
itemChanged();
15 years ago
}
}
//! Set X Value
void QwtPlotMarker::setXValue( double x )
{
setValue( x, d_data->yValue );
15 years ago
}
//! Set Y Value
void QwtPlotMarker::setYValue( double y )
{
setValue( d_data->xValue, y );
15 years ago
}
/*!
Draw the marker
\param painter Painter
15 years ago
\param xMap x Scale Map
\param yMap y Scale Map
\param canvasRect Contents rectangle of the canvas in painter coordinates
15 years ago
*/
void QwtPlotMarker::draw( QPainter *painter,
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
const QRectF &canvasRect ) const
15 years ago
{
const QPointF pos( xMap.transform( d_data->xValue ),
yMap.transform( d_data->yValue ) );
15 years ago
// draw lines
drawLines( painter, canvasRect, pos );
15 years ago
// draw symbol
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 );
15 years ago
}
drawLabel( painter, canvasRect, pos );
}
15 years ago
/*!
Draw the lines marker
15 years ago
\param painter Painter
\param canvasRect Contents rectangle of the canvas in painter coordinates
\param pos Position of the marker, translated into widget coordinates
15 years ago
\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 );
}
}
15 years ago
/*!
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;
15 years ago
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;
}
15 years ago
else
{
alignPos.setX( canvasRect.center().x() );
}
break;
15 years ago
}
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;
}
15 years ago
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();
15 years ago
}
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 );
15 years ago
}
/*!
\brief Set the line style
\param style Line style.
15 years ago
\sa lineStyle()
*/
void QwtPlotMarker::setLineStyle( LineStyle style )
15 years ago
{
if ( style != d_data->style )
{
d_data->style = style;
legendChanged();
15 years ago
itemChanged();
}
}
/*!
\return the line style
\sa setLineStyle()
15 years ago
*/
QwtPlotMarker::LineStyle QwtPlotMarker::lineStyle() const
{
return d_data->style;
15 years ago
}
/*!
\brief Assign a symbol
\param symbol New symbol
15 years ago
\sa symbol()
*/
void QwtPlotMarker::setSymbol( const QwtSymbol *symbol )
15 years ago
{
if ( symbol != d_data->symbol )
{
delete d_data->symbol;
d_data->symbol = symbol;
if ( symbol )
setLegendIconSize( symbol->boundingRect().size() );
legendChanged();
itemChanged();
}
15 years ago
}
/*!
\return the symbol
\sa setSymbol(), QwtSymbol
*/
const QwtSymbol *QwtPlotMarker::symbol() const
{
return d_data->symbol;
15 years ago
}
/*!
\brief Set the label
\param label Label text
15 years ago
\sa label()
*/
void QwtPlotMarker::setLabel( const QwtText& label )
15 years ago
{
if ( label != d_data->label )
{
15 years ago
d_data->label = label;
itemChanged();
}
}
/*!
\return the label
\sa setLabel()
*/
QwtText QwtPlotMarker::label() const
{
return d_data->label;
15 years ago
}
/*!
\brief Set the alignment of the 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.
15 years ago
\param align Alignment.
\sa labelAlignment(), labelOrientation()
15 years ago
*/
void QwtPlotMarker::setLabelAlignment( Qt::Alignment align )
15 years ago
{
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 )
15 years ago
return;
d_data->spacing = spacing;
15 years ago
itemChanged();
}
/*!
\return the spacing
\sa setSpacing()
15 years ago
*/
int QwtPlotMarker::spacing() const
{
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 ) );
15 years ago
}
/*!
Specify a pen for the line.
\param pen New pen
15 years ago
\sa linePen()
*/
void QwtPlotMarker::setLinePen( const QPen &pen )
15 years ago
{
if ( pen != d_data->pen )
{
d_data->pen = pen;
legendChanged();
15 years ago
itemChanged();
}
}
/*!
\return the line pen
\sa setLinePen()
*/
const QPen &QwtPlotMarker::linePen() const
{
return d_data->pen;
15 years ago
}
QRectF QwtPlotMarker::boundingRect() const
15 years ago
{
return QRectF( d_data->xValue, d_data->yValue, 0.0, 0.0 );
15 years ago
}
/*!
\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;
}