qwt_plot_picker.cpp 8.92 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2 3 4 5 6 7 8 9
/* -*- 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
 *****************************************************************************/

Bryant's avatar
Bryant committed
10
#include "qwt_plot_picker.h"
pixhawk's avatar
pixhawk committed
11 12 13 14
#include "qwt_plot.h"
#include "qwt_scale_div.h"
#include "qwt_painter.h"
#include "qwt_scale_map.h"
Bryant's avatar
Bryant committed
15
#include "qwt_picker_machine.h"
pixhawk's avatar
pixhawk committed
16 17 18 19 20 21 22 23 24 25 26

/*!
  \brief Create a plot picker

  The picker is set to those x- and y-axis of the plot
  that are enabled. If both or no x-axis are enabled, the picker
  is set to QwtPlot::xBottom. If both or no y-axis are
  enabled, it is set to QwtPlot::yLeft.

  \param canvas Plot canvas to observe, also the parent object

Bryant's avatar
Bryant committed
27
  \sa QwtPlot::autoReplot(), QwtPlot::replot(), scaleRect()
pixhawk's avatar
pixhawk committed
28
*/
29

Bryant's avatar
Bryant committed
30 31 32 33
QwtPlotPicker::QwtPlotPicker( QWidget *canvas ):
    QwtPicker( canvas ),
    d_xAxis( -1 ),
    d_yAxis( -1 )
pixhawk's avatar
pixhawk committed
34 35 36 37 38 39 40 41 42
{
    if ( !canvas )
        return;

    // attach axes

    int xAxis = QwtPlot::xBottom;

    const QwtPlot *plot = QwtPlotPicker::plot();
Bryant's avatar
Bryant committed
43 44 45
    if ( !plot->axisEnabled( QwtPlot::xBottom ) &&
        plot->axisEnabled( QwtPlot::xTop ) )
    {
pixhawk's avatar
pixhawk committed
46 47 48 49
        xAxis = QwtPlot::xTop;
    }

    int yAxis = QwtPlot::yLeft;
Bryant's avatar
Bryant committed
50 51 52
    if ( !plot->axisEnabled( QwtPlot::yLeft ) &&
        plot->axisEnabled( QwtPlot::yRight ) )
    {
pixhawk's avatar
pixhawk committed
53 54 55
        yAxis = QwtPlot::yRight;
    }

Bryant's avatar
Bryant committed
56
    setAxis( xAxis, yAxis );
pixhawk's avatar
pixhawk committed
57 58 59 60 61 62 63 64 65
}

/*!
  Create a plot picker

  \param xAxis Set the x axis of the picker
  \param yAxis Set the y axis of the picker
  \param canvas Plot canvas to observe, also the parent object

Bryant's avatar
Bryant committed
66
  \sa QwtPlot::autoReplot(), QwtPlot::replot(), scaleRect()
pixhawk's avatar
pixhawk committed
67
*/
Bryant's avatar
Bryant committed
68 69 70 71
QwtPlotPicker::QwtPlotPicker( int xAxis, int yAxis, QWidget *canvas ):
    QwtPicker( canvas ),
    d_xAxis( xAxis ),
    d_yAxis( yAxis )
pixhawk's avatar
pixhawk committed
72 73 74 75 76 77 78 79
{
}

/*!
  Create a plot picker

  \param xAxis X axis of the picker
  \param yAxis Y axis of the picker
Bryant's avatar
Bryant committed
80
  \param rubberBand Rubber band style
pixhawk's avatar
pixhawk committed
81 82 83 84 85 86
  \param trackerMode Tracker mode
  \param canvas Plot canvas to observe, also the parent object

  \sa QwtPicker, QwtPicker::setSelectionFlags(), QwtPicker::setRubberBand(),
      QwtPicker::setTrackerMode

Bryant's avatar
Bryant committed
87
  \sa QwtPlot::autoReplot(), QwtPlot::replot(), scaleRect()
pixhawk's avatar
pixhawk committed
88
*/
Bryant's avatar
Bryant committed
89 90 91 92 93 94
QwtPlotPicker::QwtPlotPicker( int xAxis, int yAxis,
        RubberBand rubberBand, DisplayMode trackerMode,
        QWidget *canvas ):
    QwtPicker( rubberBand, trackerMode, canvas ),
    d_xAxis( xAxis ),
    d_yAxis( yAxis )
