Home | History | Annotate | Download | only in scroll
      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 using namespace std;
     40 
     41 namespace WebCore {
     42 
     43 ScrollAnimator::ScrollAnimator(ScrollableArea* scrollableArea)
     44     : m_scrollableArea(scrollableArea)
     45     , m_currentPosX(0)
     46     , m_currentPosY(0)
     47 {
     48 }
     49 
     50 ScrollAnimator::~ScrollAnimator()
     51 {
     52 }
     53 
     54 bool ScrollAnimator::scroll(ScrollbarOrientation orientation, ScrollGranularity, float step, float multiplier)
     55 {
     56     float* currentPos = (orientation == HorizontalScrollbar) ? &m_currentPosX : &m_currentPosY;
     57     float newPos = clampScrollPosition(orientation, *currentPos + step * multiplier);
     58     float delta = *currentPos - newPos;
     59     if (*currentPos == newPos)
     60         return false;
     61     *currentPos = newPos;
     62 
     63     notifyPositionChanged(orientation == HorizontalScrollbar ? FloatSize(delta, 0) : FloatSize(0, delta));
     64 
     65     return true;
     66 }
     67 
     68 void ScrollAnimator::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
     69 {
     70     FloatSize delta = FloatSize(offset.x() - m_currentPosX, offset.y() - m_currentPosY);
     71     m_currentPosX = offset.x();
     72     m_currentPosY = offset.y();
     73     notifyPositionChanged(delta);
     74 }
     75 
     76 bool ScrollAnimator::handleWheelEvent(const PlatformWheelEvent& e)
     77 {
     78     bool canScrollX = m_scrollableArea->userInputScrollable(HorizontalScrollbar);
     79     bool canScrollY = m_scrollableArea->userInputScrollable(VerticalScrollbar);
     80 
     81     // Accept the event if we are scrollable in that direction and can still
     82     // scroll any further.
     83     float deltaX = canScrollX ? e.deltaX() : 0;
     84     float deltaY = canScrollY ? e.deltaY() : 0;
     85 
     86     bool handled = false;
     87 
     88 #if !OS(MACOSX)
     89     ScrollGranularity granularity = e.hasPreciseScrollingDeltas() ? ScrollByPrecisePixel : ScrollByPixel;
     90 #else
     91     ScrollGranularity granularity = ScrollByPixel;
     92 #endif
     93 
     94     IntSize maxForwardScrollDelta = m_scrollableArea->maximumScrollPosition() - m_scrollableArea->scrollPosition();
     95     IntSize maxBackwardScrollDelta = m_scrollableArea->scrollPosition() - m_scrollableArea->minimumScrollPosition();
     96     if ((deltaX < 0 && maxForwardScrollDelta.width() > 0)
     97         || (deltaX > 0 && maxBackwardScrollDelta.width() > 0)
     98         || (deltaY < 0 && maxForwardScrollDelta.height() > 0)
     99         || (deltaY > 0 && maxBackwardScrollDelta.height() > 0)) {
    100         handled = true;
    101 
    102         if (deltaY) {
    103             if (e.granularity() == ScrollByPageWheelEvent) {
    104                 bool negative = deltaY < 0;
    105                 deltaY = m_scrollableArea->pageStep(VerticalScrollbar);
    106                 if (negative)
    107                     deltaY = -deltaY;
    108             }
    109 
    110             scroll(VerticalScrollbar, granularity, m_scrollableArea->pixelStep(VerticalScrollbar), -deltaY);
    111         }
    112 
    113         if (deltaX) {
    114             if (e.granularity() == ScrollByPageWheelEvent) {
    115                 bool negative = deltaX < 0;
    116                 deltaX = m_scrollableArea->pageStep(HorizontalScrollbar);
    117                 if (negative)
    118                     deltaX = -deltaX;
    119             }
    120 
    121             scroll(HorizontalScrollbar, granularity, m_scrollableArea->pixelStep(HorizontalScrollbar), -deltaX);
    122         }
    123     }
    124     return handled;
    125 }
    126 
    127 void ScrollAnimator::setCurrentPosition(const FloatPoint& position)
    128 {
    129     m_currentPosX = position.x();
    130     m_currentPosY = position.y();
    131 }
    132 
    133 FloatPoint ScrollAnimator::currentPosition() const
    134 {
    135     return FloatPoint(m_currentPosX, m_currentPosY);
    136 }
    137 
    138 void ScrollAnimator::notifyPositionChanged(const FloatSize&)
    139 {
    140     m_scrollableArea->setScrollOffsetFromAnimation(IntPoint(m_currentPosX, m_currentPosY));
    141 }
    142 
    143 float ScrollAnimator::clampScrollPosition(ScrollbarOrientation orientation, float pos)
    144 {
    145     float maxScrollPos = m_scrollableArea->maximumScrollPosition(orientation);
    146     float minScrollPos = m_scrollableArea->minimumScrollPosition(orientation);
    147     return std::max(std::min(pos, maxScrollPos), minScrollPos);
    148 }
    149 
    150 } // namespace WebCore
    151