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