1/*
2 * Copyright (C) 2011, 2012 Nokia Corporation and/or its subsidiary(-ies)
3 * Copyright (C) 2011 Benjamin Poulain <benjamin@webkit.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this program; see the file COPYING.LIB.  If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22#ifndef PageViewportControllerClientQt_h
23#define PageViewportControllerClientQt_h
24
25#include "PageViewportController.h"
26#include "PageViewportControllerClient.h"
27#include <QObject>
28#include <QPointF>
29#include <QScopedPointer>
30#include <QVariant>
31#include <QVariantAnimation>
32
33QT_BEGIN_NAMESPACE
34class QRectF;
35QT_END_NAMESPACE
36
37class QQuickWebPage;
38class QQuickWebView;
39class QWebKitTest;
40
41namespace WebKit {
42
43class PageViewportControllerClientQt : public QObject, public PageViewportControllerClient {
44    Q_OBJECT
45
46public:
47    PageViewportControllerClientQt(QQuickWebView*, QQuickWebPage*);
48    ~PageViewportControllerClientQt();
49
50    virtual void setViewportPosition(const WebCore::FloatPoint& contentsPoint);
51    virtual void setPageScaleFactor(float);
52
53    virtual void didChangeContentsSize(const WebCore::IntSize&);
54    virtual void didChangeVisibleContents();
55    virtual void didChangeViewportAttributes();
56
57    virtual void setController(PageViewportController* controller) { m_controller = controller; }
58
59    // Additional methods currently only relevant in the QQuick context.
60    void touchBegin();
61    void touchEnd();
62
63    bool scrollAnimationActive() const;
64    void cancelScrollAnimation();
65
66    void panGestureStarted(const QPointF& position, qint64 eventTimestampMillis);
67    void panGestureRequestUpdate(const QPointF& position, qint64 eventTimestampMillis);
68    void panGestureEnded(const QPointF& position, qint64 eventTimestampMillis);
69    void panGestureCancelled();
70
71    bool scaleAnimationActive() const;
72    void interruptScaleAnimation();
73
74    void pinchGestureStarted(const QPointF& pinchCenterInViewportCoordinates);
75    void pinchGestureRequestUpdate(const QPointF& pinchCenterInViewportCoordinates, qreal totalScaleFactor);
76    void pinchGestureEnded();
77    void pinchGestureCancelled();
78
79    void zoomToAreaGestureEnded(const QPointF& touchPoint, const QRectF& targetArea);
80    void focusEditableArea(const QRectF& caretArea, const QRectF& targetArea);
81
82private Q_SLOTS:
83    // Respond to changes of position that are not driven by us.
84    void pageItemPositionChanged();
85
86    void scaleAnimationStateChanged(QAbstractAnimation::State, QAbstractAnimation::State);
87
88    void flickMoveStarted(); // Called when panning starts.
89    void flickMoveEnded(); //   Called when panning (+ kinetic animation) ends.
90
91private:
92    class ScaleAnimation : public QVariantAnimation {
93        PageViewportControllerClientQt* m_controllerClient;
94    public:
95        ScaleAnimation(PageViewportControllerClientQt* parent)
96            : QVariantAnimation(parent)
97            , m_controllerClient(parent)
98        { }
99
100        virtual void updateCurrentValue(const QVariant&);
101    };
102
103    class ViewportInteractionTracker {
104    public:
105        ViewportInteractionTracker(PageViewportControllerClientQt* client, bool shouldSuspend = true)
106            : m_controllerClient(client)
107            , m_shouldSuspend(shouldSuspend)
108            , m_inProgress(false)
109        { }
110
111        void begin();
112        void end();
113        bool inProgress() const { return m_inProgress; }
114
115    private:
116        PageViewportControllerClientQt* m_controllerClient;
117        bool m_shouldSuspend;
118        bool m_inProgress;
119    };
120
121    struct ScaleStackItem {
122        ScaleStackItem(qreal scale, qreal xPosition)
123            : scale(scale)
124            , xPosition(xPosition)
125        { }
126
127        qreal scale;
128        qreal xPosition;
129    };
130
131    friend class ViewportInteractionTracker;
132    friend class ScaleAnimation;
133    friend class ::QWebKitTest;
134
135    PageViewportController* m_controller;
136    QQuickWebView* const m_viewportItem;
137    QQuickWebPage* const m_pageItem;
138
139    float viewportScaleForRect(const QRectF&) const;
140    QRectF nearestValidVisibleContentsRect() const;
141
142    void setContentsRectToNearestValidBounds();
143    void updateViewportController(const QPointF& trajectory = QPointF());
144    void setContentRectVisiblePositionAtScale(const QPointF& location, qreal itemScale);
145    void animateContentRectVisible(const QRectF& contentRect);
146    void scaleContent(qreal itemScale, const QPointF& centerInCSSCoordinates = QPointF());
147    void clearRelativeZoomState();
148
149    ViewportInteractionTracker m_scaleChange;
150    ViewportInteractionTracker m_scrollChange;
151    ViewportInteractionTracker m_touchInteraction;
152
153    ScaleAnimation* m_scaleAnimation;
154    QPointF m_lastPinchCenterInViewportCoordinates;
155    QPointF m_lastScrollPosition;
156    int m_activeInteractionCount;
157    qreal m_pinchStartScale;
158    qreal m_lastCommittedScale;
159    qreal m_zoomOutScale;
160    QList<ScaleStackItem> m_scaleStack;
161};
162
163} // namespace WebKit
164
165#endif // PageViewportControllerClientQt_h
166