pixhawk's avatar
pixhawk committed
95 96 97
{
}

Bryant's avatar
Bryant committed
98 99
//! Destructor
QwtPlotPicker::~QwtPlotPicker()
pixhawk's avatar
pixhawk committed
100
{
Bryant's avatar
Bryant committed
101
}
pixhawk's avatar
pixhawk committed
102

Bryant's avatar
Bryant committed
103 104 105 106
//! \return Observed plot canvas
QWidget *QwtPlotPicker::canvas()
{
    return parentWidget();
pixhawk's avatar
pixhawk committed
107 108
}

Bryant's avatar
Bryant committed
109 110
//! \return Observed plot canvas
const QWidget *QwtPlotPicker::canvas() const
pixhawk's avatar
pixhawk committed
111
{
Bryant's avatar
Bryant committed
112
    return parentWidget();
pixhawk's avatar
pixhawk committed
113 114
}

Bryant's avatar
Bryant committed
115
//! \return Plot widget, containing the observed plot canvas
pixhawk's avatar
pixhawk committed
116 117
QwtPlot *QwtPlotPicker::plot()
{
Bryant's avatar
Bryant committed
118 119 120
    QWidget *w = canvas();
    if ( w )
        w = w->parentWidget();
pixhawk's avatar
pixhawk committed
121

Bryant's avatar
Bryant committed
122
    return qobject_cast<QwtPlot *>( w );
pixhawk's avatar
pixhawk committed
123 124
}

Bryant's avatar
Bryant committed
125
//! \return Plot widget, containing the observed plot canvas
pixhawk's avatar
pixhawk committed
126 127
const QwtPlot *QwtPlotPicker::plot() const
{
Bryant's avatar
Bryant committed
128 129 130 131 132
    const QWidget *w = canvas();
    if ( w )
        w = w->parentWidget();

    return qobject_cast<const QwtPlot *>( w );
pixhawk's avatar
pixhawk committed
133 134 135
}

/*!
Bryant's avatar
Bryant committed
136
  \return Normalized bounding rectangle of the axes
pixhawk's avatar
pixhawk committed
137 138
  \sa QwtPlot::autoReplot(), QwtPlot::replot().
*/
Bryant's avatar
Bryant committed
139
QRectF QwtPlotPicker::scaleRect() const
pixhawk's avatar
pixhawk committed
140
{
Bryant's avatar
Bryant committed
141
    QRectF rect;
pixhawk's avatar
pixhawk committed
142

Bryant's avatar
Bryant committed
143 144 145 146
    if ( plot() )
    {
        const QwtScaleDiv &xs = plot()->axisScaleDiv( xAxis() );
        const QwtScaleDiv &ys = plot()->axisScaleDiv( yAxis() );
pixhawk's avatar
pixhawk committed
147

Bryant's avatar
Bryant committed
148 149 150
        rect = QRectF( xs.lowerBound(), ys.lowerBound(),
            xs.range(), ys.range() );
        rect = rect.normalized();
pixhawk's avatar
pixhawk committed
151 152 153 154 155 156 157 158 159 160 161
    }

    return rect;
}

/*!
  Set the x and y axes of the picker

  \param xAxis X axis
  \param yAxis Y axis
*/
Bryant's avatar
Bryant committed
162
void QwtPlotPicker::setAxis( int xAxis, int yAxis )
pixhawk's avatar
pixhawk committed
163 164 165 166 167
{
    const QwtPlot *plt = plot();
    if ( !plt )
        return;

Bryant's avatar
Bryant committed
168 169
    if ( xAxis != d_xAxis || yAxis != d_yAxis )
    {
pixhawk's avatar
pixhawk committed
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
        d_xAxis = xAxis;
        d_yAxis = yAxis;
    }
}

//! Return x axis
int QwtPlotPicker::xAxis() const
{
    return d_xAxis;
}

//! Return y axis
int QwtPlotPicker::yAxis() const
{
    return d_yAxis;
}

/*!
  Translate a pixel position into a position string

  \param pos Position in pixel coordinates
  \return Position string
*/
Bryant's avatar
Bryant committed
193
QwtText QwtPlotPicker::trackerText( const QPoint &pos ) const
pixhawk's avatar
pixhawk committed
194
{
Bryant's avatar
Bryant committed
195
    return trackerTextF( invTransform( pos ) );
pixhawk's avatar
pixhawk committed
196 197 198 199 200 201 202 203 204 205 206 207 208 209
}

