aboutsummaryrefslogtreecommitdiff
path: root/src/corelib/widgets/mpannablewidget.h
blob: 8f91e334ac57559327c6b5d1bda82a28fc415a3b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
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
/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#ifndef MPANNABLEWIDGET_H
#define MPANNABLEWIDGET_H

#include "mwidgetcontroller.h"
#include "mphysics2dpanning.h"
#include "mpannablewidgetmodel.h"

class QTimerEvent;
class QGraphicsSceneMouseEvent;
class QPanGesture;
class MPannableWidgetPrivate;
class MOnDisplayChangeEvent;

/*!
 * \class MPannableWidget
 * \brief Base class which adds support for panning gesture
 *
 * MPannableWidget creates a glass on top of itself and using the
 * glass, intercepts events coming from QGraphicsScene onto its area
 * and interprets them. If the events form a panning gesture, a
 * physics class is used to create a natural Newtonian movement in the
 * direction of panning. Panning position is provided as an
 * overridable slot updatePosition(). If the events don't form a
 * panning gesture, they are forwarded underneath the glass.
 *
 * In order to change the current position of the viewport the user
 * can call setPosition() method. When this is done, integration engine
 * is started and in case that the position is outside specified bounds,
 * the physics engine will start spring action to move the viewport to
 * the allowed borders.
 *
 * The physics engine object can be obtained by calling physics() method.
 *
 * \sa MPhysics2DPanning, MPannableViewport
 */
class M_CORE_EXPORT MPannableWidget : public MWidgetController
{
    Q_OBJECT
    M_CONTROLLER(MPannableWidget)

    //! \brief Vertical panning policy status
    Q_PROPERTY(PanningPolicy verticalPanningPolicy READ verticalPanningPolicy WRITE setVerticalPanningPolicy)
    //! \brief Horizontal panning policy status
    Q_PROPERTY(PanningPolicy horizontalPanningPolicy READ horizontalPanningPolicy WRITE setHorizontalPanningPolicy)
    //! \brief Enabled panning directions
    Q_PROPERTY(Qt::Orientations panDirection READ panDirection WRITE setPanDirection)
    //! \brief Panning range
    Q_PROPERTY(QRectF range READ range WRITE setRange)
    //! \brief Panning position
    Q_PROPERTY(QPointF position READ position WRITE setPosition NOTIFY positionChanged USER true)
    //! \brief Panning threshold
    Q_PROPERTY(qreal panThreshold READ panThreshold WRITE setPanThreshold)

public:

    /*!
     * This enum contains possible values of a panning policy.
     *
     * \li PanningAlwaysOn - the pannable widget will always react to pan gesture
     * \li PanningAlwaysOff - the pannable widget will never react to pan gesture
     * \li PanningAsNeeded - the pannable widget will only react to pan gesture if the panned
     *     widget is bigger than the viewport.
     *
     * \sa setHorizontalPanningPolicy, setVerticalPanningPolicy.
     */
    enum PanningPolicy {
        PanningAlwaysOn,
        PanningAlwaysOff,
        PanningAsNeeded
    };

    /*!
     * \brief Constructs a pannable widget with a \a parent.
     */
    MPannableWidget(QGraphicsItem *parent = 0);

    /*!
     * \brief Destroys the pannable widget.
     */
    virtual ~MPannableWidget();

    /*!
     * \brief Returns the physics class instance used in
     * panning.
     */
    MPhysics2DPanning *physics() const;

    /*!
     * \brief Sets the physics engine object used when the widget is
     * panning the view.
     *
     * This method can be used to modify the behaviour of the widget
     * so that the kinetic panning effect is different than default.
     *
     * The MPannableWidget will take ownership of the physics engine
     * object.
     */
    void setPhysics(MPhysics2DPanning *physics);

    /*!
     * \brief Sets the vertical panning policy of the pannable widget.
     *
     * This method allows for finegrained control over the panning
     * functionality in the MPannableWidget. The policy argument
     * will define the result of a vertical pan gesture executed
     * over pannable widget.
     *
     * This method does not reset horizontal panning policy.
     *
     * \sa verticalPanningPolicy and setPanDirection.
     */
    void setVerticalPanningPolicy(PanningPolicy policy);

    /*!
     * \brief Sets the horizontal panning policy of the pannable widget.
     *
     * This method allows for finegrained control over the panning
     * functionality in the MPannableWidget. The policy argument
     * will define the result of a horizontal pan gesture executed
     * over pannable widget.
     *
     * This method does not reset vertical panning policy.
     *
     * \sa horizontalPanningPolicy and setPanDirection.
     */
    void setHorizontalPanningPolicy(PanningPolicy policy);

