/libs/qwt/qwt_plot_scaleitem.cpp
C++ | 453 lines | 252 code | 51 blank | 150 comment | 52 complexity | 437f4c9e227f4f0115253615d985a158 MD5 | raw file
- /* -*- 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 <qpalette.h>
- #include <qpainter.h>
- #include "qwt_plot.h"
- #include "qwt_plot_canvas.h"
- #include "qwt_scale_map.h"
- #include "qwt_plot_scaleitem.h"
- #include "qwt_double_interval.h"
- class QwtPlotScaleItem::PrivateData
- {
- public:
- PrivateData():
- position(0.0),
- borderDistance(-1),
- scaleDivFromAxis(true),
- scaleDraw(new QwtScaleDraw()) {
- }
- ~PrivateData() {
- delete scaleDraw;
- }
- #if QT_VERSION < 0x040000
- QColorGroup colorGroup;
- #else
- QPalette palette;
- #endif
- QFont font;
- double position;
- int borderDistance;
- bool scaleDivFromAxis;
- QwtScaleDraw *scaleDraw;
- QRect canvasRectCache;
- };
- /*!
- \brief Constructor for scale item at the position pos.
- \param alignment In case of QwtScaleDraw::BottomScale/QwtScaleDraw::TopScale
- the scale item is corresponding to the xAxis(),
- otherwise it corresponds to the yAxis().
- \param position x or y position, depending on the corresponding axis.
- \sa setPosition(), setAlignment()
- */
- QwtPlotScaleItem::QwtPlotScaleItem(
- QwtScaleDraw::Alignment alignment, const double pos):
- QwtPlotItem(QwtText("Scale"))
- {
- d_data = new PrivateData;
- d_data->position = pos;
- d_data->scaleDraw->setAlignment(alignment);
- setZ(11.0);
- }
- //! Destructor
- QwtPlotScaleItem::~QwtPlotScaleItem()
- {
- delete d_data;
- }
- //! \return QwtPlotItem::Rtti_PlotScale
- int QwtPlotScaleItem::rtti() const
- {
- return QwtPlotItem::Rtti_PlotScale;
- }
- /*!
- \brief Assign a scale division
- When assigning a scaleDiv the scale division won't be synchronized
- with the corresponding axis anymore.
- \param scaleDiv Scale division
- \sa scaleDiv(), setScaleDivFromAxis(), isScaleDivFromAxis()
- */
- void QwtPlotScaleItem::setScaleDiv(const QwtScaleDiv& scaleDiv)
- {
- d_data->scaleDivFromAxis = false;
- d_data->scaleDraw->setScaleDiv(scaleDiv);
- }
- //! \return Scale division
- const QwtScaleDiv& QwtPlotScaleItem::scaleDiv() const
- {
- return d_data->scaleDraw->scaleDiv();
- }
- /*!
- Enable/Disable the synchronization of the scale division with
- the corresponding axis.
- \sa isScaleDivFromAxis()
- */
- void QwtPlotScaleItem::setScaleDivFromAxis(bool on)
- {
- if ( on != d_data->scaleDivFromAxis ) {
- d_data->scaleDivFromAxis = on;
- if ( on ) {
- const QwtPlot *plt = plot();
- if ( plt ) {
- updateScaleDiv( *plt->axisScaleDiv(xAxis()),
- *plt->axisScaleDiv(yAxis()) );
- itemChanged();
- }
- }
- }
- }
- /*!
- \return True, if the synchronization of the scale division with
- the corresponding axis is enabled.
- \sa setScaleDiv(), setScaleDivFromAxis()
- */
- bool QwtPlotScaleItem::isScaleDivFromAxis() const
- {
- return d_data->scaleDivFromAxis;
- }
- #if QT_VERSION < 0x040000
- /*!
- Set the color group
- \sa QwtAbstractScaleDraw::draw(), colorGroup()
- */
- void QwtPlotScaleItem::setColorGroup(const QColorGroup &colorGroup)
- {
- if ( colorGroup != d_data->colorGroup ) {
- d_data->colorGroup = colorGroup;
- itemChanged();
- }
- }
- /*!
- \return color group
- \sa setColorGroup()
- */
- QColorGroup QwtPlotScaleItem::colorGroup() const
- {
- return d_data->colorGroup;
- }
- #else
- /*!
- Set the palette
- \sa QwtAbstractScaleDraw::draw(), palette()
- */
- void QwtPlotScaleItem::setPalette(const QPalette &palette)
- {
- if ( palette != d_data->palette ) {
- d_data->palette = palette;
- itemChanged();
- }
- }
- /*!
- \return palette
- \sa setPalette()
- */
- QPalette QwtPlotScaleItem::palette() const
- {
- return d_data->palette;
- }
- #endif
- /*!
- Change the tick label font
- \sa font
- */
- void QwtPlotScaleItem::setFont(const QFont &font)
- {
- if ( font != d_data->font ) {
- d_data->font = font;
- itemChanged();
- }
- }
- /*!
- \return tick label font
- \sa setFont()
- */
- QFont QwtPlotScaleItem::font() const
- {
- return d_data->font;
- }
- /*!
- \brief Set a scale draw
- \param axisId axis index
- \param scaleDraw object responsible for drawing scales.
- The main use case for replacing the default QwtScaleDraw is
- to overload QwtAbstractScaleDraw::label, to replace or swallow
- tick labels.
- \sa scaleDraw()
- */
- void QwtPlotScaleItem::setScaleDraw(QwtScaleDraw *scaleDraw)
- {
- if ( scaleDraw == NULL )
- return;
- if ( scaleDraw != d_data->scaleDraw )
- delete d_data->scaleDraw;
- d_data->scaleDraw = scaleDraw;
- const QwtPlot *plt = plot();
- if ( plt ) {
- updateScaleDiv( *plt->axisScaleDiv(xAxis()),
- *plt->axisScaleDiv(yAxis()) );
- }
- itemChanged();
- }
- /*!
- \return Scale draw
- \sa setScaleDraw()
- */
- const QwtScaleDraw *QwtPlotScaleItem::scaleDraw() const
- {
- return d_data->scaleDraw;
- }
- /*!
- \return Scale draw
- \sa setScaleDraw()
- */
- QwtScaleDraw *QwtPlotScaleItem::scaleDraw()
- {
- return d_data->scaleDraw;
- }
- /*!
- Change the position of the scale
- The position is interpreted as y value for horizontal axes
- and as x value for vertical axes.
- The border distance is set to -1.
- \sa position(), setAlignment()
- */
- void QwtPlotScaleItem::setPosition(double pos)
- {
- if ( d_data->position != pos ) {
- d_data->position = pos;
- d_data->borderDistance = -1;
- itemChanged();
- }
- }
- /*!
- \return Position of the scale
- \sa setPosition(), setAlignment()
- */
- double QwtPlotScaleItem::position() const
- {
- return d_data->position;
- }
- /*!
- \brief Align the scale to the canvas
- If distance is >= 0 the scale will be aligned to a
- border of the contents rect of the canvas. If
- alignment() is QwtScaleDraw::LeftScale, the scale will
- be aligned to the right border, if it is QwtScaleDraw::TopScale
- it will be aligned to the bottom (and vice versa),
- If distance is < 0 the scale will be at the position().
- \param distance Number of pixels between the canvas border and the
- backbone of the scale.
- \sa setPosition(), borderDistance()
- */
- void QwtPlotScaleItem::setBorderDistance(int distance)
- {
- if ( distance < 0 )
- distance = -1;
- if ( distance != d_data->borderDistance ) {
- d_data->borderDistance = distance;
- itemChanged();
- }
- }
- /*!
- \return Distance from a canvas border
- \sa setBorderDistance(), setPosition()
- */
- int QwtPlotScaleItem::borderDistance() const
- {
- return d_data->borderDistance;
- }
- /*!
- Change the alignment of the scale
- The alignment sets the orientation of the scale and the position of
- the ticks:
- - QwtScaleDraw::BottomScale: horizontal, ticks below
- - QwtScaleDraw::TopScale: horizontal, ticks above
- - QwtScaleDraw::LeftScale: vertical, ticks left
- - QwtScaleDraw::RightScale: vertical, ticks right
- For horizontal scales the position corresponds to QwtPlotItem::yAxis(),
- otherwise to QwtPlotItem::xAxis().
- \sa scaleDraw(), QwtScaleDraw::alignment(), setPosition()
- */
- void QwtPlotScaleItem::setAlignment(QwtScaleDraw::Alignment alignment)
- {
- QwtScaleDraw *sd = d_data->scaleDraw;
- if ( sd->alignment() != alignment ) {
- sd->setAlignment(alignment);
- itemChanged();
- }
- }
- /*!
- \brief Draw the scale
- */
- void QwtPlotScaleItem::draw(QPainter *painter,
- const QwtScaleMap &xMap, const QwtScaleMap &yMap,
- const QRect &canvasRect) const
- {
- if ( canvasRect != d_data->canvasRectCache ) {
- QwtPlotScaleItem* that = (QwtPlotScaleItem*)this;
- that->updateBorders();
- }
- QPen pen = painter->pen();
- pen.setStyle(Qt::SolidLine);
- painter->setPen(pen);
- int pw = painter->pen().width();
- if ( pw == 0 )
- pw = 1;
- QwtScaleDraw *sd = d_data->scaleDraw;
- if ( sd->orientation() == Qt::Horizontal ) {
- int y;
- if ( d_data->borderDistance >= 0 ) {
- if ( sd->alignment() == QwtScaleDraw::BottomScale )
- y = canvasRect.top() + d_data->borderDistance;
- else {
- y = canvasRect.bottom() - d_data->borderDistance - pw + 1;
- }
- } else {
- y = yMap.transform(d_data->position);
- }
- if ( y < canvasRect.top() || y > canvasRect.bottom() )
- return;
- sd->move(canvasRect.left(), y);
- sd->setLength(canvasRect.width() - 1);
- sd->setTransformation(xMap.transformation()->copy());
- } else { // == Qt::Vertical
- int x;
- if ( d_data->borderDistance >= 0 ) {
- if ( sd->alignment() == QwtScaleDraw::RightScale )
- x = canvasRect.left() + d_data->borderDistance;
- else {
- x = canvasRect.right() - d_data->borderDistance - pw + 1;
- }
- } else {
- x = xMap.transform(d_data->position);
- }
- if ( x < canvasRect.left() || x > canvasRect.right() )
- return;
- sd->move(x, canvasRect.top());
- sd->setLength(canvasRect.height() - 1);
- sd->setTransformation(yMap.transformation()->copy());
- }
- painter->setFont(d_data->font);
- #if QT_VERSION < 0x040000
- sd->draw(painter, d_data->colorGroup);
- #else
- sd->draw(painter, d_data->palette);
- #endif
- }
- /*!
- \brief Update the item to changes of the axes scale division
- In case of isScaleDivFromAxis(), the scale draw is synchronized
- to the correspond axis.
- \param xScaleDiv Scale division of the x-axis
- \param yScaleDiv Scale division of the y-axis
- \sa QwtPlot::updateAxes()
- */
- void QwtPlotScaleItem::updateScaleDiv(const QwtScaleDiv& xScaleDiv,
- const QwtScaleDiv& yScaleDiv)
- {
- QwtScaleDraw *sd = d_data->scaleDraw;
- if ( d_data->scaleDivFromAxis && sd ) {
- sd->setScaleDiv(
- sd->orientation() == Qt::Horizontal ? xScaleDiv : yScaleDiv);
- updateBorders();
- }
- }
- void QwtPlotScaleItem::updateBorders()
- {
- const QwtPlot *plt = plot();
- if ( plt == NULL || !d_data->scaleDivFromAxis )
- return;
- const QRect r = plt->canvas()->contentsRect();
- d_data->canvasRectCache = r;
- QwtDoubleInterval interval;
- if ( d_data->scaleDraw->orientation() == Qt::Horizontal ) {
- const QwtScaleMap map = plt->canvasMap(xAxis());
- interval.setMinValue(map.invTransform(r.left()));
- interval.setMaxValue(map.invTransform(r.right()));
- } else {
- const QwtScaleMap map = plt->canvasMap(yAxis());
- interval.setMinValue(map.invTransform(r.bottom()));
- interval.setMaxValue(map.invTransform(r.top()));
- }
- QwtScaleDiv scaleDiv = d_data->scaleDraw->scaleDiv();
- scaleDiv.setInterval(interval);
- d_data->scaleDraw->setScaleDiv(scaleDiv);
- }