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