123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649 |
- /* -*- 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.h"
- #include "qwt_math.h"
- #include "qwt_scale_widget.h"
- #include "qwt_scale_div.h"
- #include "qwt_scale_engine.h"
- class QwtPlot::AxisData
- {
- public:
- bool isEnabled;
- bool doAutoScale;
- double minValue;
- double maxValue;
- double stepSize;
- int maxMajor;
- int maxMinor;
- QwtScaleDiv scaleDiv;
- QwtScaleEngine *scaleEngine;
- QwtScaleWidget *scaleWidget;
- };
- //! Initialize axes
- void QwtPlot::initAxesData()
- {
- int axisId;
- for ( axisId = 0; axisId < axisCnt; axisId++ )
- d_axisData[axisId] = new AxisData;
- d_axisData[yLeft]->scaleWidget =
- new QwtScaleWidget( QwtScaleDraw::LeftScale, this );
- d_axisData[yRight]->scaleWidget =
- new QwtScaleWidget( QwtScaleDraw::RightScale, this );
- d_axisData[xTop]->scaleWidget =
- new QwtScaleWidget( QwtScaleDraw::TopScale, this );
- d_axisData[xBottom]->scaleWidget =
- new QwtScaleWidget( QwtScaleDraw::BottomScale, this );
- QFont fscl( fontInfo().family(), 10 );
- QFont fttl( fontInfo().family(), 12, QFont::Bold );
- for ( axisId = 0; axisId < axisCnt; axisId++ )
- {
- AxisData &d = *d_axisData[axisId];
- d.scaleWidget->setFont( fscl );
- d.scaleWidget->setMargin( 2 );
- QwtText text = d.scaleWidget->title();
- text.setFont( fttl );
- d.scaleWidget->setTitle( text );
- d.doAutoScale = true;
- d.minValue = 0.0;
- d.maxValue = 1000.0;
- d.stepSize = 0.0;
- d.maxMinor = 5;
- d.maxMajor = 8;
- d.scaleEngine = new QwtLinearScaleEngine;
- d.scaleDiv.invalidate();
- }
- d_axisData[yLeft]->isEnabled = true;
- d_axisData[yRight]->isEnabled = false;
- d_axisData[xBottom]->isEnabled = true;
- d_axisData[xTop]->isEnabled = false;
- }
- void QwtPlot::deleteAxesData()
- {
- for ( int axisId = 0; axisId < axisCnt; axisId++ )
- {
- delete d_axisData[axisId]->scaleEngine;
- delete d_axisData[axisId];
- d_axisData[axisId] = NULL;
- }
- }
- /*!
- \return specified axis, or NULL if axisId is invalid.
- \param axisId axis index
- */
- const QwtScaleWidget *QwtPlot::axisWidget( int axisId ) const
- {
- if ( axisValid( axisId ) )
- return d_axisData[axisId]->scaleWidget;
- return NULL;
- }
- /*!
- \return specified axis, or NULL if axisId is invalid.
- \param axisId axis index
- */
- QwtScaleWidget *QwtPlot::axisWidget( int axisId )
- {
- if ( axisValid( axisId ) )
- return d_axisData[axisId]->scaleWidget;
- return NULL;
- }
- /*!
- Change the scale engine for an axis
- \param axisId axis index
- \param scaleEngine Scale engine
- \sa axisScaleEngine()
- */
- void QwtPlot::setAxisScaleEngine( int axisId, QwtScaleEngine *scaleEngine )
- {
- if ( axisValid( axisId ) && scaleEngine != NULL )
- {
- AxisData &d = *d_axisData[axisId];
- delete d.scaleEngine;
- d.scaleEngine = scaleEngine;
- d.scaleDiv.invalidate();
- autoRefresh();
- }
- }
- /*!
- \param axisId axis index
- \return Scale engine for a specific axis
- */
- QwtScaleEngine *QwtPlot::axisScaleEngine( int axisId )
- {
- if ( axisValid( axisId ) )
- return d_axisData[axisId]->scaleEngine;
- else
- return NULL;
- }
- /*!
- \param axisId axis index
- \return Scale engine for a specific axis
- */
- const QwtScaleEngine *QwtPlot::axisScaleEngine( int axisId ) const
- {
- if ( axisValid( axisId ) )
- return d_axisData[axisId]->scaleEngine;
- else
- return NULL;
- }
- /*!
- \return \c true if autoscaling is enabled
- \param axisId axis index
- */
- bool QwtPlot::axisAutoScale( int axisId ) const
- {
- if ( axisValid( axisId ) )
- return d_axisData[axisId]->doAutoScale;
- else
- return false;
- }
- /*!
- \return \c true if a specified axis is enabled
- \param axisId axis index
- */
- bool QwtPlot::axisEnabled( int axisId ) const
- {
- if ( axisValid( axisId ) )
- return d_axisData[axisId]->isEnabled;
- else
- return false;
- }
- /*!
- \return the font of the scale labels for a specified axis
- \param axisId axis index
- */
- QFont QwtPlot::axisFont( int axisId ) const
- {
- if ( axisValid( axisId ) )
- return axisWidget( axisId )->font();
- else
- return QFont();
- }
- /*!
- \return the maximum number of major ticks for a specified axis
- \param axisId axis index
- sa setAxisMaxMajor()
- */
- int QwtPlot::axisMaxMajor( int axisId ) const
- {
- if ( axisValid( axisId ) )
- return d_axisData[axisId]->maxMajor;
- else
- return 0;
- }
- /*!
- \return the maximum number of minor ticks for a specified axis
- \param axisId axis index
- sa setAxisMaxMinor()
- */
- int QwtPlot::axisMaxMinor( int axisId ) const
- {
- if ( axisValid( axisId ) )
- return d_axisData[axisId]->maxMinor;
- else
- return 0;
- }
- /*!
- \brief Return the scale division of a specified axis
- axisScaleDiv(axisId)->lowerBound(), axisScaleDiv(axisId)->upperBound()
- are the current limits of the axis scale.
- \param axisId axis index
- \return Scale division
- \sa QwtScaleDiv, setAxisScaleDiv()
- */
- const QwtScaleDiv *QwtPlot::axisScaleDiv( int axisId ) const
- {
- if ( !axisValid( axisId ) )
- return NULL;
- return &d_axisData[axisId]->scaleDiv;
- }
- /*!
- \brief Return the scale division of a specified axis
- axisScaleDiv(axisId)->lowerBound(), axisScaleDiv(axisId)->upperBound()
- are the current limits of the axis scale.
- \param axisId axis index
- \return Scale division
- \sa QwtScaleDiv, setAxisScaleDiv()
- */
- QwtScaleDiv *QwtPlot::axisScaleDiv( int axisId )
- {
- if ( !axisValid( axisId ) )
- return NULL;
- return &d_axisData[axisId]->scaleDiv;
- }
- /*!
- \returns the scale draw of a specified axis
- \param axisId axis index
- \return specified scaleDraw for axis, or NULL if axis is invalid.
- \sa QwtScaleDraw
- */
- const QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId ) const
- {
- if ( !axisValid( axisId ) )
- return NULL;
- return axisWidget( axisId )->scaleDraw();
- }
- /*!
- \returns the scale draw of a specified axis
- \param axisId axis index
- \return specified scaleDraw for axis, or NULL if axis is invalid.
- \sa QwtScaleDraw
- */
- QwtScaleDraw *QwtPlot::axisScaleDraw( int axisId )
- {
- if ( !axisValid( axisId ) )
- return NULL;
- return axisWidget( axisId )->scaleDraw();
- }
- /*!
- Return the step size parameter, that has been set
- in setAxisScale. This doesn't need to be the step size
- of the current scale.
- \param axisId axis index
- \return step size parameter value
- \sa setAxisScale()
- */
- double QwtPlot::axisStepSize( int axisId ) const
- {
- if ( !axisValid( axisId ) )
- return 0;
- return d_axisData[axisId]->stepSize;
- }
- /*!
- \return the title of a specified axis
- \param axisId axis index
- */
- QwtText QwtPlot::axisTitle( int axisId ) const
- {
- if ( axisValid( axisId ) )
- return axisWidget( axisId )->title();
- else
- return QwtText();
- }
- /*!
- \brief Enable or disable a specified axis
- When an axis is disabled, this only means that it is not
- visible on the screen. Curves, markers and can be attached
- to disabled axes, and transformation of screen coordinates
- into values works as normal.
- Only xBottom and yLeft are enabled by default.
- \param axisId axis index
- \param tf \c true (enabled) or \c false (disabled)
- */
- void QwtPlot::enableAxis( int axisId, bool tf )
- {
- if ( axisValid( axisId ) && tf != d_axisData[axisId]->isEnabled )
- {
- d_axisData[axisId]->isEnabled = tf;
- updateLayout();
- }
- }
- /*!
- Transform the x or y coordinate of a position in the
- drawing region into a value.
- \param axisId axis index
- \param pos position
- \warning The position can be an x or a y coordinate,
- depending on the specified axis.
- */
- double QwtPlot::invTransform( int axisId, int pos ) const
- {
- if ( axisValid( axisId ) )
- return( canvasMap( axisId ).invTransform( pos ) );
- else
- return 0.0;
- }
- /*!
- \brief Transform a value into a coordinate in the plotting region
- \param axisId axis index
- \param value value
- \return X or y coordinate in the plotting region corresponding
- to the value.
- */
- double QwtPlot::transform( int axisId, double value ) const
- {
- if ( axisValid( axisId ) )
- return( canvasMap( axisId ).transform( value ) );
- else
- return 0.0;
- }
- /*!
- \brief Change the font of an axis
- \param axisId axis index
- \param f font
- \warning This function changes the font of the tick labels,
- not of the axis title.
- */
- void QwtPlot::setAxisFont( int axisId, const QFont &f )
- {
- if ( axisValid( axisId ) )
- axisWidget( axisId )->setFont( f );
- }
- /*!
- \brief Enable autoscaling for a specified axis
- This member function is used to switch back to autoscaling mode
- after a fixed scale has been set. Autoscaling is enabled by default.
- \param axisId axis index
- \sa setAxisScale(), setAxisScaleDiv()
- */
- void QwtPlot::setAxisAutoScale( int axisId )
- {
- if ( axisValid( axisId ) && !d_axisData[axisId]->doAutoScale )
- {
- d_axisData[axisId]->doAutoScale = true;
- autoRefresh();
- }
- }
- /*!
- \brief Disable autoscaling and specify a fixed scale for a selected axis.
- \param axisId axis index
- \param min
- \param max minimum and maximum of the scale
- \param stepSize Major step size. If <code>step == 0</code>, the step size is
- calculated automatically using the maxMajor setting.
- \sa setAxisMaxMajor(), setAxisAutoScale(), axisStepSize()
- */
- void QwtPlot::setAxisScale( int axisId, double min, double max, double stepSize )
- {
- if ( axisValid( axisId ) )
- {
- AxisData &d = *d_axisData[axisId];
- d.doAutoScale = false;
- d.scaleDiv.invalidate();
- d.minValue = min;
- d.maxValue = max;
- d.stepSize = stepSize;
- autoRefresh();
- }
- }
- /*!
- \brief Disable autoscaling and specify a fixed scale for a selected axis.
- \param axisId axis index
- \param scaleDiv Scale division
- \sa setAxisScale(), setAxisAutoScale()
- */
- void QwtPlot::setAxisScaleDiv( int axisId, const QwtScaleDiv &scaleDiv )
- {
- if ( axisValid( axisId ) )
- {
- AxisData &d = *d_axisData[axisId];
- d.doAutoScale = false;
- d.scaleDiv = scaleDiv;
- autoRefresh();
- }
- }
- /*!
- \brief Set a scale draw
- \param axisId axis index
- \param scaleDraw object responsible for drawing scales.
- By passing scaleDraw it is possible to extend QwtScaleDraw
- functionality and let it take place in QwtPlot. Please note
- that scaleDraw has to be created with new and will be deleted
- by the corresponding QwtScale member ( like a child object ).
- \sa QwtScaleDraw, QwtScaleWidget
- \warning The attributes of scaleDraw will be overwritten by those of the
- previous QwtScaleDraw.
- */
- void QwtPlot::setAxisScaleDraw( int axisId, QwtScaleDraw *scaleDraw )
- {
- if ( axisValid( axisId ) )
- {
- axisWidget( axisId )->setScaleDraw( scaleDraw );
- autoRefresh();
- }
- }
- /*!
- Change the alignment of the tick labels
- \param axisId axis index
- \param alignment Or'd Qt::AlignmentFlags <see qnamespace.h>
- \sa QwtScaleDraw::setLabelAlignment()
- */
- void QwtPlot::setAxisLabelAlignment( int axisId, Qt::Alignment alignment )
- {
- if ( axisValid( axisId ) )
- axisWidget( axisId )->setLabelAlignment( alignment );
- }
- /*!
- Rotate all tick labels
- \param axisId axis index
- \param rotation Angle in degrees. When changing the label rotation,
- the label alignment might be adjusted too.
- \sa QwtScaleDraw::setLabelRotation(), setAxisLabelAlignment()
- */
- void QwtPlot::setAxisLabelRotation( int axisId, double rotation )
- {
- if ( axisValid( axisId ) )
- axisWidget( axisId )->setLabelRotation( rotation );
- }
- /*!
- Set the maximum number of minor scale intervals for a specified axis
- \param axisId axis index
- \param maxMinor maximum number of minor steps
- \sa axisMaxMinor()
- */
- void QwtPlot::setAxisMaxMinor( int axisId, int maxMinor )
- {
- if ( axisValid( axisId ) )
- {
- if ( maxMinor < 0 )
- maxMinor = 0;
- if ( maxMinor > 100 )
- maxMinor = 100;
- AxisData &d = *d_axisData[axisId];
- if ( maxMinor != d.maxMinor )
- {
- d.maxMinor = maxMinor;
- d.scaleDiv.invalidate();
- autoRefresh();
- }
- }
- }
- /*!
- Set the maximum number of major scale intervals for a specified axis
- \param axisId axis index
- \param maxMajor maximum number of major steps
- \sa axisMaxMajor()
- */
- void QwtPlot::setAxisMaxMajor( int axisId, int maxMajor )
- {
- if ( axisValid( axisId ) )
- {
- if ( maxMajor < 1 )
- maxMajor = 1;
- if ( maxMajor > 1000 )
- maxMajor = 10000;
- AxisData &d = *d_axisData[axisId];
- if ( maxMajor != d.maxMajor )
- {
- d.maxMajor = maxMajor;
- d.scaleDiv.invalidate();
- autoRefresh();
- }
- }
- }
- /*!
- \brief Change the title of a specified axis
- \param axisId axis index
- \param title axis title
- */
- void QwtPlot::setAxisTitle( int axisId, const QString &title )
- {
- if ( axisValid( axisId ) )
- axisWidget( axisId )->setTitle( title );
- }
- /*!
- \brief Change the title of a specified axis
- \param axisId axis index
- \param title axis title
- */
- void QwtPlot::setAxisTitle( int axisId, const QwtText &title )
- {
- if ( axisValid( axisId ) )
- axisWidget( axisId )->setTitle( title );
- }
- //! Rebuild the scales
- void QwtPlot::updateAxes()
- {
- // Find bounding interval of the item data
- // for all axes, where autoscaling is enabled
- QwtInterval intv[axisCnt];
- const QwtPlotItemList& itmList = itemList();
- QwtPlotItemIterator it;
- for ( it = itmList.begin(); it != itmList.end(); ++it )
- {
- const QwtPlotItem *item = *it;
- if ( !item->testItemAttribute( QwtPlotItem::AutoScale ) )
- continue;
- if ( axisAutoScale( item->xAxis() ) || axisAutoScale( item->yAxis() ) )
- {
- const QRectF rect = item->boundingRect();
- intv[item->xAxis()] |= QwtInterval( rect.left(), rect.right() );
- intv[item->yAxis()] |= QwtInterval( rect.top(), rect.bottom() );
- }
- }
- // Adjust scales
- for ( int axisId = 0; axisId < axisCnt; axisId++ )
- {
- AxisData &d = *d_axisData[axisId];
- double minValue = d.minValue;
- double maxValue = d.maxValue;
- double stepSize = d.stepSize;
- if ( d.doAutoScale && intv[axisId].isValid() )
- {
- d.scaleDiv.invalidate();
- minValue = intv[axisId].minValue();
- maxValue = intv[axisId].maxValue();
- d.scaleEngine->autoScale( d.maxMajor,
- minValue, maxValue, stepSize );
- }
- if ( !d.scaleDiv.isValid() )
- {
- d.scaleDiv = d.scaleEngine->divideScale(
- minValue, maxValue,
- d.maxMajor, d.maxMinor, stepSize );
- }
- QwtScaleWidget *scaleWidget = axisWidget( axisId );
- scaleWidget->setScaleDiv(
- d.scaleEngine->transformation(), d.scaleDiv );
- int startDist, endDist;
- scaleWidget->getBorderDistHint( startDist, endDist );
- scaleWidget->setBorderDist( startDist, endDist );
- }
- for ( it = itmList.begin(); it != itmList.end(); ++it )
- {
- QwtPlotItem *item = *it;
- item->updateScaleDiv( *axisScaleDiv( item->xAxis() ),
- *axisScaleDiv( item->yAxis() ) );
- }
- }
|