CTTE: RenderObject's createAnonymous() and setDocumentForAnonymous() should take...
[WebKit-https.git] / Source / WebCore / rendering / RenderScrollbarPart.cpp
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 "RenderScrollbarPart.h"
28
29 #include "PaintInfo.h"
30 #include "RenderScrollbar.h"
31 #include "RenderScrollbarTheme.h"
32 #include "RenderView.h"
33 #include <wtf/StackStats.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 (document.renderArena()) RenderScrollbarPart(scrollbar, part);
53     renderer->setDocumentForAnonymous(document);
54     return renderer;
55 }
56
57 void RenderScrollbarPart::layout()
58 {
59     StackStats::LayoutCheckPoint layoutCheckPoint;
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     setNeedsLayout(false);
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     setPreferredLogicalWidthsDirty(false);
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 (view().frameView().isFrameViewScrollCorner(this)) {
167             view().frameView().invalidateScrollCorner(view().frameView().scrollCornerRect());
168             return;
169         }
170         
171         RenderBlock::imageChanged(image, rect);
172     }
173 }
174
175 void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset, const LayoutRect& rect)
176 {
177     // Make sure our dimensions match the rect.
178     setLocation(rect.location() - toSize(paintOffset));
179     setWidth(rect.width());
180     setHeight(rect.height());
181
182     if (graphicsContext->paintingDisabled() || !style()->opacity())
183         return;
184
185     // We don't use RenderLayers for scrollbar parts, so we need to handle opacity here.
186     // Opacity for ScrollbarBGPart is handled by RenderScrollbarTheme::willPaintScrollbar().
187     bool needsTransparencyLayer = m_part != ScrollbarBGPart && style()->opacity() < 1;
188     if (needsTransparencyLayer) {
189         graphicsContext->save();
190         graphicsContext->clip(rect);
191         graphicsContext->beginTransparencyLayer(style()->opacity());
192     }
193     
194     // Now do the paint.
195     PaintInfo paintInfo(graphicsContext, pixelSnappedIntRect(rect), PaintPhaseBlockBackground, PaintBehaviorNormal);
196     paint(paintInfo, paintOffset);
197     paintInfo.phase = PaintPhaseChildBlockBackgrounds;
198     paint(paintInfo, paintOffset);
199     paintInfo.phase = PaintPhaseFloat;
200     paint(paintInfo, paintOffset);
201     paintInfo.phase = PaintPhaseForeground;
202     paint(paintInfo, paintOffset);
203     paintInfo.phase = PaintPhaseOutline;
204     paint(paintInfo, paintOffset);
205
206     if (needsTransparencyLayer) {
207         graphicsContext->endTransparencyLayer();
208         graphicsContext->restore();
209     }
210 }
211
212 RenderObject* RenderScrollbarPart::rendererOwningScrollbar() const
213 {
214     if (!m_scrollbar)
215         return 0;
216     return m_scrollbar->owningRenderer();
217 }
218
219 }