Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2008 Apple 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
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "core/rendering/RenderScrollbarPart.h"
     28 
     29 #include "core/rendering/PaintInfo.h"
     30 #include "core/rendering/RenderScrollbar.h"
     31 #include "core/rendering/RenderScrollbarTheme.h"
     32 #include "core/rendering/RenderView.h"
     33 #include "platform/LengthFunctions.h"
     34 
     35 using namespace std;
     36 
     37 namespace WebCore {
     38 
     39 RenderScrollbarPart::RenderScrollbarPart(RenderScrollbar* scrollbar, ScrollbarPart part)
     40     : RenderBlock(0)
     41     , m_scrollbar(scrollbar)
     42     , m_part(part)
     43 {
     44 }
     45 
     46 RenderScrollbarPart::~RenderScrollbarPart()
     47 {
     48 }
     49 
     50 RenderScrollbarPart* RenderScrollbarPart::createAnonymous(Document* document, RenderScrollbar* scrollbar, ScrollbarPart part)
     51 {
     52     RenderScrollbarPart* renderer = new RenderScrollbarPart(scrollbar, part);
     53     renderer->setDocumentForAnonymous(document);
     54     return renderer;
     55 }
     56 
     57 void RenderScrollbarPart::layout()
     58 {
     59     setLocation(LayoutPoint()); // We don't worry about positioning ourselves. We're just determining our minimum width/height.
     60     if (m_scrollbar->orientation() == HorizontalScrollbar)
     61         layoutHorizontalPart();
     62     else
     63         layoutVerticalPart();
     64 
     65     clearNeedsLayout();
     66 }
     67 
     68 void RenderScrollbarPart::layoutHorizontalPart()
     69 {
     70     if (m_part == ScrollbarBGPart) {
     71         setWidth(m_scrollbar->width());
     72         computeScrollbarHeight();
     73     } else {
     74         computeScrollbarWidth();
     75         setHeight(m_scrollbar->height());
     76     }
     77 }
     78 
     79 void RenderScrollbarPart::layoutVerticalPart()
     80 {
     81     if (m_part == ScrollbarBGPart) {
     82         computeScrollbarWidth();
     83         setHeight(m_scrollbar->height());
     84     } else {
     85         setWidth(m_scrollbar->width());
     86         computeScrollbarHeight();
     87     }
     88 }
     89 
     90 static int calcScrollbarThicknessUsing(SizeType sizeType, const Length& length, int containingLength)
     91 {
     92     if (!length.isIntrinsicOrAuto() || (sizeType == MinSize && length.isAuto()))
     93         return minimumValueForLength(length, containingLength);
     94     return ScrollbarTheme::theme()->scrollbarThickness();
     95 }
     96 
     97 void RenderScrollbarPart::computeScrollbarWidth()
     98 {
     99     if (!m_scrollbar->owningRenderer())
    100         return;
    101     // FIXME: We are querying layout information but nothing guarantees that it's up-to-date, especially since we are called at style change.
    102     // FIXME: Querying the style's border information doesn't work on table cells with collapsing borders.
    103     int visibleSize = m_scrollbar->owningRenderer()->width() - m_scrollbar->owningRenderer()->style()->borderLeftWidth() - m_scrollbar->owningRenderer()->style()->borderRightWidth();
    104     int w = calcScrollbarThicknessUsing(MainOrPreferredSize, style()->width(), visibleSize);
    105     int minWidth = calcScrollbarThicknessUsing(MinSize, style()->minWidth(), visibleSize);
    106     int maxWidth = style()->maxWidth().isUndefined() ? w : calcScrollbarThicknessUsing(MaxSize, style()->maxWidth(), visibleSize);
    107     setWidth(max(minWidth, min(maxWidth, w)));
    108 
    109     // Buttons and track pieces can all have margins along the axis of the scrollbar.
    110     m_marginBox.setLeft(minimumValueForLength(style()->marginLeft(), visibleSize));
    111     m_marginBox.setRight(minimumValueForLength(style()->marginRight(), visibleSize));
    112 }
    113 
    114 void RenderScrollbarPart::computeScrollbarHeight()
    115 {
    116     if (!m_scrollbar->owningRenderer())
    117         return;
    118     // FIXME: We are querying layout information but nothing guarantees that it's up-to-date, especially since we are called at style change.
    119     // FIXME: Querying the style's border information doesn't work on table cells with collapsing borders.
    120     int visibleSize = m_scrollbar->owningRenderer()->height() -  m_scrollbar->owningRenderer()->style()->borderTopWidth() - m_scrollbar->owningRenderer()->style()->borderBottomWidth();
    121     int h = calcScrollbarThicknessUsing(MainOrPreferredSize, style()->height(), visibleSize);
    122     int minHeight = calcScrollbarThicknessUsing(MinSize, style()->minHeight(), visibleSize);
    123     int maxHeight = style()->maxHeight().isUndefined() ? h : calcScrollbarThicknessUsing(MaxSize, style()->maxHeight(), visibleSize);
    124     setHeight(max(minHeight, min(maxHeight, h)));
    125 
    126     // Buttons and track pieces can all have margins along the axis of the scrollbar.
    127     m_marginBox.setTop(minimumValueForLength(style()->marginTop(), visibleSize));
    128     m_marginBox.setBottom(minimumValueForLength(style()->marginBottom(), visibleSize));
    129 }
    130 
    131 void RenderScrollbarPart::computePreferredLogicalWidths()
    132 {
    133     if (!preferredLogicalWidthsDirty())
    134         return;
    135 
    136     m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
    137 
    138     clearPreferredLogicalWidthsDirty();
    139 }
    140 
    141 void RenderScrollbarPart::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
    142 {
    143     RenderBlock::styleWillChange(diff, newStyle);
    144     setInline(false);
    145 }
    146 
    147 void RenderScrollbarPart::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
    148 {
    149     RenderBlock::styleDidChange(diff, oldStyle);
    150     setInline(false);
    151     clearPositionedState();
    152     setFloating(false);
    153     setHasOverflowClip(false);
    154     if (oldStyle && m_scrollbar && m_part != NoPart && (diff.needsRepaint() || diff.needsLayout()))
    155         m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
    156 }
    157 
    158 void RenderScrollbarPart::imageChanged(WrappedImagePtr image, const IntRect* rect)
    159 {
    160     if (m_scrollbar && m_part != NoPart)
    161         m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
    162     else {
    163         if (FrameView* frameView = view()->frameView()) {
    164             if (frameView->isFrameViewScrollCorner(this)) {
    165                 frameView->invalidateScrollCorner(frameView->scrollCornerRect());
    166                 return;
    167             }
    168         }
    169 
    170         RenderBlock::imageChanged(image, rect);
    171     }
    172 }
    173 
    174 void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset, const LayoutRect& rect)
    175 {
    176     // Make sure our dimensions match the rect.
    177     setLocation(rect.location() - toSize(paintOffset));
    178     setWidth(rect.width());
    179     setHeight(rect.height());
    180 
    181     if (graphicsContext->paintingDisabled())
    182         return;
    183 
    184     // Now do the paint.
    185     PaintInfo paintInfo(graphicsContext, pixelSnappedIntRect(rect), PaintPhaseBlockBackground, PaintBehaviorNormal);
    186     paint(paintInfo, paintOffset);
    187     paintInfo.phase = PaintPhaseChildBlockBackgrounds;
    188     paint(paintInfo, paintOffset);
    189     paintInfo.phase = PaintPhaseFloat;
    190     paint(paintInfo, paintOffset);
    191     paintInfo.phase = PaintPhaseForeground;
    192     paint(paintInfo, paintOffset);
    193     paintInfo.phase = PaintPhaseOutline;
    194     paint(paintInfo, paintOffset);
    195 }
    196 
    197 RenderObject* RenderScrollbarPart::rendererOwningScrollbar() const
    198 {
    199     if (!m_scrollbar)
    200         return 0;
    201     return m_scrollbar->owningRenderer();
    202 }
    203 
    204 }
    205