1 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2  * QwtPolar Widget Library
3  * Copyright (C) 2008   Uwe Rathmann
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the Qwt License, Version 1.0
7  *****************************************************************************/
8 
9 #include "qwt_polar_picker.h"
10 #include "qwt_polar_plot.h"
11 #include "qwt_polar_canvas.h"
12 #include <qwt_scale_map.h>
13 #include <qwt_picker_machine.h>
14 #include <qwt_point_polar.h>
15 
16 class QwtPolarPicker::PrivateData
17 {
18 public:
PrivateData()19     PrivateData()
20     {
21     }
22 };
23 
24 /*!
25   \brief Create a polar plot picker
26   \param canvas Plot canvas to observe, also the parent object
27 */
28 
QwtPolarPicker(QwtPolarCanvas * canvas)29 QwtPolarPicker::QwtPolarPicker( QwtPolarCanvas *canvas ):
30     QwtPicker( canvas )
31 {
32     d_data = new PrivateData;
33 }
34 
35 /*!
36   Create a plot picker
37 
38   \param rubberBand Rubberband style
39   \param trackerMode Tracker mode
40   \param canvas Plot canvas to observe, also the parent object
41 
42   \sa QwtPicker, QwtPicker::setSelectionFlags(), QwtPicker::setRubberBand(),
43       QwtPicker::setTrackerMode
44 
45   \sa QwtPolarPlot::autoReplot(), QwtPolarPlot::replot(), scaleRect()
46 */
QwtPolarPicker(RubberBand rubberBand,DisplayMode trackerMode,QwtPolarCanvas * canvas)47 QwtPolarPicker::QwtPolarPicker(
48         RubberBand rubberBand, DisplayMode trackerMode,
49         QwtPolarCanvas *canvas ):
50     QwtPicker( rubberBand, trackerMode, canvas )
51 {
52     d_data = new PrivateData;
53 }
54 
55 //! Destructor
~QwtPolarPicker()56 QwtPolarPicker::~QwtPolarPicker()
57 {
58     delete d_data;
59 }
60 
61 //! \return Observed plot canvas
canvas()62 QwtPolarCanvas *QwtPolarPicker::canvas()
63 {
64     return qobject_cast<QwtPolarCanvas *>( parentWidget() );
65 }
66 
67 //! \return Observed plot canvas
canvas() const68 const QwtPolarCanvas *QwtPolarPicker::canvas() const
69 {
70     return qobject_cast<const QwtPolarCanvas *>( parentWidget() );
71 }
72 
73 //! \return Plot widget, containing the observed plot canvas
plot()74 QwtPolarPlot *QwtPolarPicker::plot()
75 {
76     QwtPolarCanvas *w = canvas();
77     if ( w )
78         return w->plot();
79 
80     return NULL;
81 }
82 
83 //! \return Plot widget, containing the observed plot canvas
plot() const84 const QwtPolarPlot *QwtPolarPicker::plot() const
85 {
86     const QwtPolarCanvas *w = canvas();
87     if ( w )
88         return w->plot();
89 
90     return NULL;
91 }
92 
93 /*!
94   Translate a pixel position into a position string
95 
96   \param pos Position in pixel coordinates
97   \return Position string
98 */
trackerText(const QPoint & pos) const99 QwtText QwtPolarPicker::trackerText( const QPoint &pos ) const
100 {
101     const QwtPointPolar polarPoint = invTransform( pos );
102     return trackerTextPolar( polarPoint );
103 }
104 
105 /*!
106   \brief Translate a position into a position string
107 
108   In case of HLineRubberBand the label is the value of the
109   y position, in case of VLineRubberBand the value of the x position.
110   Otherwise the label contains x and y position separated by a ',' .
111 
112   The format for the double to string conversion is "%.4f".
113 
114   \param pos Position
115   \return Position string
116 */
trackerTextPolar(const QwtPointPolar & pos) const117 QwtText QwtPolarPicker::trackerTextPolar( const QwtPointPolar &pos ) const
118 {
119     QString text;
120     text.sprintf( "%.4f, %.4f", pos.radius(), pos.azimuth() );
121 
122     return QwtText( text );
123 }
124 
125 /*!
126   Append a point to the selection and update rubberband and tracker.
127 
128   \param pos Additional point
129   \sa isActive, begin(), end(), move(), appended()
130 
131   \note The appended(const QPoint &), appended(const QDoublePoint &)
132         signals are emitted.
133 */
append(const QPoint & pos)134 void QwtPolarPicker::append( const QPoint &pos )
135 {
136     QwtPicker::append( pos );
137     Q_EMIT appended( invTransform( pos ) );
138 }
139 
140 /*!
141   Move the last point of the selection
142 
143   \param pos New position
144   \sa isActive, begin(), end(), append()
145 
146   \note The moved(const QPoint &), moved(const QDoublePoint &)
147         signals are emitted.
148 */
move(const QPoint & pos)149 void QwtPolarPicker::move( const QPoint &pos )
150 {
151     QwtPicker::move( pos );
152     Q_EMIT moved( invTransform( pos ) );
153 }
154 
155 /*!
156   Close a selection setting the state to inactive.
157 
158   \param ok If true, complete the selection and emit selected signals
159             otherwise discard the selection.
160   \return true if the selection is accepted, false otherwise
161 */
162 
end(bool ok)163 bool QwtPolarPicker::end( bool ok )
164 {
165     ok = QwtPicker::end( ok );
166     if ( !ok )
167         return false;
168 
169     QwtPolarPlot *plot = QwtPolarPicker::plot();
170     if ( !plot )
171         return false;
172 
173     const QPolygon points = selection();
174     if ( points.count() == 0 )
175         return false;
176 
177     QwtPickerMachine::SelectionType selectionType =
178         QwtPickerMachine::NoSelection;
179 
180     if ( stateMachine() )
181         selectionType = stateMachine()->selectionType();
182 
183     switch ( selectionType )
184     {
185         case QwtPickerMachine::PointSelection:
186         {
187             const QwtPointPolar pos = invTransform( points[0] );
188             Q_EMIT selected( pos );
189             break;
190         }
191         case QwtPickerMachine::RectSelection:
192         case QwtPickerMachine::PolygonSelection:
193         {
194             QVector<QwtPointPolar> polarPoints( points.count() );
195             for ( int i = 0; i < points.count(); i++ )
196                 polarPoints[i] = invTransform( points[i] );
197 
198             Q_EMIT selected( polarPoints );
199         }
200         default:
201             break;
202     }
203 
204     return true;
205 }
206 
207 /*!
208     Translate a point from widget into plot coordinates
209 
210     \param pos Point in widget coordinates of the plot canvas
211     \return Point in plot coordinates
212     \sa transform(), canvas()
213 */
invTransform(const QPoint & pos) const214 QwtPointPolar QwtPolarPicker::invTransform( const QPoint &pos ) const
215 {
216     QwtPointPolar polarPos;
217     if ( canvas() == NULL )
218         return QwtPointPolar();
219 
220     return canvas()->invTransform( pos );
221 }
222 
223 /*!
224     \return Bounding rectangle of the region, where picking is
225             supported.
226 */
pickRect() const227 QRect QwtPolarPicker::pickRect() const
228 {
229     const QRect cr = canvas()->contentsRect();
230     const QRect pr = plot()->plotRect( cr ).toRect();
231 
232     return cr & pr;
233 }
234 
pickArea() const235 QPainterPath QwtPolarPicker::pickArea() const
236 {
237     const QRect cr = canvas()->contentsRect();
238 
239     QPainterPath crPath;
240     crPath.addRect( cr );
241 
242     QPainterPath prPath;
243     prPath.addEllipse( plot()->plotRect( cr ) );
244 
245     return crPath.intersected( prPath );
246 }
247