15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (c) 2010, Google Inc. All rights reserved.
302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
1702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
32a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/scroll/ScrollAnimator.h"
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
341e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/FloatPoint.h"
35a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/scroll/ScrollableArea.h"
367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/PassOwnPtr.h"
371e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include <algorithm>
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace std;
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ScrollAnimator::ScrollAnimator(ScrollableArea* scrollableArea)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : m_scrollableArea(scrollableArea)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_currentPosX(0)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_currentPosY(0)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ScrollAnimator::~ScrollAnimator()
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool ScrollAnimator::scroll(ScrollbarOrientation orientation, ScrollGranularity, float step, float multiplier)
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float* currentPos = (orientation == HorizontalScrollbar) ? &m_currentPosX : &m_currentPosY;
575267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    float newPos = clampScrollPosition(orientation, *currentPos + step * multiplier);
58926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    float delta = *currentPos - newPos;
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (*currentPos == newPos)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    *currentPos = newPos;
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
63926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    notifyPositionChanged(orientation == HorizontalScrollbar ? FloatSize(delta, 0) : FloatSize(0, delta));
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    FloatSize delta = FloatSize(offset.x() - m_currentPosX, offset.y() - m_currentPosY);
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_currentPosX = offset.x();
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_currentPosY = offset.y();
73926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    notifyPositionChanged(delta);
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool ScrollAnimator::handleWheelEvent(const PlatformWheelEvent& e)
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
78f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    bool canScrollX = m_scrollableArea->userInputScrollable(HorizontalScrollbar);
79f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    bool canScrollY = m_scrollableArea->userInputScrollable(VerticalScrollbar);
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
81f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    // Accept the event if we are scrollable in that direction and can still
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // scroll any further.
83f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    float deltaX = canScrollX ? e.deltaX() : 0;
84f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    float deltaY = canScrollY ? e.deltaY() : 0;
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool handled = false;
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
888abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)#if !OS(MACOSX)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ScrollGranularity granularity = e.hasPreciseScrollingDeltas() ? ScrollByPrecisePixel : ScrollByPixel;
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#else
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ScrollGranularity granularity = ScrollByPixel;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntSize maxForwardScrollDelta = m_scrollableArea->maximumScrollPosition() - m_scrollableArea->scrollPosition();
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntSize maxBackwardScrollDelta = m_scrollableArea->scrollPosition() - m_scrollableArea->minimumScrollPosition();
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if ((deltaX < 0 && maxForwardScrollDelta.width() > 0)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || (deltaX > 0 && maxBackwardScrollDelta.width() > 0)
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || (deltaY < 0 && maxForwardScrollDelta.height() > 0)
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        || (deltaY > 0 && maxBackwardScrollDelta.height() > 0)) {
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        handled = true;
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (deltaY) {
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (e.granularity() == ScrollByPageWheelEvent) {
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                bool negative = deltaY < 0;
105f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                deltaY = m_scrollableArea->pageStep(VerticalScrollbar);
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (negative)
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    deltaY = -deltaY;
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
109f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
110f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            scroll(VerticalScrollbar, granularity, m_scrollableArea->pixelStep(VerticalScrollbar), -deltaY);
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (deltaX) {
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (e.granularity() == ScrollByPageWheelEvent) {
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                bool negative = deltaX < 0;
116f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)                deltaX = m_scrollableArea->pageStep(HorizontalScrollbar);
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (negative)
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    deltaX = -deltaX;
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
120f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
121f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)            scroll(HorizontalScrollbar, granularity, m_scrollableArea->pixelStep(HorizontalScrollbar), -deltaX);
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return handled;
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ScrollAnimator::setCurrentPosition(const FloatPoint& position)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_currentPosX = position.x();
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_currentPosY = position.y();
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FloatPoint ScrollAnimator::currentPosition() const
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return FloatPoint(m_currentPosX, m_currentPosY);
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
138a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void ScrollAnimator::notifyPositionChanged(const FloatSize&)
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_scrollableArea->setScrollOffsetFromAnimation(IntPoint(m_currentPosX, m_currentPosY));
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)float ScrollAnimator::clampScrollPosition(ScrollbarOrientation orientation, float pos)
1445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
1455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    float maxScrollPos = m_scrollableArea->maximumScrollPosition(orientation);
1465267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    float minScrollPos = m_scrollableArea->minimumScrollPosition(orientation);
1475267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    return std::max(std::min(pos, maxScrollPos), minScrollPos);
1485267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
1495267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
151