Skip to content
qwt_plot_grid.cpp 9.62 KiB
Newer Older
pixhawk's avatar
pixhawk committed
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
pixhawk's avatar
pixhawk committed
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

Bryant's avatar
Bryant committed
#include "qwt_plot_grid.h"
pixhawk's avatar
pixhawk committed
#include "qwt_painter.h"
#include "qwt_text.h"
#include "qwt_scale_map.h"
#include "qwt_scale_div.h"
Bryant's avatar
Bryant committed
#include "qwt_math.h"
#include <qpainter.h>
#include <qpen.h>
pixhawk's avatar
pixhawk committed

class QwtPlotGrid::PrivateData
{
public:
    PrivateData():
Bryant's avatar
Bryant committed
        xEnabled( true ),
        yEnabled( true ),
        xMinEnabled( false ),
        yMinEnabled( false )
    {
pixhawk's avatar
pixhawk committed
    }

    bool xEnabled;
    bool yEnabled;
    bool xMinEnabled;
    bool yMinEnabled;

    QwtScaleDiv xScaleDiv;
    QwtScaleDiv yScaleDiv;

Bryant's avatar
Bryant committed
    QPen majorPen;
    QPen minorPen;
pixhawk's avatar
pixhawk committed
};

//! Enables major grid, disables minor grid
QwtPlotGrid::QwtPlotGrid():
Bryant's avatar
Bryant committed
    QwtPlotItem( QwtText( "Grid" ) )
pixhawk's avatar
pixhawk committed
{
    d_data = new PrivateData;
Bryant's avatar
Bryant committed

    setItemInterest( QwtPlotItem::ScaleInterest, true );
    setZ( 10.0 );
pixhawk's avatar
pixhawk committed
}

//! Destructor
QwtPlotGrid::~QwtPlotGrid()
{
    delete d_data;
}

//! \return QwtPlotItem::Rtti_PlotGrid
int QwtPlotGrid::rtti() const
{
    return QwtPlotItem::Rtti_PlotGrid;
}

/*!
Bryant's avatar
Bryant committed
  \brief Enable or disable vertical grid lines
  \param on Enable (true) or disable
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
  \sa Minor grid lines can be enabled or disabled with
pixhawk's avatar
pixhawk committed
      enableXMin()
*/
Bryant's avatar
Bryant committed
void QwtPlotGrid::enableX( bool on )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( d_data->xEnabled != on )
    {
        d_data->xEnabled = on;

        legendChanged();
pixhawk's avatar
pixhawk committed
        itemChanged();
    }
}

/*!
Bryant's avatar
Bryant committed
  \brief Enable or disable horizontal grid lines
  \param on Enable (true) or disable
  \sa Minor grid lines can be enabled or disabled with enableYMin()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtPlotGrid::enableY( bool on )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( d_data->yEnabled != on )
    {
        d_data->yEnabled = on;

        legendChanged();
pixhawk's avatar
pixhawk committed
        itemChanged();
    }
}

/*!
Bryant's avatar
Bryant committed
  \brief Enable or disable  minor vertical grid lines.
  \param on Enable (true) or disable
pixhawk's avatar
pixhawk committed
  \sa enableX()
*/
Bryant's avatar
Bryant committed
void QwtPlotGrid::enableXMin( bool on )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( d_data->xMinEnabled != on )
    {
        d_data->xMinEnabled = on;

        legendChanged();
pixhawk's avatar
pixhawk committed
        itemChanged();
    }
}

/*!
Bryant's avatar
Bryant committed
  \brief Enable or disable minor horizontal grid lines
  \param on Enable (true) or disable
pixhawk's avatar
pixhawk committed
  \sa enableY()
*/
Bryant's avatar
Bryant committed
void QwtPlotGrid::enableYMin( bool on )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( d_data->yMinEnabled != on )
    {
        d_data->yMinEnabled = on;

        legendChanged();
pixhawk's avatar
pixhawk committed
        itemChanged();
    }
}

/*!
Bryant's avatar
Bryant committed
  Assign an x axis scale division

pixhawk's avatar
pixhawk committed
  \param scaleDiv Scale division
*/
Bryant's avatar
Bryant committed
void QwtPlotGrid::setXDiv( const QwtScaleDiv &scaleDiv )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( d_data->xScaleDiv != scaleDiv )
    {
pixhawk's avatar
pixhawk committed
        d_data->xScaleDiv = scaleDiv;
        itemChanged();
    }
}