    /*!
     * \brief Returns the vertical interactivity policy of the pannable widget.
     */
    PanningPolicy verticalPanningPolicy() const;

    /*!
     * \brief Returns the interactivity policy of the pannable widget.
     */
    PanningPolicy horizontalPanningPolicy() const;

    /*!
     * \brief Sets the \a range of panning.
     *
     * \sa range.
     */
    virtual void setRange(const QRectF &range);

    /*!
     * \brief Returns the range of panning.
     *
     * The range of panning defines the allowed positions of
     * the viewport over the panned widget. The panning range
     * is smaller than the panned widget size by the size of
     * the viewport.
     *
     * \note When range is zero along some axis, user can still make a
     * panning gesture on that direction but the position snaps back
     * to 0.0. If the range is shrank so that the current position
     * goes to border, the border springs are activated.
     *
     */
    virtual QRectF range() const;

    /*!
     * \brief Sets the \a position of the panning.
     *
     * If the new position is in the border, the border springs are
     * activated.
     *
     * By default, the position is QPointF(0,0).
     */
    virtual void setPosition(const QPointF &position);

    /*!
     * \brief Returns the current position of the panning.
     */
    virtual QPointF position() const;

    /*!
     * \brief Sets the enabled panning directions.
     *
     * This method allows enabling or disabling panning directions
     * of the pannable widget. It is an equivalent of methods
     * for setting panning policies: enabling a panning direction
     * has the same effect as setting PanningAlwaysOn policy for that
     * direction.Disabling a panning direction is exactly the same
     * as setting PanningAlwaysOff policy.
     *
     * The accepted values are Qt::Horizontal and/or Qt::Vertical.
     *
     * \sa setVerticalPanningPolicy and setHorizontalPanningPolicy.
     */
    virtual void setPanDirection(const Qt::Orientations &panDirection);

    /*!
     * \brief Returns the enabled panning directions.
     *
     * A panning direction is enabled if the policy of panning for
     * that direction is either PanningAlwaysOn or PanningAsNeeded.
     *
     * By default, the panning is enabled in Qt::Vertical direction.
     *
     * \deprecated Please use const version instead. Since 0.20.50
     */
    Qt::Orientations panDirection();

    /*!
     * \brief Returns the enabled panning directions.
     *
     * A panning direction is enabled if the policy of panning for
     * that direction is either PanningAlwaysOn or PanningAsNeeded.
     *
     * By default, the panning is enabled in Qt::Vertical direction.
     */
    Qt::Orientations panDirection() const;

    /*!
     * \brief Deprecated since 0.20
     */
    void setPanThreshold(qreal value);

    /*!
     * \brief Deprecated since 0.20.
     */
    qreal panThreshold();

    //! \reimp
    void setEnabled(bool enabled);
    bool isEnabled();
    //! \reimp_end

public Q_SLOTS:
    /*!
     * \brief Virtual slot for receiving position changes from
     * physics.
     */
    virtual void updatePosition(const QPointF &position);

Q_SIGNALS:

    /*!
     * \brief This signal is emitted when the position of the viewport changes.
     */
    void positionChanged(const QPointF &position);

    /*!
     * \brief When panned range changes this signal is emitted.
     */
    void rangeChanged(const QRectF &range);

    /*!
     * \brief Signals that the panning has stopped.
     */
    void panningStopped();

    /*!
     * \brief Signals that physics engine changed.
     */
    void physicsChanged();

protected:
    /*!
     * Protected constructor for derived classes.
     */
    MPannableWidget(MPannableWidgetPrivate *dd, MPannableWidgetModel *model,
                      QGraphicsItem *parent);

    //! \reimp
    virtual void cancelEvent(MCancelEvent *event);
    virtual void onDisplayChangeEvent(MOnDisplayChangeEvent *event);
    virtual void panGestureEvent(QGestureEvent *event, QPanGesture* state);
    virtual void tapAndHoldGestureEvent(QGestureEvent *event, QTapAndHoldGesture *gesture);
    virtual void orientationChangeEvent(MOrientationChangeEvent *event);
    //! \reimp_end

private:
    Q_DISABLE_COPY(MPannableWidget)
    Q_DECLARE_PRIVATE(MPannableWidget)


#ifdef UNIT_TEST
    // Test unit is defined as a friend of production code to access private members
    friend class Ut_MPannableWidget;
#endif

    friend class MPannableWidgetGlass;

    // We are using a hack which will allow reimplementing the panGestureEvent
    // method in the pannable widget without recompilation of all client applications.
    // This needs to be deleted when API unfreeze will finally happen.
    friend class MWidgetController;
};

#endif