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 35namespace blink { 36 37RenderScrollbarPart::RenderScrollbarPart(RenderScrollbar* scrollbar, ScrollbarPart part) 38 : RenderBlock(0) 39 , m_scrollbar(scrollbar) 40 , m_part(part) 41{ 42} 43 44RenderScrollbarPart::~RenderScrollbarPart() 45{ 46} 47 48RenderScrollbarPart* 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 55void 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 66void 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 77void 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 88static 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 95void 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 112void 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 129void RenderScrollbarPart::computePreferredLogicalWidths() 130{ 131 if (!preferredLogicalWidthsDirty()) 132 return; 133 134 m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0; 135 136 clearPreferredLogicalWidthsDirty(); 137} 138 139void RenderScrollbarPart::styleWillChange(StyleDifference diff, const RenderStyle& newStyle) 140{ 141 RenderBlock::styleWillChange(diff, newStyle); 142 setInline(false); 143} 144 145void 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 156void 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 172void 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 192RenderObject* RenderScrollbarPart::rendererOwningScrollbar() const 193{ 194 if (!m_scrollbar) 195 return 0; 196 return m_scrollbar->owningRenderer(); 197} 198 199} 200