273 lines
6.2 KiB
C++
273 lines
6.2 KiB
C++
|
/* -*- 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_plot_textlabel.h"
|
||
|
#include "qwt_painter.h"
|
||
|
#include "qwt_scale_map.h"
|
||
|
#include <qpainter.h>
|
||
|
#include <qpixmap.h>
|
||
|
#include <qmath.h>
|
||
|
|
||
|
static QRect qwtItemRect( int renderFlags,
|
||
|
const QRectF &rect, const QSizeF &itemSize )
|
||
|
{
|
||
|
int x;
|
||
|
if ( renderFlags & Qt::AlignLeft )
|
||
|
{
|
||
|
x = rect.left();
|
||
|
}
|
||
|
else if ( renderFlags & Qt::AlignRight )
|
||
|
{
|
||
|
x = rect.right() - itemSize.width();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
x = rect.center().x() - 0.5 * itemSize.width();
|
||
|
}
|
||
|
|
||
|
int y;
|
||
|
if ( renderFlags & Qt::AlignTop )
|
||
|
{
|
||
|
y = rect.top();
|
||
|
}
|
||
|
else if ( renderFlags & Qt::AlignBottom )
|
||
|
{
|
||
|
y = rect.bottom() - itemSize.height();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
y = rect.center().y() - 0.5 * itemSize.height();
|
||
|
}
|
||
|
|
||
|
return QRect( x, y, itemSize.width(), itemSize.height() );
|
||
|
}
|
||
|
|
||
|
class QwtPlotTextLabel::PrivateData
|
||
|
{
|
||
|
public:
|
||
|
PrivateData():
|
||
|
margin( 5 )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
QwtText text;
|
||
|
int margin;
|
||
|
|
||
|
QPixmap pixmap;
|
||
|
};
|
||
|
|
||
|
/*!
|
||
|
\brief Constructor
|
||
|
|
||
|
Initializes an text label with an empty text
|
||
|
|
||
|
Sets the following item attributes:
|
||
|
|
||
|
- QwtPlotItem::AutoScale: true
|
||
|
- QwtPlotItem::Legend: false
|
||
|
|
||
|
The z value is initialized by 150
|
||
|
|
||
|
\sa QwtPlotItem::setItemAttribute(), QwtPlotItem::setZ()
|
||
|
*/
|
||
|
|
||
|
QwtPlotTextLabel::QwtPlotTextLabel():
|
||
|
QwtPlotItem( QwtText( "Label" ) )
|
||
|
{
|
||
|
d_data = new PrivateData;
|
||
|
|
||
|
setItemAttribute( QwtPlotItem::AutoScale, false );
|
||
|
setItemAttribute( QwtPlotItem::Legend, false );
|
||
|
|
||
|
setZ( 150 );
|
||
|
}
|
||
|
|
||
|
//! Destructor
|
||
|
QwtPlotTextLabel::~QwtPlotTextLabel()
|
||
|
{
|
||
|
delete d_data;
|
||
|
}
|
||
|
|
||
|
//! \return QwtPlotItem::Rtti_PlotTextLabel
|
||
|
int QwtPlotTextLabel::rtti() const
|
||
|
{
|
||
|
return QwtPlotItem::Rtti_PlotTextLabel;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Set the text
|
||
|
|
||
|
The label will be aligned to the plot canvas according to
|
||
|
the alignment flags of text.
|
||
|
|
||
|
\param text Text to be displayed
|
||
|
|
||
|
\sa text(), QwtText::renderFlags()
|
||
|
*/
|
||
|
void QwtPlotTextLabel::setText( const QwtText &text )
|
||
|
{
|
||
|
if ( d_data->text != text )
|
||
|
{
|
||
|
d_data->text = text;
|
||
|
|
||
|
invalidateCache();
|
||
|
itemChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\return Text to be displayed
|
||
|
\sa setText()
|
||
|
*/
|
||
|
QwtText QwtPlotTextLabel::text() const
|
||
|
{
|
||
|
return d_data->text;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Set the margin
|
||
|
|
||
|
The margin is the distance between the contentsRect()
|
||
|
of the plot canvas and the rectangle where the label can
|
||
|
be displayed.
|
||
|
|
||
|
\param margin Margin
|
||
|
|
||
|
\sa margin(), textRect()
|
||
|
*/
|
||
|
void QwtPlotTextLabel::setMargin( int margin )
|
||
|
{
|
||
|
margin = qMax( margin, 0 );
|
||
|
if ( d_data->margin != margin )
|
||
|
{
|
||
|
d_data->margin = margin;
|
||
|
itemChanged();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\return Margin added to the contentsMargins() of the canvas
|
||
|
\sa setMargin()
|
||
|
*/
|
||
|
int QwtPlotTextLabel::margin() const
|
||
|
{
|
||
|
return d_data->margin;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Draw the text label
|
||
|
|
||
|
\param painter Painter
|
||
|
\param xMap x Scale Map
|
||
|
\param yMap y Scale Map
|
||
|
\param canvasRect Contents rectangle of the canvas in painter coordinates
|
||
|
|
||
|
\sa textRect()
|
||
|
*/
|
||
|
|
||
|
void QwtPlotTextLabel::draw( QPainter *painter,
|
||
|
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
|
||
|
const QRectF &canvasRect ) const
|
||
|
{
|
||
|
Q_UNUSED( xMap );
|
||
|
Q_UNUSED( yMap );
|
||
|
|
||
|
const int m = d_data->margin;
|
||
|
|
||
|
const QRectF rect = textRect( canvasRect.adjusted( m, m, -m, -m ),
|
||
|
d_data->text.textSize( painter->font() ) );
|
||
|
|
||
|
bool doCache = QwtPainter::roundingAlignment( painter );
|
||
|
if ( doCache )
|
||
|
{
|
||
|
switch( painter->paintEngine()->type() )
|
||
|
{
|
||
|
case QPaintEngine::Picture:
|
||
|
case QPaintEngine::User: // usually QwtGraphic
|
||
|
{
|
||
|
// don't use a cache for record/replay devices
|
||
|
doCache = false;
|
||
|
break;
|
||
|
}
|
||
|
default:;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( doCache )
|
||
|
{
|
||
|
// when the paint device is aligning it is not one
|
||
|
// where scalability matters ( PDF, SVG ).
|
||
|
// As rendering a text label is an expensive operation
|
||
|
// we use a cache.
|
||
|
|
||
|
int pw = 0;
|
||
|
if ( d_data->text.borderPen().style() != Qt::NoPen )
|
||
|
pw = qMax( d_data->text.borderPen().width(), 1 );
|
||
|
|
||
|
QRect pixmapRect;
|
||
|
pixmapRect.setLeft( qFloor( rect.left() ) - pw );
|
||
|
pixmapRect.setTop( qFloor( rect.top() ) - pw );
|
||
|
pixmapRect.setRight( qCeil( rect.right() ) + pw );
|
||
|
pixmapRect.setBottom( qCeil( rect.bottom() ) + pw );
|
||
|
|
||
|
#define QWT_HIGH_DPI 1
|
||
|
|
||
|
#if QT_VERSION >= 0x050100 && QWT_HIGH_DPI
|
||
|
const qreal pixelRatio = painter->device()->devicePixelRatio();
|
||
|
const QSize scaledSize = pixmapRect.size() * pixelRatio;
|
||
|
#else
|
||
|
const QSize scaledSize = pixmapRect.size();
|
||
|
#endif
|
||
|
if ( d_data->pixmap.isNull() ||
|
||
|
( scaledSize != d_data->pixmap.size() ) )
|
||
|
{
|
||
|
d_data->pixmap = QPixmap( scaledSize );
|
||
|
#if QT_VERSION >= 0x050100 && QWT_HIGH_DPI
|
||
|
d_data->pixmap.setDevicePixelRatio( pixelRatio );
|
||
|
#endif
|
||
|
d_data->pixmap.fill( Qt::transparent );
|
||
|
|
||
|
const QRect r( pw, pw,
|
||
|
pixmapRect.width() - 2 * pw, pixmapRect.height() - 2 * pw );
|
||
|
|
||
|
QPainter pmPainter( &d_data->pixmap );
|
||
|
d_data->text.draw( &pmPainter, r );
|
||
|
}
|
||
|
|
||
|
painter->drawPixmap( pixmapRect, d_data->pixmap );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
d_data->text.draw( painter, rect );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Align the text label
|
||
|
|
||
|
\param rect Canvas rectangle with margins subtracted
|
||
|
\param textSize Size required to draw the text
|
||
|
|
||
|
\return A rectangle aligned according the the alignment flags of
|
||
|
the text.
|
||
|
|
||
|
\sa setMargin(), QwtText::renderFlags(), QwtText::textSize()
|
||
|
*/
|
||
|
QRectF QwtPlotTextLabel::textRect(
|
||
|
const QRectF &rect, const QSizeF &textSize ) const
|
||
|
{
|
||
|
return qwtItemRect( d_data->text.renderFlags(), rect, textSize );
|
||
|
}
|
||
|
|
||
|
//! Invalidate all internal cache
|
||
|
void QwtPlotTextLabel::invalidateCache()
|
||
|
{
|
||
|
d_data->pixmap = QPixmap();
|
||
|
}
|