Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / scroll / ScrollAnimator.cpp
1 /*
2  * Copyright (c) 2010, Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "platform/scroll/ScrollAnimator.h"
33
34 #include "platform/geometry/FloatPoint.h"
35 #include "platform/scroll/ScrollableArea.h"
36 #include "wtf/PassOwnPtr.h"
37 #include <algorithm>
38
39 namespace blink {
40
41 ScrollAnimator::ScrollAnimator(ScrollableArea* scrollableArea)
42     : m_scrollableArea(scrollableArea)
43     , m_currentPosX(0)
44     , m_currentPosY(0)
45 {
46 }
47
48 ScrollAnimator::~ScrollAnimator()
49 {
50 }
51
52 bool ScrollAnimator::scroll(ScrollbarOrientation orientation, ScrollGranularity, float step, float delta)
53 {
54     float& currentPos = (orientation == HorizontalScrollbar) ? m_currentPosX : m_currentPosY;
55     float newPos = clampScrollPosition(orientation, currentPos + step * delta);
56     if (currentPos == newPos)
57         return false;
58     currentPos = newPos;
59
60     notifyPositionChanged();
61
62     return true;
63 }
64
65 void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
66 {
67     m_currentPosX = offset.x();
68     m_currentPosY = offset.y();
69     notifyPositionChanged();
70 }
71
72 bool ScrollAnimator::handleWheelEvent(const PlatformWheelEvent& e)
73 {
74     bool canScrollX = m_scrollableArea->userInputScrollable(HorizontalScrollbar);
75     bool canScrollY = m_scrollableArea->userInputScrollable(VerticalScrollbar);
76
77     // Accept the event if we are scrollable in that direction and can still
78     // scroll any further.
79     float deltaX = canScrollX ? e.deltaX() : 0;
80     float deltaY = canScrollY ? e.deltaY() : 0;
81
82     bool handled = false;
83
84 #if !OS(MACOSX)
85     ScrollGranularity granularity = e.hasPreciseScrollingDeltas() ? ScrollByPrecisePixel : ScrollByPixel;
86 #else
87     ScrollGranularity granularity = ScrollByPixel;
88 #endif
89
90     IntSize maxForwardScrollDelta = m_scrollableArea->maximumScrollPosition() - m_scrollableArea->scrollPosition();
91     IntSize maxBackwardScrollDelta = m_scrollableArea->scrollPosition() - m_scrollableArea->minimumScrollPosition();
92     if ((deltaX < 0 && maxForwardScrollDelta.width() > 0)
93         || (deltaX > 0 && maxBackwardScrollDelta.width() > 0)
94         || (deltaY < 0 && maxForwardScrollDelta.height() > 0)
95         || (deltaY > 0 && maxBackwardScrollDelta.height() > 0)) {
96         handled = true;
97
98         if (deltaY) {
99             if (e.granularity() == ScrollByPageWheelEvent) {
100                 bool negative = deltaY < 0;
101                 deltaY = m_scrollableArea->pageStep(VerticalScrollbar);
102                 if (negative)
103                     deltaY = -deltaY;
104             }
105
106             scroll(VerticalScrollbar, granularity, m_scrollableArea->pixelStep(VerticalScrollbar), -deltaY);
107         }
108
109         if (deltaX) {
110             if (e.granularity() == ScrollByPageWheelEvent) {
111                 bool negative = deltaX < 0;
112                 deltaX = m_scrollableArea->pageStep(HorizontalScrollbar);
113                 if (negative)
114                     deltaX = -deltaX;
115             }
116
117             scroll(HorizontalScrollbar, granularity, m_scrollableArea->pixelStep(HorizontalScrollbar), -deltaX);
118         }
119     }
120     return handled;
121 }
122
123 void ScrollAnimator::setCurrentPosition(const FloatPoint& position)
124 {
125     m_currentPosX = position.x();
126     m_currentPosY = position.y();
127 }
128
129 FloatPoint ScrollAnimator::currentPosition() const
130 {
131     return FloatPoint(m_currentPosX, m_currentPosY);
132 }
133
134 void ScrollAnimator::notifyPositionChanged()
135 {
136     m_scrollableArea->setScrollOffsetFromAnimation(IntPoint(m_currentPosX, m_currentPosY));
137 }
138
139 float ScrollAnimator::clampScrollPosition(ScrollbarOrientation orientation, float pos)
140 {
141     float maxScrollPos = m_scrollableArea->maximumScrollPosition(orientation);
142     float minScrollPos = m_scrollableArea->minimumScrollPosition(orientation);
143     return std::max(std::min(pos, maxScrollPos), minScrollPos);
144 }
145
146 } // namespace blink