/*!
  \brief Translate a position into a position string

  In case of HLineRubberBand the label is the value of the
  y position, in case of VLineRubberBand the value of the x position.
  Otherwise the label contains x and y position separated by a ',' .

  The format for the double to string conversion is "%.4f".

  \param pos Position
  \return Position string
*/
Bryant's avatar
Bryant committed
210
QwtText QwtPlotPicker::trackerTextF( const QPointF &pos ) const
pixhawk's avatar
pixhawk committed
211 212 213
{
    QString text;

Bryant's avatar
Bryant committed
214 215 216 217 218 219 220 221 222 223
    switch ( rubberBand() )
    {
        case HLineRubberBand:
            text.sprintf( "%.4f", pos.y() );
            break;
        case VLineRubberBand:
            text.sprintf( "%.4f", pos.x() );
            break;
        default:
            text.sprintf( "%.4f, %.4f", pos.x(), pos.y() );
pixhawk's avatar
pixhawk committed
224
    }
Bryant's avatar
Bryant committed
225
    return QwtText( text );
pixhawk's avatar
pixhawk committed
226 227
}

228
/*!
Bryant's avatar
Bryant committed
229
  Append a point to the selection and update rubber band and tracker.
230

pixhawk's avatar
pixhawk committed
231 232 233
  \param pos Additional point
  \sa isActive, begin(), end(), move(), appended()

234
  \note The appended(const QPoint &), appended(const QDoublePoint &)
pixhawk's avatar
pixhawk committed
235 236
        signals are emitted.
*/
Bryant's avatar
Bryant committed
237
void QwtPlotPicker::append( const QPoint &pos )
pixhawk's avatar
pixhawk committed
238
{
Bryant's avatar
Bryant committed
239 240
    QwtPicker::append( pos );
    Q_EMIT appended( invTransform( pos ) );
pixhawk's avatar
pixhawk committed
241 242 243 244 245 246 247 248
}

/*!
  Move the last point of the selection

  \param pos New position
  \sa isActive, begin(), end(), append()

249
  \note The moved(const QPoint &), moved(const QDoublePoint &)
pixhawk's avatar
pixhawk committed
250 251
        signals are emitted.
*/
Bryant's avatar
Bryant committed
252
void QwtPlotPicker::move( const QPoint &pos )
pixhawk's avatar
pixhawk committed
253
{
Bryant's avatar
Bryant committed
254 255
    QwtPicker::move( pos );
    Q_EMIT moved( invTransform( pos ) );
pixhawk's avatar
pixhawk committed
256 257 258 259 260 261 262
}

/*!
  Close a selection setting the state to inactive.

  \param ok If true, complete the selection and emit selected signals
            otherwise discard the selection.
Bryant's avatar
Bryant committed
263
  \return True if the selection has been accepted, false otherwise
pixhawk's avatar
pixhawk committed
264 265
*/

Bryant's avatar
Bryant committed
266
bool QwtPlotPicker::end( bool ok )
pixhawk's avatar
pixhawk committed
267
{
Bryant's avatar
Bryant committed
268
    ok = QwtPicker::end( ok );
pixhawk's avatar
pixhawk committed
269 270 271 272 273 274 275
    if ( !ok )
        return false;

    QwtPlot *plot = QwtPlotPicker::plot();
    if ( !plot )
        return false;

Bryant's avatar
Bryant committed
276 277
    const QPolygon points = selection();
    if ( points.count() == 0 )
pixhawk's avatar
pixhawk committed
278 279
        return false;

Bryant's avatar
Bryant committed
280 281 282 283 284
    QwtPickerMachine::SelectionType selectionType =
        QwtPickerMachine::NoSelection;

    if ( stateMachine() )
        selectionType = stateMachine()->selectionType();
pixhawk's avatar
pixhawk committed
285

Bryant's avatar
Bryant committed
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
    switch ( selectionType )
    {
        case QwtPickerMachine::PointSelection:
        {
            const QPointF pos = invTransform( points.first() );
            Q_EMIT selected( pos );
            break;
        }
        case QwtPickerMachine::RectSelection:
        {
            if ( points.count() >= 2 )
            {
                const QPoint p1 = points.first();
                const QPoint p2 = points.last();

                const QRect rect = QRect( p1, p2 ).normalized();
                Q_EMIT selected( invTransform( rect ) );
            }
            break;
        }
        case QwtPickerMachine::PolygonSelection:
        {
            QVector<QPointF> dpa( points.count() );
            for ( int i = 0; i < points.count(); i++ )
                dpa[i] = invTransform( points[i] );
pixhawk's avatar
pixhawk committed
311

Bryant's avatar
Bryant committed
312 313 314 315
            Q_EMIT selected( dpa );
        }
        default:
            break;
pixhawk's avatar
pixhawk committed
316 317 318 319 320 321 322 323 324
    }

    return true;
}

