Home | History | Annotate | Download | only in platform
      1 /*
      2  * Copyright (c) 2010, Google Inc. All rights reserved.
      3  * Copyright (C) 2008, 2011 Apple Inc. All Rights Reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  *     * Redistributions of source code must retain the above copyright
     10  * notice, this list of conditions and the following disclaimer.
     11  *     * Redistributions in binary form must reproduce the above
     12  * copyright notice, this list of conditions and the following disclaimer
     13  * in the documentation and/or other materials provided with the
     14  * distribution.
     15  *     * Neither the name of Google Inc. nor the names of its
     16  * contributors may be used to endorse or promote products derived from
     17  * this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include "config.h"
     33 #include "ScrollableArea.h"
     34 
     35 #include "GraphicsContext.h"
     36 #include "GraphicsLayer.h"
     37 #include "FloatPoint.h"
     38 #include "PlatformWheelEvent.h"
     39 #include "ScrollAnimator.h"
     40 #include "ScrollbarTheme.h"
     41 #include <wtf/PassOwnPtr.h>
     42 
     43 namespace WebCore {
     44 
     45 ScrollableArea::ScrollableArea()
     46     : m_scrollAnimator(ScrollAnimator::create(this))
     47     , m_constrainsScrollingToContentEdge(true)
     48     , m_inLiveResize(false)
     49     , m_verticalScrollElasticity(ScrollElasticityNone)
     50     , m_horizontalScrollElasticity(ScrollElasticityNone)
     51 {
     52 }
     53 
     54 ScrollableArea::~ScrollableArea()
     55 {
     56 }
     57 
     58 bool ScrollableArea::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
     59 {
     60     ScrollbarOrientation orientation;
     61     Scrollbar* scrollbar;
     62     if (direction == ScrollUp || direction == ScrollDown) {
     63         orientation = VerticalScrollbar;
     64         scrollbar = verticalScrollbar();
     65     } else {
     66         orientation = HorizontalScrollbar;
     67         scrollbar = horizontalScrollbar();
     68     }
     69 
     70     if (!scrollbar)
     71         return false;
     72 
     73     float step = 0;
     74     switch (granularity) {
     75     case ScrollByLine:
     76         step = scrollbar->lineStep();
     77         break;
     78     case ScrollByPage:
     79         step = scrollbar->pageStep();
     80         break;
     81     case ScrollByDocument:
     82         step = scrollbar->totalSize();
     83         break;
     84     case ScrollByPixel:
     85         step = scrollbar->pixelStep();
     86         break;
     87     }
     88 
     89     if (direction == ScrollUp || direction == ScrollLeft)
     90         multiplier = -multiplier;
     91 
     92     return m_scrollAnimator->scroll(orientation, granularity, step, multiplier);
     93 }
     94 
     95 void ScrollableArea::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
     96 {
     97     m_scrollAnimator->scrollToOffsetWithoutAnimation(offset);
     98 }
     99 
    100 void ScrollableArea::scrollToOffsetWithoutAnimation(ScrollbarOrientation orientation, float offset)
    101 {
    102     if (orientation == HorizontalScrollbar)
    103         scrollToXOffsetWithoutAnimation(offset);
    104     else
    105         scrollToYOffsetWithoutAnimation(offset);
    106 }
    107 
    108 void ScrollableArea::scrollToXOffsetWithoutAnimation(float x)
    109 {
    110     scrollToOffsetWithoutAnimation(FloatPoint(x, m_scrollAnimator->currentPosition().y()));
    111 }
    112 
    113 void ScrollableArea::scrollToYOffsetWithoutAnimation(float y)
    114 {
    115     scrollToOffsetWithoutAnimation(FloatPoint(m_scrollAnimator->currentPosition().x(), y));
    116 }
    117 
    118 void ScrollableArea::handleWheelEvent(PlatformWheelEvent& wheelEvent)
    119 {
    120     m_scrollAnimator->handleWheelEvent(wheelEvent);
    121 }
    122 
    123 #if ENABLE(GESTURE_EVENTS)
    124 void ScrollableArea::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
    125 {
    126     m_scrollAnimator->handleGestureEvent(gestureEvent);
    127 }
    128 #endif
    129 
    130 void ScrollableArea::setScrollOffsetFromAnimation(const IntPoint& offset)
    131 {
    132     // Tell the derived class to scroll its contents.
    133     setScrollOffset(offset);
    134 
    135     Scrollbar* verticalScrollbar = this->verticalScrollbar();
    136 
    137     // Tell the scrollbars to update their thumb postions.
    138     if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) {
    139         horizontalScrollbar->offsetDidChange();
    140         if (horizontalScrollbar->isOverlayScrollbar()) {
    141             if (!verticalScrollbar)
    142                 horizontalScrollbar->invalidate();
    143             else {
    144                 // If there is both a horizontalScrollbar and a verticalScrollbar,
    145                 // then we must also invalidate the corner between them.
    146                 IntRect boundsAndCorner = horizontalScrollbar->boundsRect();
    147                 boundsAndCorner.setWidth(boundsAndCorner.width() + verticalScrollbar->width());
    148                 horizontalScrollbar->invalidateRect(boundsAndCorner);
    149             }
    150         }
    151     }
    152     if (verticalScrollbar) {
    153         verticalScrollbar->offsetDidChange();
    154         if (verticalScrollbar->isOverlayScrollbar())
    155             verticalScrollbar->invalidate();
    156     }
    157 }
    158 
    159 void ScrollableArea::willStartLiveResize()
    160 {
    161     if (m_inLiveResize)
    162         return;
    163     m_inLiveResize = true;
    164     scrollAnimator()->willStartLiveResize();
    165 }
    166 
    167 void ScrollableArea::willEndLiveResize()
    168 {
    169     if (!m_inLiveResize)
    170         return;
    171     m_inLiveResize = false;
    172     scrollAnimator()->willEndLiveResize();
    173 }
    174 
    175 void ScrollableArea::didAddVerticalScrollbar(Scrollbar* scrollbar)
    176 {
    177     scrollAnimator()->didAddVerticalScrollbar(scrollbar);
    178 }
    179 
    180 void ScrollableArea::willRemoveVerticalScrollbar(Scrollbar* scrollbar)
    181 {
    182     scrollAnimator()->willRemoveVerticalScrollbar(scrollbar);
    183 }
    184 
    185 void ScrollableArea::didAddHorizontalScrollbar(Scrollbar* scrollbar)
    186 {
    187     scrollAnimator()->didAddHorizontalScrollbar(scrollbar);
    188 }
    189 
    190 void ScrollableArea::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
    191 {
    192     scrollAnimator()->willRemoveHorizontalScrollbar(scrollbar);
    193 }
    194 
    195 bool ScrollableArea::hasOverlayScrollbars() const
    196 {
    197     return (verticalScrollbar() && verticalScrollbar()->isOverlayScrollbar())
    198         || (horizontalScrollbar() && horizontalScrollbar()->isOverlayScrollbar());
    199 }
    200 
    201 void ScrollableArea::invalidateScrollbar(Scrollbar* scrollbar, const IntRect& rect)
    202 {
    203 #if USE(ACCELERATED_COMPOSITING)
    204     if (scrollbar == horizontalScrollbar()) {
    205         if (GraphicsLayer* graphicsLayer = layerForHorizontalScrollbar()) {
    206             graphicsLayer->setNeedsDisplay();
    207             return;
    208         }
    209     } else if (scrollbar == verticalScrollbar()) {
    210         if (GraphicsLayer* graphicsLayer = layerForVerticalScrollbar()) {
    211             graphicsLayer->setNeedsDisplay();
    212             return;
    213         }
    214     }
    215 #endif
    216     invalidateScrollbarRect(scrollbar, rect);
    217 }
    218 
    219 void ScrollableArea::invalidateScrollCorner()
    220 {
    221 #if USE(ACCELERATED_COMPOSITING)
    222     if (GraphicsLayer* graphicsLayer = layerForScrollCorner()) {
    223         graphicsLayer->setNeedsDisplay();
    224         return;
    225     }
    226 #endif
    227     invalidateScrollCornerRect(scrollCornerRect());
    228 }
    229 
    230 } // namespace WebCore
    231