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 34 using namespace std; 35 36 namespace WebCore { 37 38 RenderScrollbarPart::RenderScrollbarPart(RenderScrollbar* scrollbar, ScrollbarPart part) 39 : RenderBlock(0) 40 , m_scrollbar(scrollbar) 41 , m_part(part) 42 { 43 } 44 45 RenderScrollbarPart::~RenderScrollbarPart() 46 { 47 } 48 49 RenderScrollbarPart* RenderScrollbarPart::createAnonymous(Document* document, RenderScrollbar* scrollbar, ScrollbarPart part) 50 { 51 RenderScrollbarPart* renderer = new RenderScrollbarPart(scrollbar, part); 52 renderer->setDocumentForAnonymous(document); 53 return renderer; 54 } 55 56 void RenderScrollbarPart::layout() 57 { 58 StackStats::LayoutCheckPoint layoutCheckPoint; 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, RenderView* renderView) 91 { 92 if (!length.isIntrinsicOrAuto() || (sizeType == MinSize && length.isAuto())) 93 return minimumValueForLength(length, containingLength, renderView); 94 return ScrollbarTheme::theme()->scrollbarThickness(); 95 } 96 97 void RenderScrollbarPart::computeScrollbarWidth() 98 { 99 if (!m_scrollbar->owningRenderer()) 100 return; 101 RenderView* renderView = view(); 102 // FIXME: We are querying layout information but nothing guarantees that it's up-to-date, especially since we are called at style change. 103 // FIXME: Querying the style's border information doesn't work on table cells with collapsing borders. 104 int visibleSize = m_scrollbar->owningRenderer()->width() - m_scrollbar->owningRenderer()->style()->borderLeftWidth() - m_scrollbar->owningRenderer()->style()->borderRightWidth(); 105 int w = calcScrollbarThicknessUsing(MainOrPreferredSize, style()->width(), visibleSize, renderView); 106 int minWidth = calcScrollbarThicknessUsing(MinSize, style()->minWidth(), visibleSize, renderView); 107 int maxWidth = style()->maxWidth().isUndefined() ? w : calcScrollbarThicknessUsing(MaxSize, style()->maxWidth(), visibleSize, renderView); 108 setWidth(max(minWidth, min(maxWidth, w))); 109 110 // Buttons and track pieces can all have margins along the axis of the scrollbar. 111 m_marginBox.setLeft(minimumValueForLength(style()->marginLeft(), visibleSize, renderView)); 112 m_marginBox.setRight(minimumValueForLength(style()->marginRight(), visibleSize, renderView)); 113 } 114 115 void RenderScrollbarPart::computeScrollbarHeight() 116 { 117 if (!m_scrollbar->owningRenderer()) 118 return; 119 RenderView* renderView = view(); 120 // FIXME: We are querying layout information but nothing guarantees that it's up-to-date, especially since we are called at style change. 121 // FIXME: Querying the style's border information doesn't work on table cells with collapsing borders. 122 int visibleSize = m_scrollbar->owningRenderer()->height() - m_scrollbar->owningRenderer()->style()->borderTopWidth() - m_scrollbar->owningRenderer()->style()->borderBottomWidth(); 123 int h = calcScrollbarThicknessUsing(MainOrPreferredSize, style()->height(), visibleSize, renderView); 124 int minHeight = calcScrollbarThicknessUsing(MinSize, style()->minHeight(), visibleSize, renderView); 125 int maxHeight = style()->maxHeight().isUndefined() ? h : calcScrollbarThicknessUsing(MaxSize, style()->maxHeight(), visibleSize, renderView); 126 setHeight(max(minHeight, min(maxHeight, h))); 127 128 // Buttons and track pieces can all have margins along the axis of the scrollbar. 129 m_marginBox.setTop(minimumValueForLength(style()->marginTop(), visibleSize, renderView)); 130 m_marginBox.setBottom(minimumValueForLength(style()->marginBottom(), visibleSize, renderView)); 131 } 132 133 void RenderScrollbarPart::computePreferredLogicalWidths() 134 { 135 if (!preferredLogicalWidthsDirty()) 136 return; 137 138 m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0; 139 140 setPreferredLogicalWidthsDirty(false); 141 } 142 143 void RenderScrollbarPart::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) 144 { 145 RenderBlock::styleWillChange(diff, newStyle); 146 setInline(false); 147 } 148 149 void RenderScrollbarPart::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) 150 { 151 RenderBlock::styleDidChange(diff, oldStyle); 152 setInline(false); 153 clearPositionedState(); 154 setFloating(false); 155 setHasOverflowClip(false); 156 if (oldStyle && m_scrollbar && m_part != NoPart && diff >= StyleDifferenceRepaint) 157 m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part); 158 } 159 160 void RenderScrollbarPart::imageChanged(WrappedImagePtr image, const IntRect* rect) 161 { 162 if (m_scrollbar && m_part != NoPart) 163 m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part); 164 else { 165 if (FrameView* frameView = view()->frameView()) { 166 if (frameView->isFrameViewScrollCorner(this)) { 167 frameView->invalidateScrollCorner(frameView->scrollCornerRect()); 168 return; 169 } 170 } 171 172 RenderBlock::imageChanged(image, rect); 173 } 174 } 175 176 void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset, const LayoutRect& rect) 177 { 178 // Make sure our dimensions match the rect. 179 setLocation(rect.location() - toSize(paintOffset)); 180 setWidth(rect.width()); 181 setHeight(rect.height()); 182 183 if (graphicsContext->paintingDisabled()) 184 return; 185 186 // Now do the paint. 187 PaintInfo paintInfo(graphicsContext, pixelSnappedIntRect(rect), PaintPhaseBlockBackground, PaintBehaviorNormal); 188 paint(paintInfo, paintOffset); 189 paintInfo.phase = PaintPhaseChildBlockBackgrounds; 190 paint(paintInfo, paintOffset); 191 paintInfo.phase = PaintPhaseFloat; 192 paint(paintInfo, paintOffset); 193 paintInfo.phase = PaintPhaseForeground; 194 paint(paintInfo, paintOffset); 195 paintInfo.phase = PaintPhaseOutline; 196 paint(paintInfo, paintOffset); 197 } 198 199 RenderObject* RenderScrollbarPart::rendererOwningScrollbar() const 200 { 201 if (!m_scrollbar) 202 return 0; 203 return m_scrollbar->owningRenderer(); 204 } 205 206 } 207