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