/*!
    Translate a rectangle from pixel into plot coordinates

    \return Rectangle in plot coordinates
Bryant's avatar
Bryant committed
325
    \sa transform()
pixhawk's avatar
pixhawk committed
326
*/
Bryant's avatar
Bryant committed
327
QRectF QwtPlotPicker::invTransform( const QRect &rect ) const
pixhawk's avatar
pixhawk committed
328
{
Bryant's avatar
Bryant committed
329 330
    const QwtScaleMap xMap = plot()->canvasMap( d_xAxis );
    const QwtScaleMap yMap = plot()->canvasMap( d_yAxis );
pixhawk's avatar
pixhawk committed
331

Bryant's avatar
Bryant committed
332
    return QwtScaleMap::invTransform( xMap, yMap, rect );
pixhawk's avatar
pixhawk committed
333 334 335 336 337
}

/*!
    Translate a rectangle from plot into pixel coordinates
    \return Rectangle in pixel coordinates
Bryant's avatar
Bryant committed
338
    \sa invTransform()
pixhawk's avatar
pixhawk committed
339
*/
Bryant's avatar
Bryant committed
340
QRect QwtPlotPicker::transform( const QRectF &rect ) const
pixhawk's avatar
pixhawk committed
341
{
Bryant's avatar
Bryant committed
342 343
    const QwtScaleMap xMap = plot()->canvasMap( d_xAxis );
    const QwtScaleMap yMap = plot()->canvasMap( d_yAxis );
pixhawk's avatar
pixhawk committed
344

Bryant's avatar
Bryant committed
345
    return QwtScaleMap::transform( xMap, yMap, rect ).toRect();
pixhawk's avatar
pixhawk committed
346 347 348 349 350
}

/*!
    Translate a point from pixel into plot coordinates
    \return Point in plot coordinates
Bryant's avatar
Bryant committed
351
    \sa transform()
pixhawk's avatar
pixhawk committed
352
*/
Bryant's avatar
Bryant committed
353
QPointF QwtPlotPicker::invTransform( const QPoint &pos ) const
pixhawk's avatar
pixhawk committed
354
{
Bryant's avatar
Bryant committed
355 356
    QwtScaleMap xMap = plot()->canvasMap( d_xAxis );
    QwtScaleMap yMap = plot()->canvasMap( d_yAxis );
pixhawk's avatar
pixhawk committed
357

Bryant's avatar
Bryant committed
358 359 360 361
    return QPointF(
        xMap.invTransform( pos.x() ),
        yMap.invTransform( pos.y() )
    );
pixhawk's avatar
pixhawk committed
362 363 364 365 366
}

/*!
    Translate a point from plot into pixel coordinates
    \return Point in pixel coordinates
Bryant's avatar
Bryant committed
367
    \sa invTransform()
pixhawk's avatar
pixhawk committed
368
*/
Bryant's avatar
Bryant committed
369
QPoint QwtPlotPicker::transform( const QPointF &pos ) const
pixhawk's avatar
pixhawk committed
370
{
Bryant's avatar
Bryant committed
371 372 373 374 375
    QwtScaleMap xMap = plot()->canvasMap( d_xAxis );
    QwtScaleMap yMap = plot()->canvasMap( d_yAxis );

    const QPointF p( xMap.transform( pos.x() ),
        yMap.transform( pos.y() ) );
pixhawk's avatar
pixhawk committed
376

Bryant's avatar
Bryant committed
377
    return p.toPoint();
pixhawk's avatar
pixhawk committed
378
}