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 namespace blink {
     36 
     37 RenderScrollbarPart::RenderScrollbarPart(RenderScrollbar* scrollbar, ScrollbarPart part)
     38     : RenderBlock(0)
     39     , m_scrollbar(scrollbar)
     40     , m_part(part)
     41 {
     42 }
     43 
     44 RenderScrollbarPart::~RenderScrollbarPart()
     45 {
     46 }
     47 
     48 RenderScrollbarPart* RenderScrollbarPart::createAnonymous(Document* document, RenderScrollbar* scrollbar, ScrollbarPart part)
     49 {
     50     RenderScrollbarPart* renderer = new RenderScrollbarPart(scrollbar, part);
     51     renderer->setDocumentForAnonymous(document);
     52     return renderer;
     53 }
     54 
     55 void RenderScrollbarPart::layout()
     56 {
     57     setLocation(LayoutPoint()); // We don't worry about positioning ourselves. We're just determining our minimum width/height.
     58     if (m_scrollbar->orientation() == HorizontalScrollbar)
     59         layoutHorizontalPart();
     60     else
     61         layoutVerticalPart();
     62 
     63     clearNeedsLayout();
     64 }
     65 
     66 void RenderScrollbarPart::layoutHorizontalPart()
     67 {
     68     if (m_part == ScrollbarBGPart) {
     69         setWidth(m_scrollbar->width());
     70         computeScrollbarHeight();
     71     } else {
     72         computeScrollbarWidth();
     73         setHeight(m_scrollbar->height());
     74     }
     75 }
     76 
     77 void RenderScrollbarPart::layoutVerticalPart()
     78 {
     79     if (m_part == ScrollbarBGPart) {
     80         computeScrollbarWidth();
     81         setHeight(m_scrollbar->height());
     82     } else {
     83         setWidth(m_scrollbar->width());
     84         computeScrollbarHeight();
     85     }
     86 }
     87 
     88 static int calcScrollbarThicknessUsing(SizeType sizeType, const Length& length, int containingLength)
     89 {
     90     if (!length.isIntrinsicOrAuto() || (sizeType == MinSize && length.isAuto()))
     91         return minimumValueForLength(length, containingLength);
     92     return ScrollbarTheme::theme()->scrollbarThickness();
     93 }
     94 
     95 void RenderScrollbarPart::computeScrollbarWidth()
     96 {
     97     if (!m_scrollbar->owningRenderer())
     98         return;
     99     // FIXME: We are querying layout information but nothing guarantees that it's up-to-date, especially since we are called at style change.
    100     // FIXME: Querying the style's border information doesn't work on table cells with collapsing borders.
    101     int visibleSize = m_scrollbar->owningRenderer()->width() - m_scrollbar->owningRenderer()->style()->borderLeftWidth() - m_scrollbar->owningRenderer()->style()->borderRightWidth();
    102     int w = calcScrollbarThicknessUsing(MainOrPreferredSize, style()->width(), visibleSize);
    103     int minWidth = calcScrollbarThicknessUsing(MinSize, style()->minWidth(), visibleSize);
    104     int maxWidth = style()->maxWidth().isMaxSizeNone() ? w : calcScrollbarThicknessUsing(MaxSize, style()->maxWidth(), visibleSize);
    105     setWidth(std::max(minWidth, std::min(maxWidth, w)));
    106 
    107     // Buttons and track pieces can all have margins along the axis of the scrollbar.
    108     m_marginBox.setLeft(minimumValueForLength(style()->marginLeft(), visibleSize));
    109     m_marginBox.setRight(minimumValueForLength(style()->marginRight(), visibleSize));
    110 }
    111 
    112 void RenderScrollbarPart::computeScrollbarHeight()
    113 {
    114     if (!m_scrollbar->owningRenderer())
    115         return;
    116     // FIXME: We are querying layout information but nothing guarantees that it's up-to-date, especially since we are called at style change.
    117     // FIXME: Querying the style's border information doesn't work on table cells with collapsing borders.
    118     int visibleSize = m_scrollbar->owningRenderer()->height() -  m_scrollbar->owningRenderer()->style()->borderTopWidth() - m_scrollbar->owningRenderer()->style()->borderBottomWidth();
    119     int h = calcScrollbarThicknessUsing(MainOrPreferredSize, style()->height(), visibleSize);
    120     int minHeight = calcScrollbarThicknessUsing(MinSize, style()->minHeight(), visibleSize);
    121     int maxHeight = style()->maxHeight().isMaxSizeNone() ? h : calcScrollbarThicknessUsing(MaxSize, style()->maxHeight(), visibleSize);
    122     setHeight(std::max(minHeight, std::min(maxHeight, h)));
    123 
    124     // Buttons and track pieces can all have margins along the axis of the scrollbar.
    125     m_marginBox.setTop(minimumValueForLength(style()->marginTop(), visibleSize));
    126     m_marginBox.setBottom(minimumValueForLength(style()->marginBottom(), visibleSize));
    127 }
    128 
    129 void RenderScrollbarPart::computePreferredLogicalWidths()
    130 {
    131     if (!preferredLogicalWidthsDirty())
    132         return;
    133 
    134     m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
    135 
    136     clearPreferredLogicalWidthsDirty();
    137 }
    138 
    139 void RenderScrollbarPart::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
    140 {
    141     RenderBlock::styleWillChange(diff, newStyle);
    142     setInline(false);
    143 }
    144 
    145 void RenderScrollbarPart::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
    146 {
    147     RenderBlock::styleDidChange(diff, oldStyle);
    148     setInline(false);
    149     clearPositionedState();
    150     setFloating(false);
    151     setHasOverflowClip(false);
    152     if (oldStyle && m_scrollbar && m_part != NoPart && (diff.needsPaintInvalidation() || diff.needsLayout()))
    153         m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
    154 }
    155 
    156 void RenderScrollbarPart::imageChanged(WrappedImagePtr image, const IntRect* rect)
    157 {
    158     if (m_scrollbar && m_part != NoPart)
    159         m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
    160     else {
    161         if (FrameView* frameView = view()->frameView()) {
    162             if (frameView->isFrameViewScrollCorner(this)) {
    163                 frameView->invalidateScrollCorner(frameView->scrollCornerRect());
    164                 return;
    165             }
    166         }
    167 
    168         RenderBlock::imageChanged(image, rect);
    169     }
    170 }
    171 
    172 void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset, const LayoutRect& rect)
    173 {
    174     // Make sure our dimensions match the rect.
    175     setLocation(rect.location() - toSize(paintOffset));
    176     setWidth(rect.width());
    177     setHeight(rect.height());
    178 
    179     // Now do the paint.
    180     PaintInfo paintInfo(graphicsContext, pixelSnappedIntRect(rect), PaintPhaseBlockBackground, PaintBehaviorNormal);
    181     paint(paintInfo, paintOffset);
    182     paintInfo.phase = PaintPhaseChildBlockBackgrounds;
    183     paint(paintInfo, paintOffset);
    184     paintInfo.phase = PaintPhaseFloat;
    185     paint(paintInfo, paintOffset);
    186     paintInfo.phase = PaintPhaseForeground;
    187     paint(paintInfo, paintOffset);
    188     paintInfo.phase = PaintPhaseOutline;
    189     paint(paintInfo, paintOffset);
    190 }
    191 
    192 RenderObject* RenderScrollbarPart::rendererOwningScrollbar() const
    193 {
    194     if (!m_scrollbar)
    195         return 0;
    196     return m_scrollbar->owningRenderer();
    197 }
    198 
    199 }
    200