/******************************************************************************
 * QwtPolar Widget Library
 * Copyright (C) 2008   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_polar_picker.h"
#include "qwt_polar_plot.h"
#include "qwt_polar_canvas.h"
#include "qwt_scale_map.h"
#include "qwt_picker_machine.h"
#include "qwt_point_polar.h"

class QwtPolarPicker::PrivateData
{
};

/*!
   \brief Create a polar plot picker
   \param canvas Plot canvas to observe, also the parent object
 */

QwtPolarPicker::QwtPolarPicker( QwtPolarCanvas* canvas )
    : QwtPicker( canvas )
    , m_data( nullptr )
{
}

/*!
   Create a plot picker

   \param rubberBand Rubberband style
   \param trackerMode Tracker mode
   \param canvas Plot canvas to observe, also the parent object

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

   \sa QwtPolarPlot::autoReplot(), QwtPolarPlot::replot(), scaleRect()
 */
QwtPolarPicker::QwtPolarPicker(
        RubberBand rubberBand, DisplayMode trackerMode, QwtPolarCanvas* canvas )
    : QwtPicker( rubberBand, trackerMode, canvas )
    , m_data( nullptr )
{
}

//! Destructor
QwtPolarPicker::~QwtPolarPicker()
{
}

//! \return Observed plot canvas
QwtPolarCanvas* QwtPolarPicker::canvas()
{
    return qobject_cast< QwtPolarCanvas* >( parentWidget() );
}

//! \return Observed plot canvas
const QwtPolarCanvas* QwtPolarPicker::canvas() const
{
    return qobject_cast< const QwtPolarCanvas* >( parentWidget() );
}

//! \return Plot widget, containing the observed plot canvas
QwtPolarPlot* QwtPolarPicker::plot()
{
    QwtPolarCanvas* w = canvas();
    if ( w )
        return w->plot();

    return NULL;
}

//! \return Plot widget, containing the observed plot canvas
const QwtPolarPlot* QwtPolarPicker::plot() const
{
    const QwtPolarCanvas* w = canvas();
    if ( w )
        return w->plot();

    return NULL;
}

/*!
   Translate a pixel position into a position string

   \param pos Position in pixel coordinates
   \return Position string
 */
QwtText QwtPolarPicker::trackerText( const QPoint& pos ) const
{
    const QwtPointPolar polarPoint = invTransform( pos );
    return trackerTextPolar( polarPoint );
}

/*!
   \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
 */
QwtText QwtPolarPicker::trackerTextPolar( const QwtPointPolar& pos ) const
{
    const QString text = QString::number( pos.radius(), 'f', 4 )
        + ", " + QString::number( pos.azimuth(), 'f', 4 );

    return QwtText( text );
}

/*!
   Append a point to the selection and update rubberband and tracker.

   \param pos Additional point
   \sa isActive, begin(), end(), move(), appended()

   \note The appended(const QPoint &), appended(const QDoublePoint &)
        signals are emitted.
 */
void QwtPolarPicker::append( const QPoint& pos )
{
    QwtPicker::append( pos );
    Q_EMIT appended( invTransform( pos ) );
}

/*!
   Move the last point of the selection

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

   \note The moved(const QPoint &), moved(const QDoublePoint &)
        signals are emitted.
 */
void QwtPolarPicker::move( const QPoint& pos )
{
    QwtPicker::move( pos );
    Q_EMIT moved( invTransform( pos ) );
}

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

   \param ok If true, complete the selection and emit selected signals
            otherwise discard the selection.
   \return true if the selection is accepted, false otherwise
 */

bool QwtPolarPicker::end( bool ok )
{
    ok = QwtPicker::end( ok );
    if ( !ok )
        return false;

    QwtPolarPlot* plot = QwtPolarPicker::plot();
    if ( !plot )
        return false;

    const QPolygon points = selection();
    if ( points.count() == 0 )
        return false;

    QwtPickerMachine::SelectionType selectionType =
        QwtPickerMachine::NoSelection;

    if ( stateMachine() )
        selectionType = stateMachine()->selectionType();

    switch ( selectionType )
    {
        case QwtPickerMachine::PointSelection:
        {
            const QwtPointPolar pos = invTransform( points[0] );
            Q_EMIT selected( pos );
            break;
        }
        case QwtPickerMachine::RectSelection:
        case QwtPickerMachine::PolygonSelection:
        {
            QVector< QwtPointPolar > polarPoints( points.count() );
            for ( int i = 0; i < points.count(); i++ )
                polarPoints[i] = invTransform( points[i] );

            Q_EMIT selected( polarPoints );
        }
        default:
            break;
    }

    return true;
}

/*!
    Translate a point from widget into plot coordinates

    \param pos Point in widget coordinates of the plot canvas
    \return Point in plot coordinates
    \sa transform(), canvas()
 */
QwtPointPolar QwtPolarPicker::invTransform( const QPoint& pos ) const
{
    QwtPointPolar polarPos;
    if ( canvas() == NULL )
        return QwtPointPolar();

    return canvas()->invTransform( pos );
}

/*!
    \return Bounding rectangle of the region, where picking is
            supported.
 */
QRect QwtPolarPicker::pickRect() const
{
    const QRect cr = canvas()->contentsRect();
    const QRect pr = plot()->plotRect( cr ).toRect();

    return cr & pr;
}

QPainterPath QwtPolarPicker::pickArea() const
{
    const QRect cr = canvas()->contentsRect();

    QPainterPath crPath;
    crPath.addRect( cr );

    QPainterPath prPath;
    prPath.addEllipse( plot()->plotRect( cr ) );

    return crPath.intersected( prPath );
}

#if QWT_MOC_INCLUDE
#include "moc_qwt_polar_picker.cpp"
#endif
