/***************************************************************************** * Qwt Examples - Copyright (C) 2002 Uwe Rathmann * This file may be used under the terms of the 3-clause BSD License *****************************************************************************/ #include "CanvasPicker.h" #include #include #include CanvasPicker::CanvasPicker( bool sortedX, QwtPlot* plot ) : QObject( plot ) , m_selectedPoint( -1 ) , m_sortedX( sortedX ) { plot->canvas()->installEventFilter( this ); } QwtPlot* CanvasPicker::plot() { return qobject_cast< QwtPlot* >( parent() ); } const QwtPlot* CanvasPicker::plot() const { return qobject_cast< const QwtPlot* >( parent() ); } bool CanvasPicker::eventFilter( QObject* object, QEvent* event ) { if ( plot() == NULL || object != plot()->canvas() ) return false; switch( event->type() ) { case QEvent::MouseButtonPress: { const QMouseEvent* mouseEvent = static_cast< QMouseEvent* >( event ); select( mouseEvent->pos() ); return true; } case QEvent::MouseMove: { const QMouseEvent* mouseEvent = static_cast< QMouseEvent* >( event ); move( mouseEvent->pos() ); return true; } default: break; } return QObject::eventFilter( object, event ); } // Select the point at a position. If there is no point // deselect the selected point void CanvasPicker::select( const QPointF& pos ) { QwtPlotCurve* curve = NULL; double dist = 10e10; int index = -1; const QwtPlotItemList& itmList = plot()->itemList(); for ( QwtPlotItemIterator it = itmList.begin(); it != itmList.end(); ++it ) { if ( ( *it )->rtti() == QwtPlotItem::Rtti_PlotCurve ) { QwtPlotCurve* c = static_cast< QwtPlotCurve* >( *it ); if ( c->isVisible() ) { double d; int idx = c->closestPoint( pos, &d ); if ( d < dist ) { curve = c; index = idx; dist = d; } } } } m_selectedCurve = NULL; m_selectedPoint = -1; if ( curve && dist < 10 ) // 10 pixels tolerance { m_selectedCurve = curve; m_selectedPoint = index; } } // Move the selected point void CanvasPicker::move( const QPointF& pos ) { if ( m_selectedCurve == 0 || m_selectedPoint < 0 ) return; QVector< double > xData( m_selectedCurve->dataSize() ); QVector< double > yData( m_selectedCurve->dataSize() ); double dx = 0.0; double dy = 0.0; int numPoints = static_cast< int >( m_selectedCurve->dataSize() ); for ( int i = 0; i < numPoints; i++ ) { const QPointF sample = m_selectedCurve->sample( i ); if ( i == m_selectedPoint ) { double x = plot()->invTransform( m_selectedCurve->xAxis(), pos.x() ); double y = plot()->invTransform( m_selectedCurve->yAxis(), pos.y() ); if ( m_sortedX ) { if ( i > 0 ) { const double xMin = m_selectedCurve->sample( i - 1 ).x(); if ( x <= xMin ) x = xMin + 1; } if ( i < numPoints - 1 ) { const double xMax = m_selectedCurve->sample( i + 1 ).x(); if ( x >= xMax ) x = xMax - 1; } } xData[i] = x; yData[i] = y; dx = x - sample.x(); dy = y - sample.y(); } else { xData[i] = sample.x(); yData[i] = sample.y(); } } m_selectedCurve->setSamples( xData, yData ); const QwtPlotItemList curves = plot()->itemList( QwtPlotItem::Rtti_PlotCurve ); for ( int i = 0; i < curves.size(); i++ ) { QwtPlotCurve* curve = static_cast< QwtPlotCurve* >( curves[i] ); if ( curve == m_selectedCurve ) continue; xData.resize( curve->dataSize() ); yData.resize( curve->dataSize() ); numPoints = static_cast< int >( curve->dataSize() ); for ( int j = 0; j < numPoints; j++ ) { const QPointF sample = curve->sample( j ); xData[j] = sample.x(); yData[j] = sample.y(); if ( j == m_selectedPoint ) { xData[j] += dx; yData[j] += dy; } } curve->setSamples( xData, yData ); } plot()->replot(); }