/*!
Bryant's avatar
Bryant committed
  Assign a y axis division

  \param scaleDiv Scale division
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtPlotGrid::setYDiv( const QwtScaleDiv &scaleDiv )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( d_data->yScaleDiv != scaleDiv )
    {
        d_data->yScaleDiv = scaleDiv;
pixhawk's avatar
pixhawk committed
        itemChanged();
    }
}

/*!
Bryant's avatar
Bryant committed
  Build and assign a pen for both major and minor grid lines

  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 QwtPlotGrid::setPen( const QColor &color, qreal width, Qt::PenStyle style )
{
    setPen( QPen( color, width, style ) );
}

/*!
  Assign a pen for both major and minor grid lines

  \param pen Pen
  \sa setMajorPen(), setMinorPen()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtPlotGrid::setPen( const QPen &pen )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( d_data->majorPen != pen || d_data->minorPen != pen )
    {
        d_data->majorPen = pen;
        d_data->minorPen = pen;

        legendChanged();
pixhawk's avatar
pixhawk committed
        itemChanged();
    }
}

/*!
Bryant's avatar
Bryant committed
  Build and assign a pen for both major grid lines

  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 QwtPlotGrid::setMajorPen( const QColor &color, qreal width, Qt::PenStyle style )
{
    setMajorPen( QPen( color, width, style ) );
}

/*!
  Assign a pen for the major grid lines

  \param pen Pen
  \sa majorPen(), setMinorPen(), setPen()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtPlotGrid::setMajorPen( const QPen &pen )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( d_data->majorPen != pen )
    {
        d_data->majorPen = pen;

        legendChanged();
pixhawk's avatar
pixhawk committed
        itemChanged();
    }
}

/*!
Bryant's avatar
Bryant committed
  Build and assign a pen for the minor grid lines

  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 QwtPlotGrid::setMinorPen( const QColor &color, qreal width, Qt::PenStyle style )
{
    setMinorPen( QPen( color, width, style ) );
}

/*!
  Assign a pen for the minor grid lines

  \param pen Pen
  \sa minorPen(), setMajorPen(), setPen()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtPlotGrid::setMinorPen( const QPen &pen )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( d_data->minorPen != pen )
    {
        d_data->minorPen = pen;

        legendChanged();
pixhawk's avatar
pixhawk committed
        itemChanged();
    }
}

/*!
  \brief Draw the grid

  The grid is drawn into the bounding rectangle such that
Bryant's avatar
Bryant committed
  grid lines begin and end at the rectangle's borders. The X and Y
pixhawk's avatar
pixhawk committed
  maps are used to map the scale divisions into the drawing region
  screen.
Bryant's avatar
Bryant committed

pixhawk's avatar
pixhawk committed
  \param painter  Painter
  \param xMap X axis map
  \param yMap Y axis
Bryant's avatar
Bryant committed
  \param canvasRect Contents rectangle of the plot canvas
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtPlotGrid::draw( QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    const QRectF &canvasRect ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    //  draw minor grid lines
    QPen minorPen = d_data->minorPen;
    minorPen.setCapStyle( Qt::FlatCap );

    painter->setPen( minorPen );

    if ( d_data->xEnabled && d_data->xMinEnabled )
    {
        drawLines( painter, canvasRect, Qt::Vertical, xMap,
            d_data->xScaleDiv.ticks( QwtScaleDiv::MinorTick ) );
        drawLines( painter, canvasRect, Qt::Vertical, xMap,
            d_data->xScaleDiv.ticks( QwtScaleDiv::MediumTick ) );
pixhawk's avatar
pixhawk committed
    }

Bryant's avatar
Bryant committed
    if ( d_data->yEnabled && d_data->yMinEnabled )
    {
        drawLines( painter, canvasRect, Qt::Horizontal, yMap,
            d_data->yScaleDiv.ticks( QwtScaleDiv::MinorTick ) );
        drawLines( painter, canvasRect, Qt::Horizontal, yMap,
            d_data->yScaleDiv.ticks( QwtScaleDiv::MediumTick ) );
pixhawk's avatar
pixhawk committed
    }

Bryant's avatar
Bryant committed
    //  draw major grid lines
    QPen majorPen = d_data->majorPen;
    majorPen.setCapStyle( Qt::FlatCap );
Bryant's avatar
Bryant committed
    painter->setPen( majorPen );

    if ( d_data->xEnabled )
    {
        drawLines( painter, canvasRect, Qt::Vertical, xMap,
            d_data->xScaleDiv.ticks( QwtScaleDiv::MajorTick ) );
pixhawk's avatar
pixhawk committed
    }

Bryant's avatar
Bryant committed
    if ( d_data->yEnabled )
    {
        drawLines( painter, canvasRect, Qt::Horizontal, yMap,
            d_data->yScaleDiv.ticks( QwtScaleDiv::MajorTick ) );
pixhawk's avatar
pixhawk committed
    }
}

Bryant's avatar
Bryant committed
void QwtPlotGrid::drawLines( QPainter *painter, const QRectF &canvasRect,
    Qt::Orientation orientation, const QwtScaleMap &scaleMap,
    const QList<double> &values ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    const double x1 = canvasRect.left();
    const double x2 = canvasRect.right() - 1.0;
    const double y1 = canvasRect.top();
    const double y2 = canvasRect.bottom() - 1.0;

    const bool doAlign = QwtPainter::roundingAlignment( painter );

    for ( int i = 0; i < values.count(); i++ )
    {
        double value = scaleMap.transform( values[i] );
        if ( doAlign )
            value = qRound( value );

        if ( orientation == Qt::Horizontal )
        {
            if ( qwtFuzzyGreaterOrEqual( value, y1 ) &&
                qwtFuzzyLessOrEqual( value, y2 ) )
            {
                QwtPainter::drawLine( painter, x1, value, x2, value );
            }
        }
        else
        {
            if ( qwtFuzzyGreaterOrEqual( value, x1 ) &&
                qwtFuzzyLessOrEqual( value, x2 ) )
            {
                QwtPainter::drawLine( painter, value, y1, value, y2 );
            }
pixhawk's avatar
pixhawk committed
        }
    }
}

/*!
Bryant's avatar
Bryant committed
  \return the pen for the major grid lines
  \sa setMajorPen(), setMinorPen(), setPen()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
const QPen &QwtPlotGrid::majorPen() const
Bryant's avatar
Bryant committed
    return d_data->majorPen;
pixhawk's avatar
pixhawk committed
}

/*!
Bryant's avatar
Bryant committed
  \return the pen for the minor grid lines
  \sa setMinorPen(), setMajorPen(), setPen()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
const QPen &QwtPlotGrid::minorPen() const
Bryant's avatar
Bryant committed
    return d_data->minorPen;
pixhawk's avatar
pixhawk committed
}
pixhawk's avatar
pixhawk committed
/*!
Bryant's avatar
Bryant committed
  \return true if vertical grid lines are enabled
pixhawk's avatar
pixhawk committed
  \sa enableX()
*/
bool QwtPlotGrid::xEnabled() const
{
    return d_data->xEnabled;
pixhawk's avatar
pixhawk committed
}

