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