~macslow/unity8/fix-1475678

« back to all changes in this revision

Viewing changes to plugins/Ubuntu/Gestures/DirectionalDragArea.h

  • Committer: Michał Sawicz
  • Date: 2013-06-05 22:03:08 UTC
  • Revision ID: michal.sawicz@canonical.com-20130605220308-yny8fv3futtr04fg
Inital unity8 commit.

Previous history can be found at https://code.launchpad.net/~unity-team/unity/phablet

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2013 Canonical, Ltd.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; version 3.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 */
 
16
 
 
17
#ifndef DIRECTIONAL_DRAG_AREA_H
 
18
#define DIRECTIONAL_DRAG_AREA_H
 
19
 
 
20
#include <QtQuick/QQuickItem>
 
21
#include "UbuntuGesturesGlobal.h"
 
22
#include "Damper.h"
 
23
 
 
24
/*
 
25
 An area that detects axis-aligned single-finger drag gestures
 
26
 
 
27
 If a drag deviates too much from the components' direction recognition will
 
28
 fail. It will also fail if the drag or flick is too short. E.g. a noisy or
 
29
 fidgety click
 
30
 
 
31
 See doc/DirectionalDragArea.svg
 
32
 */
 
33
class UBUNTUGESTURES_EXPORT DirectionalDragArea : public QQuickItem {
 
34
    Q_OBJECT
 
35
 
 
36
    // The direction in which the gesture should move in order to be recognized.
 
37
    Q_PROPERTY(Direction direction READ direction WRITE setDirection NOTIFY directionChanged)
 
38
 
 
39
    // The distance travelled by the finger along the axis specified by
 
40
    // DirectionalDragArea's direction.
 
41
    Q_PROPERTY(qreal distance READ distance NOTIFY distanceChanged)
 
42
 
 
43
    // Position of the touch point performing the drag.
 
44
    Q_PROPERTY(qreal touchX READ touchX NOTIFY touchXChanged)
 
45
    Q_PROPERTY(qreal touchY READ touchY NOTIFY touchYChanged)
 
46
 
 
47
    // The current status of the directional drag gesture area.
 
48
    Q_PROPERTY(Status status READ status NOTIFY statusChanged)
 
49
 
 
50
    // Whether a drag gesture is taking place
 
51
    // This will be true as long as status is Undecided or Recognized
 
52
    // When a gesture gets rejected, dragging turns to false.
 
53
    Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged)
 
54
 
 
55
    /////
 
56
    // stuff that will be set in stone at some point
 
57
 
 
58
    // How far the touch point can move away from its expected position before
 
59
    // it causes a rejection in the gesture recognition. This is to compensate
 
60
    // for both noise in the touch input signal and for the natural irregularities
 
61
    // in the finger movement.
 
62
    // Proper value is likely device-specific.
 
63
    Q_PROPERTY(qreal maxDeviation READ maxDeviation WRITE setMaxDeviation NOTIFY maxDeviationChanged)
 
64
 
 
65
    // Widening angle, in degrees
 
66
    // It's roughly the maximum angle a touch point can make relative to the
 
67
    // axis defined by the compoment's direction for it to be recognized as a
 
68
    // directional drag.
 
69
    Q_PROPERTY(qreal wideningAngle READ wideningAngle WRITE setWideningAngle
 
70
               NOTIFY wideningAngleChanged)
 
71
 
 
72
    // How far a touch point has to move from its initial position in order for
 
73
    // it to be recognized as a directional drag.
 
74
    Q_PROPERTY(qreal distanceThreshold READ distanceThreshold WRITE setDistanceThreshold
 
75
               NOTIFY distanceThresholdChanged)
 
76
 
 
77
    //
 
78
    /////
 
79
 
 
80
    Q_ENUMS(Direction)
 
81
    Q_ENUMS(Status)
 
82
public:
 
83
    DirectionalDragArea(QQuickItem *parent = 0);
 
84
 
 
85
    enum Direction { Rightwards, // Along the positive direction of the X axis
 
86
                     Leftwards, // Along the negative direction of the X axis
 
87
                     Downwards, // Along the positive direction of the Y axis
 
88
                     Upwards }; // Along the negative direction of the Y axis
 