/*!
Bryant's avatar
Bryant committed
  \return true if minor vertical grid lines are enabled
pixhawk's avatar
pixhawk committed
  \sa enableXMin()
*/
bool QwtPlotGrid::xMinEnabled() const
{
    return d_data->xMinEnabled;
pixhawk's avatar
pixhawk committed
}

/*!
Bryant's avatar
Bryant committed
  \return true if horizontal grid lines are enabled
pixhawk's avatar
pixhawk committed
  \sa enableY()
*/
bool QwtPlotGrid::yEnabled() const
{
    return d_data->yEnabled;
pixhawk's avatar
pixhawk committed
}

/*!
Bryant's avatar
Bryant committed
  \return true if minor horizontal grid lines are enabled
pixhawk's avatar
pixhawk committed
  \sa enableYMin()
*/
bool QwtPlotGrid::yMinEnabled() const
pixhawk's avatar
pixhawk committed
{
    return d_data->yMinEnabled;
pixhawk's avatar
pixhawk committed
}

pixhawk's avatar
pixhawk committed
/*! \return the scale division of the x axis */
const QwtScaleDiv &QwtPlotGrid::xScaleDiv() const
{
    return d_data->xScaleDiv;
pixhawk's avatar
pixhawk committed
}

/*! \return the scale division of the y axis */
const QwtScaleDiv &QwtPlotGrid::yScaleDiv() const
{
    return d_data->yScaleDiv;
pixhawk's avatar
pixhawk committed
}
Bryant's avatar
Bryant committed
/*!
   Update the grid to changes of the axes scale division

   \param xScaleDiv Scale division of the x-axis
   \param yScaleDiv Scale division of the y-axis

   \sa QwtPlot::updateAxes()
*/
void QwtPlotGrid::updateScaleDiv( const QwtScaleDiv& xScaleDiv,
    const QwtScaleDiv& yScaleDiv )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    setXDiv( xScaleDiv );
    setYDiv( yScaleDiv );
pixhawk's avatar
pixhawk committed
}