89
    Direction direction() const;
 
90
    void setDirection(Direction);
 
91
 
 
92
    // Describes the state of the directional drag gesture.
 
93
    enum Status {
 
94
        // There's no touch point over this area.
 
95
        WaitingForTouch,
 
96
 
 
97
        // A touch point has landed on this area but it's not know yet whether it is
 
98
        // performing a drag in the correct direction.
 
99
        Undecided, //Recognizing,
 
100
 
 
101
        // There's a touch point in this area and it performed a drag in the correct
 
102
        // direction.
 
103
        //
 
104
        // Once recognized, the gesture state will move back to Absent only once
 
105
        // that touch point ends. The gesture will remain in the Recognized state even if
 
106
        // the touch point starts moving in other directions or halts.
 
107
        Recognized,
 
108
 
 
109
        // A gesture was performed but it wasn't a single-touch drag in the correct
 
110
        // direction.
 
111
        // It will remain in this state until there are no more touch points over this
 
112
        // area, at which point it will move to Absent state.
 
113
        Rejected
 
114
    };
 
115
    Status status() const { return m_status; }
 
116
 
 
117
    qreal distance() const;
 
118
 
 
119
    qreal touchX() const;
 
120
    qreal touchY() const;
 
121
 
 
122
    bool dragging() const { return (m_status == Undecided) || (m_status == Recognized); }
 
123
 
 
124
    qreal maxDeviation() const { return m_dampedPos.maxDelta(); }
 
125
    void setMaxDeviation(qreal value);
 
126
 
 
127
    qreal wideningAngle() const;
 
128
    void setWideningAngle(qreal value);
 
129
 
 
130
    qreal distanceThreshold() const { return m_distanceThreshold; }
 
131
    void setDistanceThreshold(qreal value);
 
132
 
 
133
Q_SIGNALS:
 
134
    void directionChanged(Direction direction);
 
135
    void statusChanged(Status value);
 
136
    void draggingChanged(bool value);
 
137
    void distanceChanged(qreal value);
 
138
    void maxDeviationChanged(qreal value);
 
139
    void wideningAngleChanged(qreal value);
 
140
    void distanceThresholdChanged(qreal value);
 
141
    void touchXChanged(qreal value);
 
142
    void touchYChanged(qreal value);
 
143
 
 
144
protected:
 
145
    virtual void touchEvent(QTouchEvent *event);
 
146
 
 
147
private:
 
148
    void touchEvent_absent(QTouchEvent *event);
 
149
    void touchEvent_undecided(QTouchEvent *event);
 
150
    void touchEvent_recognized(QTouchEvent *event);
 
151
    void touchEvent_rejected(QTouchEvent *event);
 
152
    bool pointInsideAllowedArea() const;
 
153
    bool movingInRightDirection() const;
 
154
    bool movedFarEnough(const QPointF &point) const;
 
155
    const QTouchEvent::TouchPoint *fetchTargetTouchPoint(QTouchEvent *event);
 
156
    void setStatus(Status newStatus);
 
157
    void setPreviousPos(QPointF point);
 
158
 
 
159
    // convenience functions
 
160
    bool directionIsHorizontal() const;
 
161
    bool directionIsVertical() const;
 
162
 
 
163
    Status m_status;
 
164
 
 
165
    QPointF m_startPos;
 
166
    QPointF m_previousPos;
 
167
    int m_touchId;
 
168
 
 
169
    // A movement damper is used in some of the gesture recognition calculations
 
170
    // to get rid of noise or small oscillations in the touch position.
 
171
    DampedPointF m_dampedPos;
 
172
    QPointF m_previousDampedPos;
 
173
 
 
174
    Direction m_direction;
 
175
    qreal m_wideningAngle; // in degrees
 
176
    qreal m_wideningFactor; // it's tan(degreesToRadian(m_wideningAngle))
 
177
    qreal m_distanceThreshold;
 
178
};
 
179
 
 
180
#endif // DIRECTIONAL_DRAG_AREA_H